Salome HOME
Merge branch 'master' of salome:modules/med
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingCartesianAMRMesh.cxx
1 // Copyright (C) 2007-2014  CEA/DEN, EDF R&D
2 //
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.
7 //
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.
12 //
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
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay
20
21 #include "MEDCouplingCartesianAMRMesh.hxx"
22 #include "MEDCouplingIMesh.hxx"
23 #include "MEDCouplingUMesh.hxx"
24
25 #include <limits>
26 #include <sstream>
27
28 using namespace ParaMEDMEM;
29
30 /// @cond INTERNAL
31
32 /*!
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  */
37 MEDCouplingCartesianAMRPatch::MEDCouplingCartesianAMRPatch(MEDCouplingCartesianAMRMesh *mesh, const std::vector< std::pair<int,int> >& bottomLeftTopRight)
38 {
39   if(!mesh)
40     throw INTERP_KERNEL::Exception("EDCouplingCartesianAMRPatch constructor : input mesh is NULL !");
41   _mesh=mesh; _mesh->incrRef();
42   int dim((int)bottomLeftTopRight.size());
43   if(dim!=_mesh->getSpaceDimension())
44     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch constructor : space dimension of father and input bottomLeft/topRight size mismatches !");
45   _bl_tr=bottomLeftTopRight;
46 }
47
48 int MEDCouplingCartesianAMRPatch::getNumberOfCellsRecursiveWithOverlap() const
49 {
50   return _mesh->getNumberOfCellsRecursiveWithOverlap();
51 }
52
53 int MEDCouplingCartesianAMRPatch::getNumberOfCellsRecursiveWithoutOverlap() const
54 {
55   return _mesh->getNumberOfCellsRecursiveWithoutOverlap();
56 }
57
58 int MEDCouplingCartesianAMRPatch::getMaxNumberOfLevelsRelativeToThis() const
59 {
60   return _mesh->getMaxNumberOfLevelsRelativeToThis();
61 }
62
63 void MEDCouplingCartesianAMRPatch::addPatch(const std::vector< std::pair<int,int> >& bottomLeftTopRight, int factor)
64 {
65   return _mesh->addPatch(bottomLeftTopRight,factor);
66 }
67
68 int MEDCouplingCartesianAMRPatch::getNumberOfOverlapedCellsForFather() const
69 {
70   return MEDCouplingStructuredMesh::DeduceNumberOfGivenRangeInCompactFrmt(_bl_tr);
71 }
72
73 std::size_t MEDCouplingCartesianAMRPatch::getHeapMemorySizeWithoutChildren() const
74 {
75   std::size_t ret(sizeof(MEDCouplingCartesianAMRPatch));
76   ret+=_bl_tr.capacity()*sizeof(std::pair<int,int>);
77   return ret;
78 }
79
80 std::vector<const BigMemoryObject *> MEDCouplingCartesianAMRPatch::getDirectChildren() const
81 {
82   std::vector<const BigMemoryObject *> ret;
83   if((const MEDCouplingCartesianAMRMesh *)_mesh)
84     ret.push_back((const MEDCouplingCartesianAMRMesh *)_mesh);
85   return ret;
86 }
87
88 /// @endcond
89
90
91 MEDCouplingCartesianAMRMesh *MEDCouplingCartesianAMRMesh::New(const std::string& meshName, int spaceDim, const int *nodeStrctStart, const int *nodeStrctStop,
92                                               const double *originStart, const double *originStop, const double *dxyzStart, const double *dxyzStop)
93 {
94   return new MEDCouplingCartesianAMRMesh(meshName,spaceDim,nodeStrctStart,nodeStrctStop,originStart,originStop,dxyzStart,dxyzStop);
95 }
96
97 int MEDCouplingCartesianAMRMesh::getSpaceDimension() const
98 {
99   return _mesh->getSpaceDimension();
100 }
101
102 int MEDCouplingCartesianAMRMesh::getMaxNumberOfLevelsRelativeToThis() const
103 {
104   int ret(1);
105   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
106     ret=std::max(ret,(*it)->getMaxNumberOfLevelsRelativeToThis()+1);
107   return ret;
108 }
109
110 int MEDCouplingCartesianAMRMesh::getNumberOfCellsAtCurrentLevel() const
111 {
112   return _mesh->getNumberOfCells();
113 }
114
115 int MEDCouplingCartesianAMRMesh::getNumberOfCellsRecursiveWithOverlap() const
116 {
117   int ret(_mesh->getNumberOfCells());
118   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
119     {
120       ret+=(*it)->getNumberOfCellsRecursiveWithOverlap();
121     }
122   return ret;
123 }
124
125 int MEDCouplingCartesianAMRMesh::getNumberOfCellsRecursiveWithoutOverlap() const
126 {
127   int ret(_mesh->getNumberOfCells());
128   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
129     {
130       ret-=(*it)->getNumberOfOverlapedCellsForFather();
131       ret+=(*it)->getNumberOfCellsRecursiveWithoutOverlap();
132     }
133   return ret;
134 }
135
136 const MEDCouplingCartesianAMRMesh *MEDCouplingCartesianAMRMesh::getFather() const
137 {
138   return _father;
139 }
140
141 const MEDCouplingCartesianAMRMesh *MEDCouplingCartesianAMRMesh::getGodFather() const
142 {
143   if(_father==0)
144     return this;
145   else
146     return _father->getGodFather();
147 }
148
149 void MEDCouplingCartesianAMRMesh::detachFromFather()
150 {
151   _father=0;
152 }
153
154 /*!
155  * \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,
156  *                                a the end cell (\b excluded) of the range for the second element of the pair.
157  * \param [in] factor The != 0 factor of refinement.
158  */
159 void MEDCouplingCartesianAMRMesh::addPatch(const std::vector< std::pair<int,int> >& bottomLeftTopRight, int factor)
160 {
161   MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> mesh(static_cast<MEDCouplingIMesh *>(_mesh->buildStructuredSubPart(bottomLeftTopRight)));
162   mesh->refineWithFactor(factor);
163   MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRMesh> zeMesh(new MEDCouplingCartesianAMRMesh(this,mesh));
164   MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> elt(new MEDCouplingCartesianAMRPatch(zeMesh,bottomLeftTopRight));
165   _patches.push_back(elt);
166 }
167
168 void MEDCouplingCartesianAMRMesh::removePatch(int patchId)
169 {
170   checkPatchId(patchId);
171   int sz((int)_patches.size()),j(0);
172   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> > patches(sz-1);
173   for(int i=0;i<sz;i++)
174     if(i!=patchId)
175       patches[j++]=_patches[i];
176   (const_cast<MEDCouplingCartesianAMRMesh *>(_patches[patchId]->getMesh()))->detachFromFather();
177   _patches=patches;
178   declareAsNew();
179 }
180
181 int MEDCouplingCartesianAMRMesh::getNumberOfPatches() const
182 {
183   return (int)_patches.size();
184 }
185
186 const MEDCouplingCartesianAMRPatch *MEDCouplingCartesianAMRMesh::getPatch(int patchId) const
187 {
188   checkPatchId(patchId);
189   return _patches[patchId];
190 }
191
192 MEDCouplingUMesh *MEDCouplingCartesianAMRMesh::buildUnstructured() const
193 {
194   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> part(_mesh->buildUnstructured());
195   std::vector<bool> bs(_mesh->getNumberOfCells(),false);
196   std::vector<int> cgs(_mesh->getCellGridStructure());
197   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > msSafe(_patches.size()+1);
198   std::size_t ii(0);
199   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++,ii++)
200     {
201       MEDCouplingStructuredMesh::SwitchOnIdsFrom(cgs,(*it)->getBLTRRange(),bs);
202       msSafe[ii+1]=(*it)->getMesh()->buildUnstructured();
203     }
204   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsOff(DataArrayInt::BuildListOfSwitchedOff(bs));
205   msSafe[0]=static_cast<MEDCouplingUMesh *>(part->buildPartOfMySelf(eltsOff->begin(),eltsOff->end(),false));
206   std::vector< const MEDCouplingUMesh * > ms(msSafe.size());
207   for(std::size_t i=0;i<msSafe.size();i++)
208     ms[i]=msSafe[i];
209   return MEDCouplingUMesh::MergeUMeshes(ms);
210 }
211
212 MEDCouplingCartesianAMRMesh::MEDCouplingCartesianAMRMesh(const std::string& meshName, int spaceDim, const int *nodeStrctStart, const int *nodeStrctStop,
213                                          const double *originStart, const double *originStop, const double *dxyzStart, const double *dxyzStop):_father(0)
214 {
215   _mesh=MEDCouplingIMesh::New(meshName,spaceDim,nodeStrctStart,nodeStrctStop,originStart,originStop,dxyzStart,dxyzStop);
216 }
217
218 MEDCouplingCartesianAMRMesh::MEDCouplingCartesianAMRMesh(MEDCouplingCartesianAMRMesh *father, MEDCouplingIMesh *mesh):_father(father)
219 {
220   if(!_father)
221     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh(MEDCouplingIMesh *mesh) constructor : empty father !");
222   if(!mesh)
223     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh(MEDCouplingIMesh *mesh) constructor : The input mesh is null !");
224   mesh->checkCoherency();
225   _mesh=mesh; _mesh->incrRef();
226 }
227
228 void MEDCouplingCartesianAMRMesh::checkPatchId(int patchId) const
229 {
230   int sz(getNumberOfPatches());
231   if(patchId<0 || patchId>=sz)
232     {
233       std::ostringstream oss; oss << "MEDCouplingCartesianAMRMesh::checkPatchId : invalid patchId (" << patchId << ") ! Must be in [0," << sz << ") !";
234       throw INTERP_KERNEL::Exception(oss.str().c_str());
235     }
236 }
237
238 std::size_t MEDCouplingCartesianAMRMesh::getHeapMemorySizeWithoutChildren() const
239 {
240   return sizeof(MEDCouplingCartesianAMRMesh);
241 }
242
243 std::vector<const BigMemoryObject *> MEDCouplingCartesianAMRMesh::getDirectChildren() const
244 {
245   std::vector<const BigMemoryObject *> ret;
246   if((const MEDCouplingIMesh *)_mesh)
247     ret.push_back((const MEDCouplingIMesh *)_mesh);
248   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
249     {
250       if((const MEDCouplingCartesianAMRPatch*)*it)
251         ret.push_back((const MEDCouplingCartesianAMRPatch*)*it);
252     }
253   return ret;
254 }
255
256 void MEDCouplingCartesianAMRMesh::updateTime() const
257 {
258   if((const MEDCouplingIMesh *)_mesh)
259     updateTimeWith(*_mesh);
260   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
261     {
262       const MEDCouplingCartesianAMRPatch *elt(*it);
263       if(!elt)
264         continue;
265       const MEDCouplingCartesianAMRMesh *mesh(elt->getMesh());
266       if(mesh)
267         updateTimeWith(*mesh);
268     }
269 }