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