Salome HOME
[EDF26877] : management of computation of measure field on field on Gauss Point in...
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingRemapper.cxx
index 884132a50e75cc8657794124104d50fc2ebfeebd..231f29bba6d4906dd59c30e3a39c842bf4e1c5f8 100755 (executable)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2019  CEA/DEN, EDF R&D
+// Copyright (C) 2007-2022  CEA/DEN, EDF R&D
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
@@ -27,6 +27,7 @@
 #include "MEDCouplingCMesh.hxx"
 #include "MEDCouplingNormalizedUnstructuredMesh.txx"
 #include "MEDCouplingNormalizedCartesianMesh.txx"
+#include "MEDCouplingFieldDiscretizationOnNodesFE.hxx"
 
 #include "Interpolation1D.txx"
 #include "Interpolation2DCurve.hxx"
@@ -123,10 +124,7 @@ void MEDCouplingRemapper::setCrudeMatrixEx(const MEDCouplingFieldTemplate *src,
         }
     }
   _matrix=m;
-  _deno_multiply.clear();
-  _deno_multiply.resize(_matrix.size());
-  _deno_reverse_multiply.clear();
-  _deno_reverse_multiply.resize(srcNbElem);
+  synchronizeSizeOfSideMatricesAfterMatrixComputation(srcNbElem);
 }
 
 int MEDCouplingRemapper::prepareInterpKernelOnly()
