Salome HOME
Debug for ghostlev > 1. Optimization of neighbors.
[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 MEDCouplingCartesianAMRPatchGF::MEDCouplingCartesianAMRPatchGF(MEDCouplingCartesianAMRMesh *mesh):MEDCouplingCartesianAMRPatchGen(mesh)
550 {
551 }
552
553 std::size_t MEDCouplingCartesianAMRPatchGF::getHeapMemorySizeWithoutChildren() const
554 {
555   return sizeof(MEDCouplingCartesianAMRPatchGF);
556 }
557
558 MEDCouplingDataForGodFather::MEDCouplingDataForGodFather(MEDCouplingCartesianAMRMeshGen *gf):_gf(gf),_tlc(gf)
559 {
560   if(!gf)
561     throw INTERP_KERNEL::Exception("MEDCouplingDataForGodFather constructor : A data has to be attached to a AMR Mesh instance !");
562   gf->incrRef();
563 }
564
565 void MEDCouplingDataForGodFather::checkGodFatherFrozen() const
566 {
567   _tlc.checkConst();
568 }
569
570 bool MEDCouplingDataForGodFather::changeGodFather(MEDCouplingCartesianAMRMeshGen *gf)
571 {
572   bool ret(_tlc.keepTrackOfNewTL(gf));
573   if(ret)
574     {
575       _gf=gf;
576       if(gf)
577         gf->incrRef();
578     }
579   return ret;
580 }
581
582 /*!
583  * 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.
584  */
585 MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::New(MEDCouplingCartesianAMRMeshGen *gf, const std::vector< std::pair<std::string,int> >& fieldNames, int ghostLev)
586 {
587   return new MEDCouplingAMRAttribute(gf,fieldNames,ghostLev);
588 }
589
590 MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::New(MEDCouplingCartesianAMRMeshGen *gf, const std::vector< std::pair<std::string, std::vector<std::string> > >& fieldNames, int ghostLev)
591 {
592   std::size_t sz(fieldNames.size());
593   std::vector< std::pair<std::string,int> > fieldNames2(sz);
594   std::vector< std::vector<std::string> > compNames(sz);
595   for(std::size_t i=0;i<sz;i++)
596     {
597       fieldNames2[i].first=fieldNames[i].first;
598       fieldNames2[i].second=(int)fieldNames[i].second.size();
599       compNames[i]=fieldNames[i].second;
600     }
601   MEDCouplingAutoRefCountObjectPtr<MEDCouplingAMRAttribute> ret(New(gf,fieldNames2,ghostLev));
602   ret->spillInfoOnComponents(compNames);
603   return ret.retn();
604 }
605
606 /*!
607  * Assign the info on components for all DataArrayDouble instance recursively stored in \a this.
608  * 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.
609  * The second dim of \a compNames represent the component names component per component corresponding to the field. The size of this 2nd dimension has
610  * to perfectly fit with those specified in MEDCouplingAMRAttribute::New.
611  */
612 void MEDCouplingAMRAttribute::spillInfoOnComponents(const std::vector< std::vector<std::string> >& compNames)
613 {
614   _tlc.checkConst();
615   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::iterator it=_levs.begin();it!=_levs.end();it++)
616     (*it)->spillInfoOnComponents(compNames);
617 }
618
619 /*!
620  * Assign nature for each fields in \a this.
621  * \param [in] nfs
622  */
623 void MEDCouplingAMRAttribute::spillNatures(const std::vector<NatureOfField>& nfs)
624 {
625   _tlc.checkConst();
626   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::iterator it=_levs.begin();it!=_levs.end();it++)
627     (*it)->spillNatures(nfs);
628 }
629
630 /*!
631  * This method returns all DataArrayDouble instances lying on the specified mesh \a mesh.
632  * If \a mesh is not part of the progeny of god father object given at construction of \a this an exception will be thrown.
633  *
634  * \return std::vector<DataArrayDouble *> - DataArrayDouble instances to be deallocated by the caller (using decrRef).
635  * \sa retrieveFieldOn
636  */
637 std::vector<DataArrayDouble *> MEDCouplingAMRAttribute::retrieveFieldsOn(MEDCouplingCartesianAMRMeshGen *mesh) const
638 {
639   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
640     {
641       int tmp(-1);
642       if((*it)->presenceOf(mesh,tmp))
643         {
644           const DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp));
645           return ddc.retrieveFields();
646         }
647     }
648   throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::retrieveFieldsOn : the mesh specified is not in the progeny of this !");
649 }
650
651 /*!
652  * \sa retrieveFieldsOn
653  */
654 const DataArrayDouble *MEDCouplingAMRAttribute::getFieldOn(MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) const
655 {
656   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
657     {
658       int tmp(-1);
659       if((*it)->presenceOf(mesh,tmp))
660         {
661           const DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp));
662           return ddc.getFieldWithName(fieldName);
663         }
664     }
665   throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::retrieveFieldOn : the mesh specified is not in the progeny of this !");
666 }
667
668 /*!
669  * This method returns a field on an unstructured mesh the most refined as possible without overlap.
670  * Ghost part are not visible here.
671  *
672  * \return MEDCouplingFieldDouble * - a field on cells that the caller has to deal with (deallocate it).
673  */
674 MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnRecurseWithoutOverlapWithoutGhost(MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) const
675 {
676   std::vector<const DataArrayDouble *> recurseArrs;
677   std::size_t lev(0);
678   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++,lev++)
679     {
680       int tmp(-1);
681       if((*it)->presenceOf(mesh,tmp))
682         {
683           const DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp));
684           recurseArrs.push_back(ddc.getFieldWithName(fieldName));
685           break;
686         }
687     }
688   lev++;
689   for(std::size_t i=lev;i<_levs.size();i++)
690     {
691       const MEDCouplingGridCollection *gc(_levs[i]);
692       gc->fillIfInTheProgenyOf(fieldName,mesh,recurseArrs);
693     }
694   return mesh->buildCellFieldOnRecurseWithoutOverlapWithoutGhost(_ghost_lev,recurseArrs);
695 }
696
697 /*!
698  * This method builds a newly created field on cell just lying on mesh \a mesh without its eventual refinement.
699  * The output field also displays ghost cells.
700  *
701  * \return MEDCouplingFieldDouble * - a field on cells that the caller has to deal with (deallocate it).
702  *
703  * \sa buildCellFieldOnWithoutGhost
704  */
705 MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnWithGhost(MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) const
706 {
707   const DataArrayDouble *arr(0);
708   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
709     {
710       int tmp(-1);
711       if((*it)->presenceOf(mesh,tmp))
712         {
713           const DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp));
714           arr=ddc.getFieldWithName(fieldName);
715         }
716     }
717   if(!arr)
718     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::buildCellFieldOnWithGhost : the mesh specified is not in the progeny of this !");
719   MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> im(mesh->getImageMesh()->buildWithGhost(_ghost_lev));
720   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS));
721   ret->setMesh(im);
722   ret->setArray(const_cast<DataArrayDouble *>(arr));
723   ret->setName(arr->getName());
724   return ret.retn();
725 }
726
727 /*!
728  * This method builds a newly created field on cell just lying on mesh \a mesh without its eventual refinement.
729  * The output field does not display ghost cells.
730  *
731  * \return MEDCouplingFieldDouble * - a field on cells that the caller has to deal with (deallocate it).
732  *
733  * \sa buildCellFieldOnWithGhost
734  */
735 MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnWithoutGhost(MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) const
736 {
737   //tony
738   const DataArrayDouble *arr(0);
739   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
740     {
741       int tmp(-1);
742       if((*it)->presenceOf(mesh,tmp))
743         {
744           const DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp));
745           arr=ddc.getFieldWithName(fieldName);
746         }
747     }
748   if(!arr)
749     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::buildCellFieldOnWithoutGhost : the mesh specified is not in the progeny of this !");
750   //
751   MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> im(mesh->getImageMesh()->buildWithGhost(_ghost_lev));
752   std::vector<int> cgs(mesh->getImageMesh()->getCellGridStructure()),cgsWG(im->getCellGridStructure());
753   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr2(DataArrayDouble::New());
754   arr2->alloc(mesh->getImageMesh()->getNumberOfCells(),arr->getNumberOfComponents());
755   std::vector< std::pair<int,int> > cgs2(MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(cgs));
756   MEDCouplingStructuredMesh::ApplyGhostOnCompactFrmt(cgs2,_ghost_lev);
757   std::vector<int> fakeFactors(mesh->getImageMesh()->getSpaceDimension(),1);
758   MEDCouplingIMesh::SpreadCoarseToFine(arr,cgsWG,arr2,cgs2,fakeFactors);
759   arr2->copyStringInfoFrom(*arr);
760   //
761   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS));
762   ret->setMesh(mesh->getImageMesh());
763   ret->setArray(arr2);
764   ret->setName(arr->getName());
765   return ret.retn();
766 }
767
768 /*!
769  * This method synchronizes from fine to coarse direction arrays. This method makes the hypothesis that \a this has been allocated before using
770  * MEDCouplingAMRAttribute::alloc method.
771  */
772 void MEDCouplingAMRAttribute::synchronizeFineToCoarse()
773 {
774   if(_levs.empty())
775     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineToCoarse : not any levels in this !");
776   std::size_t sz(_levs.size());
777   //
778   while(sz>1)
779     {
780       sz--;
781       const MEDCouplingGridCollection *fine(_levs[sz]),*coarse(_levs[sz-1]);
782       MEDCouplingGridCollection::SynchronizeFineToCoarse(_ghost_lev,fine,coarse);
783     }
784 }
785
786 /*!
787  * 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
788  * MEDCouplingAMRAttribute::alloc method.
789  */
790 void MEDCouplingAMRAttribute::synchronizeCoarseToFine()
791 {
792   if(_levs.empty())
793     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeCoarseToFine : not any levels in this !");
794   std::size_t sz(_levs.size());
795   //
796   for(std::size_t i=1;i<sz;i++)
797     {
798       const MEDCouplingGridCollection *fine(_levs[i]),*coarse(_levs[i-1]);
799       MEDCouplingGridCollection::SynchronizeCoarseToFine(_ghost_lev,coarse,fine);
800     }
801 }
802
803 /*!
804  * This method synchronizes the ghost zone of all patches (excepted the god father one).
805  * This method operates in 4 steps. Larger is the number of steps more accurate is the information in the ghost zone.
806  *
807  * - firstly coarse to fine with no interactions between brother patches.
808  * - secondly connected brother patches in a same master patch are updated.
809  * - thirdly connected nephew patches are updated each other.
810  * - forthly nth generation cousin patches are updated each other.
811  *
812  * This method makes the hypothesis that \a this has been allocated before using MEDCouplingAMRAttribute::alloc method.
813  * So if \a _ghost_lev == 0 this method has no effect.
814  */
815 void MEDCouplingAMRAttribute::synchronizeAllGhostZones()
816 {
817   if(_levs.empty())
818     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineEachOther : not any levels in this !");
819   // 1st - synchronize from coarse to the finest all the patches (excepted the god father one)
820   std::size_t sz(_levs.size());
821   for(std::size_t i=1;i<sz;i++)
822     {
823       const MEDCouplingGridCollection *fine(_levs[i]),*coarse(_levs[i-1]);
824       MEDCouplingGridCollection::SynchronizeCoarseToFineOnlyInGhostZone(_ghost_lev,coarse,fine);
825     }
826   // 2nd - classical direct sublevel inside common patch
827   for(std::size_t i=1;i<sz;i++)
828     {
829       const MEDCouplingGridCollection *fine(_levs[i]);
830       if(!fine)
831         throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineEachOtherInGhostZone : presence of a NULL element !");
832       fine->synchronizeFineEachOther(_ghost_lev,_neighbors[i]);
833     }
834   // 3rd - mixed level
835   for(std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >::const_iterator it=_mixed_lev_neighbors.begin();it!=_mixed_lev_neighbors.end();it++)
836     {
837       const DataArrayDoubleCollection *firstDAC(&findCollectionAttachedTo((*it).first->getMesh())),*secondDAC(&findCollectionAttachedTo((*it).second->getMesh()));
838       DataArrayDoubleCollection::SynchronizeGhostZoneOfOneUsingTwo(_ghost_lev,(*it).first,firstDAC,(*it).second,secondDAC);
839     }
840   // 4th - same level but with far ancestor.
841   for(std::size_t i=1;i<sz;i++)
842     {
843       const MEDCouplingGridCollection *fine(_levs[i]);
844       fine->synchronizeFineEachOtherExt(_ghost_lev,_cross_lev_neighbors[i]);
845     }
846 }
847
848 /*!
849  * This method allocates all DataArrayDouble instances stored recursively in \a this.
850  *
851  * \sa dealloc
852  */
853 void MEDCouplingAMRAttribute::alloc()
854 {
855   _tlc.resetState();
856   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::iterator it=_levs.begin();it!=_levs.end();it++)
857     {
858       MEDCouplingGridCollection *elt(*it);
859       if(elt)
860         elt->alloc(_ghost_lev);
861       else
862         throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::alloc : internal error !");
863     }
864 }
865
866 /*!
867  * This method deallocates all DataArrayDouble instances stored recursively in \a this.
868  * \sa alloc
869  */
870 void MEDCouplingAMRAttribute::dealloc()
871 {
872   _tlc.checkConst();
873   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::iterator it=_levs.begin();it!=_levs.end();it++)
874     {
875       MEDCouplingGridCollection *elt(*it);
876       if(elt)
877         elt->dealloc();
878       else
879         throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::dealloc : internal error !");
880     }
881 }
882
883 bool MEDCouplingAMRAttribute::changeGodFather(MEDCouplingCartesianAMRMeshGen *gf)
884 {
885   bool ret(MEDCouplingDataForGodFather::changeGodFather(gf));
886   return ret;
887 }
888
889 std::size_t MEDCouplingAMRAttribute::getHeapMemorySizeWithoutChildren() const
890 {
891   std::size_t ret(sizeof(MEDCouplingAMRAttribute));
892   ret+=_levs.capacity()*sizeof(MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection>);
893   return ret;
894 }
895
896 std::vector<const BigMemoryObject *> MEDCouplingAMRAttribute::getDirectChildren() const
897 {
898   std::vector<const BigMemoryObject *> ret;
899   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
900     {
901       const MEDCouplingGridCollection *elt(*it);
902       if(elt)
903         ret.push_back(elt);
904     }
905   return ret;
906 }
907
908 void MEDCouplingAMRAttribute::updateTime() const
909 {//tony
910 }
911
912 MEDCouplingAMRAttribute::MEDCouplingAMRAttribute(MEDCouplingCartesianAMRMeshGen *gf, const std::vector< std::pair<std::string,int> >& fieldNames, int ghostLev):MEDCouplingDataForGodFather(gf),_ghost_lev(ghostLev)
913 {
914   //gf non empty, checked by constructor
915   int maxLev(gf->getMaxNumberOfLevelsRelativeToThis());
916   _levs.resize(maxLev);
917   for(int i=0;i<maxLev;i++)
918     {
919       std::vector<MEDCouplingCartesianAMRPatchGen *> patches(gf->retrieveGridsAt(i));
920       std::size_t sz(patches.size());
921       std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatchGen> > patchesSafe(patches.size());
922       for(std::size_t j=0;j<sz;j++)
923         patchesSafe[j]=patches[j];
924       std::vector<const MEDCouplingCartesianAMRMeshGen *> ms(sz);
925       for(std::size_t j=0;j<sz;j++)
926         {
927           ms[j]=patches[j]->getMesh();
928         }
929       _levs[i]=MEDCouplingGridCollection::New(ms,fieldNames);
930     }
931   // updates cross levels neighbors
932   _neighbors.resize(_levs.size());
933   _cross_lev_neighbors.resize(_levs.size());
934   if(_levs.empty())
935     throw INTERP_KERNEL::Exception("constructor of MEDCouplingAMRAttribute : not any levels in this !");
936   std::size_t sz(_levs.size());
937   for(std::size_t i=1;i<sz;i++)
938     {
939       const MEDCouplingGridCollection *fine(_levs[i]);
940       if(!fine)
941         throw INTERP_KERNEL::Exception("constructor of MEDCouplingAMRAttribute : presence of a NULL element !");
942       _neighbors[i]=fine->findNeighbors(_ghost_lev);
943       if(i!=sz-1)
944         {
945           for(std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >::const_iterator it=_neighbors[i].begin();it!=_neighbors[i].end();it++)
946             {
947               MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOf(_ghost_lev,(*it).first,(*it).second,_mixed_lev_neighbors);
948               std::vector< std::vector < std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > > neighs2(MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOfSameLev(_ghost_lev,(*it).first,(*it).second));
949               std::size_t fullLev(i+neighs2.size());
950               if(fullLev>=sz)
951                 throw INTERP_KERNEL::Exception("constructor of MEDCouplingAMRAttribute : internal error ! something is wrong in computation of cross level neighbors !");
952               std::size_t ii(i+1);
953               for(std::vector< std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > >::const_iterator it0=neighs2.begin();it0!=neighs2.end();it0++,ii++)
954                 _cross_lev_neighbors[ii].insert(_cross_lev_neighbors[ii].end(),(*it0).begin(),(*it0).end());
955             }
956         }
957     }
958 }
959
960 const DataArrayDoubleCollection& MEDCouplingAMRAttribute::findCollectionAttachedTo(const MEDCouplingCartesianAMRMeshGen *m) const
961 {
962   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
963     {
964       const MEDCouplingGridCollection *elt(*it);
965       if(elt)
966         {
967           int tmp(-1);
968           if(elt->presenceOf(m,tmp))
969             {
970               return elt->getFieldsAt(tmp);
971             }
972         }
973     }
974   throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::findCollectionAttachedTo : unable to find such part of mesh in this !");
975 }