Salome HOME
Patch creation on multi level.
[modules/med.git] / src / MEDCoupling / MEDCouplingAMRAttribute.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 "MEDCouplingAMRAttribute.hxx"
22 #include "MEDCouplingFieldDouble.hxx"
23 #include "MEDCouplingMemArray.hxx"
24 #include "MEDCouplingIMesh.hxx"
25
26 #include <sstream>
27
28 using namespace ParaMEDMEM;
29
30 DataArrayDoubleCollection *DataArrayDoubleCollection::New(const std::vector< std::pair<std::string,int> >& fieldNames)
31 {
32   return new DataArrayDoubleCollection(fieldNames);
33 }
34
35 void DataArrayDoubleCollection::allocTuples(int nbOfTuples)
36 {
37   std::size_t sz(_arrs.size());
38   for(std::size_t i=0;i<sz;i++)
39     _arrs[i]->reAlloc(nbOfTuples);
40 }
41
42 void DataArrayDoubleCollection::dellocTuples()
43 {
44   std::size_t sz(_arrs.size());
45   for(std::size_t i=0;i<sz;i++)
46     _arrs[i]->reAlloc(0);
47 }
48
49 void DataArrayDoubleCollection::spillInfoOnComponents(const std::vector< std::vector<std::string> >& compNames)
50 {
51   std::size_t sz(_arrs.size());
52   if(sz!=compNames.size())
53     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::spillInfoOnComponents : first size of compNames has to be equal to the number of fields defined !");
54   for(std::size_t i=0;i<sz;i++)
55     {
56       const std::vector<std::string>& names(compNames[i]);
57       _arrs[i]->setInfoOnComponents(names);
58     }
59 }
60
61 std::vector<DataArrayDouble *> DataArrayDoubleCollection::retrieveFields() const
62 {
63   std::size_t sz(_arrs.size());
64   std::vector<DataArrayDouble *> ret(sz);
65   for(std::size_t i=0;i<sz;i++)
66     {
67       const DataArrayDouble *tmp(_arrs[i]);
68       ret[i]=const_cast<DataArrayDouble *>(tmp);
69       if(ret[i])
70         ret[i]->incrRef();
71     }
72   return ret;
73 }
74
75 const DataArrayDouble *DataArrayDoubleCollection::getFieldWithName(const std::string& name) const
76 {
77   std::vector<std::string> vec;
78   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> >::const_iterator it=_arrs.begin();it!=_arrs.end();it++)
79     {
80       const DataArrayDouble *obj(*it);
81       if(obj)
82         {
83           if(obj->getName()==name)
84             return obj;
85           else
86             vec.push_back(obj->getName());
87         }
88     }
89   std::ostringstream oss; oss << "DataArrayDoubleCollection::getFieldWithName : fieldName \"" << name << "\" does not exist in this ! Possibilities are :";
90   std::copy(vec.begin(),vec.end(),std::ostream_iterator<std::string>(oss," "));
91   throw INTERP_KERNEL::Exception(oss.str().c_str());
92 }
93
94 void DataArrayDoubleCollection::SynchronizeFineToCoarse(int ghostLev, const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh, int patchId, const DataArrayDoubleCollection *fine, DataArrayDoubleCollection *coarse)
95 {
96   if(!fine || !coarse)
97     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeFineToCoarse : the input DataArrayDouble collections must be non NULL !");
98   std::size_t sz(coarse->_arrs.size());
99   if(fine->_arrs.size()!=sz)
100     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeFineToCoarse : the input DataArrayDouble collection must have the same size !");
101   for(std::size_t i=0;i<sz;i++)
102     fatherOfFineMesh->fillCellFieldComingFromPatchGhost(patchId,fine->_arrs[i],coarse->_arrs[i],ghostLev);
103 }
104
105 void DataArrayDoubleCollection::SynchronizeCoarseToFine(int ghostLev, const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh, int patchId, const DataArrayDoubleCollection *coarse, DataArrayDoubleCollection *fine)
106 {
107   if(!fine || !coarse)
108     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeCoarseToFine : the input DataArrayDouble collections must be non NULL !");
109   std::size_t sz(coarse->_arrs.size());
110   if(fine->_arrs.size()!=sz)
111     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeCoarseToFine : the input DataArrayDouble collection must have the same size !");
112   for(std::size_t i=0;i<sz;i++)
113     fatherOfFineMesh->fillCellFieldOnPatchGhost(patchId,coarse->_arrs[i],fine->_arrs[i],ghostLev);
114 }
115
116 void DataArrayDoubleCollection::SynchronizeFineEachOther(int patchId, int ghostLev, const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh, const std::vector<const MEDCouplingCartesianAMRMeshGen *>& children, const std::vector<DataArrayDoubleCollection *>& fieldsOnFine)
117 {
118   if(!fatherOfFineMesh)
119     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeFineEachOther : father is NULL !");
120   std::size_t sz(children.size());
121   if(fieldsOnFine.size()!=sz)
122     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeFineEachOther : sizes of vectors mismatch !");
123   if(sz<=1)
124     return ;
125   std::size_t nbOfCall(fieldsOnFine[0]->_arrs.size());
126   for(std::size_t i=0;i<sz;i++)
127     if(fatherOfFineMesh->getPatchIdFromChildMesh(children[i])!=(int)i)
128       throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeFineEachOther : internal error !");
129   for(std::size_t i=1;i<sz;i++)
130     if(nbOfCall!=fieldsOnFine[i]->_arrs.size())
131       throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeFineEachOther : the collection of DataArrayDouble must have all the same size !");
132   for(std::size_t i=0;i<nbOfCall;i++)
133     {
134       std::vector<const DataArrayDouble *> arrs(sz);
135       for(std::size_t j=0;j<sz;j++)
136         arrs[j]=fieldsOnFine[j]->_arrs[i];
137       fatherOfFineMesh->fillCellFieldOnPatchOnlyGhostAdv(patchId,ghostLev,arrs);
138     }
139 }
140
141 /*!
142  * This method updates \a p1dac ghost zone parts using \a p2dac (which is really const). \a p2 is in the neighborhood of \a p1 (which size is defined by \a ghostLev).
143  */
144 void DataArrayDoubleCollection::SynchronizeGhostZoneOfOneUsingTwo(int ghostLev, const MEDCouplingCartesianAMRPatch *p1, const DataArrayDoubleCollection *p1dac, const MEDCouplingCartesianAMRPatch *p2, const DataArrayDoubleCollection *p2dac)
145 {
146   if(!p1 || !p1dac || !p2 || !p2dac)
147     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeGhostZoneOfOneUsingTwo : input pointer must be not NULL !");
148   std::size_t sz(p1dac->_arrs.size());
149   if(p2dac->_arrs.size()!=sz)
150     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeGhostZoneOfOneUsingTwo : size of DataArrayDouble Collection must be the same !");
151   for(std::size_t i=0;i<sz;i++)
152     {
153       const DataArrayDouble *zeArrWhichGhostsWillBeUpdated(p1dac->_arrs[i]);
154       MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoMixedLev(ghostLev,p1,p2,const_cast<DataArrayDouble *>(zeArrWhichGhostsWillBeUpdated),p2dac->_arrs[i]);
155     }
156 }
157
158 void DataArrayDoubleCollection::SynchronizeCoarseToFineOnlyInGhostZone(int ghostLev, const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh, int patchId, const DataArrayDoubleCollection *coarse, DataArrayDoubleCollection *fine)
159 {
160   if(!fine || !coarse)
161     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeCoarseToFineOnlyInGhostZone : the input DataArrayDouble collections must be non NULL !");
162   std::size_t sz(coarse->_arrs.size());
163   if(fine->_arrs.size()!=sz)
164     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeCoarseToFineOnlyInGhostZone : the input DataArrayDouble collection must have the same size !");
165   for(std::size_t i=0;i<sz;i++)
166     fatherOfFineMesh->fillCellFieldOnPatchOnlyOnGhostZone(patchId,coarse->_arrs[i],fine->_arrs[i],ghostLev);
167 }
168
169 void DataArrayDoubleCollection::synchronizeMyGhostZoneUsing(int ghostLev, const DataArrayDoubleCollection& other, const MEDCouplingCartesianAMRPatch *thisp, const MEDCouplingCartesianAMRPatch *otherp, const MEDCouplingCartesianAMRMeshGen *father) const
170 {
171   DataArrayDoubleCollection *thisNC(const_cast<DataArrayDoubleCollection *>(this));
172   std::size_t sz(_arrs.size());
173   if(other._arrs.size()!=sz)
174     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::synchronizeMyGhostZoneUsing : sizes of collections must match !");
175   for(std::size_t i=0;i<sz;i++)
176     father->fillCellFieldOnPatchOnlyOnGhostZoneWith(ghostLev,thisp,otherp,thisNC->_arrs[i],other._arrs[i]);
177 }
178
179 void DataArrayDoubleCollection::synchronizeMyGhostZoneUsingExt(int ghostLev, const DataArrayDoubleCollection& other, const MEDCouplingCartesianAMRPatch *thisp, const MEDCouplingCartesianAMRPatch *otherp) const
180 {
181   DataArrayDoubleCollection *thisNC(const_cast<DataArrayDoubleCollection *>(this));
182   std::size_t sz(_arrs.size());
183   if(other._arrs.size()!=sz)
184     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::synchronizeMyGhostZoneUsingExt : sizes of collections must match !");
185   for(std::size_t i=0;i<sz;i++)
186     MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoExt(ghostLev,thisp,otherp,thisNC->_arrs[i],other._arrs[i]);
187 }
188
189 DataArrayDoubleCollection::DataArrayDoubleCollection(const std::vector< std::pair<std::string,int> >& fieldNames):_arrs(fieldNames.size())
190 {
191   std::size_t sz(fieldNames.size());
192   std::vector<std::string> names(sz);
193   for(std::size_t i=0;i<sz;i++)
194     {
195       const std::pair<std::string,int>& info(fieldNames[i]);
196       _arrs[i]=DataArrayDouble::New();
197       _arrs[i]->alloc(0,info.second);
198       _arrs[i]->setName(info.first);
199       names[i]=info.second;
200     }
201   CheckDiscriminantNames(names);
202 }
203
204 std::size_t DataArrayDoubleCollection::getHeapMemorySizeWithoutChildren() const
205 {
206   std::size_t ret(sizeof(DataArrayDoubleCollection));
207   ret+=_arrs.capacity()*sizeof(MEDCouplingAutoRefCountObjectPtr<DataArrayDouble>);
208   return ret;
209 }
210
211 std::vector<const BigMemoryObject *> DataArrayDoubleCollection::getDirectChildren() const
212 {
213   std::vector<const BigMemoryObject *> ret;
214   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> >::const_iterator it=_arrs.begin();it!=_arrs.end();it++)
215     {
216       const DataArrayDouble *pt(*it);
217       if(pt)
218         ret.push_back(pt);
219     }
220   return ret;
221 }
222
223 void DataArrayDoubleCollection::updateTime() const
224 {
225   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> >::const_iterator it=_arrs.begin();it!=_arrs.end();it++)
226     {
227       const DataArrayDouble *pt(*it);
228       if(pt)
229         updateTimeWith(*pt);
230     }
231 }
232
233 void DataArrayDoubleCollection::CheckDiscriminantNames(const std::vector<std::string>& names)
234 {
235   std::set<std::string> s(names.begin(),names.end());
236   if(s.size()!=names.size())
237     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::CheckDiscriminantNames : The names of fields must be different each other ! It is not the case !");
238 }
239
240 MEDCouplingGridCollection *MEDCouplingGridCollection::New(const std::vector<const MEDCouplingCartesianAMRMeshGen *>& ms, const std::vector< std::pair<std::string,int> >& fieldNames)
241 {
242   return new MEDCouplingGridCollection(ms,fieldNames);
243 }
244
245 void MEDCouplingGridCollection::alloc(int ghostLev)
246 {
247   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
248     {
249       int nbTuples((*it).first->getNumberOfCellsAtCurrentLevelGhost(ghostLev));
250       DataArrayDoubleCollection *dadc((*it).second);
251       if(dadc)
252         dadc->allocTuples(nbTuples);
253       else
254         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::alloc : internal error !");
255     }
256 }
257
258 void MEDCouplingGridCollection::dealloc()
259 {
260   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
261     {
262       DataArrayDoubleCollection *dadc((*it).second);
263       if(dadc)
264         dadc->dellocTuples();
265       else
266         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::dealloc : internal error !");
267     }
268 }
269
270 void MEDCouplingGridCollection::spillInfoOnComponents(const std::vector< std::vector<std::string> >& compNames)
271 {
272   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
273     (*it).second->spillInfoOnComponents(compNames);
274 }
275
276 bool MEDCouplingGridCollection::presenceOf(const MEDCouplingCartesianAMRMeshGen *m, int& pos) const
277 {
278   int ret(0);
279   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++,ret++)
280     {
281       if((*it).first==m)
282         {
283           pos=ret;
284           return true;
285         }
286     }
287   return false;
288 }
289
290 const DataArrayDoubleCollection& MEDCouplingGridCollection::getFieldsAt(int pos) const
291 {
292   if(pos<0 || pos>(int)_map_of_dadc.size())
293     throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::getFieldsAt : invalid pos given in input ! Must be in [0,size) !");
294   return *_map_of_dadc[pos].second;
295 }
296
297 void MEDCouplingGridCollection::SynchronizeFineToCoarse(int ghostLev, const MEDCouplingGridCollection *fine, const MEDCouplingGridCollection *coarse)
298 {
299   if(!fine || !coarse)
300     throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeFineToCoarse : one or more input pointer is NULL !");
301   const std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >& mf(fine->_map_of_dadc);
302   const std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >& mc(coarse->_map_of_dadc);
303   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=mf.begin();it!=mf.end();it++)
304     {
305       const MEDCouplingCartesianAMRMeshGen *fineMesh((*it).first);
306       const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh(fineMesh->getFather());
307       bool found(false);
308       for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it0=mc.begin();it0!=mc.end() && !found;it0++)
309         {
310           if((*it0).first==fatherOfFineMesh)
311             {
312               found=true;
313               int patchId(fatherOfFineMesh->getPatchIdFromChildMesh(fineMesh));
314               const DataArrayDoubleCollection *coarseDaCol((*it0).second);
315               DataArrayDoubleCollection *coarseModified(const_cast<DataArrayDoubleCollection *>(coarseDaCol));//coarse values in DataArrayDouble will be altered
316               DataArrayDoubleCollection::SynchronizeFineToCoarse(ghostLev,fatherOfFineMesh,patchId,(*it).second,coarseModified);
317             }
318         }
319       if(!found)
320         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeFineToCoarse : a fine mesh is orphan regarding given coarse meshes !");
321     }
322 }
323
324 void MEDCouplingGridCollection::SynchronizeCoarseToFine(int ghostLev, const MEDCouplingGridCollection *coarse, const MEDCouplingGridCollection *fine)
325 {
326   if(!fine || !coarse)
327     throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeCoarseToFine : one or more input pointer is NULL !");
328   const std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >& mf(fine->_map_of_dadc);
329   const std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >& mc(coarse->_map_of_dadc);
330   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=mf.begin();it!=mf.end();it++)
331     {
332       const MEDCouplingCartesianAMRMeshGen *fineMesh((*it).first);
333       const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh(fineMesh->getFather());
334       bool found(false);
335       for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it0=mc.begin();it0!=mc.end() && !found;it0++)
336         {
337           if((*it0).first==fatherOfFineMesh)
338             {
339               found=true;
340               int patchId(fatherOfFineMesh->getPatchIdFromChildMesh(fineMesh));
341               const DataArrayDoubleCollection *fineDaCol((*it).second);
342               DataArrayDoubleCollection *fineModified(const_cast<DataArrayDoubleCollection *>(fineDaCol));//fine values in DataArrayDouble will be altered
343               DataArrayDoubleCollection::SynchronizeCoarseToFine(ghostLev,fatherOfFineMesh,patchId,(*it0).second,fineModified);
344             }
345         }
346       if(!found)
347         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeCoarseToFine : a fine mesh is orphan regarding given coarse meshes !");
348     }
349 }
350
351 /*!
352  * All the pairs in \a ps must share the same father. If not call synchronizeFineEachOtherExt instead.
353  *
354  * \sa synchronizeFineEachOtherExt
355  */
356 void MEDCouplingGridCollection::synchronizeFineEachOther(int ghostLev, const std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >& ps) const
357 {
358   for(std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >::const_iterator it=ps.begin();it!=ps.end();it++)
359     {
360       int p1,p2;
361       if(!presenceOf((*it).first->getMesh(),p1))
362         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::synchronizeFineEachOther : internal error #1 !");
363       if(!presenceOf((*it).second->getMesh(),p2))
364         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::synchronizeFineEachOther : internal error #2 !");
365       const DataArrayDoubleCollection& col1(getFieldsAt(p1));
366       const DataArrayDoubleCollection& col2(getFieldsAt(p2));
367       col1.synchronizeMyGhostZoneUsing(ghostLev,col2,(*it).first,(*it).second,(*it).first->getMesh()->getFather());
368     }
369 }
370
371 /*!
372  * This method is a generalization of synchronizeFineEachOther because elements in pairs are \b not sharing the same father but are neighbors nevertheless.
373  *
374  * \sa synchronizeFineEachOther
375  */
376 void MEDCouplingGridCollection::synchronizeFineEachOtherExt(int ghostLev, const std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >& ps) const
377 {
378   for(std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >::const_iterator it=ps.begin();it!=ps.end();it++)
379     {
380       int p1,p2;
381       if(!presenceOf((*it).first->getMesh(),p1))
382         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::synchronizeFineEachOtherExt : internal error #1 !");
383       if(!presenceOf((*it).second->getMesh(),p2))
384         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::synchronizeFineEachOtherExt : internal error #2 !");
385       const DataArrayDoubleCollection& col1(getFieldsAt(p1));
386       const DataArrayDoubleCollection& col2(getFieldsAt(p2));
387       col1.synchronizeMyGhostZoneUsingExt(ghostLev,col2,(*it).first,(*it).second);
388     }
389 }
390
391 /*!
392  * The pairs returned share the same direct father. The number of returned elements must be even.
393  */
394 std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > MEDCouplingGridCollection::findNeighbors(int ghostLev) const
395 {
396   std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > ret;
397   std::map<const MEDCouplingCartesianAMRMeshGen *,std::vector< const MEDCouplingCartesianAMRMeshGen * > > m;
398   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
399     {
400       const MEDCouplingCartesianAMRMeshGen *fineMesh((*it).first);
401       const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh(fineMesh->getFather());
402       m[fatherOfFineMesh].push_back(fineMesh);
403     }
404   for(std::map<const MEDCouplingCartesianAMRMeshGen *,std::vector< const MEDCouplingCartesianAMRMeshGen * > >::const_iterator it0=m.begin();it0!=m.end();it0++)
405     {
406       for(std::vector<const MEDCouplingCartesianAMRMeshGen *>::const_iterator it1=(*it0).second.begin();it1!=(*it0).second.end();it1++)
407         {
408           int patchId((*it0).first->getPatchIdFromChildMesh(*it1));
409           std::vector<int> neighs((*it0).first->getPatchIdsInTheNeighborhoodOf(patchId,ghostLev));
410           const MEDCouplingCartesianAMRPatch *pRef((*it0).first->getPatch(patchId));
411           for(std::vector<int>::const_iterator it2=neighs.begin();it2!=neighs.end();it2++)
412             {
413               const MEDCouplingCartesianAMRPatch *pLoc((*it0).first->getPatch(*it2));
414               ret.push_back(std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *>(pRef,pLoc));
415             }
416         }
417     }
418   if(ret.size()%2!=0)
419     throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::findNeighbors : something is wrong ! The number of neighbor pairs must be %2 ==0 !");
420   return ret;
421 }
422
423 void MEDCouplingGridCollection::SynchronizeCoarseToFineOnlyInGhostZone(int ghostLev, const MEDCouplingGridCollection *coarse, const MEDCouplingGridCollection *fine)
424 {
425   if(!fine || !coarse)
426     throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeCoarseToFineOnlyInGhostZone : one or more input pointer is NULL !");
427   const std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >& mf(fine->_map_of_dadc);
428   const std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >& mc(coarse->_map_of_dadc);
429   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=mf.begin();it!=mf.end();it++)
430     {
431       const MEDCouplingCartesianAMRMeshGen *fineMesh((*it).first);
432       const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh(fineMesh->getFather());
433       bool found(false);
434       for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it0=mc.begin();it0!=mc.end() && !found;it0++)
435         {
436           if((*it0).first==fatherOfFineMesh)
437             {
438               found=true;
439               int patchId(fatherOfFineMesh->getPatchIdFromChildMesh(fineMesh));
440               const DataArrayDoubleCollection *fineDaCol((*it).second);
441               DataArrayDoubleCollection *fineModified(const_cast<DataArrayDoubleCollection *>(fineDaCol));//fine values in DataArrayDouble will be altered
442               DataArrayDoubleCollection::SynchronizeCoarseToFineOnlyInGhostZone(ghostLev,fatherOfFineMesh,patchId,(*it0).second,fineModified);
443             }
444         }
445       if(!found)
446         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeCoarseToFineOnlyInGhostZone : a fine mesh is orphan regarding given coarse meshes !");
447     }
448 }
449
450 void MEDCouplingGridCollection::fillIfInTheProgenyOf(const std::string& fieldName, const MEDCouplingCartesianAMRMeshGen *head, std::vector<const DataArrayDouble *>& recurseArrs) const
451 {
452   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
453     {
454       const MEDCouplingCartesianAMRMeshGen *a((*it).first);
455       if(head==a || head->isObjectInTheProgeny(a))
456         {
457           const DataArrayDoubleCollection *gc((*it).second);
458           recurseArrs.push_back(gc->getFieldWithName(fieldName));
459         }
460     }
461 }
462
463 MEDCouplingGridCollection::MEDCouplingGridCollection(const std::vector<const MEDCouplingCartesianAMRMeshGen *>& ms, const std::vector< std::pair<std::string,int> >& fieldNames):_map_of_dadc(ms.size())
464 {
465   std::size_t sz(ms.size());
466   for(std::size_t i=0;i<sz;i++)
467     {
468       if(!ms[i])
469         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection constructor : presence of NULL MEDCouplingCartesianAMRMeshGen instance !");
470       _map_of_dadc[i].first=ms[i];
471       _map_of_dadc[i].second=DataArrayDoubleCollection::New(fieldNames);
472     }
473 }
474
475 std::size_t MEDCouplingGridCollection::getHeapMemorySizeWithoutChildren() const
476 {
477   std::size_t ret(sizeof(MEDCouplingGridCollection));
478   ret+=_map_of_dadc.capacity()*sizeof(std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> >);
479   return ret;
480 }
481
482 std::vector<const BigMemoryObject *> MEDCouplingGridCollection::getDirectChildren() const
483 {
484   std::vector<const BigMemoryObject *> ret;
485   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
486     {
487       const DataArrayDoubleCollection *col((*it).second);
488       if(col)
489         ret.push_back(col);
490     }
491   return ret;
492 }
493
494 void MEDCouplingGridCollection::updateTime() const
495 {
496   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
497     {
498       const MEDCouplingCartesianAMRMeshGen *a((*it).first);
499       if(a)
500         updateTimeWith(*a);
501       const DataArrayDoubleCollection *b((*it).second);
502       if(b)
503         updateTimeWith(*b);
504     }
505 }
506
507 /*!
508  * 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.
509  */
510 MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::New(MEDCouplingCartesianAMRMeshGen *gf, const std::vector< std::pair<std::string,int> >& fieldNames, int ghostLev)
511 {
512   return new MEDCouplingAMRAttribute(gf,fieldNames,ghostLev);
513 }
514
515 MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::New(MEDCouplingCartesianAMRMeshGen *gf, const std::vector< std::pair<std::string, std::vector<std::string> > >& fieldNames, int ghostLev)
516 {
517   std::size_t sz(fieldNames.size());
518   std::vector< std::pair<std::string,int> > fieldNames2(sz);
519   std::vector< std::vector<std::string> > compNames(sz);
520   for(std::size_t i=0;i<sz;i++)
521     {
522       fieldNames2[i].first=fieldNames[i].first;
523       fieldNames2[i].second=(int)fieldNames[i].second.size();
524       compNames[i]=fieldNames[i].second;
525     }
526   MEDCouplingAutoRefCountObjectPtr<MEDCouplingAMRAttribute> ret(New(gf,fieldNames2,ghostLev));
527   ret->spillInfoOnComponents(compNames);
528   return ret.retn();
529 }
530
531 /*!
532  * Assign the info on components for all DataArrayDouble instance recursively stored in \a this.
533  * The first dim of input \a compNames is the field id in the same order than those implicitely specified in \a fieldNames parameter of MEDCouplingAMRAttribute::New.
534  * The second dim of \a compNames represent the component names component per component corresponding to the field. The size of this 2nd dimension has
535  * to perfectly fit with those specified in MEDCouplingAMRAttribute::New.
536  */
537 void MEDCouplingAMRAttribute::spillInfoOnComponents(const std::vector< std::vector<std::string> >& compNames)
538 {
539   _tlc.checkConst();
540   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::iterator it=_levs.begin();it!=_levs.end();it++)
541     (*it)->spillInfoOnComponents(compNames);
542 }
543
544 /*!
545  * This method returns all DataArrayDouble instances lying on the specified mesh \a mesh.
546  * If \a mesh is not part of the progeny of god father object given at construction of \a this an exception will be thrown.
547  *
548  * \return std::vector<DataArrayDouble *> - DataArrayDouble instances to be deallocated by the caller (using decrRef).
549  * \sa retrieveFieldOn
550  */
551 std::vector<DataArrayDouble *> MEDCouplingAMRAttribute::retrieveFieldsOn(MEDCouplingCartesianAMRMeshGen *mesh) const
552 {
553   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
554     {
555       int tmp(-1);
556       if((*it)->presenceOf(mesh,tmp))
557         {
558           const DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp));
559           return ddc.retrieveFields();
560         }
561     }
562   throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::retrieveFieldsOn : the mesh specified is not in the progeny of this !");
563 }
564
565 /*!
566  * \sa retrieveFieldsOn
567  */
568 const DataArrayDouble *MEDCouplingAMRAttribute::getFieldOn(MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) const
569 {
570   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
571     {
572       int tmp(-1);
573       if((*it)->presenceOf(mesh,tmp))
574         {
575           const DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp));
576           return ddc.getFieldWithName(fieldName);
577         }
578     }
579   throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::retrieveFieldOn : the mesh specified is not in the progeny of this !");
580 }
581
582 /*!
583  * This method returns a field on an unstructured mesh the most refined as possible without overlap.
584  * Ghost part are not visible here.
585  *
586  * \return MEDCouplingFieldDouble * - a field on cells that the caller has to deal with (deallocate it).
587  */
588 MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnRecurseWithoutOverlapWithoutGhost(MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) const
589 {
590   std::vector<const DataArrayDouble *> recurseArrs;
591   std::size_t lev(0);
592   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++,lev++)
593     {
594       int tmp(-1);
595       if((*it)->presenceOf(mesh,tmp))
596         {
597           const DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp));
598           recurseArrs.push_back(ddc.getFieldWithName(fieldName));
599           break;
600         }
601     }
602   lev++;
603   for(std::size_t i=lev;i<_levs.size();i++)
604     {
605       const MEDCouplingGridCollection *gc(_levs[i]);
606       gc->fillIfInTheProgenyOf(fieldName,mesh,recurseArrs);
607     }
608   return mesh->buildCellFieldOnRecurseWithoutOverlapWithoutGhost(_ghost_lev,recurseArrs);
609 }
610
611 /*!
612  * This method builds a newly created field on cell just lying on mesh \a mesh without its eventual refinement.
613  * The output field also displays ghost cells.
614  *
615  * \return MEDCouplingFieldDouble * - a field on cells that the caller has to deal with (deallocate it).
616  *
617  * \sa buildCellFieldOnWithoutGhost
618  */
619 MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnWithGhost(MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) const
620 {
621   const DataArrayDouble *arr(0);
622   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
623     {
624       int tmp(-1);
625       if((*it)->presenceOf(mesh,tmp))
626         {
627           const DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp));
628           arr=ddc.getFieldWithName(fieldName);
629         }
630     }
631   if(!arr)
632     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::buildCellFieldOnWithGhost : the mesh specified is not in the progeny of this !");
633   MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> im(mesh->getImageMesh()->buildWithGhost(_ghost_lev));
634   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS));
635   ret->setMesh(im);
636   ret->setArray(const_cast<DataArrayDouble *>(arr));
637   ret->setName(arr->getName());
638   return ret.retn();
639 }
640
641 /*!
642  * This method builds a newly created field on cell just lying on mesh \a mesh without its eventual refinement.
643  * The output field does not display ghost cells.
644  *
645  * \return MEDCouplingFieldDouble * - a field on cells that the caller has to deal with (deallocate it).
646  *
647  * \sa buildCellFieldOnWithGhost
648  */
649 MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnWithoutGhost(MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) const
650 {
651   //tony
652   const DataArrayDouble *arr(0);
653   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
654     {
655       int tmp(-1);
656       if((*it)->presenceOf(mesh,tmp))
657         {
658           const DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp));
659           arr=ddc.getFieldWithName(fieldName);
660         }
661     }
662   if(!arr)
663     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::buildCellFieldOnWithoutGhost : the mesh specified is not in the progeny of this !");
664   //
665   MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> im(mesh->getImageMesh()->buildWithGhost(_ghost_lev));
666   std::vector<int> cgs(mesh->getImageMesh()->getCellGridStructure()),cgsWG(im->getCellGridStructure());
667   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr2(DataArrayDouble::New());
668   arr2->alloc(mesh->getImageMesh()->getNumberOfCells(),arr->getNumberOfComponents());
669   std::vector< std::pair<int,int> > cgs2(MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(cgs));
670   MEDCouplingCartesianAMRPatch::ApplyGhostOnCompactFrmt(cgs2,_ghost_lev);
671   std::vector<int> fakeFactors(mesh->getImageMesh()->getSpaceDimension(),1);
672   MEDCouplingIMesh::SpreadCoarseToFine(arr,cgsWG,arr2,cgs2,fakeFactors);
673   arr2->copyStringInfoFrom(*arr);
674   //
675   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS));
676   ret->setMesh(mesh->getImageMesh());
677   ret->setArray(arr2);
678   ret->setName(arr->getName());
679   return ret.retn();
680 }
681
682 /*!
683  * This method synchronizes from fine to coarse direction arrays. This method makes the hypothesis that \a this has been allocated before using
684  * MEDCouplingAMRAttribute::alloc method.
685  */
686 void MEDCouplingAMRAttribute::synchronizeFineToCoarse()
687 {
688   if(_levs.empty())
689     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineToCoarse : not any levels in this !");
690   std::size_t sz(_levs.size());
691   //
692   while(sz>1)
693     {
694       sz--;
695       const MEDCouplingGridCollection *fine(_levs[sz]),*coarse(_levs[sz-1]);
696       MEDCouplingGridCollection::SynchronizeFineToCoarse(_ghost_lev,fine,coarse);
697     }
698 }
699
700 /*!
701  * 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
702  * MEDCouplingAMRAttribute::alloc method.
703  */
704 void MEDCouplingAMRAttribute::synchronizeCoarseToFine()
705 {
706   if(_levs.empty())
707     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeCoarseToFine : not any levels in this !");
708   std::size_t sz(_levs.size());
709   //
710   for(std::size_t i=1;i<sz;i++)
711     {
712       const MEDCouplingGridCollection *fine(_levs[i]),*coarse(_levs[i-1]);
713       MEDCouplingGridCollection::SynchronizeCoarseToFine(_ghost_lev,coarse,fine);
714     }
715 }
716
717 /*!
718  * This method synchronizes the ghost zone of all patches (excepted the god father one).
719  * This method operates in 4 steps. Larger is the number of steps more accurate is the information in the ghost zone.
720  *
721  * - firstly coarse to fine with no interactions between brother patches.
722  * - secondly connected brother patches in a same master patch are updated.
723  * - thirdly connected nephew patches are updated each other.
724  * - forthly nth generation cousin patches are updated each other.
725  *
726  * This method makes the hypothesis that \a this has been allocated before using MEDCouplingAMRAttribute::alloc method.
727  * So if \a _ghost_lev == 0 this method has no effect.
728  */
729 void MEDCouplingAMRAttribute::synchronizeAllGhostZones()
730 {
731   if(_levs.empty())
732     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineEachOther : not any levels in this !");
733   // 1st - synchronize from coarse to the finest all the patches (excepted the god father one)
734   std::size_t sz(_levs.size());
735   for(std::size_t i=1;i<sz;i++)
736     {
737       const MEDCouplingGridCollection *fine(_levs[i]),*coarse(_levs[i-1]);
738       MEDCouplingGridCollection::SynchronizeCoarseToFineOnlyInGhostZone(_ghost_lev,coarse,fine);
739     }
740   // 2nd - classical direct sublevel inside common patch
741   for(std::size_t i=1;i<sz;i++)
742     {
743       const MEDCouplingGridCollection *fine(_levs[i]);
744       if(!fine)
745         throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineEachOtherInGhostZone : presence of a NULL element !");
746       fine->synchronizeFineEachOther(_ghost_lev,_neighbors[i]);
747     }
748   // 3rd - mixed level
749   for(std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >::const_iterator it=_mixed_lev_neighbors.begin();it!=_mixed_lev_neighbors.end();it++)
750     {
751       const DataArrayDoubleCollection *firstDAC(&findCollectionAttachedTo((*it).first->getMesh())),*secondDAC(&findCollectionAttachedTo((*it).second->getMesh()));
752       DataArrayDoubleCollection::SynchronizeGhostZoneOfOneUsingTwo(_ghost_lev,(*it).first,firstDAC,(*it).second,secondDAC);
753     }
754   // 4th - same level but with far ancestor.
755   for(std::size_t i=1;i<sz;i++)
756     {
757       const MEDCouplingGridCollection *fine(_levs[i]);
758       fine->synchronizeFineEachOtherExt(_ghost_lev,_cross_lev_neighbors[i]);
759     }
760 }
761
762 /*!
763  * This method allocates all DataArrayDouble instances stored recursively in \a this.
764  *
765  * \sa dealloc
766  */
767 void MEDCouplingAMRAttribute::alloc()
768 {
769   _tlc.resetState();
770   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::iterator it=_levs.begin();it!=_levs.end();it++)
771     {
772       MEDCouplingGridCollection *elt(*it);
773       if(elt)
774         elt->alloc(_ghost_lev);
775       else
776         throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::alloc : internal error !");
777     }
778 }
779
780 /*!
781  * This method deallocates all DataArrayDouble instances stored recursively in \a this.
782  * \sa alloc
783  */
784 void MEDCouplingAMRAttribute::dealloc()
785 {
786   _tlc.checkConst();
787   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::iterator it=_levs.begin();it!=_levs.end();it++)
788     {
789       MEDCouplingGridCollection *elt(*it);
790       if(elt)
791         elt->dealloc();
792       else
793         throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::dealloc : internal error !");
794     }
795 }
796
797 bool MEDCouplingAMRAttribute::changeGodFather(MEDCouplingCartesianAMRMeshGen *gf)
798 {
799   bool ret(MEDCouplingDataForGodFather::changeGodFather(gf));
800   return ret;
801 }
802
803 std::size_t MEDCouplingAMRAttribute::getHeapMemorySizeWithoutChildren() const
804 {
805   std::size_t ret(sizeof(MEDCouplingAMRAttribute));
806   ret+=_levs.capacity()*sizeof(MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection>);
807   return ret;
808 }
809
810 std::vector<const BigMemoryObject *> MEDCouplingAMRAttribute::getDirectChildren() const
811 {
812   std::vector<const BigMemoryObject *> ret;
813   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
814     {
815       const MEDCouplingGridCollection *elt(*it);
816       if(elt)
817         ret.push_back(elt);
818     }
819   return ret;
820 }
821
822 void MEDCouplingAMRAttribute::updateTime() const
823 {//tony
824 }
825
826 MEDCouplingAMRAttribute::MEDCouplingAMRAttribute(MEDCouplingCartesianAMRMeshGen *gf, const std::vector< std::pair<std::string,int> >& fieldNames, int ghostLev):MEDCouplingDataForGodFather(gf),_ghost_lev(ghostLev)
827 {
828   //gf non empty, checked by constructor
829   int maxLev(gf->getMaxNumberOfLevelsRelativeToThis());
830   _levs.resize(maxLev);
831   for(int i=0;i<maxLev;i++)
832     {
833       std::vector<MEDCouplingCartesianAMRPatchGen *> patches(gf->retrieveGridsAt(i));
834       std::size_t sz(patches.size());
835       std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatchGen> > patchesSafe(patches.size());
836       for(std::size_t j=0;j<sz;j++)
837         patchesSafe[j]=patches[j];
838       std::vector<const MEDCouplingCartesianAMRMeshGen *> ms(sz);
839       for(std::size_t j=0;j<sz;j++)
840         {
841           ms[j]=patches[j]->getMesh();
842         }
843       _levs[i]=MEDCouplingGridCollection::New(ms,fieldNames);
844     }
845   // updates cross levels neighbors
846   _neighbors.resize(_levs.size());
847   _cross_lev_neighbors.resize(_levs.size());
848   if(_levs.empty())
849     throw INTERP_KERNEL::Exception("constructor of MEDCouplingAMRAttribute : not any levels in this !");
850   std::size_t sz(_levs.size());
851   for(std::size_t i=1;i<sz;i++)
852     {
853       const MEDCouplingGridCollection *fine(_levs[i]);
854       if(!fine)
855         throw INTERP_KERNEL::Exception("constructor of MEDCouplingAMRAttribute : presence of a NULL element !");
856       _neighbors[i]=fine->findNeighbors(_ghost_lev);
857       if(i!=sz-1)
858         {
859           for(std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >::const_iterator it=_neighbors[i].begin();it!=_neighbors[i].end();it++)
860             {
861               MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOf(_ghost_lev,(*it).first,(*it).second,_mixed_lev_neighbors);
862               std::vector< std::vector < std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > > neighs2(MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOfSameLev(_ghost_lev,(*it).first,(*it).second));
863               std::size_t fullLev(i+neighs2.size());
864               if(fullLev>=sz)
865                 throw INTERP_KERNEL::Exception("constructor of MEDCouplingAMRAttribute : internal error ! something is wrong in computation of cross level neighbors !");
866               std::size_t ii(i+1);
867               for(std::vector< std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > >::const_iterator it0=neighs2.begin();it0!=neighs2.end();it0++,ii++)
868                 _cross_lev_neighbors[ii].insert(_cross_lev_neighbors[ii].end(),(*it0).begin(),(*it0).end());
869             }
870         }
871     }
872 }
873
874 const DataArrayDoubleCollection& MEDCouplingAMRAttribute::findCollectionAttachedTo(const MEDCouplingCartesianAMRMeshGen *m) const
875 {
876   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
877     {
878       const MEDCouplingGridCollection *elt(*it);
879       if(elt)
880         {
881           int tmp(-1);
882           if(elt->presenceOf(m,tmp))
883             {
884               return elt->getFieldsAt(tmp);
885             }
886         }
887     }
888   throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::findCollectionAttachedTo : unable to find such part of mesh in this !");
889 }