Salome HOME
Modification of the getHeapMemorySize computation.
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingFieldDiscretization.cxx
index ec5661169ea9571644563621f1fa1515c00b9c0c..04dc709084582968cdcdc0acc67a4d18e314a0c1 100644 (file)
@@ -179,11 +179,16 @@ void MEDCouplingFieldDiscretization::updateTime() const
 {
 }
 
-std::size_t MEDCouplingFieldDiscretization::getHeapMemorySize() const
+std::size_t MEDCouplingFieldDiscretization::getHeapMemorySizeWithoutChildren() const
 {
   return 0;
 }
 
+std::vector<RefCountObject *> MEDCouplingFieldDiscretization::getDirectChildren() const
+{
+  return std::vector<RefCountObject *>();
+}
+
 /*!
  * Computes normL1 of DataArrayDouble instance arr.
  * @param res output parameter expected to be of size arr->getNumberOfComponents();
@@ -621,8 +626,9 @@ DataArrayDouble *MEDCouplingFieldDiscretizationP0::getValueOnMulti(const DataArr
 {
   if(!mesh)
     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationP0::getValueOnMulti : NULL input mesh !");
-  std::vector<int> elts,eltsIndex;
-  mesh->getCellsContainingPoints(loc,nbOfPoints,_precision,elts,eltsIndex);
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsArr,eltsIndexArr;
+  mesh->getCellsContainingPoints(loc,nbOfPoints,_precision,eltsArr,eltsIndexArr);
+  const int *elts(eltsArr->begin()),*eltsIndex(eltsIndexArr->begin());
   int spaceDim=mesh->getSpaceDimension();
   int nbOfComponents=arr->getNumberOfComponents();
   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
@@ -1002,8 +1008,9 @@ DataArrayDouble *MEDCouplingFieldDiscretizationP1::getValueOnMulti(const DataArr
 {
   if(!mesh)
     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationP1::getValueOnMulti : NULL input mesh !");
-  std::vector<int> elts,eltsIndex;
-  mesh->getCellsContainingPoints(loc,nbOfPoints,_precision,elts,eltsIndex);
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsArr,eltsIndexArr;
+  mesh->getCellsContainingPoints(loc,nbOfPoints,_precision,eltsArr,eltsIndexArr);
+  const int *elts(eltsArr->begin()),*eltsIndex(eltsIndexArr->begin());
   int spaceDim=mesh->getSpaceDimension();
   int nbOfComponents=arr->getNumberOfComponents();
   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
@@ -1067,11 +1074,17 @@ void MEDCouplingFieldDiscretizationPerCell::updateTime() const
     updateTimeWith(*_discr_per_cell);
 }
 
-std::size_t MEDCouplingFieldDiscretizationPerCell::getHeapMemorySize() const
+std::size_t MEDCouplingFieldDiscretizationPerCell::getHeapMemorySizeWithoutChildren() const
+{
+  std::size_t ret(MEDCouplingFieldDiscretization::getHeapMemorySizeWithoutChildren());
+  return ret;
+}
+
+std::vector<RefCountObject *> MEDCouplingFieldDiscretizationPerCell::getDirectChildren() const
 {
-  std::size_t ret=0;
+  std::vector<RefCountObject *> ret(MEDCouplingFieldDiscretization::getDirectChildren());
   if(_discr_per_cell)
-    ret+=_discr_per_cell->getHeapMemorySize();
+    ret.push_back(const_cast<DataArrayInt *>(_discr_per_cell));
   return ret;
 }
 
@@ -1305,12 +1318,13 @@ std::string MEDCouplingFieldDiscretizationGauss::getStringRepr() const
   return oss.str();
 }
 
-std::size_t MEDCouplingFieldDiscretizationGauss::getHeapMemorySize() const
+std::size_t MEDCouplingFieldDiscretizationGauss::getHeapMemorySizeWithoutChildren() const
 {
-  std::size_t ret=_loc.capacity()*sizeof(MEDCouplingGaussLocalization);
+  std::size_t ret(MEDCouplingFieldDiscretizationPerCell::getHeapMemorySizeWithoutChildren());
+  ret+=_loc.capacity()*sizeof(MEDCouplingGaussLocalization);
   for(std::vector<MEDCouplingGaussLocalization>::const_iterator it=_loc.begin();it!=_loc.end();it++)
     ret+=(*it).getHeapMemorySize();
-  return MEDCouplingFieldDiscretizationPerCell::getHeapMemorySize()+ret;
+  return ret;
 }
 
 const char *MEDCouplingFieldDiscretizationGauss::getRepr() const
@@ -1323,7 +1337,7 @@ const char *MEDCouplingFieldDiscretizationGauss::getRepr() const
  */
 int MEDCouplingFieldDiscretizationGauss::getNumberOfTuplesExpectedRegardingCode(const MEDCouplingMesh *mesh, const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
 {
-  if(!_discr_per_cell || _discr_per_cell->isAllocated() || _discr_per_cell->getNumberOfComponents()!=1)
+  if(!_discr_per_cell || !_discr_per_cell->isAllocated() || _discr_per_cell->getNumberOfComponents()!=1)
     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::getNumberOfTuplesExpectedRegardingCode");
   if(code.size()%3!=0)
     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::getNumberOfTuplesExpectedRegardingCode : invalid input code !");
@@ -1366,8 +1380,17 @@ int MEDCouplingFieldDiscretizationGauss::getNumberOfTuples(const MEDCouplingMesh
     throw INTERP_KERNEL::Exception("Discretization is not initialized!");
   const int *dcPtr=_discr_per_cell->getConstPointer();
   int nbOfTuples=_discr_per_cell->getNumberOfTuples();
+  int maxSz=(int)_loc.size();
   for(const int *w=dcPtr;w!=dcPtr+nbOfTuples;w++)
-    ret+=_loc[*w].getNumberOfGaussPt();
+    {
+      if(*w>=0 && *w<maxSz)
+        ret+=_loc[*w].getNumberOfGaussPt();
+      else
+        {
+          std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationGauss::getNumberOfTuples : At cell #" << std::distance(dcPtr,w) << " localization id is " << *w << " should be in [0," << maxSz << ") !";
+          throw INTERP_KERNEL::Exception(oss.str().c_str());
+        }
+    }
   return ret;
 }
 
@@ -2568,43 +2591,92 @@ void MEDCouplingFieldDiscretizationKriging::getValueOn(const DataArrayDouble *ar
 
 DataArrayDouble *MEDCouplingFieldDiscretizationKriging::getValueOnMulti(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, const double *loc, int nbOfTargetPoints) const
 {
-  if(!mesh)
-    throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationKriging::getValueOnMulti : NULL input mesh !");
-  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getLocalizationOfDiscValues(mesh);
-  int nbOfPts=coords->getNumberOfTuples();
-  int dimension=coords->getNumberOfComponents();
-  //
-  int delta=0;
-  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> KnewiK=computeVectorOfCoefficients(mesh,arr,delta);
+  if(!arr || !arr->isAllocated())
+    throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationKriging::getValueOnMulti : input array is null or not allocated !");
+  int nbOfRows(getNumberOfMeshPlaces(mesh));
+  if(arr->getNumberOfTuples()!=nbOfRows)
+    {
+      std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationKriging::getValueOnMulti : input array does not have correct number of tuples ! Excepted " << nbOfRows << " having " << arr->getNumberOfTuples() << " !";
+      throw INTERP_KERNEL::Exception(oss.str().c_str());
+    }
+  int nbCols(-1),nbCompo(arr->getNumberOfComponents());
+  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> m(computeEvaluationMatrixOnGivenPts(mesh,loc,nbOfTargetPoints,nbCols));
+  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
+  ret->alloc(nbOfTargetPoints,nbCompo);
+  INTERP_KERNEL::matrixProduct(m->begin(),nbOfTargetPoints,nbCols,arr->begin(),nbOfRows,nbCompo,ret->getPointer());
+  return ret.retn();
+}
+
+void MEDCouplingFieldDiscretizationKriging::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
+{
+  stream << "Kriging spatial discretization.";
+}
+
+/*!
+ * Returns the matrix of size nbRows = \a nbOfTargetPoints and \a nbCols = \a nbCols. This matrix is useful if 
+ * 
+ * \return the new result matrix to be deallocated by the caller.
+ */
+DataArrayDouble *MEDCouplingFieldDiscretizationKriging::computeEvaluationMatrixOnGivenPts(const MEDCouplingMesh *mesh, const double *loc, int nbOfTargetPoints, int& nbCols) const
+{
+  int isDrift(-1),nbRows(-1);
+  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> matrixInv(computeInverseMatrix(mesh,isDrift,nbRows));
   //
+  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getLocalizationOfDiscValues(mesh);
+  int nbOfPts(coords->getNumberOfTuples()),dimension(coords->getNumberOfComponents());
   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> locArr=DataArrayDouble::New();
   locArr->useArray(loc,false,CPP_DEALLOC,nbOfTargetPoints,dimension);
+  nbCols=nbOfPts;
+  //
   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> matrix2=coords->buildEuclidianDistanceDenseMatrixWith(locArr);
-  operateOnDenseMatrix(mesh->getSpaceDimension(),nbOfPts*nbOfTargetPoints,matrix2->getPointer());
+  operateOnDenseMatrix(mesh->getSpaceDimension(),nbOfTargetPoints*nbOfPts,matrix2->getPointer());
+  //
   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> matrix3=DataArrayDouble::New();
-  matrix3->alloc((nbOfPts+delta)*nbOfTargetPoints,1);
+  matrix3->alloc(nbOfTargetPoints*nbRows,1);
   double *work=matrix3->getPointer();
-  const double *workCst=matrix2->getConstPointer();
-  const double *workCst2=loc;
-  for(int i=0;i<nbOfTargetPoints;i++,workCst+=nbOfPts,workCst2+=delta-1)
+  const double *workCst(matrix2->begin()),*workCst2(loc);
+  for(int i=0;i<nbOfTargetPoints;i++,workCst+=nbOfPts,workCst2+=isDrift-1)
     {
       for(int j=0;j<nbOfPts;j++)
-        work[j*nbOfTargetPoints+i]=workCst[j];
-      work[nbOfPts*nbOfTargetPoints+i]=1.0;
-      for(int j=0;j<delta-1;j++)
-        work[(nbOfPts+1+j)*nbOfTargetPoints+i]=workCst2[j];
+        work[i*nbRows+j]=workCst[j];
+      work[i*nbRows+nbOfPts]=1.0;
+      for(int j=0;j<isDrift-1;j++)
+        work[i*nbRows+(nbOfPts+1+j)]=workCst2[j];
     }
-  //
-  int nbOfCompo=arr->getNumberOfComponents();
-  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
-  ret->alloc(nbOfTargetPoints,nbOfCompo);
-  INTERP_KERNEL::matrixProduct(KnewiK->getConstPointer(),1,nbOfPts+delta,matrix3->getConstPointer(),nbOfPts+delta,nbOfTargetPoints*nbOfCompo,ret->getPointer());
-  return ret.retn();
+  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
+  ret->alloc(nbOfTargetPoints,nbRows);
+  INTERP_KERNEL::matrixProduct(matrix3->begin(),nbOfTargetPoints,nbRows,matrixInv->begin(),nbRows,nbRows,ret->getPointer());
+  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret2(DataArrayDouble::New());
+  ret2->alloc(nbOfTargetPoints*nbOfPts,1);
+  workCst=ret->begin(); work=ret2->getPointer();
+  for(int i=0;i<nbOfTargetPoints;i++,workCst+=nbRows)
+    work=std::copy(workCst,workCst+nbOfPts,work);
+  return ret2.retn();
 }
 
-void MEDCouplingFieldDiscretizationKriging::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
+/*!
+ * This method returns the square matrix of size \a matSz that is the inverse of the kriging matrix. The returned matrix can returned all the coeffs of kriging
+ * when multiplied by the vector of values attached to each point.
+ * 
+ * \param [out] isDrift return if drift coefficients are present in the returned vector of coefficients. If different from 0 there is presence of drift coefficients.
+ * \param [out] matSz the size of returned square matrix
+ * \return the new result matrix to be deallocated by the caller.
+ */
+DataArrayDouble *MEDCouplingFieldDiscretizationKriging::computeInverseMatrix(const MEDCouplingMesh *mesh, int& isDrift, int& matSz) const
 {
-  stream << "Kriging spatial discretization.";
+  if(!mesh)
+    throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationKriging::computeVectorOfCoefficients : NULL input mesh !");
+  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getLocalizationOfDiscValues(mesh);
+  int nbOfPts=coords->getNumberOfTuples();
+  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> matrix=coords->buildEuclidianDistanceDenseMatrix();
+  operateOnDenseMatrix(mesh->getSpaceDimension(),nbOfPts*nbOfPts,matrix->getPointer());
+  // Drift
+  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> matrixWithDrift=performDrift(matrix,coords,isDrift);
+  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> matrixInv=DataArrayDouble::New();
+  matSz=nbOfPts+isDrift;
+  matrixInv->alloc(matSz*matSz,1);
+  INTERP_KERNEL::inverseMatrix(matrixWithDrift->getConstPointer(),matSz,matrixInv->getPointer());
+  return matrixInv.retn();
 }
 
 /*!
@@ -2613,32 +2685,21 @@ void MEDCouplingFieldDiscretizationKriging::reprQuickOverview(std::ostream& stre
  * 
  * \param [in] mesh is the sources of nodes on which kriging will be done regarding the parameters and the value of \c this->getSpaceDimension()
  * \param [in] arr input field DataArrayDouble whose number of tuples must be equal to the number of nodes in \a mesh
- * \param [out] isDrift return if drift coefficients are present in the returned vector of coefficients, and if. If different from 0 there is presence of drift coefficients.
+ * \param [out] isDrift return if drift coefficients are present in the returned vector of coefficients. If different from 0 there is presence of drift coefficients.
  *              Whatever the value of \a isDrift the number of tuples of returned DataArrayDouble  will be equal to \c arr->getNumberOfTuples() + \a isDrift.
  * \return a newly allocated array containing coefficients including or not drift coefficient at the end depending the value of \a isDrift parameter.
  */
 DataArrayDouble *MEDCouplingFieldDiscretizationKriging::computeVectorOfCoefficients(const MEDCouplingMesh *mesh, const DataArrayDouble *arr, int& isDrift) const
 {
-  if(!mesh)
-    throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationKriging::computeVectorOfCoefficients : NULL input mesh !");
-  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getLocalizationOfDiscValues(mesh);
-  int nbOfPts=coords->getNumberOfTuples();
-  //int dimension=coords->getNumberOfComponents();
-  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> matrix=coords->buildEuclidianDistanceDenseMatrix();
-  operateOnDenseMatrix(mesh->getSpaceDimension(),nbOfPts*nbOfPts,matrix->getPointer());
-  // Drift
-  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> matrixWithDrift=performDrift(matrix,coords,isDrift);
-  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> matrixInv=DataArrayDouble::New();
-  matrixInv->alloc((nbOfPts+isDrift)*(nbOfPts+isDrift),1);
-  INTERP_KERNEL::inverseMatrix(matrixWithDrift->getConstPointer(),nbOfPts+isDrift,matrixInv->getPointer());
-  //
+  int nbRows(-1);
+  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> matrixInv(computeInverseMatrix(mesh,isDrift,nbRows));
   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> KnewiK=DataArrayDouble::New();
-  KnewiK->alloc((nbOfPts+isDrift)*1,1);
+  KnewiK->alloc(nbRows*1,1);
   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr2=DataArrayDouble::New();
-  arr2->alloc((nbOfPts+isDrift)*1,1);
+  arr2->alloc(nbRows*1,1);
   double *work=std::copy(arr->begin(),arr->end(),arr2->getPointer());
   std::fill(work,work+isDrift,0.);
-  INTERP_KERNEL::matrixProduct(matrixInv->getConstPointer(),nbOfPts+isDrift,nbOfPts+isDrift,arr2->getConstPointer(),nbOfPts+isDrift,1,KnewiK->getPointer());
+  INTERP_KERNEL::matrixProduct(matrixInv->getConstPointer(),nbRows,nbRows,arr2->getConstPointer(),nbRows,1,KnewiK->getPointer());
   return KnewiK.retn();
 }
 
@@ -2662,8 +2723,23 @@ void MEDCouplingFieldDiscretizationKriging::operateOnDenseMatrix(int spaceDimens
           }
         break;
       }
+    case 2:
+      {
+        for(int i=0;i<nbOfElems;i++)
+          {
+            double val=matrixPtr[i];
+            if(val!=0.)
+              matrixPtr[i]=val*val*log(val);
+          }
+        break;
+      }
+    case 3:
+      {
+        //nothing here : it is not a bug g(h)=h with spaceDim 3.
+        break;
+      }
     default:
-      throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationKriging::operateOnDenseMatrix : only dimension 1 implemented !");
+      throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationKriging::operateOnDenseMatrix : only dimension 1, 2 and 3 implemented !");
     }
 }
 
@@ -2706,7 +2782,7 @@ DataArrayDouble *MEDCouplingFieldDiscretizationKriging::performDrift(const DataA
       destWork=std::copy(srcWork2,srcWork2+szOfMatrix,destWork);
       srcWork2+=szOfMatrix;
       std::fill(destWork,destWork+spaceDimension+1,0.);
-      destWork+=spaceDimension;
+      destWork+=spaceDimension+1;
     }
   //
   return ret.retn();