Salome HOME
Spread and condense on cell fields on images meshes with ghost management in 1D and 2D.
authorgeay <anthony.geay@cea.fr>
Fri, 23 May 2014 16:48:05 +0000 (18:48 +0200)
committergeay <anthony.geay@cea.fr>
Fri, 23 May 2014 16:48:05 +0000 (18:48 +0200)
src/MEDCoupling/MEDCouplingCartesianAMRMesh.cxx
src/MEDCoupling/MEDCouplingCartesianAMRMesh.hxx
src/MEDCoupling/MEDCouplingIMesh.cxx
src/MEDCoupling/MEDCouplingIMesh.hxx
src/MEDCoupling/MEDCouplingMemArray.cxx
src/MEDCoupling/MEDCouplingMemArray.hxx
src/MEDCoupling_Swig/MEDCouplingBasicsTest.py
src/MEDCoupling_Swig/MEDCouplingCommon.i
src/MEDCoupling_Swig/MEDCouplingRemapperTest.py

index 9436290c9a2bcc955938d9444387f68259403b41..fd2fde3848cb87b75d9a37dafb12f922f927ae08 100644 (file)
@@ -35,9 +35,8 @@ using namespace ParaMEDMEM;
  * \param [in] mesh not null pointer of refined mesh replacing the cell range of \a father defined by the bottom left and top right just after.
  * \param [in] bottomLeftTopRight a vector equal to the space dimension of \a mesh that specifies for each dimension, the included cell start of the range for the first element of the pair,
  *                                a the end cell (\b excluded) of the range for the second element of the pair.
- * \param [in] factors The refinement per axis relative to the father of \a this.
  */
-MEDCouplingCartesianAMRPatch::MEDCouplingCartesianAMRPatch(MEDCouplingCartesianAMRMesh *mesh, const std::vector< std::pair<int,int> >& bottomLeftTopRight, const std::vector<int>& factors)
+MEDCouplingCartesianAMRPatch::MEDCouplingCartesianAMRPatch(MEDCouplingCartesianAMRMesh *mesh, const std::vector< std::pair<int,int> >& bottomLeftTopRight)
 {
   if(!mesh)
     throw INTERP_KERNEL::Exception("EDCouplingCartesianAMRPatch constructor : input mesh is NULL !");
@@ -46,9 +45,6 @@ MEDCouplingCartesianAMRPatch::MEDCouplingCartesianAMRPatch(MEDCouplingCartesianA
   if(dim!=dimExp)
     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch constructor : space dimension of father and input bottomLeft/topRight size mismatches !");
   _bl_tr=bottomLeftTopRight;
-  if((int)factors.size()!=dimExp)
-    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch constructor : space dimension of father and input factors per axis size mismatches !");
-  _factors=factors;
 }
 
 int MEDCouplingCartesianAMRPatch::getNumberOfCellsRecursiveWithOverlap() const
@@ -105,6 +101,22 @@ int MEDCouplingCartesianAMRMesh::getSpaceDimension() const
   return _mesh->getSpaceDimension();
 }
 
