+void DealWithCut(double minPatchLgth, const InternalPatch *patchToBeSplit, int axisId, mcIdType cutPlace, std::vector<MCAuto<InternalPatch> >& listOfPatches)
+{
+ MCAuto<InternalPatch> leftPart,rightPart;
+ std::vector< std::pair<mcIdType,mcIdType> > rect(patchToBeSplit->getConstPart());
+ std::vector< std::pair<mcIdType,mcIdType> > leftRect(rect),rightRect(rect);
+ leftRect[axisId].second=cutPlace+1;
+ rightRect[axisId].first=cutPlace+1;
+ leftPart=patchToBeSplit->extractPart(leftRect);
+ rightPart=patchToBeSplit->extractPart(rightRect);
+ leftPart->zipToFitOnCriterion(ToIdType(minPatchLgth)); rightPart->zipToFitOnCriterion(ToIdType(minPatchLgth));
+ listOfPatches.push_back(leftPart);
+ listOfPatches.push_back(rightPart);
+}
+
+/// @endcond
+
+void MEDCouplingCartesianAMRMeshGen::removeAllPatches()
+{
+ _patches.clear();
+ declareAsNew();
+}
+
+void MEDCouplingCartesianAMRMeshGen::removePatch(mcIdType patchId)
+{
+ checkPatchId(patchId);
+ mcIdType sz(ToIdType(_patches.size())),j(0);
+ std::vector< MCAuto<MEDCouplingCartesianAMRPatch> > patches(sz-1);
+ for(mcIdType i=0;i<sz;i++)
+ if(i!=patchId)
+ patches[j++]=_patches[i];
+ (const_cast<MEDCouplingCartesianAMRMeshGen *>(_patches[patchId]->getMesh()))->detachFromFather();
+ _patches=patches;
+ declareAsNew();
+}
+
+mcIdType MEDCouplingCartesianAMRMeshGen::getNumberOfPatches() const
+{
+ return ToIdType(_patches.size());
+}
+
+/*!
+ * This method is a generic algorithm to create patches in \a this (by destroying the patches if any).
+ * This method uses \a criterion array as a field on cells on this level.
+ * This method only create patches at level 0 relative to \a this.
+ *
+ * This generic algorithm can be degenerated into three child ones, depending on the arguments given; in particular depending
+ * on whether they are equal to 0 or not.
+ * 1/ If minimumPatchLength = maximumPatchLength = maximumPatchVolume = 0, then we have the Berger-Rigoutsos algorithm.
+ * This algorithm was developed in 1991 and seems appropriate for sequential programming.
+ * 2/ If maximumPatchLength = 0, then we have the Livne algorithm.
+ * This algorithm was developed in 2004 and is an improvement of the Berger-Rigoutsos algorithm.
+ * 3/ If maximumPatchVolume = 0, the we have the lmin-lmax algorithm.
+ * This algorithm was developed by Arthur TALPAERT in 2014 and is an improvement of the Livne algorithm. It is especially
+ * appropriate for parallel computing, where one patch would be given to one CPU. See Arthur TALPAERT's 2014 CANUM poster
+ * for more information.
+ *
+ */
+void MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion(const INTERP_KERNEL::BoxSplittingOptions& bso, const std::vector<bool>& criterion, const std::vector<mcIdType>& factors)
+{
+ mcIdType nbCells(getNumberOfCellsAtCurrentLevel());
+ if(nbCells!=ToIdType(criterion.size()))
+ throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion : the number of tuples of criterion array must be equal to the number of cells at the current level !");
+ _patches.clear();
+ std::vector<mcIdType> cgs(_mesh->getCellGridStructure());
+ std::vector< MCAuto<InternalPatch> > listOfPatches,listOfPatchesOK;
+ //
+ MCAuto<InternalPatch> p(new InternalPatch);
+ p->setNumberOfTrue(MEDCouplingStructuredMesh::FindMinimalPartOf(bso.getMinimumPatchLength(),cgs,criterion,p->getCriterion(),p->getPart()));
+ if(p->presenceOfTrue())
+ listOfPatches.push_back(p);
+ while(!listOfPatches.empty())
+ {
+ std::vector< MCAuto<InternalPatch> > listOfPatchesTmp;
+ for(std::vector< MCAuto<InternalPatch> >::iterator it=listOfPatches.begin();it!=listOfPatches.end();it++)
+ {
+ //
+ int axisId;
+ mcIdType largestLength,cutPlace;
+ MEDCouplingStructuredMesh::FindTheWidestAxisOfGivenRangeInCompactFrmt((*it)->getConstPart(),axisId,largestLength);
+ if((*it)->getEfficiency()>=bso.getEfficiencyThreshold() && ((*it)->getNumberOfCells()>bso.getMaximumNbOfCellsInPatch() || largestLength>bso.getMaximumPatchLength()))
+ {
+ DissectBigPatch(bso,*it,axisId,largestLength,cutPlace);
+ DealWithCut(bso.getMinimumPatchLength(),*it,axisId,cutPlace,listOfPatchesTmp);
+ continue;
+ }//action 1
+ if(FindHole(bso,*it,axisId,cutPlace))//axisId overwritten here if FindHole equal to true !
+ { DealWithCut(bso.getMinimumPatchLength(),*it,axisId,cutPlace,listOfPatchesTmp); continue; }//action 2
+ if(FindInflection(bso,*it,cutPlace,axisId))//axisId overwritten here if cutFound equal to true !
+ { DealWithCut(bso.getMinimumPatchLength(),*it,axisId,cutPlace,listOfPatchesTmp); continue; }//action 3
+ if(TryAction4(bso,*it,axisId,largestLength,cutPlace))
+ { DealWithCut(bso.getMinimumPatchLength(),*it,axisId,cutPlace,listOfPatchesTmp); continue; }//action 4
+ else
+ listOfPatchesOK.push_back(DealWithNoCut(*it));
+ }
+ listOfPatches=listOfPatchesTmp;
+ }
+ for(std::vector< MCAuto<InternalPatch> >::const_iterator it=listOfPatchesOK.begin();it!=listOfPatchesOK.end();it++)
+ addPatch((*it)->getConstPart(),factors);
+ declareAsNew();
+}
+
+/*!
+ * 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.
+ * This method only create patches at level 0 relative to \a this.
+ */
+void MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion(const INTERP_KERNEL::BoxSplittingOptions& bso, const DataArrayByte *criterion, const std::vector<mcIdType>& factors)
+{
+ if(!criterion || !criterion->isAllocated())
+ throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::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);
+ declareAsNew();
+}
+
+void MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion(const INTERP_KERNEL::BoxSplittingOptions& bso, const DataArrayDouble *criterion, const std::vector<mcIdType>& factors, double eps)
+{
+ if(!criterion)
+ throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion : null criterion pointer !");
+ std::vector<bool> inp(criterion->toVectorOfBool(eps));
+ createPatchesFromCriterion(bso,inp,factors);
+}
+
+mcIdType MEDCouplingCartesianAMRMeshGen::getPatchIdFromChildMesh(const MEDCouplingCartesianAMRMeshGen *mesh) const
+{
+ mcIdType ret(0);
+ for(std::vector< MCAuto<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++,ret++)
+ {
+ if((*it)->getMesh()==mesh)
+ return ret;
+ }
+ throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::getPatchIdFromChildMesh : no such a mesh in my direct progeny !");
+}
+
+std::vector< const MEDCouplingCartesianAMRPatch *> MEDCouplingCartesianAMRMeshGen::getPatches() const
+{
+ std::size_t sz(_patches.size());
+ std::vector< const MEDCouplingCartesianAMRPatch *> ret(sz);
+ for(std::size_t i=0;i<sz;i++)
+ ret[i]=_patches[i];
+ return ret;
+}
+
+const MEDCouplingCartesianAMRPatch *MEDCouplingCartesianAMRMeshGen::getPatch(mcIdType patchId) const
+{
+ checkPatchId(patchId);
+ return _patches[patchId];
+}
+
+/*!
+ * This method states if patch2 (with id \a patchId2) is in the neighborhood of patch1 (with id \a patchId1).
+ * The neighborhood size is defined by \a ghostLev in the reference of \a this ( \b not in the reference of patches !).
+ */
+bool MEDCouplingCartesianAMRMeshGen::isPatchInNeighborhoodOf(mcIdType patchId1, mcIdType patchId2, mcIdType ghostLev) const
+{
+ const MEDCouplingCartesianAMRPatch *p1(getPatch(patchId1)),*p2(getPatch(patchId2));
+ return p1->isInMyNeighborhood(p2,ghostLev);
+}
+
+/*!
+ * 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 *MEDCouplingCartesianAMRMeshGen::createCellFieldOnPatch(mcIdType 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());
+ MCAuto<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 creating a new instance
+ * it fills the value into the \a cellFieldOnPatch data.
+ *
+ * \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 MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatch(mcIdType patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch, bool isConservative) 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());
+ if(isConservative)
+ {
+ mcIdType fact(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(getFactors()));
+ std::transform(cellFieldOnPatch->begin(),cellFieldOnPatch->end(),cellFieldOnPatch->getPointer(),std::bind(std::multiplies<double>(),std::placeholders::_1,1./((double)fact)));
+ }
+}
+
+/*!
+ * This method is the generalization of fillCellFieldOnPatch method. This method only projects coarse to fine without considering the
+ * potential neighbor patches covered by the ghost cells of 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.
+ * \param [in,out] cellFieldOnPatch - The array of the cell field on the requested patch to be filled.
+ * \param [in] ghostLev - The size of the ghost zone (must be >=0 !)
+ *
+ * \sa fillCellFieldOnPatch, fillCellFieldOnPatchGhostAdv
+ */
+void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchGhost(mcIdType patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch, mcIdType ghostLev, bool isConservative) const
+{
+ if(!cellFieldOnThis || !cellFieldOnThis->isAllocated())
+ throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createCellFieldOnPatchGhost : the input cell field array is NULL or not allocated !");
+ const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
+ MEDCouplingIMesh::SpreadCoarseToFineGhost(cellFieldOnThis,_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors(),ghostLev);
+ if(isConservative)
+ {
+ mcIdType fact(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(getFactors()));
+ std::transform(cellFieldOnPatch->begin(),cellFieldOnPatch->end(),cellFieldOnPatch->getPointer(),std::bind(std::multiplies<double>(),std::placeholders::_1,1./((double)fact)));
+ }
+}
+
+/*!
+ * This method is equivalent to fillCellFieldOnPatchGhost except that here \b ONLY \b the \b ghost \b zone will be updated
+ * in \a cellFieldOnPatch.
+ *
+ * \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 \b only \b in \b the \b ghost \b zone.
+ * \param [in] ghostLev - The size of the ghost zone (must be >=0 !)
+ */
+void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchOnlyOnGhostZone(mcIdType patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch, mcIdType ghostLev) const
+{
+ if(!cellFieldOnThis || !cellFieldOnThis->isAllocated())
+ throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::fillCellFieldOnPatchOnlyOnGhostZone : the input cell field array is NULL or not allocated !");
+ const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
+ MEDCouplingIMesh::SpreadCoarseToFineGhostZone(cellFieldOnThis,_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors(),ghostLev);
+}
+
+/*!
+ * This method is a refinement of fillCellFieldOnPatchGhost. fillCellFieldOnPatchGhost is first called.
+ * Then for all other patches than those pointed by \a patchId that overlap the ghost zone of the patch impact the ghost zone adequately.
+ *
+ * \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] ghostLev - The size of the ghost zone (must be >=0 !)
+ * \param [in] arrsOnPatches - \b WARNING arrsOnPatches[patchId] is \b NOT \b const. All others are const.
+ *
+ * \sa fillCellFieldOnPatchOnlyGhostAdv
+ */
+void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchGhostAdv(mcIdType patchId, const DataArrayDouble *cellFieldOnThis, mcIdType ghostLev, const std::vector<const DataArrayDouble *>& arrsOnPatches, bool isConservative) const
+{
+ mcIdType nbp(getNumberOfPatches());
+ if(nbp!=ToIdType(arrsOnPatches.size()))
+ {
+ std::ostringstream oss; oss << "MEDCouplingCartesianAMRMesh::fillCellFieldOnPatchGhostAdv : there are " << nbp << " patches in this and " << arrsOnPatches.size() << " arrays in the last parameter !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ DataArrayDouble *theFieldToFill(const_cast<DataArrayDouble *>(arrsOnPatches[patchId]));
+ // first, do as usual
+ fillCellFieldOnPatchGhost(patchId,cellFieldOnThis,theFieldToFill,ghostLev,isConservative);
+ fillCellFieldOnPatchOnlyGhostAdv(patchId,ghostLev,arrsOnPatches);
+}
+
+/*!
+ * This method updates the patch with id \a patchId considering the only the all the patches in \a this to fill ghost zone.
+ * So \b warning, the DataArrayDouble instance \a arrsOnPatches[patchId] is non const.
+ *
+ * \sa getPatchIdsInTheNeighborhoodOf
+ */
+void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchOnlyGhostAdv(mcIdType patchId, mcIdType ghostLev, const std::vector<const DataArrayDouble *>& arrsOnPatches) const
+{
+ mcIdType nbp(getNumberOfPatches());
+ if(nbp!=ToIdType(arrsOnPatches.size()))
+ {
+ std::ostringstream oss; oss << "MEDCouplingCartesianAMRMesh::fillCellFieldOnPatchOnlyGhostAdv : there are " << nbp << " patches in this and " << arrsOnPatches.size() << " arrays in the last parameter !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ const MEDCouplingCartesianAMRPatch *refP(getPatch(patchId));
+ DataArrayDouble *theFieldToFill(const_cast<DataArrayDouble *>(arrsOnPatches[patchId]));
+ std::vector<mcIdType> ids(getPatchIdsInTheNeighborhoodOf(patchId,ghostLev));
+ for(std::vector<mcIdType>::const_iterator it=ids.begin();it!=ids.end();it++)
+ {
+ const MEDCouplingCartesianAMRPatch *otherP(getPatch(*it));
+ MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwo(ghostLev,_factors,refP,otherP,theFieldToFill,arrsOnPatches[*it]);
+ }
+}
+
+void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchOnlyOnGhostZoneWith(mcIdType ghostLev, const MEDCouplingCartesianAMRPatch *patchToBeModified, const MEDCouplingCartesianAMRPatch *neighborPatch, DataArrayDouble *cellFieldOnPatch, const DataArrayDouble *cellFieldNeighbor) const
+{
+ MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwo(ghostLev,_factors,patchToBeModified,neighborPatch,cellFieldOnPatch,cellFieldNeighbor);
+}
+
+/*!
+ * 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.
+ * \param [in] isConservative - true if the field needs to be conserved. false if maximum principle has to be applied.
+ *
+ * \throw if \a patchId is not in [ 0 , \c this->getNumberOfPatches() )
+ * \throw if \a cellFieldOnPatch is NULL or not allocated
+ * \sa createCellFieldOnPatch, MEDCouplingIMesh::CondenseFineToCoarse,fillCellFieldComingFromPatchGhost
+ */
+void MEDCouplingCartesianAMRMeshGen::fillCellFieldComingFromPatch(mcIdType patchId, const DataArrayDouble *cellFieldOnPatch, DataArrayDouble *cellFieldOnThis, bool isConservative) 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);
+ if(!isConservative)
+ {
+ mcIdType fact(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(getFactors()));
+ MEDCouplingStructuredMesh::MultiplyPartOf(_mesh->getCellGridStructure(),patch->getBLTRRange(),1./((double)fact),cellFieldOnThis);
+ }
+}
+
+/*!
+ * This method is the extension of MEDCouplingCartesianAMRMesh::fillCellFieldComingFromPatch managing the ghost cells. If this
+ * method is called with \a ghostLev equal to 0 it behaves exactly as MEDCouplingCartesianAMRMesh::fillCellFieldComingFromPatch.
+ *
+ * \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.
+ * \param [in] ghostLev The size of ghost zone (must be >= 0 !)
+ * \param [in] isConservative - true if the field needs to be conserved. false if maximum principle has to be applied.
+ *
+ * \throw if \a patchId is not in [ 0 , \c this->getNumberOfPatches() )
+ * \throw if \a cellFieldOnPatch is NULL or not allocated
+ * \sa fillCellFieldComingFromPatch
+ */
+void MEDCouplingCartesianAMRMeshGen::fillCellFieldComingFromPatchGhost(mcIdType patchId, const DataArrayDouble *cellFieldOnPatch, DataArrayDouble *cellFieldOnThis, mcIdType ghostLev, bool isConservative) const
+{
+ if(!cellFieldOnPatch || !cellFieldOnPatch->isAllocated())
+ throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::fillCellFieldComingFromPatchGhost : the input cell field array is NULL or not allocated !");
+ const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
+ MEDCouplingIMesh::CondenseFineToCoarseGhost(_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors(),cellFieldOnThis,ghostLev);
+ if(!isConservative)
+ {
+ mcIdType fact(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(getFactors()));
+ MEDCouplingStructuredMesh::MultiplyPartOfByGhost(_mesh->getCellGridStructure(),patch->getBLTRRange(),ghostLev,1./((double)fact),cellFieldOnThis);
+ }
+}
+
+/*!
+ * This method finds all patches (located by their ids) that are in the neighborhood of patch with id \a patchId. The neighborhood size is
+ * defined by ghostLev.
+ *
+ * \param [in] patchId - the id of the considered patch.
+ * \param [in] ghostLev - the size of the neighborhood.
+ * \return DataArrayIdType * - the newly allocated array containing the list of patches in the neighborhood of the considered patch. This array is to be deallocated by the caller.
+ */
+DataArrayIdType *MEDCouplingCartesianAMRMeshGen::findPatchesInTheNeighborhoodOf(mcIdType patchId, mcIdType ghostLev) const
+{
+ mcIdType nbp(getNumberOfPatches());
+ MCAuto<DataArrayIdType> ret(DataArrayIdType::New()); ret->alloc(0,1);
+ for(mcIdType i=0;i<nbp;i++)
+ {
+ if(i!=patchId)
+ if(isPatchInNeighborhoodOf(i,patchId,ghostLev))
+ ret->pushBackSilent(i);
+ }
+ return ret.retn();
+}
+
+MEDCouplingUMesh *MEDCouplingCartesianAMRMeshGen::buildUnstructured() const
+{
+ MCAuto<MEDCouplingUMesh> part(_mesh->buildUnstructured());
+ std::vector<bool> bs(_mesh->getNumberOfCells(),false);
+ std::vector<mcIdType> cgs(_mesh->getCellGridStructure());
+ std::vector< MCAuto<MEDCouplingUMesh> > msSafe(_patches.size()+1);
+ std::size_t ii(0);
+ for(std::vector< MCAuto<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++,ii++)
+ {
+ MEDCouplingStructuredMesh::SwitchOnIdsFrom(cgs,(*it)->getBLTRRange(),bs);
+ msSafe[ii+1]=(*it)->getMesh()->buildUnstructured();
+ }
+ MCAuto<DataArrayIdType> eltsOff(DataArrayIdType::BuildListOfSwitchedOff(bs));
+ msSafe[0]=static_cast<MEDCouplingUMesh *>(part->buildPartOfMySelf(eltsOff->begin(),eltsOff->end(),false));
+ std::vector< const MEDCouplingUMesh * > ms(msSafe.size());
+ for(std::size_t i=0;i<msSafe.size();i++)
+ ms[i]=msSafe[i];
+ return MEDCouplingUMesh::MergeUMeshes(ms);
+}
+
+/*!
+ * This method returns a mesh containing as cells that there is patches at the current level.
+ * The patches are seen like 'boxes' that is too say the refinement will not appear here.
+ *
+ * \return MEDCoupling1SGTUMesh * - A new object to be managed by the caller containing as cells as there are patches in \a this.
+ */
+MEDCoupling1SGTUMesh *MEDCouplingCartesianAMRMeshGen::buildMeshFromPatchEnvelop() const
+{
+ std::vector<const MEDCoupling1SGTUMesh *> cells;
+ std::vector< MCAuto<MEDCoupling1SGTUMesh> > cellsSafe;
+ for(std::vector< MCAuto<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
+ {
+ const MEDCouplingCartesianAMRPatch *patch(*it);
+ if(patch)
+ {
+ MCAuto<MEDCouplingIMesh> cell(patch->getMesh()->getImageMesh()->asSingleCell());
+ MCAuto<MEDCoupling1SGTUMesh> cell1SGT(cell->build1SGTUnstructured());
+ cellsSafe.push_back(cell1SGT); cells.push_back(cell1SGT);
+ }
+ }
+ return MEDCoupling1SGTUMesh::Merge1SGTUMeshes(cells);
+}
+
+MEDCoupling1SGTUMesh *MEDCouplingCartesianAMRMeshGen::buildMeshOfDirectChildrenOnly() const
+{
+ std::vector<const MEDCoupling1SGTUMesh *> patches;
+ std::vector< MCAuto<MEDCoupling1SGTUMesh> > patchesSafe;
+ for(std::vector< MCAuto<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
+ {
+ const MEDCouplingCartesianAMRPatch *patch(*it);
+ if(patch)
+ {
+ MCAuto<MEDCoupling1SGTUMesh> patchMesh(patch->getMesh()->getImageMesh()->build1SGTUnstructured());
+ patchesSafe.push_back(patchMesh); patches.push_back(patchMesh);
+ }
+ }
+ return MEDCoupling1SGTUMesh::Merge1SGTUMeshes(patches);
+}
+
+/*!
+ * This method works same as buildUnstructured except that arrays are given in input to build a field on cell in output.
+ * \return MEDCouplingFieldDouble * - a newly created instance the caller has reponsability to deal with.
+ * \sa buildUnstructured
+ */
+MEDCouplingFieldDouble *MEDCouplingCartesianAMRMeshGen::buildCellFieldOnRecurseWithoutOverlapWithoutGhost(mcIdType ghostSz, const std::vector<const DataArrayDouble *>& recurseArrs) const
+{
+ if(recurseArrs.empty())
+ throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::buildCellFieldOnRecurseWithoutOverlapWithoutGhost : array is empty ! Should never happen !");
+ //
+ std::vector<bool> bs(_mesh->getNumberOfCells(),false);
+ std::vector<mcIdType> cgs(_mesh->getCellGridStructure());
+ std::vector< MCAuto<MEDCouplingFieldDouble> > msSafe(_patches.size()+1);
+ std::size_t ii(0);
+ for(std::vector< MCAuto<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++,ii++)
+ {
+ MEDCouplingStructuredMesh::SwitchOnIdsFrom(cgs,(*it)->getBLTRRange(),bs);
+ std::vector<const DataArrayDouble *> tmpArrs(extractSubTreeFromGlobalFlatten((*it)->getMesh(),recurseArrs));
+ msSafe[ii+1]=(*it)->getMesh()->buildCellFieldOnRecurseWithoutOverlapWithoutGhost(ghostSz,tmpArrs);
+ }
+ MCAuto<DataArrayIdType> eltsOff(DataArrayIdType::BuildListOfSwitchedOff(bs));
+ //
+ MCAuto<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS));
+ MCAuto<DataArrayDouble> arr2(extractGhostFrom(ghostSz,recurseArrs[0]));
+ arr2=arr2->selectByTupleIdSafe(eltsOff->begin(),eltsOff->end());
+ ret->setArray(arr2);
+ ret->setName(arr2->getName());
+ MCAuto<MEDCouplingUMesh> part(_mesh->buildUnstructured());
+ MCAuto<MEDCouplingMesh> mesh(part->buildPartOfMySelf(eltsOff->begin(),eltsOff->end(),false));
+ ret->setMesh(mesh);
+ msSafe[0]=ret;
+ //
+ std::vector< const MEDCouplingFieldDouble * > ms(msSafe.size());
+ for(std::size_t i=0;i<msSafe.size();i++)
+ ms[i]=msSafe[i];
+ //
+ return MEDCouplingFieldDouble::MergeFields(ms);
+}
+
+/*!
+ * This method extracts from \arr arr the part inside \a arr by cutting the \a ghostSz external part.
+ * \arr is expected to be an array having a number of tuples equal to \c getImageMesh()->buildWithGhost(ghostSz).
+ */
+DataArrayDouble *MEDCouplingCartesianAMRMeshGen::extractGhostFrom(mcIdType ghostSz, const DataArrayDouble *arr) const
+{
+ std::vector<mcIdType> st(_mesh->getCellGridStructure());
+ std::vector< std::pair<mcIdType,mcIdType> > p(MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(st));
+ std::transform(st.begin(),st.end(),st.begin(),std::bind(std::plus<mcIdType>(),std::placeholders::_1,2*ghostSz));
+ MEDCouplingStructuredMesh::ApplyGhostOnCompactFrmt(p,ghostSz);
+ MCAuto<DataArrayDouble> ret(MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom(st,arr,p));
+ return ret.retn();
+}
+
+/*!
+ * This method returns all the patches in \a this not equal to \a patchId that are in neighborhood of patch with id \a patchId.
+ *
+ * \sa fillCellFieldOnPatchOnlyGhostAdv
+ */
+std::vector<mcIdType> MEDCouplingCartesianAMRMeshGen::getPatchIdsInTheNeighborhoodOf(mcIdType patchId, mcIdType ghostLev) const
+{
+ std::vector<mcIdType> ret;
+ mcIdType nbp(getNumberOfPatches());
+ //
+ for(mcIdType i=0;i<nbp;i++)
+ {
+ if(i!=patchId)
+ if(isPatchInNeighborhoodOf(i,patchId,ghostLev))
+ ret.push_back(i);
+ }
+ return ret;
+}
+
+/*!
+ * This method returns a dump python of \a this. It is useful for users of createPatchesFromCriterion method for debugging.
+ *
+ * \sa dumpPatchesOf, createPatchesFromCriterion, createPatchesFromCriterionML
+ */
+std::string MEDCouplingCartesianAMRMeshGen::buildPythonDumpOfThis() const
+{
+ std::ostringstream oss;
+ oss << "amr=MEDCouplingCartesianAMRMesh(\""<< getImageMesh()->getName() << "\"," << getSpaceDimension() << ",[";
+ std::vector<mcIdType> ngs(getImageMesh()->getNodeGridStructure());
+ std::vector<double> orig(getImageMesh()->getOrigin()),dxyz(getImageMesh()->getDXYZ());
+ std::copy(ngs.begin(),ngs.end(),std::ostream_iterator<mcIdType>(oss,","));
+ oss << "],[";
+ std::copy(orig.begin(),orig.end(),std::ostream_iterator<double>(oss,","));
+ oss << "],[";
+ std::copy(dxyz.begin(),dxyz.end(),std::ostream_iterator<double>(oss,","));
+ oss << "])\n";
+ dumpPatchesOf("amr",oss);
+ return oss.str();
+}
+
+MEDCouplingCartesianAMRMeshGen::MEDCouplingCartesianAMRMeshGen(const MEDCouplingCartesianAMRMeshGen& other):RefCountObject(other),_mesh(other._mesh),_patches(other._patches),_factors(other._factors)
+{
+ const MEDCouplingIMesh *mesh(other._mesh);
+ if(mesh)
+ _mesh=static_cast<MEDCouplingIMesh *>(mesh->deepCopy());
+ std::size_t sz(other._patches.size());
+ for(std::size_t i=0;i<sz;i++)
+ {
+ const MEDCouplingCartesianAMRPatch *patch(other._patches[i]);
+ if(patch)
+ _patches[i]=patch->deepCopy(this);
+ }
+}
+
+MEDCouplingCartesianAMRMeshGen::MEDCouplingCartesianAMRMeshGen(const std::string& meshName, int spaceDim, const mcIdType *nodeStrctStart, const mcIdType *nodeStrctStop,
+ const double *originStart, const double *originStop, const double *dxyzStart, const double *dxyzStop)
+{
+ _mesh=MEDCouplingIMesh::New(meshName,spaceDim,nodeStrctStart,nodeStrctStop,originStart,originStop,dxyzStart,dxyzStop);
+}
+
+MEDCouplingCartesianAMRMeshGen::MEDCouplingCartesianAMRMeshGen(MEDCouplingIMesh *mesh)
+{
+ if(!mesh)
+ throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen(MEDCouplingIMesh *mesh) constructor : The input mesh is null !");
+ mesh->checkConsistencyLight();
+ _mesh=mesh; _mesh->incrRef();
+}
+
+void MEDCouplingCartesianAMRMeshGen::checkPatchId(mcIdType patchId) const
+{
+ mcIdType sz(getNumberOfPatches());
+ if(patchId<0 || patchId>=sz)
+ {
+ std::ostringstream oss; oss << "MEDCouplingCartesianAMRMeshGen::checkPatchId : invalid patchId (" << patchId << ") ! Must be in [0," << sz << ") !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+}
+
+void MEDCouplingCartesianAMRMeshGen::checkFactorsAndIfNotSetAssign(const std::vector<mcIdType>& factors)
+{
+ if(getSpaceDimension()!=ToIdType(factors.size()))
+ throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::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 ");
+ }
+}
+
+void MEDCouplingCartesianAMRMeshGen::retrieveGridsAtInternal(mcIdType lev, std::vector< MCAuto<MEDCouplingCartesianAMRPatchGen> >& grids) const
+{
+ if(lev==0)
+ {
+ const MEDCouplingCartesianAMRMesh *thisc(dynamic_cast<const MEDCouplingCartesianAMRMesh *>(this));//tony
+ MCAuto<MEDCouplingCartesianAMRPatchGF> elt(new MEDCouplingCartesianAMRPatchGF(const_cast<MEDCouplingCartesianAMRMesh *>(thisc)));
+ grids.push_back(DynamicCastSafe<MEDCouplingCartesianAMRPatchGF,MEDCouplingCartesianAMRPatchGen>(elt));
+ }
+ else if(lev==1)
+ {
+ for(std::vector< MCAuto<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
+ {
+ const MEDCouplingCartesianAMRPatch *pt(*it);
+ if(pt)
+ {
+ MCAuto<MEDCouplingCartesianAMRPatch> tmp1(*it);
+ grids.push_back(DynamicCastSafe<MEDCouplingCartesianAMRPatch,MEDCouplingCartesianAMRPatchGen>(tmp1));
+ }
+ }
+ }
+ else
+ {
+ for(std::vector< MCAuto<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
+ {
+ const MEDCouplingCartesianAMRPatch *pt(*it);
+ if(pt)
+ pt->getMesh()->retrieveGridsAtInternal(lev-1,grids);
+ }
+ }
+}
+
+mcIdType MEDCouplingCartesianAMRMeshGen::GetGhostLevelInFineRef(mcIdType ghostLev, const std::vector<mcIdType>& factors)
+{
+ if(ghostLev<0)
+ throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::GetGhostLevelInFineRef : the ghost size must be >=0 !");
+ if(factors.empty())
+ throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::GetGhostLevelInFineRef : no factors defined !");
+ mcIdType ghostLevInPatchRef;
+ if(ghostLev==0)
+ ghostLevInPatchRef=0;
+ else
+ {
+ ghostLevInPatchRef=(ghostLev-1)/factors[0]+1;
+ for(std::size_t i=0;i<factors.size();i++)
+ ghostLevInPatchRef=std::max(ghostLevInPatchRef,(ghostLev-1)/factors[i]+1);
+ }
+ return ghostLevInPatchRef;
+}
+
+/*!
+ * This method returns a sub set of \a all. The subset is defined by the \a head in the tree defined by \a this.
+ * Elements in \a all are expected to be sorted from god father to most refined structure.
+ */
+std::vector<const DataArrayDouble *> MEDCouplingCartesianAMRMeshGen::extractSubTreeFromGlobalFlatten(const MEDCouplingCartesianAMRMeshGen *head, const std::vector<const DataArrayDouble *>& all) const
+{
+ mcIdType maxLev(getMaxNumberOfLevelsRelativeToThis());
+ std::vector<const DataArrayDouble *> ret;
+ std::vector<const MEDCouplingCartesianAMRMeshGen *> meshes(1,this);
+ std::size_t kk(0);
+ for(mcIdType i=0;i<maxLev;i++)
+ {
+ std::vector<const MEDCouplingCartesianAMRMeshGen *> meshesTmp;
+ for(std::vector<const MEDCouplingCartesianAMRMeshGen *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
+ {
+ if((*it)==head || head->isObjectInTheProgeny(*it))
+ ret.push_back(all[kk]);
+ kk++;
+ std::vector< const MEDCouplingCartesianAMRPatch *> ps((*it)->getPatches());
+ for(std::vector< const MEDCouplingCartesianAMRPatch *>::const_iterator it0=ps.begin();it0!=ps.end();it0++)
+ {
+ const MEDCouplingCartesianAMRMeshGen *mesh((*it0)->getMesh());
+ meshesTmp.push_back(mesh);
+ }
+ }
+ meshes=meshesTmp;
+ }
+ if(kk!=all.size())
+ throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::extractSubTreeFromGlobalFlatten : the size of input vector is not compatible with number of leaves in this !");
+ return ret;
+}
+
+void MEDCouplingCartesianAMRMeshGen::dumpPatchesOf(const std::string& varName, std::ostream& oss) const
+{
+ std::size_t j(0);
+ for(std::vector< MCAuto<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
+ {
+ const MEDCouplingCartesianAMRPatch *patch(*it);
+ if(patch)
+ {
+ std::ostringstream oss2; oss2 << varName << ".addPatch([";
+ const std::vector< std::pair<mcIdType,mcIdType> >& bltr(patch->getBLTRRange());
+ std::size_t sz(bltr.size());
+ for(std::size_t i=0;i<sz;i++)
+ {
+ oss2 << "(" << bltr[i].first << "," << bltr[i].second << ")";
+ if(i!=sz-1)
+ oss2 << ",";
+ }
+ oss2 << "],[";
+ std::copy(_factors.begin(),_factors.end(),std::ostream_iterator<mcIdType>(oss2,","));
+ oss2 << "])\n";
+ oss << oss2.str();
+ std::ostringstream oss3; oss3 << varName << "[" << j++ << "]";
+ patch->getMesh()->dumpPatchesOf(oss3.str(),oss);
+ }
+ }
+}
+
+std::size_t MEDCouplingCartesianAMRMeshGen::getHeapMemorySizeWithoutChildren() const
+{
+ return sizeof(MEDCouplingCartesianAMRMeshGen);
+}
+
+std::vector<const BigMemoryObject *> MEDCouplingCartesianAMRMeshGen::getDirectChildrenWithNull() const
+{
+ std::vector<const BigMemoryObject *> ret;
+ ret.push_back((const MEDCouplingIMesh *)_mesh);
+ for(std::vector< MCAuto<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
+ ret.push_back((const MEDCouplingCartesianAMRPatch*)*it);
+ return ret;
+}
+
+void MEDCouplingCartesianAMRMeshGen::updateTime() const
+{
+ if((const MEDCouplingIMesh *)_mesh)
+ updateTimeWith(*_mesh);
+ for(std::vector< MCAuto<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
+ {
+ const MEDCouplingCartesianAMRPatch *elt(*it);
+ if(!elt)
+ continue;
+ const MEDCouplingCartesianAMRMeshGen *mesh(elt->getMesh());
+ if(mesh)
+ updateTimeWith(*mesh);
+ }
+}
+
+MEDCouplingCartesianAMRMeshSub::MEDCouplingCartesianAMRMeshSub(MEDCouplingCartesianAMRMeshGen *father, MEDCouplingIMesh *mesh):MEDCouplingCartesianAMRMeshGen(mesh),_father(father)
+{
+ if(!_father)
+ throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshSub(MEDCouplingCartesianAMRMeshGen *father, MEDCouplingIMesh *mesh) constructor : empty father !");
+}
+
+const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRMeshSub::getFather() const
+{
+ return _father;
+}
+
+const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRMeshSub::getGodFather() const
+{
+ if(!_father)
+ throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshSub::getGodFather : Impossible to find a god father because there is a hole in chain !");
+ return _father->getGodFather();
+}
+
+/*!
+ * This method returns the level of \a this. 0 for god father. 1 for children of god father ...
+ */
+mcIdType MEDCouplingCartesianAMRMeshSub::getAbsoluteLevel() const
+{
+ if(!_father)
+ throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshSub::getAbsoluteLevel : Impossible to find a god father because there is a hole in chain !");
+ return _father->getAbsoluteLevel()+1;
+}
+
+void MEDCouplingCartesianAMRMeshSub::detachFromFather()
+{
+ _father=0;
+ declareAsNew();
+}
+
+std::vector< std::pair<mcIdType,mcIdType> > MEDCouplingCartesianAMRMeshSub::positionRelativeToGodFather(std::vector<mcIdType>& st) const
+{
+ st=_father->getFactors();
+ std::size_t dim(st.size());
+ std::vector<mcIdType> prev(st);
+ mcIdType id(_father->getPatchIdFromChildMesh(this));
+ const MEDCouplingCartesianAMRPatch *p(_father->getPatch(id));
+ std::vector< std::pair<mcIdType,mcIdType> > ret(p->getBLTRRange());
+ std::vector<mcIdType> delta(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(ret)),start(dim);
+ std::transform(delta.begin(),delta.end(),prev.begin(),delta.begin(),std::multiplies<mcIdType>());
+ for(std::size_t i=0;i<dim;i++)
+ start[i]=ret[i].first;
+ std::transform(start.begin(),start.end(),prev.begin(),start.begin(),std::multiplies<mcIdType>());
+ const MEDCouplingCartesianAMRMeshGen *it(_father);
+ while(!dynamic_cast<const MEDCouplingCartesianAMRMesh *>(it))
+ {
+ const MEDCouplingCartesianAMRMeshSub *itc(static_cast<const MEDCouplingCartesianAMRMeshSub *>(it));
+ mcIdType id2(itc->_father->getPatchIdFromChildMesh(itc));
+ const MEDCouplingCartesianAMRPatch *p2(itc->_father->getPatch(id2));
+ const std::vector< std::pair<mcIdType,mcIdType> >& start2(p2->getBLTRRange());
+ std::vector<mcIdType> tmp(dim);
+ for(std::size_t i=0;i<dim;i++)
+ tmp[i]=start2[i].first;
+ //
+ prev=itc->_father->getFactors();
+ std::transform(st.begin(),st.end(),prev.begin(),st.begin(),std::multiplies<mcIdType>());
+ std::transform(st.begin(),st.end(),tmp.begin(),tmp.begin(),std::multiplies<mcIdType>());
+ std::transform(start.begin(),start.end(),tmp.begin(),start.begin(),std::plus<mcIdType>());
+ it=itc->_father;
+ }
+ for(std::size_t i=0;i<dim;i++)
+ {
+ ret[i].first=start[i];
+ ret[i].second=start[i]+delta[i];
+ }
+ return ret;
+}
+
+mcIdType MEDCouplingCartesianAMRMeshSub::getAbsoluteLevelRelativeTo(const MEDCouplingCartesianAMRMeshGen *ref) const
+{
+ if(this==ref)
+ return 0;
+ if(_father==0)
+ throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshSub::getAbsoluteLevelRelativeTo : ref is not in the progeny of this !");
+ else
+ return _father->getAbsoluteLevelRelativeTo(ref)+1;
+}
+
+MEDCouplingCartesianAMRMeshSub::MEDCouplingCartesianAMRMeshSub(const MEDCouplingCartesianAMRMeshSub& other, MEDCouplingCartesianAMRMeshGen *father):MEDCouplingCartesianAMRMeshGen(other),_father(father)
+{
+}
+
+MEDCouplingCartesianAMRMeshSub *MEDCouplingCartesianAMRMeshSub::deepCopy(MEDCouplingCartesianAMRMeshGen *fath) const
+{
+ return new MEDCouplingCartesianAMRMeshSub(*this,fath);
+}
+
+/*!
+ * \sa getPositionRelativeTo
+ */
+void MEDCouplingCartesianAMRMeshSub::getPositionRelativeToInternal(const MEDCouplingCartesianAMRMeshGen *ref, std::vector<mcIdType>& ret) const
+{
+ if(this==ref)
+ return ;
+ if(!_father)
+ throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshSub::getPositionRelativeToInternal : ref is not in the progeny of this !");
+ mcIdType myId(_father->getPatchIdFromChildMesh(this));
+ ret.push_back(myId);
+ _father->getPositionRelativeToInternal(ref,ret);
+}
+
+MEDCouplingCartesianAMRMesh *MEDCouplingCartesianAMRMesh::New(const std::string& meshName, int spaceDim, const mcIdType *nodeStrctStart, const mcIdType *nodeStrctStop,
+ const double *originStart, const double *originStop, const double *dxyzStart, const double *dxyzStop)
+{
+ return new MEDCouplingCartesianAMRMesh(meshName,spaceDim,nodeStrctStart,nodeStrctStop,originStart,originStop,dxyzStart,dxyzStop);
+}
+
+MEDCouplingCartesianAMRMesh *MEDCouplingCartesianAMRMesh::New(MEDCouplingIMesh *mesh)
+{
+ return new MEDCouplingCartesianAMRMesh(mesh);
+}
+
+const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRMesh::getFather() const
+{
+ //I'm god father ! No father !
+ return 0;
+}
+
+const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRMesh::getGodFather() const
+{
+ return this;
+}
+
+mcIdType MEDCouplingCartesianAMRMesh::getAbsoluteLevel() const
+{
+ return 0;
+}
+
+void MEDCouplingCartesianAMRMesh::detachFromFather()
+{//not a bug - do nothing
+}
+
+std::vector< std::pair<mcIdType,mcIdType> > MEDCouplingCartesianAMRMesh::positionRelativeToGodFather(std::vector<mcIdType>& st) const
+{
+ st=_mesh->getCellGridStructure();
+ return MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(st);
+}
+
+mcIdType MEDCouplingCartesianAMRMesh::getAbsoluteLevelRelativeTo(const MEDCouplingCartesianAMRMeshGen *ref) const
+{
+ if(this==ref)
+ return 0;
+ throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::getAbsoluteLevelRelativeTo : ref is not in the progeny of this !");
+}
+
+std::vector<MEDCouplingCartesianAMRPatchGen *> MEDCouplingCartesianAMRMesh::retrieveGridsAt(mcIdType absoluteLev) const
+{
+ std::vector< MCAuto<MEDCouplingCartesianAMRPatchGen> > rets;
+ retrieveGridsAtInternal(absoluteLev,rets);
+ std::vector< MEDCouplingCartesianAMRPatchGen * > ret(rets.size());
+ for(std::size_t i=0;i<rets.size();i++)
+ {
+ ret[i]=rets[i].retn();
+ }
+ return ret;
+}
+
+MEDCouplingCartesianAMRMesh *MEDCouplingCartesianAMRMesh::deepCopy(MEDCouplingCartesianAMRMeshGen *father) const
+{
+ if(father)
+ throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::deepCopy : specifying a not null father for a God Father object !");
+ return new MEDCouplingCartesianAMRMesh(*this);
+}
+
+/*!
+ * This method creates a multi level patches split at once.
+ * This method calls as many times as size of \a bso createPatchesFromCriterion. Size of \a bso and size of \a factors must be the same !
+ * \b WARNING, after the call the number of levels in \a this is equal to bso.size() + 1 !
+ *
+ * \param [in] bso vector of BoxSplittingOptions
+ * \param [in] criterion DataArrayDouble
+ * \param [in] factors vector of vector of factors
+ * \param [in] eps - See DataArrayDouble::toVectorOfBool for more information about the semantic of eps.
+ *
+ * \sa createPatchesFromCriterion
+ */
+void MEDCouplingCartesianAMRMesh::createPatchesFromCriterionML(const std::vector<const INTERP_KERNEL::BoxSplittingOptions *>& bso, const DataArrayDouble *criterion, const std::vector< std::vector<mcIdType> >& factors, double eps)
+{
+ std::size_t nbOfLevs(bso.size());
+ if(nbOfLevs!=factors.size())
+ throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createPatchesFromCriterionML : size of vectors must be the same !");
+ if(nbOfLevs==0)
+ return ;
+ if(!bso[0])
+ throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createPatchesFromCriterionML : pointers in 1st arg must be not NULL !");
+ createPatchesFromCriterion(*bso[0],criterion,factors[0],eps);
+ for(std::size_t i=1;i<nbOfLevs;i++)
+ {
+ if(!bso[i])
+ throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createPatchesFromCriterionML : presence of a NULL BoxSplittingOptions in input vector !");
+ //
+ std::vector<MEDCouplingCartesianAMRPatchGen *> elts(retrieveGridsAt(ToIdType((i))));
+ std::size_t sz(elts.size());
+ std::vector< MCAuto<MEDCouplingCartesianAMRPatchGen> > elts2(sz);
+ std::vector< MCAuto<DataArrayDouble> > elts3(sz);
+ for(std::size_t ii=0;ii<sz;ii++)
+ elts2[ii]=elts[ii];
+ //
+ static const char TMP_STR[]="TMP";
+ std::vector< std::pair<std::string,int> > fieldNames(1); fieldNames[0].first=TMP_STR; fieldNames[0].second=1;
+ MCAuto<MEDCouplingAMRAttribute> att(MEDCouplingAMRAttribute::New(this,fieldNames,0));
+ att->alloc();
+ DataArrayDouble *tmpDa(const_cast<DataArrayDouble *>(att->getFieldOn(this,TMP_STR)));
+ tmpDa->deepCopyFrom(*criterion);
+ att->synchronizeCoarseToFine();
+ for(std::size_t ii=0;ii<sz;ii++)
+ {
+ const DataArrayDouble *critOnLeaf(att->getFieldOn(const_cast<MEDCouplingCartesianAMRMeshGen *>(elts[ii]->getMesh()),TMP_STR));
+ elts3[ii]=const_cast<DataArrayDouble *>(critOnLeaf); elts3[ii]->incrRef();
+ }
+ att=0;
+ for(std::size_t ii=0;ii<sz;ii++)
+ const_cast<MEDCouplingCartesianAMRMeshGen *>(elts[ii]->getMesh())->createPatchesFromCriterion(*bso[i],elts3[ii],factors[i],eps);
+ }
+}
+
+void MEDCouplingCartesianAMRMesh::getPositionRelativeToInternal(const MEDCouplingCartesianAMRMeshGen *ref, std::vector<mcIdType>& ret) const
+{
+
+}
+
+MEDCouplingCartesianAMRMesh::MEDCouplingCartesianAMRMesh(const MEDCouplingCartesianAMRMesh& other):MEDCouplingCartesianAMRMeshGen(other)
+{
+}
+
+MEDCouplingCartesianAMRMesh::MEDCouplingCartesianAMRMesh(const std::string& meshName, int spaceDim, const mcIdType *nodeStrctStart, const mcIdType *nodeStrctStop,
+ const double *originStart, const double *originStop, const double *dxyzStart, const double *dxyzStop):MEDCouplingCartesianAMRMeshGen(meshName,spaceDim,nodeStrctStart,nodeStrctStop,originStart,originStop,dxyzStart,dxyzStop)
+{
+}
+
+MEDCouplingCartesianAMRMesh::MEDCouplingCartesianAMRMesh(MEDCouplingIMesh *mesh):MEDCouplingCartesianAMRMeshGen(mesh)
+{
+}
+
+std::vector<const BigMemoryObject *> MEDCouplingCartesianAMRMesh::getDirectChildrenWithNull() const
+{
+ std::vector<const BigMemoryObject *> ret(MEDCouplingCartesianAMRMeshGen::getDirectChildrenWithNull());
+ return ret;
+}
+
+MEDCouplingCartesianAMRMesh::~MEDCouplingCartesianAMRMesh()