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