@@ -181,6 +179,8 @@ int MEDCouplingRemapper::prepareNotInterpKernelOnly()
   {
     case 0:
       return prepareNotInterpKernelOnlyGaussGauss();
+    case 1:
+      return prepareNotInterpKernelOnlyFEFE();
     default:
       {
         std::ostringstream oss; oss << "MEDCouplingRemapper::prepareNotInterpKernelOnly : INTERNAL ERROR ! the method \"" << method << "\" declared as managed bu not implemented !";
@@ -194,7 +194,7 @@ int MEDCouplingRemapper::prepareNotInterpKernelOnly()
  * If meshes of \b srcField and \b targetField do not match exactly those given into \ref MEDCoupling::MEDCouplingRemapper::prepare "prepare method" an exception will be thrown.
  * 
  * \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 MEDCoupling::MEDCouplingRemapper::prepare.
- * \param [in/out] targetField the destination field with the allocated array in which all tuples will be overwritten.
+ * \param [in,out] targetField the destination field with the allocated array in which all tuples will be overwritten.
  * \param [in] dftValue is the value that will be assigned in the targetField to each entity of target mesh (entity depending on the method selected on prepare invocation) that is not intercepted by any entity of source mesh.
  *             For example in "P0P0" case (cell-cell) if a cell in target mesh is not overlapped by any source cell the \a dftValue value will be attached on that cell in the returned \a targetField. In some cases a target
  *             cell not intercepted by any source cell is a bug so in this case it is advised to set a huge value (1e300 for example) to \a dftValue to quickly point to the problem. But for users doing parallelism a target cell can
@@ -249,7 +249,7 @@ void MEDCouplingRemapper::reverseTransfer(MEDCouplingFieldDouble *srcField, cons
   if(array)
     {
       srcField->checkConsistencyLight();
-      if(ToIdType(trgNbOfCompo)!=srcField->getNumberOfTuplesExpected())
+      if(trgNbOfCompo != srcField->getNumberOfComponents())
         throw INTERP_KERNEL::Exception("Number of components mismatch !");
     }
   else
@@ -427,6 +427,24 @@ int MEDCouplingRemapper::prepareInterpKernelOnlyUU()
       INTERP_KERNEL::Interpolation1D interpolation(*this);
       nbCols=interpolation.interpolateMeshes(source_mesh_wrapper,target_mesh_wrapper,_matrix,method);
     }
+  else if(srcMeshDim==1 && trgMeshDim==0 && srcSpaceDim==1 )
+    {
+      if(getIntersectionType()!=INTERP_KERNEL::PointLocator)
+        throw INTERP_KERNEL::Exception("Invalid interpolation requested between 1D and 0D into 1D space ! Select PointLocator as intersection type !");
+      MEDCouplingNormalizedUnstructuredMesh<1,1> source_mesh_wrapper(src_mesh);
+      MEDCouplingNormalizedUnstructuredMesh<1,1> target_mesh_wrapper(target_mesh);
+      INTERP_KERNEL::Interpolation1D interpolation(*this);
+      nbCols=interpolation.interpolateMeshes0D(source_mesh_wrapper,target_mesh_wrapper,_matrix,method);
+    }
+  else if(srcMeshDim==1 && trgMeshDim==0 && srcSpaceDim==2 )
+    {
+      if(getIntersectionType()!=INTERP_KERNEL::PointLocator)
+        throw INTERP_KERNEL::Exception("Invalid interpolation requested between 1D and 0D into 2D space ! Select PointLocator as intersection type !");
+      MEDCouplingNormalizedUnstructuredMesh<2,1> source_mesh_wrapper(src_mesh);
+      MEDCouplingNormalizedUnstructuredMesh<2,1> target_mesh_wrapper(target_mesh);
+      INTERP_KERNEL::Interpolation1D interpolation(*this);
+      nbCols=interpolation.interpolateMeshes0D(source_mesh_wrapper,target_mesh_wrapper,_matrix,method);
+    }
   else if(srcMeshDim==1 && trgMeshDim==1 && srcSpaceDim==2)
     {
       MEDCouplingNormalizedUnstructuredMesh<2,1> source_mesh_wrapper(src_mesh);
@@ -671,11 +689,7 @@ int MEDCouplingRemapper::prepareInterpKernelOnlyUU()
     }
   else
     throw INTERP_KERNEL::Exception("No interpolation available for the given mesh and space dimension");
-  _deno_multiply.clear();
-  _deno_multiply.resize(_matrix.size());
-  _deno_reverse_multiply.clear();
-  _deno_reverse_multiply.resize(nbCols);
-  declareAsNew();
+  synchronizeSizeOfSideMatricesAfterMatrixComputation(nbCols);
   return 1;
 }
 
@@ -703,17 +717,13 @@ int MEDCouplingRemapper::prepareInterpKernelOnlyEE()
   INTERP_KERNEL::Interpolation1D interpolation1D(*this);
   if(interpolation1D.getIntersectionType()==INTERP_KERNEL::Geometric2D)// For intersection type of 1D, Geometric2D do not deal with it ! -> make interpolation1D not inherite from this
     interpolation1D.setIntersectionType(INTERP_KERNEL::Triangulation);//
-  mcIdType nbCols1D=interpolation1D.interpolateMeshes(s1DWrapper,t1DWrapper,matrix1D,methC);
+    mcIdType nbCols1D=interpolation1D.interpolateMeshes(s1DWrapper,t1DWrapper,matrix1D,methC);
   s1D->decrRef();
   t1D->decrRef();
   buildFinalInterpolationMatrixByConvolution(matrix1D,matrix2D,src_mesh->getMesh3DIds()->getConstPointer(),nbCols2D,nbCols1D,
                                              target_mesh->getMesh3DIds()->getConstPointer());
   //
-  _deno_multiply.clear();
-  _deno_multiply.resize(_matrix.size());
-  _deno_reverse_multiply.clear();
-  _deno_reverse_multiply.resize(nbCols2D*nbCols1D);
-  declareAsNew();
+  synchronizeSizeOfSideMatricesAfterMatrixComputation(nbCols2D*nbCols1D);
   return 1;
 }
 
@@ -765,11 +775,7 @@ int MEDCouplingRemapper::prepareInterpKernelOnlyUC()
   ReverseMatrix(res,target_mesh->getNumberOfCells(),_matrix);
   nullifiedTinyCoeffInCrudeMatrixAbs(0.);
   //
-  _deno_multiply.clear();
-  _deno_multiply.resize(_matrix.size());
-  _deno_reverse_multiply.clear();
-  _deno_reverse_multiply.resize(src_mesh->getNumberOfCells());
-  declareAsNew();
+  synchronizeSizeOfSideMatricesAfterMatrixComputation(src_mesh->getNumberOfCells());
   return 1;
 }
 
@@ -819,11 +825,7 @@ int MEDCouplingRemapper::prepareInterpKernelOnlyCU()
   }
   nullifiedTinyCoeffInCrudeMatrixAbs(0.);
   //
