X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FMEDCoupling%2FMEDCouplingAMRAttribute.cxx;h=96ed62922bbbcb02663cfe9a5dd90595b6d8e180;hb=30e370a928f879a1c9be2bd685cda6cabec223cf;hp=f27671edd748d9d701491b8151fb6aabfa9f9975;hpb=e0879ba9f27014ce3729ff123e62509db3ba3263;p=tools%2Fmedcoupling.git diff --git a/src/MEDCoupling/MEDCouplingAMRAttribute.cxx b/src/MEDCoupling/MEDCouplingAMRAttribute.cxx index f27671edd..96ed62922 100644 --- a/src/MEDCoupling/MEDCouplingAMRAttribute.cxx +++ b/src/MEDCoupling/MEDCouplingAMRAttribute.cxx @@ -24,6 +24,7 @@ #include "MEDCouplingIMesh.hxx" #include +#include using namespace ParaMEDMEM; @@ -51,6 +52,21 @@ void DataArrayDoubleCollection::dellocTuples() _arrs[i].first->reAlloc(0); } +void DataArrayDoubleCollection::copyFrom(const DataArrayDoubleCollection& other) +{ + std::size_t sz(_arrs.size()); + if(sz!=other._arrs.size()) + throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::copyFrom : size are not the same !"); + for(std::size_t i=0;icpyFrom(*otherArr); + } +} + void DataArrayDoubleCollection::spillInfoOnComponents(const std::vector< std::vector >& compNames) { std::size_t sz(_arrs.size()); @@ -75,6 +91,29 @@ void DataArrayDoubleCollection::spillNatures(const std::vector& n } } +std::vector< std::pair < std::string, std::vector > > DataArrayDoubleCollection::getInfoOnComponents() const +{ + std::size_t sz(_arrs.size()); + std::vector< std::pair < std::string, std::vector > > ret(sz); + for(std::size_t i=0;i >(elt->getName(),elt->getInfoOnComponents()); + } + return ret; +} + +std::vector DataArrayDoubleCollection::getNatures() const +{ + std::size_t sz(_arrs.size()); + std::vector ret(sz); + for(std::size_t i=0;i DataArrayDoubleCollection::retrieveFields() const { std::size_t sz(_arrs.size()); @@ -108,6 +147,44 @@ const DataArrayDouble *DataArrayDoubleCollection::getFieldWithName(const std::st throw INTERP_KERNEL::Exception(oss.str().c_str()); } +DataArrayDouble *DataArrayDoubleCollection::getFieldWithName(const std::string& name) +{ + std::vector vec; + for(std::vector< std::pair< MEDCouplingAutoRefCountObjectPtr, NatureOfField > >::iterator it=_arrs.begin();it!=_arrs.end();it++) + { + DataArrayDouble *obj((*it).first); + if(obj) + { + if(obj->getName()==name) + return obj; + else + vec.push_back(obj->getName()); + } + } + std::ostringstream oss; oss << "DataArrayDoubleCollection::getFieldWithName non const : fieldName \"" << name << "\" does not exist in this ! Possibilities are :"; + std::copy(vec.begin(),vec.end(),std::ostream_iterator(oss," ")); + throw INTERP_KERNEL::Exception(oss.str().c_str()); +} + +DataArrayDouble *DataArrayDoubleCollection::at(int pos) +{ + if(pos<0 || pos>=(int)_arrs.size()) + throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::at (non const) : pos must be in [0,nbOfFields) !"); + return _arrs[pos].first; +} + +const DataArrayDouble *DataArrayDoubleCollection::at(int pos) const +{ + if(pos<0 || pos>=(int)_arrs.size()) + throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::at : pos must be in [0,nbOfFields) !"); + return _arrs[pos].first; +} + +int DataArrayDoubleCollection::size() const +{ + return (int)_arrs.size(); +} + void DataArrayDoubleCollection::SynchronizeFineToCoarse(int ghostLev, const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh, int patchId, const DataArrayDoubleCollection *fine, DataArrayDoubleCollection *coarse) { if(!fine || !coarse) @@ -174,7 +251,9 @@ void DataArrayDoubleCollection::SynchronizeGhostZoneOfOneUsingTwo(int ghostLev, for(std::size_t i=0;i_arrs[i].first); - MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoMixedLev(ghostLev,p1,p2,const_cast(zeArrWhichGhostsWillBeUpdated),p2dac->_arrs[i].first); + DataArrayDoubleCollection::CheckSameNatures(p1dac->_arrs[i].second,p2dac->_arrs[i].second); + bool isConservative(DataArrayDoubleCollection::IsConservativeNature(p1dac->_arrs[i].second)); + MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoMixedLev(ghostLev,p1,p2,const_cast(zeArrWhichGhostsWillBeUpdated),p2dac->_arrs[i].first,isConservative); } } @@ -216,6 +295,12 @@ DataArrayDoubleCollection::DataArrayDoubleCollection(const std::vector< std::pai for(std::size_t i=0;i& info(fieldNames[i]); + if(info.second<=0) + { + std::ostringstream oss; oss << "DataArrayDoubleCollection constructor : At pos #" << i << " the array with name \"" << info.first << "\" as a number of components equal to " << info.second; + oss << " It has to be >=1 !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } _arrs[i].first=DataArrayDouble::New(); _arrs[i].first->alloc(0,info.second); _arrs[i].first->setName(info.first); @@ -244,15 +329,11 @@ std::size_t DataArrayDoubleCollection::getHeapMemorySizeWithoutChildren() const return ret; } -std::vector DataArrayDoubleCollection::getDirectChildren() const +std::vector DataArrayDoubleCollection::getDirectChildrenWithNull() const { std::vector ret; for(std::vector< std::pair< MEDCouplingAutoRefCountObjectPtr, NatureOfField > >::const_iterator it=_arrs.begin();it!=_arrs.end();it++) - { - const DataArrayDouble *pt((*it).first); - if(pt) - ret.push_back(pt); - } + ret.push_back((const DataArrayDouble *)(*it).first); return ret; } @@ -298,9 +379,9 @@ MEDCouplingGridCollection *MEDCouplingGridCollection::New(const std::vector& n (*it).second->spillNatures(nfs); } +std::vector< std::pair > > MEDCouplingGridCollection::getInfoOnComponents() const +{ + if(_map_of_dadc.empty()) + throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::getInfoOnComponents : empty map !"); + const DataArrayDoubleCollection *elt(_map_of_dadc[0].second); + if(!elt) + throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::getInfoOnComponents : null pointer !"); + return elt->getInfoOnComponents(); +} + +std::vector MEDCouplingGridCollection::getNatures() const +{ + if(_map_of_dadc.empty()) + throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::getNatures : empty map !"); + const DataArrayDoubleCollection *elt(_map_of_dadc[0].second); + if(!elt) + throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::getNatures : null pointer !"); + return elt->getNatures(); +} + bool MEDCouplingGridCollection::presenceOf(const MEDCouplingCartesianAMRMeshGen *m, int& pos) const { int ret(0); @@ -361,6 +462,52 @@ const DataArrayDoubleCollection& MEDCouplingGridCollection::getFieldsAt(int pos) return *_map_of_dadc[pos].second; } +DataArrayDoubleCollection& MEDCouplingGridCollection::getFieldsAt(int pos) +{ + if(pos<0 || pos>(int)_map_of_dadc.size()) + throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::getFieldsAt (non const) : invalid pos given in input ! Must be in [0,size) !"); + return *_map_of_dadc[pos].second; +} + +/*! + * This method copies for all grids intersecting themselves (between \a this and \a other), the values of fields of \a other to the intersecting + * part of fields of \a this. The fields are expected to be the same between \a other and \a this. + * This methods makes the hypothesis that \a this and \a other share two god father that are compatible each other that is to say with the same cell grid structure. + */ +void MEDCouplingGridCollection::copyOverlappedZoneFrom(int ghostLev, const MEDCouplingGridCollection& other) +{ + for(std::vector< std::pair > >::iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++) + { + std::vector deltaThis,deltaOther; + std::vector< std::pair > rgThis((*it).first->positionRelativeToGodFather(deltaThis)); + std::vector thisSt((*it).first->getImageMesh()->getCellGridStructure()); + std::transform(thisSt.begin(),thisSt.end(),thisSt.begin(),std::bind2nd(std::plus(),2*ghostLev)); + for(std::vector< std::pair > >::const_iterator it2=other._map_of_dadc.begin();it2!=other._map_of_dadc.end();it2++) + { + std::vector< std::pair > rgOther((*it2).first->positionRelativeToGodFather(deltaOther)); + if(MEDCouplingStructuredMesh::AreRangesIntersect(rgThis,rgOther)) + { + std::vector< std::pair > isect(MEDCouplingStructuredMesh::IntersectRanges(rgThis,rgOther)); + std::vector< std::pair > pThis,pOther; + MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(rgThis,isect,pThis,true); + MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(rgOther,isect,pOther,true); + std::vector otherSt((*it2).first->getImageMesh()->getCellGridStructure()); + MEDCouplingStructuredMesh::ApplyGhostOnCompactFrmt(pThis,ghostLev); + MEDCouplingStructuredMesh::ApplyGhostOnCompactFrmt(pOther,ghostLev); + std::transform(otherSt.begin(),otherSt.end(),otherSt.begin(),std::bind2nd(std::plus(),2*ghostLev)); + int sz((*it2).second->size()); + for(int i=0;iat(i)); + DataArrayDouble *thisArr((*it).second->at(i)); + MEDCouplingAutoRefCountObjectPtr partOfOther(MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom(otherSt,otherArr,pOther)); + MEDCouplingStructuredMesh::AssignPartOfFieldOfDoubleUsing(thisSt,thisArr,pThis,partOfOther); + } + } + } + } +} + void MEDCouplingGridCollection::SynchronizeFineToCoarse(int ghostLev, const MEDCouplingGridCollection *fine, const MEDCouplingGridCollection *coarse) { if(!fine || !coarse) @@ -539,12 +686,13 @@ MEDCouplingGridCollection::MEDCouplingGridCollection(const std::vector pos(other._map_of_dadc[i].first->getPositionRelativeTo(oldGf)); + _map_of_dadc[i].first=newGf->getMeshAtPosition(pos); const DataArrayDoubleCollection *dac(other._map_of_dadc[i].second); if(dac) _map_of_dadc[i].second=dac->deepCpy(); @@ -558,15 +706,11 @@ std::size_t MEDCouplingGridCollection::getHeapMemorySizeWithoutChildren() const return ret; } -std::vector MEDCouplingGridCollection::getDirectChildren() const +std::vector MEDCouplingGridCollection::getDirectChildrenWithNull() const { std::vector ret; for(std::vector< std::pair > >::const_iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++) - { - const DataArrayDoubleCollection *col((*it).second); - if(col) - ret.push_back(col); - } + ret.push_back((const DataArrayDoubleCollection *)(*it).second); return ret; } @@ -583,16 +727,17 @@ void MEDCouplingGridCollection::updateTime() const } } -MEDCouplingCartesianAMRPatchGF::MEDCouplingCartesianAMRPatchGF(MEDCouplingCartesianAMRMesh *mesh):MEDCouplingCartesianAMRPatchGen(mesh) +MEDCouplingCartesianAMRMesh *MEDCouplingDataForGodFather::getMyGodFather() { + return _gf; } -std::size_t MEDCouplingCartesianAMRPatchGF::getHeapMemorySizeWithoutChildren() const +const MEDCouplingCartesianAMRMesh *MEDCouplingDataForGodFather::getMyGodFather() const { - return sizeof(MEDCouplingCartesianAMRPatchGF); + return _gf; } -MEDCouplingDataForGodFather::MEDCouplingDataForGodFather(MEDCouplingCartesianAMRMeshGen *gf):_gf(gf),_tlc(gf) +MEDCouplingDataForGodFather::MEDCouplingDataForGodFather(MEDCouplingCartesianAMRMesh *gf):_gf(gf),_tlc(gf) { if(!gf) throw INTERP_KERNEL::Exception("MEDCouplingDataForGodFather constructor : A data has to be attached to a AMR Mesh instance !"); @@ -604,7 +749,7 @@ void MEDCouplingDataForGodFather::checkGodFatherFrozen() const _tlc.checkConst(); } -bool MEDCouplingDataForGodFather::changeGodFather(MEDCouplingCartesianAMRMeshGen *gf) +bool MEDCouplingDataForGodFather::changeGodFather(MEDCouplingCartesianAMRMesh *gf) { bool ret(_tlc.keepTrackOfNewTL(gf)); if(ret) @@ -616,20 +761,27 @@ bool MEDCouplingDataForGodFather::changeGodFather(MEDCouplingCartesianAMRMeshGen return ret; } -MEDCouplingDataForGodFather::MEDCouplingDataForGodFather(const MEDCouplingDataForGodFather& other):RefCountObject(other),_gf(other._gf),_tlc(other._gf) +MEDCouplingDataForGodFather::MEDCouplingDataForGodFather(const MEDCouplingDataForGodFather& other, bool deepCpyGF):RefCountObject(other),_gf(other._gf),_tlc(other._gf) { other._tlc.checkConst(); + if(deepCpyGF) + { + const MEDCouplingCartesianAMRMesh *gf(other._gf); + if(gf) + _gf=gf->deepCpy(0); + _tlc.keepTrackOfNewTL(_gf); + } } /*! * This method creates, attach to a main AMR mesh \a gf ( called god father :-) ) and returns a data linked to \a gf ready for the computation. */ -MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::New(MEDCouplingCartesianAMRMeshGen *gf, const std::vector< std::pair >& fieldNames, int ghostLev) +MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::New(MEDCouplingCartesianAMRMesh *gf, const std::vector< std::pair >& fieldNames, int ghostLev) { return new MEDCouplingAMRAttribute(gf,fieldNames,ghostLev); } -MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::New(MEDCouplingCartesianAMRMeshGen *gf, const std::vector< std::pair > >& fieldNames, int ghostLev) +MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::New(MEDCouplingCartesianAMRMesh *gf, const std::vector< std::pair > >& fieldNames, int ghostLev) { std::size_t sz(fieldNames.size()); std::vector< std::pair > fieldNames2(sz); @@ -671,7 +823,12 @@ void MEDCouplingAMRAttribute::spillNatures(const std::vector& nfs MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::deepCpy() const { - return new MEDCouplingAMRAttribute(*this); + return new MEDCouplingAMRAttribute(*this,true); +} + +MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::deepCpyWithoutGodFather() const +{ + return new MEDCouplingAMRAttribute(*this,false); } /*! @@ -719,7 +876,21 @@ const DataArrayDouble *MEDCouplingAMRAttribute::getFieldOn(MEDCouplingCartesianA return ddc.getFieldWithName(fieldName); } } - throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::retrieveFieldOn : the mesh specified is not in the progeny of this !"); + throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::getFieldOn : the mesh specified is not in the progeny of this !"); +} + +DataArrayDouble *MEDCouplingAMRAttribute::getFieldOn(MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) +{ + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::iterator it=_levs.begin();it!=_levs.end();it++) + { + int tmp(-1); + if((*it)->presenceOf(mesh,tmp)) + { + DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp)); + return ddc.getFieldWithName(fieldName); + } + } + throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::getFieldOn non const : the mesh specified is not in the progeny of this !"); } /*! @@ -791,7 +962,6 @@ MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnWithGhost(MEDCo */ MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnWithoutGhost(MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) const { - //tony const DataArrayDouble *arr(0); for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_levs.begin();it!=_levs.end();it++) { @@ -822,9 +992,169 @@ MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnWithoutGhost(ME return ret.retn(); } + +std::string MEDCouplingAMRAttribute::writeVTHB(const std::string& fileName) const +{ + static const char EXT[]=".vthb"; + std::string baseName,extName,zeFileName; + MEDCouplingMesh::SplitExtension(fileName,baseName,extName); + if(extName==EXT) + zeFileName=fileName; + else + { zeFileName=baseName; zeFileName+=EXT; } + // + std::ofstream ofs(fileName.c_str()); + ofs << "\n"; + const MEDCouplingCartesianAMRMesh *gf(getMyGodFather()); + ofs << " getImageMesh()); + std::vector orig(gfm->getOrigin()); + std::vector spacing(gfm->getDXYZ()); + int dim((int)orig.size()); + std::copy(orig.begin(),orig.end(),std::ostream_iterator(ofs," ")); ofs << "\" grid_description=\""; + for(int i=0;i\n"; + // + int maxLev(gf->getMaxNumberOfLevelsRelativeToThis()),kk(0); + for(int i=0;i patches(gf->retrieveGridsAt(i)); + std::size_t sz(patches.size()); + std::vector< MEDCouplingAutoRefCountObjectPtr > patchesSafe(sz); + for(std::size_t j=0;j(ofs," ")); + ofs << "\">\n"; + if(i!=maxLev-1) + { + std::vector factors(patches[0]->getMesh()->getFactors()); + for(int k=0;k::const_iterator it=patches.begin();it!=patches.end();it++,jj++,kk++) + { + ofs << " (*it)); + const MEDCouplingCartesianAMRMeshGen *mesh((*it)->getMesh()); + if(patchCast) + { + const std::vector< std::pair >& bltr(patchCast->getBLTRRangeRelativeToGF()); + for(int pp=0;ppgetMesh()->getImageMesh()); + std::vector cgs(im->getCellGridStructure()); + for(int pp=0;pppresenceOf((*it)->getMesh(),tmp)) + { + const DataArrayDoubleCollection& ddc(_levs[i]->getFieldsAt(tmp)); + std::vector arrs(ddc.retrieveFields()); + std::size_t nbFields(arrs.size()); + std::vector< MEDCouplingAutoRefCountObjectPtr > arrsSafe(nbFields),arrs2Safe(nbFields); + std::vector< const MEDCouplingFieldDouble *> fields(nbFields); + std::vector< MEDCouplingAutoRefCountObjectPtr > fieldsSafe(nbFields); + for(std::size_t pp=0;pp im(mesh->getImageMesh()->buildWithGhost(_ghost_lev)); + std::vector cgs(mesh->getImageMesh()->getCellGridStructure()),cgsWG(im->getCellGridStructure()); + arrs2Safe[pp]=DataArrayDouble::New(); + arrs2Safe[pp]->alloc(mesh->getImageMesh()->getNumberOfCells(),arrs[pp]->getNumberOfComponents()); + std::vector< std::pair > cgs2(MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(cgs)); + MEDCouplingStructuredMesh::ApplyGhostOnCompactFrmt(cgs2,_ghost_lev); + std::vector fakeFactors(mesh->getImageMesh()->getSpaceDimension(),1); + MEDCouplingIMesh::SpreadCoarseToFine(arrs[pp],cgsWG,arrs2Safe[pp],cgs2,fakeFactors); + arrs2Safe[pp]->copyStringInfoFrom(*arrs[pp]); + // + fieldsSafe[pp]=MEDCouplingFieldDouble::New(ON_CELLS); fields[pp]=fieldsSafe[pp]; + fieldsSafe[pp]->setMesh(mesh->getImageMesh()); + fieldsSafe[pp]->setArray(arrs2Safe[pp]); + fieldsSafe[pp]->setName(arrs[pp]->getName()); + } + std::ostringstream vtiFileName; vtiFileName << baseName << "_" << kk << ".vti"; + MEDCouplingFieldDouble::WriteVTK(vtiFileName.str(),fields,true); + // + ofs << vtiFileName.str() << "\">\n"; + ofs << " \n \n"; + } + } + ofs << " \n"; + } + // + ofs << " \n"; + ofs << "\n"; + return zeFileName; +} + + /*! + * This method is useful just after a remesh after a time step computation to project values in \a this to the new + * mesh \a targetGF. + * + * This method performs a projection from \a this to a target AMR mesh \a targetGF. + * This method performs the projection by trying to transfer the finest information to \a targetGF. + * \b WARNING this method does not update the ghost zone, if any. + * The level0 of \a this god father must have the same structure than those of \a targetGF. + * + * This method makes checks that ghost size of \a this and \a targetGF are the same, and that + * the number of levels in \a this and in \a targetGF are also the same. + */ +MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::projectTo(MEDCouplingCartesianAMRMesh *targetGF) const +{ + if(!targetGF) + throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::projectTo : given other target god is NULL !"); + if(_levs.empty()) + throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::projectTo : no levels in this !"); + const MEDCouplingGridCollection *lev0(_levs[0]); + if(!lev0) + throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::projectTo : lev0 is NULL !"); + std::vector< std::pair < std::string, std::vector > > fieldNames(lev0->getInfoOnComponents()); + MEDCouplingAutoRefCountObjectPtr ret(MEDCouplingAMRAttribute::New(targetGF,fieldNames,_ghost_lev)); + ret->spillNatures(lev0->getNatures()); + ret->alloc(); + int nbLevs(getNumberOfLevels()); + if(targetGF->getMaxNumberOfLevelsRelativeToThis()!=nbLevs) + throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::projectTo : number of levels of this and targetGF must be the same !"); + // first step copy level0 + if(getMyGodFather()->getImageMesh()->getCellGridStructure()!=targetGF->getImageMesh()->getCellGridStructure()) + throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::projectTo : god father of this and target ones do not have the same structure !"); + const DataArrayDoubleCollection& col(lev0->getFieldsAt(0)); + DataArrayDoubleCollection& colTarget(ret->_levs[0]->getFieldsAt(0)); + colTarget.copyFrom(col); + // then go deeper and deeper + for(int i=1;isynchronizeCoarseToFineByOneLevel(i-1); + MEDCouplingGridCollection *targetCol(ret->_levs[i]); + if(!targetCol) + throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::projectTo : null lev of target !"); + const MEDCouplingGridCollection *thisCol(_levs[i]); + if(!thisCol) + throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::projectTo : null lev of this !"); + targetCol->copyOverlappedZoneFrom(_ghost_lev,*thisCol); + } + return ret.retn(); +} + /*! * This method synchronizes from fine to coarse direction arrays. This method makes the hypothesis that \a this has been allocated before using * MEDCouplingAMRAttribute::alloc method. + * This method \b DOES \b NOT \b UPDATE the ghost zones (neither the fine not the coarse) * * \sa synchronizeFineToCoarseBetween */ @@ -845,6 +1175,7 @@ void MEDCouplingAMRAttribute::synchronizeFineToCoarse() * This method allows to synchronizes fields on fine patches on level \a fromLev to coarser patches at \a toLev level. * This method operates step by step performing the synchronization the \a fromLev to \a fromLev - 1, then \a fromLev -1 to \a fromLev - 2 ... * until reaching \a toLev level. + * This method \b DOES \b NOT \b UPDATE the ghost zones (neither the fine not the coarse). * * \param [in] fromLev - an existing level considered as fine so bigger than \a toLev * \param [in] toLev - an existing level considered as the target level to reach. @@ -866,6 +1197,7 @@ void MEDCouplingAMRAttribute::synchronizeFineToCoarseBetween(int fromLev, int to /*! * This method synchronizes from coarse to fine arrays and fine to fine each other (if _ghost_lev is >0). This method makes the hypothesis that \a this has been allocated before using * MEDCouplingAMRAttribute::alloc method. + * This method \b DOES \b UPDATE \b the \b ghost \b zone (contrary to synchronizeFineToCoarse method) */ void MEDCouplingAMRAttribute::synchronizeCoarseToFine() { @@ -881,6 +1213,7 @@ void MEDCouplingAMRAttribute::synchronizeCoarseToFine() * This method allows to synchronizes fields on coarse patches on level \a fromLev to their respective refined patches at \a toLev level. * This method operates step by step performing the synchronization the \a fromLev to \a fromLev + 1, then \a fromLev + 1 to \a fromLev + 2 ... * until reaching \a toLev level. + * This method \b DOES \b UPDATE \b the \b ghost \b zone (contrary to synchronizeFineToCoarseBetween method) * * \param [in] fromLev - an existing level considered as coarse so lower than \a toLev * \param [in] toLev - an existing level considered as the target level to reach. @@ -912,22 +1245,22 @@ void MEDCouplingAMRAttribute::synchronizeCoarseToFineBetween(int fromLev, int to */ void MEDCouplingAMRAttribute::synchronizeAllGhostZones() { - if(_levs.empty()) + int sz(getNumberOfLevels()); + if(sz==0) throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineEachOther : not any levels in this !"); // 1st - synchronize from coarse to the finest all the patches (excepted the god father one) - std::size_t sz(_levs.size()); - for(std::size_t i=1;isynchronizeFineEachOther(_ghost_lev,_neighbors[i]); + curLev->synchronizeFineEachOther(_ghost_lev,_neighbors[i]); } // 3rd - mixed level for(std::vector< std::pair >::const_iterator it=_mixed_lev_neighbors.begin();it!=_mixed_lev_neighbors.end();it++) @@ -936,13 +1269,78 @@ void MEDCouplingAMRAttribute::synchronizeAllGhostZones() DataArrayDoubleCollection::SynchronizeGhostZoneOfOneUsingTwo(_ghost_lev,(*it).first,firstDAC,(*it).second,secondDAC); } // 4th - same level but with far ancestor. - for(std::size_t i=1;isynchronizeFineEachOtherExt(_ghost_lev,_cross_lev_neighbors[i]); } } +/*! + * This method works \b ONLY \b ON \b DIRECT \b SONS \b OF \a mesh. So only a part of patches at a given level is updated here. + * The ghost zone of all of these sons of \a mesh are updated using the brother patches (the patches sharing the \b SAME \a mesh). + * It is sometimes possible that a ghost zone of some sons of \a mesh are covered by a patch of same level but different father. + * For such cases, the ghost zones are \b NOT updated. If you need a more thorough (but more costly) ghost zone update use synchronizeAllGhostZonesAtASpecifiedLevel method instead. + * + * \param [in] mesh - an element in the progeny of god father in \a this, which the ghost zone of its sons will be updated each other. + * + */ +void MEDCouplingAMRAttribute::synchronizeAllGhostZonesOfDirectChidrenOf(const MEDCouplingCartesianAMRMeshGen *mesh) +{ + if(!mesh) + throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeAllGhostZonesOfDirectChidrenOf : input mesh is NULL !"); + int level(mesh->getAbsoluteLevelRelativeTo(_gf)),sz(getNumberOfLevels()); + if(level<0 || level>=sz-1) + throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeAllGhostZonesOfDirectChidrenOf : the specified level does not exist ! Must be in [0,nbOfLevelsOfThis-1) !"); + const std::vector< std::pair >& itemsToFilter(_neighbors[level+1]); + std::vector< std::pair > itemsToSync; itemsToSync.reserve(itemsToFilter.size()); + for(std::vector< std::pair >::const_iterator it=itemsToFilter.begin();it!=itemsToFilter.end();it++) + { + if((*it).first->getMesh()->getFather()==mesh && (*it).second->getMesh()->getFather()==mesh) + itemsToSync.push_back(std::pair((*it).first,(*it).second)); + } + const MEDCouplingGridCollection *curLev(_levs[level+1]); + if(!curLev) + throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeAllGhostZonesOfDirectChidrenOf : presence of a NULL element !"); + curLev->synchronizeFineEachOther(_ghost_lev,itemsToSync); +} + +/*! + * This method updates \b all the patches at level \a level each other without consideration of their father. + * So this method is more time consuming than synchronizeAllGhostZonesOfDirectChidrenOf. + */ +void MEDCouplingAMRAttribute::synchronizeAllGhostZonesAtASpecifiedLevel(int level) +{ + int maxLev(getNumberOfLevels()); + if(level<0 || level>=maxLev) + throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeAllGhostZonesAtASpecifiedLevel : the specified level must be in [0,maxLevel) !"); + if(level==0) + return ;//at level 0 only one patch -> no need to update + // 1st step - updates all patches pairs at level \a level sharing the same father + const std::vector< std::pair >& items(_neighbors[level]); + const MEDCouplingGridCollection *curLev(_levs[level]); + if(!curLev) + throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeAllGhostZonesAtASpecifiedLevel : presence of a NULL element !"); + curLev->synchronizeFineEachOther(_ghost_lev,items); + //2nd step - updates all patches pairs at level \a level not sharing the same father + const std::vector< std::pair >& items2(_cross_lev_neighbors[level]); + curLev->synchronizeFineEachOtherExt(_ghost_lev,items2); +} + +/*! + * This method updates ghost zones of patches at level \a level whatever their father \b using \b father \b patches \b ONLY (at level \b level - 1). + * This method is useful to propagate to the ghost zone of childhood the modification. + */ +void MEDCouplingAMRAttribute::synchronizeAllGhostZonesAtASpecifiedLevelUsingOnlyFather(int level) +{ + int maxLev(getNumberOfLevels()); + if(level<=0 || level>=maxLev) + throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeAllGhostZonesAtASpecifiedLevelUsingOnlyFather : the specified level must be in (0,maxLevel) !"); + const MEDCouplingGridCollection *fine(_levs[level]),*coarse(_levs[level-1]); + MEDCouplingGridCollection::SynchronizeCoarseToFineOnlyInGhostZone(_ghost_lev,coarse,fine); + //_cross_lev_neighbors is not needed. +} + /*! * This method allocates all DataArrayDouble instances stored recursively in \a this. * @@ -978,7 +1376,7 @@ void MEDCouplingAMRAttribute::dealloc() } } -bool MEDCouplingAMRAttribute::changeGodFather(MEDCouplingCartesianAMRMeshGen *gf) +bool MEDCouplingAMRAttribute::changeGodFather(MEDCouplingCartesianAMRMesh *gf) { bool ret(MEDCouplingDataForGodFather::changeGodFather(gf)); return ret; @@ -991,15 +1389,11 @@ std::size_t MEDCouplingAMRAttribute::getHeapMemorySizeWithoutChildren() const return ret; } -std::vector MEDCouplingAMRAttribute::getDirectChildren() const +std::vector MEDCouplingAMRAttribute::getDirectChildrenWithNull() const { std::vector ret; for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_levs.begin();it!=_levs.end();it++) - { - const MEDCouplingGridCollection *elt(*it); - if(elt) - ret.push_back(elt); - } + ret.push_back((const MEDCouplingGridCollection *)*it); return ret; } @@ -1007,7 +1401,7 @@ void MEDCouplingAMRAttribute::updateTime() const {//tony } -MEDCouplingAMRAttribute::MEDCouplingAMRAttribute(MEDCouplingCartesianAMRMeshGen *gf, const std::vector< std::pair >& fieldNames, int ghostLev):MEDCouplingDataForGodFather(gf),_ghost_lev(ghostLev) +MEDCouplingAMRAttribute::MEDCouplingAMRAttribute(MEDCouplingCartesianAMRMesh *gf, const std::vector< std::pair >& fieldNames, int ghostLev):MEDCouplingDataForGodFather(gf),_ghost_lev(ghostLev) { //gf non empty, checked by constructor int maxLev(gf->getMaxNumberOfLevelsRelativeToThis()); @@ -1055,7 +1449,7 @@ MEDCouplingAMRAttribute::MEDCouplingAMRAttribute(MEDCouplingCartesianAMRMeshGen } } -MEDCouplingAMRAttribute::MEDCouplingAMRAttribute(const MEDCouplingAMRAttribute& other):MEDCouplingDataForGodFather(other),_ghost_lev(other._ghost_lev),_levs(other._levs.size()),_neighbors(other._neighbors),_mixed_lev_neighbors(other._mixed_lev_neighbors),_cross_lev_neighbors(other._cross_lev_neighbors) +MEDCouplingAMRAttribute::MEDCouplingAMRAttribute(const MEDCouplingAMRAttribute& other, bool deepCpyGF):MEDCouplingDataForGodFather(other,deepCpyGF),_ghost_lev(other._ghost_lev),_levs(other._levs.size()),_neighbors(other._neighbors),_mixed_lev_neighbors(other._mixed_lev_neighbors),_cross_lev_neighbors(other._cross_lev_neighbors) { std::size_t sz(other._levs.size()); for(std::size_t i=0;ideepCpy(); + _levs[i]=other._levs[i]->deepCpy(_gf,other._gf); + } + } + //_cross_lev_neighbors(other._cross_lev_neighbors) + sz=other._neighbors.size(); + for(std::size_t i=0;i >& neigh2(other._neighbors[i]); + std::size_t sz2(neigh2.size()); + std::vector< std::pair >& neigh3(_neighbors[i]); + for(std::size_t j=0;j pp1(p1->getMesh()->getPositionRelativeTo(other._gf)),pp2(p2->getMesh()->getPositionRelativeTo(other._gf)); + neigh3[j].first=_gf->getPatchAtPosition(pp1); + neigh3[j].second=_gf->getPatchAtPosition(pp2); + } + } + // + sz=other._mixed_lev_neighbors.size(); + for(std::size_t i=0;i pp1(p1->getMesh()->getPositionRelativeTo(other._gf)),pp2(p2->getMesh()->getPositionRelativeTo(other._gf)); + _mixed_lev_neighbors[i].first=_gf->getPatchAtPosition(pp1); + _mixed_lev_neighbors[i].second=_gf->getPatchAtPosition(pp2); + } + // + sz=other._cross_lev_neighbors.size(); + for(std::size_t i=0;i >& neigh2(other._cross_lev_neighbors[i]); + std::size_t sz2(neigh2.size()); + std::vector< std::pair >& neigh3(_cross_lev_neighbors[i]); + for(std::size_t j=0;j pp1(p1->getMesh()->getPositionRelativeTo(other._gf)),pp2(p2->getMesh()->getPositionRelativeTo(other._gf)); + neigh3[j].first=_gf->getPatchAtPosition(pp1); + neigh3[j].second=_gf->getPatchAtPosition(pp2); } } }