+void MEDCouplingCartesianAMRMesh::setFactors(const std::vector<int>& newFactors)
+{
+  if(getSpaceDimension()!=(int)newFactors.size())
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::setFactors : size of input factors is not equal to the space dimension !");
+  if(_factors.empty())
+    {
+      _factors=newFactors;
+      return ;
+    }
+  if(_factors==newFactors)
+    return ;
+  if(!_patches.empty())
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::setFactors : modification of factors is not allowed when presence of patches !");
+  _factors=newFactors;
+}
+
 int MEDCouplingCartesianAMRMesh::getMaxNumberOfLevelsRelativeToThis() const
 {
   int ret(1);
@@ -160,14 +172,15 @@ void MEDCouplingCartesianAMRMesh::detachFromFather()
 /*!
  * \param [in] bottomLeftTopRight a vector equal to the space dimension of \a mesh that specifies for each dimension, the included cell start of the range for the first element of the pair,
  *                                a the end cell (\b excluded) of the range for the second element of the pair.
- * \param [in] factors The != 0 factor of refinement per axis.
+ * \param [in] factors The factor of refinement per axis (different from 0).
  */
 void MEDCouplingCartesianAMRMesh::addPatch(const std::vector< std::pair<int,int> >& bottomLeftTopRight, const std::vector<int>& factors)
 {
+  checkFactorsAndIfNotSetAssign(factors);
   MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> mesh(static_cast<MEDCouplingIMesh *>(_mesh->buildStructuredSubPart(bottomLeftTopRight)));
   mesh->refineWithFactor(factors);
   MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRMesh> zeMesh(new MEDCouplingCartesianAMRMesh(this,mesh));
-  MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> elt(new MEDCouplingCartesianAMRPatch(zeMesh,bottomLeftTopRight,factors));
+  MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> elt(new MEDCouplingCartesianAMRPatch(zeMesh,bottomLeftTopRight));
   _patches.push_back(elt);
 }
 
@@ -330,7 +343,7 @@ void FindInflection(const INTERP_KERNEL::BoxSplittingOptions& bso, const Interna
       // Gradient absolute value
       for ( unsigned int i=1;i<derivate_second_order.size();i++)
         gradient_absolute.push_back(fabs(derivate_second_order[i]-derivate_second_order[i-1])) ;
-      if(derivate_second_order.empty())//tony -> si empty le reste plante !
+      if(derivate_second_order.empty())
         continue;
       for (unsigned int i=0;i<derivate_second_order.size()-1;i++)
         {
@@ -444,21 +457,17 @@ void DealWithCut(const InternalPatch *patchToBeSplit, int axisId, int cutPlace,
 /*!
  * This method creates patches in \a this (by destroying the patches if any). This method uses \a criterion array as a field on cells on this level.
  */
-void MEDCouplingCartesianAMRMesh::createPatchesFromCriterion(const INTERP_KERNEL::BoxSplittingOptions& bso, const DataArrayByte *criterion, const std::vector<int>& factors)
+void MEDCouplingCartesianAMRMesh::createPatchesFromCriterion(const INTERP_KERNEL::BoxSplittingOptions& bso, const std::vector<bool>& criterion, const std::vector<int>& factors)
 {
-  if(!criterion || !criterion->isAllocated())
-    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createPatchesFromCriterion : the criterion DataArrayByte instance must be allocated and not NULL !");
   int nbCells(getNumberOfCellsAtCurrentLevel());
-  if(nbCells!=criterion->getNumberOfTuples())
+  if(nbCells!=(int)criterion.size())
     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createPatchesFromCriterion : the number of tuples of criterion array must be equal to the number of cells at the current level !");
   _patches.clear();
-  //
   std::vector<int> cgs(_mesh->getCellGridStructure());
-  std::vector<bool> crit(criterion->toVectorOfBool());//check that criterion has one component.
   std::vector< MEDCouplingAutoRefCountObjectPtr<InternalPatch> > listOfPatches,listOfPatchesOK;
   //
   MEDCouplingAutoRefCountObjectPtr<InternalPatch> p(new InternalPatch);
-  p->setNumberOfTrue(MEDCouplingStructuredMesh::FindMinimalPartOf(cgs,crit,p->getCriterion(),p->getPart()));
+  p->setNumberOfTrue(MEDCouplingStructuredMesh::FindMinimalPartOf(cgs,criterion,p->getCriterion(),p->getPart()));
   if(p->presenceOfTrue())
     listOfPatches.push_back(p);
   while(!listOfPatches.empty())
@@ -489,6 +498,23 @@ void MEDCouplingCartesianAMRMesh::createPatchesFromCriterion(const INTERP_KERNEL
     addPatch((*it)->getConstPart(),factors);
 }
 
+/*!
+ * This method creates patches in \a this (by destroying the patches if any). This method uses \a criterion array as a field on cells on this level.
+ */
+void MEDCouplingCartesianAMRMesh::createPatchesFromCriterion(const INTERP_KERNEL::BoxSplittingOptions& bso, const DataArrayByte *criterion, const std::vector<int>& factors)
+{
+  if(!criterion || !criterion->isAllocated())
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createPatchesFromCriterion : the criterion DataArrayByte instance must be allocated and not NULL !");
+  std::vector<bool> crit(criterion->toVectorOfBool());//check that criterion has one component.
+  createPatchesFromCriterion(bso,crit,factors);
+}
+
+void MEDCouplingCartesianAMRMesh::removeAllPatches()
+{
+  _patches.clear();
+  declareAsNew();
+}
+
 void MEDCouplingCartesianAMRMesh::removePatch(int patchId)
 {
   checkPatchId(patchId);
@@ -513,6 +539,67 @@ const MEDCouplingCartesianAMRPatch *MEDCouplingCartesianAMRMesh::getPatch(int pa
   return _patches[patchId];
 }
 
+/*!
+ * This method creates a new cell field array on given \a patchId patch in \a this starting from a coarse cell field on \a this \a cellFieldOnThis.
+ * This method can be seen as a fast projection from the cell field \a cellFieldOnThis on \c this->getImageMesh() to a refined part of \a this
+ * defined by the patch with id \a patchId.
+ *
+ * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
+ * \param [in] cellFieldOnThis - The array of the cell field on \c this->getImageMesh() to be projected to patch having id \a patchId.
+ * \return DataArrayDouble * - The array of the cell field on the requested patch
+ *
+ * \throw if \a patchId is not in [ 0 , \c this->getNumberOfPatches() )
+ * \throw if \a cellFieldOnThis is NULL or not allocated
+ * \sa fillCellFieldOnPatch, MEDCouplingIMesh::SpreadCoarseToFine
+ */
+DataArrayDouble *MEDCouplingCartesianAMRMesh::createCellFieldOnPatch(int patchId, const DataArrayDouble *cellFieldOnThis) const
+{
+  if(!cellFieldOnThis || !cellFieldOnThis->isAllocated())
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createCellFieldOnPatch : the input cell field array is NULL or not allocated !");
+  const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
+  const MEDCouplingIMesh *fine(patch->getMesh()->getImageMesh());
+  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(fine->getNumberOfCells(),cellFieldOnThis->getNumberOfComponents());
+  ret->copyStringInfoFrom(*cellFieldOnThis);
+  MEDCouplingIMesh::SpreadCoarseToFine(cellFieldOnThis,_mesh->getCellGridStructure(),ret,patch->getBLTRRange(),getFactors());
+  return ret.retn();
+}
+
+/*!
+ * This method is equivalent to MEDCouplingCartesianAMRMesh::createCellFieldOnPatch except that here instead of
+ *
+ * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
+ * \param [in] cellFieldOnThis - The array of the cell field on \c this->getImageMesh() to be projected to patch having id \a patchId.
+ * \param [in,out] cellFieldOnPatch - The array of the cell field on the requested patch to be filled.
+ *
+ * \sa createCellFieldOnPatch, fillCellFieldComingFromPatch
+ */
+void MEDCouplingCartesianAMRMesh::fillCellFieldOnPatch(int patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch) const
+{
+  if(!cellFieldOnThis || !cellFieldOnThis->isAllocated())
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createCellFieldOnPatch : the input cell field array is NULL or not allocated !");
+  const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
+  MEDCouplingIMesh::SpreadCoarseToFine(cellFieldOnThis,_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors());
+}
+
+/*!
+ * This method updates \a cellFieldOnThis part of values coming from the cell field \a cellFieldOnPatch lying on patch having id \a patchId.
+ *
+ * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
+ * \param [in] cellFieldOnPatch - The array of the cell field on patch with id \a patchId.
+ * \param [in,out] cellFieldOnThis The array of the cell field on \a this to be updated only on the part concerning the patch with id \a patchId.
+ *
+ * \throw if \a patchId is not in [ 0 , \c this->getNumberOfPatches() )
+ * \throw if \a cellFieldOnPatch is NULL or not allocated
+ * \sa createCellFieldOnPatch, MEDCouplingIMesh::CondenseFineToCoarse
+ */
+void MEDCouplingCartesianAMRMesh::fillCellFieldComingFromPatch(int patchId, const DataArrayDouble *cellFieldOnPatch, DataArrayDouble *cellFieldOnThis) const
+{
+  if(!cellFieldOnPatch || !cellFieldOnPatch->isAllocated())
+      throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::fillCellFieldComingFromPatch : the input cell field array is NULL or not allocated !");
+  const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
+  MEDCouplingIMesh::CondenseFineToCoarse(_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors(),cellFieldOnThis);
+}
+
 MEDCouplingUMesh *MEDCouplingCartesianAMRMesh::buildUnstructured() const
 {
   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> part(_mesh->buildUnstructured());
@@ -582,6 +669,21 @@ void MEDCouplingCartesianAMRMesh::checkPatchId(int patchId) const
     }
 }
 
+void MEDCouplingCartesianAMRMesh::checkFactorsAndIfNotSetAssign(const std::vector<int>& factors)
+{
+  if(getSpaceDimension()!=(int)factors.size())
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::checkFactorsAndIfNotSetAssign : invalid size of factors ! size must be equal to the spaceDimension !");
+  if(_factors.empty())
+    {
+      _factors=factors;
+    }
+  else
+    {
+      if(_factors!=factors)
+        throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::checkFactorsAndIfNotSetAssign : the factors ");
+    }
+}
+
 std::size_t MEDCouplingCartesianAMRMesh::getHeapMemorySizeWithoutChildren() const
 {
   return sizeof(MEDCouplingCartesianAMRMesh);
index d0ab4a4218040e35843e68f3c394648682e66659..bfade9b4fde406d2945e717ced1438ff9081946b 100644 (file)
@@ -34,6 +34,7 @@ namespace ParaMEDMEM
   class MEDCouplingIMesh;
   class MEDCouplingUMesh;
   class DataArrayByte;
+  class DataArrayDouble;
   class MEDCoupling1SGTUMesh;
   class MEDCouplingCartesianAMRMesh;
 
@@ -41,7 +42,7 @@ namespace ParaMEDMEM
   class MEDCouplingCartesianAMRPatch : public RefCountObject
   {
   public:
-    MEDCouplingCartesianAMRPatch(MEDCouplingCartesianAMRMesh *mesh, const std::vector< std::pair<int,int> >& bottomLeftTopRight, const std::vector<int>& factors);
+    MEDCouplingCartesianAMRPatch(MEDCouplingCartesianAMRMesh *mesh, const std::vector< std::pair<int,int> >& bottomLeftTopRight);
     // direct forward to _mesh
     MEDCOUPLING_EXPORT int getNumberOfCellsRecursiveWithOverlap() const;
     MEDCOUPLING_EXPORT int getNumberOfCellsRecursiveWithoutOverlap() const;
@@ -58,7 +59,6 @@ namespace ParaMEDMEM
   private:
     //! bottom left/top right cell range relative to \a _father
     std::vector< std::pair<int,int> > _bl_tr;
-    std::vector<int> _factors;
     MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRMesh> _mesh;
   };
   /// @endcond
@@ -74,6 +74,8 @@ namespace ParaMEDMEM
     MEDCOUPLING_EXPORT static MEDCouplingCartesianAMRMesh *New(const std::string& meshName, int spaceDim, const int *nodeStrctStart, const int *nodeStrctStop,
                                                                const double *originStart, const double *originStop, const double *dxyzStart, const double *dxyzStop);
     MEDCOUPLING_EXPORT int getSpaceDimension() const;
+    MEDCOUPLING_EXPORT const std::vector<int>& getFactors() const { return _factors; }
+    MEDCOUPLING_EXPORT void setFactors(const std::vector<int>& newFactors);
     MEDCOUPLING_EXPORT int getMaxNumberOfLevelsRelativeToThis() const;
     MEDCOUPLING_EXPORT int getNumberOfCellsAtCurrentLevel() const;
     MEDCOUPLING_EXPORT int getNumberOfCellsRecursiveWithOverlap() const;
@@ -84,10 +86,15 @@ namespace ParaMEDMEM
     MEDCOUPLING_EXPORT const MEDCouplingCartesianAMRMesh *getGodFather() const;
     MEDCOUPLING_EXPORT void detachFromFather();
     MEDCOUPLING_EXPORT void addPatch(const std::vector< std::pair<int,int> >& bottomLeftTopRight, const std::vector<int>& factors);
+    MEDCOUPLING_EXPORT void createPatchesFromCriterion(const INTERP_KERNEL::BoxSplittingOptions& bso, const std::vector<bool>& criterion, const std::vector<int>& factors);
     MEDCOUPLING_EXPORT void createPatchesFromCriterion(const INTERP_KERNEL::BoxSplittingOptions& bso, const DataArrayByte *criterion, const std::vector<int>& factors);
+    MEDCOUPLING_EXPORT void removeAllPatches();
     MEDCOUPLING_EXPORT void removePatch(int patchId);
     MEDCOUPLING_EXPORT int getNumberOfPatches() const;
     MEDCOUPLING_EXPORT const MEDCouplingCartesianAMRPatch *getPatch(int patchId) const;
+    MEDCOUPLING_EXPORT DataArrayDouble *createCellFieldOnPatch(int patchId, const DataArrayDouble *cellFieldOnThis) const;
+    MEDCOUPLING_EXPORT void fillCellFieldOnPatch(int patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch) const;
+    MEDCOUPLING_EXPORT void fillCellFieldComingFromPatch(int patchId, const DataArrayDouble *cellFieldOnPatch, DataArrayDouble *cellFieldOnThis) const;
     //
     MEDCOUPLING_EXPORT MEDCouplingUMesh *buildUnstructured() const;
     MEDCOUPLING_EXPORT MEDCoupling1SGTUMesh *buildMeshFromPatchEnvelop() const;
@@ -96,6 +103,7 @@ namespace ParaMEDMEM
                                 const double *originStart, const double *originStop, const double *dxyzStart, const double *dxyzStop);
     MEDCouplingCartesianAMRMesh(MEDCouplingCartesianAMRMesh *father, MEDCouplingIMesh *mesh);
     void checkPatchId(int patchId) const;
+    void checkFactorsAndIfNotSetAssign(const std::vector<int>& factors);
   protected:
     MEDCOUPLING_EXPORT std::size_t getHeapMemorySizeWithoutChildren() const;
     MEDCOUPLING_EXPORT std::vector<const BigMemoryObject *> getDirectChildren() const;
@@ -104,6 +112,7 @@ namespace ParaMEDMEM
     MEDCouplingCartesianAMRMesh *_father;
     MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> _mesh;
     std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> > _patches;
+    std::vector<int> _factors;
   };
 }
 
index 4b3da324ab9f5517c144cb0c4662e9782c073bbd..30458429b83f5c11cd7083d2a782ad04add04ecd 100644 (file)
@@ -75,6 +75,33 @@ MEDCouplingIMesh *MEDCouplingIMesh::clone(bool recDeepCpy) const
   return new MEDCouplingIMesh(*this,recDeepCpy);
 }
 
+/*!
+ * This method creates a copy of \a this enlarged by \a ghostLev cells on each axis.
+ * If \a ghostLev equal to 0 this method behaves as MEDCouplingIMesh::clone.
+ *
+ * \param [in] ghostLev - the ghost level expected
+ * \return MEDCouplingIMesh * - a newly alloacted object to be managed by the caller.
+ * \throw if \a ghostLev < 0.
+ */
+MEDCouplingIMesh *MEDCouplingIMesh::buildWithGhost(int ghostLev) const
+{
+  if(ghostLev<0)
+    throw INTERP_KERNEL::Exception("MEDCouplingIMesh::buildWithGhost : the ghostLev must be >= 0 !");
+  checkCoherency();
+  int spaceDim(getSpaceDimension());
+  double origin[3],dxyz[3];
+  int structure[3];
+  for(int i=0;i<spaceDim;i++)
+    {
+      origin[i]=_origin[i]-ghostLev*_dxyz[i];
+      dxyz[i]=_dxyz[i];
+      structure[i]=_structure[i]+2*ghostLev;
+    }
+  MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> ret(MEDCouplingIMesh::New(getName(),spaceDim,structure,structure+spaceDim,origin,origin+spaceDim,dxyz,dxyz+spaceDim));
+  ret->copyTinyInfoFrom(this);
+  return ret.retn();
+}
+
 void MEDCouplingIMesh::setNodeStruct(const int *nodeStrctStart, const int *nodeStrctStop)
 {
   checkSpaceDimension();
@@ -241,14 +268,15 @@ MEDCouplingIMesh *MEDCouplingIMesh::asSingleCell() const
  * to a coarse MEDCouplingIMesh instance. So this method can be seen as a specialization in P0P0 conservative interpolation non overlaping from fine image mesh
  * to a coarse image mesh. Only tuples ( deduced from \a fineLocInCoarse ) of \a coarseDA will be modified. Other tuples of \a coarseDA will be let unchanged.
  *
- * \param [in,out] 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] 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
+ * \param [in,out] coarseDA The DataArrayDouble corresponding to the a cell field of a coarse mesh whose cell structure is defined by \a coarseSt.
+ *
+ * \sa CondenseFineToCoarseGhost,SpreadCoarseToFine
  */
-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)
+void MEDCouplingIMesh::CondenseFineToCoarse(const std::vector<int>& coarseSt, const DataArrayDouble *fineDA, const std::vector< std::pair<int,int> >& fineLocInCoarse, const std::vector<int>& facts, DataArrayDouble *coarseDA)
 {
   if(!coarseDA || !coarseDA->isAllocated() || !fineDA || !fineDA->isAllocated())
     throw INTERP_KERNEL::Exception("MEDCouplingIMesh::CondenseFineToCoarse : the parameters 1 or 3 are NULL or not allocated !");
@@ -352,6 +380,102 @@ void MEDCouplingIMesh::CondenseFineToCoarse(DataArrayDouble *coarseDA, const std
   }
 }
 
+/*!
+ * 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
+ * to a coarse image mesh. Only tuples ( deduced from \a fineLocInCoarse ) of \a coarseDA will be modified. Other tuples of \a coarseDA will be let unchanged.
+ *
+ * \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.
+ * \param [in,out] coarseDA The DataArrayDouble corresponding to the a cell field of a coarse mesh whose cell structure is defined by \a coarseSt.
+ * \param [in] ghostSize - The size of the ghost zone. The ghost zone is expected to be the same for all axis and both for coarse and fine meshes.
+ *
+ * \sa CondenseFineToCoarse,SpreadCoarseToFineGhost
+ */
+void MEDCouplingIMesh::CondenseFineToCoarseGhost(const std::vector<int>& coarseSt, const DataArrayDouble *fineDA, const std::vector< std::pair<int,int> >& fineLocInCoarse, const std::vector<int>& facts, DataArrayDouble *coarseDA, int ghostSize)
+{
+  if(ghostSize<0)
+    throw INTERP_KERNEL::Exception("MEDCouplingIMesh::CondenseFineToCoarseGhost : ghost level >= 0 !");
+  if(!coarseDA || !coarseDA->isAllocated() || !fineDA || !fineDA->isAllocated())
+    throw INTERP_KERNEL::Exception("MEDCouplingIMesh::CondenseFineToCoarseGhost : the parameters 1 or 3 are NULL or not allocated !");
+  std::vector<int> coarseStG(coarseSt.size()); std::transform(coarseSt.begin(),coarseSt.end(),coarseStG.begin(),std::bind2nd(std::plus<int>(),2*ghostSize));
+  //std::vector<int> fineStG(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(fineLocInCoarse));
+  //std::transform(fineStG.begin(),fineStG.end(),fineStG.begin(),std::bind2nd(std::plus<int>(),2*ghostSize));
+  int meshDim((int)coarseSt.size()),nbOfTuplesInCoarseExp(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(coarseStG));
+  int nbCompo(fineDA->getNumberOfComponents());
+  if(coarseDA->getNumberOfComponents()!=nbCompo)
+    throw INTERP_KERNEL::Exception("MEDCouplingIMesh::CondenseFineToCoarseGhost : 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::CondenseFineToCoarseGhost : 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::CondenseFineToCoarseGhost : Expecting " << nbOfTuplesInCoarseExp << " tuples having " << coarseDA->getNumberOfTuples() << " !";
+      throw INTERP_KERNEL::Exception(oss.str().c_str());
+    }
+  //int nbTuplesFine(fineDA->getNumberOfTuples());
+  //int fact(std::accumulate(facts.begin(),facts.end(),1,std::multiplies<int>()));
+  /*if(nbTuplesFine!=fact*nbOfTuplesInFineExp)
+    {
+      std::ostringstream oss; oss << "MEDCouplingIMesh::CondenseFineToCoarseGhost : Invalid number of tuples ("  << nbTuplesFine << ") of fine dataarray is invalid ! Must be " << fact*nbOfTuplesInFineExp << "!";
+      throw INTERP_KERNEL::Exception(oss.str().c_str());
+    }*/
+  double *outPtr(coarseDA->getPointer());
+  const double *inPtr(fineDA->begin());
+  //
+  std::vector<int> dims(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(fineLocInCoarse));
+  switch(meshDim)
+  {
+    case 1:
+      {
+        int offset(fineLocInCoarse[0].first+ghostSize),fact0(facts[0]);
+        inPtr+=ghostSize*nbCompo;
+        for(int i=0;i<dims[0];i++)
+          {
+            double *loc(outPtr+(offset+i)*nbCompo);
+            for(int ifact=0;ifact<fact0;ifact++,inPtr+=nbCompo)
+              {
+                if(ifact!=0)
+                  std::transform(inPtr,inPtr+nbCompo,loc,loc,std::plus<double>());
+                else
+                  std::copy(inPtr,inPtr+nbCompo,loc);
+              }
+          }
+        break;
+      }
+    case 2:
+      {
+        int nxwg(coarseSt[0]+2*ghostSize);
+        int kk(fineLocInCoarse[0].first+ghostSize+nxwg*(fineLocInCoarse[1].first+ghostSize)),fact1(facts[1]),fact0(facts[0]);
+        inPtr+=(dims[0]*fact0+2*ghostSize)*nbCompo;
+        for(int j=0;j<dims[1];j++)
+          {
+             for(int jfact=0;jfact<fact1;jfact++)
+              {
+                inPtr+=ghostSize*nbCompo;
+                for(int i=0;i<dims[0];i++)
+                  {
+                    double *loc(outPtr+(kk+i)*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>());
+                        else
+                          std::copy(inPtr,inPtr+nbCompo,loc);
+                      }
+                  }
+                inPtr+=ghostSize*nbCompo;
+              }
+            kk+=nxwg;
+          }
+        break;
+      }
+    default:
+      throw INTERP_KERNEL::Exception("MEDCouplingIMesh::CondenseFineToCoarseGhost : only dimensions 1, 2 supported !");
+  }
+}
+
 /*!
  * This method spreads the values of coarse data \a coarseDA into \a fineDA.
  *
@@ -360,7 +484,7 @@ void MEDCouplingIMesh::CondenseFineToCoarse(DataArrayDouble *coarseDA, const std
  * \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
+ * \sa SpreadCoarseToFineGhost, 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)
 {
@@ -451,6 +575,121 @@ void MEDCouplingIMesh::SpreadCoarseToFine(const DataArrayDouble *coarseDA, const
   }
 }
 
+/*!
+ * 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.
+ * \param [in] ghostSize - The size of the ghost zone. The ghost zone is expected to be the same for all axis and both for coarse and fine meshes.
+ * \sa CondenseFineToCoarse
+ */
+void MEDCouplingIMesh::SpreadCoarseToFineGhost(const DataArrayDouble *coarseDA, const std::vector<int>& coarseSt, DataArrayDouble *fineDA, const std::vector< std::pair<int,int> >& fineLocInCoarse, const std::vector<int>& facts, int ghostSize)
+{
+  if(ghostSize<0)
+    throw INTERP_KERNEL::Exception("MEDCouplingIMesh::SpreadCoarseToFineGhost : ghost level >= 0 !");
+  if(!coarseDA || !coarseDA->isAllocated() || !fineDA || !fineDA->isAllocated())
+    throw INTERP_KERNEL::Exception("MEDCouplingIMesh::SpreadCoarseToFineGhost : the parameters 1 or 3 are NULL or not allocated !");
+  std::vector<int> coarseStG(coarseSt.size()); std::transform(coarseSt.begin(),coarseSt.end(),coarseStG.begin(),std::bind2nd(std::plus<int>(),2*ghostSize));
+  //std::vector<int> fineStG(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(fineLocInCoarse)); std::transform(fineStG.begin(),fineStG.end(),fineStG.begin(),std::bind2nd(std::plus<int>(),2*ghostSize));
+  int meshDim((int)coarseSt.size()),nbOfTuplesInCoarseExp(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(coarseStG));
+  int nbCompo(fineDA->getNumberOfComponents());
+  if(coarseDA->getNumberOfComponents()!=nbCompo)
+    throw INTERP_KERNEL::Exception("MEDCouplingIMesh::SpreadCoarseToFineGhost : 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::SpreadCoarseToFineGhost : 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::SpreadCoarseToFineGhost : 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::SpreadCoarseToFineGhost : 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::SpreadCoarseToFineGhost : Invalid number of tuples ("  << nbTuplesFine << ") of fine dataarray is invalid ! Must be " << fact*nbOfTuplesInFineExp << "!";
+      throw INTERP_KERNEL::Exception(oss.str().c_str());
+    }*/
+  //
+  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+ghostSize-1),fact0(facts[0]);//offset is always >=0 thanks to the fact that ghostSize>=1 !
+        for(int i=0;i<ghostSize;i++)
+          outPtr=std::copy(inPtr+offset*nbCompo,inPtr+(offset+1)*nbCompo,outPtr);
+        offset=fineLocInCoarse[0].first+ghostSize;
+        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);
+          }
+        offset=fineLocInCoarse[0].second+ghostSize;
+        for(int i=0;i<ghostSize;i++)
+          outPtr=std::copy(inPtr+offset*nbCompo,inPtr+(offset+1)*nbCompo,outPtr);
+        break;
+      }
+    case 2:
+      {
+        int nxwg(coarseSt[0]+2*ghostSize),fact0(facts[0]),fact1(facts[1]);
+        int kk(fineLocInCoarse[0].first+ghostSize-1+nxwg*(fineLocInCoarse[1].first+ghostSize-1));//kk is always >=0 thanks to the fact that ghostSize>=1 !
+        for(int jg=0;jg<ghostSize;jg++)
+          {
+            for(int ig=0;ig<ghostSize;ig++)
+              outPtr=std::copy(inPtr+kk*nbCompo,inPtr+(kk+1)*nbCompo,outPtr);
+            int kk0(kk+1);
+            for(int ig=0;ig<dims[0];ig++,kk0++)
+              for(int ifact=0;ifact<fact0;ifact++)
+                outPtr=std::copy(inPtr+(kk0)*nbCompo,inPtr+(kk0+1)*nbCompo,outPtr);
+            for(int ik=0;ik<ghostSize;ik++)
+              outPtr=std::copy(inPtr+kk0*nbCompo,inPtr+(kk0+1)*nbCompo,outPtr);
+          }
+        for(int j=0;j<dims[1];j++)
+          {
+            kk=fineLocInCoarse[0].first-1+ghostSize+nxwg*(fineLocInCoarse[1].first+ghostSize+j);
+            for(int jfact=0;jfact<fact1;jfact++)
+              {
+                for(int ig=0;ig<ghostSize;ig++)
+                  outPtr=std::copy(inPtr+kk*nbCompo,inPtr+(kk+1)*nbCompo,outPtr);
+                int kk0(kk+1);
+                for(int i=0;i<dims[0];i++,kk0++)
+                  {
+                    const double *loc(inPtr+kk0*nbCompo);
+                    for(int ifact=0;ifact<fact0;ifact++)
+                      outPtr=std::copy(loc,loc+nbCompo,outPtr);
+                  }
+                for(int ig=0;ig<ghostSize;ig++)
+                  outPtr=std::copy(inPtr+kk0*nbCompo,inPtr+(kk0+1)*nbCompo,outPtr);
+              }
+          }
+        kk=fineLocInCoarse[0].first+ghostSize-1+nxwg*(fineLocInCoarse[1].second+ghostSize);
+        for(int jg=0;jg<ghostSize;jg++)
+          {
+            for(int ig=0;ig<ghostSize;ig++)
+              outPtr=std::copy(inPtr+kk*nbCompo,inPtr+(kk+1)*nbCompo,outPtr);
+            int kk0(kk+1);
+            for(int ig=0;ig<dims[0];ig++,kk0++)
+              for(int ifact=0;ifact<fact0;ifact++)
+                outPtr=std::copy(inPtr+(kk0)*nbCompo,inPtr+(kk0+1)*nbCompo,outPtr);
+            for(int ik=0;ik<ghostSize;ik++)
+              outPtr=std::copy(inPtr+kk0*nbCompo,inPtr+(kk0+1)*nbCompo,outPtr);
+          }
+        break;
+      }
+    default:
+      throw INTERP_KERNEL::Exception("MEDCouplingIMesh::SpreadCoarseToFineGhost : only dimensions 1, 2 supported !");
+  }
+}
+
 void MEDCouplingIMesh::setSpaceDimension(int spaceDim)
 {
   if(spaceDim==_space_dim)
index ad61412547ca6dafc0a87655b2d873d3140db260..f08cf7381f8562f700164bd6dd3264c998c183b8 100644 (file)
@@ -48,11 +48,14 @@ namespace ParaMEDMEM
     MEDCOUPLING_EXPORT MEDCouplingCMesh *convertToCartesian() const;
     MEDCOUPLING_EXPORT void refineWithFactor(const std::vector<int>& factors);
     MEDCOUPLING_EXPORT MEDCouplingIMesh *asSingleCell() const;
-    MEDCOUPLING_EXPORT static void CondenseFineToCoarse(DataArrayDouble *coarseDA, const std::vector<int>& coarseSt, const DataArrayDouble *fineDA, const std::vector< std::pair<int,int> >& fineLocInCoarse, const std::vector<int>& facts);
+    MEDCOUPLING_EXPORT static void CondenseFineToCoarse(const std::vector<int>& coarseSt, const DataArrayDouble *fineDA, const std::vector< std::pair<int,int> >& fineLocInCoarse, const std::vector<int>& facts, DataArrayDouble *coarseDA);
+    MEDCOUPLING_EXPORT static void CondenseFineToCoarseGhost(const std::vector<int>& coarseSt, const DataArrayDouble *fineDA, const std::vector< std::pair<int,int> >& fineLocInCoarse, const std::vector<int>& facts, DataArrayDouble *coarseDA, int ghostSize);
     MEDCOUPLING_EXPORT static void SpreadCoarseToFine(const DataArrayDouble *coarseDA, const std::vector<int>& coarseSt, DataArrayDouble *fineDA, const std::vector< std::pair<int,int> >& fineLocInCoarse, const std::vector<int>& facts);
+    MEDCOUPLING_EXPORT static void SpreadCoarseToFineGhost(const DataArrayDouble *coarseDA, const std::vector<int>& coarseSt, DataArrayDouble *fineDA, const std::vector< std::pair<int,int> >& fineLocInCoarse, const std::vector<int>& facts, int ghostSize);
     //
     MEDCOUPLING_EXPORT MEDCouplingMesh *deepCpy() const;
     MEDCOUPLING_EXPORT MEDCouplingIMesh *clone(bool recDeepCpy) const;
+    MEDCOUPLING_EXPORT MEDCouplingIMesh *buildWithGhost(int ghostLev) const;
     MEDCOUPLING_EXPORT void updateTime() const;
     MEDCOUPLING_EXPORT std::size_t getHeapMemorySizeWithoutChildren() const;
     MEDCOUPLING_EXPORT std::vector<const BigMemoryObject *> getDirectChildren() const;
index e2ccfd8ea87475e100b0ef6239ca624b5fd5b982..44a708d7cf31c9543516f4b9396a76ae46e03864 100644 (file)
@@ -5584,6 +5584,37 @@ void DataArrayDouble::powEqual(const DataArrayDouble *other)
   declareAsNew();
 }
 
