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
19 // Author : Anthony Geay (CEA/DEN)
21 #include "MEDCouplingRemapper.hxx"
22 #include "MEDCouplingMemArray.hxx"
23 #include "MEDCouplingFieldDouble.hxx"
24 #include "MEDCouplingFieldTemplate.hxx"
25 #include "MEDCouplingFieldDiscretization.hxx"
26 #include "MEDCouplingExtrudedMesh.hxx"
27 #include "MEDCouplingCMesh.hxx"
28 #include "MEDCouplingNormalizedUnstructuredMesh.txx"
29 #include "MEDCouplingNormalizedCartesianMesh.txx"
31 #include "Interpolation1D.txx"
32 #include "Interpolation2DCurve.hxx"
33 #include "Interpolation2D.txx"
34 #include "Interpolation3D.txx"
35 #include "Interpolation3DSurf.hxx"
36 #include "Interpolation2D1D.txx"
37 #include "Interpolation3D2D.txx"
38 #include "InterpolationCU.txx"
39 #include "InterpolationCC.txx"
41 using namespace ParaMEDMEM;
43 MEDCouplingRemapper::MEDCouplingRemapper():_src_ft(0),_target_ft(0),_interp_matrix_pol(IK_ONLY_PREFERED),_nature_of_deno(NoNature),_time_deno_update(0)
47 MEDCouplingRemapper::~MEDCouplingRemapper()
52 int MEDCouplingRemapper::prepare(const MEDCouplingMesh *srcMesh, const MEDCouplingMesh *targetMesh, const std::string& method)
54 if(!srcMesh || !targetMesh)
55 throw INTERP_KERNEL::Exception("MEDCouplingRemapper::prepare : presence of NULL input pointer !");
56 std::string srcMethod,targetMethod;
57 INTERP_KERNEL::Interpolation<INTERP_KERNEL::Interpolation3D>::CheckAndSplitInterpolationMethod(method,srcMethod,targetMethod);
58 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldTemplate> src=MEDCouplingFieldTemplate::New(MEDCouplingFieldDiscretization::GetTypeOfFieldFromStringRepr(srcMethod));
59 src->setMesh(srcMesh);
60 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldTemplate> target=MEDCouplingFieldTemplate::New(MEDCouplingFieldDiscretization::GetTypeOfFieldFromStringRepr(targetMethod));
61 target->setMesh(targetMesh);
62 return prepareEx(src,target);
65 int MEDCouplingRemapper::prepareEx(const MEDCouplingFieldTemplate *src, const MEDCouplingFieldTemplate *target)
68 throw INTERP_KERNEL::Exception("MEDCouplingRemapper::prepareEx : presence of NULL input pointer !");
69 if(!src->getMesh() || !target->getMesh())
70 throw INTERP_KERNEL::Exception("MEDCouplingRemapper::prepareEx : presence of NULL mesh pointer in given field template !");
72 _src_ft=const_cast<MEDCouplingFieldTemplate *>(src); _src_ft->incrRef();
73 _target_ft=const_cast<MEDCouplingFieldTemplate *>(target); _target_ft->incrRef();
74 if(isInterpKernelOnlyOrNotOnly())
75 return prepareInterpKernelOnly();
77 return prepareNotInterpKernelOnly();
80 int MEDCouplingRemapper::prepareInterpKernelOnly()
82 int meshInterpType=((int)_src_ft->getMesh()->getType()*16)+(int)_target_ft->getMesh()->getType();
83 switch(meshInterpType)
93 case 85://Unstructured-Unstructured
94 return prepareInterpKernelOnlyUU();
97 case 87://Unstructured-Cartesian
98 return prepareInterpKernelOnlyUC();
101 case 117://Cartesian-Unstructured
102 return prepareInterpKernelOnlyCU();
103 case 119://Cartesian-Cartesian
104 return prepareInterpKernelOnlyCC();
105 case 136://Extruded-Extruded
106 return prepareInterpKernelOnlyEE();
108 throw INTERP_KERNEL::Exception("MEDCouplingRemapper::prepareInterpKernelOnly : Not managed type of meshes ! Dealt meshes type are : Unstructured<->Unstructured, Unstructured<->Cartesian, Cartesian<->Cartesian, Extruded<->Extruded !");
112 int MEDCouplingRemapper::prepareNotInterpKernelOnly()
114 std::string srcm,trgm,method;
115 method=checkAndGiveInterpolationMethodStr(srcm,trgm);
116 switch(CheckInterpolationMethodManageableByNotOnlyInterpKernel(method))
119 return prepareNotInterpKernelOnlyGaussGauss();
122 std::ostringstream oss; oss << "MEDCouplingRemapper::prepareNotInterpKernelOnly : INTERNAL ERROR ! the method \"" << method << "\" declared as managed bu not implemented !";
123 throw INTERP_KERNEL::Exception(oss.str().c_str());
129 * This method performs the operation source to target using matrix computed in ParaMEDMEM::MEDCouplingRemapper::prepare method.
130 * If meshes of \b srcField and \b targetField do not match exactly those given into \ref ParaMEDMEM::MEDCouplingRemapper::prepare "prepare method" an exception will be thrown.
132 * \param [in] srcField is the source field from which the interpolation will be done. The mesh into \b srcField should be the same than those specified on ParaMEDMEM::MEDCouplingRemapper::prepare.
133 * \param [out] targetField the destination field with the allocated array in which all tuples will be overwritten.
135 void MEDCouplingRemapper::transfer(const MEDCouplingFieldDouble *srcField, MEDCouplingFieldDouble *targetField, double dftValue)
137 if(!srcField || !targetField)
138 throw INTERP_KERNEL::Exception("MEDCouplingRemapper::transfer : input field must be both not NULL !");
139 transferUnderground(srcField,targetField,true,dftValue);
143 * This method is equivalent to ParaMEDMEM::MEDCouplingRemapper::transfer except that here \b targetField is a in/out parameter.
144 * If an entity (cell for example) in targetField is not fetched by any entity (cell for example) of \b srcField, the value in targetField is
146 * This method requires that \b targetField was fully defined and allocated. If the array is not allocated an exception will be thrown.
148 * \param [in] srcField is the source field from which the interpolation will be done. The mesh into \b srcField should be the same than those specified on ParaMEDMEM::MEDCouplingRemapper::prepare.
149 * \param [in,out] targetField the destination field with the allocated array in which only tuples whose entities are fetched by interpolation will be overwritten only.
151 void MEDCouplingRemapper::partialTransfer(const MEDCouplingFieldDouble *srcField, MEDCouplingFieldDouble *targetField)
153 if(!srcField || !targetField)
154 throw INTERP_KERNEL::Exception("MEDCouplingRemapper::partialTransfer : input field must be both not NULL !");
155 transferUnderground(srcField,targetField,false,std::numeric_limits<double>::max());
158 void MEDCouplingRemapper::reverseTransfer(MEDCouplingFieldDouble *srcField, const MEDCouplingFieldDouble *targetField, double dftValue)
160 if(!srcField || !targetField)
161 throw INTERP_KERNEL::Exception("MEDCouplingRemapper::reverseTransfer : input fields must be both not NULL !");
163 targetField->checkCoherency();
164 if(_src_ft->getDiscretization()->getStringRepr()!=srcField->getDiscretization()->getStringRepr())
165 throw INTERP_KERNEL::Exception("Incoherency with prepare call for source field");
166 if(_target_ft->getDiscretization()->getStringRepr()!=targetField->getDiscretization()->getStringRepr())
167 throw INTERP_KERNEL::Exception("Incoherency with prepare call for target field");
168 if(srcField->getNature()!=targetField->getNature())
169 throw INTERP_KERNEL::Exception("Natures of fields mismatch !");
170 if(targetField->getNumberOfTuplesExpected()!=_target_ft->getNumberOfTuplesExpected())
172 std::ostringstream oss;
173 oss << "MEDCouplingRemapper::reverseTransfer : in given source field the number of tuples required is " << _target_ft->getNumberOfTuplesExpected() << " (on prepare) and number of tuples in given target field is " << targetField->getNumberOfTuplesExpected();
174 oss << " ! It appears that the target support is not the same between the prepare and the transfer !";
175 throw INTERP_KERNEL::Exception(oss.str().c_str());
177 DataArrayDouble *array(srcField->getArray());
178 int trgNbOfCompo=targetField->getNumberOfComponents();
181 srcField->checkCoherency();
182 if(trgNbOfCompo!=srcField->getNumberOfTuplesExpected())
183 throw INTERP_KERNEL::Exception("Number of components mismatch !");
187 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble > tmp(DataArrayDouble::New());
188 tmp->alloc(srcField->getNumberOfTuplesExpected(),trgNbOfCompo);
189 srcField->setArray(tmp);
191 computeDeno(srcField->getNature(),srcField,targetField);
192 double *resPointer(srcField->getArray()->getPointer());
193 const double *inputPointer=targetField->getArray()->getConstPointer();
194 computeReverseProduct(inputPointer,trgNbOfCompo,dftValue,resPointer);
197 MEDCouplingFieldDouble *MEDCouplingRemapper::transferField(const MEDCouplingFieldDouble *srcField, double dftValue)
201 throw INTERP_KERNEL::Exception("MEDCouplingRemapper::transferField : input srcField is NULL !");
202 srcField->checkCoherency();
203 if(_src_ft->getDiscretization()->getStringRepr()!=srcField->getDiscretization()->getStringRepr())
204 throw INTERP_KERNEL::Exception("Incoherency with prepare call for source field");
205 MEDCouplingFieldDouble *ret=MEDCouplingFieldDouble::New(*_target_ft,srcField->getTimeDiscretization());
206 ret->setNature(srcField->getNature());
207 transfer(srcField,ret,dftValue);
208 ret->copyAllTinyAttrFrom(srcField);//perform copy of tiny strings after and not before transfer because the array will be created on transfer
212 MEDCouplingFieldDouble *MEDCouplingRemapper::reverseTransferField(const MEDCouplingFieldDouble *targetField, double dftValue)
215 throw INTERP_KERNEL::Exception("MEDCouplingRemapper::transferField : input targetField is NULL !");
216 targetField->checkCoherency();
218 if(_target_ft->getDiscretization()->getStringRepr()!=targetField->getDiscretization()->getStringRepr())
219 throw INTERP_KERNEL::Exception("Incoherency with prepare call for target field");
220 MEDCouplingFieldDouble *ret=MEDCouplingFieldDouble::New(*_src_ft,targetField->getTimeDiscretization());
221 ret->setNature(targetField->getNature());
222 reverseTransfer(ret,targetField,dftValue);
223 ret->copyAllTinyAttrFrom(targetField);//perform copy of tiny strings after and not before reverseTransfer because the array will be created on reverseTransfer
228 * This method does nothing more than inherited INTERP_KERNEL::InterpolationOptions::setOptionInt method. This method
229 * is here only for automatic CORBA generators.
231 bool MEDCouplingRemapper::setOptionInt(const std::string& key, int value)
233 return INTERP_KERNEL::InterpolationOptions::setOptionInt(key,value);
237 * This method does nothing more than inherited INTERP_KERNEL::InterpolationOptions::setOptionInt method. This method
238 * is here only for automatic CORBA generators.
240 bool MEDCouplingRemapper::setOptionDouble(const std::string& key, double value)
242 return INTERP_KERNEL::InterpolationOptions::setOptionDouble(key,value);
246 * This method does nothing more than inherited INTERP_KERNEL::InterpolationOptions::setOptionInt method. This method
247 * is here only for automatic CORBA generators.
249 bool MEDCouplingRemapper::setOptionString(const std::string& key, const std::string& value)
251 return INTERP_KERNEL::InterpolationOptions::setOptionString(key,value);
255 * This method returns the interpolation matrix policy. This policy specifies which interpolation matrix method to keep or prefered.
256 * If interpolation matrix policy is :
258 * - set to IK_ONLY_PREFERED (0) (the default) : the INTERP_KERNEL only method is prefered. That is to say, if it is possible to treat the case
259 * regarding spatial discretization of source and target with INTERP_KERNEL only method, INTERP_KERNEL only method will be performed.
260 * If not, the \b not only INTERP_KERNEL method will be attempt.
262 * - set to NOT_IK_ONLY_PREFERED (1) : the \b NOT only INTERP_KERNEL method is prefered. That is to say, if it is possible to treat the case
263 * regarding spatial discretization of source and target with \b NOT only INTERP_KERNEL method, \b NOT only INTERP_KERNEL method, will be performed.
264 * If not, the INTERP_KERNEL only method will be attempt.
266 * - IK_ONLY_FORCED (2) : Only INTERP_KERNEL only method will be launched.
268 * - NOT_IK_ONLY_FORCED (3) : Only \b NOT INTERP_KERNEL only method will be launched.
270 * \sa MEDCouplingRemapper::setInterpolationMatrixPolicy
272 int MEDCouplingRemapper::getInterpolationMatrixPolicy() const
274 return _interp_matrix_pol;
278 * This method sets a new interpolation matrix policy. The default one is IK_PREFERED (0). The input is of type \c int to be dealt by standard Salome
279 * CORBA component generators. This method throws an INTERP_KERNEL::Exception if a the input integer is not in the available possibilities, that is to say not in
280 * [0 (IK_PREFERED) , 1 (NOT_IK_PREFERED), 2 (IK_ONLY_FORCED), 3 (NOT_IK_ONLY_FORCED)].
282 * If interpolation matrix policy is :
284 * - set to IK_ONLY_PREFERED (0) (the default) : the INTERP_KERNEL only method is prefered. That is to say, if it is possible to treat the case
285 * regarding spatial discretization of source and target with INTERP_KERNEL only method, INTERP_KERNEL only method will be performed.
286 * If not, the \b not only INTERP_KERNEL method will be attempt.
288 * - set to NOT_IK_ONLY_PREFERED (1) : the \b NOT only INTERP_KERNEL method is prefered. That is to say, if it is possible to treat the case
289 * regarding spatial discretization of source and target with \b NOT only INTERP_KERNEL method, \b NOT only INTERP_KERNEL method, will be performed.
290 * If not, the INTERP_KERNEL only method will be attempt.
292 * - IK_ONLY_FORCED (2) : Only INTERP_KERNEL only method will be launched.
294 * - NOT_IK_ONLY_FORCED (3) : Only \b NOT INTERP_KERNEL only method will be launched.
296 * \input newInterpMatPol the new interpolation matrix method policy. This parameter is of type \c int and not of type \c ParaMEDMEM::InterpolationMatrixPolicy
297 * for automatic generation of CORBA component.
299 * \sa MEDCouplingRemapper::getInterpolationMatrixPolicy
301 void MEDCouplingRemapper::setInterpolationMatrixPolicy(int newInterpMatPol)
303 switch(newInterpMatPol)
306 _interp_matrix_pol=IK_ONLY_PREFERED;
309 _interp_matrix_pol=NOT_IK_ONLY_PREFERED;
312 _interp_matrix_pol=IK_ONLY_FORCED;
315 _interp_matrix_pol=NOT_IK_ONLY_FORCED;
318 throw INTERP_KERNEL::Exception("MEDCouplingRemapper::setInterpolationMatrixPolicy : invalid input integer value ! Should be in [0 (IK_PREFERED) , 1 (NOT_IK_PREFERED), 2 (IK_ONLY_FORCED), 3 (NOT_IK_ONLY_FORCED)] ! For information, the default is IK_PREFERED=0 !");
322 int MEDCouplingRemapper::prepareInterpKernelOnlyUU()
324 const MEDCouplingPointSet *src_mesh=static_cast<const MEDCouplingPointSet *>(_src_ft->getMesh());
325 const MEDCouplingPointSet *target_mesh=static_cast<const MEDCouplingPointSet *>(_target_ft->getMesh());
326 std::string srcMeth,trgMeth;
327 std::string method(checkAndGiveInterpolationMethodStr(srcMeth,trgMeth));
328 const int srcMeshDim=src_mesh->getMeshDimension();
331 srcSpaceDim=src_mesh->getSpaceDimension();
332 const int trgMeshDim=target_mesh->getMeshDimension();
335 trgSpaceDim=target_mesh->getSpaceDimension();
336 if(trgSpaceDim!=srcSpaceDim)
337 if(trgSpaceDim!=-1 && srcSpaceDim!=-1)
338 throw INTERP_KERNEL::Exception("Incoherent space dimension detected between target and source.");
340 if(srcMeshDim==1 && trgMeshDim==1 && srcSpaceDim==1)
342 MEDCouplingNormalizedUnstructuredMesh<1,1> source_mesh_wrapper(src_mesh);
343 MEDCouplingNormalizedUnstructuredMesh<1,1> target_mesh_wrapper(target_mesh);
344 INTERP_KERNEL::Interpolation1D interpolation(*this);
345 nbCols=interpolation.interpolateMeshes(source_mesh_wrapper,target_mesh_wrapper,_matrix,method);
347 else if(srcMeshDim==1 && trgMeshDim==1 && srcSpaceDim==2)
349 MEDCouplingNormalizedUnstructuredMesh<2,1> source_mesh_wrapper(src_mesh);
350 MEDCouplingNormalizedUnstructuredMesh<2,1> target_mesh_wrapper(target_mesh);
351 INTERP_KERNEL::Interpolation2DCurve interpolation(*this);
352 nbCols=interpolation.interpolateMeshes(source_mesh_wrapper,target_mesh_wrapper,_matrix,method);
354 else if(srcMeshDim==2 && trgMeshDim==2 && srcSpaceDim==2)
356 MEDCouplingNormalizedUnstructuredMesh<2,2> source_mesh_wrapper(src_mesh);
357 MEDCouplingNormalizedUnstructuredMesh<2,2> target_mesh_wrapper(target_mesh);
358 INTERP_KERNEL::Interpolation2D interpolation(*this);
359 nbCols=interpolation.interpolateMeshes(source_mesh_wrapper,target_mesh_wrapper,_matrix,method);
361 else if(srcMeshDim==3 && trgMeshDim==3 && srcSpaceDim==3)
363 MEDCouplingNormalizedUnstructuredMesh<3,3> source_mesh_wrapper(src_mesh);
364 MEDCouplingNormalizedUnstructuredMesh<3,3> target_mesh_wrapper(target_mesh);
365 INTERP_KERNEL::Interpolation3D interpolation(*this);
366 nbCols=interpolation.interpolateMeshes(source_mesh_wrapper,target_mesh_wrapper,_matrix,method);
368 else if(srcMeshDim==2 && trgMeshDim==2 && srcSpaceDim==3)
370 MEDCouplingNormalizedUnstructuredMesh<3,2> source_mesh_wrapper(src_mesh);
371 MEDCouplingNormalizedUnstructuredMesh<3,2> target_mesh_wrapper(target_mesh);
372 INTERP_KERNEL::Interpolation3DSurf interpolation(*this);
373 nbCols=interpolation.interpolateMeshes(source_mesh_wrapper,target_mesh_wrapper,_matrix,method);
375 else if(srcMeshDim==3 && trgMeshDim==1 && srcSpaceDim==3)
377 if(getIntersectionType()!=INTERP_KERNEL::PointLocator)
378 throw INTERP_KERNEL::Exception("Invalid interpolation requested between 3D and 1D ! Select PointLocator as intersection type !");
379 MEDCouplingNormalizedUnstructuredMesh<3,3> source_mesh_wrapper(src_mesh);
380 MEDCouplingNormalizedUnstructuredMesh<3,3> target_mesh_wrapper(target_mesh);
381 INTERP_KERNEL::Interpolation3D interpolation(*this);
382 nbCols=interpolation.interpolateMeshes(source_mesh_wrapper,target_mesh_wrapper,_matrix,method);
384 else if(srcMeshDim==1 && trgMeshDim==3 && srcSpaceDim==3)
386 if(getIntersectionType()!=INTERP_KERNEL::PointLocator)
387 throw INTERP_KERNEL::Exception("Invalid interpolation requested between 3D and 1D ! Select PointLocator as intersection type !");
388 MEDCouplingNormalizedUnstructuredMesh<3,3> source_mesh_wrapper(src_mesh);
389 MEDCouplingNormalizedUnstructuredMesh<3,3> target_mesh_wrapper(target_mesh);
390 INTERP_KERNEL::Interpolation3D interpolation(*this);
391 std::vector<std::map<int,double> > matrixTmp;
392 std::string revMethod(BuildMethodFrom(trgMeth,srcMeth));
393 nbCols=interpolation.interpolateMeshes(target_mesh_wrapper,source_mesh_wrapper,matrixTmp,revMethod);
394 ReverseMatrix(matrixTmp,nbCols,_matrix);
395 nbCols=matrixTmp.size();
397 else if(srcMeshDim==2 && trgMeshDim==1 && srcSpaceDim==2)
399 if(getIntersectionType()==INTERP_KERNEL::PointLocator)
401 MEDCouplingNormalizedUnstructuredMesh<2,2> source_mesh_wrapper(src_mesh);
402 MEDCouplingNormalizedUnstructuredMesh<2,2> target_mesh_wrapper(target_mesh);
403 INTERP_KERNEL::Interpolation2D interpolation(*this);
404 nbCols=interpolation.interpolateMeshes(source_mesh_wrapper,target_mesh_wrapper,_matrix,method);
408 MEDCouplingNormalizedUnstructuredMesh<2,2> source_mesh_wrapper(src_mesh);
409 MEDCouplingNormalizedUnstructuredMesh<2,2> target_mesh_wrapper(target_mesh);
410 INTERP_KERNEL::Interpolation2D1D interpolation(*this);
411 std::vector<std::map<int,double> > matrixTmp;
412 std::string revMethod(BuildMethodFrom(trgMeth,srcMeth));
413 nbCols=interpolation.interpolateMeshes(target_mesh_wrapper,source_mesh_wrapper,matrixTmp,revMethod);
414 ReverseMatrix(matrixTmp,nbCols,_matrix);
415 nbCols=matrixTmp.size();
416 INTERP_KERNEL::Interpolation2D1D::DuplicateFacesType duplicateFaces=interpolation.retrieveDuplicateFaces();
417 if(!duplicateFaces.empty())
419 std::ostringstream oss; oss << "An unexpected situation happend ! For the following 1D Cells are part of edges shared by 2D cells :\n";
420 for(std::map<int,std::set<int> >::const_iterator it=duplicateFaces.begin();it!=duplicateFaces.end();it++)
422 oss << "1D Cell #" << (*it).first << " is part of common edge of following 2D cells ids : ";
423 std::copy((*it).second.begin(),(*it).second.end(),std::ostream_iterator<int>(oss," "));
429 else if(srcMeshDim==1 && trgMeshDim==2 && srcSpaceDim==2)
431 if(getIntersectionType()==INTERP_KERNEL::PointLocator)
433 MEDCouplingNormalizedUnstructuredMesh<2,2> source_mesh_wrapper(src_mesh);
434 MEDCouplingNormalizedUnstructuredMesh<2,2> target_mesh_wrapper(target_mesh);
435 INTERP_KERNEL::Interpolation2D interpolation(*this);
436 std::vector<std::map<int,double> > matrixTmp;
437 std::string revMethod(BuildMethodFrom(trgMeth,srcMeth));
438 nbCols=interpolation.interpolateMeshes(target_mesh_wrapper,source_mesh_wrapper,matrixTmp,revMethod);
439 ReverseMatrix(matrixTmp,nbCols,_matrix);
440 nbCols=matrixTmp.size();
444 MEDCouplingNormalizedUnstructuredMesh<2,2> source_mesh_wrapper(src_mesh);
445 MEDCouplingNormalizedUnstructuredMesh<2,2> target_mesh_wrapper(target_mesh);
446 INTERP_KERNEL::Interpolation2D1D interpolation(*this);
447 nbCols=interpolation.interpolateMeshes(source_mesh_wrapper,target_mesh_wrapper,_matrix,method);
448 INTERP_KERNEL::Interpolation2D1D::DuplicateFacesType duplicateFaces=interpolation.retrieveDuplicateFaces();
449 if(!duplicateFaces.empty())
451 std::ostringstream oss; oss << "An unexpected situation happend ! For the following 1D Cells are part of edges shared by 2D cells :\n";
452 for(std::map<int,std::set<int> >::const_iterator it=duplicateFaces.begin();it!=duplicateFaces.end();it++)
454 oss << "1D Cell #" << (*it).first << " is part of common edge of following 2D cells ids : ";
455 std::copy((*it).second.begin(),(*it).second.end(),std::ostream_iterator<int>(oss," "));
461 else if(srcMeshDim==2 && trgMeshDim==3 && srcSpaceDim==3)
463 MEDCouplingNormalizedUnstructuredMesh<3,3> source_mesh_wrapper(src_mesh);
464 MEDCouplingNormalizedUnstructuredMesh<3,3> target_mesh_wrapper(target_mesh);
465 INTERP_KERNEL::Interpolation3D2D interpolation(*this);
466 nbCols=interpolation.interpolateMeshes(source_mesh_wrapper,target_mesh_wrapper,_matrix,method);
467 INTERP_KERNEL::Interpolation3D2D::DuplicateFacesType duplicateFaces=interpolation.retrieveDuplicateFaces();
468 if(!duplicateFaces.empty())
470 std::ostringstream oss; oss << "An unexpected situation happend ! For the following 2D Cells are part of edges shared by 3D cells :\n";
471 for(std::map<int,std::set<int> >::const_iterator it=duplicateFaces.begin();it!=duplicateFaces.end();it++)
473 oss << "2D Cell #" << (*it).first << " is part of common face of following 3D cells ids : ";
474 std::copy((*it).second.begin(),(*it).second.end(),std::ostream_iterator<int>(oss," "));
479 else if(srcMeshDim==3 && trgMeshDim==2 && srcSpaceDim==3)
481 MEDCouplingNormalizedUnstructuredMesh<3,3> source_mesh_wrapper(src_mesh);
482 MEDCouplingNormalizedUnstructuredMesh<3,3> target_mesh_wrapper(target_mesh);
483 INTERP_KERNEL::Interpolation3D2D interpolation(*this);
484 std::vector<std::map<int,double> > matrixTmp;
485 std::string revMethod(BuildMethodFrom(trgMeth,srcMeth));
486 nbCols=interpolation.interpolateMeshes(target_mesh_wrapper,source_mesh_wrapper,matrixTmp,revMethod);
487 ReverseMatrix(matrixTmp,nbCols,_matrix);
488 nbCols=matrixTmp.size();
489 INTERP_KERNEL::Interpolation3D2D::DuplicateFacesType duplicateFaces=interpolation.retrieveDuplicateFaces();
490 if(!duplicateFaces.empty())
492 std::ostringstream oss; oss << "An unexpected situation happend ! For the following 2D Cells are part of edges shared by 3D cells :\n";
493 for(std::map<int,std::set<int> >::const_iterator it=duplicateFaces.begin();it!=duplicateFaces.end();it++)
495 oss << "2D Cell #" << (*it).first << " is part of common face of following 3D cells ids : ";
496 std::copy((*it).second.begin(),(*it).second.end(),std::ostream_iterator<int>(oss," "));
501 else if(trgMeshDim==-1)
503 if(srcMeshDim==2 && srcSpaceDim==2)
505 MEDCouplingNormalizedUnstructuredMesh<2,2> source_mesh_wrapper(src_mesh);
506 INTERP_KERNEL::Interpolation2D interpolation(*this);
507 nbCols=interpolation.toIntegralUniform(source_mesh_wrapper,_matrix,srcMeth);
509 else if(srcMeshDim==3 && srcSpaceDim==3)
511 MEDCouplingNormalizedUnstructuredMesh<3,3> source_mesh_wrapper(src_mesh);
512 INTERP_KERNEL::Interpolation3D interpolation(*this);
513 nbCols=interpolation.toIntegralUniform(source_mesh_wrapper,_matrix,srcMeth);
515 else if(srcMeshDim==2 && srcSpaceDim==3)
517 MEDCouplingNormalizedUnstructuredMesh<3,2> source_mesh_wrapper(src_mesh);
518 INTERP_KERNEL::Interpolation3DSurf interpolation(*this);
519 nbCols=interpolation.toIntegralUniform(source_mesh_wrapper,_matrix,srcMeth);
522 throw INTERP_KERNEL::Exception("No interpolation available for the given mesh and space dimension of source mesh to -1D targetMesh");
524 else if(srcMeshDim==-1)
526 if(trgMeshDim==2 && trgSpaceDim==2)
528 MEDCouplingNormalizedUnstructuredMesh<2,2> source_mesh_wrapper(target_mesh);
529 INTERP_KERNEL::Interpolation2D interpolation(*this);
530 nbCols=interpolation.fromIntegralUniform(source_mesh_wrapper,_matrix,trgMeth);
532 else if(trgMeshDim==3 && trgSpaceDim==3)
534 MEDCouplingNormalizedUnstructuredMesh<3,3> source_mesh_wrapper(target_mesh);
535 INTERP_KERNEL::Interpolation3D interpolation(*this);
536 nbCols=interpolation.fromIntegralUniform(source_mesh_wrapper,_matrix,trgMeth);
538 else if(trgMeshDim==2 && trgSpaceDim==3)
540 MEDCouplingNormalizedUnstructuredMesh<3,2> source_mesh_wrapper(target_mesh);
541 INTERP_KERNEL::Interpolation3DSurf interpolation(*this);
542 nbCols=interpolation.fromIntegralUniform(source_mesh_wrapper,_matrix,trgMeth);
545 throw INTERP_KERNEL::Exception("No interpolation available for the given mesh and space dimension of source mesh from -1D sourceMesh");
548 throw INTERP_KERNEL::Exception("No interpolation available for the given mesh and space dimension");
549 _deno_multiply.clear();
550 _deno_multiply.resize(_matrix.size());
551 _deno_reverse_multiply.clear();
552 _deno_reverse_multiply.resize(nbCols);
557 int MEDCouplingRemapper::prepareInterpKernelOnlyEE()
559 std::string srcMeth,trgMeth;
560 std::string methC=checkAndGiveInterpolationMethodStr(srcMeth,trgMeth);
561 const MEDCouplingExtrudedMesh *src_mesh=static_cast<const MEDCouplingExtrudedMesh *>(_src_ft->getMesh());
562 const MEDCouplingExtrudedMesh *target_mesh=static_cast<const MEDCouplingExtrudedMesh *>(_target_ft->getMesh());
564 throw INTERP_KERNEL::Exception("MEDCouplingRemapper::prepareInterpKernelOnlyEE : Only P0P0 method implemented for Extruded/Extruded meshes !");
565 MEDCouplingNormalizedUnstructuredMesh<3,2> source_mesh_wrapper(src_mesh->getMesh2D());
566 MEDCouplingNormalizedUnstructuredMesh<3,2> target_mesh_wrapper(target_mesh->getMesh2D());
567 INTERP_KERNEL::Interpolation3DSurf interpolation2D(*this);
568 std::vector<std::map<int,double> > matrix2D;
569 int nbCols2D=interpolation2D.interpolateMeshes(source_mesh_wrapper,target_mesh_wrapper,matrix2D,methC);
570 MEDCouplingUMesh *s1D,*t1D;
572 MEDCouplingExtrudedMesh::Project1DMeshes(src_mesh->getMesh1D(),target_mesh->getMesh1D(),getPrecision(),s1D,t1D,v);
573 MEDCouplingNormalizedUnstructuredMesh<1,1> s1DWrapper(s1D);
574 MEDCouplingNormalizedUnstructuredMesh<1,1> t1DWrapper(t1D);
575 std::vector<std::map<int,double> > matrix1D;
576 INTERP_KERNEL::Interpolation1D interpolation1D(*this);
577 int nbCols1D=interpolation1D.interpolateMeshes(s1DWrapper,t1DWrapper,matrix1D,methC);
580 buildFinalInterpolationMatrixByConvolution(matrix1D,matrix2D,src_mesh->getMesh3DIds()->getConstPointer(),nbCols2D,nbCols1D,
581 target_mesh->getMesh3DIds()->getConstPointer());
583 _deno_multiply.clear();
584 _deno_multiply.resize(_matrix.size());
585 _deno_reverse_multiply.clear();
586 _deno_reverse_multiply.resize(nbCols2D*nbCols1D);
591 int MEDCouplingRemapper::prepareInterpKernelOnlyUC()
593 std::string srcMeth,trgMeth;
594 std::string methodCpp=checkAndGiveInterpolationMethodStr(srcMeth,trgMeth);
595 if(methodCpp!="P0P0")
596 throw INTERP_KERNEL::Exception("MEDCouplingRemapper::prepareInterpKernelOnlyUC : only P0P0 interpolation supported for the moment !");
597 const MEDCouplingUMesh *src_mesh=static_cast<const MEDCouplingUMesh *>(_src_ft->getMesh());
598 const MEDCouplingCMesh *target_mesh=static_cast<const MEDCouplingCMesh *>(_target_ft->getMesh());
599 const int srcMeshDim=src_mesh->getMeshDimension();
600 const int srcSpceDim=src_mesh->getSpaceDimension();
601 const int trgMeshDim=target_mesh->getMeshDimension();
602 if(srcMeshDim!=srcSpceDim || srcMeshDim!=trgMeshDim)
603 throw INTERP_KERNEL::Exception("MEDCouplingRemapper::prepareInterpKernelOnlyUC : space dim of src unstructured should be equal to mesh dim of src unstructured and should be equal also equal to trg cartesian dimension !");
604 std::vector<std::map<int,double> > res;
609 MEDCouplingNormalizedCartesianMesh<1> targetWrapper(target_mesh);
610 MEDCouplingNormalizedUnstructuredMesh<1,1> sourceWrapper(src_mesh);
611 INTERP_KERNEL::InterpolationCU myInterpolator(*this);
612 myInterpolator.interpolateMeshes(targetWrapper,sourceWrapper,res,"P0P0");
617 MEDCouplingNormalizedCartesianMesh<2> targetWrapper(target_mesh);
618 MEDCouplingNormalizedUnstructuredMesh<2,2> sourceWrapper(src_mesh);
619 INTERP_KERNEL::InterpolationCU myInterpolator(*this);
620 myInterpolator.interpolateMeshes(targetWrapper,sourceWrapper,res,"P0P0");
625 MEDCouplingNormalizedCartesianMesh<3> targetWrapper(target_mesh);
626 MEDCouplingNormalizedUnstructuredMesh<3,3> sourceWrapper(src_mesh);
627 INTERP_KERNEL::InterpolationCU myInterpolator(*this);
628 myInterpolator.interpolateMeshes(targetWrapper,sourceWrapper,res,"P0P0");
632 throw INTERP_KERNEL::Exception("MEDCouplingRemapper::prepareInterpKernelOnlyUC : only dimension 1 2 or 3 supported !");
634 ReverseMatrix(res,target_mesh->getNumberOfCells(),_matrix);
635 nullifiedTinyCoeffInCrudeMatrixAbs(0.);
637 _deno_multiply.clear();
638 _deno_multiply.resize(_matrix.size());
639 _deno_reverse_multiply.clear();
640 _deno_reverse_multiply.resize(src_mesh->getNumberOfCells());
645 int MEDCouplingRemapper::prepareInterpKernelOnlyCU()
647 std::string srcMeth,trgMeth;
648 std::string methodCpp=checkAndGiveInterpolationMethodStr(srcMeth,trgMeth);
649 if(methodCpp!="P0P0")
650 throw INTERP_KERNEL::Exception("MEDCouplingRemapper::prepareInterpKernelOnlyCU : only P0P0 interpolation supported for the moment !");
651 const MEDCouplingCMesh *src_mesh=static_cast<const MEDCouplingCMesh *>(_src_ft->getMesh());
652 const MEDCouplingUMesh *target_mesh=static_cast<const MEDCouplingUMesh *>(_target_ft->getMesh());
653 const int srcMeshDim=src_mesh->getMeshDimension();
654 const int trgMeshDim=target_mesh->getMeshDimension();
655 const int trgSpceDim=target_mesh->getSpaceDimension();
656 if(trgMeshDim!=trgSpceDim || trgMeshDim!=srcMeshDim)
657 throw INTERP_KERNEL::Exception("MEDCouplingRemapper::prepareInterpKernelOnlyCU : space dim of target unstructured should be equal to mesh dim of target unstructured and should be equal also equal to source cartesian dimension !");
662 MEDCouplingNormalizedCartesianMesh<1> sourceWrapper(src_mesh);
663 MEDCouplingNormalizedUnstructuredMesh<1,1> targetWrapper(target_mesh);
664 INTERP_KERNEL::InterpolationCU myInterpolator(*this);
665 myInterpolator.interpolateMeshes(sourceWrapper,targetWrapper,_matrix,"P0P0");
670 MEDCouplingNormalizedCartesianMesh<2> sourceWrapper(src_mesh);
671 MEDCouplingNormalizedUnstructuredMesh<2,2> targetWrapper(target_mesh);
672 INTERP_KERNEL::InterpolationCU myInterpolator(*this);
673 myInterpolator.interpolateMeshes(sourceWrapper,targetWrapper,_matrix,"P0P0");
678 MEDCouplingNormalizedCartesianMesh<3> sourceWrapper(src_mesh);
679 MEDCouplingNormalizedUnstructuredMesh<3,3> targetWrapper(target_mesh);
680 INTERP_KERNEL::InterpolationCU myInterpolator(*this);
681 myInterpolator.interpolateMeshes(sourceWrapper,targetWrapper,_matrix,"P0P0");
685 throw INTERP_KERNEL::Exception("MEDCouplingRemapper::prepareInterpKernelOnlyCU : only dimension 1 2 or 3 supported !");
687 nullifiedTinyCoeffInCrudeMatrixAbs(0.);
689 _deno_multiply.clear();
690 _deno_multiply.resize(_matrix.size());
691 _deno_reverse_multiply.clear();
692 _deno_reverse_multiply.resize(src_mesh->getNumberOfCells());
697 int MEDCouplingRemapper::prepareInterpKernelOnlyCC()
699 std::string srcMeth,trgMeth;
700 std::string methodCpp=checkAndGiveInterpolationMethodStr(srcMeth,trgMeth);
701 if(methodCpp!="P0P0")
702 throw INTERP_KERNEL::Exception("MEDCouplingRemapper::prepareInterpKernelOnlyCC : only P0P0 interpolation supported for the moment !");
703 const MEDCouplingCMesh *src_mesh=static_cast<const MEDCouplingCMesh *>(_src_ft->getMesh());
704 const MEDCouplingCMesh *target_mesh=static_cast<const MEDCouplingCMesh *>(_target_ft->getMesh());
705 const int srcMeshDim=src_mesh->getMeshDimension();
706 const int trgMeshDim=target_mesh->getMeshDimension();
707 if(trgMeshDim!=srcMeshDim)
708 throw INTERP_KERNEL::Exception("MEDCouplingRemapper::prepareInterpKernelOnlyCC : dim of target cartesian should be equal to dim of source cartesian dimension !");
713 MEDCouplingNormalizedCartesianMesh<1> sourceWrapper(src_mesh);
714 MEDCouplingNormalizedCartesianMesh<1> targetWrapper(target_mesh);
715 INTERP_KERNEL::InterpolationCC myInterpolator(*this);
716 myInterpolator.interpolateMeshes(sourceWrapper,targetWrapper,_matrix,"P0P0");
721 MEDCouplingNormalizedCartesianMesh<2> sourceWrapper(src_mesh);
722 MEDCouplingNormalizedCartesianMesh<2> targetWrapper(target_mesh);
723 INTERP_KERNEL::InterpolationCC myInterpolator(*this);
724 myInterpolator.interpolateMeshes(sourceWrapper,targetWrapper,_matrix,"P0P0");
729 MEDCouplingNormalizedCartesianMesh<3> sourceWrapper(src_mesh);
730 MEDCouplingNormalizedCartesianMesh<3> targetWrapper(target_mesh);
731 INTERP_KERNEL::InterpolationCC myInterpolator(*this);
732 myInterpolator.interpolateMeshes(sourceWrapper,targetWrapper,_matrix,"P0P0");
736 throw INTERP_KERNEL::Exception("MEDCouplingRemapper::prepareInterpKernelOnlyCC : only dimension 1 2 or 3 supported !");
738 nullifiedTinyCoeffInCrudeMatrixAbs(0.);
740 _deno_multiply.clear();
741 _deno_multiply.resize(_matrix.size());
742 _deno_reverse_multiply.clear();
743 _deno_reverse_multiply.resize(src_mesh->getNumberOfCells());
748 int MEDCouplingRemapper::prepareNotInterpKernelOnlyGaussGauss()
750 if(getIntersectionType()!=INTERP_KERNEL::PointLocator)
751 throw INTERP_KERNEL::Exception("MEDCouplingRemapper::prepareNotInterpKernelOnlyGaussGauss : The intersection type is not supported ! Only PointLocator is supported for Gauss->Gauss interpolation ! Please invoke setIntersectionType(PointLocator) on the MEDCouplingRemapper instance !");
752 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> trgLoc=_target_ft->getLocalizationOfDiscr();
753 const double *trgLocPtr=trgLoc->begin();
754 int trgSpaceDim=trgLoc->getNumberOfComponents();
755 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> srcOffsetArr=_src_ft->getDiscretization()->getOffsetArr(_src_ft->getMesh());
756 if(trgSpaceDim!=_src_ft->getMesh()->getSpaceDimension())
758 std::ostringstream oss; oss << "MEDCouplingRemapper::prepareNotInterpKernelOnlyGaussGauss : space dimensions mismatch between source and target !";
759 oss << " Target discretization localization has dimension " << trgSpaceDim << ", whereas the space dimension of source is equal to ";
760 oss << _src_ft->getMesh()->getSpaceDimension() << " !";
761 throw INTERP_KERNEL::Exception(oss.str().c_str());
763 const int *srcOffsetArrPtr=srcOffsetArr->begin();
764 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> srcLoc=_src_ft->getLocalizationOfDiscr();
765 const double *srcLocPtr=srcLoc->begin();
766 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsArr,eltsIndexArr;
767 int trgNbOfGaussPts=trgLoc->getNumberOfTuples();
768 _matrix.resize(trgNbOfGaussPts);
769 _src_ft->getMesh()->getCellsContainingPoints(trgLoc->begin(),trgNbOfGaussPts,getPrecision(),eltsArr,eltsIndexArr);
770 const int *elts(eltsArr->begin()),*eltsIndex(eltsIndexArr->begin());
771 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nbOfSrcCellsShTrgPts(eltsIndexArr->deltaShiftIndex());
772 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids0=nbOfSrcCellsShTrgPts->getIdsNotEqual(0);
773 for(const int *trgId=ids0->begin();trgId!=ids0->end();trgId++)
775 const double *ptTrg=trgLocPtr+trgSpaceDim*(*trgId);
776 int srcCellId=elts[eltsIndex[*trgId]];
777 double dist=std::numeric_limits<double>::max();
779 for(int srcId=srcOffsetArrPtr[srcCellId];srcId<srcOffsetArrPtr[srcCellId+1];srcId++)
781 const double *ptSrc=srcLocPtr+trgSpaceDim*srcId;
783 for(int i=0;i<trgSpaceDim;i++)
784 tmp+=(ptTrg[i]-ptSrc[i])*(ptTrg[i]-ptSrc[i]);
786 { dist=tmp; srcEntry=srcId; }
788 _matrix[*trgId][srcEntry]=1.;
790 if(ids0->getNumberOfTuples()!=trgNbOfGaussPts)
792 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> orphanTrgIds=nbOfSrcCellsShTrgPts->getIdsEqual(0);
793 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> orphanTrg=trgLoc->selectByTupleId(orphanTrgIds->begin(),orphanTrgIds->end());
794 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> srcIdPerTrg=srcLoc->findClosestTupleId(orphanTrg);
795 const int *srcIdPerTrgPtr=srcIdPerTrg->begin();
796 for(const int *orphanTrgId=orphanTrgIds->begin();orphanTrgId!=orphanTrgIds->end();orphanTrgId++,srcIdPerTrgPtr++)
797 _matrix[*orphanTrgId][*srcIdPerTrgPtr]=2.;
799 _deno_multiply.clear();
800 _deno_multiply.resize(_matrix.size());
801 _deno_reverse_multiply.clear();
802 _deno_reverse_multiply.resize(srcLoc->getNumberOfTuples());
808 * This method checks that the input interpolation \a method is managed by not INTERP_KERNEL only methods.
809 * If no an INTERP_KERNEL::Exception will be thrown. If yes, a magic number will be returned to switch in the MEDCouplingRemapper::prepareNotInterpKernelOnly method.
811 int MEDCouplingRemapper::CheckInterpolationMethodManageableByNotOnlyInterpKernel(const std::string& method)
813 if(method=="GAUSSGAUSS")
815 std::ostringstream oss; oss << "MEDCouplingRemapper::CheckInterpolationMethodManageableByNotOnlyInterpKernel : ";
816 oss << "The method \"" << method << "\" is not manageable by not INTERP_KERNEL only method.";
817 oss << " Not only INTERP_KERNEL methods dealed are : GAUSSGAUSS !";
818 throw INTERP_KERNEL::Exception(oss.str().c_str());
822 * This method determines regarding \c _interp_matrix_pol attribute ( set by MEDCouplingRemapper::setInterpolationMatrixPolicy and by default equal
823 * to IK_ONLY_PREFERED = 0 ) , which method will be applied. If \c true is returned the INTERP_KERNEL only method should be applied to \c false the \b not
824 * only INTERP_KERNEL method should be applied.
826 bool MEDCouplingRemapper::isInterpKernelOnlyOrNotOnly() const
828 std::string srcm,trgm,method;
829 method=checkAndGiveInterpolationMethodStr(srcm,trgm);
830 switch(_interp_matrix_pol)
832 case IK_ONLY_PREFERED:
836 std::string tmp1,tmp2;
837 INTERP_KERNEL::Interpolation<INTERP_KERNEL::Interpolation3D>::CheckAndSplitInterpolationMethod(method,tmp1,tmp2);
840 catch(INTERP_KERNEL::Exception& /*e*/)
845 case NOT_IK_ONLY_PREFERED:
849 CheckInterpolationMethodManageableByNotOnlyInterpKernel(method);
852 catch(INTERP_KERNEL::Exception& /*e*/)
859 case NOT_IK_ONLY_FORCED:
862 throw INTERP_KERNEL::Exception("MEDCouplingRemapper::isInterpKernelOnlyOrNotOnly : internal error ! The interpolation matrix policy is not managed ! Try to change it using MEDCouplingRemapper::setInterpolationMatrixPolicy !");
866 void MEDCouplingRemapper::updateTime() const
870 void MEDCouplingRemapper::checkPrepare() const
872 const MEDCouplingFieldTemplate *s(_src_ft),*t(_target_ft);
874 throw INTERP_KERNEL::Exception("MEDCouplingRemapper::checkPrepare : it appears that MEDCouplingRemapper::prepare(Ex) has not been called !");
875 if(!s->getMesh() || !t->getMesh())
876 throw INTERP_KERNEL::Exception("MEDCouplingRemapper::checkPrepare : it appears that no all field templates have their mesh set !");
880 * This method builds a code considering already set field discretization int \a this : \a _src_ft and \a _target_ft.
881 * This method returns 3 informations (2 in ouput parameters and 1 in return).
883 * \param [out] srcMeth the string code of the discretization of source field template
884 * \param [out] trgMeth the string code of the discretization of target field template
885 * \return the standardized string code (compatible with INTERP_KERNEL) for matrix of numerators (in \a _matrix)
887 std::string MEDCouplingRemapper::checkAndGiveInterpolationMethodStr(std::string& srcMeth, std::string& trgMeth) const
889 const MEDCouplingFieldTemplate *s(_src_ft),*t(_target_ft);
891 throw INTERP_KERNEL::Exception("MEDCouplingRemapper::checkAndGiveInterpolationMethodStr : it appears that no all field templates have been set !");
892 if(!s->getMesh() || !t->getMesh())
893 throw INTERP_KERNEL::Exception("MEDCouplingRemapper::checkAndGiveInterpolationMethodStr : it appears that no all field templates have their mesh set !");
894 srcMeth=_src_ft->getDiscretization()->getRepr();
895 trgMeth=_target_ft->getDiscretization()->getRepr();
896 return BuildMethodFrom(srcMeth,trgMeth);
899 std::string MEDCouplingRemapper::BuildMethodFrom(const std::string& meth1, const std::string& meth2)
901 std::string method(meth1); method+=meth2;
905 void MEDCouplingRemapper::releaseData(bool matrixSuppression)
909 if(matrixSuppression)
912 _deno_multiply.clear();
913 _deno_reverse_multiply.clear();
917 void MEDCouplingRemapper::transferUnderground(const MEDCouplingFieldDouble *srcField, MEDCouplingFieldDouble *targetField, bool isDftVal, double dftValue)
919 if(!srcField || !targetField)
920 throw INTERP_KERNEL::Exception("MEDCouplingRemapper::transferUnderground : srcField or targetField is NULL !");
921 srcField->checkCoherency();
923 if(_src_ft->getDiscretization()->getStringRepr()!=srcField->getDiscretization()->getStringRepr())
924 throw INTERP_KERNEL::Exception("Incoherency with prepare call for source field");
925 if(_target_ft->getDiscretization()->getStringRepr()!=targetField->getDiscretization()->getStringRepr())
926 throw INTERP_KERNEL::Exception("Incoherency with prepare call for target field");
927 if(srcField->getNature()!=targetField->getNature())
928 throw INTERP_KERNEL::Exception("Natures of fields mismatch !");
929 if(srcField->getNumberOfTuplesExpected()!=_src_ft->getNumberOfTuplesExpected())
931 std::ostringstream oss;
932 oss << "MEDCouplingRemapper::transferUnderground : in given source field the number of tuples required is " << _src_ft->getNumberOfTuplesExpected() << " (on prepare) and number of tuples in given source field is " << srcField->getNumberOfTuplesExpected();
933 oss << " ! It appears that the source support is not the same between the prepare and the transfer !";
934 throw INTERP_KERNEL::Exception(oss.str().c_str());
936 DataArrayDouble *array(targetField->getArray());
937 int srcNbOfCompo(srcField->getNumberOfComponents());
940 targetField->checkCoherency();
941 if(srcNbOfCompo!=targetField->getNumberOfComponents())
942 throw INTERP_KERNEL::Exception("Number of components mismatch !");
947 throw INTERP_KERNEL::Exception("MEDCouplingRemapper::partialTransfer : This method requires that the array of target field exists ! Allocate it or call MEDCouplingRemapper::transfer instead !");
948 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp(DataArrayDouble::New());
949 tmp->alloc(targetField->getNumberOfTuples(),srcNbOfCompo);
950 targetField->setArray(tmp);
952 computeDeno(srcField->getNature(),srcField,targetField);
953 double *resPointer(targetField->getArray()->getPointer());
954 const double *inputPointer(srcField->getArray()->getConstPointer());
955 computeProduct(inputPointer,srcNbOfCompo,isDftVal,dftValue,resPointer);
958 void MEDCouplingRemapper::computeDeno(NatureOfField nat, const MEDCouplingFieldDouble *srcField, const MEDCouplingFieldDouble *trgField)
961 return computeDenoFromScratch(nat,srcField,trgField);
962 else if(nat!=_nature_of_deno)
963 return computeDenoFromScratch(nat,srcField,trgField);
964 else if(nat==_nature_of_deno && _time_deno_update!=getTimeOfThis())
965 return computeDenoFromScratch(nat,srcField,trgField);
968 void MEDCouplingRemapper::computeDenoFromScratch(NatureOfField nat, const MEDCouplingFieldDouble *srcField, const MEDCouplingFieldDouble *trgField)
971 _time_deno_update=getTimeOfThis();
972 switch(_nature_of_deno)
974 case ConservativeVolumic:
976 ComputeRowSumAndColSum(_matrix,_deno_multiply,_deno_reverse_multiply);
981 MEDCouplingFieldDouble *deno=srcField->getDiscretization()->getMeasureField(srcField->getMesh(),getMeasureAbsStatus());
982 MEDCouplingFieldDouble *denoR=trgField->getDiscretization()->getMeasureField(trgField->getMesh(),getMeasureAbsStatus());
983 const double *denoPtr=deno->getArray()->getConstPointer();
984 const double *denoRPtr=denoR->getArray()->getConstPointer();
985 if(trgField->getMesh()->getMeshDimension()==-1)
987 double *denoRPtr2=denoR->getArray()->getPointer();
988 denoRPtr2[0]=std::accumulate(denoPtr,denoPtr+deno->getNumberOfTuples(),0.);
990 if(srcField->getMesh()->getMeshDimension()==-1)
992 double *denoPtr2=deno->getArray()->getPointer();
993 denoPtr2[0]=std::accumulate(denoRPtr,denoRPtr+denoR->getNumberOfTuples(),0.);
996 for(std::vector<std::map<int,double> >::const_iterator iter1=_matrix.begin();iter1!=_matrix.end();iter1++,idx++)
997 for(std::map<int,double>::const_iterator iter2=(*iter1).begin();iter2!=(*iter1).end();iter2++)
999 _deno_multiply[idx][(*iter2).first]=denoPtr[(*iter2).first];
1000 _deno_reverse_multiply[(*iter2).first][idx]=denoRPtr[idx];
1006 case IntegralGlobConstraint:
1008 ComputeColSumAndRowSum(_matrix,_deno_multiply,_deno_reverse_multiply);
1013 MEDCouplingFieldDouble *deno=trgField->getDiscretization()->getMeasureField(trgField->getMesh(),getMeasureAbsStatus());
1014 MEDCouplingFieldDouble *denoR=srcField->getDiscretization()->getMeasureField(srcField->getMesh(),getMeasureAbsStatus());
1015 const double *denoPtr=deno->getArray()->getConstPointer();
1016 const double *denoRPtr=denoR->getArray()->getConstPointer();
1017 if(trgField->getMesh()->getMeshDimension()==-1)
1019 double *denoRPtr2=denoR->getArray()->getPointer();
1020 denoRPtr2[0]=std::accumulate(denoPtr,denoPtr+deno->getNumberOfTuples(),0.);
1022 if(srcField->getMesh()->getMeshDimension()==-1)
1024 double *denoPtr2=deno->getArray()->getPointer();
1025 denoPtr2[0]=std::accumulate(denoRPtr,denoRPtr+denoR->getNumberOfTuples(),0.);
1028 for(std::vector<std::map<int,double> >::const_iterator iter1=_matrix.begin();iter1!=_matrix.end();iter1++,idx++)
1029 for(std::map<int,double>::const_iterator iter2=(*iter1).begin();iter2!=(*iter1).end();iter2++)
1031 _deno_multiply[idx][(*iter2).first]=denoPtr[idx];
1032 _deno_reverse_multiply[(*iter2).first][idx]=denoRPtr[(*iter2).first];
1039 throw INTERP_KERNEL::Exception("No nature specified ! Select one !");
1043 void MEDCouplingRemapper::computeProduct(const double *inputPointer, int inputNbOfCompo, bool isDftVal, double dftValue, double *resPointer)
1046 double *tmp=new double[inputNbOfCompo];
1047 for(std::vector<std::map<int,double> >::const_iterator iter1=_matrix.begin();iter1!=_matrix.end();iter1++,idx++)
1049 if((*iter1).empty())
1052 std::fill(resPointer+idx*inputNbOfCompo,resPointer+(idx+1)*inputNbOfCompo,dftValue);
1056 std::fill(resPointer+idx*inputNbOfCompo,resPointer+(idx+1)*inputNbOfCompo,0.);
1057 std::map<int,double>::const_iterator iter3=_deno_multiply[idx].begin();
1058 for(std::map<int,double>::const_iterator iter2=(*iter1).begin();iter2!=(*iter1).end();iter2++,iter3++)
1060 std::transform(inputPointer+(*iter2).first*inputNbOfCompo,inputPointer+((*iter2).first+1)*inputNbOfCompo,tmp,std::bind2nd(std::multiplies<double>(),(*iter2).second/(*iter3).second));
1061 std::transform(tmp,tmp+inputNbOfCompo,resPointer+idx*inputNbOfCompo,resPointer+idx*inputNbOfCompo,std::plus<double>());
1067 void MEDCouplingRemapper::computeReverseProduct(const double *inputPointer, int inputNbOfCompo, double dftValue, double *resPointer)
1069 std::vector<bool> isReached(_deno_reverse_multiply.size(),false);
1071 double *tmp=new double[inputNbOfCompo];
1072 std::fill(resPointer,resPointer+inputNbOfCompo*_deno_reverse_multiply.size(),0.);
1073 for(std::vector<std::map<int,double> >::const_iterator iter1=_matrix.begin();iter1!=_matrix.end();iter1++,idx++)
1075 for(std::map<int,double>::const_iterator iter2=(*iter1).begin();iter2!=(*iter1).end();iter2++)
1077 isReached[(*iter2).first]=true;
1078 std::transform(inputPointer+idx*inputNbOfCompo,inputPointer+(idx+1)*inputNbOfCompo,tmp,std::bind2nd(std::multiplies<double>(),(*iter2).second/_deno_reverse_multiply[(*iter2).first][idx]));
1079 std::transform(tmp,tmp+inputNbOfCompo,resPointer+((*iter2).first)*inputNbOfCompo,resPointer+((*iter2).first)*inputNbOfCompo,std::plus<double>());
1084 for(std::vector<bool>::const_iterator iter3=isReached.begin();iter3!=isReached.end();iter3++,idx++)
1086 std::fill(resPointer+idx*inputNbOfCompo,resPointer+(idx+1)*inputNbOfCompo,dftValue);
1089 void MEDCouplingRemapper::ReverseMatrix(const std::vector<std::map<int,double> >& matIn, int nbColsMatIn, std::vector<std::map<int,double> >& matOut)
1091 matOut.resize(nbColsMatIn);
1093 for(std::vector<std::map<int,double> >::const_iterator iter1=matIn.begin();iter1!=matIn.end();iter1++,id++)
1094 for(std::map<int,double>::const_iterator iter2=(*iter1).begin();iter2!=(*iter1).end();iter2++)
1095 matOut[(*iter2).first][id]=(*iter2).second;
1098 void MEDCouplingRemapper::ComputeRowSumAndColSum(const std::vector<std::map<int,double> >& matrixDeno,
1099 std::vector<std::map<int,double> >& deno, std::vector<std::map<int,double> >& denoReverse)
1101 std::map<int,double> values;
1103 for(std::vector<std::map<int,double> >::const_iterator iter1=matrixDeno.begin();iter1!=matrixDeno.end();iter1++,idx++)
1106 for(std::map<int,double>::const_iterator iter2=(*iter1).begin();iter2!=(*iter1).end();iter2++)
1108 sum+=(*iter2).second;
1109 values[(*iter2).first]+=(*iter2).second;
1111 for(std::map<int,double>::const_iterator iter2=(*iter1).begin();iter2!=(*iter1).end();iter2++)
1112 deno[idx][(*iter2).first]=sum;
1115 for(std::vector<std::map<int,double> >::const_iterator iter1=matrixDeno.begin();iter1!=matrixDeno.end();iter1++,idx++)
1117 for(std::map<int,double>::const_iterator iter2=(*iter1).begin();iter2!=(*iter1).end();iter2++)
1118 denoReverse[(*iter2).first][idx]=values[(*iter2).first];
1122 void MEDCouplingRemapper::ComputeColSumAndRowSum(const std::vector<std::map<int,double> >& matrixDeno,
1123 std::vector<std::map<int,double> >& deno, std::vector<std::map<int,double> >& denoReverse)
1125 std::map<int,double> values;
1127 for(std::vector<std::map<int,double> >::const_iterator iter1=matrixDeno.begin();iter1!=matrixDeno.end();iter1++,idx++)
1130 for(std::map<int,double>::const_iterator iter2=(*iter1).begin();iter2!=(*iter1).end();iter2++)
1132 sum+=(*iter2).second;
1133 values[(*iter2).first]+=(*iter2).second;
1135 for(std::map<int,double>::const_iterator iter2=(*iter1).begin();iter2!=(*iter1).end();iter2++)
1136 denoReverse[(*iter2).first][idx]=sum;
1139 for(std::vector<std::map<int,double> >::const_iterator iter1=matrixDeno.begin();iter1!=matrixDeno.end();iter1++,idx++)
1141 for(std::map<int,double>::const_iterator iter2=(*iter1).begin();iter2!=(*iter1).end();iter2++)
1142 deno[idx][(*iter2).first]=values[(*iter2).first];
1146 void MEDCouplingRemapper::buildFinalInterpolationMatrixByConvolution(const std::vector< std::map<int,double> >& m1D,
1147 const std::vector< std::map<int,double> >& m2D,
1148 const int *corrCellIdSrc, int nbOf2DCellsSrc, int nbOf1DCellsSrc,
1149 const int *corrCellIdTrg)
1151 int nbOf2DCellsTrg=m2D.size();
1152 int nbOf1DCellsTrg=m1D.size();
1153 int nbOf3DCellsTrg=nbOf2DCellsTrg*nbOf1DCellsTrg;
1154 _matrix.resize(nbOf3DCellsTrg);
1156 for(std::vector< std::map<int,double> >::const_iterator iter2R=m2D.begin();iter2R!=m2D.end();iter2R++,id2R++)
1158 for(std::map<int,double>::const_iterator iter2C=(*iter2R).begin();iter2C!=(*iter2R).end();iter2C++)
1161 for(std::vector< std::map<int,double> >::const_iterator iter1R=m1D.begin();iter1R!=m1D.end();iter1R++,id1R++)
1163 for(std::map<int,double>::const_iterator iter1C=(*iter1R).begin();iter1C!=(*iter1R).end();iter1C++)
1165 _matrix[corrCellIdTrg[id1R*nbOf2DCellsTrg+id2R]][corrCellIdSrc[(*iter1C).first*nbOf2DCellsSrc+(*iter2C).first]]=(*iter1C).second*((*iter2C).second);
1172 void MEDCouplingRemapper::PrintMatrix(const std::vector<std::map<int,double> >& m)
1175 for(std::vector<std::map<int,double> >::const_iterator iter1=m.begin();iter1!=m.end();iter1++,id++)
1177 std::cout << "Target Cell # " << id << " : ";
1178 for(std::map<int,double>::const_iterator iter2=(*iter1).begin();iter2!=(*iter1).end();iter2++)
1179 std::cout << "(" << (*iter2).first << "," << (*iter2).second << "), ";
1180 std::cout << std::endl;
1184 const std::vector<std::map<int,double> >& MEDCouplingRemapper::getCrudeMatrix() const
1190 * Returns the number of columns of matrix returned by MEDCouplingRemapper::getCrudeMatrix method.
1192 int MEDCouplingRemapper::getNumberOfColsOfMatrix() const
1194 return (int)_deno_reverse_multiply.size();
1198 * This method is supposed to be called , if needed, right after MEDCouplingRemapper::prepare or MEDCouplingRemapper::prepareEx.
1199 * If not the behaviour is unpredictable.
1200 * This method works on precomputed \a this->_matrix. All coefficients in the matrix is lower than \a maxValAbs this coefficient is
1201 * set to 0. That is to say that its entry disappear from the map storing the corresponding row in the data storage of sparse crude matrix.
1202 * This method is useful to correct at a high level some problems linked to precision. Indeed, with some \ref NatureOfField "natures of field" some threshold effect
1205 * \param [in] maxValAbs is a limit behind which a coefficient is set to 0. \a maxValAbs is expected to be positive, if not this method do nothing.
1206 * \return a positive value that tells the number of coefficients put to 0. The 0 returned value means that the matrix has remained unchanged.
1207 * \sa MEDCouplingRemapper::nullifiedTinyCoeffInCrudeMatrix
1209 int MEDCouplingRemapper::nullifiedTinyCoeffInCrudeMatrixAbs(double maxValAbs)
1212 std::vector<std::map<int,double> > matrixNew(_matrix.size());
1214 for(std::vector<std::map<int,double> >::const_iterator it1=_matrix.begin();it1!=_matrix.end();it1++,i++)
1216 std::map<int,double>& rowNew=matrixNew[i];
1217 for(std::map<int,double>::const_iterator it2=(*it1).begin();it2!=(*it1).end();it2++)
1219 if(fabs((*it2).second)>maxValAbs)
1220 rowNew[(*it2).first]=(*it2).second;
1231 * This method is supposed to be called , if needed, right after MEDCouplingRemapper::prepare or MEDCouplingRemapper::prepareEx.
1232 * If not the behaviour is unpredictable.
1233 * This method works on precomputed \a this->_matrix. All coefficients in the matrix is lower than delta multiplied by \a scaleFactor this coefficient is
1234 * set to 0. That is to say that its entry disappear from the map storing the corresponding row in the data storage of sparse crude matrix.
1235 * delta is the value returned by MEDCouplingRemapper::getMaxValueInCrudeMatrix method.
1236 * This method is useful to correct at a high level some problems linked to precision. Indeed, with some \ref NatureOfField "natures of field" some threshold effect
1239 * \param [in] scaleFactor is the scale factor from which coefficients lower than \a scaleFactor times range width of coefficients are set to zero.
1240 * \return a positive value that tells the number of coefficients put to 0. The 0 returned value means that the matrix has remained unchanged. If -1 is returned it means
1241 * that all coefficients are null.
1242 * \sa MEDCouplingRemapper::nullifiedTinyCoeffInCrudeMatrixAbs
1244 int MEDCouplingRemapper::nullifiedTinyCoeffInCrudeMatrix(double scaleFactor)
1246 double maxVal=getMaxValueInCrudeMatrix();
1249 return nullifiedTinyCoeffInCrudeMatrixAbs(scaleFactor*maxVal);
1253 * This method is supposed to be called , if needed, right after MEDCouplingRemapper::prepare or MEDCouplingRemapper::prepareEx.
1254 * If not the behaviour is unpredictable.
1255 * This method returns the maximum of the absolute values of coefficients into the sparse crude matrix.
1256 * The returned value is positive.
1258 double MEDCouplingRemapper::getMaxValueInCrudeMatrix() const
1261 for(std::vector<std::map<int,double> >::const_iterator it1=_matrix.begin();it1!=_matrix.end();it1++)
1262 for(std::map<int,double>::const_iterator it2=(*it1).begin();it2!=(*it1).end();it2++)
1263 if(fabs((*it2).second)>ret)
1264 ret=fabs((*it2).second);