1 // Copyright (C) 2007-2013 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.
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
20 #include "ParaMESH.hxx"
21 #include "ParaFIELD.hxx"
22 #include "ProcessorGroup.hxx"
23 #include "MxN_Mapping.hxx"
24 #include "InterpolationMatrix.hxx"
25 #include "TranslationRotationMatrix.hxx"
26 #include "Interpolation.hxx"
27 #include "Interpolation1D.txx"
28 #include "Interpolation2DCurve.hxx"
29 #include "Interpolation2D.txx"
30 #include "Interpolation3DSurf.hxx"
31 #include "Interpolation3D.txx"
32 #include "Interpolation3D2D.txx"
33 #include "Interpolation2D1D.txx"
34 #include "MEDCouplingUMesh.hxx"
35 #include "MEDCouplingNormalizedUnstructuredMesh.txx"
36 #include "InterpolationOptions.hxx"
37 #include "NormalizedUnstructuredMesh.hxx"
38 #include "ElementLocator.hxx"
42 // class InterpolationMatrix
43 // This class enables the storage of an interpolation matrix Wij mapping
44 // source field Sj to target field Ti via Ti=Vi^(-1).Wij.Sj.
45 // The matrix is built and stored on the processors belonging to the source
53 // ====================================================================
54 // Creates an empty matrix structure linking two distributed supports.
55 // The method must be called by all processors belonging to source
57 // param source_support local support
58 // param source_group processor group containing the local processors
59 // param target_group processor group containing the distant processors
60 // param method interpolation method
61 // ====================================================================
63 InterpolationMatrix::InterpolationMatrix(const ParaMEDMEM::ParaFIELD *source_field,
64 const ProcessorGroup& source_group,
65 const ProcessorGroup& target_group,
66 const DECOptions& dec_options,
67 const INTERP_KERNEL::InterpolationOptions& interp_options):
68 INTERP_KERNEL::InterpolationOptions(interp_options),
69 DECOptions(dec_options),
70 _source_field(source_field),
71 _source_support(source_field->getSupport()->getCellMesh()),
72 _mapping(source_group, target_group, dec_options),
73 _source_group(source_group),
74 _target_group(target_group)
76 int nbelems = source_field->getField()->getNumberOfTuples();
77 _row_offsets.resize(nbelems+1);
78 _coeffs.resize(nbelems);
79 _target_volume.resize(nbelems);
82 InterpolationMatrix::~InterpolationMatrix()
87 // ======================================================================
88 // \brief Adds the contribution of a distant subdomain to the*
89 // interpolation matrix.
90 // The method adds contribution to the interpolation matrix.
91 // For each row of the matrix, elements are addded as
92 // a (column, coeff) pair in the _coeffs array. This column number refers
93 // to an element on the target side via the _col_offsets array.
94 // It is made of a series of (iproc, ielem) pairs.
95 // The number of elements per row is stored in the row_offsets array.
97 // param distant_support local representation of the distant subdomain
98 // param iproc_distant id of the distant subdomain (in the distant group)
99 // param distant_elems mapping between the local representation of
100 // the subdomain and the actual elem ids on the distant subdomain
101 // ======================================================================
103 void InterpolationMatrix::addContribution ( MEDCouplingPointSet& distant_support,
105 const int* distant_elems,
106 const std::string& srcMeth,
107 const std::string& targetMeth)
109 std::string interpMethod(targetMeth);
110 interpMethod+=srcMeth;
111 //creating the interpolator structure
112 vector<map<int,double> > surfaces;
114 //computation of the intersection volumes between source and target elements
115 MEDCouplingUMesh *distant_supportC=dynamic_cast<MEDCouplingUMesh *>(&distant_support);
116 MEDCouplingUMesh *source_supportC=dynamic_cast<MEDCouplingUMesh *>(_source_support);
117 if ( distant_support.getMeshDimension() == -1 )
119 if(source_supportC->getMeshDimension()==2 && source_supportC->getSpaceDimension()==2)
121 MEDCouplingNormalizedUnstructuredMesh<2,2> source_mesh_wrapper(source_supportC);
122 INTERP_KERNEL::Interpolation2D interpolation(*this);
123 colSize=interpolation.fromIntegralUniform(source_mesh_wrapper,surfaces,srcMeth.c_str());
125 else if(source_supportC->getMeshDimension()==3 && source_supportC->getSpaceDimension()==3)
127 MEDCouplingNormalizedUnstructuredMesh<3,3> source_mesh_wrapper(source_supportC);
128 INTERP_KERNEL::Interpolation3D interpolation(*this);
129 colSize=interpolation.fromIntegralUniform(source_mesh_wrapper,surfaces,srcMeth.c_str());
131 else if(source_supportC->getMeshDimension()==2 && source_supportC->getSpaceDimension()==3)
133 MEDCouplingNormalizedUnstructuredMesh<3,2> source_mesh_wrapper(source_supportC);
134 INTERP_KERNEL::Interpolation3DSurf interpolation(*this);
135 colSize=interpolation.fromIntegralUniform(source_mesh_wrapper,surfaces,srcMeth.c_str());
138 throw INTERP_KERNEL::Exception("No para interpolation available for the given mesh and space dimension of source mesh to -1D targetMesh");
140 else if ( source_supportC->getMeshDimension() == -1 )
142 if(distant_supportC->getMeshDimension()==2 && distant_supportC->getSpaceDimension()==2)
144 MEDCouplingNormalizedUnstructuredMesh<2,2> distant_mesh_wrapper(distant_supportC);
145 INTERP_KERNEL::Interpolation2D interpolation(*this);
146 colSize=interpolation.toIntegralUniform(distant_mesh_wrapper,surfaces,srcMeth.c_str());
148 else if(distant_supportC->getMeshDimension()==3 && distant_supportC->getSpaceDimension()==3)
150 MEDCouplingNormalizedUnstructuredMesh<3,3> distant_mesh_wrapper(distant_supportC);
151 INTERP_KERNEL::Interpolation3D interpolation(*this);
152 colSize=interpolation.toIntegralUniform(distant_mesh_wrapper,surfaces,srcMeth.c_str());
154 else if(distant_supportC->getMeshDimension()==2 && distant_supportC->getSpaceDimension()==3)
156 MEDCouplingNormalizedUnstructuredMesh<3,2> distant_mesh_wrapper(distant_supportC);
157 INTERP_KERNEL::Interpolation3DSurf interpolation(*this);
158 colSize=interpolation.toIntegralUniform(distant_mesh_wrapper,surfaces,srcMeth.c_str());
161 throw INTERP_KERNEL::Exception("No para interpolation available for the given mesh and space dimension of distant mesh to -1D sourceMesh");
163 else if ( distant_support.getMeshDimension() == 2
164 && _source_support->getMeshDimension() == 3
165 && distant_support.getSpaceDimension() == 3 && _source_support->getSpaceDimension() == 3)
167 MEDCouplingNormalizedUnstructuredMesh<3,3> target_wrapper(distant_supportC);
168 MEDCouplingNormalizedUnstructuredMesh<3,3> source_wrapper(source_supportC);
169 INTERP_KERNEL::Interpolation3D2D interpolator (*this);
170 colSize=interpolator.interpolateMeshes(target_wrapper,source_wrapper,surfaces,interpMethod.c_str());
171 target_wrapper.releaseTempArrays();
172 source_wrapper.releaseTempArrays();
174 else if ( distant_support.getMeshDimension() == 1
175 && _source_support->getMeshDimension() == 2
176 && distant_support.getSpaceDimension() == 2 && _source_support->getSpaceDimension() == 2)
178 MEDCouplingNormalizedUnstructuredMesh<2,2> target_wrapper(distant_supportC);
179 MEDCouplingNormalizedUnstructuredMesh<2,2> source_wrapper(source_supportC);
180 INTERP_KERNEL::Interpolation2D1D interpolator (*this);
181 colSize=interpolator.interpolateMeshes(target_wrapper,source_wrapper,surfaces,interpMethod.c_str());
182 target_wrapper.releaseTempArrays();
183 source_wrapper.releaseTempArrays();
185 else if (distant_support.getMeshDimension() != _source_support->getMeshDimension())
187 throw INTERP_KERNEL::Exception("local and distant meshes do not have the same space and mesh dimensions");
189 else if( distant_support.getMeshDimension() == 1
190 && distant_support.getSpaceDimension() == 1 )
192 MEDCouplingNormalizedUnstructuredMesh<1,1> target_wrapper(distant_supportC);
193 MEDCouplingNormalizedUnstructuredMesh<1,1> source_wrapper(source_supportC);
195 INTERP_KERNEL::Interpolation1D interpolation(*this);
196 colSize=interpolation.interpolateMeshes(target_wrapper,source_wrapper,surfaces,interpMethod.c_str());
197 target_wrapper.releaseTempArrays();
198 source_wrapper.releaseTempArrays();
200 else if( distant_support.getMeshDimension() == 1
201 && distant_support.getSpaceDimension() == 2 )
203 MEDCouplingNormalizedUnstructuredMesh<2,1> target_wrapper(distant_supportC);
204 MEDCouplingNormalizedUnstructuredMesh<2,1> source_wrapper(source_supportC);
206 INTERP_KERNEL::Interpolation2DCurve interpolation(*this);
207 colSize=interpolation.interpolateMeshes(target_wrapper,source_wrapper,surfaces,interpMethod.c_str());
208 target_wrapper.releaseTempArrays();
209 source_wrapper.releaseTempArrays();
211 else if ( distant_support.getMeshDimension() == 2
212 && distant_support.getSpaceDimension() == 3 )
214 MEDCouplingNormalizedUnstructuredMesh<3,2> target_wrapper(distant_supportC);
215 MEDCouplingNormalizedUnstructuredMesh<3,2> source_wrapper(source_supportC);
217 INTERP_KERNEL::Interpolation3DSurf interpolator (*this);
218 colSize=interpolator.interpolateMeshes(target_wrapper,source_wrapper,surfaces,interpMethod.c_str());
219 target_wrapper.releaseTempArrays();
220 source_wrapper.releaseTempArrays();
222 else if ( distant_support.getMeshDimension() == 2
223 && distant_support.getSpaceDimension() == 2)
225 MEDCouplingNormalizedUnstructuredMesh<2,2> target_wrapper(distant_supportC);
226 MEDCouplingNormalizedUnstructuredMesh<2,2> source_wrapper(source_supportC);
228 INTERP_KERNEL::Interpolation2D interpolator (*this);
229 colSize=interpolator.interpolateMeshes(target_wrapper,source_wrapper,surfaces,interpMethod.c_str());
230 target_wrapper.releaseTempArrays();
231 source_wrapper.releaseTempArrays();
233 else if ( distant_support.getMeshDimension() == 3
234 && distant_support.getSpaceDimension() == 3 )
236 MEDCouplingNormalizedUnstructuredMesh<3,3> target_wrapper(distant_supportC);
237 MEDCouplingNormalizedUnstructuredMesh<3,3> source_wrapper(source_supportC);
239 INTERP_KERNEL::Interpolation3D interpolator (*this);
240 colSize=interpolator.interpolateMeshes(target_wrapper,source_wrapper,surfaces,interpMethod.c_str());
241 target_wrapper.releaseTempArrays();
242 source_wrapper.releaseTempArrays();
246 throw INTERP_KERNEL::Exception("no interpolator exists for these mesh and space dimensions ");
248 bool needTargetSurf=isSurfaceComputationNeeded(targetMeth);
250 MEDCouplingFieldDouble *target_triangle_surf=0;
252 target_triangle_surf = distant_support.getMeasureField(getMeasureAbsStatus());
253 fillDSFromVM(iproc_distant,distant_elems,surfaces,target_triangle_surf);
256 target_triangle_surf->decrRef();
259 void InterpolationMatrix::fillDSFromVM(int iproc_distant, const int* distant_elems, const std::vector< std::map<int,double> >& values, MEDCouplingFieldDouble *surf)
261 //loop over the elements to build the interpolation
263 int source_size=values.size();
264 for (int ielem=0; ielem < source_size; ielem++)
266 _row_offsets[ielem+1] += values[ielem].size();
267 for(map<int,double>::const_iterator iter=values[ielem].begin();iter!=values[ielem].end();iter++)
271 localId=distant_elems[iter->first];
274 //locating the (iproc, itriangle) pair in the list of columns
275 map<pair<int,int>,int >::iterator iter2 = _col_offsets.find(make_pair(iproc_distant,localId));
278 if (iter2 == _col_offsets.end())
280 //(iproc, itriangle) is not registered in the list
281 //of distant elements
282 col_id =_col_offsets.size();
283 _col_offsets.insert(make_pair(make_pair(iproc_distant,localId),col_id));
284 _mapping.addElementFromSource(iproc_distant,localId);
288 col_id = iter2->second;
290 //the non zero coefficient is stored
292 //col_id is the number of the column
293 //iter->second is the value of the coefficient
296 double surface = surf->getIJ(iter->first,0);
297 _target_volume[ielem].push_back(surface);
299 _coeffs[ielem].push_back(make_pair(col_id,iter->second));
304 void InterpolationMatrix::serializeMe(std::vector< std::vector< std::map<int,double> > >& data1, std::vector<int>& data2) const
308 const std::vector<std::pair<int,int> >& sendingIds=_mapping.getSendingIds();
309 std::set<int> procsS;
310 for(std::vector<std::pair<int,int> >::const_iterator iter1=sendingIds.begin();iter1!=sendingIds.end();iter1++)
311 procsS.insert((*iter1).first);
312 data1.resize(procsS.size());
313 data2.resize(procsS.size());
314 std::copy(procsS.begin(),procsS.end(),data2.begin());
315 std::map<int,int> fastProcAcc;
317 for(std::set<int>::const_iterator iter2=procsS.begin();iter2!=procsS.end();iter2++,id++)
318 fastProcAcc[*iter2]=id;
319 int nbOfSrcElt=_coeffs.size();
320 for(std::vector< std::vector< std::map<int,double> > >::iterator iter3=data1.begin();iter3!=data1.end();iter3++)
321 (*iter3).resize(nbOfSrcElt);
323 for(std::vector< std::vector< std::pair<int,double> > >::const_iterator iter4=_coeffs.begin();iter4!=_coeffs.end();iter4++,id++)
325 for(std::vector< std::pair<int,double> >::const_iterator iter5=(*iter4).begin();iter5!=(*iter4).end();iter5++)
327 const std::pair<int,int>& elt=sendingIds[(*iter5).first];
328 data1[fastProcAcc[elt.first]][id][elt.second]=(*iter5).second;
333 void InterpolationMatrix::initialize()
335 int lgth=_coeffs.size();
336 _row_offsets.clear(); _row_offsets.resize(lgth+1);
337 _coeffs.clear(); _coeffs.resize(lgth);
338 _target_volume.clear(); _target_volume.resize(lgth);
339 _col_offsets.clear();
340 _mapping.initialize();
343 void InterpolationMatrix::finishContributionW(ElementLocator& elementLocator)
345 NatureOfField nature=elementLocator.getLocalNature();
348 case ConservativeVolumic:
349 computeConservVolDenoW(elementLocator);
353 if(!elementLocator.isM1DCorr())
354 computeIntegralDenoW(elementLocator);
356 computeGlobConstraintDenoW(elementLocator);
359 case IntegralGlobConstraint:
360 computeGlobConstraintDenoW(elementLocator);
364 if(!elementLocator.isM1DCorr())
365 computeRevIntegralDenoW(elementLocator);
367 computeConservVolDenoW(elementLocator);
371 throw INTERP_KERNEL::Exception("Not recognized nature of field. Change nature of Field.");
376 void InterpolationMatrix::finishContributionL(ElementLocator& elementLocator)
378 NatureOfField nature=elementLocator.getLocalNature();
381 case ConservativeVolumic:
382 computeConservVolDenoL(elementLocator);
386 if(!elementLocator.isM1DCorr())
387 computeIntegralDenoL(elementLocator);
389 computeConservVolDenoL(elementLocator);
392 case IntegralGlobConstraint:
393 //this is not a bug doing like ConservativeVolumic
394 computeConservVolDenoL(elementLocator);
398 if(!elementLocator.isM1DCorr())
399 computeRevIntegralDenoL(elementLocator);
401 computeConservVolDenoL(elementLocator);
405 throw INTERP_KERNEL::Exception("Not recognized nature of field. Change nature of Field.");
410 void InterpolationMatrix::computeConservVolDenoW(ElementLocator& elementLocator)
412 computeGlobalColSum(_deno_reverse_multiply);
413 computeGlobalRowSum(elementLocator,_deno_multiply,_deno_reverse_multiply);
416 void InterpolationMatrix::computeConservVolDenoL(ElementLocator& elementLocator)
418 int pol1=elementLocator.sendPolicyToWorkingSideL();
419 if(pol1==ElementLocator::NO_POST_TREATMENT_POLICY)
421 elementLocator.recvFromWorkingSideL();
422 elementLocator.sendToWorkingSideL();
424 else if(ElementLocator::CUMULATIVE_POLICY)
426 //ask for lazy side to deduce ids eventually missing on working side and to send it back.
427 elementLocator.recvLocalIdsFromWorkingSideL();
428 elementLocator.sendCandidatesGlobalIdsToWorkingSideL();
429 elementLocator.recvCandidatesForAddElementsL();
430 elementLocator.sendAddElementsToWorkingSideL();
431 //Working side has updated its eventually missing ids updates its global ids with lazy side procs contribution
432 elementLocator.recvLocalIdsFromWorkingSideL();
433 elementLocator.sendGlobalIdsToWorkingSideL();
434 //like no post treatment
435 elementLocator.recvFromWorkingSideL();
436 elementLocator.sendToWorkingSideL();
439 throw INTERP_KERNEL::Exception("Not managed policy detected on lazy side : not implemented !");
442 void InterpolationMatrix::computeIntegralDenoW(ElementLocator& elementLocator)
444 MEDCouplingFieldDouble *source_triangle_surf = _source_support->getMeasureField(getMeasureAbsStatus());
445 _deno_multiply.resize(_coeffs.size());
446 vector<vector<double> >::iterator iter6=_deno_multiply.begin();
447 const double *values=source_triangle_surf->getArray()->getConstPointer();
448 for(vector<vector<pair<int,double> > >::const_iterator iter4=_coeffs.begin();iter4!=_coeffs.end();iter4++,iter6++,values++)
450 (*iter6).resize((*iter4).size());
451 std::fill((*iter6).begin(),(*iter6).end(),*values);
453 source_triangle_surf->decrRef();
454 _deno_reverse_multiply=_target_volume;
457 void InterpolationMatrix::computeRevIntegralDenoW(ElementLocator& elementLocator)
459 _deno_multiply=_target_volume;
460 MEDCouplingFieldDouble *source_triangle_surf = _source_support->getMeasureField(getMeasureAbsStatus());
461 _deno_reverse_multiply.resize(_coeffs.size());
462 vector<vector<double> >::iterator iter6=_deno_reverse_multiply.begin();
463 const double *values=source_triangle_surf->getArray()->getConstPointer();
464 for(vector<vector<pair<int,double> > >::const_iterator iter4=_coeffs.begin();iter4!=_coeffs.end();iter4++,iter6++,values++)
466 (*iter6).resize((*iter4).size());
467 std::fill((*iter6).begin(),(*iter6).end(),*values);
469 source_triangle_surf->decrRef();
473 * Nothing to do because surface computation is on working side.
475 void InterpolationMatrix::computeIntegralDenoL(ElementLocator& elementLocator)
480 * Nothing to do because surface computation is on working side.
482 void InterpolationMatrix::computeRevIntegralDenoL(ElementLocator& elementLocator)
487 void InterpolationMatrix::computeGlobConstraintDenoW(ElementLocator& elementLocator)
489 computeGlobalColSum(_deno_multiply);
490 computeGlobalRowSum(elementLocator,_deno_reverse_multiply,_deno_multiply);
493 void InterpolationMatrix::computeGlobalRowSum(ElementLocator& elementLocator, std::vector<std::vector<double> >& denoStrorage, std::vector<std::vector<double> >& denoStrorageInv)
495 //stores id in distant procs sorted by lazy procs connected with
496 vector< vector<int> > rowsPartialSumI;
497 //stores for each lazy procs connected with, if global info is available and if it's the case the policy
498 vector<int> policyPartial;
499 //stores the corresponding values.
500 vector< vector<double> > rowsPartialSumD;
501 elementLocator.recvPolicyFromLazySideW(policyPartial);
502 int pol1=mergePolicies(policyPartial);
503 if(pol1==ElementLocator::NO_POST_TREATMENT_POLICY)
505 computeLocalRowSum(elementLocator.getDistantProcIds(),rowsPartialSumI,rowsPartialSumD);
506 elementLocator.sendSumToLazySideW(rowsPartialSumI,rowsPartialSumD);
507 elementLocator.recvSumFromLazySideW(rowsPartialSumD);
509 else if(pol1==ElementLocator::CUMULATIVE_POLICY)
511 //updateWithNewAdditionnalElements(addingElements);
512 //stores for each lazy procs connected with, the ids in global mode if it exists (regarding policyPartial). This array has exactly the size of rowsPartialSumI,
513 //if policyPartial has CUMALATIVE_POLICY in each.
514 vector< vector<int> > globalIdsPartial;
515 computeLocalRowSum(elementLocator.getDistantProcIds(),rowsPartialSumI,rowsPartialSumD);
516 elementLocator.sendLocalIdsToLazyProcsW(rowsPartialSumI);
517 elementLocator.recvCandidatesGlobalIdsFromLazyProcsW(globalIdsPartial);
518 std::vector< std::vector<int> > addingElements;
519 findAdditionnalElements(elementLocator,addingElements,rowsPartialSumI,globalIdsPartial);
520 addGhostElements(elementLocator.getDistantProcIds(),addingElements);
521 rowsPartialSumI.clear();
522 globalIdsPartial.clear();
523 computeLocalRowSum(elementLocator.getDistantProcIds(),rowsPartialSumI,rowsPartialSumD);
524 elementLocator.sendLocalIdsToLazyProcsW(rowsPartialSumI);
525 elementLocator.recvGlobalIdsFromLazyProcsW(rowsPartialSumI,globalIdsPartial);
527 elementLocator.sendSumToLazySideW(rowsPartialSumI,rowsPartialSumD);
528 elementLocator.recvSumFromLazySideW(rowsPartialSumD);
529 mergeRowSum3(globalIdsPartial,rowsPartialSumD);
530 mergeCoeffs(elementLocator.getDistantProcIds(),rowsPartialSumI,globalIdsPartial,denoStrorageInv);
533 throw INTERP_KERNEL::Exception("Not managed policy detected : not implemented !");
534 divideByGlobalRowSum(elementLocator.getDistantProcIds(),rowsPartialSumI,rowsPartialSumD,denoStrorage);
538 * @param distantProcs in parameter that indicates which lazy procs are concerned.
539 * @param resPerProcI out parameter that must be cleared before calling this method. The size of 1st dimension is equal to the size of 'distantProcs'.
540 * It contains the element ids (2nd dimension) of the corresponding lazy proc.
541 * @param resPerProcD out parameter with the same format than 'resPerProcI'. It contains corresponding sum values.
543 void InterpolationMatrix::computeLocalRowSum(const std::vector<int>& distantProcs, std::vector<std::vector<int> >& resPerProcI,
544 std::vector<std::vector<double> >& resPerProcD) const
546 resPerProcI.resize(distantProcs.size());
547 resPerProcD.resize(distantProcs.size());
548 std::vector<double> res(_col_offsets.size());
549 for(vector<vector<pair<int,double> > >::const_iterator iter=_coeffs.begin();iter!=_coeffs.end();iter++)
550 for(vector<pair<int,double> >::const_iterator iter3=(*iter).begin();iter3!=(*iter).end();iter3++)
551 res[(*iter3).first]+=(*iter3).second;
554 const vector<std::pair<int,int> >& mapping=_mapping.getSendingIds();
555 for(vector<std::pair<int,int> >::const_iterator iter2=mapping.begin();iter2!=mapping.end();iter2++)
557 std::pair<set<int>::iterator,bool> isIns=procsSet.insert((*iter2).first);
559 id=std::find(distantProcs.begin(),distantProcs.end(),(*iter2).first)-distantProcs.begin();
560 resPerProcI[id].push_back((*iter2).second);
561 resPerProcD[id].push_back(res[iter2-mapping.begin()]);
566 * This method is only usable when CUMULATIVE_POLICY detected. This method finds elements ids (typically nodes) lazy side that
567 * are not present in columns of 'this' and that should regarding cumulative merge of elements regarding their global ids.
569 void InterpolationMatrix::findAdditionnalElements(ElementLocator& elementLocator, std::vector<std::vector<int> >& elementsToAdd,
570 const std::vector<std::vector<int> >& resPerProcI, const std::vector<std::vector<int> >& globalIdsPartial)
572 std::set<int> globalIds;
573 int nbLazyProcs=globalIdsPartial.size();
574 for(int i=0;i<nbLazyProcs;i++)
575 globalIds.insert(globalIdsPartial[i].begin(),globalIdsPartial[i].end());
576 std::vector<int> tmp(globalIds.size());
577 std::copy(globalIds.begin(),globalIds.end(),tmp.begin());
579 elementLocator.sendCandidatesForAddElementsW(tmp);
580 elementLocator.recvAddElementsFromLazyProcsW(elementsToAdd);
583 void InterpolationMatrix::addGhostElements(const std::vector<int>& distantProcs, const std::vector<std::vector<int> >& elementsToAdd)
585 std::vector< std::vector< std::map<int,double> > > data1;
586 std::vector<int> data2;
587 serializeMe(data1,data2);
589 int nbOfDistProcs=distantProcs.size();
590 for(int i=0;i<nbOfDistProcs;i++)
592 int procId=distantProcs[i];
593 const std::vector<int>& eltsForThisProc=elementsToAdd[i];
594 if(!eltsForThisProc.empty())
596 std::vector<int>::iterator iter1=std::find(data2.begin(),data2.end(),procId);
597 std::map<int,double> *toFeed=0;
598 if(iter1!=data2.end())
600 int rank=iter1-data2.begin();
601 toFeed=&(data1[rank].back());
605 iter1=std::lower_bound(data2.begin(),data2.end(),procId);
606 int rank=iter1-data2.begin();
607 data2.insert(iter1,procId);
608 std::vector< std::map<int,double> > tmp(data1.front().size());
609 data1.insert(data1.begin()+rank,tmp);
610 toFeed=&(data1[rank].back());
612 for(std::vector<int>::const_iterator iter2=eltsForThisProc.begin();iter2!=eltsForThisProc.end();iter2++)
613 (*toFeed)[*iter2]=0.;
617 nbOfDistProcs=data2.size();
618 for(int j=0;j<nbOfDistProcs;j++)
619 fillDSFromVM(data2[j],0,data1[j],0);
622 int InterpolationMatrix::mergePolicies(const std::vector<int>& policyPartial)
624 if(policyPartial.empty())
625 return ElementLocator::NO_POST_TREATMENT_POLICY;
626 int ref=policyPartial[0];
627 std::vector<int>::const_iterator iter1=std::find_if(policyPartial.begin(),policyPartial.end(),std::bind2nd(std::not_equal_to<int>(),ref));
628 if(iter1!=policyPartial.end())
630 std::ostringstream msg; msg << "Incompatible policies between lazy procs each other : proc # " << iter1-policyPartial.begin();
631 throw INTERP_KERNEL::Exception(msg.str().c_str());
637 * This method introduce global ids aspects in computed 'rowsPartialSumD'.
638 * As precondition rowsPartialSumD.size()==policyPartial.size()==globalIdsPartial.size(). Foreach i in [0;rowsPartialSumD.size() ) rowsPartialSumD[i].size()==globalIdsPartial[i].size()
639 * @param rowsPartialSumD : in parameter, Partial row sum computed for each lazy procs connected with.
640 * @param rowsPartialSumI : in parameter, Corresponding local ids for each lazy procs connected with.
641 * @param globalIdsPartial : in parameter, the global numbering, of elements connected with.
642 * @param globalIdsLazySideInteraction : out parameter, constituted from all global ids of lazy procs connected with.
643 * @para sumCorresponding : out parameter, relative to 'globalIdsLazySideInteraction'
645 void InterpolationMatrix::mergeRowSum(const std::vector< std::vector<double> >& rowsPartialSumD, const std::vector< std::vector<int> >& globalIdsPartial,
646 std::vector<int>& globalIdsLazySideInteraction, std::vector<double>& sumCorresponding)
648 std::map<int,double> sumToReturn;
649 int nbLazyProcs=rowsPartialSumD.size();
650 for(int i=0;i<nbLazyProcs;i++)
652 const std::vector<double>& rowSumOfP=rowsPartialSumD[i];
653 const std::vector<int>& globalIdsOfP=globalIdsPartial[i];
654 std::vector<double>::const_iterator iter1=rowSumOfP.begin();
655 std::vector<int>::const_iterator iter2=globalIdsOfP.begin();
656 for(;iter1!=rowSumOfP.end();iter1++,iter2++)
657 sumToReturn[*iter2]+=*iter1;
660 int lgth=sumToReturn.size();
661 globalIdsLazySideInteraction.resize(lgth);
662 sumCorresponding.resize(lgth);
663 std::vector<int>::iterator iter3=globalIdsLazySideInteraction.begin();
664 std::vector<double>::iterator iter4=sumCorresponding.begin();
665 for(std::map<int,double>::const_iterator iter5=sumToReturn.begin();iter5!=sumToReturn.end();iter5++,iter3++,iter4++)
667 *iter3=(*iter5).first;
668 *iter4=(*iter5).second;
673 * This method simply reorganize the result contained in 'sumCorresponding' computed by lazy side into 'rowsPartialSumD' with help of 'globalIdsPartial' and 'globalIdsLazySideInteraction'
675 * @param globalIdsPartial : in parameter, global ids sorted by lazy procs
676 * @param rowsPartialSumD : in/out parameter, with exactly the same size as 'globalIdsPartial'
677 * @param globalIdsLazySideInteraction : in parameter that represents ALL the global ids of every lazy procs in interaction
678 * @param sumCorresponding : in parameter with same size as 'globalIdsLazySideInteraction' that stores the corresponding sum of 'globalIdsLazySideInteraction'
680 void InterpolationMatrix::mergeRowSum2(const std::vector< std::vector<int> >& globalIdsPartial, std::vector< std::vector<double> >& rowsPartialSumD,
681 const std::vector<int>& globalIdsLazySideInteraction, const std::vector<double>& sumCorresponding)
683 std::map<int,double> acc;
684 std::vector<int>::const_iterator iter1=globalIdsLazySideInteraction.begin();
685 std::vector<double>::const_iterator iter2=sumCorresponding.begin();
686 for(;iter1!=globalIdsLazySideInteraction.end();iter1++,iter2++)
689 int nbLazyProcs=globalIdsPartial.size();
690 for(int i=0;i<nbLazyProcs;i++)
692 const std::vector<int>& tmp1=globalIdsPartial[i];
693 std::vector<double>& tmp2=rowsPartialSumD[i];
694 std::vector<int>::const_iterator iter3=tmp1.begin();
695 std::vector<double>::iterator iter4=tmp2.begin();
696 for(;iter3!=tmp1.end();iter3++,iter4++)
701 void InterpolationMatrix::mergeRowSum3(const std::vector< std::vector<int> >& globalIdsPartial, std::vector< std::vector<double> >& rowsPartialSumD)
703 std::map<int,double> sum;
704 std::vector< std::vector<int> >::const_iterator iter1=globalIdsPartial.begin();
705 std::vector< std::vector<double> >::iterator iter2=rowsPartialSumD.begin();
706 for(;iter1!=globalIdsPartial.end();iter1++,iter2++)
708 std::vector<int>::const_iterator iter3=(*iter1).begin();
709 std::vector<double>::const_iterator iter4=(*iter2).begin();
710 for(;iter3!=(*iter1).end();iter3++,iter4++)
713 iter2=rowsPartialSumD.begin();
714 for(iter1=globalIdsPartial.begin();iter1!=globalIdsPartial.end();iter1++,iter2++)
716 std::vector<int>::const_iterator iter3=(*iter1).begin();
717 std::vector<double>::iterator iter4=(*iter2).begin();
718 for(;iter3!=(*iter1).end();iter3++,iter4++)
724 * This method updates this->_coeffs attribute in order to take into account hidden (because having the same global number) similar nodes in _coeffs array.
725 * If in this->_coeffs two distant element id have the same global id their values will be replaced for each by the sum of the two.
726 * @param procsInInteraction input parameter : specifies the procId in absolute of distant lazy procs in interaction with
727 * @param rowsPartialSumI input parameter : local ids of distant lazy procs elements in interaction with
728 * @param globalIdsPartial input parameter : global ids of distant lazy procs elements in interaction with
730 void InterpolationMatrix::mergeCoeffs(const std::vector<int>& procsInInteraction, const std::vector< std::vector<int> >& rowsPartialSumI,
731 const std::vector<std::vector<int> >& globalIdsPartial, std::vector<std::vector<double> >& denoStrorageInv)
733 //preparing fast access structures
734 std::map<int,int> procT;
736 for(std::vector<int>::const_iterator iter1=procsInInteraction.begin();iter1!=procsInInteraction.end();iter1++,localProcId++)
737 procT[*iter1]=localProcId;
738 int size=procsInInteraction.size();
739 std::vector<std::map<int,int> > localToGlobal(size);
740 for(int i=0;i<size;i++)
742 std::map<int,int>& myLocalToGlobal=localToGlobal[i];
743 const std::vector<int>& locals=rowsPartialSumI[i];
744 const std::vector<int>& globals=globalIdsPartial[i];
745 std::vector<int>::const_iterator iter3=locals.begin();
746 std::vector<int>::const_iterator iter4=globals.begin();
747 for(;iter3!=locals.end();iter3++,iter4++)
748 myLocalToGlobal[*iter3]=*iter4;
751 const vector<std::pair<int,int> >& mapping=_mapping.getSendingIds();
752 std::map<int,double> globalIdVal;
753 //accumulate for same global id on lazy part.
754 for(vector<vector<pair<int,double> > >::iterator iter1=_coeffs.begin();iter1!=_coeffs.end();iter1++)
755 for(vector<pair<int,double> >::iterator iter2=(*iter1).begin();iter2!=(*iter1).end();iter2++)
757 const std::pair<int,int>& distantLocalLazyId=mapping[(*iter2).first];
758 int localLazyProcId=procT[distantLocalLazyId.first];
759 int globalDistantLazyId=localToGlobal[localLazyProcId][distantLocalLazyId.second];
760 globalIdVal[globalDistantLazyId]+=(*iter2).second;
763 std::vector<std::vector<double> >::iterator iter3=denoStrorageInv.begin();
764 for(vector<vector<pair<int,double> > >::iterator iter1=_coeffs.begin();iter1!=_coeffs.end();iter1++,iter3++)
766 double val=(*iter3).back();
767 (*iter3).resize((*iter1).size());
768 std::vector<double>::iterator iter4=(*iter3).begin();
769 for(vector<pair<int,double> >::iterator iter2=(*iter1).begin();iter2!=(*iter1).end();iter2++,iter4++)
771 const std::pair<int,int>& distantLocalLazyId=mapping[(*iter2).first];
772 int localLazyProcId=procT[distantLocalLazyId.first];
773 int globalDistantLazyId=localToGlobal[localLazyProcId][distantLocalLazyId.second];
774 double newVal=globalIdVal[globalDistantLazyId];
775 if((*iter2).second!=0.)
776 (*iter4)=val*newVal/(*iter2).second;
778 (*iter4)=std::numeric_limits<double>::max();
779 (*iter2).second=newVal;
784 void InterpolationMatrix::divideByGlobalRowSum(const std::vector<int>& distantProcs, const std::vector<std::vector<int> >& resPerProcI,
785 const std::vector<std::vector<double> >& resPerProcD, std::vector<std::vector<double> >& deno)
787 map<int,double> fastSums;
789 for(vector<int>::const_iterator iter1=distantProcs.begin();iter1!=distantProcs.end();iter1++,procId++)
791 const std::vector<int>& currentProcI=resPerProcI[procId];
792 const std::vector<double>& currentProcD=resPerProcD[procId];
793 vector<double>::const_iterator iter3=currentProcD.begin();
794 for(vector<int>::const_iterator iter2=currentProcI.begin();iter2!=currentProcI.end();iter2++,iter3++)
795 fastSums[_col_offsets[std::make_pair(*iter1,*iter2)]]=*iter3;
797 deno.resize(_coeffs.size());
798 vector<vector<double> >::iterator iter6=deno.begin();
799 for(vector<vector<pair<int,double> > >::const_iterator iter4=_coeffs.begin();iter4!=_coeffs.end();iter4++,iter6++)
801 (*iter6).resize((*iter4).size());
802 vector<double>::iterator iter7=(*iter6).begin();
803 for(vector<pair<int,double> >::const_iterator iter5=(*iter4).begin();iter5!=(*iter4).end();iter5++,iter7++)
804 *iter7=fastSums[(*iter5).first];
808 void InterpolationMatrix::computeGlobalColSum(std::vector<std::vector<double> >& denoStrorage)
810 denoStrorage.resize(_coeffs.size());
811 vector<vector<double> >::iterator iter2=denoStrorage.begin();
812 for(vector<vector<pair<int,double> > >::const_iterator iter1=_coeffs.begin();iter1!=_coeffs.end();iter1++,iter2++)
814 (*iter2).resize((*iter1).size());
815 double sumOfCurrentRow=0.;
816 for(vector<pair<int,double> >::const_iterator iter3=(*iter1).begin();iter3!=(*iter1).end();iter3++)
817 sumOfCurrentRow+=(*iter3).second;
818 std::fill((*iter2).begin(),(*iter2).end(),sumOfCurrentRow);
822 void InterpolationMatrix::resizeGlobalColSum(std::vector<std::vector<double> >& denoStrorage)
824 vector<vector<double> >::iterator iter2=denoStrorage.begin();
825 for(vector<vector<pair<int,double> > >::const_iterator iter1=_coeffs.begin();iter1!=_coeffs.end();iter1++,iter2++)
827 double val=(*iter2).back();
828 (*iter2).resize((*iter1).size());
829 std::fill((*iter2).begin(),(*iter2).end(),val);
833 // ==================================================================
834 // The call to this method updates the arrays on the target side
835 // so that they know which amount of data from which processor they
837 // That call makes actual interpolations via multiply method
839 // ==================================================================
841 void InterpolationMatrix::prepare()
843 int nbelems = _source_field->getField()->getNumberOfTuples();
844 for (int ielem=0; ielem < nbelems; ielem++)
846 _row_offsets[ielem+1]+=_row_offsets[ielem];
848 _mapping.prepareSendRecv();
852 // =======================================================================
853 // brief performs t=Ws, where t is the target field, s is the source field
855 // The call to this method must be called both on the working side
856 // and on the idle side. On the working side, the vector T=VT^(-1).(W.S)
857 // is computed and sent. On the idle side, no computation is done, but the
858 // result from the working side is received and the field is updated.
860 // param field source field on processors involved on the source side,
861 // target field on processors on the target side
862 // =======================================================================
864 void InterpolationMatrix::multiply(MEDCouplingFieldDouble& field) const
866 int nbcomp = field.getArray()->getNumberOfComponents();
867 vector<double> target_value(_col_offsets.size()* nbcomp,0.0);
869 //computing the matrix multiply on source side
870 if (_source_group.containsMyRank())
872 int nbrows = _coeffs.size();
875 // W is the intersection matrix
876 // S is the source vector
878 for (int irow=0; irow<nbrows; irow++)
880 for (int icomp=0; icomp< nbcomp; icomp++)
882 double coeff_row = field.getIJ(irow,icomp);
883 for (int icol=_row_offsets[irow]; icol< _row_offsets[irow+1];icol++)
885 int colid= _coeffs[irow][icol-_row_offsets[irow]].first;
886 double value = _coeffs[irow][icol-_row_offsets[irow]].second;
887 double deno = _deno_multiply[irow][icol-_row_offsets[irow]];
888 target_value[colid*nbcomp+icomp]+=value*coeff_row/deno;
894 if (_target_group.containsMyRank())
896 int nbelems = field.getArray()->getNumberOfTuples() ;
897 double* value = const_cast<double*> (field.getArray()->getPointer());
898 for (int i=0; i<nbelems*nbcomp; i++)
904 //on source side : sending T=VT^(-1).(W.S)
905 //on target side :: receiving T and storing it in field
906 _mapping.sendRecv(&target_value[0],field);
910 // =========================================================================
911 // brief performs s=WTt, where t is the target field, s is the source field,
912 // WT is the transpose matrix from W
914 // The call to this method must be called both on the working side
915 // and on the idle side. On the working side, the target vector T is
916 // received and the vector S=VS^(-1).(WT.T) is computed to update
918 // On the idle side, no computation is done, but the field is sent.
920 // param field source field on processors involved on the source side,
921 // target field on processors on the target side
922 // =========================================================================
924 void InterpolationMatrix::transposeMultiply(MEDCouplingFieldDouble& field) const
926 int nbcomp = field.getArray()->getNumberOfComponents();
927 vector<double> source_value(_col_offsets.size()* nbcomp,0.0);
928 _mapping.reverseSendRecv(&source_value[0],field);
930 //treatment of the transpose matrix multiply on the source side
931 if (_source_group.containsMyRank())
933 int nbrows = _coeffs.size();
934 double *array = field.getArray()->getPointer() ;
937 std::fill(array, array+nbrows*nbcomp, 0.0) ;
941 //T is the target vector
942 for (int irow = 0; irow < nbrows; irow++)
944 for (int icol = _row_offsets[irow]; icol < _row_offsets[irow+1]; icol++)
946 int colid = _coeffs[irow][icol-_row_offsets[irow]].first;
947 double value = _coeffs[irow][icol-_row_offsets[irow]].second;
948 double deno = _deno_reverse_multiply[irow][icol-_row_offsets[irow]];
949 for (int icomp=0; icomp<nbcomp; icomp++)
951 double coeff_row = source_value[colid*nbcomp+icomp];
952 array[irow*nbcomp+icomp] += value*coeff_row/deno;
959 bool InterpolationMatrix::isSurfaceComputationNeeded(const std::string& method) const