Salome HOME
First test OK with createPatchesFromCriterion
[modules/med.git] / src / MEDCoupling / MEDCouplingIMesh.cxx
index b7f8e78cb050676c9ec4d01b3be3be4038533130..4b3da324ab9f5517c144cb0c4662e9782c073bbd 100644 (file)
@@ -182,20 +182,60 @@ MEDCouplingCMesh *MEDCouplingIMesh::convertToCartesian() const
  * The origin of \a this will be not touched only spacing and node structure will be changed.
  * This method can be useful for AMR users.
  */
-void MEDCouplingIMesh::refineWithFactor(int factor)
+void MEDCouplingIMesh::refineWithFactor(const std::vector<int>& factors)
 {
-  if(factor==0)
-    throw INTERP_KERNEL::Exception("MEDCouplingIMesh::refineWithFactor : refinement factor must be != 0 !");
+  if((int)factors.size()!=_space_dim)
+    throw INTERP_KERNEL::Exception("MEDCouplingIMesh::refineWithFactor : refinement factors must have size equal to spaceDim !");
   checkCoherency();
-  int factAbs(std::abs(factor));
-  double fact2(1./(double)factor);
-  std::transform(_structure,_structure+_space_dim,_structure,std::bind2nd(std::plus<int>(),-1));
-  std::transform(_structure,_structure+_space_dim,_structure,std::bind2nd(std::multiplies<int>(),factAbs));
-  std::transform(_structure,_structure+_space_dim,_structure,std::bind2nd(std::plus<int>(),1));
-  std::transform(_dxyz,_dxyz+_space_dim,_dxyz,std::bind2nd(std::multiplies<double>(),fact2));
+  std::vector<int> structure(_structure,_structure+3);
+  std::vector<double> dxyz(_dxyz,_dxyz+3);
+  for(int i=0;i<_space_dim;i++)
+    {
+      if(factors[i]<=0)
+        {
+          std::ostringstream oss; oss << "MEDCouplingIMesh::refineWithFactor : factor for axis #" << i << " (" << factors[i] << ")is invalid ! Must be > 0 !";
+          throw INTERP_KERNEL::Exception(oss.str().c_str());
+        }
+      int factAbs(std::abs(factors[i]));
+      double fact2(1./(double)factors[i]);
+      structure[i]=(_structure[i]-1)*factAbs+1;
+      dxyz[i]=fact2*_dxyz[i];
+    }
+  std::copy(structure.begin(),structure.end(),_structure);
+  std::copy(dxyz.begin(),dxyz.end(),_dxyz);
   declareAsNew();
 }
 
+/*!
+ * This method returns a newly created mesh containing a single cell in it. This returned cell covers exactly the space covered by \a this.
+ *
+ * \return MEDCouplingIMesh * - A newly created object (to be managed by the caller with decrRef) containing simply one cell.
+ *
+ * \throw if \a this does not pass the \c checkCoherency test.
+ */
+MEDCouplingIMesh *MEDCouplingIMesh::asSingleCell() const
+{
+  checkCoherency();
+  int spaceDim(getSpaceDimension()),nodeSt[3];
+  double dxyz[3];
+  for(int i=0;i<spaceDim;i++)
+    {
+      if(_structure[i]>=2)
+        {
+          nodeSt[i]=2;
+          dxyz[i]=(_structure[i]-1)*_dxyz[i];
+        }
+      else
+        {
+          nodeSt[i]=_structure[i];
+          dxyz[i]=_dxyz[i];
+        }
+    }
+  MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> ret(MEDCouplingIMesh::New(getName(),getSpaceDimension(),nodeSt,nodeSt+spaceDim,_origin,_origin+spaceDim,dxyz,dxyz+spaceDim));
+  ret->copyTinyInfoFrom(this);
+  return ret.retn();
+}
+
 /*!
  * This static method is useful to condense field on cells of a MEDCouplingIMesh instance coming from a refinement ( MEDCouplingIMesh::refineWithFactor for example)
  * to a coarse MEDCouplingIMesh instance. So this method can be seen as a specialization in P0P0 conservative interpolation non overlaping from fine image mesh
@@ -205,8 +245,10 @@ void MEDCouplingIMesh::refineWithFactor(int factor)
  * \param [in] coarseSt The cell structure of coarse mesh.
  * \param [in] fineDA The DataArray containing the cell field on uniformly refined mesh
  * \param [in] fineLocInCoarse The cell localization of refined mesh into the coarse one.
+ * \param [in] facts The refinement coefficient per axis.
+ * \sa SpreadCoarseToFine
  */