+/*!
+ * This method is \b NOT wrapped into python because it can be useful only for performance reasons in C++ context.
+ * All values in \a this must be 0. or 1. within eps error. 0 means false, 1 means true.
+ * If an another value than 0 or 1 appear (within eps precision) an INTERP_KERNEL::Exception will be thrown.
+ *
+ * \throw if \a this is not allocated.
+ * \throw if \a this has not exactly one component.
+ */
+std::vector<bool> DataArrayDouble::toVectorOfBool(double eps) const
+{
+  checkAllocated();
+  if(getNumberOfComponents()!=1)
+    throw INTERP_KERNEL::Exception("DataArrayDouble::toVectorOfBool : must be applied on single component array !");
+  int nbt(getNumberOfTuples());
+  std::vector<bool> ret(nbt);
+  const double *pt(begin());
+  for(int i=0;i<nbt;i++)
+    {
+      if(fabs(pt[i])<eps)
+        ret[i]=false;
+      else if(fabs(pt[i]-1.)<eps)
+        ret[i]=true;
+      else
+        {
+          std::ostringstream oss; oss << "DataArrayDouble::toVectorOfBool : the tuple #" << i << " has value " << pt[i] << " is invalid ! must be 0. or 1. !";
+          throw INTERP_KERNEL::Exception(oss.str().c_str());
+        }
+    }
+  return ret;
+}
+
 /*!
  * Useless method for end user. Only for MPI/Corba/File serialsation for multi arrays class.
  * Server side.
index 7e01a1aaf2fb1aa343329dd41fa6edc1a782d3c4..e4b99ca15fa4b5e899350d0777f08df86e6eb8c3 100644 (file)
@@ -370,6 +370,7 @@ namespace ParaMEDMEM
     MEDCOUPLING_EXPORT void updateTime() const { }
     MEDCOUPLING_EXPORT MemArray<double>& accessToMemArray() { return _mem; }
     MEDCOUPLING_EXPORT const MemArray<double>& accessToMemArray() const { return _mem; }
+    MEDCOUPLING_EXPORT std::vector<bool> toVectorOfBool(double eps) const;
   public:
     MEDCOUPLING_EXPORT void getTinySerializationIntInformation(std::vector<int>& tinyInfo) const;
     MEDCOUPLING_EXPORT void getTinySerializationStrInformation(std::vector<std::string>& tinyInfo) const;
index 3a0d610bbc492de128c03d7183f576d36cea5336..f96bc4d480a0164254e8b22ec67a001c610237ca 100644 (file)
@@ -14953,26 +14953,26 @@ class MEDCouplingBasicsTest(unittest.TestCase):
         self.assertEqual(1,amr.getNumberOfPatches())
         self.assertEqual(2,amr.getMaxNumberOfLevelsRelativeToThis())
         self.assertEqual(2,amr.getSpaceDimension())
-        amr[0].addPatch([(2,3),(1,3)],[2,2])
+        amr[0].addPatch([(2,3),(1,3)],[3,2])
         self.assertEqual(amr[0].getBLTRRange(),[(1,2),(0,1)])
         self.assertEqual(4,amr.getNumberOfCellsAtCurrentLevel())
-        self.assertEqual(28,amr.getNumberOfCellsRecursiveWithOverlap())
-        self.assertEqual(25,amr.getNumberOfCellsRecursiveWithoutOverlap())
+        self.assertEqual(32,amr.getNumberOfCellsRecursiveWithOverlap())
+        self.assertEqual(29,amr.getNumberOfCellsRecursiveWithoutOverlap())
         self.assertEqual(1,amr.getNumberOfPatches())
         self.assertEqual(3,amr.getMaxNumberOfLevelsRelativeToThis())
         self.assertEqual(2,amr.getSpaceDimension())
-        amr[0].addPatch([(0,2),(3,4)],[3,3])
+        amr[0].addPatch([(0,2),(3,4)],[3,2])
         self.assertEqual(16,amr[0].getMesh().getNumberOfCellsAtCurrentLevel())
-        self.assertEqual(46,amr.getNumberOfCellsRecursiveWithOverlap())
-        self.assertEqual(41,amr.getNumberOfCellsRecursiveWithoutOverlap())
+        self.assertEqual(44,amr.getNumberOfCellsRecursiveWithOverlap())
+        self.assertEqual(39,amr.getNumberOfCellsRecursiveWithoutOverlap())
         self.assertEqual(2,amr[0].getMesh().getNumberOfPatches())
         self.assertEqual(3,amr.getMaxNumberOfLevelsRelativeToThis())
         self.assertEqual(2,amr.getSpaceDimension())
         del amr[0][1]
         self.assertEqual(amr[0].getBLTRRange(),[(1,2),(0,1)])
         self.assertEqual(4,amr.getNumberOfCellsAtCurrentLevel())
-        self.assertEqual(28,amr.getNumberOfCellsRecursiveWithOverlap())
-        self.assertEqual(25,amr.getNumberOfCellsRecursiveWithoutOverlap())
+        self.assertEqual(32,amr.getNumberOfCellsRecursiveWithOverlap())
+        self.assertEqual(29,amr.getNumberOfCellsRecursiveWithoutOverlap())
         self.assertEqual(1,amr.getNumberOfPatches())
         self.assertEqual(3,amr.getMaxNumberOfLevelsRelativeToThis())
         self.assertEqual(2,amr.getSpaceDimension())
@@ -15080,17 +15080,17 @@ class MEDCouplingBasicsTest(unittest.TestCase):
         """ Test condensation of fine IMesh instance into a coarse one, with a factor. See testRemapperAMR1 in MEDCouplingRemapperTest.py file to see how the expected value is obtained."""
         coarse=DataArrayDouble(35) ; coarse.iota(0) #X=5,Y=7
         fine=DataArrayDouble(3*2*4*4) ; fine.iota(0) #X=3,Y=2 refined by 4
-        MEDCouplingIMesh.CondenseFineToCoarse(coarse,[5,7],fine,[(1,4),(2,4)],[4,4])
+        MEDCouplingIMesh.CondenseFineToCoarse([5,7],fine,[(1,4),(2,4)],[4,4],coarse)
         self.assertTrue(coarse.isEqual(DataArrayDouble([0,1,2,3,4,5,6,7,8,9,10,312,376,440,14,15,1080,1144,1208,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34]),1e-12))
         # 3D
         coarse=DataArrayDouble(175) ; coarse.iota(0) #X=5,Y=7,Z=5
         fine=DataArrayDouble(3*2*3*4*4*4) ; fine.iota(0) #X=3,Y=2,Z=3 refined by 4
-        MEDCouplingIMesh.CondenseFineToCoarse(coarse,[5,7,5],fine,[(1,4),(2,4),(1,4)],[4,4,4])
+        MEDCouplingIMesh.CondenseFineToCoarse([5,7,5],fine,[(1,4),(2,4),(1,4)],[4,4,4],coarse)
         self.assertTrue(coarse.isEqual(DataArrayDouble([0.,1.,2.,3.,4.,5.,6.,7.,8.,9.,10.,11.,12.,13.,14.,15.,16.,17.,18.,19.,20.,21.,22.,23.,24.,25.,26.,27.,28.,29.,30.,31.,32.,33.,34.,35.,36.,37.,38.,39.,40.,41.,42.,43.,44.,45.,10464.,10720.,10976.,49.,50.,13536.,13792.,14048.,54.,55.,56.,57.,58.,59.,60.,61.,62.,63.,64.,65.,66.,67.,68.,69.,70.,71.,72.,73.,74.,75.,76.,77.,78.,79.,80.,35040.,35296.,35552.,84.,85.,38112.,38368.,38624.,89.,90.,91.,92.,93.,94.,95.,96.,97.,98.,99.,100.,101.,102.,103.,104.,105.,106.,107.,108.,109.,110.,111.,112.,113.,114.,115.,59616.,59872.,60128.,119.,120.,62688.,62944.,63200.,124.,125.,126.,127.,128.,129.,130.,131.,132.,133.,134.,135.,136.,137.,138.,139.,140.,141.,142.,143.,144.,145.,146.,147.,148.,149.,150.,151.,152.,153.,154.,155.,156.,157.,158.,159.,160.,161.,162.,163.,164.,165.,166.,167.,168.,169.,170.,171.,172.,173.,174.]),1e-12))
         # 1D
         coarse=DataArrayDouble(5) ; coarse.iota(0) #X=5
         fine=DataArrayDouble(3*4) ; fine.iota(0) #X=3 refined by 4
-        MEDCouplingIMesh.CondenseFineToCoarse(coarse,[5],fine,[(1,4)],[4])
+        MEDCouplingIMesh.CondenseFineToCoarse([5],fine,[(1,4)],[4],coarse)
         self.assertTrue(coarse.isEqual(DataArrayDouble([0,6,22,38,4]),1e-12))
         pass
 
@@ -15142,6 +15142,28 @@ class MEDCouplingBasicsTest(unittest.TestCase):
         self.assertTrue(m.getCoords().isEqualWithoutConsideringStr(DataArrayDouble([(0,0),(2,0),(0,2),(2,2)]),1e-12))
         pass
 
+    def testAMR5(self):
+        """ Idem testAMR3, test spread of coarse IMesh instance into a fine one, with a factor, but here ghost is used !"""
+        # 1D
+        coarse=DataArrayDouble(5+2) ; coarse.iota(-1) #X=5 with ghostLev=1
+        fine=DataArrayDouble(3*4+2) ; fine.iota(1000) #X=3 refined by 4 with ghostLev=1
+        MEDCouplingIMesh.SpreadCoarseToFineGhost(coarse,[5],fine,[(1,4)],[4],1)
+        self.assertTrue(fine.isEqual(DataArrayDouble([0,1,1,1,1,2,2,2,2,3,3,3,3,4]),1e-12))
+        coarse.iota(-1000)
+        MEDCouplingIMesh.CondenseFineToCoarseGhost([5],fine,[(1,4)],[4],coarse,1)
+        self.assertTrue(coarse.isEqual(DataArrayDouble([-1000.,-999.,4.,8.,12.,-995.,-994.]),1e-12))
+        # 2D
+        coarse=DataArrayDouble((5+2*1)*(7+2*1)) ; coarse.iota(0) #X=5,Y=7 with ghostLev=1
+        fine=DataArrayDouble((3*4+2*1)*(2*4+2*1)) ; fine.iota(1000) #X=3,Y=2 refined by 4
+        MEDCouplingIMesh.SpreadCoarseToFineGhost(coarse,[5,7],fine,[(1,4),(2,4)],[4,4],1)
+        self.assertTrue(fine.isEqual(DataArrayDouble([15.,16.,16.,16.,16.,17.,17.,17.,17.,18.,18.,18.,18.,19.,22.,23.,23.,23.,23.,24.,24.,24.,24.,25.,25.,25.,25.,26.,22.,23.,23.,23.,23.,24.,24.,24.,24.,25.,25.,25.,25.,26.,22.,23.,23.,23.,23.,24.,24.,24.,24.,25.,25.,25.,25.,26.,22.,23.,23.,23.,23.,24.,24.,24.,24.,25.,25.,25.,25.,26.,29.,30.,30.,30.,30.,31.,31.,31.,31.,32.,32.,32.,32.,33.,29.,30.,30.,30.,30.,31.,31.,31.,31.,32.,32.,32.,32.,33.,29.,30.,30.,30.,30.,31.,31.,31.,31.,32.,32.,32.,32.,33.,29.,30.,30.,30.,30.,31.,31.,31.,31.,32.,32.,32.,32.,33.,36.,37.,37.,37.,37.,38.,38.,38.,38.,39.,39.,39.,39.,40.]),1e-12))
+        f=MEDCouplingFieldDouble(ON_CELLS) ; f.setMesh(MEDCouplingIMesh("",2,DataArrayInt([8,10]),[0.,0.],DataArrayDouble((1.,1.)))) ; f.setArray(coarse) ; f.setName("tutu") ; f.checkCoherency() ; f.writeVTK("coarse.vti")
+        coarse.iota(-1000)
+        MEDCouplingIMesh.CondenseFineToCoarseGhost([5,7],fine,[(1,4),(2,4)],[4,4],coarse,1)
+        f=MEDCouplingFieldDouble(ON_CELLS) ; f.setMesh(MEDCouplingIMesh("",2,DataArrayInt([8,10]),[0.,0.],DataArrayDouble((1.,1.)))) ; f.setArray(coarse) ; f.setName("tutu") ; f.checkCoherency() ; f.writeVTK("coarse.vti")
+        self.assertTrue(coarse.isEqual(DataArrayDouble([-1000.,-999.,-998.,-997.,-996.,-995.,-994.,-993.,-992.,-991.,-990.,-989.,-988.,-987.,-986.,-985.,-984.,-983.,-982.,-981.,-980.,-979.,-978.,368.,384.,400.,-974.,-973.,-972.,-971.,480.,496.,512.,-967.,-966.,-965.,-964.,-963.,-962.,-961.,-960.,-959.,-958.,-957.,-956.,-955.,-954.,-953.,-952.,-951.,-950.,-949.,-948.,-947.,-946.,-945.,-944.,-943.,-942.,-941.,-940.,-939.,-938.]),1e-12))
+        pass
+
     def setUp(self):
         pass
     pass
index cc63077360b55453852d3b5c8dd7dd4c875f93f6..a6bc608f454748800fba118753f0c824f247a87c 100644 (file)
@@ -307,6 +307,7 @@ using namespace INTERP_KERNEL;
 %newobject ParaMEDMEM::MEDCouplingCMesh::getCoordsAt;
 %newobject ParaMEDMEM::MEDCouplingIMesh::New;
 %newobject ParaMEDMEM::MEDCouplingIMesh::asSingleCell;
+%newobject ParaMEDMEM::MEDCouplingIMesh::buildWithGhost;
 %newobject ParaMEDMEM::MEDCouplingIMesh::convertToCartesian;
 %newobject ParaMEDMEM::MEDCouplingCurveLinearMesh::New;
 %newobject ParaMEDMEM::MEDCouplingCurveLinearMesh::clone;
@@ -323,6 +324,7 @@ using namespace INTERP_KERNEL;
 %newobject ParaMEDMEM::MEDCouplingCartesianAMRMesh::getGodFather;
 %newobject ParaMEDMEM::MEDCouplingCartesianAMRMesh::getFather;
 %newobject ParaMEDMEM::MEDCouplingCartesianAMRMesh::getPatch;
+%newobject ParaMEDMEM::MEDCouplingCartesianAMRMesh::createCellFieldOnPatch;
 %newobject ParaMEDMEM::MEDCouplingCartesianAMRMesh::__getitem__;
 %newobject ParaMEDMEM::DenseMatrix::New;
 %newobject ParaMEDMEM::DenseMatrix::deepCpy;
@@ -3065,6 +3067,7 @@ namespace ParaMEDMEM
     MEDCouplingCMesh *convertToCartesian() const throw(INTERP_KERNEL::Exception);
     void refineWithFactor(const std::vector<int>& factors) throw(INTERP_KERNEL::Exception);
     MEDCouplingIMesh *asSingleCell() const throw(INTERP_KERNEL::Exception);
+    MEDCouplingIMesh *buildWithGhost(int ghostLev) const throw(INTERP_KERNEL::Exception);
     %extend
     {
       MEDCouplingIMesh()
@@ -3127,11 +3130,18 @@ namespace ParaMEDMEM
         self->setDXYZ(originPtr,originPtr+nbTuples);
       }
 
-      static void CondenseFineToCoarse(DataArrayDouble *coarseDA, const std::vector<int>& coarseSt, const DataArrayDouble *fineDA, PyObject *fineLocInCoarse, const std::vector<int>& facts) throw(INTERP_KERNEL::Exception)
+      static void CondenseFineToCoarse(const std::vector<int>& coarseSt, const DataArrayDouble *fineDA, PyObject *fineLocInCoarse, const std::vector<int>& facts, DataArrayDouble *coarseDA) throw(INTERP_KERNEL::Exception)
       {
         std::vector< std::pair<int,int> > inp;
         convertPyToVectorPairInt(fineLocInCoarse,inp);
-        MEDCouplingIMesh::CondenseFineToCoarse(coarseDA,coarseSt,fineDA,inp,facts);
+        MEDCouplingIMesh::CondenseFineToCoarse(coarseSt,fineDA,inp,facts,coarseDA);
+      }
+
+      static void CondenseFineToCoarseGhost(const std::vector<int>& coarseSt, const DataArrayDouble *fineDA, PyObject *fineLocInCoarse, const std::vector<int>& facts, DataArrayDouble *coarseDA, int ghostSize) throw(INTERP_KERNEL::Exception)
+      {
+        std::vector< std::pair<int,int> > inp;
+        convertPyToVectorPairInt(fineLocInCoarse,inp);
+        MEDCouplingIMesh::CondenseFineToCoarseGhost(coarseSt,fineDA,inp,facts,coarseDA,ghostSize);
       }
 
       static void SpreadCoarseToFine(const DataArrayDouble *coarseDA, const std::vector<int>& coarseSt, DataArrayDouble *fineDA, PyObject *fineLocInCoarse, const std::vector<int>& facts) throw(INTERP_KERNEL::Exception)
@@ -3141,6 +3151,13 @@ namespace ParaMEDMEM
         MEDCouplingIMesh::SpreadCoarseToFine(coarseDA,coarseSt,fineDA,inp,facts);
       }
 
+      static void SpreadCoarseToFineGhost(const DataArrayDouble *coarseDA, const std::vector<int>& coarseSt, DataArrayDouble *fineDA, PyObject *fineLocInCoarse, const std::vector<int>& facts, int ghostSize) throw(INTERP_KERNEL::Exception)
+      {
+        std::vector< std::pair<int,int> > inp;
+        convertPyToVectorPairInt(fineLocInCoarse,inp);
+        MEDCouplingIMesh::SpreadCoarseToFineGhost(coarseDA,coarseSt,fineDA,inp,facts,ghostSize);
+      }
+
       std::string __str__() const throw(INTERP_KERNEL::Exception)
       {
         return self->simpleRepr();
@@ -4750,6 +4767,8 @@ namespace ParaMEDMEM
   public:
     
     int getSpaceDimension() const throw(INTERP_KERNEL::Exception);
+    const std::vector<int>& getFactors() const throw(INTERP_KERNEL::Exception);
+    void setFactors(const std::vector<int>& newFactors) throw(INTERP_KERNEL::Exception);
     int getMaxNumberOfLevelsRelativeToThis() const throw(INTERP_KERNEL::Exception);
     int getNumberOfCellsAtCurrentLevel() const throw(INTERP_KERNEL::Exception);
     int getNumberOfCellsRecursiveWithOverlap() const throw(INTERP_KERNEL::Exception);
@@ -4758,9 +4777,13 @@ namespace ParaMEDMEM
     int getNumberOfPatches() const throw(INTERP_KERNEL::Exception);    
     MEDCouplingUMesh *buildUnstructured() const throw(INTERP_KERNEL::Exception);
     MEDCoupling1SGTUMesh *buildMeshFromPatchEnvelop() const throw(INTERP_KERNEL::Exception);
+    void removeAllPatches() throw(INTERP_KERNEL::Exception);
     void removePatch(int patchId) throw(INTERP_KERNEL::Exception);
     void detachFromFather() throw(INTERP_KERNEL::Exception);
     void createPatchesFromCriterion(const INTERP_KERNEL::BoxSplittingOptions& bso, const DataArrayByte *criterion, const std::vector<int>& factors) throw(INTERP_KERNEL::Exception);
+    DataArrayDouble *createCellFieldOnPatch(int patchId, const DataArrayDouble *cellFieldOnThis) const throw(INTERP_KERNEL::Exception);
+    void fillCellFieldOnPatch(int patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch) const throw(INTERP_KERNEL::Exception);
+    void fillCellFieldComingFromPatch(int patchId, const DataArrayDouble *cellFieldOnPatch, DataArrayDouble *cellFieldOnThis) const throw(INTERP_KERNEL::Exception);
     %extend
     {
       static MEDCouplingCartesianAMRMesh *New(const std::string& meshName, int spaceDim, PyObject *nodeStrct, PyObject *origin, PyObject *dxyz) throw(INTERP_KERNEL::Exception)
index 72f92c59ee7587d1995dfdf1eefa484d8dc6eb33..44b0f8bd399674ba33bb3df3185dee4b7b90e099 100644 (file)
@@ -765,7 +765,7 @@ class MEDCouplingBasicsTest(unittest.TestCase):
         """ This test is the origin of the ref values for MEDCouplingBasicsTest.testAMR2"""
         coarse=DataArrayDouble(35) ; coarse.iota(0) #X=5,Y=7
         fine=DataArrayDouble(3*2*4*4) ; fine.iota(0) #X=3,Y=2 refined by 4
-        MEDCouplingIMesh.CondenseFineToCoarse(coarse,[5,7],fine,[(1,4),(2,4)],[4,4])
+        MEDCouplingIMesh.CondenseFineToCoarse([5,7],fine,[(1,4),(2,4)],[4,4],coarse)
         #
         m=MEDCouplingCartesianAMRMesh("mesh",2,[6,8],[0.,0.],[1.,1.])
         trgMesh=m.buildUnstructured()