1 // Copyright (C) 2007-2014 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // Author : Anthony Geay
21 #include "MEDCouplingCartesianAMRMesh.hxx"
22 #include "MEDCouplingIMesh.hxx"
23 #include "MEDCouplingUMesh.hxx"
28 using namespace ParaMEDMEM;
33 * \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.
34 * \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,
35 * a the end cell (\b excluded) of the range for the second element of the pair.
36 * \param [in] factors The refinement per axis relative to the father of \a this.
38 MEDCouplingCartesianAMRPatch::MEDCouplingCartesianAMRPatch(MEDCouplingCartesianAMRMesh *mesh, const std::vector< std::pair<int,int> >& bottomLeftTopRight, const std::vector<int>& factors)
41 throw INTERP_KERNEL::Exception("EDCouplingCartesianAMRPatch constructor : input mesh is NULL !");
42 _mesh=mesh; _mesh->incrRef();
43 int dim((int)bottomLeftTopRight.size()),dimExp(_mesh->getSpaceDimension());
45 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch constructor : space dimension of father and input bottomLeft/topRight size mismatches !");
46 _bl_tr=bottomLeftTopRight;
47 if((int)factors.size()!=dimExp)
48 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch constructor : space dimension of father and input factors per axis size mismatches !");
52 int MEDCouplingCartesianAMRPatch::getNumberOfCellsRecursiveWithOverlap() const
54 return _mesh->getNumberOfCellsRecursiveWithOverlap();
57 int MEDCouplingCartesianAMRPatch::getNumberOfCellsRecursiveWithoutOverlap() const
59 return _mesh->getNumberOfCellsRecursiveWithoutOverlap();
62 int MEDCouplingCartesianAMRPatch::getMaxNumberOfLevelsRelativeToThis() const
64 return _mesh->getMaxNumberOfLevelsRelativeToThis();
67 void MEDCouplingCartesianAMRPatch::addPatch(const std::vector< std::pair<int,int> >& bottomLeftTopRight, const std::vector<int>& factors)
69 return _mesh->addPatch(bottomLeftTopRight,factors);
72 int MEDCouplingCartesianAMRPatch::getNumberOfOverlapedCellsForFather() const
74 return MEDCouplingStructuredMesh::DeduceNumberOfGivenRangeInCompactFrmt(_bl_tr);
77 std::size_t MEDCouplingCartesianAMRPatch::getHeapMemorySizeWithoutChildren() const
79 std::size_t ret(sizeof(MEDCouplingCartesianAMRPatch));
80 ret+=_bl_tr.capacity()*sizeof(std::pair<int,int>);
84 std::vector<const BigMemoryObject *> MEDCouplingCartesianAMRPatch::getDirectChildren() const
86 std::vector<const BigMemoryObject *> ret;
87 if((const MEDCouplingCartesianAMRMesh *)_mesh)
88 ret.push_back((const MEDCouplingCartesianAMRMesh *)_mesh);
95 MEDCouplingCartesianAMRMesh *MEDCouplingCartesianAMRMesh::New(const std::string& meshName, int spaceDim, const int *nodeStrctStart, const int *nodeStrctStop,
96 const double *originStart, const double *originStop, const double *dxyzStart, const double *dxyzStop)
98 return new MEDCouplingCartesianAMRMesh(meshName,spaceDim,nodeStrctStart,nodeStrctStop,originStart,originStop,dxyzStart,dxyzStop);
101 int MEDCouplingCartesianAMRMesh::getSpaceDimension() const
103 return _mesh->getSpaceDimension();
106 int MEDCouplingCartesianAMRMesh::getMaxNumberOfLevelsRelativeToThis() const
109 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
110 ret=std::max(ret,(*it)->getMaxNumberOfLevelsRelativeToThis()+1);
114 int MEDCouplingCartesianAMRMesh::getNumberOfCellsAtCurrentLevel() const
116 return _mesh->getNumberOfCells();
119 int MEDCouplingCartesianAMRMesh::getNumberOfCellsRecursiveWithOverlap() const
121 int ret(_mesh->getNumberOfCells());
122 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
124 ret+=(*it)->getNumberOfCellsRecursiveWithOverlap();
129 int MEDCouplingCartesianAMRMesh::getNumberOfCellsRecursiveWithoutOverlap() const
131 int ret(_mesh->getNumberOfCells());
132 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
134 ret-=(*it)->getNumberOfOverlapedCellsForFather();
135 ret+=(*it)->getNumberOfCellsRecursiveWithoutOverlap();
140 const MEDCouplingCartesianAMRMesh *MEDCouplingCartesianAMRMesh::getFather() const
145 const MEDCouplingCartesianAMRMesh *MEDCouplingCartesianAMRMesh::getGodFather() const
150 return _father->getGodFather();
153 void MEDCouplingCartesianAMRMesh::detachFromFather()
159 * \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,
160 * a the end cell (\b excluded) of the range for the second element of the pair.
161 * \param [in] factors The != 0 factor of refinement per axis.
163 void MEDCouplingCartesianAMRMesh::addPatch(const std::vector< std::pair<int,int> >& bottomLeftTopRight, const std::vector<int>& factors)
165 MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> mesh(static_cast<MEDCouplingIMesh *>(_mesh->buildStructuredSubPart(bottomLeftTopRight)));
166 mesh->refineWithFactor(factors);
167 MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRMesh> zeMesh(new MEDCouplingCartesianAMRMesh(this,mesh));
168 MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> elt(new MEDCouplingCartesianAMRPatch(zeMesh,bottomLeftTopRight,factors));
169 _patches.push_back(elt);
174 class InternalPatch : public RefCountObjectOnly
177 InternalPatch():_nb_of_true(0) { }
178 double getEfficiency() const { return (double)_nb_of_true/(double)_crit.size(); }
179 int getNumberOfCells() const { return (int)_crit.size(); }
180 void setNumberOfTrue(int nboft) { _nb_of_true=nboft; }
181 std::vector<bool>& getCriterion() { return _crit; }
182 std::vector< std::pair<int,int> >& getPart() { return _part; }
183 const std::vector< std::pair<int,int> >& getConstPart() const { return _part; }
184 bool presenceOfTrue() const { return _nb_of_true>0; }
189 std::vector<bool> _crit;
190 std::vector< std::pair<int,int> > _part;
194 void dissectBigPatch (const Mesh& mesh, const Field& fieldFlag, const unsigned int minCellDirection,
195 const unsigned int big_dims, const int dissect_direction, int cut[3] ) const
199 float * ratio = NULL ;
200 float * ratio_inner = NULL ;
202 ratio = new float [big_dims-1];
203 for(unsigned int id=0; id<big_dims-1; id++)
205 float efficiency[2] ;
206 for(int h=0; h<2; h++)
209 copy(getIndexCorners(),getIndexCorners()+4,rect_h) ;
211 rect_h[dissect_direction+2] = _indexCorners[dissect_direction]+id ;
213 rect_h[dissect_direction] = _indexCorners[dissect_direction]+id+1;
215 Patch patch_h(rect_h);
216 patch_h.computeMesh(mesh);
217 patch_h.computeFieldFlag(fieldFlag);
220 if ( dissect_direction == 0 )
221 nb_cells_h = patch_h.getNx() ;
223 nb_cells_h = patch_h.getNy() ;
225 int nb_cells_flag_h = patch_h.getNumberOfCellsFlags();
226 efficiency[h] = float (nb_cells_flag_h) / float(nb_cells_h) ;
228 ratio[id] = max(efficiency[0],efficiency[1])/
229 min(efficiency[0],efficiency[1]) ;
232 int dim_ratio_inner = big_dims-1-2*(minCellDirection-1) ;
233 ratio_inner = new float [dim_ratio_inner];
234 float min_ratio = 1.E10 ;
236 for(int i=0; i<dim_ratio_inner; i++)
238 if ( ratio[minCellDirection-1+i] < min_ratio )
240 min_ratio = ratio[minCellDirection-1+i] ;
241 index_min = i+minCellDirection ;
245 cut_place = index_min + _indexCorners[dissect_direction] - 1 ;
248 cut[2] = dissect_direction ;
250 delete [] ratio_inner ;
256 * This method creates patches in \a this (by destroying the patches if any). This method uses \a criterion
258 void MEDCouplingCartesianAMRMesh::createPatchesFromCriterion(const INTERP_KERNEL::BoxSplittingOptions& bso, const DataArrayByte *criterion, const std::vector<int>& factors)
260 if(!criterion || !criterion->isAllocated())
261 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createPatchesFromCriterion : the criterion DataArrayByte instance must be allocated and not NULL !");
262 int nbCells(getNumberOfCellsAtCurrentLevel());
263 if(nbCells!=criterion->getNumberOfTuples())
264 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 !");
267 std::vector<int> cgs(_mesh->getCellGridStructure());
268 std::vector<bool> crit(criterion->toVectorOfBool());//check that criterion has one component.
269 std::vector< MEDCouplingAutoRefCountObjectPtr<InternalPatch> > listOfPatches,listOfPatchesOK;
271 MEDCouplingAutoRefCountObjectPtr<InternalPatch> p(new InternalPatch);
272 p->setNumberOfTrue(MEDCouplingStructuredMesh::FindMinimalPartOf(cgs,crit,p->getCriterion(),p->getPart()));
273 if(p->presenceOfTrue())
274 listOfPatches.push_back(p);
275 while(!listOfPatches.empty())
277 std::vector< MEDCouplingAutoRefCountObjectPtr<InternalPatch> > listOfPatchesTmp;
278 for(std::vector< MEDCouplingAutoRefCountObjectPtr<InternalPatch> >::iterator it=listOfPatches.begin();it!=listOfPatches.end();it++)
281 if((*it)->getEfficiency()>=bso.getEffeciency())
283 if((*it)->getNumberOfCells()>=bso.getMaxCells())
289 listOfPatches=listOfPatchesTmp;
291 for(std::vector< MEDCouplingAutoRefCountObjectPtr<InternalPatch> >::const_iterator it=listOfPatchesOK.begin();it!=listOfPatchesOK.end();it++)
293 addPatch((*it)->getConstPart(),factors);
297 void MEDCouplingCartesianAMRMesh::removePatch(int patchId)
299 checkPatchId(patchId);
300 int sz((int)_patches.size()),j(0);
301 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> > patches(sz-1);
302 for(int i=0;i<sz;i++)
304 patches[j++]=_patches[i];
305 (const_cast<MEDCouplingCartesianAMRMesh *>(_patches[patchId]->getMesh()))->detachFromFather();
310 int MEDCouplingCartesianAMRMesh::getNumberOfPatches() const
312 return (int)_patches.size();
315 const MEDCouplingCartesianAMRPatch *MEDCouplingCartesianAMRMesh::getPatch(int patchId) const
317 checkPatchId(patchId);
318 return _patches[patchId];
321 MEDCouplingUMesh *MEDCouplingCartesianAMRMesh::buildUnstructured() const
323 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> part(_mesh->buildUnstructured());
324 std::vector<bool> bs(_mesh->getNumberOfCells(),false);
325 std::vector<int> cgs(_mesh->getCellGridStructure());
326 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > msSafe(_patches.size()+1);
328 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++,ii++)
330 MEDCouplingStructuredMesh::SwitchOnIdsFrom(cgs,(*it)->getBLTRRange(),bs);
331 msSafe[ii+1]=(*it)->getMesh()->buildUnstructured();
333 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsOff(DataArrayInt::BuildListOfSwitchedOff(bs));
334 msSafe[0]=static_cast<MEDCouplingUMesh *>(part->buildPartOfMySelf(eltsOff->begin(),eltsOff->end(),false));
335 std::vector< const MEDCouplingUMesh * > ms(msSafe.size());
336 for(std::size_t i=0;i<msSafe.size();i++)
338 return MEDCouplingUMesh::MergeUMeshes(ms);
341 MEDCouplingCartesianAMRMesh::MEDCouplingCartesianAMRMesh(const std::string& meshName, int spaceDim, const int *nodeStrctStart, const int *nodeStrctStop,
342 const double *originStart, const double *originStop, const double *dxyzStart, const double *dxyzStop):_father(0)
344 _mesh=MEDCouplingIMesh::New(meshName,spaceDim,nodeStrctStart,nodeStrctStop,originStart,originStop,dxyzStart,dxyzStop);
347 MEDCouplingCartesianAMRMesh::MEDCouplingCartesianAMRMesh(MEDCouplingCartesianAMRMesh *father, MEDCouplingIMesh *mesh):_father(father)
350 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh(MEDCouplingIMesh *mesh) constructor : empty father !");
352 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh(MEDCouplingIMesh *mesh) constructor : The input mesh is null !");
353 mesh->checkCoherency();
354 _mesh=mesh; _mesh->incrRef();
357 void MEDCouplingCartesianAMRMesh::checkPatchId(int patchId) const
359 int sz(getNumberOfPatches());
360 if(patchId<0 || patchId>=sz)
362 std::ostringstream oss; oss << "MEDCouplingCartesianAMRMesh::checkPatchId : invalid patchId (" << patchId << ") ! Must be in [0," << sz << ") !";
363 throw INTERP_KERNEL::Exception(oss.str().c_str());
367 std::size_t MEDCouplingCartesianAMRMesh::getHeapMemorySizeWithoutChildren() const
369 return sizeof(MEDCouplingCartesianAMRMesh);
372 std::vector<const BigMemoryObject *> MEDCouplingCartesianAMRMesh::getDirectChildren() const
374 std::vector<const BigMemoryObject *> ret;
375 if((const MEDCouplingIMesh *)_mesh)
376 ret.push_back((const MEDCouplingIMesh *)_mesh);
377 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
379 if((const MEDCouplingCartesianAMRPatch*)*it)
380 ret.push_back((const MEDCouplingCartesianAMRPatch*)*it);
385 void MEDCouplingCartesianAMRMesh::updateTime() const
387 if((const MEDCouplingIMesh *)_mesh)
388 updateTimeWith(*_mesh);
389 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
391 const MEDCouplingCartesianAMRPatch *elt(*it);
394 const MEDCouplingCartesianAMRMesh *mesh(elt->getMesh());
396 updateTimeWith(*mesh);