-void MEDCouplingIMesh::CondenseFineToCoarse(DataArrayDouble *coarseDA, const std::vector<int>& coarseSt, const DataArrayDouble *fineDA, const std::vector< std::pair<int,int> >& fineLocInCoarse)
+void MEDCouplingIMesh::CondenseFineToCoarse(DataArrayDouble *coarseDA, const std::vector<int>& coarseSt, const DataArrayDouble *fineDA, const std::vector< std::pair<int,int> >& fineLocInCoarse, const std::vector<int>& facts)
 {
   if(!coarseDA || !coarseDA->isAllocated() || !fineDA || !fineDA->isAllocated())
     throw INTERP_KERNEL::Exception("MEDCouplingIMesh::CondenseFineToCoarse : the parameters 1 or 3 are NULL or not allocated !");
@@ -214,18 +256,22 @@ void MEDCouplingIMesh::CondenseFineToCoarse(DataArrayDouble *coarseDA, const std
   int nbCompo(fineDA->getNumberOfComponents());
   if(coarseDA->getNumberOfComponents()!=nbCompo)
     throw INTERP_KERNEL::Exception("MEDCouplingIMesh::CondenseFineToCoarse : the number of components of fine DA and coarse one mismatches !");
-  if(meshDim!=(int)fineLocInCoarse.size())
-    throw INTERP_KERNEL::Exception("MEDCouplingIMesh::CondenseFineToCoarse : the size of fineLocInCoarse (4th param) must be equal to the sier of coarseSt (2nd param) !");
+  if(meshDim!=(int)fineLocInCoarse.size() || meshDim!=(int)facts.size())
+    throw INTERP_KERNEL::Exception("MEDCouplingIMesh::CondenseFineToCoarse : the size of fineLocInCoarse (4th param) and facts (5th param) must be equal to the sier of coarseSt (2nd param) !");
   if(coarseDA->getNumberOfTuples()!=nbOfTuplesInCoarseExp)
     {
-      std::ostringstream oss; oss << "MEDCouplingIMesh::CondenseFineToCoarse : Expecting " << nbOfTuplesInCoarseExp << " having " << coarseDA->getNumberOfTuples() << " !";
+      std::ostringstream oss; oss << "MEDCouplingIMesh::CondenseFineToCoarse : Expecting " << nbOfTuplesInCoarseExp << " tuples having " << coarseDA->getNumberOfTuples() << " !";
       throw INTERP_KERNEL::Exception(oss.str().c_str());
     }
   int nbTuplesFine(fineDA->getNumberOfTuples());
   if(nbTuplesFine%nbOfTuplesInFineExp!=0)
     throw INTERP_KERNEL::Exception("MEDCouplingIMesh::CondenseFineToCoarse : Invalid nb of tuples in fine DataArray regarding its structure !");
-  int factN(nbTuplesFine/nbOfTuplesInFineExp);
-  int fact(FindIntRoot(factN,meshDim));
+  int fact(std::accumulate(facts.begin(),facts.end(),1,std::multiplies<int>()));
+  if(nbTuplesFine!=fact*nbOfTuplesInFineExp)
+    {
+      std::ostringstream oss; oss << "MEDCouplingIMesh::CondenseFineToCoarse : Invalid number of tuples ("  << nbTuplesFine << ") of fine dataarray is invalid ! Must be " << fact*nbOfTuplesInFineExp << "!";
+      throw INTERP_KERNEL::Exception(oss.str().c_str());
+    }
   // to improve use jump-iterator. Factorizes with SwitchOnIdsFrom BuildExplicitIdsFrom
   double *outPtr(coarseDA->getPointer());
   const double *inPtr(fineDA->begin());
@@ -235,11 +281,11 @@ void MEDCouplingIMesh::CondenseFineToCoarse(DataArrayDouble *coarseDA, const std
   {
     case 1:
       {
-        int offset(fineLocInCoarse[0].first);
+        int offset(fineLocInCoarse[0].first),fact0(facts[0]);
         for(int i=0;i<dims[0];i++)
           {
             double *loc(outPtr+(offset+i)*nbCompo);
-            for(int ifact=0;ifact<fact;ifact++,inPtr+=nbCompo)
+            for(int ifact=0;ifact<fact0;ifact++,inPtr+=nbCompo)
               {
                 if(ifact!=0)
                   std::transform(inPtr,inPtr+nbCompo,loc,loc,std::plus<double>());
@@ -251,15 +297,15 @@ void MEDCouplingIMesh::CondenseFineToCoarse(DataArrayDouble *coarseDA, const std
       }
     case 2:
       {
-        int kk(fineLocInCoarse[0].first+coarseSt[0]*fineLocInCoarse[1].first);
+        int kk(fineLocInCoarse[0].first+coarseSt[0]*fineLocInCoarse[1].first),fact1(facts[1]),fact0(facts[0]);
         for(int j=0;j<dims[1];j++)
           {
-            for(int jfact=0;jfact<fact;jfact++)
+            for(int jfact=0;jfact<fact1;jfact++)
               {
                 for(int i=0;i<dims[0];i++)
                   {
                     double *loc(outPtr+(kk+i)*nbCompo);
-                    for(int ifact=0;ifact<fact;ifact++,inPtr+=nbCompo)
+                    for(int ifact=0;ifact<fact0;ifact++,inPtr+=nbCompo)
                       {
                         if(jfact!=0 || ifact!=0)
                           std::transform(inPtr,inPtr+nbCompo,loc,loc,std::plus<double>());
@@ -274,19 +320,19 @@ void MEDCouplingIMesh::CondenseFineToCoarse(DataArrayDouble *coarseDA, const std
       }
     case 3:
       {
-        int kk(fineLocInCoarse[0].first+coarseSt[0]*fineLocInCoarse[1].first+coarseSt[0]*coarseSt[1]*fineLocInCoarse[2].first);
+        int kk(fineLocInCoarse[0].first+coarseSt[0]*fineLocInCoarse[1].first+coarseSt[0]*coarseSt[1]*fineLocInCoarse[2].first),fact2(facts[2]),fact1(facts[1]),fact0(facts[0]);
         for(int k=0;k<dims[2];k++)
           {
-            for(int kfact=0;kfact<fact;kfact++)
+            for(int kfact=0;kfact<fact2;kfact++)
               {
                 for(int j=0;j<dims[1];j++)
                   {
-                    for(int jfact=0;jfact<fact;jfact++)
+                    for(int jfact=0;jfact<fact1;jfact++)
                       {
                         for(int i=0;i<dims[0];i++)
                           {
                             double *loc(outPtr+(kk+i+j*coarseSt[0])*nbCompo);
-                            for(int ifact=0;ifact<fact;ifact++,inPtr+=nbCompo)
+                            for(int ifact=0;ifact<fact0;ifact++,inPtr+=nbCompo)
                               {
                                 if(kfact!=0 || jfact!=0 || ifact!=0)
                                   std::transform(inPtr,inPtr+nbCompo,loc,loc,std::plus<double>());
@@ -306,6 +352,105 @@ void MEDCouplingIMesh::CondenseFineToCoarse(DataArrayDouble *coarseDA, const std
   }
 }
 
+/*!
+ * This method spreads the values of coarse data \a coarseDA into \a fineDA.
+ *
+ * \param [in] coarseDA The DataArrayDouble corresponding to the a cell field of a coarse mesh whose cell structure is defined by \a coarseSt.
+ * \param [in] coarseSt The cell structure of coarse mesh.
+ * \param [in,out] fineDA The DataArray containing the cell field on uniformly refined mesh
+ * \param [in] fineLocInCoarse The cell localization of refined mesh into the coarse one.
+ * \param [in] facts The refinement coefficient per axis.
+ * \sa CondenseFineToCoarse
+ */
+void MEDCouplingIMesh::SpreadCoarseToFine(const DataArrayDouble *coarseDA, const std::vector<int>& coarseSt, DataArrayDouble *fineDA, const std::vector< std::pair<int,int> >& fineLocInCoarse, const std::vector<int>& facts)
+{
+  if(!coarseDA || !coarseDA->isAllocated() || !fineDA || !fineDA->isAllocated())
+    throw INTERP_KERNEL::Exception("MEDCouplingIMesh::SpreadCoarseToFine : the parameters 1 or 3 are NULL or not allocated !");
+  int meshDim((int)coarseSt.size()),nbOfTuplesInCoarseExp(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(coarseSt)),nbOfTuplesInFineExp(MEDCouplingStructuredMesh::DeduceNumberOfGivenRangeInCompactFrmt(fineLocInCoarse));
+  int nbCompo(fineDA->getNumberOfComponents());
+  if(coarseDA->getNumberOfComponents()!=nbCompo)
+    throw INTERP_KERNEL::Exception("MEDCouplingIMesh::SpreadCoarseToFine : the number of components of fine DA and coarse one mismatches !");
+  if(meshDim!=(int)fineLocInCoarse.size() || meshDim!=(int)facts.size())
+    throw INTERP_KERNEL::Exception("MEDCouplingIMesh::SpreadCoarseToFine : the size of fineLocInCoarse (4th param) and facts (5th param) must be equal to the sier of coarseSt (2nd param) !");
+  if(coarseDA->getNumberOfTuples()!=nbOfTuplesInCoarseExp)
+    {
+      std::ostringstream oss; oss << "MEDCouplingIMesh::SpreadCoarseToFine : Expecting " << nbOfTuplesInCoarseExp << " tuples having " << coarseDA->getNumberOfTuples() << " !";
+      throw INTERP_KERNEL::Exception(oss.str().c_str());
+    }
+  int nbTuplesFine(fineDA->getNumberOfTuples());
+  if(nbTuplesFine%nbOfTuplesInFineExp!=0)
+    throw INTERP_KERNEL::Exception("MEDCouplingIMesh::SpreadCoarseToFine : Invalid nb of tuples in fine DataArray regarding its structure !");
+  int fact(std::accumulate(facts.begin(),facts.end(),1,std::multiplies<int>()));
+  if(nbTuplesFine!=fact*nbOfTuplesInFineExp)
+    {
+      std::ostringstream oss; oss << "MEDCouplingIMesh::SpreadCoarseToFine : Invalid number of tuples ("  << nbTuplesFine << ") of fine dataarray is invalid ! Must be " << fact*nbOfTuplesInFineExp << "!";
+      throw INTERP_KERNEL::Exception(oss.str().c_str());
+    }
+  // to improve use jump-iterator. Factorizes with SwitchOnIdsFrom BuildExplicitIdsFrom
+  double *outPtr(fineDA->getPointer());
+  const double *inPtr(coarseDA->begin());
+  //
+  std::vector<int> dims(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(fineLocInCoarse));
+  switch(meshDim)
+  {
+    case 1:
+      {
+        int offset(fineLocInCoarse[0].first),fact0(facts[0]);
+        for(int i=0;i<dims[0];i++)
+          {
+            const double *loc(inPtr+(offset+i)*nbCompo);
+            for(int ifact=0;ifact<fact0;ifact++)
+              outPtr=std::copy(loc,loc+nbCompo,outPtr);
+          }
+        break;
+      }
+    case 2:
+      {
+        int kk(fineLocInCoarse[0].first+coarseSt[0]*fineLocInCoarse[1].first),fact0(facts[0]),fact1(facts[1]);
+        for(int j=0;j<dims[1];j++)
+          {
+            for(int jfact=0;jfact<fact1;jfact++)
+              {
+                for(int i=0;i<dims[0];i++)
+                  {
+                    const double *loc(inPtr+(kk+i)*nbCompo);
+                    for(int ifact=0;ifact<fact0;ifact++)
+                      outPtr=std::copy(loc,loc+nbCompo,outPtr);
+                  }
+              }
+            kk+=coarseSt[0];
+          }
+        break;
+      }
+    case 3:
+      {
+        int kk(fineLocInCoarse[0].first+coarseSt[0]*fineLocInCoarse[1].first+coarseSt[0]*coarseSt[1]*fineLocInCoarse[2].first),fact0(facts[0]),fact1(facts[2]),fact2(facts[2]);
+        for(int k=0;k<dims[2];k++)
+          {
+            for(int kfact=0;kfact<fact2;kfact++)
+              {
+                for(int j=0;j<dims[1];j++)
+                  {
+                    for(int jfact=0;jfact<fact1;jfact++)
+                      {
+                        for(int i=0;i<dims[0];i++)
+                          {
+                            const double *loc(inPtr+(kk+i+j*coarseSt[0])*nbCompo);
+                            for(int ifact=0;ifact<fact0;ifact++)
+                              outPtr=std::copy(loc,loc+nbCompo,outPtr);
+                          }
+                      }
+                  }
+              }
+            kk+=coarseSt[0]*coarseSt[1];
+          }
+        break;
+      }
+    default:
+      throw INTERP_KERNEL::Exception("MEDCouplingIMesh::SpreadCoarseToFine : only dimensions 1, 2 and 3 supported !");
+  }
+}
+
 void MEDCouplingIMesh::setSpaceDimension(int spaceDim)
 {
   if(spaceDim==_space_dim)