Salome HOME
First test of synchronization of patches each other.
[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(MEDCouplingCartesianAMRMesh *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(MEDCouplingCartesianAMRMesh *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  */
618 MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnWithGhost(MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) const
619 {
620   const DataArrayDouble *arr(0);
621   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
622     {
623       int tmp(-1);
624       if((*it)->presenceOf(mesh,tmp))
625         {
626           const DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp));
627           arr=ddc.getFieldWithName(fieldName);
628         }
629     }
630   if(!arr)
631     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::buildCellFieldOnWithGhost : the mesh specified is not in the progeny of this !");
632   MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> im(mesh->getImageMesh()->buildWithGhost(_ghost_lev));
633   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS));
634   ret->setMesh(im);
635   ret->setArray(const_cast<DataArrayDouble *>(arr));
636   ret->setName(arr->getName());
637   return ret.retn();
638 }
639
640 /*!
641  * This method synchronizes from fine to coarse direction arrays. This method makes the hypothesis that \a this has been allocated before using
642  * MEDCouplingAMRAttribute::alloc method.
643  */
644 void MEDCouplingAMRAttribute::synchronizeFineToCoarse()
645 {
646   if(_levs.empty())
647     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineToCoarse : not any levels in this !");
648   std::size_t sz(_levs.size());
649   //
650   while(sz>1)
651     {
652       sz--;
653       const MEDCouplingGridCollection *fine(_levs[sz]),*coarse(_levs[sz-1]);
654       MEDCouplingGridCollection::SynchronizeFineToCoarse(_ghost_lev,fine,coarse);
655     }
656 }
657
658 /*!
659  * 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
660  * MEDCouplingAMRAttribute::alloc method.
661  */
662 void MEDCouplingAMRAttribute::synchronizeCoarseToFine()
663 {
664   if(_levs.empty())
665     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeCoarseToFine : not any levels in this !");
666   std::size_t sz(_levs.size());
667   //
668   for(std::size_t i=1;i<sz;i++)
669     {
670       const MEDCouplingGridCollection *fine(_levs[i]),*coarse(_levs[i-1]);
671       MEDCouplingGridCollection::SynchronizeCoarseToFine(_ghost_lev,coarse,fine);
672     }
673 }
674
675 /*!
676  * This method synchronizes the ghost zone of all patches (excepted the god father one).
677  * This method operates in 4 steps. Larger is the number of steps more accurate is the information in the ghost zone.
678  *
679  * - firstly coarse to fine with no interactions between brother patches.
680  * - secondly connected brother patches in a same master patch are updated.
681  * - thirdly connected nephew patches are updated each other.
682  * - forthly nth generation cousin patches are updated each other.
683  *
684  * This method makes the hypothesis that \a this has been allocated before using MEDCouplingAMRAttribute::alloc method.
685  * So if \a _ghost_lev == 0 this method has no effect.
686  */
687 void MEDCouplingAMRAttribute::synchronizeAllGhostZones()
688 {
689   if(_levs.empty())
690     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineEachOther : not any levels in this !");
691   // 1st - synchronize from coarse to the finest all the patches (excepted the god father one)
692   std::size_t sz(_levs.size());
693   for(std::size_t i=1;i<sz;i++)
694     {
695       const MEDCouplingGridCollection *fine(_levs[i]),*coarse(_levs[i-1]);
696       MEDCouplingGridCollection::SynchronizeCoarseToFineOnlyInGhostZone(_ghost_lev,coarse,fine);
697     }
698   // 2nd - classical direct sublevel inside common patch
699   for(std::size_t i=1;i<sz;i++)
700     {
701       const MEDCouplingGridCollection *fine(_levs[i]);
702       if(!fine)
703         throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineEachOtherInGhostZone : presence of a NULL element !");
704       fine->synchronizeFineEachOther(_ghost_lev,_neighbors[i]);
705     }
706   // 3rd - mixed level
707   for(std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >::const_iterator it=_mixed_lev_neighbors.begin();it!=_mixed_lev_neighbors.end();it++)
708     {
709       const DataArrayDoubleCollection *firstDAC(&findCollectionAttachedTo((*it).first->getMesh())),*secondDAC(&findCollectionAttachedTo((*it).second->getMesh()));
710       DataArrayDoubleCollection::SynchronizeGhostZoneOfOneUsingTwo(_ghost_lev,(*it).first,firstDAC,(*it).second,secondDAC);
711     }
712   // 4th - same level but with far ancestor.
713   for(std::size_t i=1;i<sz;i++)
714     {
715       const MEDCouplingGridCollection *fine(_levs[i]);
716       fine->synchronizeFineEachOtherExt(_ghost_lev,_cross_lev_neighbors[i]);
717     }
718 }
719
720 /*!
721  * This method allocates all DataArrayDouble instances stored recursively in \a this.
722  *
723  * \sa dealloc
724  */
725 void MEDCouplingAMRAttribute::alloc()
726 {
727   _tlc.resetState();
728   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::iterator it=_levs.begin();it!=_levs.end();it++)
729     {
730       MEDCouplingGridCollection *elt(*it);
731       if(elt)
732         elt->alloc(_ghost_lev);
733       else
734         throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::alloc : internal error !");
735     }
736 }
737
738 /*!
739  * This method deallocates all DataArrayDouble instances stored recursively in \a this.
740  * \sa alloc
741  */
742 void MEDCouplingAMRAttribute::dealloc()
743 {
744   _tlc.checkConst();
745   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::iterator it=_levs.begin();it!=_levs.end();it++)
746     {
747       MEDCouplingGridCollection *elt(*it);
748       if(elt)
749         elt->dealloc();
750       else
751         throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::dealloc : internal error !");
752     }
753 }
754
755 bool MEDCouplingAMRAttribute::changeGodFather(MEDCouplingCartesianAMRMesh *gf)
756 {
757   bool ret(MEDCouplingDataForGodFather::changeGodFather(gf));
758   return ret;
759 }
760
761 std::size_t MEDCouplingAMRAttribute::getHeapMemorySizeWithoutChildren() const
762 {
763   std::size_t ret(sizeof(MEDCouplingAMRAttribute));
764   ret+=_levs.capacity()*sizeof(MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection>);
765   return ret;
766 }
767
768 std::vector<const BigMemoryObject *> MEDCouplingAMRAttribute::getDirectChildren() const
769 {
770   std::vector<const BigMemoryObject *> ret;
771   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
772     {
773       const MEDCouplingGridCollection *elt(*it);
774       if(elt)
775         ret.push_back(elt);
776     }
777   return ret;
778 }
779
780 void MEDCouplingAMRAttribute::updateTime() const
781 {//tony
782 }
783
784 MEDCouplingAMRAttribute::MEDCouplingAMRAttribute(MEDCouplingCartesianAMRMesh *gf, const std::vector< std::pair<std::string,int> >& fieldNames, int ghostLev):MEDCouplingDataForGodFather(gf),_ghost_lev(ghostLev)
785 {
786   //gf non empty, checked by constructor
787   int maxLev(gf->getMaxNumberOfLevelsRelativeToThis());
788   _levs.resize(maxLev);
789   for(int i=0;i<maxLev;i++)
790     {
791       std::vector<MEDCouplingCartesianAMRPatchGen *> patches(gf->retrieveGridsAt(i));
792       std::size_t sz(patches.size());
793       std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatchGen> > patchesSafe(patches.size());
794       for(std::size_t j=0;j<sz;j++)
795         patchesSafe[j]=patches[j];
796       std::vector<const MEDCouplingCartesianAMRMeshGen *> ms(sz);
797       for(std::size_t j=0;j<sz;j++)
798         {
799           ms[j]=patches[j]->getMesh();
800         }
801       _levs[i]=MEDCouplingGridCollection::New(ms,fieldNames);
802     }
803   // updates cross levels neighbors
804   _neighbors.resize(_levs.size());
805   _cross_lev_neighbors.resize(_levs.size());
806   if(_levs.empty())
807     throw INTERP_KERNEL::Exception("constructor of MEDCouplingAMRAttribute : not any levels in this !");
808   std::size_t sz(_levs.size());
809   for(std::size_t i=1;i<sz;i++)
810     {
811       const MEDCouplingGridCollection *fine(_levs[i]);
812       if(!fine)
813         throw INTERP_KERNEL::Exception("constructor of MEDCouplingAMRAttribute : presence of a NULL element !");
814       _neighbors[i]=fine->findNeighbors(_ghost_lev);
815       if(i!=sz-1)
816         {
817           for(std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >::const_iterator it=_neighbors[i].begin();it!=_neighbors[i].end();it++)
818             {
819               MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOf(_ghost_lev,(*it).first,(*it).second,_mixed_lev_neighbors);
820               std::vector< std::vector < std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > > neighs2(MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOfSameLev(_ghost_lev,(*it).first,(*it).second));
821               std::size_t fullLev(i+neighs2.size());
822               if(fullLev>=sz)
823                 throw INTERP_KERNEL::Exception("constructor of MEDCouplingAMRAttribute : internal error ! something is wrong in computation of cross level neighbors !");
824               std::size_t ii(i+1);
825               for(std::vector< std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > >::const_iterator it0=neighs2.begin();it0!=neighs2.end();it0++,ii++)
826                 _cross_lev_neighbors[ii].insert(_cross_lev_neighbors[ii].end(),(*it0).begin(),(*it0).end());
827             }
828         }
829     }
830 }
831
832 const DataArrayDoubleCollection& MEDCouplingAMRAttribute::findCollectionAttachedTo(const MEDCouplingCartesianAMRMeshGen *m) const
833 {
834   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
835     {
836       const MEDCouplingGridCollection *elt(*it);
837       if(elt)
838         {
839           int tmp(-1);
840           if(elt->presenceOf(m,tmp))
841             {
842               return elt->getFieldsAt(tmp);
843             }
844         }
845     }
846   throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::findCollectionAttachedTo : unable to find such part of mesh in this !");
847 }