Salome HOME
Doc
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingAMRAttribute.cxx
1 // Copyright (C) 2007-2020  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 #include <fstream>
28 #include <functional>
29
30 using namespace MEDCoupling;
31
32 /// @cond INTERNAL
33 DataArrayDoubleCollection *DataArrayDoubleCollection::New(const std::vector< std::pair<std::string,int> >& fieldNames)
34 {
35   return new DataArrayDoubleCollection(fieldNames);
36 }
37
38 DataArrayDoubleCollection *DataArrayDoubleCollection::deepCopy() const
39 {
40   return new DataArrayDoubleCollection(*this);
41 }
42
43 void DataArrayDoubleCollection::allocTuples(mcIdType nbOfTuples)
44 {
45   std::size_t sz(_arrs.size());
46   for(std::size_t i=0;i<sz;i++)
47     _arrs[i].first->reAlloc(nbOfTuples);
48 }
49
50 void DataArrayDoubleCollection::dellocTuples()
51 {
52   std::size_t sz(_arrs.size());
53   for(std::size_t i=0;i<sz;i++)
54     _arrs[i].first->reAlloc(0);
55 }
56
57 void DataArrayDoubleCollection::copyFrom(const DataArrayDoubleCollection& other)
58 {
59   std::size_t sz(_arrs.size());
60   if(sz!=other._arrs.size())
61     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::copyFrom : size are not the same !");
62   for(std::size_t i=0;i<sz;i++)
63     {
64       DataArrayDouble *thisArr(_arrs[i].first);
65       const DataArrayDouble *otherArr(other._arrs[i].first);
66       if(!thisArr || !otherArr)
67         throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::copyFrom : empty DataArray !");
68       thisArr->deepCopyFrom(*otherArr);
69     }
70 }
71
72 void DataArrayDoubleCollection::spillInfoOnComponents(const std::vector< std::vector<std::string> >& compNames)
73 {
74   std::size_t sz(_arrs.size());
75   if(sz!=compNames.size())
76     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::spillInfoOnComponents : first size of compNames has to be equal to the number of fields defined !");
77   for(std::size_t i=0;i<sz;i++)
78     {
79       const std::vector<std::string>& names(compNames[i]);
80       _arrs[i].first->setInfoOnComponents(names);
81     }
82 }
83
84 void DataArrayDoubleCollection::spillNatures(const std::vector<NatureOfField>& nfs)
85 {
86   std::size_t sz(_arrs.size());
87   if(sz!=nfs.size())
88     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::spillNatures : first size of vector of NatureOfField has to be equal to the number of fields defined !");
89   for(std::size_t i=0;i<sz;i++)
90     {
91       CheckValidNature(nfs[i]);
92       _arrs[i].second=nfs[i];
93     }
94 }
95
96 std::vector< std::pair < std::string, std::vector<std::string> > > DataArrayDoubleCollection::getInfoOnComponents() const
97 {
98   std::size_t sz(_arrs.size());
99   std::vector< std::pair < std::string, std::vector<std::string> > > ret(sz);
100   for(std::size_t i=0;i<sz;i++)
101     {
102       const DataArrayDouble *elt(_arrs[i].first);
103       if(!elt)
104         throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::getInfoOnComponents : empty array !");
105       ret[i]=std::pair < std::string, std::vector<std::string> >(elt->getName(),elt->getInfoOnComponents());
106     }
107   return ret;
108 }
109
110 std::vector<NatureOfField> DataArrayDoubleCollection::getNatures() const
111 {
112   std::size_t sz(_arrs.size());
113   std::vector<NatureOfField> ret(sz);
114   for(std::size_t i=0;i<sz;i++)
115     ret[i]=_arrs[i].second;
116   return ret;
117 }
118
119 std::vector<DataArrayDouble *> DataArrayDoubleCollection::retrieveFields() const
120 {
121   std::size_t sz(_arrs.size());
122   std::vector<DataArrayDouble *> ret(sz);
123   for(std::size_t i=0;i<sz;i++)
124     {
125       const DataArrayDouble *tmp(_arrs[i].first);
126       ret[i]=const_cast<DataArrayDouble *>(tmp);
127       if(ret[i])
128         ret[i]->incrRef();
129     }
130   return ret;
131 }
132
133 const DataArrayDouble *DataArrayDoubleCollection::getFieldWithName(const std::string& name) const
134 {
135   std::vector<std::string> vec;
136   for(std::vector< std::pair< MCAuto<DataArrayDouble>, NatureOfField > >::const_iterator it=_arrs.begin();it!=_arrs.end();it++)
137     {
138       const DataArrayDouble *obj((*it).first);
139       if(obj)
140         {
141           if(obj->getName()==name)
142             return obj;
143           else
144             vec.push_back(obj->getName());
145         }
146     }
147   std::ostringstream oss; oss << "DataArrayDoubleCollection::getFieldWithName : fieldName \"" << name << "\" does not exist in this ! Possibilities are :";
148   std::copy(vec.begin(),vec.end(),std::ostream_iterator<std::string>(oss," "));
149   throw INTERP_KERNEL::Exception(oss.str().c_str());
150 }
151
152 DataArrayDouble *DataArrayDoubleCollection::getFieldWithName(const std::string& name)
153 {
154   std::vector<std::string> vec;
155   for(std::vector< std::pair< MCAuto<DataArrayDouble>, NatureOfField > >::iterator it=_arrs.begin();it!=_arrs.end();it++)
156     {
157       DataArrayDouble *obj((*it).first);
158       if(obj)
159         {
160           if(obj->getName()==name)
161             return obj;
162           else
163             vec.push_back(obj->getName());
164         }
165     }
166   std::ostringstream oss; oss << "DataArrayDoubleCollection::getFieldWithName non const : fieldName \"" << name << "\" does not exist in this ! Possibilities are :";
167   std::copy(vec.begin(),vec.end(),std::ostream_iterator<std::string>(oss," "));
168   throw INTERP_KERNEL::Exception(oss.str().c_str());
169 }
170
171 DataArrayDouble *DataArrayDoubleCollection::at(mcIdType pos)
172 {
173   if(pos<0 || pos>=ToIdType(_arrs.size()))
174     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::at (non const) : pos must be in [0,nbOfFields) !");
175   return _arrs[pos].first;
176 }
177
178 const DataArrayDouble *DataArrayDoubleCollection::at(mcIdType pos) const
179 {
180   if(pos<0 || pos>=ToIdType(_arrs.size()))
181     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::at : pos must be in [0,nbOfFields) !");
182   return _arrs[pos].first;
183 }
184
185 mcIdType DataArrayDoubleCollection::size() const
186 {
187   return ToIdType(_arrs.size());
188 }
189
190 void DataArrayDoubleCollection::SynchronizeFineToCoarse(mcIdType ghostLev, const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh, mcIdType patchId, const DataArrayDoubleCollection *fine, DataArrayDoubleCollection *coarse)
191 {
192   if(!fine || !coarse)
193     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeFineToCoarse : the input DataArrayDouble collections must be non NULL !");
194   std::size_t sz(coarse->_arrs.size());
195   if(fine->_arrs.size()!=sz)
196     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeFineToCoarse : the input DataArrayDouble collection must have the same size !");
197   for(std::size_t i=0;i<sz;i++)
198     {
199       CheckSameNatures(fine->_arrs[i].second,coarse->_arrs[i].second);
200       fatherOfFineMesh->fillCellFieldComingFromPatchGhost(patchId,fine->_arrs[i].first,coarse->_arrs[i].first,ghostLev,IsConservativeNature(coarse->_arrs[i].second));
201     }
202 }
203
204 void DataArrayDoubleCollection::SynchronizeCoarseToFine(mcIdType ghostLev, const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh, mcIdType patchId, const DataArrayDoubleCollection *coarse, DataArrayDoubleCollection *fine)
205 {
206   if(!fine || !coarse)
207     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeCoarseToFine : the input DataArrayDouble collections must be non NULL !");
208   std::size_t sz(coarse->_arrs.size());
209   if(fine->_arrs.size()!=sz)
210     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeCoarseToFine : the input DataArrayDouble collection must have the same size !");
211   for(std::size_t i=0;i<sz;i++)
212     {
213       CheckSameNatures(fine->_arrs[i].second,coarse->_arrs[i].second);
214       fatherOfFineMesh->fillCellFieldOnPatchGhost(patchId,coarse->_arrs[i].first,fine->_arrs[i].first,ghostLev,IsConservativeNature(coarse->_arrs[i].second));
215     }
216 }
217
218 void DataArrayDoubleCollection::SynchronizeFineEachOther(mcIdType patchId, mcIdType ghostLev, const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh, const std::vector<const MEDCouplingCartesianAMRMeshGen *>& children, const std::vector<DataArrayDoubleCollection *>& fieldsOnFine)
219 {
220   if(!fatherOfFineMesh)
221     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeFineEachOther : father is NULL !");
222   std::size_t sz(children.size());
223   if(fieldsOnFine.size()!=sz)
224     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeFineEachOther : sizes of vectors mismatch !");
225   if(sz<=1)
226     return ;
227   std::size_t nbOfCall(fieldsOnFine[0]->_arrs.size());
228   for(std::size_t i=0;i<sz;i++)
229     if(fatherOfFineMesh->getPatchIdFromChildMesh(children[i])!=ToIdType(i))
230       throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeFineEachOther : internal error !");
231   for(std::size_t i=1;i<sz;i++)
232     if(nbOfCall!=fieldsOnFine[i]->_arrs.size())
233       throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeFineEachOther : the collection of DataArrayDouble must have all the same size !");
234   for(std::size_t i=0;i<nbOfCall;i++)
235     {
236       std::vector<const DataArrayDouble *> arrs(sz);
237       for(std::size_t j=0;j<sz;j++)
238         arrs[j]=fieldsOnFine[j]->_arrs[i].first;
239       fatherOfFineMesh->fillCellFieldOnPatchOnlyGhostAdv(patchId,ghostLev,arrs);
240     }
241 }
242
243 /*!
244  * 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).
245  */
246 void DataArrayDoubleCollection::SynchronizeGhostZoneOfOneUsingTwo(mcIdType ghostLev, const MEDCouplingCartesianAMRPatch *p1, const DataArrayDoubleCollection *p1dac, const MEDCouplingCartesianAMRPatch *p2, const DataArrayDoubleCollection *p2dac)
247 {
248   if(!p1 || !p1dac || !p2 || !p2dac)
249     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeGhostZoneOfOneUsingTwo : input pointer must be not NULL !");
250   std::size_t sz(p1dac->_arrs.size());
251   if(p2dac->_arrs.size()!=sz)
252     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeGhostZoneOfOneUsingTwo : size of DataArrayDouble Collection must be the same !");
253   for(std::size_t i=0;i<sz;i++)
254     {
255       const DataArrayDouble *zeArrWhichGhostsWillBeUpdated(p1dac->_arrs[i].first);
256       DataArrayDoubleCollection::CheckSameNatures(p1dac->_arrs[i].second,p2dac->_arrs[i].second);
257       bool isConservative(DataArrayDoubleCollection::IsConservativeNature(p1dac->_arrs[i].second));
258       MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoMixedLev(ghostLev,p1,p2,const_cast<DataArrayDouble *>(zeArrWhichGhostsWillBeUpdated),p2dac->_arrs[i].first,isConservative);
259     }
260 }
261
262 void DataArrayDoubleCollection::SynchronizeCoarseToFineOnlyInGhostZone(mcIdType ghostLev, const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh, mcIdType patchId, const DataArrayDoubleCollection *coarse, DataArrayDoubleCollection *fine)
263 {
264   if(!fine || !coarse)
265     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeCoarseToFineOnlyInGhostZone : the input DataArrayDouble collections must be non NULL !");
266   std::size_t sz(coarse->_arrs.size());
267   if(fine->_arrs.size()!=sz)
268     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeCoarseToFineOnlyInGhostZone : the input DataArrayDouble collection must have the same size !");
269   for(std::size_t i=0;i<sz;i++)
270     fatherOfFineMesh->fillCellFieldOnPatchOnlyOnGhostZone(patchId,coarse->_arrs[i].first,fine->_arrs[i].first,ghostLev);
271 }
272
273 void DataArrayDoubleCollection::synchronizeMyGhostZoneUsing(mcIdType ghostLev, const DataArrayDoubleCollection& other, const MEDCouplingCartesianAMRPatch *thisp, const MEDCouplingCartesianAMRPatch *otherp, const MEDCouplingCartesianAMRMeshGen *father) const
274 {
275   DataArrayDoubleCollection *thisNC(const_cast<DataArrayDoubleCollection *>(this));
276   std::size_t sz(_arrs.size());
277   if(other._arrs.size()!=sz)
278     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::synchronizeMyGhostZoneUsing : sizes of collections must match !");
279   for(std::size_t i=0;i<sz;i++)
280     father->fillCellFieldOnPatchOnlyOnGhostZoneWith(ghostLev,thisp,otherp,thisNC->_arrs[i].first,other._arrs[i].first);
281 }
282
283 void DataArrayDoubleCollection::synchronizeMyGhostZoneUsingExt(mcIdType ghostLev, const DataArrayDoubleCollection& other, const MEDCouplingCartesianAMRPatch *thisp, const MEDCouplingCartesianAMRPatch *otherp) const
284 {
285   DataArrayDoubleCollection *thisNC(const_cast<DataArrayDoubleCollection *>(this));
286   std::size_t sz(_arrs.size());
287   if(other._arrs.size()!=sz)
288     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::synchronizeMyGhostZoneUsingExt : sizes of collections must match !");
289   for(std::size_t i=0;i<sz;i++)
290     MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoExt(ghostLev,thisp,otherp,thisNC->_arrs[i].first,other._arrs[i].first);
291 }
292
293 DataArrayDoubleCollection::DataArrayDoubleCollection(const std::vector< std::pair<std::string,int> >& fieldNames):_arrs(fieldNames.size())
294 {
295   std::size_t sz(fieldNames.size());
296   std::vector<std::string> names(sz);
297   for(std::size_t i=0;i<sz;i++)
298     {
299       const std::pair<std::string,int>& info(fieldNames[i]);
300       if(info.second<=0)
301         {
302           std::ostringstream oss; oss << "DataArrayDoubleCollection constructor : At pos #" << i << " the array with name \"" << info.first << "\" as a number of components equal to " << info.second;
303           oss << " It has to be >=1 !";
304           throw INTERP_KERNEL::Exception(oss.str().c_str());
305         }
306       _arrs[i].first=DataArrayDouble::New();
307       _arrs[i].first->alloc(0,info.second);
308       _arrs[i].first->setName(info.first);
309       names[i]=info.first;
310       _arrs[i].second=IntensiveMaximum;
311     }
312   CheckDiscriminantNames(names);
313 }
314
315 DataArrayDoubleCollection::DataArrayDoubleCollection(const DataArrayDoubleCollection& other):RefCountObject(other),_arrs(other._arrs.size())
316 {
317   std::size_t sz(other._arrs.size());
318   for(std::size_t i=0;i<sz;i++)
319     {
320       _arrs[i].second=other._arrs[i].second;
321       const DataArrayDouble *da(other._arrs[i].first);
322       if(da)
323         _arrs[i].first=da->deepCopy();
324     }
325 }
326
327 std::size_t DataArrayDoubleCollection::getHeapMemorySizeWithoutChildren() const
328 {
329   std::size_t ret(sizeof(DataArrayDoubleCollection));
330   ret+=_arrs.capacity()*sizeof(MCAuto<DataArrayDouble>);
331   return ret;
332 }
333
334 std::vector<const BigMemoryObject *> DataArrayDoubleCollection::getDirectChildrenWithNull() const
335 {
336   std::vector<const BigMemoryObject *> ret;
337   for(std::vector< std::pair< MCAuto<DataArrayDouble>, NatureOfField > >::const_iterator it=_arrs.begin();it!=_arrs.end();it++)
338     ret.push_back((const DataArrayDouble *)(*it).first);
339   return ret;
340 }
341
342 void DataArrayDoubleCollection::updateTime() const
343 {
344   for(std::vector< std::pair< MCAuto<DataArrayDouble>, NatureOfField > >::const_iterator it=_arrs.begin();it!=_arrs.end();it++)
345     {
346       const DataArrayDouble *pt((*it).first);
347       if(pt)
348         updateTimeWith(*pt);
349     }
350 }
351
352 void DataArrayDoubleCollection::CheckDiscriminantNames(const std::vector<std::string>& names)
353 {
354   std::set<std::string> s(names.begin(),names.end());
355   if(s.size()!=names.size())
356     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::CheckDiscriminantNames : The names of fields must be different each other ! It is not the case !");
357 }
358
359 bool DataArrayDoubleCollection::IsConservativeNature(NatureOfField n)
360 {
361   CheckValidNature(n);
362   return n==IntensiveConservation || n==ExtensiveConservation;
363 }
364
365 void DataArrayDoubleCollection::CheckSameNatures(NatureOfField n1, NatureOfField n2)
366 {
367   CheckValidNature(n1);
368   CheckValidNature(n2);
369   if(n1!=n2)
370     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::CheckSameNatures : natures are not the same !");
371 }
372
373 void DataArrayDoubleCollection::CheckValidNature(NatureOfField n)
374 {
375   if(n!=IntensiveMaximum && n!=ExtensiveMaximum && n!=ExtensiveConservation && n!=IntensiveConservation)
376     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::CheckValidNature : unrecognized nature !");
377 }
378
379 MEDCouplingGridCollection *MEDCouplingGridCollection::New(const std::vector<const MEDCouplingCartesianAMRMeshGen *>& ms, const std::vector< std::pair<std::string,int> >& fieldNames)
380 {
381   return new MEDCouplingGridCollection(ms,fieldNames);
382 }
383
384 MEDCouplingGridCollection *MEDCouplingGridCollection::deepCopy(const MEDCouplingCartesianAMRMeshGen *newGf, const MEDCouplingCartesianAMRMeshGen *oldGf) const
385 {
386   return new MEDCouplingGridCollection(*this,newGf,oldGf);
387 }
388
389 void MEDCouplingGridCollection::alloc(mcIdType ghostLev)
390 {
391   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MCAuto<DataArrayDoubleCollection> > >::iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
392     {
393       mcIdType nbTuples((*it).first->getNumberOfCellsAtCurrentLevelGhost(ghostLev));
394       DataArrayDoubleCollection *dadc((*it).second);
395       if(dadc)
396         dadc->allocTuples(nbTuples);
397       else
398         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::alloc : internal error !");
399     }
400 }
401
402 void MEDCouplingGridCollection::dealloc()
403 {
404   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MCAuto<DataArrayDoubleCollection> > >::iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
405     {
406       DataArrayDoubleCollection *dadc((*it).second);
407       if(dadc)
408         dadc->dellocTuples();
409       else
410         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::dealloc : internal error !");
411     }
412 }
413
414 void MEDCouplingGridCollection::spillInfoOnComponents(const std::vector< std::vector<std::string> >& compNames)
415 {
416   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MCAuto<DataArrayDoubleCollection> > >::iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
417     (*it).second->spillInfoOnComponents(compNames);
418 }
419
420 void MEDCouplingGridCollection::spillNatures(const std::vector<NatureOfField>& nfs)
421 {
422   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MCAuto<DataArrayDoubleCollection> > >::iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
423     (*it).second->spillNatures(nfs);
424 }
425
426 std::vector< std::pair<std::string, std::vector<std::string> > > MEDCouplingGridCollection::getInfoOnComponents() const
427 {
428   if(_map_of_dadc.empty())
429     throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::getInfoOnComponents : empty map !");
430   const DataArrayDoubleCollection *elt(_map_of_dadc[0].second);
431   if(!elt)
432     throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::getInfoOnComponents : null pointer !");
433   return elt->getInfoOnComponents();
434 }
435
436 std::vector<NatureOfField> MEDCouplingGridCollection::getNatures() const
437 {
438   if(_map_of_dadc.empty())
439     throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::getNatures : empty map !");
440   const DataArrayDoubleCollection *elt(_map_of_dadc[0].second);
441   if(!elt)
442     throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::getNatures : null pointer !");
443   return elt->getNatures();
444 }
445
446 bool MEDCouplingGridCollection::presenceOf(const MEDCouplingCartesianAMRMeshGen *m, mcIdType& pos) const
447 {
448   mcIdType ret(0);
449   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MCAuto<DataArrayDoubleCollection> > >::const_iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++,ret++)
450     {
451       if((*it).first==m)
452         {
453           pos=ret;
454           return true;
455         }
456     }
457   return false;
458 }
459
460 const DataArrayDoubleCollection& MEDCouplingGridCollection::getFieldsAt(mcIdType pos) const
461 {
462   if(pos<0 || pos>ToIdType(_map_of_dadc.size()))
463     throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::getFieldsAt : invalid pos given in input ! Must be in [0,size) !");
464   return *_map_of_dadc[pos].second;
465 }
466
467 DataArrayDoubleCollection& MEDCouplingGridCollection::getFieldsAt(mcIdType pos)
468 {
469   if(pos<0 || pos>ToIdType(_map_of_dadc.size()))
470     throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::getFieldsAt (non const) : invalid pos given in input ! Must be in [0,size) !");
471   return *_map_of_dadc[pos].second;
472 }
473
474 /*!
475  * This method copies for all grids intersecting themselves (between \a this and \a other), the values of fields of \a other to the intersecting
476  * part of fields of \a this. The fields are expected to be the same between \a other and \a this.
477  * This methods makes the hypothesis that \a this and \a other share two god father that are compatible each other that is to say with the same cell grid structure.
478  */
479 void MEDCouplingGridCollection::copyOverlappedZoneFrom(mcIdType ghostLev, const MEDCouplingGridCollection& other)
480 {
481   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MCAuto<DataArrayDoubleCollection> > >::iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
482     {
483       std::vector<mcIdType> deltaThis,deltaOther;
484       std::vector< std::pair<mcIdType,mcIdType> > rgThis((*it).first->positionRelativeToGodFather(deltaThis));
485       std::vector<mcIdType> thisSt((*it).first->getImageMesh()->getCellGridStructure());
486       std::transform(thisSt.begin(),thisSt.end(),thisSt.begin(),std::bind(std::plus<mcIdType>(),std::placeholders::_1,2*ghostLev));
487       for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MCAuto<DataArrayDoubleCollection> > >::const_iterator it2=other._map_of_dadc.begin();it2!=other._map_of_dadc.end();it2++)
488         {
489           std::vector< std::pair<mcIdType,mcIdType> > rgOther((*it2).first->positionRelativeToGodFather(deltaOther));
490           if(MEDCouplingStructuredMesh::AreRangesIntersect(rgThis,rgOther))
491             {
492               std::vector< std::pair<mcIdType,mcIdType> > isect(MEDCouplingStructuredMesh::IntersectRanges(rgThis,rgOther));
493               std::vector< std::pair<mcIdType,mcIdType> > pThis,pOther;
494               MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(rgThis,isect,pThis,true);
495               MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(rgOther,isect,pOther,true);
496               std::vector<mcIdType> otherSt((*it2).first->getImageMesh()->getCellGridStructure());
497               MEDCouplingStructuredMesh::ApplyGhostOnCompactFrmt(pThis,ghostLev);
498               MEDCouplingStructuredMesh::ApplyGhostOnCompactFrmt(pOther,ghostLev);
499               std::transform(otherSt.begin(),otherSt.end(),otherSt.begin(),std::bind(std::plus<mcIdType>(),std::placeholders::_1,2*ghostLev));
500               mcIdType sz((*it2).second->size());
501               for(mcIdType i=0;i<sz;i++)
502                 {
503                   const DataArrayDouble *otherArr((*it2).second->at(i));
504                   DataArrayDouble *thisArr((*it).second->at(i));
505                   MCAuto<DataArrayDouble> partOfOther(MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom(otherSt,otherArr,pOther));
506                   MEDCouplingStructuredMesh::AssignPartOfFieldOfDoubleUsing(thisSt,thisArr,pThis,partOfOther);
507                 }
508             }
509         }
510     }
511 }
512
513 void MEDCouplingGridCollection::SynchronizeFineToCoarse(mcIdType ghostLev, const MEDCouplingGridCollection *fine, const MEDCouplingGridCollection *coarse)
514 {
515   if(!fine || !coarse)
516     throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeFineToCoarse : one or more input pointer is NULL !");
517   const std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MCAuto<DataArrayDoubleCollection> > >& mf(fine->_map_of_dadc);
518   const std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MCAuto<DataArrayDoubleCollection> > >& mc(coarse->_map_of_dadc);
519   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MCAuto<DataArrayDoubleCollection> > >::const_iterator it=mf.begin();it!=mf.end();it++)
520     {
521       const MEDCouplingCartesianAMRMeshGen *fineMesh((*it).first);
522       const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh(fineMesh->getFather());
523       bool found(false);
524       for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MCAuto<DataArrayDoubleCollection> > >::const_iterator it0=mc.begin();it0!=mc.end() && !found;it0++)
525         {
526           if((*it0).first==fatherOfFineMesh)
527             {
528               found=true;
529               mcIdType patchId(fatherOfFineMesh->getPatchIdFromChildMesh(fineMesh));
530               const DataArrayDoubleCollection *coarseDaCol((*it0).second);
531               DataArrayDoubleCollection *coarseModified(const_cast<DataArrayDoubleCollection *>(coarseDaCol));//coarse values in DataArrayDouble will be altered
532               DataArrayDoubleCollection::SynchronizeFineToCoarse(ghostLev,fatherOfFineMesh,patchId,(*it).second,coarseModified);
533             }
534         }
535       if(!found)
536         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeFineToCoarse : a fine mesh is orphan regarding given coarse meshes !");
537     }
538 }
539
540 void MEDCouplingGridCollection::SynchronizeCoarseToFine(mcIdType ghostLev, const MEDCouplingGridCollection *coarse, const MEDCouplingGridCollection *fine)
541 {
542   if(!fine || !coarse)
543     throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeCoarseToFine : one or more input pointer is NULL !");
544   const std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MCAuto<DataArrayDoubleCollection> > >& mf(fine->_map_of_dadc);
545   const std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MCAuto<DataArrayDoubleCollection> > >& mc(coarse->_map_of_dadc);
546   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MCAuto<DataArrayDoubleCollection> > >::const_iterator it=mf.begin();it!=mf.end();it++)
547     {
548       const MEDCouplingCartesianAMRMeshGen *fineMesh((*it).first);
549       const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh(fineMesh->getFather());
550       bool found(false);
551       for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MCAuto<DataArrayDoubleCollection> > >::const_iterator it0=mc.begin();it0!=mc.end() && !found;it0++)
552         {
553           if((*it0).first==fatherOfFineMesh)
554             {
555               found=true;
556               mcIdType patchId(fatherOfFineMesh->getPatchIdFromChildMesh(fineMesh));
557               const DataArrayDoubleCollection *fineDaCol((*it).second);
558               DataArrayDoubleCollection *fineModified(const_cast<DataArrayDoubleCollection *>(fineDaCol));//fine values in DataArrayDouble will be altered
559               DataArrayDoubleCollection::SynchronizeCoarseToFine(ghostLev,fatherOfFineMesh,patchId,(*it0).second,fineModified);
560             }
561         }
562       if(!found)
563         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeCoarseToFine : a fine mesh is orphan regarding given coarse meshes !");
564     }
565 }
566
567 /*!
568  * All the pairs in \a ps must share the same father. If not call synchronizeFineEachOtherExt instead.
569  *
570  * \sa synchronizeFineEachOtherExt
571  */
572 void MEDCouplingGridCollection::synchronizeFineEachOther(mcIdType ghostLev, const std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >& ps) const
573 {
574   for(std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >::const_iterator it=ps.begin();it!=ps.end();it++)
575     {
576       mcIdType p1,p2;
577       if(!presenceOf((*it).first->getMesh(),p1))
578         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::synchronizeFineEachOther : internal error #1 !");
579       if(!presenceOf((*it).second->getMesh(),p2))
580         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::synchronizeFineEachOther : internal error #2 !");
581       const DataArrayDoubleCollection& col1(getFieldsAt(p1));
582       const DataArrayDoubleCollection& col2(getFieldsAt(p2));
583       col1.synchronizeMyGhostZoneUsing(ghostLev,col2,(*it).first,(*it).second,(*it).first->getMesh()->getFather());
584     }
585 }
586
587 /*!
588  * This method is a generalization of synchronizeFineEachOther because elements in pairs are \b not sharing the same father but are neighbors nevertheless.
589  *
590  * \sa synchronizeFineEachOther
591  */
592 void MEDCouplingGridCollection::synchronizeFineEachOtherExt(mcIdType ghostLev, const std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >& ps) const
593 {
594   for(std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >::const_iterator it=ps.begin();it!=ps.end();it++)
595     {
596       mcIdType p1,p2;
597       if(!presenceOf((*it).first->getMesh(),p1))
598         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::synchronizeFineEachOtherExt : internal error #1 !");
599       if(!presenceOf((*it).second->getMesh(),p2))
600         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::synchronizeFineEachOtherExt : internal error #2 !");
601       const DataArrayDoubleCollection& col1(getFieldsAt(p1));
602       const DataArrayDoubleCollection& col2(getFieldsAt(p2));
603       col1.synchronizeMyGhostZoneUsingExt(ghostLev,col2,(*it).first,(*it).second);
604     }
605 }
606
607 /*!
608  * The pairs returned share the same direct father. The number of returned elements must be even.
609  */
610 std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > MEDCouplingGridCollection::findNeighbors(mcIdType ghostLev) const
611 {
612   std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > ret;
613   std::map<const MEDCouplingCartesianAMRMeshGen *,std::vector< const MEDCouplingCartesianAMRMeshGen * > > m;
614   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MCAuto<DataArrayDoubleCollection> > >::const_iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
615     {
616       const MEDCouplingCartesianAMRMeshGen *fineMesh((*it).first);
617       const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh(fineMesh->getFather());
618       m[fatherOfFineMesh].push_back(fineMesh);
619     }
620   for(std::map<const MEDCouplingCartesianAMRMeshGen *,std::vector< const MEDCouplingCartesianAMRMeshGen * > >::const_iterator it0=m.begin();it0!=m.end();it0++)
621     {
622       for(std::vector<const MEDCouplingCartesianAMRMeshGen *>::const_iterator it1=(*it0).second.begin();it1!=(*it0).second.end();it1++)
623         {
624           mcIdType patchId((*it0).first->getPatchIdFromChildMesh(*it1));
625           std::vector<mcIdType> neighs((*it0).first->getPatchIdsInTheNeighborhoodOf(patchId,ghostLev));
626           const MEDCouplingCartesianAMRPatch *pRef((*it0).first->getPatch(patchId));
627           for(std::vector<mcIdType>::const_iterator it2=neighs.begin();it2!=neighs.end();it2++)
628             {
629               const MEDCouplingCartesianAMRPatch *pLoc((*it0).first->getPatch(*it2));
630               ret.push_back(std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *>(pRef,pLoc));
631             }
632         }
633     }
634   if(ret.size()%2!=0)
635     throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::findNeighbors : something is wrong ! The number of neighbor pairs must be %2 ==0 !");
636   return ret;
637 }
638
639 void MEDCouplingGridCollection::SynchronizeCoarseToFineOnlyInGhostZone(mcIdType ghostLev, const MEDCouplingGridCollection *coarse, const MEDCouplingGridCollection *fine)
640 {
641   if(!fine || !coarse)
642     throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeCoarseToFineOnlyInGhostZone : one or more input pointer is NULL !");
643   const std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MCAuto<DataArrayDoubleCollection> > >& mf(fine->_map_of_dadc);
644   const std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MCAuto<DataArrayDoubleCollection> > >& mc(coarse->_map_of_dadc);
645   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MCAuto<DataArrayDoubleCollection> > >::const_iterator it=mf.begin();it!=mf.end();it++)
646     {
647       const MEDCouplingCartesianAMRMeshGen *fineMesh((*it).first);
648       const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh(fineMesh->getFather());
649       bool found(false);
650       for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MCAuto<DataArrayDoubleCollection> > >::const_iterator it0=mc.begin();it0!=mc.end() && !found;it0++)
651         {
652           if((*it0).first==fatherOfFineMesh)
653             {
654               found=true;
655               mcIdType patchId(fatherOfFineMesh->getPatchIdFromChildMesh(fineMesh));
656               const DataArrayDoubleCollection *fineDaCol((*it).second);
657               DataArrayDoubleCollection *fineModified(const_cast<DataArrayDoubleCollection *>(fineDaCol));//fine values in DataArrayDouble will be altered
658               DataArrayDoubleCollection::SynchronizeCoarseToFineOnlyInGhostZone(ghostLev,fatherOfFineMesh,patchId,(*it0).second,fineModified);
659             }
660         }
661       if(!found)
662         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeCoarseToFineOnlyInGhostZone : a fine mesh is orphan regarding given coarse meshes !");
663     }
664 }
665
666 void MEDCouplingGridCollection::fillIfInTheProgenyOf(const std::string& fieldName, const MEDCouplingCartesianAMRMeshGen *head, std::vector<const DataArrayDouble *>& recurseArrs) const
667 {
668   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MCAuto<DataArrayDoubleCollection> > >::const_iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
669     {
670       const MEDCouplingCartesianAMRMeshGen *a((*it).first);
671       if(head==a || head->isObjectInTheProgeny(a))
672         {
673           const DataArrayDoubleCollection *gc((*it).second);
674           recurseArrs.push_back(gc->getFieldWithName(fieldName));
675         }
676     }
677 }
678
679 MEDCouplingGridCollection::MEDCouplingGridCollection(const std::vector<const MEDCouplingCartesianAMRMeshGen *>& ms, const std::vector< std::pair<std::string,int> >& fieldNames):_map_of_dadc(ms.size())
680 {
681   std::size_t sz(ms.size());
682   for(std::size_t i=0;i<sz;i++)
683     {
684       if(!ms[i])
685         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection constructor : presence of NULL MEDCouplingCartesianAMRMeshGen instance !");
686       _map_of_dadc[i].first=ms[i];
687       _map_of_dadc[i].second=DataArrayDoubleCollection::New(fieldNames);
688     }
689 }
690
691 MEDCouplingGridCollection::MEDCouplingGridCollection(const MEDCouplingGridCollection& other, const MEDCouplingCartesianAMRMeshGen *newGf, const MEDCouplingCartesianAMRMeshGen *oldGf):RefCountObject(other),_map_of_dadc(other._map_of_dadc.size())
692 {
693   std::size_t sz(other._map_of_dadc.size());
694   for(std::size_t i=0;i<sz;i++)
695     {
696       std::vector<mcIdType> pos(other._map_of_dadc[i].first->getPositionRelativeTo(oldGf));
697       _map_of_dadc[i].first=newGf->getMeshAtPosition(pos);
698       const DataArrayDoubleCollection *dac(other._map_of_dadc[i].second);
699       if(dac)
700         _map_of_dadc[i].second=dac->deepCopy();
701     }
702 }
703
704 std::size_t MEDCouplingGridCollection::getHeapMemorySizeWithoutChildren() const
705 {
706   std::size_t ret(sizeof(MEDCouplingGridCollection));
707   ret+=_map_of_dadc.capacity()*sizeof(std::pair<const MEDCouplingCartesianAMRMeshGen *,MCAuto<DataArrayDoubleCollection> >);
708   return ret;
709 }
710
711 std::vector<const BigMemoryObject *> MEDCouplingGridCollection::getDirectChildrenWithNull() const
712 {
713   std::vector<const BigMemoryObject *> ret;
714   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MCAuto<DataArrayDoubleCollection> > >::const_iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
715     ret.push_back((const DataArrayDoubleCollection *)(*it).second);
716   return ret;
717 }
718
719 void MEDCouplingGridCollection::updateTime() const
720 {
721   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MCAuto<DataArrayDoubleCollection> > >::const_iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
722     {
723       const MEDCouplingCartesianAMRMeshGen *a((*it).first);
724       if(a)
725         updateTimeWith(*a);
726       const DataArrayDoubleCollection *b((*it).second);
727       if(b)
728         updateTimeWith(*b);
729     }
730 }
731
732 /// @endcond
733
734 MEDCouplingCartesianAMRMesh *MEDCouplingDataForGodFather::getMyGodFather()
735 {
736   return _gf;
737 }
738
739 const MEDCouplingCartesianAMRMesh *MEDCouplingDataForGodFather::getMyGodFather() const
740 {
741   return _gf;
742 }
743
744 MEDCouplingDataForGodFather::MEDCouplingDataForGodFather(MEDCouplingCartesianAMRMesh *gf):_gf(gf),_tlc(gf)
745 {
746   if(!gf)
747     throw INTERP_KERNEL::Exception("MEDCouplingDataForGodFather constructor : A data has to be attached to a AMR Mesh instance !");
748   gf->incrRef();
749 }
750
751 void MEDCouplingDataForGodFather::checkGodFatherFrozen() const
752 {
753   _tlc.checkConst();
754 }
755
756 bool MEDCouplingDataForGodFather::changeGodFather(MEDCouplingCartesianAMRMesh *gf)
757 {
758   bool ret(_tlc.keepTrackOfNewTL(gf));
759   if(ret)
760     {
761       _gf=gf;
762       if(gf)
763         gf->incrRef();
764     }
765   return ret;
766 }
767
768 MEDCouplingDataForGodFather::MEDCouplingDataForGodFather(const MEDCouplingDataForGodFather& other, bool deepCpyGF):RefCountObject(other),_gf(other._gf),_tlc(other._gf)
769 {
770   other._tlc.checkConst();
771   if(deepCpyGF)
772     {
773       const MEDCouplingCartesianAMRMesh *gf(other._gf);
774       if(gf)
775         _gf=gf->deepCopy(0);
776       _tlc.keepTrackOfNewTL(_gf);
777     }
778 }
779
780 /*!
781  * 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.
782  */
783 MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::New(MEDCouplingCartesianAMRMesh *gf, const std::vector< std::pair<std::string,int> >& fieldNames, mcIdType ghostLev)
784 {
785   return new MEDCouplingAMRAttribute(gf,fieldNames,ghostLev);
786 }
787
788 MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::New(MEDCouplingCartesianAMRMesh *gf, const std::vector< std::pair<std::string, std::vector<std::string> > >& fieldNames, mcIdType ghostLev)
789 {
790   std::size_t sz(fieldNames.size());
791   std::vector< std::pair<std::string,int> > fieldNames2(sz);
792   std::vector< std::vector<std::string> > compNames(sz);
793   for(std::size_t i=0;i<sz;i++)
794     {
795       fieldNames2[i].first=fieldNames[i].first;
796       fieldNames2[i].second=(int)fieldNames[i].second.size();
797       compNames[i]=fieldNames[i].second;
798     }
799   MCAuto<MEDCouplingAMRAttribute> ret(New(gf,fieldNames2,ghostLev));
800   ret->spillInfoOnComponents(compNames);
801   return ret.retn();
802 }
803
804 /*!
805  * Assign the info on components for all DataArrayDouble instance recursively stored in \a this.
806  * The first dim of input \a compNames is the field id in the same order than those implicitly specified in \a fieldNames parameter of MEDCouplingAMRAttribute::New.
807  * The second dim of \a compNames represent the component names component per component corresponding to the field. The size of this 2nd dimension has
808  * to perfectly fit with those specified in MEDCouplingAMRAttribute::New.
809  */
810 void MEDCouplingAMRAttribute::spillInfoOnComponents(const std::vector< std::vector<std::string> >& compNames)
811 {
812   _tlc.checkConst();
813   for(std::vector< MCAuto<MEDCouplingGridCollection> >::iterator it=_levs.begin();it!=_levs.end();it++)
814     (*it)->spillInfoOnComponents(compNames);
815 }
816
817 /*!
818  * Assign nature for each fields in \a this.
819  * \param [in] nfs vector of field natures.
820  */
821 void MEDCouplingAMRAttribute::spillNatures(const std::vector<NatureOfField>& nfs)
822 {
823   _tlc.checkConst();
824   for(std::vector< MCAuto<MEDCouplingGridCollection> >::iterator it=_levs.begin();it!=_levs.end();it++)
825     (*it)->spillNatures(nfs);
826 }
827
828 MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::deepCopy() const
829 {
830   return new MEDCouplingAMRAttribute(*this,true);
831 }
832
833 MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::deepCpyWithoutGodFather() const
834 {
835   return new MEDCouplingAMRAttribute(*this,false);
836 }
837
838 /*!
839  * Returns the number of levels by \b only \b considering \a this (god father instance is considered only to see if it has not changed still last update of \a this).
840  *
841  */
842 mcIdType MEDCouplingAMRAttribute::getNumberOfLevels() const
843 {
844   checkGodFatherFrozen();
845   return ToIdType(_levs.size());
846 }
847
848 /*!
849  * This method returns all DataArrayDouble instances lying on the specified mesh \a mesh.
850  * If \a mesh is not part of the progeny of god father object given at construction of \a this an exception will be thrown.
851  *
852  * \return std::vector<DataArrayDouble *> - DataArrayDouble instances to be deallocated by the caller (using decrRef).
853  * \sa retrieveFieldOn
854  */
855 std::vector<DataArrayDouble *> MEDCouplingAMRAttribute::retrieveFieldsOn(MEDCouplingCartesianAMRMeshGen *mesh) const
856 {
857   for(std::vector< MCAuto<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
858     {
859       mcIdType tmp(-1);
860       if((*it)->presenceOf(mesh,tmp))
861         {
862           const DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp));
863           return ddc.retrieveFields();
864         }
865     }
866   throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::retrieveFieldsOn : the mesh specified is not in the progeny of this !");
867 }
868
869 /*!
870  * \sa retrieveFieldsOn
871  */
872 const DataArrayDouble *MEDCouplingAMRAttribute::getFieldOn(MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) const
873 {
874   for(std::vector< MCAuto<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
875     {
876       mcIdType tmp(-1);
877       if((*it)->presenceOf(mesh,tmp))
878         {
879           const DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp));
880           return ddc.getFieldWithName(fieldName);
881         }
882     }
883   throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::getFieldOn : the mesh specified is not in the progeny of this !");
884 }
885
886 DataArrayDouble *MEDCouplingAMRAttribute::getFieldOn(MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName)
887 {
888   for(std::vector< MCAuto<MEDCouplingGridCollection> >::iterator it=_levs.begin();it!=_levs.end();it++)
889     {
890       mcIdType tmp(-1);
891       if((*it)->presenceOf(mesh,tmp))
892         {
893           DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp));
894           return ddc.getFieldWithName(fieldName);
895         }
896     }
897   throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::getFieldOn non const : the mesh specified is not in the progeny of this !");
898 }
899
900 /*!
901  * This method returns a field on an unstructured mesh the most refined as possible without overlap.
902  * Ghost part are not visible here.
903  *
904  * \return MEDCouplingFieldDouble * - a field on cells that the caller has to deal with (deallocate it).
905  */
906 MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnRecurseWithoutOverlapWithoutGhost(MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) const
907 {
908   std::vector<const DataArrayDouble *> recurseArrs;
909   std::size_t lev(0);
910   for(std::vector< MCAuto<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++,lev++)
911     {
912       mcIdType tmp(-1);
913       if((*it)->presenceOf(mesh,tmp))
914         {
915           const DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp));
916           recurseArrs.push_back(ddc.getFieldWithName(fieldName));
917           break;
918         }
919     }
920   lev++;
921   for(std::size_t i=lev;i<_levs.size();i++)
922     {
923       const MEDCouplingGridCollection *gc(_levs[i]);
924       gc->fillIfInTheProgenyOf(fieldName,mesh,recurseArrs);
925     }
926   return mesh->buildCellFieldOnRecurseWithoutOverlapWithoutGhost(_ghost_lev,recurseArrs);
927 }
928
929 /*!
930  * This method builds a newly created field on cell just lying on mesh \a mesh without its eventual refinement.
931  * The output field also displays ghost cells.
932  *
933  * \return MEDCouplingFieldDouble * - a field on cells that the caller has to deal with (deallocate it).
934  *
935  * \sa buildCellFieldOnWithoutGhost
936  */
937 MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnWithGhost(MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) const
938 {
939   const DataArrayDouble *arr(0);
940   for(std::vector< MCAuto<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
941     {
942       mcIdType tmp(-1);
943       if((*it)->presenceOf(mesh,tmp))
944         {
945           const DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp));
946           arr=ddc.getFieldWithName(fieldName);
947         }
948     }
949   if(!arr)
950     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::buildCellFieldOnWithGhost : the mesh specified is not in the progeny of this !");
951   MCAuto<MEDCouplingIMesh> im(mesh->getImageMesh()->buildWithGhost(_ghost_lev));
952   MCAuto<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS));
953   ret->setMesh(im);
954   ret->setArray(const_cast<DataArrayDouble *>(arr));
955   ret->setName(arr->getName());
956   return ret.retn();
957 }
958
959 /*!
960  * This method builds a newly created field on cell just lying on mesh \a mesh without its eventual refinement.
961  * The output field does not display ghost cells.
962  *
963  * \return MEDCouplingFieldDouble * - a field on cells that the caller has to deal with (deallocate it).
964  *
965  * \sa buildCellFieldOnWithGhost
966  */
967 MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnWithoutGhost(MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) const
968 {
969   const DataArrayDouble *arr(0);
970   for(std::vector< MCAuto<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
971     {
972       mcIdType tmp(-1);
973       if((*it)->presenceOf(mesh,tmp))
974         {
975           const DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp));
976           arr=ddc.getFieldWithName(fieldName);
977         }
978     }
979   if(!arr)
980     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::buildCellFieldOnWithoutGhost : the mesh specified is not in the progeny of this !");
981   //
982   MCAuto<MEDCouplingIMesh> im(mesh->getImageMesh()->buildWithGhost(_ghost_lev));
983   std::vector<mcIdType> cgs(mesh->getImageMesh()->getCellGridStructure()),cgsWG(im->getCellGridStructure());
984   MCAuto<DataArrayDouble> arr2(DataArrayDouble::New());
985   arr2->alloc(mesh->getImageMesh()->getNumberOfCells(),arr->getNumberOfComponents());
986   std::vector< std::pair<mcIdType,mcIdType> > cgs2(MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(cgs));
987   MEDCouplingStructuredMesh::ApplyGhostOnCompactFrmt(cgs2,_ghost_lev);
988   std::vector<mcIdType> fakeFactors(mesh->getImageMesh()->getSpaceDimension(),1);
989   MEDCouplingIMesh::SpreadCoarseToFine(arr,cgsWG,arr2,cgs2,fakeFactors);
990   arr2->copyStringInfoFrom(*arr);
991   //
992   MCAuto<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS));
993   ret->setMesh(mesh->getImageMesh());
994   ret->setArray(arr2);
995   ret->setName(arr->getName());
996   return ret.retn();
997 }
998
999
1000 std::string MEDCouplingAMRAttribute::writeVTHB(const std::string& fileName) const
1001 {
1002   static const char EXT[]=".vthb";
1003   std::string baseName,extName,zeFileName;
1004   MEDCouplingMesh::SplitExtension(fileName,baseName,extName);
1005   if(extName==EXT)
1006     zeFileName=fileName;
1007   else
1008     { zeFileName=baseName; zeFileName+=EXT; }
1009   //
1010   std::ofstream ofs(fileName.c_str());
1011   ofs << "<VTKFile type=\"vtkOverlappingAMR\" version=\"1.1\" byte_order=\"" << MEDCouplingByteOrderStr() << "\">\n";
1012   const MEDCouplingCartesianAMRMesh *gf(getMyGodFather());
1013   ofs << "  <vtkOverlappingAMR origin=\"";
1014   const MEDCouplingIMesh *gfm(gf->getImageMesh());
1015   std::vector<double> orig(gfm->getOrigin());
1016   std::vector<double> spacing(gfm->getDXYZ());
1017   mcIdType dim(ToIdType(orig.size()));
1018   std::copy(orig.begin(),orig.end(),std::ostream_iterator<double>(ofs," ")); ofs << "\" grid_description=\"";
1019   for(mcIdType i=0;i<dim;i++)
1020     {
1021       char tmp[2]; tmp[0]=(char)(int('X')+i); tmp[1]='\0';
1022       ofs << tmp;
1023     }
1024   ofs << "\">\n";
1025   //
1026   mcIdType maxLev(gf->getMaxNumberOfLevelsRelativeToThis()),kk(0);
1027   for(mcIdType i=0;i<maxLev;i++)
1028     {
1029       std::vector<MEDCouplingCartesianAMRPatchGen *> patches(gf->retrieveGridsAt(i));
1030       std::size_t sz(patches.size());
1031       std::vector< MCAuto<MEDCouplingCartesianAMRPatchGen> > patchesSafe(sz);
1032       for(std::size_t j=0;j<sz;j++)
1033         patchesSafe[j]=patches[j];
1034       if(sz==0)
1035         continue;
1036       ofs << "    <Block level=\"" << i << "\" spacing=\"";
1037       std::copy(spacing.begin(),spacing.end(),std::ostream_iterator<double>(ofs," "));
1038       ofs << "\">\n";
1039       if(i!=maxLev-1)
1040         {
1041           std::vector<mcIdType> factors(patches[0]->getMesh()->getFactors());
1042           for(mcIdType k=0;k<dim;k++)
1043             spacing[k]*=1./((double) factors[k]);
1044         }
1045       std::size_t jj(0);
1046       for(std::vector<MEDCouplingCartesianAMRPatchGen *>::const_iterator it=patches.begin();it!=patches.end();it++,jj++,kk++)
1047         {
1048           ofs << "      <DataSet index=\"" << jj << "\" amr_box=\"";
1049           const MEDCouplingCartesianAMRPatch *patchCast(dynamic_cast<const MEDCouplingCartesianAMRPatch *>(*it));
1050           const MEDCouplingCartesianAMRMeshGen *mesh((*it)->getMesh());
1051           if(patchCast)
1052             {
1053               const std::vector< std::pair<mcIdType,mcIdType> >& bltr(patchCast->getBLTRRangeRelativeToGF());
1054               for(mcIdType pp=0;pp<dim;pp++)
1055                 ofs << bltr[pp].first << " " << bltr[pp].second-1 << " ";
1056             }
1057           else
1058             {
1059               const MEDCouplingIMesh *im((*it)->getMesh()->getImageMesh());
1060               std::vector<mcIdType> cgs(im->getCellGridStructure());
1061               for(mcIdType pp=0;pp<dim;pp++)
1062                 ofs << "0 " << cgs[pp]-1 << " ";
1063             }
1064           ofs << "\" file=\"";
1065           //
1066           mcIdType tmp(-1);
1067           if(_levs[i]->presenceOf((*it)->getMesh(),tmp))
1068             {
1069               const DataArrayDoubleCollection& ddc(_levs[i]->getFieldsAt(tmp));
1070               std::vector<DataArrayDouble *> arrs(ddc.retrieveFields());
1071               std::size_t nbFields(arrs.size());
1072               std::vector< MCAuto<DataArrayDouble> > arrsSafe(nbFields),arrs2Safe(nbFields);
1073               std::vector< const MEDCouplingFieldDouble *> fields(nbFields);
1074               std::vector< MCAuto<MEDCouplingFieldDouble> > fieldsSafe(nbFields);
1075               for(std::size_t pp=0;pp<nbFields;pp++)
1076                 arrsSafe[pp]=arrs[pp];
1077               for(std::size_t pp=0;pp<nbFields;pp++)
1078                 {
1079                   MCAuto<MEDCouplingIMesh> im(mesh->getImageMesh()->buildWithGhost(_ghost_lev));
1080                   std::vector<mcIdType> cgs(mesh->getImageMesh()->getCellGridStructure()),cgsWG(im->getCellGridStructure());
1081                   arrs2Safe[pp]=DataArrayDouble::New();
1082                   arrs2Safe[pp]->alloc(mesh->getImageMesh()->getNumberOfCells(),arrs[pp]->getNumberOfComponents());
1083                   std::vector< std::pair<mcIdType,mcIdType> > cgs2(MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(cgs));
1084                   MEDCouplingStructuredMesh::ApplyGhostOnCompactFrmt(cgs2,_ghost_lev);
1085                   std::vector<mcIdType> fakeFactors(mesh->getImageMesh()->getSpaceDimension(),1);
1086                   MEDCouplingIMesh::SpreadCoarseToFine(arrs[pp],cgsWG,arrs2Safe[pp],cgs2,fakeFactors);
1087                   arrs2Safe[pp]->copyStringInfoFrom(*arrs[pp]);
1088                   //
1089                   fieldsSafe[pp]=MEDCouplingFieldDouble::New(ON_CELLS); fields[pp]=fieldsSafe[pp];
1090                   fieldsSafe[pp]->setMesh(mesh->getImageMesh());
1091                   fieldsSafe[pp]->setArray(arrs2Safe[pp]);
1092                   fieldsSafe[pp]->setName(arrs[pp]->getName());
1093                 }
1094               std::ostringstream vtiFileName; vtiFileName << baseName << "_" << kk << ".vti";
1095               MEDCouplingFieldDouble::WriteVTK(vtiFileName.str(),fields,true);
1096               //
1097               ofs << vtiFileName.str() << "\">\n";
1098               ofs << "      \n      </DataSet>\n";
1099             }
1100         }
1101       ofs << "    </Block>\n";
1102     }
1103   //
1104   ofs << "  </vtkOverlappingAMR>\n";
1105   ofs << "</VTKFile>\n";
1106   return zeFileName;
1107 }
1108
1109   /*!
1110    * This method is useful just after a remesh after a time step computation to project values in \a this to the new
1111    * mesh \a targetGF.
1112    *
1113    * This method performs a projection from \a this to a target AMR mesh \a targetGF.
1114    * This method performs the projection by trying to transfer the finest information to \a targetGF.
1115  * \b WARNING this method does not update the ghost zone, if any.
1116  * The level0 of \a this god father must have the same structure than those of \a targetGF.
1117  *
1118  * This method makes checks that ghost size of \a this and \a targetGF are the same, and that
1119  * the number of levels in \a this and in \a targetGF are also the same.
1120  */
1121 MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::projectTo(MEDCouplingCartesianAMRMesh *targetGF) const
1122 {
1123   if(!targetGF)
1124     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::projectTo : given other target god is NULL !");
1125   if(_levs.empty())
1126     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::projectTo : no levels in this !");
1127   const MEDCouplingGridCollection *lev0(_levs[0]);
1128   if(!lev0)
1129     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::projectTo : lev0 is NULL !");
1130   std::vector< std::pair < std::string, std::vector<std::string> > > fieldNames(lev0->getInfoOnComponents());
1131   MCAuto<MEDCouplingAMRAttribute> ret(MEDCouplingAMRAttribute::New(targetGF,fieldNames,_ghost_lev));
1132   ret->spillNatures(lev0->getNatures());
1133   ret->alloc();
1134   mcIdType nbLevs(getNumberOfLevels());
1135   if(targetGF->getMaxNumberOfLevelsRelativeToThis()!=nbLevs)
1136     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::projectTo : number of levels of this and targetGF must be the same !");
1137   // first step copy level0
1138   if(getMyGodFather()->getImageMesh()->getCellGridStructure()!=targetGF->getImageMesh()->getCellGridStructure())
1139     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::projectTo : god father of this and target ones do not have the same structure !");
1140   const DataArrayDoubleCollection& col(lev0->getFieldsAt(0));
1141   DataArrayDoubleCollection& colTarget(ret->_levs[0]->getFieldsAt(0));
1142   colTarget.copyFrom(col);
1143   // then go deeper and deeper
1144   for(mcIdType i=1;i<nbLevs;i++)
1145     {
1146       ret->synchronizeCoarseToFineByOneLevel(i-1);
1147       MEDCouplingGridCollection *targetCol(ret->_levs[i]);
1148       if(!targetCol)
1149         throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::projectTo : null lev of target !");
1150       const MEDCouplingGridCollection *thisCol(_levs[i]);
1151       if(!thisCol)
1152         throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::projectTo : null lev of this !");
1153       targetCol->copyOverlappedZoneFrom(_ghost_lev,*thisCol);
1154     }
1155   return ret.retn();
1156 }
1157
1158 /*!
1159  * This method synchronizes from fine to coarse direction arrays. This method makes the hypothesis that \a this has been allocated before using
1160  * MEDCouplingAMRAttribute::alloc method.
1161  * This method \b DOES \b NOT \b UPDATE the ghost zones (neither the fine not the coarse)
1162  *
1163  * \sa synchronizeFineToCoarseBetween
1164  */
1165 void MEDCouplingAMRAttribute::synchronizeFineToCoarse()
1166 {
1167   if(_levs.empty())
1168     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineToCoarse : not any levels in this !");
1169   std::size_t sz(_levs.size());
1170   //
1171   while(sz>1)
1172     {
1173       sz--;
1174       synchronizeFineToCoarseByOneLevel(ToIdType(sz));
1175     }
1176 }
1177
1178 /*!
1179  * This method allows to synchronizes fields on fine patches on level \a fromLev to coarser patches at \a toLev level.
1180  * This method operates step by step performing the synchronization the \a fromLev to \a fromLev - 1, then \a fromLev -1 to \a fromLev - 2 ...
1181  * until reaching \a toLev level.
1182  * This method \b DOES \b NOT \b UPDATE the ghost zones (neither the fine not the coarse).
1183  *
1184  * \param [in] fromLev - an existing level considered as fine so bigger than \a toLev
1185  * \param [in] toLev - an existing level considered as the target level to reach.
1186  *
1187  */
1188 void MEDCouplingAMRAttribute::synchronizeFineToCoarseBetween(mcIdType fromLev, mcIdType toLev)
1189 {
1190   mcIdType nbl(getNumberOfLevels());
1191   if(fromLev<0 || toLev<0 || fromLev>=nbl || toLev>=nbl)
1192     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineToCoarseBetween : fromLev and toLev must be >= 0 and lower than number of levels in this !");
1193   if(fromLev==toLev)
1194     return ;//nothing to do
1195   if(fromLev<toLev)
1196     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineToCoarseBetween : the fromLev level is lower than toLev level ! Call synchronizeFineToCoarseBetween ");
1197   for(mcIdType i=fromLev;i>toLev;i--)
1198     synchronizeFineToCoarseByOneLevel(i);
1199 }
1200
1201 /*!
1202  * 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
1203  * MEDCouplingAMRAttribute::alloc method.
1204  * This method \b DOES \b UPDATE \b the \b ghost \b zone (contrary to synchronizeFineToCoarse method)
1205  */
1206 void MEDCouplingAMRAttribute::synchronizeCoarseToFine()
1207 {
1208   if(_levs.empty())
1209     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeCoarseToFine : not any levels in this !");
1210   std::size_t sz(_levs.size());
1211   //
1212   for(std::size_t i=0;i<sz-1;i++)
1213     synchronizeCoarseToFineByOneLevel(ToIdType(i));
1214 }
1215
1216 /*!
1217  * This method allows to synchronizes fields on coarse patches on level \a fromLev to their respective refined patches at \a toLev level.
1218  * This method operates step by step performing the synchronization the \a fromLev to \a fromLev + 1, then \a fromLev + 1 to \a fromLev + 2 ...
1219  * until reaching \a toLev level.
1220  * This method \b DOES \b UPDATE \b the \b ghost \b zone (contrary to synchronizeFineToCoarseBetween method)
1221  *
1222  * \param [in] fromLev - an existing level considered as coarse so lower than \a toLev
1223  * \param [in] toLev - an existing level considered as the target level to reach.
1224  */
1225 void MEDCouplingAMRAttribute::synchronizeCoarseToFineBetween(mcIdType fromLev, mcIdType toLev)
1226 {
1227   mcIdType nbl(getNumberOfLevels());
1228   if(fromLev<0 || toLev<0 || fromLev>=nbl || toLev>=nbl)
1229     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeCoarseToFineBetween : fromLev and toLev must be >= 0 and lower than number of levels in this !");
1230   if(fromLev==toLev)
1231     return ;//nothing to do
1232   if(fromLev>toLev)
1233     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeCoarseToFineBetween : the fromLev level is greater than toLev level ! Call synchronizeFineToCoarseBetween instead !");
1234   for(mcIdType i=fromLev;i<toLev;i++)
1235     synchronizeCoarseToFineByOneLevel(i);
1236 }
1237
1238 /*!
1239  * This method synchronizes the ghost zone of all patches (excepted the god father one).
1240  * This method operates in 4 steps. Larger is the number of steps more accurate is the information in the ghost zone.
1241  *
1242  * - firstly coarse to fine with no interactions between brother patches.
1243  * - secondly connected brother patches in a same master patch are updated.
1244  * - thirdly connected nephew patches are updated each other.
1245  * - forthly nth generation cousin patches are updated each other.
1246  *
1247  * This method makes the hypothesis that \a this has been allocated before using MEDCouplingAMRAttribute::alloc method.
1248  * So if \a _ghost_lev == 0 this method has no effect.
1249  */
1250 void MEDCouplingAMRAttribute::synchronizeAllGhostZones()
1251 {
1252   mcIdType sz(getNumberOfLevels());
1253   if(sz==0)
1254     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineEachOther : not any levels in this !");
1255   // 1st - synchronize from coarse to the finest all the patches (excepted the god father one)
1256   for(mcIdType i=1;i<sz;i++)
1257     {
1258       const MEDCouplingGridCollection *fine(_levs[i]),*coarse(_levs[i-1]);
1259       MEDCouplingGridCollection::SynchronizeCoarseToFineOnlyInGhostZone(_ghost_lev,coarse,fine);
1260     }
1261   // 2nd - classical direct sublevel inside common patch
1262   for(mcIdType i=1;i<sz;i++)
1263     {
1264       const MEDCouplingGridCollection *curLev(_levs[i]);
1265       if(!curLev)
1266         throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineEachOtherInGhostZone : presence of a NULL element !");
1267       curLev->synchronizeFineEachOther(_ghost_lev,_neighbors[i]);
1268     }
1269   // 3rd - mixed level
1270   for(std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >::const_iterator it=_mixed_lev_neighbors.begin();it!=_mixed_lev_neighbors.end();it++)
1271     {
1272       const DataArrayDoubleCollection *firstDAC(&findCollectionAttachedTo((*it).first->getMesh())),*secondDAC(&findCollectionAttachedTo((*it).second->getMesh()));
1273       DataArrayDoubleCollection::SynchronizeGhostZoneOfOneUsingTwo(_ghost_lev,(*it).first,firstDAC,(*it).second,secondDAC);
1274     }
1275   // 4th - same level but with far ancestor.
1276   for(mcIdType i=1;i<sz;i++)
1277     {
1278       const MEDCouplingGridCollection *fine(_levs[i]);
1279       fine->synchronizeFineEachOtherExt(_ghost_lev,_cross_lev_neighbors[i]);
1280     }
1281 }
1282
1283 /*!
1284  * This method works \b ONLY \b ON \b DIRECT \b SONS \b OF \a mesh. So only a part of patches at a given level is updated here.
1285  * The ghost zone of all of these sons of \a mesh are updated using the brother patches (the patches sharing the \b SAME \a mesh).
1286  * It is sometimes possible that a ghost zone of some sons of \a mesh are covered by a patch of same level but different father.
1287  * For such cases, the ghost zones are \b NOT updated. If you need a more thorough (but more costly) ghost zone update use synchronizeAllGhostZonesAtASpecifiedLevel method instead.
1288  *
1289  * \param [in] mesh - an element in the progeny of god father in \a this, which the ghost zone of its sons will be updated each other.
1290  *
1291  */
1292 void MEDCouplingAMRAttribute::synchronizeAllGhostZonesOfDirectChidrenOf(const MEDCouplingCartesianAMRMeshGen *mesh)
1293 {
1294   if(!mesh)
1295     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeAllGhostZonesOfDirectChidrenOf : input mesh is NULL !");
1296   mcIdType level(mesh->getAbsoluteLevelRelativeTo(_gf)),sz(getNumberOfLevels());
1297   if(level<0 || level>=sz-1)
1298     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeAllGhostZonesOfDirectChidrenOf : the specified level does not exist ! Must be in [0,nbOfLevelsOfThis-1) !");
1299   const std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >& itemsToFilter(_neighbors[level+1]);
1300   std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > itemsToSync; itemsToSync.reserve(itemsToFilter.size());
1301   for(std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >::const_iterator it=itemsToFilter.begin();it!=itemsToFilter.end();it++)
1302     {
1303       if((*it).first->getMesh()->getFather()==mesh && (*it).second->getMesh()->getFather()==mesh)
1304         itemsToSync.push_back(std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *>((*it).first,(*it).second));
1305     }
1306   const MEDCouplingGridCollection *curLev(_levs[level+1]);
1307   if(!curLev)
1308     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeAllGhostZonesOfDirectChidrenOf : presence of a NULL element !");
1309   curLev->synchronizeFineEachOther(_ghost_lev,itemsToSync);
1310 }
1311
1312 /*!
1313  * This method updates \b all the patches at level \a level each other without consideration of their father.
1314  * So this method is more time consuming than synchronizeAllGhostZonesOfDirectChidrenOf.
1315  */
1316 void MEDCouplingAMRAttribute::synchronizeAllGhostZonesAtASpecifiedLevel(mcIdType level)
1317 {
1318   mcIdType maxLev(getNumberOfLevels());
1319   if(level<0 || level>=maxLev)
1320     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeAllGhostZonesAtASpecifiedLevel : the specified level must be in [0,maxLevel) !");
1321   if(level==0)
1322     return ;//at level 0 only one patch -> no need to update
1323   // 1st step - updates all patches pairs at level \a level sharing the same father
1324   const std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >& items(_neighbors[level]);
1325   const MEDCouplingGridCollection *curLev(_levs[level]);
1326   if(!curLev)
1327     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeAllGhostZonesAtASpecifiedLevel : presence of a NULL element !");
1328   curLev->synchronizeFineEachOther(_ghost_lev,items);
1329   //2nd step - updates all patches pairs at level \a level not sharing the same father
1330   const std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >& items2(_cross_lev_neighbors[level]);
1331   curLev->synchronizeFineEachOtherExt(_ghost_lev,items2);
1332 }
1333
1334 /*!
1335  * This method updates ghost zones of patches at level \a level whatever their father \b using \b father \b patches \b ONLY (at level \b level - 1).
1336  * This method is useful to propagate to the ghost zone of childhood the modification.
1337  */
1338 void MEDCouplingAMRAttribute::synchronizeAllGhostZonesAtASpecifiedLevelUsingOnlyFather(mcIdType level)
1339 {
1340   mcIdType maxLev(getNumberOfLevels());
1341   if(level<=0 || level>=maxLev)
1342     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeAllGhostZonesAtASpecifiedLevelUsingOnlyFather : the specified level must be in (0,maxLevel) !");
1343   const MEDCouplingGridCollection *fine(_levs[level]),*coarse(_levs[level-1]);
1344   MEDCouplingGridCollection::SynchronizeCoarseToFineOnlyInGhostZone(_ghost_lev,coarse,fine);
1345   //_cross_lev_neighbors is not needed.
1346 }
1347
1348 /*!
1349  * This method allocates all DataArrayDouble instances stored recursively in \a this.
1350  *
1351  * \sa dealloc
1352  */
1353 void MEDCouplingAMRAttribute::alloc()
1354 {
1355   _tlc.resetState();
1356   for(std::vector< MCAuto<MEDCouplingGridCollection> >::iterator it=_levs.begin();it!=_levs.end();it++)
1357     {
1358       MEDCouplingGridCollection *elt(*it);
1359       if(elt)
1360         elt->alloc(_ghost_lev);
1361       else
1362         throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::alloc : internal error !");
1363     }
1364 }
1365
1366 /*!
1367  * This method deallocates all DataArrayDouble instances stored recursively in \a this.
1368  * \sa alloc
1369  */
1370 void MEDCouplingAMRAttribute::dealloc()
1371 {
1372   _tlc.checkConst();
1373   for(std::vector< MCAuto<MEDCouplingGridCollection> >::iterator it=_levs.begin();it!=_levs.end();it++)
1374     {
1375       MEDCouplingGridCollection *elt(*it);
1376       if(elt)
1377         elt->dealloc();
1378       else
1379         throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::dealloc : internal error !");
1380     }
1381 }
1382
1383 bool MEDCouplingAMRAttribute::changeGodFather(MEDCouplingCartesianAMRMesh *gf)
1384 {
1385   bool ret(MEDCouplingDataForGodFather::changeGodFather(gf));
1386   return ret;
1387 }
1388
1389 std::size_t MEDCouplingAMRAttribute::getHeapMemorySizeWithoutChildren() const
1390 {
1391   std::size_t ret(sizeof(MEDCouplingAMRAttribute));
1392   ret+=_levs.capacity()*sizeof(MCAuto<MEDCouplingGridCollection>);
1393   return ret;
1394 }
1395
1396 std::vector<const BigMemoryObject *> MEDCouplingAMRAttribute::getDirectChildrenWithNull() const
1397 {
1398   std::vector<const BigMemoryObject *> ret;
1399   for(std::vector< MCAuto<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
1400     ret.push_back((const MEDCouplingGridCollection *)*it);
1401   return ret;
1402 }
1403
1404 void MEDCouplingAMRAttribute::updateTime() const
1405 {//tony
1406 }
1407
1408 MEDCouplingAMRAttribute::MEDCouplingAMRAttribute(MEDCouplingCartesianAMRMesh *gf, const std::vector< std::pair<std::string,int> >& fieldNames, mcIdType ghostLev):MEDCouplingDataForGodFather(gf),_ghost_lev(ghostLev)
1409 {
1410   //gf non empty, checked by constructor
1411   mcIdType maxLev(gf->getMaxNumberOfLevelsRelativeToThis());
1412   _levs.resize(maxLev);
1413   for(mcIdType i=0;i<maxLev;i++)
1414     {
1415       std::vector<MEDCouplingCartesianAMRPatchGen *> patches(gf->retrieveGridsAt(i));
1416       std::size_t sz(patches.size());
1417       std::vector< MCAuto<MEDCouplingCartesianAMRPatchGen> > patchesSafe(patches.size());
1418       for(std::size_t j=0;j<sz;j++)
1419         patchesSafe[j]=patches[j];
1420       std::vector<const MEDCouplingCartesianAMRMeshGen *> ms(sz);
1421       for(std::size_t j=0;j<sz;j++)
1422         {
1423           ms[j]=patches[j]->getMesh();
1424         }
1425       _levs[i]=MEDCouplingGridCollection::New(ms,fieldNames);
1426     }
1427   // updates cross levels neighbors
1428   _neighbors.resize(_levs.size());
1429   _cross_lev_neighbors.resize(_levs.size());
1430   if(_levs.empty())
1431     throw INTERP_KERNEL::Exception("constructor of MEDCouplingAMRAttribute : not any levels in this !");
1432   std::size_t sz(_levs.size());
1433   for(std::size_t i=1;i<sz;i++)
1434     {
1435       const MEDCouplingGridCollection *fine(_levs[i]);
1436       if(!fine)
1437         throw INTERP_KERNEL::Exception("constructor of MEDCouplingAMRAttribute : presence of a NULL element !");
1438       _neighbors[i]=fine->findNeighbors(_ghost_lev);
1439       if(i!=sz-1)
1440         {
1441           for(std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >::const_iterator it=_neighbors[i].begin();it!=_neighbors[i].end();it++)
1442             {
1443               MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOf(_ghost_lev,(*it).first,(*it).second,_mixed_lev_neighbors);
1444               std::vector< std::vector < std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > > neighs2(MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOfSameLev(_ghost_lev,(*it).first,(*it).second));
1445               std::size_t fullLev(i+neighs2.size());
1446               if(fullLev>=sz)
1447                 throw INTERP_KERNEL::Exception("constructor of MEDCouplingAMRAttribute : internal error ! something is wrong in computation of cross level neighbors !");
1448               std::size_t ii(i+1);
1449               for(std::vector< std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > >::const_iterator it0=neighs2.begin();it0!=neighs2.end();it0++,ii++)
1450                 _cross_lev_neighbors[ii].insert(_cross_lev_neighbors[ii].end(),(*it0).begin(),(*it0).end());
1451             }
1452         }
1453     }
1454 }
1455
1456 MEDCouplingAMRAttribute::MEDCouplingAMRAttribute(const MEDCouplingAMRAttribute& other, bool deepCpyGF):MEDCouplingDataForGodFather(other,deepCpyGF),_ghost_lev(other._ghost_lev),_levs(other._levs.size()),_neighbors(other._neighbors),_mixed_lev_neighbors(other._mixed_lev_neighbors),_cross_lev_neighbors(other._cross_lev_neighbors)
1457 {
1458   std::size_t sz(other._levs.size());
1459   for(std::size_t i=0;i<sz;i++)
1460     {
1461       const MEDCouplingGridCollection *elt(other._levs[i]);
1462       if(elt)
1463         {
1464           _levs[i]=other._levs[i]->deepCopy(_gf,other._gf);
1465         }
1466     }
1467   //_cross_lev_neighbors(other._cross_lev_neighbors)
1468   sz=other._neighbors.size();
1469   for(std::size_t i=0;i<sz;i++)
1470     {
1471       const std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >& neigh2(other._neighbors[i]);
1472       std::size_t sz2(neigh2.size());
1473       std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >& neigh3(_neighbors[i]);
1474       for(std::size_t j=0;j<sz2;j++)
1475         {
1476           const MEDCouplingCartesianAMRPatch *p1(neigh2[j].first),*p2(neigh2[j].second);
1477           std::vector<mcIdType> pp1(p1->getMesh()->getPositionRelativeTo(other._gf)),pp2(p2->getMesh()->getPositionRelativeTo(other._gf));
1478           neigh3[j].first=_gf->getPatchAtPosition(pp1);
1479           neigh3[j].second=_gf->getPatchAtPosition(pp2);
1480         }
1481     }
1482   //
1483   sz=other._mixed_lev_neighbors.size();
1484   for(std::size_t i=0;i<sz;i++)
1485     {
1486       const MEDCouplingCartesianAMRPatch *p1(other._mixed_lev_neighbors[i].first),*p2(other._mixed_lev_neighbors[i].second);
1487       std::vector<mcIdType> pp1(p1->getMesh()->getPositionRelativeTo(other._gf)),pp2(p2->getMesh()->getPositionRelativeTo(other._gf));
1488       _mixed_lev_neighbors[i].first=_gf->getPatchAtPosition(pp1);
1489       _mixed_lev_neighbors[i].second=_gf->getPatchAtPosition(pp2);
1490     }
1491   //
1492   sz=other._cross_lev_neighbors.size();
1493   for(std::size_t i=0;i<sz;i++)
1494     {
1495       const std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >& neigh2(other._cross_lev_neighbors[i]);
1496       std::size_t sz2(neigh2.size());
1497       std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >& neigh3(_cross_lev_neighbors[i]);
1498       for(std::size_t j=0;j<sz2;j++)
1499         {
1500           const MEDCouplingCartesianAMRPatch *p1(neigh2[j].first),*p2(neigh2[j].second);
1501           std::vector<mcIdType> pp1(p1->getMesh()->getPositionRelativeTo(other._gf)),pp2(p2->getMesh()->getPositionRelativeTo(other._gf));
1502           neigh3[j].first=_gf->getPatchAtPosition(pp1);
1503           neigh3[j].second=_gf->getPatchAtPosition(pp2);
1504         }
1505     }
1506 }
1507
1508 const DataArrayDoubleCollection& MEDCouplingAMRAttribute::findCollectionAttachedTo(const MEDCouplingCartesianAMRMeshGen *m) const
1509 {
1510   for(std::vector< MCAuto<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
1511     {
1512       const MEDCouplingGridCollection *elt(*it);
1513       if(elt)
1514         {
1515           mcIdType tmp(-1);
1516           if(elt->presenceOf(m,tmp))
1517             {
1518               return elt->getFieldsAt(tmp);
1519             }
1520         }
1521     }
1522   throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::findCollectionAttachedTo : unable to find such part of mesh in this !");
1523 }
1524
1525 void MEDCouplingAMRAttribute::synchronizeFineToCoarseByOneLevel(mcIdType level)
1526 {
1527   mcIdType nbl(getNumberOfLevels());
1528   if(level<=0 || level>=nbl)
1529     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineToCoarseByOneLevel : the input level must be in ]0,nb_of_levels[ !");
1530   const MEDCouplingGridCollection *fine(_levs[level]),*coarse(_levs[level-1]);
1531   MEDCouplingGridCollection::SynchronizeFineToCoarse(_ghost_lev,fine,coarse);
1532 }
1533
1534 void MEDCouplingAMRAttribute::synchronizeCoarseToFineByOneLevel(mcIdType level)
1535 {
1536   mcIdType nbl(getNumberOfLevels());
1537   if(level<0 || level>=nbl-1)
1538     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineToCoarseByOneLevel : the input level must be in [0,nb_of_levels[ !");
1539   const MEDCouplingGridCollection *fine(_levs[level+1]),*coarse(_levs[level]);
1540   MEDCouplingGridCollection::SynchronizeCoarseToFine(_ghost_lev,coarse,fine);
1541 }