1 // Copyright (C) 2007-2015 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 #include "CommInterface.hxx"
22 #include "ElementLocator.hxx"
23 #include "Topology.hxx"
24 #include "BlockTopology.hxx"
25 #include "ParaFIELD.hxx"
26 #include "ParaMESH.hxx"
27 #include "ProcessorGroup.hxx"
28 #include "MPIProcessorGroup.hxx"
29 #include "MEDCouplingFieldDouble.hxx"
30 #include "MEDCouplingAutoRefCountObjectPtr.hxx"
31 #include "DirectedBoundingBox.hxx"
39 //#define USE_DIRECTED_BB
43 ElementLocator::ElementLocator(const ParaFIELD& sourceField,
44 const ProcessorGroup& distant_group,
45 const ProcessorGroup& local_group)
46 : _local_para_field(sourceField),
47 _local_cell_mesh(sourceField.getSupport()->getCellMesh()),
48 _local_face_mesh(sourceField.getSupport()->getFaceMesh()),
49 _distant_group(distant_group),
50 _local_group(local_group)
52 _union_group = _local_group.fuse(distant_group);
53 _computeBoundingBoxes();
54 _comm=getCommunicator();
57 ElementLocator::~ElementLocator()
60 delete [] _domain_bounding_boxes;
63 const MPI_Comm *ElementLocator::getCommunicator() const
65 MPIProcessorGroup* group=static_cast<MPIProcessorGroup*> (_union_group);
66 return group->getComm();
69 NatureOfField ElementLocator::getLocalNature() const
71 return _local_para_field.getField()->getNature();
74 // ==========================================================================
75 // Procedure for exchanging mesh between a distant proc and a local processor
76 // param idistantrank proc id on distant group
77 // param distant_mesh on return , points to a local reconstruction of
79 // param distant_ids on return, contains a vector defining a correspondence
80 // between the distant ids and the ids of the local reconstruction
81 // ==========================================================================
82 void ElementLocator::exchangeMesh(int idistantrank,
83 MEDCouplingPointSet*& distant_mesh,
86 int rank = _union_group->translateRank(&_distant_group,idistantrank);
88 if (find(_distant_proc_ids.begin(), _distant_proc_ids.end(),rank)==_distant_proc_ids.end())
91 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems;
92 #ifdef USE_DIRECTED_BB
93 INTERP_KERNEL::DirectedBoundingBox dbb;
94 double* distant_bb = _domain_bounding_boxes+rank*dbb.dataSize(_local_cell_mesh_space_dim);
95 dbb.setData(distant_bb);
96 elems=_local_cell_mesh->getCellsInBoundingBox(dbb,getBoundingBoxAdjustment());
98 double* distant_bb = _domain_bounding_boxes+rank*2*_local_cell_mesh_space_dim;
99 elems=_local_cell_mesh->getCellsInBoundingBox(distant_bb,getBoundingBoxAdjustment());
102 DataArrayInt *distant_ids_send;
103 MEDCouplingPointSet *send_mesh = (MEDCouplingPointSet *)_local_para_field.getField()->buildSubMeshData(elems->begin(),elems->end(),distant_ids_send);
104 _exchangeMesh(send_mesh, distant_mesh, idistantrank, distant_ids_send, distant_ids);
105 distant_ids_send->decrRef();
108 send_mesh->decrRef();
111 void ElementLocator::exchangeMethod(const std::string& sourceMeth, int idistantrank, std::string& targetMeth)
113 CommInterface comm_interface=_union_group->getCommInterface();
114 MPIProcessorGroup* group=static_cast<MPIProcessorGroup*> (_union_group);
115 const MPI_Comm* comm=(group->getComm());
117 // it must be converted to union numbering before communication
118 int idistRankInUnion = group->translateRank(&_distant_group,idistantrank);
119 char *recv_buffer=new char[4];
120 std::vector<char> send_buffer(4);
121 std::copy(sourceMeth.begin(),sourceMeth.end(),send_buffer.begin());
122 comm_interface.sendRecv(&send_buffer[0], 4, MPI_CHAR,idistRankInUnion, 1112,
123 recv_buffer, 4, MPI_CHAR,idistRankInUnion, 1112,
125 targetMeth=recv_buffer;
126 delete [] recv_buffer;
130 // ======================
131 // Compute bounding boxes
132 // ======================
134 void ElementLocator::_computeBoundingBoxes()
136 CommInterface comm_interface =_union_group->getCommInterface();
137 MPIProcessorGroup* group=static_cast<MPIProcessorGroup*> (_union_group);
138 const MPI_Comm* comm = group->getComm();
139 _local_cell_mesh_space_dim = -1;
140 if(_local_cell_mesh->getMeshDimension() != -1)
141 _local_cell_mesh_space_dim=_local_cell_mesh->getSpaceDimension();
142 int *spaceDimForAll=new int[_union_group->size()];
143 comm_interface.allGather(&_local_cell_mesh_space_dim, 1, MPI_INT,
144 spaceDimForAll,1, MPI_INT,
146 _local_cell_mesh_space_dim=*std::max_element(spaceDimForAll,spaceDimForAll+_union_group->size());
147 _is_m1d_corr=((*std::min_element(spaceDimForAll,spaceDimForAll+_union_group->size()))==-1);
148 for(int i=0;i<_union_group->size();i++)
149 if(spaceDimForAll[i]!=_local_cell_mesh_space_dim && spaceDimForAll[i]!=-1)
150 throw INTERP_KERNEL::Exception("Spacedim not matches !");
151 delete [] spaceDimForAll;
152 #ifdef USE_DIRECTED_BB
153 INTERP_KERNEL::DirectedBoundingBox dbb;
154 int bbSize = dbb.dataSize(_local_cell_mesh_space_dim);
155 _domain_bounding_boxes = new double[bbSize*_union_group->size()];
156 if(_local_cell_mesh->getMeshDimension() != -1)
157 dbb = INTERP_KERNEL::DirectedBoundingBox(_local_cell_mesh->getCoords()->getPointer(),
158 _local_cell_mesh->getNumberOfNodes(),
159 _local_cell_mesh_space_dim);
160 std::vector<double> dbbData = dbb.getData();
161 if ( dbbData.size() < bbSize ) dbbData.resize(bbSize,0);
162 double * minmax= &dbbData[0];
164 int bbSize = 2*_local_cell_mesh_space_dim;
165 _domain_bounding_boxes = new double[bbSize*_union_group->size()];
166 double * minmax=new double [bbSize];
167 if(_local_cell_mesh->getMeshDimension() != -1)
168 _local_cell_mesh->getBoundingBox(minmax);
170 for(int i=0;i<_local_cell_mesh_space_dim;i++)
172 minmax[i*2]=-std::numeric_limits<double>::max();
173 minmax[i*2+1]=std::numeric_limits<double>::max();
177 comm_interface.allGather(minmax, bbSize, MPI_DOUBLE,
178 _domain_bounding_boxes,bbSize, MPI_DOUBLE,
181 for (int i=0; i< _distant_group.size(); i++)
183 int rank=_union_group->translateRank(&_distant_group,i);
185 if (_intersectsBoundingBox(rank))
187 _distant_proc_ids.push_back(rank);
190 #ifdef USE_DIRECTED_BB
197 // =============================================
198 // Intersect Bounding Box (with a given "irank")
199 // =============================================
200 bool ElementLocator::_intersectsBoundingBox(int irank)
202 #ifdef USE_DIRECTED_BB
203 INTERP_KERNEL::DirectedBoundingBox local_dbb, distant_dbb;
204 local_dbb.setData( _domain_bounding_boxes+_union_group->myRank()*local_dbb.dataSize( _local_cell_mesh_space_dim ));
205 distant_dbb.setData( _domain_bounding_boxes+irank*distant_dbb.dataSize( _local_cell_mesh_space_dim ));
206 return !local_dbb.isDisjointWith( distant_dbb );
208 double* local_bb = _domain_bounding_boxes+_union_group->myRank()*2*_local_cell_mesh_space_dim;
209 double* distant_bb = _domain_bounding_boxes+irank*2*_local_cell_mesh_space_dim;
211 for (int idim=0; idim < _local_cell_mesh_space_dim; idim++)
213 const double eps = 1e-12;
214 bool intersects = (distant_bb[idim*2]<local_bb[idim*2+1]+eps)
215 && (local_bb[idim*2]<distant_bb[idim*2+1]+eps);
216 if (!intersects) return false;
222 // ======================
223 // Exchanging meshes data
224 // ======================
225 void ElementLocator::_exchangeMesh( MEDCouplingPointSet* local_mesh,
226 MEDCouplingPointSet*& distant_mesh,
228 const DataArrayInt* distant_ids_send,
229 int*& distant_ids_recv)
231 CommInterface comm_interface=_union_group->getCommInterface();
233 // First stage : exchanging sizes
234 // ------------------------------
235 vector<double> tinyInfoLocalD,tinyInfoDistantD(1);//not used for the moment
236 vector<int> tinyInfoLocal,tinyInfoDistant;
237 vector<string> tinyInfoLocalS;
238 //Getting tiny info of local mesh to allow the distant proc to initialize and allocate
239 //the transmitted mesh.
240 local_mesh->getTinySerializationInformation(tinyInfoLocalD,tinyInfoLocal,tinyInfoLocalS);
241 tinyInfoLocal.push_back(distant_ids_send->getNumberOfTuples());
242 tinyInfoDistant.resize(tinyInfoLocal.size());
243 std::fill(tinyInfoDistant.begin(),tinyInfoDistant.end(),0);
244 MPIProcessorGroup* group=static_cast<MPIProcessorGroup*> (_union_group);
245 const MPI_Comm* comm=group->getComm();
248 // iproc_distant is the number of proc in distant group
249 // it must be converted to union numbering before communication
250 int iprocdistant_in_union = group->translateRank(&_distant_group,
253 comm_interface.sendRecv(&tinyInfoLocal[0], tinyInfoLocal.size(), MPI_INT, iprocdistant_in_union, 1112,
254 &tinyInfoDistant[0], tinyInfoDistant.size(), MPI_INT,iprocdistant_in_union,1112,
256 DataArrayInt *v1Local=0;
257 DataArrayDouble *v2Local=0;
258 DataArrayInt *v1Distant=DataArrayInt::New();
259 DataArrayDouble *v2Distant=DataArrayDouble::New();
260 //serialization of local mesh to send data to distant proc.
261 local_mesh->serialize(v1Local,v2Local);
262 //Building the right instance of copy of distant mesh.
263 MEDCouplingPointSet *distant_mesh_tmp=MEDCouplingPointSet::BuildInstanceFromMeshType((MEDCouplingMeshType)tinyInfoDistant[0]);
264 std::vector<std::string> unusedTinyDistantSts;
265 distant_mesh_tmp->resizeForUnserialization(tinyInfoDistant,v1Distant,v2Distant,unusedTinyDistantSts);
272 nbLocalElems=v1Local->getNbOfElems();
273 ptLocal=v1Local->getPointer();
277 nbDistElem=v1Distant->getNbOfElems();
278 ptDist=v1Distant->getPointer();
280 comm_interface.sendRecv(ptLocal, nbLocalElems, MPI_INT,
281 iprocdistant_in_union, 1111,
282 ptDist, nbDistElem, MPI_INT,
283 iprocdistant_in_union,1111,
290 nbLocalElems=v2Local->getNbOfElems();
291 ptLocal2=v2Local->getPointer();
296 nbDistElem=v2Distant->getNbOfElems();
297 ptDist2=v2Distant->getPointer();
299 comm_interface.sendRecv(ptLocal2, nbLocalElems, MPI_DOUBLE,
300 iprocdistant_in_union, 1112,
301 ptDist2, nbDistElem, MPI_DOUBLE,
302 iprocdistant_in_union, 1112,
305 distant_mesh=distant_mesh_tmp;
306 //finish unserialization
307 distant_mesh->unserialization(tinyInfoDistantD,tinyInfoDistant,v1Distant,v2Distant,unusedTinyDistantSts);
309 distant_ids_recv=new int[tinyInfoDistant.back()];
310 comm_interface.sendRecv(const_cast<void *>(reinterpret_cast<const void *>(distant_ids_send->getConstPointer())),tinyInfoLocal.back(), MPI_INT,
311 iprocdistant_in_union, 1113,
312 distant_ids_recv,tinyInfoDistant.back(), MPI_INT,
313 iprocdistant_in_union,1113,
320 v1Distant->decrRef();
322 v2Distant->decrRef();
326 * connected with ElementLocator::sendPolicyToWorkingSideL
328 void ElementLocator::recvPolicyFromLazySideW(std::vector<int>& policy)
330 policy.resize(_distant_proc_ids.size());
334 for(vector<int>::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++)
337 comm.recv((void *)&toRecv,1,MPI_INT,*iter,1120,*_comm,&status);
338 policy[procId]=toRecv;
343 * connected with ElementLocator::recvFromWorkingSideL
345 void ElementLocator::sendSumToLazySideW(const std::vector< std::vector<int> >& distantLocEltIds, const std::vector< std::vector<double> >& partialSumRelToDistantIds)
349 for(vector<int>::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++)
351 const vector<int>& eltIds=distantLocEltIds[procId];
352 const vector<double>& valued=partialSumRelToDistantIds[procId];
353 int lgth=eltIds.size();
354 comm.send(&lgth,1,MPI_INT,*iter,1114,*_comm);
355 comm.send(const_cast<void *>(reinterpret_cast<const void *>(&eltIds[0])),lgth,MPI_INT,*iter,1115,*_comm);
356 comm.send(const_cast<void *>(reinterpret_cast<const void *>(&valued[0])),lgth,MPI_DOUBLE,*iter,1116,*_comm);
361 * connected with ElementLocator::sendToWorkingSideL
363 void ElementLocator::recvSumFromLazySideW(std::vector< std::vector<double> >& globalSumRelToDistantIds)
368 for(vector<int>::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++)
370 std::vector<double>& vec=globalSumRelToDistantIds[procId];
371 comm.recv(&vec[0],vec.size(),MPI_DOUBLE,*iter,1117,*_comm,&status);
376 * connected with ElementLocator::recvLocalIdsFromWorkingSideL
378 void ElementLocator::sendLocalIdsToLazyProcsW(const std::vector< std::vector<int> >& distantLocEltIds)
382 for(vector<int>::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++)
384 const vector<int>& eltIds=distantLocEltIds[procId];
385 int lgth=eltIds.size();
386 comm.send(&lgth,1,MPI_INT,*iter,1121,*_comm);
387 comm.send(const_cast<void *>(reinterpret_cast<const void *>(&eltIds[0])),lgth,MPI_INT,*iter,1122,*_comm);
392 * connected with ElementLocator::sendGlobalIdsToWorkingSideL
394 void ElementLocator::recvGlobalIdsFromLazyProcsW(const std::vector< std::vector<int> >& distantLocEltIds, std::vector< std::vector<int> >& globalIds)
399 globalIds.resize(_distant_proc_ids.size());
400 for(vector<int>::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++)
402 const std::vector<int>& vec=distantLocEltIds[procId];
403 std::vector<int>& global=globalIds[procId];
404 global.resize(vec.size());
405 comm.recv(&global[0],vec.size(),MPI_INT,*iter,1123,*_comm,&status);
410 * connected with ElementLocator::sendCandidatesGlobalIdsToWorkingSideL
412 void ElementLocator::recvCandidatesGlobalIdsFromLazyProcsW(std::vector< std::vector<int> >& globalIds)
417 globalIds.resize(_distant_proc_ids.size());
418 for(vector<int>::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++)
420 std::vector<int>& global=globalIds[procId];
422 comm.recv(&lgth,1,MPI_INT,*iter,1132,*_comm,&status);
424 comm.recv(&global[0],lgth,MPI_INT,*iter,1133,*_comm,&status);
429 * connected with ElementLocator::recvSumFromWorkingSideL
431 void ElementLocator::sendPartialSumToLazyProcsW(const std::vector<int>& distantGlobIds, const std::vector<double>& sum)
435 int lgth=distantGlobIds.size();
436 for(vector<int>::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++)
438 comm.send(&lgth,1,MPI_INT,*iter,1124,*_comm);
439 comm.send(const_cast<void *>(reinterpret_cast<const void *>(&distantGlobIds[0])),lgth,MPI_INT,*iter,1125,*_comm);
440 comm.send(const_cast<void *>(reinterpret_cast<const void *>(&sum[0])),lgth,MPI_DOUBLE,*iter,1126,*_comm);
445 * connected with ElementLocator::recvCandidatesForAddElementsL
447 void ElementLocator::sendCandidatesForAddElementsW(const std::vector<int>& distantGlobIds)
451 int lgth=distantGlobIds.size();
452 for(vector<int>::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++)
454 comm.send(const_cast<void *>(reinterpret_cast<const void *>(&lgth)),1,MPI_INT,*iter,1128,*_comm);
455 comm.send(const_cast<void *>(reinterpret_cast<const void *>(&distantGlobIds[0])),lgth,MPI_INT,*iter,1129,*_comm);
460 * connected with ElementLocator::sendAddElementsToWorkingSideL
462 void ElementLocator::recvAddElementsFromLazyProcsW(std::vector<std::vector<int> >& elementsToAdd)
467 int lgth=_distant_proc_ids.size();
468 elementsToAdd.resize(lgth);
469 for(vector<int>::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++)
472 std::vector<int>& eltToFeed=elementsToAdd[procId];
473 comm.recv(&locLgth,1,MPI_INT,*iter,1130,*_comm,&status);
474 eltToFeed.resize(locLgth);
475 comm.recv(&eltToFeed[0],locLgth,MPI_INT,*iter,1131,*_comm,&status);
480 * connected with ElementLocator::recvPolicyFromLazySideW
482 int ElementLocator::sendPolicyToWorkingSideL()
486 DataArrayInt *isCumulative=_local_para_field.returnCumulativeGlobalNumbering();
489 toSend=CUMULATIVE_POLICY;
490 isCumulative->decrRef();
493 toSend=NO_POST_TREATMENT_POLICY;
494 for(vector<int>::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++)
495 comm.send(&toSend,1,MPI_INT,*iter,1120,*_comm);
500 * connected with ElementLocator::sendSumToLazySideW
502 void ElementLocator::recvFromWorkingSideL()
504 _values_added.resize(_local_para_field.getField()->getNumberOfTuples());
507 _ids_per_working_proc.resize(_distant_proc_ids.size());
509 for(vector<int>::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++)
512 comm.recv(&lgth,1,MPI_INT,*iter,1114,*_comm,&status);
513 vector<int>& ids=_ids_per_working_proc[procId];
515 vector<double> values(lgth);
516 comm.recv(&ids[0],lgth,MPI_INT,*iter,1115,*_comm,&status);
517 comm.recv(&values[0],lgth,MPI_DOUBLE,*iter,1116,*_comm,&status);
518 for(int i=0;i<lgth;i++)
519 _values_added[ids[i]]+=values[i];
524 * connected with ElementLocator::recvSumFromLazySideW
526 void ElementLocator::sendToWorkingSideL()
530 for(vector<int>::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++)
532 vector<int>& ids=_ids_per_working_proc[procId];
533 vector<double> valsToSend(ids.size());
534 vector<double>::iterator iter3=valsToSend.begin();
535 for(vector<int>::const_iterator iter2=ids.begin();iter2!=ids.end();iter2++,iter3++)
536 *iter3=_values_added[*iter2];
537 comm.send(&valsToSend[0],ids.size(),MPI_DOUBLE,*iter,1117,*_comm);
540 //_ids_per_working_proc.clear();
544 * connected with ElementLocator::sendLocalIdsToLazyProcsW
546 void ElementLocator::recvLocalIdsFromWorkingSideL()
550 _ids_per_working_proc.resize(_distant_proc_ids.size());
552 for(vector<int>::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++)
555 vector<int>& ids=_ids_per_working_proc[procId];
556 comm.recv(&lgth,1,MPI_INT,*iter,1121,*_comm,&status);
558 comm.recv(&ids[0],lgth,MPI_INT,*iter,1122,*_comm,&status);
563 * connected with ElementLocator::recvGlobalIdsFromLazyProcsW
565 void ElementLocator::sendGlobalIdsToWorkingSideL()
569 DataArrayInt *globalIds=_local_para_field.returnGlobalNumbering();
570 const int *globalIdsC=globalIds->getConstPointer();
571 for(vector<int>::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++)
573 const vector<int>& ids=_ids_per_working_proc[procId];
574 vector<int> valsToSend(ids.size());
575 vector<int>::iterator iter1=valsToSend.begin();
576 for(vector<int>::const_iterator iter2=ids.begin();iter2!=ids.end();iter2++,iter1++)
577 *iter1=globalIdsC[*iter2];
578 comm.send(&valsToSend[0],ids.size(),MPI_INT,*iter,1123,*_comm);
581 globalIds->decrRef();
585 * connected with ElementLocator::sendPartialSumToLazyProcsW
587 void ElementLocator::recvSumFromWorkingSideL()
590 int wProcSize=_distant_proc_ids.size();
592 _ids_per_working_proc.resize(wProcSize);
593 _values_per_working_proc.resize(wProcSize);
595 std::map<int,double> sums;
596 for(vector<int>::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++)
599 comm.recv(&lgth,1,MPI_INT,*iter,1124,*_comm,&status);
600 vector<int>& ids=_ids_per_working_proc[procId];
601 vector<double>& vals=_values_per_working_proc[procId];
604 comm.recv(&ids[0],lgth,MPI_INT,*iter,1125,*_comm,&status);
605 comm.recv(&vals[0],lgth,MPI_DOUBLE,*iter,1126,*_comm,&status);
606 vector<int>::const_iterator iter1=ids.begin();
607 vector<double>::const_iterator iter2=vals.begin();
608 for(;iter1!=ids.end();iter1++,iter2++)
609 sums[*iter1]+=*iter2;
611 //assign sum to prepare sending to working side
612 for(procId=0;procId<wProcSize;procId++)
614 vector<int>& ids=_ids_per_working_proc[procId];
615 vector<double>& vals=_values_per_working_proc[procId];
616 vector<int>::const_iterator iter1=ids.begin();
617 vector<double>::iterator iter2=vals.begin();
618 for(;iter1!=ids.end();iter1++,iter2++)
625 * Foreach working procs Wi compute and push it in _ids_per_working_proc3,
626 * if it exist, local id of nodes that are in interaction with an another lazy proc than this
627 * and that exists in this \b but with no interaction with this.
628 * The computation is performed here. sendAddElementsToWorkingSideL is only in charge to send
629 * precomputed _ids_per_working_proc3 attribute.
630 * connected with ElementLocator::sendCandidatesForAddElementsW
632 void ElementLocator::recvCandidatesForAddElementsL()
635 int wProcSize=_distant_proc_ids.size();
637 _ids_per_working_proc3.resize(wProcSize);
639 std::map<int,double> sums;
640 DataArrayInt *globalIds=_local_para_field.returnGlobalNumbering();
641 const int *globalIdsC=globalIds->getConstPointer();
642 int nbElts=globalIds->getNumberOfTuples();
643 std::set<int> globalIdsS(globalIdsC,globalIdsC+nbElts);
644 for(vector<int>::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++)
646 const std::vector<int>& ids0=_ids_per_working_proc[procId];
647 int lgth0=ids0.size();
649 for(int i=0;i<lgth0;i++)
650 elts0.insert(globalIdsC[ids0[i]]);
652 comm.recv(&lgth,1,MPI_INT,*iter,1128,*_comm,&status);
653 vector<int> ids(lgth);
654 comm.recv(&ids[0],lgth,MPI_INT,*iter,1129,*_comm,&status);
655 set<int> ids1(ids.begin(),ids.end());
658 set_intersection(globalIdsS.begin(),globalIdsS.end(),ids1.begin(),ids1.end(),inserter(tmp5,tmp5.begin()));
659 set_difference(tmp5.begin(),tmp5.end(),elts0.begin(),elts0.end(),inserter(tmp6,tmp6.begin()));
660 std::vector<int>& ids2=_ids_per_working_proc3[procId];
661 ids2.resize(tmp6.size());
662 std::copy(tmp6.begin(),tmp6.end(),ids2.begin());
664 for(std::vector<int>::iterator iter2=ids2.begin();iter2!=ids2.end();iter2++)
665 *iter2=std::find(globalIdsC,globalIdsC+nbElts,*iter2)-globalIdsC;
668 globalIds->decrRef();
672 * connected with ElementLocator::recvAddElementsFromLazyProcsW
674 void ElementLocator::sendAddElementsToWorkingSideL()
678 for(vector<int>::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++)
680 const std::vector<int>& vals=_ids_per_working_proc3[procId];
681 int size=vals.size();
682 comm.send(const_cast<void *>(reinterpret_cast<const void *>(&size)),1,MPI_INT,*iter,1130,*_comm);
683 comm.send(const_cast<void *>(reinterpret_cast<const void *>(&vals[0])),size,MPI_INT,*iter,1131,*_comm);
688 * This method sends to working side Wi only nodes in interaction with Wi \b and located on boundary, to reduce number.
689 * connected with ElementLocator::recvCandidatesGlobalIdsFromLazyProcsW
691 void ElementLocator::sendCandidatesGlobalIdsToWorkingSideL()
695 DataArrayInt *globalIds=_local_para_field.returnGlobalNumbering();
696 const int *globalIdsC=globalIds->getConstPointer();
697 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=_local_para_field.getSupport()->getCellMesh()->findBoundaryNodes();
698 for(int *iter1=candidates->getPointer();iter1!=candidates->getPointer()+candidates->getNumberOfTuples();iter1++)
699 (*iter1)=globalIdsC[*iter1];
700 std::set<int> candidatesS(candidates->begin(),candidates->end());
701 for(vector<int>::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++)
703 const vector<int>& ids=_ids_per_working_proc[procId];
704 vector<int> valsToSend(ids.size());
705 vector<int>::iterator iter1=valsToSend.begin();
706 for(vector<int>::const_iterator iter2=ids.begin();iter2!=ids.end();iter2++,iter1++)
707 *iter1=globalIdsC[*iter2];
708 std::set<int> tmp2(valsToSend.begin(),valsToSend.end());
709 std::vector<int> tmp3;
710 set_intersection(candidatesS.begin(),candidatesS.end(),tmp2.begin(),tmp2.end(),std::back_insert_iterator< std::vector<int> >(tmp3));
711 int lgth=tmp3.size();
712 comm.send(&lgth,1,MPI_INT,*iter,1132,*_comm);
713 comm.send(&tmp3[0],lgth,MPI_INT,*iter,1133,*_comm);
716 globalIds->decrRef();