Salome HOME
Debug on limit cases when input part are empty. Correct bug of DeduceNumberOfEntities.
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingStructuredMesh.cxx
index 8db11f5a821d89de73a0280329e870591acf42fd..58ec89f01f767fe0a55e02f76ef62f9eca7cfca7 100644 (file)
@@ -660,6 +660,85 @@ DataArrayInt *MEDCouplingStructuredMesh::Build1GTNodalConnectivityOfSubLevelMesh
   }
 }
 
+/*!
+ * This method returns the list of ids sorted ascendingly of entities that are in the corner in ghost zone.
+ * The ids are returned in a newly created DataArrayInt having a single component.
+ *
+ * \param [in] st - The structure \b without ghost cells.
+ * \param [in] ghostLev - The size of the ghost zone (>=0)
+ * \return DataArrayInt * - The DataArray containing all the ids the caller is to deallocate.
+ */
+DataArrayInt *MEDCouplingStructuredMesh::ComputeCornersGhost(const std::vector<int>& st, int ghostLev)
+{
+  if(ghostLev<0)
+    throw INTERP_KERNEL::Exception("MEDCouplingStructuredMesh::ComputeCornersGhost : ghost lev must be >= 0 !");
+  std::size_t dim(st.size());
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New());
+  switch(dim)
+  {
+    case 1:
+      {
+        ret->alloc(2*ghostLev,1);
+        int *ptr(ret->getPointer());
+        for(int i=0;i<ghostLev;i++,ptr++)
+          *ptr=i;
+        int offset(st[0]);
+        if(offset<0)
+          throw INTERP_KERNEL::Exception("MEDCouplingStructuredMesh::ComputeCornersGhost : element in 1D structure must be >= 0 !");
+        for(int i=0;i<ghostLev;i++,ptr++)
+          *ptr=offset+ghostLev+i;
+        break;
+      }
+    case 2:
+      {
+        int offsetX(st[0]),offsetY(st[1]);
+        if(offsetX<0 || offsetY<0)
+          throw INTERP_KERNEL::Exception("MEDCouplingStructuredMesh::ComputeCornersGhost : elements in 2D structure must be >= 0 !");
+        ret->alloc(4*ghostLev,1);
+        int *ptr(ret->getPointer());
+        for(int i=0;i<ghostLev;i++)
+          {
+            *ptr++=i*(2*ghostLev+offsetX+1);
+            *ptr++=offsetX+2*ghostLev-1+i*(2*ghostLev+offsetX-1);
+          }
+        for(int i=0;i<ghostLev;i++)
+          {
+            *ptr++=(2*ghostLev+offsetX)*(offsetY+ghostLev)+ghostLev-1+i*(2*ghostLev+offsetX-1);
+            *ptr++=(2*ghostLev+offsetX)*(offsetY+ghostLev)+offsetX+ghostLev+i*(2*ghostLev+offsetX+1);
+          }
+        break;
+      }
+    case 3:
+      {
+        int offsetX(st[0]),offsetY(st[1]),offsetZ(st[2]);
+        if(offsetX<0 || offsetY<0 || offsetZ<0)
+          throw INTERP_KERNEL::Exception("MEDCouplingStructuredMesh::ComputeCornersGhost : elements in 3D structure must be >= 0 !");
+        ret->alloc(8*ghostLev,1);
+        int *ptr(ret->getPointer());
+        int zeOffsetZ((offsetX+2*ghostLev)*(offsetY+2*ghostLev));
+        for(int i=0;i<ghostLev;i++)
+          {
+            *ptr++=i*(2*ghostLev+offsetX+1)+i*zeOffsetZ;
+            *ptr++=offsetX+2*ghostLev-1+i*(2*ghostLev+offsetX-1)+i*zeOffsetZ;
+            *ptr++=(2*ghostLev+offsetX)*(offsetY+ghostLev)+ghostLev-1+(ghostLev-i-1)*(2*ghostLev+offsetX-1)+i*zeOffsetZ;
+            *ptr++=(2*ghostLev+offsetX)*(offsetY+ghostLev)+offsetX+ghostLev+(ghostLev-i-1)*(2*ghostLev+offsetX+1)+i*zeOffsetZ;
+          }
+        int j(0),zeOffsetZ2(zeOffsetZ*(offsetZ+ghostLev));
+        for(int i=ghostLev-1;i>=0;i--,j++)
+          {
+            *ptr++=i*(2*ghostLev+offsetX+1)+j*zeOffsetZ+zeOffsetZ2;
+            *ptr++=offsetX+2*ghostLev-1+i*(2*ghostLev+offsetX-1)+j*zeOffsetZ+zeOffsetZ2;
+            *ptr++=(2*ghostLev+offsetX)*(offsetY+ghostLev)+ghostLev-1+(ghostLev-i-1)*(2*ghostLev+offsetX-1)+j*zeOffsetZ+zeOffsetZ2;
+            *ptr++=(2*ghostLev+offsetX)*(offsetY+ghostLev)+offsetX+ghostLev+(ghostLev-i-1)*(2*ghostLev+offsetX+1)+j*zeOffsetZ+zeOffsetZ2;
+          }
+        break;
+      }
+    default:
+      throw INTERP_KERNEL::Exception("MEDCouplingStructuredMesh::ComputeCornersGhost : Only dimensions 1, 2 and 3 are supported actually !");
+  }
+  return ret.retn();
+}
+
 /*!
  * This method retrieves the number of entities (it can be cells or nodes) given a range in compact standard format
  * used in methods like BuildExplicitIdsFrom,IsPartStructured.
@@ -669,7 +748,6 @@ DataArrayInt *MEDCouplingStructuredMesh::Build1GTNodalConnectivityOfSubLevelMesh
 int MEDCouplingStructuredMesh::DeduceNumberOfGivenRangeInCompactFrmt(const std::vector< std::pair<int,int> >& partCompactFormat)
 {
   int ret(1);
-  bool isFetched(false);
   std::size_t ii(0);
   for(std::vector< std::pair<int,int> >::const_iterator it=partCompactFormat.begin();it!=partCompactFormat.end();it++,ii++)
     {
@@ -679,13 +757,9 @@ int MEDCouplingStructuredMesh::DeduceNumberOfGivenRangeInCompactFrmt(const std::
           std::ostringstream oss; oss << "MEDCouplingStructuredMesh::DeduceNumberOfGivenRangeInCompactFrmt : invalid input at dimension " << ii << " !";
           throw INTERP_KERNEL::Exception(oss.str().c_str());
         }
-      if(b-a>0)
-        {
-          isFetched=true;
-          ret*=(b-a);
-        }
+      ret*=(b-a);
     }
-  return isFetched?ret:0;
+  return ret;
 }
 
 int MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(const std::vector<int>& st)
@@ -1014,7 +1088,7 @@ int MEDCouplingStructuredMesh::FindMinimalPartOf3D(const std::vector<int>& st, c
             {
               nxMin=std::min(nxMin,k); nxMax=std::max(nxMax,k);
               nyMin=std::min(nyMin,j); nyMax=std::max(nyMax,j);
-              nzMin=std::min(nyMin,i); nzMax=std::max(nyMax,i);
+              nzMin=std::min(nzMin,i); nzMax=std::max(nzMax,i);
               ret++;
             }
         }
@@ -1270,11 +1344,81 @@ bool MEDCouplingStructuredMesh::IsPartStructured(const int *startIds, const int
   }
 }
 
+/*!
+ * This method takes in input a compact format [[Xmax,Xmin),[Ymin,Ymax)] and returns the corresponding dimensions for each axis that is to say
+ * [Xmax-Xmin,Ymax-Ymin].
+ *
+ * \throw if an axis range is so that max<min
+ * \sa GetCompactFrmtFromDimensions
+ */
 std::vector<int> MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(const std::vector< std::pair<int,int> >& partCompactFormat)
 {
   std::vector<int> ret(partCompactFormat.size());
   for(std::size_t i=0;i<partCompactFormat.size();i++)
-    ret[i]=partCompactFormat[i].second-partCompactFormat[i].first;
+    {
+      if(partCompactFormat[i].first>partCompactFormat[i].second)
+        {
+          std::ostringstream oss; oss << "MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt : For axis #" << i << " end is before start !";
+          throw INTERP_KERNEL::Exception(oss.str().c_str());
+        }
+      ret[i]=partCompactFormat[i].second-partCompactFormat[i].first;
+    }
+  return ret;
+}
+
+/*!
+ * This method takes in input a vector giving the number of entity per axis and returns for each axis a range starting from [0,0...]
+ *
+ * \throw if there is an axis in \a dims that is < 0.
+ * \sa GetDimensionsFromCompactFrmt, ChangeReferenceFromGlobalOfCompactFrmt, ChangeReferenceToGlobalOfCompactFrmt
+ */
+std::vector< std::pair<int,int> > MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(const std::vector<int>& dims)
+{
+  std::size_t sz(dims.size());
+  std::vector< std::pair<int,int> > ret(sz);
+  for(std::size_t i=0;i<sz;i++)
+    {
+      if(dims[i]<0)
+        {
+          std::ostringstream oss; oss << "MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt : For axis #" << i << " dimension < 0 !";
+          throw INTERP_KERNEL::Exception(oss.str().c_str());
+        }
+      ret[i].first=0;
+      ret[i].second=dims[i];
+    }
+  return ret;
+}
+
+/*!
+ * This method returns the intersection zone of two ranges (in compact format) \a r1 and \a r2.
+ * This method will throw exception if on one axis the intersection is empty.
+ */
+std::vector< std::pair<int,int> > MEDCouplingStructuredMesh::IntersectRanges(const std::vector< std::pair<int,int> >& r1, const std::vector< std::pair<int,int> >& r2)
+{
+  std::size_t sz(r1.size());
+  if(sz!=r2.size())
+    throw INTERP_KERNEL::Exception("MEDCouplingStructuredMesh::IntersectRanges : the two ranges must have the same dimension !");
+  std::vector< std::pair<int,int> > ret(sz);
+  for(std::size_t i=0;i<sz;i++)
+    {
+      if(r1[i].first>r1[i].second)
+        {
+          std::ostringstream oss; oss << "MEDCouplingStructuredMesh::IntersectRanges : On axis " << i << " of range r1, end is before start !";
+          throw INTERP_KERNEL::Exception(oss.str().c_str());
+        }
+      if(r2[i].first>r2[i].second)
+        {
+          std::ostringstream oss; oss << "MEDCouplingStructuredMesh::IntersectRanges : On axis " << i << " of range r2, end is before start !";
+          throw INTERP_KERNEL::Exception(oss.str().c_str());
+        }
+      ret[i].first=std::max(r1[i].first,r2[i].first);
+      ret[i].second=std::min(r1[i].second,r2[i].second);
+      if(ret[i].first>ret[i].second)
+        {
+          std::ostringstream oss; oss << "MEDCouplingStructuredMesh::IntersectRanges : On axis " << i << " the intersection of r1 and r2 is empty !";
+          throw INTERP_KERNEL::Exception(oss.str().c_str());
+        }
+    }
   return ret;
 }
 