-  _deno_multiply.clear();
-  _deno_multiply.resize(_matrix.size());
-  _deno_reverse_multiply.clear();
-  _deno_reverse_multiply.resize(src_mesh->getNumberOfCells());
-  declareAsNew();
+  synchronizeSizeOfSideMatricesAfterMatrixComputation(src_mesh->getNumberOfCells());
   return 1;
 }
 
@@ -872,11 +874,7 @@ int MEDCouplingRemapper::prepareInterpKernelOnlyCC()
   }
   nullifiedTinyCoeffInCrudeMatrixAbs(0.);
   //
-  _deno_multiply.clear();
-  _deno_multiply.resize(_matrix.size());
-  _deno_reverse_multiply.clear();
-  _deno_reverse_multiply.resize(src_mesh->getNumberOfCells());
-  declareAsNew();
+  synchronizeSizeOfSideMatricesAfterMatrixComputation(src_mesh->getNumberOfCells());
   return 1;
 }
 
@@ -931,11 +929,43 @@ int MEDCouplingRemapper::prepareNotInterpKernelOnlyGaussGauss()
       for(const mcIdType *orphanTrgId=orphanTrgIds->begin();orphanTrgId!=orphanTrgIds->end();orphanTrgId++,srcIdPerTrgPtr++)
         _matrix[*orphanTrgId][*srcIdPerTrgPtr]=2.;
     }
-  _deno_multiply.clear();
-  _deno_multiply.resize(_matrix.size());
-  _deno_reverse_multiply.clear();
-  _deno_reverse_multiply.resize(srcLoc->getNumberOfTuples());
-  declareAsNew();
+  synchronizeSizeOfSideMatricesAfterMatrixComputation( srcLoc->getNumberOfTuples() );
+  return 1;
+}
+
+int MEDCouplingRemapper::prepareNotInterpKernelOnlyFEFE()
+{
+  if(getIntersectionType()!=INTERP_KERNEL::PointLocator)
+    throw INTERP_KERNEL::Exception("MEDCouplingRemapper::prepareNotInterpKernelOnlyFEFE : The intersection type is not supported ! Only PointLocator is supported for FE->FE interpolation ! Please invoke setIntersectionType(PointLocator) on the MEDCouplingRemapper instance !");
+  MCAuto<DataArrayDouble> trgLoc=_target_ft->getLocalizationOfDiscr();
+  mcIdType trgSpaceDim=ToIdType(trgLoc->getNumberOfComponents());
+  if(trgSpaceDim!=3)
+    THROW_IK_EXCEPTION("prepareNotInterpKernelOnlyFEFE : only spacedim 3 supported for target !")
+  if(_src_ft->getMesh()->getSpaceDimension() != 3)
+    THROW_IK_EXCEPTION("prepareNotInterpKernelOnlyFEFE : only spacedim 3 supported for source !")
+  const MEDCouplingUMesh *srcUMesh( dynamic_cast<const MEDCouplingUMesh *>(_src_ft->getMesh()) );
+  const MEDCouplingPointSet *trgMesh( dynamic_cast<const MEDCouplingPointSet *>(_target_ft->getMesh()) );
+  if( !srcUMesh )
+    THROW_IK_EXCEPTION("prepareNotInterpKernelOnlyFEFE : only 3D UMesh supported as source !");
+  if( !trgMesh )
+    THROW_IK_EXCEPTION("prepareNotInterpKernelOnlyFEFE : only 3D PointSet mesh supported as target !");
+
+  _matrix.clear();
+  _matrix.resize(trgMesh->getNumberOfNodes());
+  mcIdType rowId(0);
+
+  auto matrixFeeder = [this,&rowId](const MEDCouplingGaussLocalization& gl, const std::vector<mcIdType>& conn)
+  {
+    auto& row = this->_matrix[rowId++];
+    MCAuto<DataArrayDouble> resVector( gl.getShapeFunctionValues() );
+    for(int iPt = 0 ; iPt < gl.getNumberOfPtsInRefCell(); ++iPt)
+    {
+      row[ conn[iPt] ] = resVector->getIJ(0,iPt);
+    }
+  };
+
+  MEDCouplingFieldDiscretizationOnNodesFE::GetRefCoordOfListOf3DPtsIn3D(srcUMesh,trgMesh->getCoords()->begin(),trgMesh->getNumberOfNodes(),matrixFeeder);
+  synchronizeSizeOfSideMatricesAfterMatrixComputation( srcUMesh->getNumberOfNodes() );
   return 1;
 }
 
