1 // Copyright (C) 2007-2014 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
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;
113 //computation of the intersection volumes between source and target elements
114 MEDCouplingUMesh *distant_supportC=dynamic_cast<MEDCouplingUMesh *>(&distant_support);
115 MEDCouplingUMesh *source_supportC=dynamic_cast<MEDCouplingUMesh *>(_source_support);
116 if ( distant_support.getMeshDimension() == -1 )
118 if(source_supportC->getMeshDimension()==2 && source_supportC->getSpaceDimension()==2)
120 MEDCouplingNormalizedUnstructuredMesh<2,2> source_mesh_wrapper(source_supportC);
121 INTERP_KERNEL::Interpolation2D interpolation(*this);
122 interpolation.fromIntegralUniform(source_mesh_wrapper,surfaces,srcMeth);
124 else if(source_supportC->getMeshDimension()==3 && source_supportC->getSpaceDimension()==3)
126 MEDCouplingNormalizedUnstructuredMesh<3,3> source_mesh_wrapper(source_supportC);
127 INTERP_KERNEL::Interpolation3D interpolation(*this);
128 interpolation.fromIntegralUniform(source_mesh_wrapper,surfaces,srcMeth);
130 else if(source_supportC->getMeshDimension()==2 && source_supportC->getSpaceDimension()==3)
132 MEDCouplingNormalizedUnstructuredMesh<3,2> source_mesh_wrapper(source_supportC);
133 INTERP_KERNEL::Interpolation3DSurf interpolation(*this);
134 interpolation.fromIntegralUniform(source_mesh_wrapper,surfaces,srcMeth);
137 throw INTERP_KERNEL::Exception("No para interpolation available for the given mesh and space dimension of source mesh to -1D targetMesh");
139 else if ( source_supportC->getMeshDimension() == -1 )
141 if(distant_supportC->getMeshDimension()==2 && distant_supportC->getSpaceDimension()==2)
143 MEDCouplingNormalizedUnstructuredMesh<2,2> distant_mesh_wrapper(distant_supportC);
144 INTERP_KERNEL::Interpolation2D interpolation(*this);
145 interpolation.toIntegralUniform(distant_mesh_wrapper,surfaces,srcMeth);
147 else if(distant_supportC->getMeshDimension()==3 && distant_supportC->getSpaceDimension()==3)
149 MEDCouplingNormalizedUnstructuredMesh<3,3> distant_mesh_wrapper(distant_supportC);
150 INTERP_KERNEL::Interpolation3D interpolation(*this);
151 interpolation.toIntegralUniform(distant_mesh_wrapper,surfaces,srcMeth);
153 else if(distant_supportC->getMeshDimension()==2 && distant_supportC->getSpaceDimension()==3)
155 MEDCouplingNormalizedUnstructuredMesh<3,2> distant_mesh_wrapper(distant_supportC);
156 INTERP_KERNEL::Interpolation3DSurf interpolation(*this);
157 interpolation.toIntegralUniform(distant_mesh_wrapper,surfaces,srcMeth);
160 throw INTERP_KERNEL::Exception("No para interpolation available for the given mesh and space dimension of distant mesh to -1D sourceMesh");
162 else if ( distant_support.getMeshDimension() == 2
163 && _source_support->getMeshDimension() == 3
164 && distant_support.getSpaceDimension() == 3 && _source_support->getSpaceDimension() == 3)
166 MEDCouplingNormalizedUnstructuredMesh<3,3> target_wrapper(distant_supportC);
167 MEDCouplingNormalizedUnstructuredMesh<3,3> source_wrapper(source_supportC);
168 INTERP_KERNEL::Interpolation3D2D interpolator (*this);
169 interpolator.interpolateMeshes(target_wrapper,source_wrapper,surfaces,interpMethod);
170 target_wrapper.releaseTempArrays();
171 source_wrapper.releaseTempArrays();
173 else if ( distant_support.getMeshDimension() == 1
174 && _source_support->getMeshDimension() == 2
175 && distant_support.getSpaceDimension() == 2 && _source_support->getSpaceDimension() == 2)
177 MEDCouplingNormalizedUnstructuredMesh<2,2> target_wrapper(distant_supportC);
178 MEDCouplingNormalizedUnstructuredMesh<2,2> source_wrapper(source_supportC);
179 INTERP_KERNEL::Interpolation2D1D interpolator (*this);
180 interpolator.interpolateMeshes(target_wrapper,source_wrapper,surfaces,interpMethod);
181 target_wrapper.releaseTempArrays();
182 source_wrapper.releaseTempArrays();
184 else if (distant_support.getMeshDimension() != _source_support->getMeshDimension())
186 throw INTERP_KERNEL::Exception("local and distant meshes do not have the same space and mesh dimensions");
188 else if( distant_support.getMeshDimension() == 1
189 && distant_support.getSpaceDimension() == 1 )
191 MEDCouplingNormalizedUnstructuredMesh<1,1> target_wrapper(distant_supportC);
192 MEDCouplingNormalizedUnstructuredMesh<1,1> source_wrapper(source_supportC);
194 INTERP_KERNEL::Interpolation1D interpolation(*this);
195 interpolation.interpolateMeshes(target_wrapper,source_wrapper,surfaces,interpMethod);
196 target_wrapper.releaseTempArrays();
197 source_wrapper.releaseTempArrays();
199 else if( distant_support.getMeshDimension() == 1
200 && distant_support.getSpaceDimension() == 2 )
202 MEDCouplingNormalizedUnstructuredMesh<2,1> target_wrapper(distant_supportC);
203 MEDCouplingNormalizedUnstructuredMesh<2,1> source_wrapper(source_supportC);
205 INTERP_KERNEL::Interpolation2DCurve interpolation(*this);
206 interpolation.interpolateMeshes(target_wrapper,source_wrapper,surfaces,interpMethod);
207 target_wrapper.releaseTempArrays();
208 source_wrapper.releaseTempArrays();
210 else if ( distant_support.getMeshDimension() == 2
211 && distant_support.getSpaceDimension() == 3 )
213 MEDCouplingNormalizedUnstructuredMesh<3,2> target_wrapper(distant_supportC);
214 MEDCouplingNormalizedUnstructuredMesh<3,2> source_wrapper(source_supportC);
216 INTERP_KERNEL::Interpolation3DSurf interpolator (*this);
217 interpolator.interpolateMeshes(target_wrapper,source_wrapper,surfaces,interpMethod);
218 target_wrapper.releaseTempArrays();
219 source_wrapper.releaseTempArrays();
221 else if ( distant_support.getMeshDimension() == 2
222 && distant_support.getSpaceDimension() == 2)
224 MEDCouplingNormalizedUnstructuredMesh<2,2> target_wrapper(distant_supportC);
225 MEDCouplingNormalizedUnstructuredMesh<2,2> source_wrapper(source_supportC);
227 INTERP_KERNEL::Interpolation2D interpolator (*this);
228 interpolator.interpolateMeshes(target_wrapper,source_wrapper,surfaces,interpMethod);
229 target_wrapper.releaseTempArrays();
230 source_wrapper.releaseTempArrays();
232 else if ( distant_support.getMeshDimension() == 3
233 && distant_support.getSpaceDimension() == 3 )
235 MEDCouplingNormalizedUnstructuredMesh<3,3> target_wrapper(distant_supportC);
236 MEDCouplingNormalizedUnstructuredMesh<3,3> source_wrapper(source_supportC);
238 INTERP_KERNEL::Interpolation3D interpolator (*this);
239 interpolator.interpolateMeshes(target_wrapper,source_wrapper,surfaces,interpMethod);
240 target_wrapper.releaseTempArrays();
241 source_wrapper.releaseTempArrays();
245 throw INTERP_KERNEL::Exception("no interpolator exists for these mesh and space dimensions ");
247 bool needTargetSurf=isSurfaceComputationNeeded(targetMeth);
249 MEDCouplingFieldDouble *target_triangle_surf=0;
251 target_triangle_surf = distant_support.getMeasureField(getMeasureAbsStatus());
252 fillDSFromVM(iproc_distant,distant_elems,surfaces,target_triangle_surf);
255 target_triangle_surf->decrRef();
258 void InterpolationMatrix::fillDSFromVM(int iproc_distant, const int* distant_elems, const std::vector< std::map<int,double> >& values, MEDCouplingFieldDouble *surf)
260 //loop over the elements to build the interpolation
262 int source_size=values.size();
263 for (int ielem=0; ielem < source_size; ielem++)
265 _row_offsets[ielem+1] += values[ielem].size();
266 for(map<int,double>::const_iterator iter=values[ielem].begin();iter!=values[ielem].end();iter++)
270 localId=distant_elems[iter->first];
273 //locating the (iproc, itriangle) pair in the list of columns
274 map<pair<int,int>,int >::iterator iter2 = _col_offsets.find(make_pair(iproc_distant,localId));
277 if (iter2 == _col_offsets.end())
279 //(iproc, itriangle) is not registered in the list
280 //of distant elements
281 col_id =_col_offsets.size();
282 _col_offsets.insert(make_pair(make_pair(iproc_distant,localId),col_id));
283 _mapping.addElementFromSource(iproc_distant,localId);
287 col_id = iter2->second;
289 //the non zero coefficient is stored
291 //col_id is the number of the column
292 //iter->second is the value of the coefficient
295 double surface = surf->getIJ(iter->first,0);
296 _target_volume[ielem].push_back(surface);
298 _coeffs[ielem].push_back(make_pair(col_id,iter->second));
303 void InterpolationMatrix::serializeMe(std::vector< std::vector< std::map<int,double> > >& data1, std::vector<int>& data2) const
307 const std::vector<std::pair<int,int> >& sendingIds=_mapping.getSendingIds();
308 std::set<int> procsS;
309 for(std::vector<std::pair<int,int> >::const_iterator iter1=sendingIds.begin();iter1!=sendingIds.end();iter1++)
310 procsS.insert((*iter1).first);
311 data1.resize(procsS.size());
312 data2.resize(procsS.size());
313 std::copy(procsS.begin(),procsS.end(),data2.begin());
314 std::map<int,int> fastProcAcc;
316 for(std::set<int>::const_iterator iter2=procsS.begin();iter2!=procsS.end();iter2++,id++)
317 fastProcAcc[*iter2]=id;
318 int nbOfSrcElt=_coeffs.size();
319 for(std::vector< std::vector< std::map<int,double> > >::iterator iter3=data1.begin();iter3!=data1.end();iter3++)
320 (*iter3).resize(nbOfSrcElt);
322 for(std::vector< std::vector< std::pair<int,double> > >::const_iterator iter4=_coeffs.begin();iter4!=_coeffs.end();iter4++,id++)
324 for(std::vector< std::pair<int,double> >::const_iterator iter5=(*iter4).begin();iter5!=(*iter4).end();iter5++)
326 const std::pair<int,int>& elt=sendingIds[(*iter5).first];
327 data1[fastProcAcc[elt.first]][id][elt.second]=(*iter5).second;
332 void InterpolationMatrix::initialize()
334 int lgth=_coeffs.size();
335 _row_offsets.clear(); _row_offsets.resize(lgth+1);
336 _coeffs.clear(); _coeffs.resize(lgth);
337 _target_volume.clear(); _target_volume.resize(lgth);
338 _col_offsets.clear();
339 _mapping.initialize();
342 void InterpolationMatrix::finishContributionW(ElementLocator& elementLocator)
344 NatureOfField nature=elementLocator.getLocalNature();
347 case ConservativeVolumic:
348 computeConservVolDenoW(elementLocator);
352 if(!elementLocator.isM1DCorr())
353 computeIntegralDenoW(elementLocator);
355 computeGlobConstraintDenoW(elementLocator);
358 case IntegralGlobConstraint:
359 computeGlobConstraintDenoW(elementLocator);
363 if(!elementLocator.isM1DCorr())
364 computeRevIntegralDenoW(elementLocator);
366 computeConservVolDenoW(elementLocator);
370 throw INTERP_KERNEL::Exception("Not recognized nature of field. Change nature of Field.");
375 void InterpolationMatrix::finishContributionL(ElementLocator& elementLocator)
377 NatureOfField nature=elementLocator.getLocalNature();
380 case ConservativeVolumic:
381 computeConservVolDenoL(elementLocator);
385 if(!elementLocator.isM1DCorr())
386 computeIntegralDenoL(elementLocator);
388 computeConservVolDenoL(elementLocator);
391 case IntegralGlobConstraint:
392 //this is not a bug doing like ConservativeVolumic
393 computeConservVolDenoL(elementLocator);
397 if(!elementLocator.isM1DCorr())
398 computeRevIntegralDenoL(elementLocator);
400 computeConservVolDenoL(elementLocator);
404 throw INTERP_KERNEL::Exception("Not recognized nature of field. Change nature of Field.");
409 void InterpolationMatrix::computeConservVolDenoW(ElementLocator& elementLocator)
411 computeGlobalColSum(_deno_reverse_multiply);
412 computeGlobalRowSum(elementLocator,_deno_multiply,_deno_reverse_multiply);
415 void InterpolationMatrix::computeConservVolDenoL(ElementLocator& elementLocator)
417 int pol1=elementLocator.sendPolicyToWorkingSideL();
418 if(pol1==ElementLocator::NO_POST_TREATMENT_POLICY)
420 elementLocator.recvFromWorkingSideL();
421 elementLocator.sendToWorkingSideL();
423 else if(ElementLocator::CUMULATIVE_POLICY)
425 //ask for lazy side to deduce ids eventually missing on working side and to send it back.
426 elementLocator.recvLocalIdsFromWorkingSideL();
427 elementLocator.sendCandidatesGlobalIdsToWorkingSideL();
428 elementLocator.recvCandidatesForAddElementsL();
429 elementLocator.sendAddElementsToWorkingSideL();
430 //Working side has updated its eventually missing ids updates its global ids with lazy side procs contribution
431 elementLocator.recvLocalIdsFromWorkingSideL();
432 elementLocator.sendGlobalIdsToWorkingSideL();
433 //like no post treatment
434 elementLocator.recvFromWorkingSideL();
435 elementLocator.sendToWorkingSideL();
438 throw INTERP_KERNEL::Exception("Not managed policy detected on lazy side : not implemented !");
441 void InterpolationMatrix::computeIntegralDenoW(ElementLocator& elementLocator)
443 MEDCouplingFieldDouble *source_triangle_surf = _source_support->getMeasureField(getMeasureAbsStatus());
444 _deno_multiply.resize(_coeffs.size());
445 vector<vector<double> >::iterator iter6=_deno_multiply.begin();
446 const double *values=source_triangle_surf->getArray()->getConstPointer();
447 for(vector<vector<pair<int,double> > >::const_iterator iter4=_coeffs.begin();iter4!=_coeffs.end();iter4++,iter6++,values++)
449 (*iter6).resize((*iter4).size());
450 std::fill((*iter6).begin(),(*iter6).end(),*values);
452 source_triangle_surf->decrRef();
453 _deno_reverse_multiply=_target_volume;
456 void InterpolationMatrix::computeRevIntegralDenoW(ElementLocator& elementLocator)
458 _deno_multiply=_target_volume;
459 MEDCouplingFieldDouble *source_triangle_surf = _source_support->getMeasureField(getMeasureAbsStatus());
460 _deno_reverse_multiply.resize(_coeffs.size());
461 vector<vector<double> >::iterator iter6=_deno_reverse_multiply.begin();
462 const double *values=source_triangle_surf->getArray()->getConstPointer();
463 for(vector<vector<pair<int,double> > >::const_iterator iter4=_coeffs.begin();iter4!=_coeffs.end();iter4++,iter6++,values++)
465 (*iter6).resize((*iter4).size());
466 std::fill((*iter6).begin(),(*iter6).end(),*values);
468 source_triangle_surf->decrRef();
472 * Nothing to do because surface computation is on working side.
474 void InterpolationMatrix::computeIntegralDenoL(ElementLocator& elementLocator)
479 * Nothing to do because surface computation is on working side.
481 void InterpolationMatrix::computeRevIntegralDenoL(ElementLocator& elementLocator)
486 void InterpolationMatrix::computeGlobConstraintDenoW(ElementLocator& elementLocator)
488 computeGlobalColSum(_deno_multiply);
489 computeGlobalRowSum(elementLocator,_deno_reverse_multiply,_deno_multiply);
492 void InterpolationMatrix::computeGlobalRowSum(ElementLocator& elementLocator, std::vector<std::vector<double> >& denoStrorage, std::vector<std::vector<double> >& denoStrorageInv)
494 //stores id in distant procs sorted by lazy procs connected with
495 vector< vector<int> > rowsPartialSumI;
496 //stores for each lazy procs connected with, if global info is available and if it's the case the policy
497 vector<int> policyPartial;
498 //stores the corresponding values.
499 vector< vector<double> > rowsPartialSumD;
500 elementLocator.recvPolicyFromLazySideW(policyPartial);
501 int pol1=mergePolicies(policyPartial);
502 if(pol1==ElementLocator::NO_POST_TREATMENT_POLICY)
504 computeLocalRowSum(elementLocator.getDistantProcIds(),rowsPartialSumI,rowsPartialSumD);
505 elementLocator.sendSumToLazySideW(rowsPartialSumI,rowsPartialSumD);
506 elementLocator.recvSumFromLazySideW(rowsPartialSumD);
508 else if(pol1==ElementLocator::CUMULATIVE_POLICY)
510 //updateWithNewAdditionnalElements(addingElements);
511 //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,
512 //if policyPartial has CUMALATIVE_POLICY in each.
513 vector< vector<int> > globalIdsPartial;
514 computeLocalRowSum(elementLocator.getDistantProcIds(),rowsPartialSumI,rowsPartialSumD);
515 elementLocator.sendLocalIdsToLazyProcsW(rowsPartialSumI);
516 elementLocator.recvCandidatesGlobalIdsFromLazyProcsW(globalIdsPartial);
517 std::vector< std::vector<int> > addingElements;
518 findAdditionnalElements(elementLocator,addingElements,rowsPartialSumI,globalIdsPartial);
519 addGhostElements(elementLocator.getDistantProcIds(),addingElements);
520 rowsPartialSumI.clear();
521 globalIdsPartial.clear();
522 computeLocalRowSum(elementLocator.getDistantProcIds(),rowsPartialSumI,rowsPartialSumD);
523 elementLocator.sendLocalIdsToLazyProcsW(rowsPartialSumI);
524 elementLocator.recvGlobalIdsFromLazyProcsW(rowsPartialSumI,globalIdsPartial);
526 elementLocator.sendSumToLazySideW(rowsPartialSumI,rowsPartialSumD);
527 elementLocator.recvSumFromLazySideW(rowsPartialSumD);
528 mergeRowSum3(globalIdsPartial,rowsPartialSumD);
529 mergeCoeffs(elementLocator.getDistantProcIds(),rowsPartialSumI,globalIdsPartial,denoStrorageInv);
532 throw INTERP_KERNEL::Exception("Not managed policy detected : not implemented !");
533 divideByGlobalRowSum(elementLocator.getDistantProcIds(),rowsPartialSumI,rowsPartialSumD,denoStrorage);
537 * @param distantProcs in parameter that indicates which lazy procs are concerned.
538 * @param resPerProcI out parameter that must be cleared before calling this method. The size of 1st dimension is equal to the size of 'distantProcs'.
539 * It contains the element ids (2nd dimension) of the corresponding lazy proc.
540 * @param resPerProcD out parameter with the same format than 'resPerProcI'. It contains corresponding sum values.
542 void InterpolationMatrix::computeLocalRowSum(const std::vector<int>& distantProcs, std::vector<std::vector<int> >& resPerProcI,
543 std::vector<std::vector<double> >& resPerProcD) const
545 resPerProcI.resize(distantProcs.size());
546 resPerProcD.resize(distantProcs.size());
547 std::vector<double> res(_col_offsets.size());
548 for(vector<vector<pair<int,double> > >::const_iterator iter=_coeffs.begin();iter!=_coeffs.end();iter++)
549 for(vector<pair<int,double> >::const_iterator iter3=(*iter).begin();iter3!=(*iter).end();iter3++)
550 res[(*iter3).first]+=(*iter3).second;
553 const vector<std::pair<int,int> >& mapping=_mapping.getSendingIds();
554 for(vector<std::pair<int,int> >::const_iterator iter2=mapping.begin();iter2!=mapping.end();iter2++)
556 std::pair<set<int>::iterator,bool> isIns=procsSet.insert((*iter2).first);
558 id=std::find(distantProcs.begin(),distantProcs.end(),(*iter2).first)-distantProcs.begin();
559 resPerProcI[id].push_back((*iter2).second);
560 resPerProcD[id].push_back(res[iter2-mapping.begin()]);
565 * This method is only usable when CUMULATIVE_POLICY detected. This method finds elements ids (typically nodes) lazy side that
566 * are not present in columns of 'this' and that should regarding cumulative merge of elements regarding their global ids.
568 void InterpolationMatrix::findAdditionnalElements(ElementLocator& elementLocator, std::vector<std::vector<int> >& elementsToAdd,
569 const std::vector<std::vector<int> >& resPerProcI, const std::vector<std::vector<int> >& globalIdsPartial)
571 std::set<int> globalIds;
572 int nbLazyProcs=globalIdsPartial.size();
573 for(int i=0;i<nbLazyProcs;i++)
574 globalIds.insert(globalIdsPartial[i].begin(),globalIdsPartial[i].end());
575 std::vector<int> tmp(globalIds.size());
576 std::copy(globalIds.begin(),globalIds.end(),tmp.begin());
578 elementLocator.sendCandidatesForAddElementsW(tmp);
579 elementLocator.recvAddElementsFromLazyProcsW(elementsToAdd);
582 void InterpolationMatrix::addGhostElements(const std::vector<int>& distantProcs, const std::vector<std::vector<int> >& elementsToAdd)
584 std::vector< std::vector< std::map<int,double> > > data1;
585 std::vector<int> data2;
586 serializeMe(data1,data2);
588 int nbOfDistProcs=distantProcs.size();
589 for(int i=0;i<nbOfDistProcs;i++)
591 int procId=distantProcs[i];
592 const std::vector<int>& eltsForThisProc=elementsToAdd[i];
593 if(!eltsForThisProc.empty())
595 std::vector<int>::iterator iter1=std::find(data2.begin(),data2.end(),procId);
596 std::map<int,double> *toFeed=0;
597 if(iter1!=data2.end())
599 int rank=iter1-data2.begin();
600 toFeed=&(data1[rank].back());
604 iter1=std::lower_bound(data2.begin(),data2.end(),procId);
605 int rank=iter1-data2.begin();
606 data2.insert(iter1,procId);
607 std::vector< std::map<int,double> > tmp(data1.front().size());
608 data1.insert(data1.begin()+rank,tmp);
609 toFeed=&(data1[rank].back());
611 for(std::vector<int>::const_iterator iter2=eltsForThisProc.begin();iter2!=eltsForThisProc.end();iter2++)
612 (*toFeed)[*iter2]=0.;
616 nbOfDistProcs=data2.size();
617 for(int j=0;j<nbOfDistProcs;j++)
618 fillDSFromVM(data2[j],0,data1[j],0);
621 int InterpolationMatrix::mergePolicies(const std::vector<int>& policyPartial)
623 if(policyPartial.empty())
624 return ElementLocator::NO_POST_TREATMENT_POLICY;
625 int ref=policyPartial[0];
626 std::vector<int>::const_iterator iter1=std::find_if(policyPartial.begin(),policyPartial.end(),std::bind2nd(std::not_equal_to<int>(),ref));
627 if(iter1!=policyPartial.end())
629 std::ostringstream msg; msg << "Incompatible policies between lazy procs each other : proc # " << iter1-policyPartial.begin();
630 throw INTERP_KERNEL::Exception(msg.str().c_str());
636 * This method introduce global ids aspects in computed 'rowsPartialSumD'.
637 * As precondition rowsPartialSumD.size()==policyPartial.size()==globalIdsPartial.size(). Foreach i in [0;rowsPartialSumD.size() ) rowsPartialSumD[i].size()==globalIdsPartial[i].size()
638 * @param rowsPartialSumD : in parameter, Partial row sum computed for each lazy procs connected with.
639 * @param rowsPartialSumI : in parameter, Corresponding local ids for each lazy procs connected with.
640 * @param globalIdsPartial : in parameter, the global numbering, of elements connected with.
641 * @param globalIdsLazySideInteraction : out parameter, constituted from all global ids of lazy procs connected with.
642 * @para sumCorresponding : out parameter, relative to 'globalIdsLazySideInteraction'
644 void InterpolationMatrix::mergeRowSum(const std::vector< std::vector<double> >& rowsPartialSumD, const std::vector< std::vector<int> >& globalIdsPartial,
645 std::vector<int>& globalIdsLazySideInteraction, std::vector<double>& sumCorresponding)
647 std::map<int,double> sumToReturn;
648 int nbLazyProcs=rowsPartialSumD.size();
649 for(int i=0;i<nbLazyProcs;i++)
651 const std::vector<double>& rowSumOfP=rowsPartialSumD[i];
652 const std::vector<int>& globalIdsOfP=globalIdsPartial[i];
653 std::vector<double>::const_iterator iter1=rowSumOfP.begin();
654 std::vector<int>::const_iterator iter2=globalIdsOfP.begin();
655 for(;iter1!=rowSumOfP.end();iter1++,iter2++)
656 sumToReturn[*iter2]+=*iter1;
659 int lgth=sumToReturn.size();
660 globalIdsLazySideInteraction.resize(lgth);
661 sumCorresponding.resize(lgth);
662 std::vector<int>::iterator iter3=globalIdsLazySideInteraction.begin();
663 std::vector<double>::iterator iter4=sumCorresponding.begin();
664 for(std::map<int,double>::const_iterator iter5=sumToReturn.begin();iter5!=sumToReturn.end();iter5++,iter3++,iter4++)
666 *iter3=(*iter5).first;
667 *iter4=(*iter5).second;
672 * This method simply reorganize the result contained in 'sumCorresponding' computed by lazy side into 'rowsPartialSumD' with help of 'globalIdsPartial' and 'globalIdsLazySideInteraction'
674 * @param globalIdsPartial : in parameter, global ids sorted by lazy procs
675 * @param rowsPartialSumD : in/out parameter, with exactly the same size as 'globalIdsPartial'
676 * @param globalIdsLazySideInteraction : in parameter that represents ALL the global ids of every lazy procs in interaction
677 * @param sumCorresponding : in parameter with same size as 'globalIdsLazySideInteraction' that stores the corresponding sum of 'globalIdsLazySideInteraction'
679 void InterpolationMatrix::mergeRowSum2(const std::vector< std::vector<int> >& globalIdsPartial, std::vector< std::vector<double> >& rowsPartialSumD,
680 const std::vector<int>& globalIdsLazySideInteraction, const std::vector<double>& sumCorresponding)
682 std::map<int,double> acc;
683 std::vector<int>::const_iterator iter1=globalIdsLazySideInteraction.begin();
684 std::vector<double>::const_iterator iter2=sumCorresponding.begin();
685 for(;iter1!=globalIdsLazySideInteraction.end();iter1++,iter2++)
688 int nbLazyProcs=globalIdsPartial.size();
689 for(int i=0;i<nbLazyProcs;i++)
691 const std::vector<int>& tmp1=globalIdsPartial[i];
692 std::vector<double>& tmp2=rowsPartialSumD[i];
693 std::vector<int>::const_iterator iter3=tmp1.begin();
694 std::vector<double>::iterator iter4=tmp2.begin();
695 for(;iter3!=tmp1.end();iter3++,iter4++)
700 void InterpolationMatrix::mergeRowSum3(const std::vector< std::vector<int> >& globalIdsPartial, std::vector< std::vector<double> >& rowsPartialSumD)
702 std::map<int,double> sum;
703 std::vector< std::vector<int> >::const_iterator iter1=globalIdsPartial.begin();
704 std::vector< std::vector<double> >::iterator iter2=rowsPartialSumD.begin();
705 for(;iter1!=globalIdsPartial.end();iter1++,iter2++)
707 std::vector<int>::const_iterator iter3=(*iter1).begin();
708 std::vector<double>::const_iterator iter4=(*iter2).begin();
709 for(;iter3!=(*iter1).end();iter3++,iter4++)
712 iter2=rowsPartialSumD.begin();
713 for(iter1=globalIdsPartial.begin();iter1!=globalIdsPartial.end();iter1++,iter2++)
715 std::vector<int>::const_iterator iter3=(*iter1).begin();
716 std::vector<double>::iterator iter4=(*iter2).begin();
717 for(;iter3!=(*iter1).end();iter3++,iter4++)
723 * This method updates this->_coeffs attribute in order to take into account hidden (because having the same global number) similar nodes in _coeffs array.
724 * 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.
725 * @param procsInInteraction input parameter : specifies the procId in absolute of distant lazy procs in interaction with
726 * @param rowsPartialSumI input parameter : local ids of distant lazy procs elements in interaction with
727 * @param globalIdsPartial input parameter : global ids of distant lazy procs elements in interaction with
729 void InterpolationMatrix::mergeCoeffs(const std::vector<int>& procsInInteraction, const std::vector< std::vector<int> >& rowsPartialSumI,
730 const std::vector<std::vector<int> >& globalIdsPartial, std::vector<std::vector<double> >& denoStrorageInv)
732 //preparing fast access structures
733 std::map<int,int> procT;
735 for(std::vector<int>::const_iterator iter1=procsInInteraction.begin();iter1!=procsInInteraction.end();iter1++,localProcId++)
736 procT[*iter1]=localProcId;
737 int size=procsInInteraction.size();
738 std::vector<std::map<int,int> > localToGlobal(size);
739 for(int i=0;i<size;i++)
741 std::map<int,int>& myLocalToGlobal=localToGlobal[i];
742 const std::vector<int>& locals=rowsPartialSumI[i];
743 const std::vector<int>& globals=globalIdsPartial[i];
744 std::vector<int>::const_iterator iter3=locals.begin();
745 std::vector<int>::const_iterator iter4=globals.begin();
746 for(;iter3!=locals.end();iter3++,iter4++)
747 myLocalToGlobal[*iter3]=*iter4;
750 const vector<std::pair<int,int> >& mapping=_mapping.getSendingIds();
751 std::map<int,double> globalIdVal;
752 //accumulate for same global id on lazy part.
753 for(vector<vector<pair<int,double> > >::iterator iter1=_coeffs.begin();iter1!=_coeffs.end();iter1++)
754 for(vector<pair<int,double> >::iterator iter2=(*iter1).begin();iter2!=(*iter1).end();iter2++)
756 const std::pair<int,int>& distantLocalLazyId=mapping[(*iter2).first];
757 int localLazyProcId=procT[distantLocalLazyId.first];
758 int globalDistantLazyId=localToGlobal[localLazyProcId][distantLocalLazyId.second];
759 globalIdVal[globalDistantLazyId]+=(*iter2).second;
762 std::vector<std::vector<double> >::iterator iter3=denoStrorageInv.begin();
763 for(vector<vector<pair<int,double> > >::iterator iter1=_coeffs.begin();iter1!=_coeffs.end();iter1++,iter3++)
765 double val=(*iter3).back();
766 (*iter3).resize((*iter1).size());
767 std::vector<double>::iterator iter4=(*iter3).begin();
768 for(vector<pair<int,double> >::iterator iter2=(*iter1).begin();iter2!=(*iter1).end();iter2++,iter4++)
770 const std::pair<int,int>& distantLocalLazyId=mapping[(*iter2).first];
771 int localLazyProcId=procT[distantLocalLazyId.first];
772 int globalDistantLazyId=localToGlobal[localLazyProcId][distantLocalLazyId.second];
773 double newVal=globalIdVal[globalDistantLazyId];
774 if((*iter2).second!=0.)
775 (*iter4)=val*newVal/(*iter2).second;
777 (*iter4)=std::numeric_limits<double>::max();
778 (*iter2).second=newVal;
783 void InterpolationMatrix::divideByGlobalRowSum(const std::vector<int>& distantProcs, const std::vector<std::vector<int> >& resPerProcI,
784 const std::vector<std::vector<double> >& resPerProcD, std::vector<std::vector<double> >& deno)
786 map<int,double> fastSums;
788 for(vector<int>::const_iterator iter1=distantProcs.begin();iter1!=distantProcs.end();iter1++,procId++)
790 const std::vector<int>& currentProcI=resPerProcI[procId];
791 const std::vector<double>& currentProcD=resPerProcD[procId];
792 vector<double>::const_iterator iter3=currentProcD.begin();
793 for(vector<int>::const_iterator iter2=currentProcI.begin();iter2!=currentProcI.end();iter2++,iter3++)
794 fastSums[_col_offsets[std::make_pair(*iter1,*iter2)]]=*iter3;
796 deno.resize(_coeffs.size());
797 vector<vector<double> >::iterator iter6=deno.begin();
798 for(vector<vector<pair<int,double> > >::const_iterator iter4=_coeffs.begin();iter4!=_coeffs.end();iter4++,iter6++)
800 (*iter6).resize((*iter4).size());
801 vector<double>::iterator iter7=(*iter6).begin();
802 for(vector<pair<int,double> >::const_iterator iter5=(*iter4).begin();iter5!=(*iter4).end();iter5++,iter7++)
803 *iter7=fastSums[(*iter5).first];
807 void InterpolationMatrix::computeGlobalColSum(std::vector<std::vector<double> >& denoStrorage)
809 denoStrorage.resize(_coeffs.size());
810 vector<vector<double> >::iterator iter2=denoStrorage.begin();
811 for(vector<vector<pair<int,double> > >::const_iterator iter1=_coeffs.begin();iter1!=_coeffs.end();iter1++,iter2++)
813 (*iter2).resize((*iter1).size());
814 double sumOfCurrentRow=0.;
815 for(vector<pair<int,double> >::const_iterator iter3=(*iter1).begin();iter3!=(*iter1).end();iter3++)
816 sumOfCurrentRow+=(*iter3).second;
817 std::fill((*iter2).begin(),(*iter2).end(),sumOfCurrentRow);
821 void InterpolationMatrix::resizeGlobalColSum(std::vector<std::vector<double> >& denoStrorage)
823 vector<vector<double> >::iterator iter2=denoStrorage.begin();
824 for(vector<vector<pair<int,double> > >::const_iterator iter1=_coeffs.begin();iter1!=_coeffs.end();iter1++,iter2++)
826 double val=(*iter2).back();
827 (*iter2).resize((*iter1).size());
828 std::fill((*iter2).begin(),(*iter2).end(),val);
832 // ==================================================================
833 // The call to this method updates the arrays on the target side
834 // so that they know which amount of data from which processor they
836 // That call makes actual interpolations via multiply method
838 // ==================================================================
840 void InterpolationMatrix::prepare()
842 int nbelems = _source_field->getField()->getNumberOfTuples();
843 for (int ielem=0; ielem < nbelems; ielem++)
845 _row_offsets[ielem+1]+=_row_offsets[ielem];
847 _mapping.prepareSendRecv();
851 // =======================================================================
852 // brief performs t=Ws, where t is the target field, s is the source field
854 // The call to this method must be called both on the working side
855 // and on the idle side. On the working side, the vector T=VT^(-1).(W.S)
856 // is computed and sent. On the idle side, no computation is done, but the
857 // result from the working side is received and the field is updated.
859 // param field source field on processors involved on the source side,
860 // target field on processors on the target side
861 // =======================================================================
863 void InterpolationMatrix::multiply(MEDCouplingFieldDouble& field) const
865 int nbcomp = field.getArray()->getNumberOfComponents();
866 vector<double> target_value(_col_offsets.size()* nbcomp,0.0);
868 //computing the matrix multiply on source side
869 if (_source_group.containsMyRank())
871 int nbrows = _coeffs.size();
874 // W is the intersection matrix
875 // S is the source vector
877 for (int irow=0; irow<nbrows; irow++)
879 for (int icomp=0; icomp< nbcomp; icomp++)
881 double coeff_row = field.getIJ(irow,icomp);
882 for (int icol=_row_offsets[irow]; icol< _row_offsets[irow+1];icol++)
884 int colid= _coeffs[irow][icol-_row_offsets[irow]].first;
885 double value = _coeffs[irow][icol-_row_offsets[irow]].second;
886 double deno = _deno_multiply[irow][icol-_row_offsets[irow]];
887 target_value[colid*nbcomp+icomp]+=value*coeff_row/deno;
893 if (_target_group.containsMyRank())
895 int nbelems = field.getArray()->getNumberOfTuples() ;
896 double* value = const_cast<double*> (field.getArray()->getPointer());
897 for (int i=0; i<nbelems*nbcomp; i++)
903 //on source side : sending T=VT^(-1).(W.S)
904 //on target side :: receiving T and storing it in field
905 _mapping.sendRecv(&target_value[0],field);
909 // =========================================================================
910 // brief performs s=WTt, where t is the target field, s is the source field,
911 // WT is the transpose matrix from W
913 // The call to this method must be called both on the working side
914 // and on the idle side. On the working side, the target vector T is
915 // received and the vector S=VS^(-1).(WT.T) is computed to update
917 // On the idle side, no computation is done, but the field is sent.
919 // param field source field on processors involved on the source side,
920 // target field on processors on the target side
921 // =========================================================================
923 void InterpolationMatrix::transposeMultiply(MEDCouplingFieldDouble& field) const
925 int nbcomp = field.getArray()->getNumberOfComponents();
926 vector<double> source_value(_col_offsets.size()* nbcomp,0.0);
927 _mapping.reverseSendRecv(&source_value[0],field);
929 //treatment of the transpose matrix multiply on the source side
930 if (_source_group.containsMyRank())
932 int nbrows = _coeffs.size();
933 double *array = field.getArray()->getPointer() ;
936 std::fill(array, array+nbrows*nbcomp, 0.0) ;
940 //T is the target vector
941 for (int irow = 0; irow < nbrows; irow++)
943 for (int icol = _row_offsets[irow]; icol < _row_offsets[irow+1]; icol++)
945 int colid = _coeffs[irow][icol-_row_offsets[irow]].first;
946 double value = _coeffs[irow][icol-_row_offsets[irow]].second;
947 double deno = _deno_reverse_multiply[irow][icol-_row_offsets[irow]];
948 for (int icomp=0; icomp<nbcomp; icomp++)
950 double coeff_row = source_value[colid*nbcomp+icomp];
951 array[irow*nbcomp+icomp] += value*coeff_row/deno;
958 bool InterpolationMatrix::isSurfaceComputationNeeded(const std::string& method) const