@@ -1343,7 +1487,7 @@ void MEDCouplingStructuredMesh::SwitchOnIdsFrom(const std::vector<int>& st, cons
  * \param [in] partCompactFormat The compact subpart to be enabled.
  * \param [out] fieldOut the result of the extraction.
  *
- * \sa MEDCouplingStructuredMesh::BuildExplicitIdsFrom, SwitchOnIdsFrom
+ * \sa MEDCouplingStructuredMesh::BuildExplicitIdsFrom, SwitchOnIdsFrom, ExtractFieldOfDoubleFrom
  */
 void MEDCouplingStructuredMesh::ExtractFieldOfBoolFrom(const std::vector<int>& st, const std::vector<bool>& fieldOfBool, const std::vector< std::pair<int,int> >& partCompactFormat, std::vector<bool>& fieldOut)
 {
@@ -1392,15 +1536,78 @@ void MEDCouplingStructuredMesh::ExtractFieldOfBoolFrom(const std::vector<int>& s
   }
 }
 
+/*!
+ * This method is close to SwitchOnIdsFrom except that here, a sub field \a fieldOut is built starting from the input field \a fieldOfDbl having the structure \a st.
+ * The extraction is defined by \a partCompactFormat.
+ *
+ * \param [in] st The entity structure.
+ * \param [in] fieldOfDbl field of doubles having a number of tuples equal to \c MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(st).
+ * \param [in] partCompactFormat The compact subpart to be enabled.
+ * \return DataArrayDouble * -the result of the extraction.
+ *
+ * \sa MEDCouplingStructuredMesh::BuildExplicitIdsFrom, SwitchOnIdsFrom, ExtractFieldOfBoolFrom
+ */
+DataArrayDouble *MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom(const std::vector<int>& st, const DataArrayDouble *fieldOfDbl, const std::vector< std::pair<int,int> >& partCompactFormat)
+{
+  if(!fieldOfDbl || !fieldOfDbl->isAllocated())
+    throw INTERP_KERNEL::Exception("MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom : input array of double is NULL or not allocated!");
+  if(st.size()!=partCompactFormat.size())
+    throw INTERP_KERNEL::Exception("MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom : input arrays must have the same size !");
+  if(fieldOfDbl->getNumberOfTuples()!=DeduceNumberOfGivenStructure(st))
+    throw INTERP_KERNEL::Exception("MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom : invalid size of input array of double regarding the structure !");
+  std::vector<int> dims(GetDimensionsFromCompactFrmt(partCompactFormat));
+  int nbOfTuplesOfOutField(DeduceNumberOfGivenStructure(dims)),nbComp(fieldOfDbl->getNumberOfComponents());
+  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfTuplesOfOutField,nbComp);
+  ret->copyStringInfoFrom(*fieldOfDbl);
+  double *ptRet(ret->getPointer());
+  const double *fieldOfDblPtr(fieldOfDbl->begin());
+  switch(st.size())
+  {
+    case 3:
+      {
+        for(int i=0;i<dims[2];i++)
+          {
+            int a=(partCompactFormat[2].first+i)*st[0]*st[1];
+            for(int j=0;j<dims[1];j++)
+              {
+                int b=(partCompactFormat[1].first+j)*st[0];
+                for(int k=0;k<dims[0];k++)
+                  ptRet=std::copy(fieldOfDblPtr+(partCompactFormat[0].first+k+b+a)*nbComp,fieldOfDblPtr+(partCompactFormat[0].first+k+b+a+1)*nbComp,ptRet);
+              }
+          }
+        break;
+      }
+    case 2:
+      {
+        for(int j=0;j<dims[1];j++)
+          {
+            int b=(partCompactFormat[1].first+j)*st[0];
+            for(int k=0;k<dims[0];k++)
+              ptRet=std::copy(fieldOfDblPtr+(partCompactFormat[0].first+k+b)*nbComp,fieldOfDblPtr+(partCompactFormat[0].first+k+b+1)*nbComp,ptRet);
+          }
+        break;
+      }
+    case 1:
+      {
+        for(int k=0;k<dims[0];k++)
+          ptRet=std::copy(fieldOfDblPtr+(partCompactFormat[0].first+k)*nbComp,fieldOfDblPtr+(partCompactFormat[0].first+k+1)*nbComp,ptRet);
+        break;
+      }
+    default:
+      throw INTERP_KERNEL::Exception("MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom : Dimension supported are 1,2 or 3 !");
+  }
+  return ret.retn();
+}
+
 /*!
  * This method changes the reference of a part of structured mesh \a partOfBigInAbs define in absolute reference to a new reference \a bigInAbs.
  * So this method only performs a translation by doing \a partOfBigRelativeToBig = \a partOfBigInAbs - \a bigInAbs
- * This method also checks that \a partOfBigInAbs is included in \a bigInAbs.
+ * This method also checks (if \a check=true) that \a partOfBigInAbs is included in \a bigInAbs.
  * This method is useful to extract a part from a field lying on a big mesh.
  *
- * \sa ChangeReferenceToGlobalOfCompactFrmt, BuildExplicitIdsFrom, SwitchOnIdsFrom, ExtractFieldOfBoolFrom
+ * \sa ChangeReferenceToGlobalOfCompactFrmt, BuildExplicitIdsFrom, SwitchOnIdsFrom, ExtractFieldOfBoolFrom, ExtractFieldOfDoubleFrom
  */