@@ -947,9 +977,11 @@ int MEDCouplingRemapper::CheckInterpolationMethodManageableByNotOnlyInterpKernel
 {
   if(method=="GAUSSGAUSS")
     return 0;
+  if(method=="FEFE")
+    return 1;
   std::ostringstream oss; oss << "MEDCouplingRemapper::CheckInterpolationMethodManageableByNotOnlyInterpKernel : ";
   oss << "The method \"" << method << "\" is not manageable by not INTERP_KERNEL only method.";
-  oss << " Not only INTERP_KERNEL methods dealed are : GAUSSGAUSS !";
+  oss << " Not only INTERP_KERNEL methods dealed are : GAUSSGAUSS FEFE !";
   throw INTERP_KERNEL::Exception(oss.str().c_str());
 }
 
@@ -1011,6 +1043,15 @@ void MEDCouplingRemapper::checkPrepare() const
     throw INTERP_KERNEL::Exception("MEDCouplingRemapper::checkPrepare : it appears that no all field templates have their mesh set !");
 }
 
+void MEDCouplingRemapper::synchronizeSizeOfSideMatricesAfterMatrixComputation(mcIdType nbOfColsInMatrix)
+{
+  _deno_multiply.clear();
+  _deno_multiply.resize(_matrix.size());
+  _deno_reverse_multiply.clear();
+  _deno_reverse_multiply.resize(nbOfColsInMatrix);
+  declareAsNew();
+}
+
 /*!
  * This method builds a code considering already set field discretization int \a this : \a _src_ft and \a _target_ft.
  * This method returns 3 information (2 in output parameters and 1 in return).
@@ -1126,7 +1167,6 @@ void MEDCouplingRemapper::computeDeno(NatureOfField nat, const MEDCouplingFieldD
 void MEDCouplingRemapper::computeDenoFromScratch(NatureOfField nat, const MEDCouplingFieldDouble *srcField, const MEDCouplingFieldDouble *trgField)
 {
   _nature_of_deno=nat;
-  std::size_t _time_deno_update=getTimeOfThis();
   switch(_nature_of_deno)
   {
     case IntensiveMaximum:
@@ -1215,7 +1255,7 @@ void MEDCouplingRemapper::computeProduct(const double *inputPointer, int inputNb
       std::map<mcIdType,double>::const_iterator iter3=_deno_multiply[idx].begin();
       for(std::map<mcIdType,double>::const_iterator iter2=(*iter1).begin();iter2!=(*iter1).end();iter2++,iter3++)
         {
-          std::transform(inputPointer+(*iter2).first*inputNbOfCompo,inputPointer+((*iter2).first+1)*inputNbOfCompo,tmp,std::bind2nd(std::multiplies<double>(),(*iter2).second/(*iter3).second));
+          std::transform(inputPointer+(*iter2).first*inputNbOfCompo,inputPointer+((*iter2).first+1)*inputNbOfCompo,tmp,std::bind(std::multiplies<double>(),std::placeholders::_1,(*iter2).second/(*iter3).second));
           std::transform(tmp,tmp+inputNbOfCompo,resPointer+idx*inputNbOfCompo,resPointer+idx*inputNbOfCompo,std::plus<double>());
         }
     }
@@ -1233,7 +1273,7 @@ void MEDCouplingRemapper::computeReverseProduct(const double *inputPointer, int
       for(std::map<mcIdType,double>::const_iterator iter2=(*iter1).begin();iter2!=(*iter1).end();iter2++)
         {
           isReached[(*iter2).first]=true;
-          std::transform(inputPointer+idx*inputNbOfCompo,inputPointer+(idx+1)*inputNbOfCompo,tmp,std::bind2nd(std::multiplies<double>(),(*iter2).second/_deno_reverse_multiply[(*iter2).first][idx]));
+          std::transform(inputPointer+idx*inputNbOfCompo,inputPointer+(idx+1)*inputNbOfCompo,tmp,std::bind(std::multiplies<double>(),std::placeholders::_1,(*iter2).second/_deno_reverse_multiply[(*iter2).first][idx]));
           std::transform(tmp,tmp+inputNbOfCompo,resPointer+((*iter2).first)*inputNbOfCompo,resPointer+((*iter2).first)*inputNbOfCompo,std::plus<double>());
         }
     }