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