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