-void MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(const std::vector< std::pair<int,int> >& bigInAbs, const std::vector< std::pair<int,int> >& partOfBigInAbs, std::vector< std::pair<int,int> >& partOfBigRelativeToBig)
+void MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(const std::vector< std::pair<int,int> >& bigInAbs, const std::vector< std::pair<int,int> >& partOfBigInAbs, std::vector< std::pair<int,int> >& partOfBigRelativeToBig, bool check)
 {
   std::size_t dim(bigInAbs.size());
   if(dim!=partOfBigInAbs.size())
@@ -1408,21 +1615,27 @@ void MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(const std
   partOfBigRelativeToBig.resize(dim);
   for(std::size_t i=0;i<dim;i++)
     {
-      if(bigInAbs[i].first>bigInAbs[i].second)
+      if(check)
         {
-          std::ostringstream oss; oss << "MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt : Error at axis #" << i << " the input big part invalid, end before start !";
-          throw INTERP_KERNEL::Exception(oss.str().c_str());
-        }
-      if(partOfBigInAbs[i].first<bigInAbs[i].first || partOfBigInAbs[i].first>=bigInAbs[i].second)
-        {
-          std::ostringstream oss; oss << "MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt : Error at axis #" << i << " the part is not included in the big one (start) !";
-          throw INTERP_KERNEL::Exception(oss.str().c_str());
+          if(bigInAbs[i].first>bigInAbs[i].second)
+            {
+              std::ostringstream oss; oss << "MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt : Error at axis #" << i << " the input big part invalid, end before start !";
+              throw INTERP_KERNEL::Exception(oss.str().c_str());
+            }
+          if(partOfBigInAbs[i].first<bigInAbs[i].first || partOfBigInAbs[i].first>=bigInAbs[i].second)
+            {
+              std::ostringstream oss; oss << "MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt : Error at axis #" << i << " the part is not included in the big one (start) !";
+              throw INTERP_KERNEL::Exception(oss.str().c_str());
+            }
         }
       partOfBigRelativeToBig[i].first=partOfBigInAbs[i].first-bigInAbs[i].first;
-      if(partOfBigInAbs[i].second<partOfBigInAbs[i].first || partOfBigInAbs[i].second>bigInAbs[i].second)
+      if(check)
         {
-          std::ostringstream oss; oss << "MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt : Error at axis #" << i << " the part is not included in the big one (end) !";
-          throw INTERP_KERNEL::Exception(oss.str().c_str());
+          if(partOfBigInAbs[i].second<partOfBigInAbs[i].first || partOfBigInAbs[i].second>bigInAbs[i].second)
+            {
+              std::ostringstream oss; oss << "MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt : Error at axis #" << i << " the part is not included in the big one (end) !";
+              throw INTERP_KERNEL::Exception(oss.str().c_str());
+            }
         }
       partOfBigRelativeToBig[i].second=partOfBigInAbs[i].second-bigInAbs[i].first;
     }
@@ -1433,7 +1646,7 @@ void MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(const std
  *
  * \sa ChangeReferenceFromGlobalOfCompactFrmt
  */
-void MEDCouplingStructuredMesh::ChangeReferenceToGlobalOfCompactFrmt(const std::vector< std::pair<int,int> >& bigInAbs, const std::vector< std::pair<int,int> >& partOfBigRelativeToBig, std::vector< std::pair<int,int> >& partOfBigInAbs)
+void MEDCouplingStructuredMesh::ChangeReferenceToGlobalOfCompactFrmt(const std::vector< std::pair<int,int> >& bigInAbs, const std::vector< std::pair<int,int> >& partOfBigRelativeToBig, std::vector< std::pair<int,int> >& partOfBigInAbs, bool check)
 {
   std::size_t dim(bigInAbs.size());
   if(dim!=partOfBigRelativeToBig.size())
@@ -1441,32 +1654,73 @@ void MEDCouplingStructuredMesh::ChangeReferenceToGlobalOfCompactFrmt(const std::
   partOfBigInAbs.resize(dim);
   for(std::size_t i=0;i<dim;i++)
     {
-      if(bigInAbs[i].first>bigInAbs[i].second)
+      if(check)
         {
-          std::ostringstream oss; oss << "MEDCouplingStructuredMesh::ChangeReferenceToGlobalOfCompactFrmt : Error at axis #" << i << " the input big part invalid, end before start !";
-          throw INTERP_KERNEL::Exception(oss.str().c_str());
-        }
-      if(partOfBigRelativeToBig[i].first<0 || partOfBigRelativeToBig[i].first>=bigInAbs[i].second-bigInAbs[i].first)
-        {
-          std::ostringstream oss; oss << "MEDCouplingStructuredMesh::ChangeReferenceToGlobalOfCompactFrmt : Error at axis #" << i << " the start of part is not in the big one !";
-          throw INTERP_KERNEL::Exception(oss.str().c_str());
+          if(bigInAbs[i].first>bigInAbs[i].second)
+            {
+              std::ostringstream oss; oss << "MEDCouplingStructuredMesh::ChangeReferenceToGlobalOfCompactFrmt : Error at axis #" << i << " the input big part invalid, end before start !";
+              throw INTERP_KERNEL::Exception(oss.str().c_str());
+            }
+          if(partOfBigRelativeToBig[i].first<0 || partOfBigRelativeToBig[i].first>=bigInAbs[i].second-bigInAbs[i].first)
+            {
+              std::ostringstream oss; oss << "MEDCouplingStructuredMesh::ChangeReferenceToGlobalOfCompactFrmt : Error at axis #" << i << " the start of part is not in the big one !";
+              throw INTERP_KERNEL::Exception(oss.str().c_str());
+            }
         }
       partOfBigInAbs[i].first=partOfBigRelativeToBig[i].first+bigInAbs[i].first;
-      if(partOfBigRelativeToBig[i].second<partOfBigRelativeToBig[i].first || partOfBigRelativeToBig[i].second>bigInAbs[i].second-bigInAbs[i].first)
+      if(check)
         {
-          std::ostringstream oss; oss << "MEDCouplingStructuredMesh::ChangeReferenceToGlobalOfCompactFrmt : Error at axis #" << i << " the end of part is not in the big one !";
-          throw INTERP_KERNEL::Exception(oss.str().c_str());
+          if(partOfBigRelativeToBig[i].second<partOfBigRelativeToBig[i].first || partOfBigRelativeToBig[i].second>bigInAbs[i].second-bigInAbs[i].first)
+            {
+              std::ostringstream oss; oss << "MEDCouplingStructuredMesh::ChangeReferenceToGlobalOfCompactFrmt : Error at axis #" << i << " the end of part is not in the big one !";
+              throw INTERP_KERNEL::Exception(oss.str().c_str());
+            }
         }
       partOfBigInAbs[i].second=partOfBigRelativeToBig[i].second+bigInAbs[i].first;
     }
 }
 
+/*!
+ * This method performs a translation (defined by \a translation) of \a part and returns the result of translated part.
+ *
+ * \sa FindTranslationFrom
+ */
+std::vector< std::pair<int,int> > MEDCouplingStructuredMesh::TranslateCompactFrmt(const std::vector< std::pair<int,int> >& part, const std::vector<int>& translation)
+{
+  std::size_t sz(part.size());
+  if(translation.size()!=sz)
+    throw INTERP_KERNEL::Exception("MEDCouplingStructuredMesh::TranslateCompactFrmt : the sizes are not equal !");
+  std::vector< std::pair<int,int> > ret(sz);
+  for(std::size_t i=0;i<sz;i++)
+    {
+      ret[i].first=part[i].first+translation[i];
+      ret[i].second=part[i].second+translation[i];
+    }
+  return ret;
+}
+
+/*!
+ * \sa TranslateCompactFrmt
+ */
+std::vector<int> MEDCouplingStructuredMesh::FindTranslationFrom(const std::vector< std::pair<int,int> >& startingFrom, const std::vector< std::pair<int,int> >& goingTo)
+{
+  std::size_t sz(startingFrom.size());
+  if(goingTo.size()!=sz)
+    throw INTERP_KERNEL::Exception("MEDCouplingStructuredMesh::FindTranslationFrom : the sizes are not equal !");
+  std::vector< int > ret(sz);
+  for(std::size_t i=0;i<sz;i++)
+    {
+      ret[i]=goingTo[i].first-startingFrom[i].first;
+    }
+  return ret;
+}
+
 /*!
  * This method builds the explicit entity array from the structure in \a st and the range in \a partCompactFormat.
  * If the range contains invalid values regarding sructure an exception will be thrown.
  *
  * \return DataArrayInt * - a new object.
- * \sa MEDCouplingStructuredMesh::IsPartStructured, MEDCouplingStructuredMesh::DeduceNumberOfGivenRangeInCompactFrmt, SwitchOnIdsFrom, ExtractFieldOfBoolFrom
+ * \sa MEDCouplingStructuredMesh::IsPartStructured, MEDCouplingStructuredMesh::DeduceNumberOfGivenRangeInCompactFrmt, SwitchOnIdsFrom, ExtractFieldOfBoolFrom, ExtractFieldOfDoubleFrom, MultiplyPartOf
  */
 DataArrayInt *MEDCouplingStructuredMesh::BuildExplicitIdsFrom(const std::vector<int>& st, const std::vector< std::pair<int,int> >& partCompactFormat)
 {
@@ -1480,7 +1734,7 @@ DataArrayInt *MEDCouplingStructuredMesh::BuildExplicitIdsFrom(const std::vector<
         throw INTERP_KERNEL::Exception("MEDCouplingStructuredMesh::BuildExplicitIdsFrom : invalid input range 1 !");
       if(partCompactFormat[i].second<0 || partCompactFormat[i].second>st[i])
         throw INTERP_KERNEL::Exception("MEDCouplingStructuredMesh::BuildExplicitIdsFrom : invalid input range 2 !");
-      if(partCompactFormat[i].second<=partCompactFormat[i].first)
+      if(partCompactFormat[i].second<partCompactFormat[i].first)
         throw INTERP_KERNEL::Exception("MEDCouplingStructuredMesh::BuildExplicitIdsFrom : invalid input range 3 !");
       dims[i]=partCompactFormat[i].second-partCompactFormat[i].first;
       nbOfItems*=dims[i];
@@ -1526,6 +1780,148 @@ DataArrayInt *MEDCouplingStructuredMesh::BuildExplicitIdsFrom(const std::vector<
   return ret.retn();
 }
 
+/*!
+ * This method multiplies by \a factor values in tuples located by \a part in \a da.
+ *
+ * \param [in] st - the structure of grid ( \b without considering ghost cells).
+ * \param [in] part - the part in the structure ( \b without considering ghost cells) contained in grid whose structure is defined by \a st.
+ * \param [in] factor - the factor, the tuples in \a da will be multiply by.
+ * \param [in,out] da - The DataArray in wich only tuples specified by \a part will be modified.
+ *
+ * \sa BuildExplicitIdsFrom
+ */
+void MEDCouplingStructuredMesh::MultiplyPartOf(const std::vector<int>& st, const std::vector< std::pair<int,int> >& part, double factor, DataArrayDouble *da)
+{
+  if(!da || !da->isAllocated())
+    throw INTERP_KERNEL::Exception("MEDCouplingStructuredMesh::MultiplyPartOf : DataArrayDouble instance must be not NULL and allocated !");
+  if(st.size()!=part.size())
+    throw INTERP_KERNEL::Exception("MEDCouplingStructuredMesh::MultiplyPartOf : input arrays must have the same size !");
+  std::vector<int> dims(st.size());
+  for(std::size_t i=0;i<st.size();i++)
+    {
+      if(part[i].first<0 || part[i].first>st[i])
+        throw INTERP_KERNEL::Exception("MEDCouplingStructuredMesh::MultiplyPartOf : invalid input range 1 !");
+      if(part[i].second<0 || part[i].second>st[i])
+        throw INTERP_KERNEL::Exception("MEDCouplingStructuredMesh::MultiplyPartOf : invalid input range 2 !");
+      if(part[i].second<part[i].first)
+        throw INTERP_KERNEL::Exception("MEDCouplingStructuredMesh::MultiplyPartOf : invalid input range 3 !");
+      dims[i]=part[i].second-part[i].first;
+    }
+  int nbOfTuplesExp(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(st)),nbCompo(da->getNumberOfComponents());
+  if(da->getNumberOfTuples()!=nbOfTuplesExp)
+    {
+      std::ostringstream oss; oss << "MEDCouplingStructuredMesh::MultiplyPartOf : invalid nb of tuples ! Expected " << nbOfTuplesExp << " having " << da->getNumberOfTuples() << " !";
+      throw INTERP_KERNEL::Exception(oss.str().c_str());
+    }
+  double *pt(da->getPointer());
+  switch(st.size())
+  {
+    case 3:
+      {
+        for(int i=0;i<dims[2];i++)
+          {
+            int a=(part[2].first+i)*st[0]*st[1];
+            for(int j=0;j<dims[1];j++)
+              {
+                int b=(part[1].first+j)*st[0];
+                for(int k=0;k<dims[0];k++)
+                  {
+                    int offset(part[0].first+k+b+a);
+                    std::transform(pt+nbCompo*offset,pt+nbCompo*(offset+1),pt+nbCompo*offset,std::bind2nd(std::multiplies<double>(),factor));
+                  }
+              }
+          }
+        break;
+      }
+    case 2:
+      {
+        for(int j=0;j<dims[1];j++)
+          {
+            int b=(part[1].first+j)*st[0];
+            for(int k=0;k<dims[0];k++)
+              {
+                int offset(part[0].first+k+b);
+                std::transform(pt+nbCompo*offset,pt+nbCompo*(offset+1),pt+nbCompo*offset,std::bind2nd(std::multiplies<double>(),factor));
+              }
+          }
+        break;
+      }
+    case 1:
+      {
+        for(int k=0;k<dims[0];k++)
+          {
+            int offset(part[0].first+k);
+            std::transform(pt+nbCompo*offset,pt+nbCompo*(offset+1),pt+nbCompo*offset,std::bind2nd(std::multiplies<double>(),factor));
+          }
+        break;
+      }
+    default:
+      throw INTERP_KERNEL::Exception("MEDCouplingStructuredMesh::MultiplyPartOf : Dimension supported are 1,2 or 3 !");
+  }
+}
+
+/*!
+ * This method multiplies by \a factor values in tuples located by \a part in \a da.
+ *
+ * \param [in] st - the structure of grid ( \b without considering ghost cells).
+ * \param [in] part - the part in the structure ( \b without considering ghost cells) contained in grid whose structure is defined by \a st.
+ * \param [in] ghostSize - \a ghostSize must be >= 0.
+ * \param [in] factor - the factor, the tuples in \a da will be multiply by.
+ * \param [in,out] da - The DataArray in wich only tuples specified by \a part will be modified.
+ *
+ * \sa MultiplyPartOf, PutInGhostFormat
+ */
+void MEDCouplingStructuredMesh::MultiplyPartOfByGhost(const std::vector<int>& st, const std::vector< std::pair<int,int> >& part, int ghostSize, double factor, DataArrayDouble *da)
+{
+  std::vector<int> stWG;
+  std::vector< std::pair<int,int> > partWG;
+  PutInGhostFormat(ghostSize,st,part,stWG,partWG);
+  MultiplyPartOf(stWG,partWG,factor,da);
+}
+
+/*!
+ * This method multiplies by \a factor values in tuples located by \a part in \a da.
+ *
+ * \param [in] st - the structure of grid ( \b without considering ghost cells).
+ * \param [in] part - the part in the structure ( \b without considering ghost cells) contained in grid whose structure is defined by \a st.
+ * \param [in] ghostSize - \a ghostSize must be >= 0.
+ * \param [out] stWithGhost - the structure considering ghost cells.
+ * \param [out] partWithGhost - the part considering the ghost cells.
+ *
+ * \sa MultiplyPartOf, PutInGhostFormat
+ */
+void MEDCouplingStructuredMesh::PutInGhostFormat(int ghostSize, const std::vector<int>& st, const std::vector< std::pair<int,int> >& part, std::vector<int>& stWithGhost, std::vector< std::pair<int,int> >&partWithGhost)
+{
+  if(ghostSize<0)
+    throw INTERP_KERNEL::Exception("MEDCouplingStructuredMesh::PutInGhostFormat : ghost size must be >= 0 !");
+  std::size_t dim(part.size());
+  if(st.size()!=dim)
+    throw INTERP_KERNEL::Exception("MEDCouplingStructuredMesh::PutInGhostFormat : the dimension of input vectors must be the same !");
+  for(std::size_t i=0;i<dim;i++)
+    if(part[i].first<0 || part[i].first>part[i].second || part[i].second>st[i])
+      throw INTERP_KERNEL::Exception("MEDCouplingStructuredMesh::PutInGhostFormat : the specified part is invalid ! The begin must be >= 0 and <= end ! The end must be <= to the size at considered dimension !");
+  stWithGhost.resize(st.size());
+  std::transform(st.begin(),st.end(),stWithGhost.begin(),std::bind2nd(std::plus<int>(),2*ghostSize));
+  partWithGhost=part;
+  ApplyGhostOnCompactFrmt(partWithGhost,ghostSize);
+}
+
+/*!
+ * \param [in,out] partBeforeFact - the part of a image mesh in compact format that will be put in ghost reference.
+ * \param [in] ghostSize - the ghost size of zone for all axis.
+ */
+void MEDCouplingStructuredMesh::ApplyGhostOnCompactFrmt(std::vector< std::pair<int,int> >& partBeforeFact, int ghostSize)
+{
+  if(ghostSize<0)
+    throw INTERP_KERNEL::Exception("MEDCouplingStructuredMesh::ApplyGhostOnCompactFrmt : ghost size must be >= 0 !");
+  std::size_t sz(partBeforeFact.size());
+  for(std::size_t i=0;i<sz;i++)
+    {
+      partBeforeFact[i].first+=ghostSize;
+      partBeforeFact[i].second+=ghostSize;
+    }
+}
+
 int MEDCouplingStructuredMesh::GetNumberOfCellsOfSubLevelMesh(const std::vector<int>& cgs, int mdim)
 {
   int ret(0);