Salome HOME
Some debugs and improvements. Tests coming soon !
[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
28 using namespace ParaMEDMEM;
29
30 DataArrayDoubleCollection *DataArrayDoubleCollection::New(const std::vector< std::pair<std::string,int> >& fieldNames)
31 {
32   return new DataArrayDoubleCollection(fieldNames);
33 }
34
35 DataArrayDoubleCollection *DataArrayDoubleCollection::deepCpy() const
36 {
37   return new DataArrayDoubleCollection(*this);
38 }
39
40 void DataArrayDoubleCollection::allocTuples(int nbOfTuples)
41 {
42   std::size_t sz(_arrs.size());
43   for(std::size_t i=0;i<sz;i++)
44     _arrs[i].first->reAlloc(nbOfTuples);
45 }
46
47 void DataArrayDoubleCollection::dellocTuples()
48 {
49   std::size_t sz(_arrs.size());
50   for(std::size_t i=0;i<sz;i++)
51     _arrs[i].first->reAlloc(0);
52 }
53
54 void DataArrayDoubleCollection::spillInfoOnComponents(const std::vector< std::vector<std::string> >& compNames)
55 {
56   std::size_t sz(_arrs.size());
57   if(sz!=compNames.size())
58     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::spillInfoOnComponents : first size of compNames has to be equal to the number of fields defined !");
59   for(std::size_t i=0;i<sz;i++)
60     {
61       const std::vector<std::string>& names(compNames[i]);
62       _arrs[i].first->setInfoOnComponents(names);
63     }
64 }
65
66 void DataArrayDoubleCollection::spillNatures(const std::vector<NatureOfField>& nfs)
67 {
68   std::size_t sz(_arrs.size());
69   if(sz!=nfs.size())
70     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::spillNatures : first size of vector of NatureOfField has to be equal to the number of fields defined !");
71   for(std::size_t i=0;i<sz;i++)
72     {
73       CheckValidNature(nfs[i]);
74       _arrs[i].second=nfs[i];
75     }
76 }
77
78 std::vector<DataArrayDouble *> DataArrayDoubleCollection::retrieveFields() const
79 {
80   std::size_t sz(_arrs.size());
81   std::vector<DataArrayDouble *> ret(sz);
82   for(std::size_t i=0;i<sz;i++)
83     {
84       const DataArrayDouble *tmp(_arrs[i].first);
85       ret[i]=const_cast<DataArrayDouble *>(tmp);
86       if(ret[i])
87         ret[i]->incrRef();
88     }
89   return ret;
90 }
91
92 const DataArrayDouble *DataArrayDoubleCollection::getFieldWithName(const std::string& name) const
93 {
94   std::vector<std::string> vec;
95   for(std::vector< std::pair< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble>, NatureOfField > >::const_iterator it=_arrs.begin();it!=_arrs.end();it++)
96     {
97       const DataArrayDouble *obj((*it).first);
98       if(obj)
99         {
100           if(obj->getName()==name)
101             return obj;
102           else
103             vec.push_back(obj->getName());
104         }
105     }
106   std::ostringstream oss; oss << "DataArrayDoubleCollection::getFieldWithName : fieldName \"" << name << "\" does not exist in this ! Possibilities are :";
107   std::copy(vec.begin(),vec.end(),std::ostream_iterator<std::string>(oss," "));
108   throw INTERP_KERNEL::Exception(oss.str().c_str());
109 }
110
111 void DataArrayDoubleCollection::SynchronizeFineToCoarse(int ghostLev, const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh, int patchId, const DataArrayDoubleCollection *fine, DataArrayDoubleCollection *coarse)
112 {
113   if(!fine || !coarse)
114     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeFineToCoarse : the input DataArrayDouble collections must be non NULL !");
115   std::size_t sz(coarse->_arrs.size());
116   if(fine->_arrs.size()!=sz)
117     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeFineToCoarse : the input DataArrayDouble collection must have the same size !");
118   for(std::size_t i=0;i<sz;i++)
119     {
120       CheckSameNatures(fine->_arrs[i].second,coarse->_arrs[i].second);
121       fatherOfFineMesh->fillCellFieldComingFromPatchGhost(patchId,fine->_arrs[i].first,coarse->_arrs[i].first,ghostLev,IsConservativeNature(coarse->_arrs[i].second));
122     }
123 }
124
125 void DataArrayDoubleCollection::SynchronizeCoarseToFine(int ghostLev, const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh, int patchId, const DataArrayDoubleCollection *coarse, DataArrayDoubleCollection *fine)
126 {
127   if(!fine || !coarse)
128     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeCoarseToFine : the input DataArrayDouble collections must be non NULL !");
129   std::size_t sz(coarse->_arrs.size());
130   if(fine->_arrs.size()!=sz)
131     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeCoarseToFine : the input DataArrayDouble collection must have the same size !");
132   for(std::size_t i=0;i<sz;i++)
133     {
134       CheckSameNatures(fine->_arrs[i].second,coarse->_arrs[i].second);
135       fatherOfFineMesh->fillCellFieldOnPatchGhost(patchId,coarse->_arrs[i].first,fine->_arrs[i].first,ghostLev,IsConservativeNature(coarse->_arrs[i].second));
136     }
137 }
138
139 void DataArrayDoubleCollection::SynchronizeFineEachOther(int patchId, int ghostLev, const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh, const std::vector<const MEDCouplingCartesianAMRMeshGen *>& children, const std::vector<DataArrayDoubleCollection *>& fieldsOnFine)
140 {
141   if(!fatherOfFineMesh)
142     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeFineEachOther : father is NULL !");
143   std::size_t sz(children.size());
144   if(fieldsOnFine.size()!=sz)
145     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeFineEachOther : sizes of vectors mismatch !");
146   if(sz<=1)
147     return ;
148   std::size_t nbOfCall(fieldsOnFine[0]->_arrs.size());
149   for(std::size_t i=0;i<sz;i++)
150     if(fatherOfFineMesh->getPatchIdFromChildMesh(children[i])!=(int)i)
151       throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeFineEachOther : internal error !");
152   for(std::size_t i=1;i<sz;i++)
153     if(nbOfCall!=fieldsOnFine[i]->_arrs.size())
154       throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeFineEachOther : the collection of DataArrayDouble must have all the same size !");
155   for(std::size_t i=0;i<nbOfCall;i++)
156     {
157       std::vector<const DataArrayDouble *> arrs(sz);
158       for(std::size_t j=0;j<sz;j++)
159         arrs[j]=fieldsOnFine[j]->_arrs[i].first;
160       fatherOfFineMesh->fillCellFieldOnPatchOnlyGhostAdv(patchId,ghostLev,arrs);
161     }
162 }
163
164 /*!
165  * 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).
166  */
167 void DataArrayDoubleCollection::SynchronizeGhostZoneOfOneUsingTwo(int ghostLev, const MEDCouplingCartesianAMRPatch *p1, const DataArrayDoubleCollection *p1dac, const MEDCouplingCartesianAMRPatch *p2, const DataArrayDoubleCollection *p2dac)
168 {
169   if(!p1 || !p1dac || !p2 || !p2dac)
170     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeGhostZoneOfOneUsingTwo : input pointer must be not NULL !");
171   std::size_t sz(p1dac->_arrs.size());
172   if(p2dac->_arrs.size()!=sz)
173     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeGhostZoneOfOneUsingTwo : size of DataArrayDouble Collection must be the same !");
174   for(std::size_t i=0;i<sz;i++)
175     {
176       const DataArrayDouble *zeArrWhichGhostsWillBeUpdated(p1dac->_arrs[i].first);
177       MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoMixedLev(ghostLev,p1,p2,const_cast<DataArrayDouble *>(zeArrWhichGhostsWillBeUpdated),p2dac->_arrs[i].first);
178     }
179 }
180
181 void DataArrayDoubleCollection::SynchronizeCoarseToFineOnlyInGhostZone(int ghostLev, const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh, int patchId, const DataArrayDoubleCollection *coarse, DataArrayDoubleCollection *fine)
182 {
183   if(!fine || !coarse)
184     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeCoarseToFineOnlyInGhostZone : the input DataArrayDouble collections must be non NULL !");
185   std::size_t sz(coarse->_arrs.size());
186   if(fine->_arrs.size()!=sz)
187     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeCoarseToFineOnlyInGhostZone : the input DataArrayDouble collection must have the same size !");
188   for(std::size_t i=0;i<sz;i++)
189     fatherOfFineMesh->fillCellFieldOnPatchOnlyOnGhostZone(patchId,coarse->_arrs[i].first,fine->_arrs[i].first,ghostLev);
190 }
191
192 void DataArrayDoubleCollection::synchronizeMyGhostZoneUsing(int ghostLev, const DataArrayDoubleCollection& other, const MEDCouplingCartesianAMRPatch *thisp, const MEDCouplingCartesianAMRPatch *otherp, const MEDCouplingCartesianAMRMeshGen *father) const
193 {
194   DataArrayDoubleCollection *thisNC(const_cast<DataArrayDoubleCollection *>(this));
195   std::size_t sz(_arrs.size());
196   if(other._arrs.size()!=sz)
197     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::synchronizeMyGhostZoneUsing : sizes of collections must match !");
198   for(std::size_t i=0;i<sz;i++)
199     father->fillCellFieldOnPatchOnlyOnGhostZoneWith(ghostLev,thisp,otherp,thisNC->_arrs[i].first,other._arrs[i].first);
200 }
201
202 void DataArrayDoubleCollection::synchronizeMyGhostZoneUsingExt(int ghostLev, const DataArrayDoubleCollection& other, const MEDCouplingCartesianAMRPatch *thisp, const MEDCouplingCartesianAMRPatch *otherp) const
203 {
204   DataArrayDoubleCollection *thisNC(const_cast<DataArrayDoubleCollection *>(this));
205   std::size_t sz(_arrs.size());
206   if(other._arrs.size()!=sz)
207     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::synchronizeMyGhostZoneUsingExt : sizes of collections must match !");
208   for(std::size_t i=0;i<sz;i++)
209     MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoExt(ghostLev,thisp,otherp,thisNC->_arrs[i].first,other._arrs[i].first);
210 }
211
212 DataArrayDoubleCollection::DataArrayDoubleCollection(const std::vector< std::pair<std::string,int> >& fieldNames):_arrs(fieldNames.size())
213 {
214   std::size_t sz(fieldNames.size());
215   std::vector<std::string> names(sz);
216   for(std::size_t i=0;i<sz;i++)
217     {
218       const std::pair<std::string,int>& info(fieldNames[i]);
219       _arrs[i].first=DataArrayDouble::New();
220       _arrs[i].first->alloc(0,info.second);
221       _arrs[i].first->setName(info.first);
222       names[i]=info.second;
223       _arrs[i].second=ConservativeVolumic;
224     }
225   CheckDiscriminantNames(names);
226 }
227
228 DataArrayDoubleCollection::DataArrayDoubleCollection(const DataArrayDoubleCollection& other):RefCountObject(other),_arrs(other._arrs.size())
229 {
230   std::size_t sz(other._arrs.size());
231   for(std::size_t i=0;i<sz;i++)
232     {
233       _arrs[i].second=other._arrs[i].second;
234       const DataArrayDouble *da(other._arrs[i].first);
235       if(da)
236         _arrs[i].first=da->deepCpy();
237     }
238 }
239
240 std::size_t DataArrayDoubleCollection::getHeapMemorySizeWithoutChildren() const
241 {
242   std::size_t ret(sizeof(DataArrayDoubleCollection));
243   ret+=_arrs.capacity()*sizeof(MEDCouplingAutoRefCountObjectPtr<DataArrayDouble>);
244   return ret;
245 }
246
247 std::vector<const BigMemoryObject *> DataArrayDoubleCollection::getDirectChildren() const
248 {
249   std::vector<const BigMemoryObject *> ret;
250   for(std::vector< std::pair< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble>, NatureOfField > >::const_iterator it=_arrs.begin();it!=_arrs.end();it++)
251     {
252       const DataArrayDouble *pt((*it).first);
253       if(pt)
254         ret.push_back(pt);
255     }
256   return ret;
257 }
258
259 void DataArrayDoubleCollection::updateTime() const
260 {
261   for(std::vector< std::pair< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble>, NatureOfField > >::const_iterator it=_arrs.begin();it!=_arrs.end();it++)
262     {
263       const DataArrayDouble *pt((*it).first);
264       if(pt)
265         updateTimeWith(*pt);
266     }
267 }
268
269 void DataArrayDoubleCollection::CheckDiscriminantNames(const std::vector<std::string>& names)
270 {
271   std::set<std::string> s(names.begin(),names.end());
272   if(s.size()!=names.size())
273     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::CheckDiscriminantNames : The names of fields must be different each other ! It is not the case !");
274 }
275
276 bool DataArrayDoubleCollection::IsConservativeNature(NatureOfField n)
277 {
278   CheckValidNature(n);
279   return n==RevIntegral || n==IntegralGlobConstraint;
280 }
281
282 void DataArrayDoubleCollection::CheckSameNatures(NatureOfField n1, NatureOfField n2)
283 {
284   CheckValidNature(n1);
285   CheckValidNature(n2);
286   if(n1!=n2)
287     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::CheckSameNatures : natures are not the same !");
288 }
289
290 void DataArrayDoubleCollection::CheckValidNature(NatureOfField n)
291 {
292   if(n!=ConservativeVolumic && n!=Integral && n!=IntegralGlobConstraint && n!=RevIntegral)
293     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::CheckValidNature : unrecognized nature !");
294 }
295
296 MEDCouplingGridCollection *MEDCouplingGridCollection::New(const std::vector<const MEDCouplingCartesianAMRMeshGen *>& ms, const std::vector< std::pair<std::string,int> >& fieldNames)
297 {
298   return new MEDCouplingGridCollection(ms,fieldNames);
299 }
300
301 MEDCouplingGridCollection *MEDCouplingGridCollection::deepCpy(const MEDCouplingCartesianAMRMeshGen *newGf, const MEDCouplingCartesianAMRMeshGen *oldGf) const
302 {
303   return new MEDCouplingGridCollection(*this,newGf,oldGf);
304 }
305
306 void MEDCouplingGridCollection::alloc(int ghostLev)
307 {
308   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
309     {
310       int nbTuples((*it).first->getNumberOfCellsAtCurrentLevelGhost(ghostLev));
311       DataArrayDoubleCollection *dadc((*it).second);
312       if(dadc)
313         dadc->allocTuples(nbTuples);
314       else
315         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::alloc : internal error !");
316     }
317 }
318
319 void MEDCouplingGridCollection::dealloc()
320 {
321   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
322     {
323       DataArrayDoubleCollection *dadc((*it).second);
324       if(dadc)
325         dadc->dellocTuples();
326       else
327         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::dealloc : internal error !");
328     }
329 }
330
331 void MEDCouplingGridCollection::spillInfoOnComponents(const std::vector< std::vector<std::string> >& compNames)
332 {
333   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
334     (*it).second->spillInfoOnComponents(compNames);
335 }
336
337 void MEDCouplingGridCollection::spillNatures(const std::vector<NatureOfField>& nfs)
338 {
339   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
340     (*it).second->spillNatures(nfs);
341 }
342
343 bool MEDCouplingGridCollection::presenceOf(const MEDCouplingCartesianAMRMeshGen *m, int& pos) const
344 {
345   int ret(0);
346   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++,ret++)
347     {
348       if((*it).first==m)
349         {
350           pos=ret;
351           return true;
352         }
353     }
354   return false;
355 }
356
357 const DataArrayDoubleCollection& MEDCouplingGridCollection::getFieldsAt(int pos) const
358 {
359   if(pos<0 || pos>(int)_map_of_dadc.size())
360     throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::getFieldsAt : invalid pos given in input ! Must be in [0,size) !");
361   return *_map_of_dadc[pos].second;
362 }
363
364 void MEDCouplingGridCollection::SynchronizeFineToCoarse(int ghostLev, const MEDCouplingGridCollection *fine, const MEDCouplingGridCollection *coarse)
365 {
366   if(!fine || !coarse)
367     throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeFineToCoarse : one or more input pointer is NULL !");
368   const std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >& mf(fine->_map_of_dadc);
369   const std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >& mc(coarse->_map_of_dadc);
370   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=mf.begin();it!=mf.end();it++)
371     {
372       const MEDCouplingCartesianAMRMeshGen *fineMesh((*it).first);
373       const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh(fineMesh->getFather());
374       bool found(false);
375       for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it0=mc.begin();it0!=mc.end() && !found;it0++)
376         {
377           if((*it0).first==fatherOfFineMesh)
378             {
379               found=true;
380               int patchId(fatherOfFineMesh->getPatchIdFromChildMesh(fineMesh));
381               const DataArrayDoubleCollection *coarseDaCol((*it0).second);
382               DataArrayDoubleCollection *coarseModified(const_cast<DataArrayDoubleCollection *>(coarseDaCol));//coarse values in DataArrayDouble will be altered
383               DataArrayDoubleCollection::SynchronizeFineToCoarse(ghostLev,fatherOfFineMesh,patchId,(*it).second,coarseModified);
384             }
385         }
386       if(!found)
387         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeFineToCoarse : a fine mesh is orphan regarding given coarse meshes !");
388     }
389 }
390
391 void MEDCouplingGridCollection::SynchronizeCoarseToFine(int ghostLev, const MEDCouplingGridCollection *coarse, const MEDCouplingGridCollection *fine)
392 {
393   if(!fine || !coarse)
394     throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeCoarseToFine : one or more input pointer is NULL !");
395   const std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >& mf(fine->_map_of_dadc);
396   const std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >& mc(coarse->_map_of_dadc);
397   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=mf.begin();it!=mf.end();it++)
398     {
399       const MEDCouplingCartesianAMRMeshGen *fineMesh((*it).first);
400       const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh(fineMesh->getFather());
401       bool found(false);
402       for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it0=mc.begin();it0!=mc.end() && !found;it0++)
403         {
404           if((*it0).first==fatherOfFineMesh)
405             {
406               found=true;
407               int patchId(fatherOfFineMesh->getPatchIdFromChildMesh(fineMesh));
408               const DataArrayDoubleCollection *fineDaCol((*it).second);
409               DataArrayDoubleCollection *fineModified(const_cast<DataArrayDoubleCollection *>(fineDaCol));//fine values in DataArrayDouble will be altered
410               DataArrayDoubleCollection::SynchronizeCoarseToFine(ghostLev,fatherOfFineMesh,patchId,(*it0).second,fineModified);
411             }
412         }
413       if(!found)
414         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeCoarseToFine : a fine mesh is orphan regarding given coarse meshes !");
415     }
416 }
417
418 /*!
419  * All the pairs in \a ps must share the same father. If not call synchronizeFineEachOtherExt instead.
420  *
421  * \sa synchronizeFineEachOtherExt
422  */
423 void MEDCouplingGridCollection::synchronizeFineEachOther(int ghostLev, const std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >& ps) const
424 {
425   for(std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >::const_iterator it=ps.begin();it!=ps.end();it++)
426     {
427       int p1,p2;
428       if(!presenceOf((*it).first->getMesh(),p1))
429         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::synchronizeFineEachOther : internal error #1 !");
430       if(!presenceOf((*it).second->getMesh(),p2))
431         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::synchronizeFineEachOther : internal error #2 !");
432       const DataArrayDoubleCollection& col1(getFieldsAt(p1));
433       const DataArrayDoubleCollection& col2(getFieldsAt(p2));
434       col1.synchronizeMyGhostZoneUsing(ghostLev,col2,(*it).first,(*it).second,(*it).first->getMesh()->getFather());
435     }
436 }
437
438 /*!
439  * This method is a generalization of synchronizeFineEachOther because elements in pairs are \b not sharing the same father but are neighbors nevertheless.
440  *
441  * \sa synchronizeFineEachOther
442  */
443 void MEDCouplingGridCollection::synchronizeFineEachOtherExt(int ghostLev, const std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >& ps) const
444 {
445   for(std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >::const_iterator it=ps.begin();it!=ps.end();it++)
446     {
447       int p1,p2;
448       if(!presenceOf((*it).first->getMesh(),p1))
449         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::synchronizeFineEachOtherExt : internal error #1 !");
450       if(!presenceOf((*it).second->getMesh(),p2))
451         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::synchronizeFineEachOtherExt : internal error #2 !");
452       const DataArrayDoubleCollection& col1(getFieldsAt(p1));
453       const DataArrayDoubleCollection& col2(getFieldsAt(p2));
454       col1.synchronizeMyGhostZoneUsingExt(ghostLev,col2,(*it).first,(*it).second);
455     }
456 }
457
458 /*!
459  * The pairs returned share the same direct father. The number of returned elements must be even.
460  */
461 std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > MEDCouplingGridCollection::findNeighbors(int ghostLev) const
462 {
463   std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > ret;
464   std::map<const MEDCouplingCartesianAMRMeshGen *,std::vector< const MEDCouplingCartesianAMRMeshGen * > > m;
465   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
466     {
467       const MEDCouplingCartesianAMRMeshGen *fineMesh((*it).first);
468       const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh(fineMesh->getFather());
469       m[fatherOfFineMesh].push_back(fineMesh);
470     }
471   for(std::map<const MEDCouplingCartesianAMRMeshGen *,std::vector< const MEDCouplingCartesianAMRMeshGen * > >::const_iterator it0=m.begin();it0!=m.end();it0++)
472     {
473       for(std::vector<const MEDCouplingCartesianAMRMeshGen *>::const_iterator it1=(*it0).second.begin();it1!=(*it0).second.end();it1++)
474         {
475           int patchId((*it0).first->getPatchIdFromChildMesh(*it1));
476           std::vector<int> neighs((*it0).first->getPatchIdsInTheNeighborhoodOf(patchId,ghostLev));
477           const MEDCouplingCartesianAMRPatch *pRef((*it0).first->getPatch(patchId));
478           for(std::vector<int>::const_iterator it2=neighs.begin();it2!=neighs.end();it2++)
479             {
480               const MEDCouplingCartesianAMRPatch *pLoc((*it0).first->getPatch(*it2));
481               ret.push_back(std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *>(pRef,pLoc));
482             }
483         }
484     }
485   if(ret.size()%2!=0)
486     throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::findNeighbors : something is wrong ! The number of neighbor pairs must be %2 ==0 !");
487   return ret;
488 }
489
490 void MEDCouplingGridCollection::SynchronizeCoarseToFineOnlyInGhostZone(int ghostLev, const MEDCouplingGridCollection *coarse, const MEDCouplingGridCollection *fine)
491 {
492   if(!fine || !coarse)
493     throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeCoarseToFineOnlyInGhostZone : one or more input pointer is NULL !");
494   const std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >& mf(fine->_map_of_dadc);
495   const std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >& mc(coarse->_map_of_dadc);
496   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=mf.begin();it!=mf.end();it++)
497     {
498       const MEDCouplingCartesianAMRMeshGen *fineMesh((*it).first);
499       const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh(fineMesh->getFather());
500       bool found(false);
501       for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it0=mc.begin();it0!=mc.end() && !found;it0++)
502         {
503           if((*it0).first==fatherOfFineMesh)
504             {
505               found=true;
506               int patchId(fatherOfFineMesh->getPatchIdFromChildMesh(fineMesh));
507               const DataArrayDoubleCollection *fineDaCol((*it).second);
508               DataArrayDoubleCollection *fineModified(const_cast<DataArrayDoubleCollection *>(fineDaCol));//fine values in DataArrayDouble will be altered
509               DataArrayDoubleCollection::SynchronizeCoarseToFineOnlyInGhostZone(ghostLev,fatherOfFineMesh,patchId,(*it0).second,fineModified);
510             }
511         }
512       if(!found)
513         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeCoarseToFineOnlyInGhostZone : a fine mesh is orphan regarding given coarse meshes !");
514     }
515 }
516
517 void MEDCouplingGridCollection::fillIfInTheProgenyOf(const std::string& fieldName, const MEDCouplingCartesianAMRMeshGen *head, std::vector<const DataArrayDouble *>& recurseArrs) const
518 {
519   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
520     {
521       const MEDCouplingCartesianAMRMeshGen *a((*it).first);
522       if(head==a || head->isObjectInTheProgeny(a))
523         {
524           const DataArrayDoubleCollection *gc((*it).second);
525           recurseArrs.push_back(gc->getFieldWithName(fieldName));
526         }
527     }
528 }
529
530 MEDCouplingGridCollection::MEDCouplingGridCollection(const std::vector<const MEDCouplingCartesianAMRMeshGen *>& ms, const std::vector< std::pair<std::string,int> >& fieldNames):_map_of_dadc(ms.size())
531 {
532   std::size_t sz(ms.size());
533   for(std::size_t i=0;i<sz;i++)
534     {
535       if(!ms[i])
536         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection constructor : presence of NULL MEDCouplingCartesianAMRMeshGen instance !");
537       _map_of_dadc[i].first=ms[i];
538       _map_of_dadc[i].second=DataArrayDoubleCollection::New(fieldNames);
539     }
540 }
541
542 MEDCouplingGridCollection::MEDCouplingGridCollection(const MEDCouplingGridCollection& other, const MEDCouplingCartesianAMRMeshGen *newGf, const MEDCouplingCartesianAMRMeshGen *oldGf):RefCountObject(other),_map_of_dadc(other._map_of_dadc.size())
543 {
544   std::size_t sz(other._map_of_dadc.size());
545   for(std::size_t i=0;i<sz;i++)
546     {
547       std::vector<int> pos(other._map_of_dadc[i].first->getPositionRelativeTo(oldGf));
548       _map_of_dadc[i].first=newGf->getMeshAtPosition(pos);
549       const DataArrayDoubleCollection *dac(other._map_of_dadc[i].second);
550       if(dac)
551         _map_of_dadc[i].second=dac->deepCpy();
552     }
553 }
554
555 std::size_t MEDCouplingGridCollection::getHeapMemorySizeWithoutChildren() const
556 {
557   std::size_t ret(sizeof(MEDCouplingGridCollection));
558   ret+=_map_of_dadc.capacity()*sizeof(std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> >);
559   return ret;
560 }
561
562 std::vector<const BigMemoryObject *> MEDCouplingGridCollection::getDirectChildren() const
563 {
564   std::vector<const BigMemoryObject *> ret;
565   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
566     {
567       const DataArrayDoubleCollection *col((*it).second);
568       if(col)
569         ret.push_back(col);
570     }
571   return ret;
572 }
573
574 void MEDCouplingGridCollection::updateTime() const
575 {
576   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
577     {
578       const MEDCouplingCartesianAMRMeshGen *a((*it).first);
579       if(a)
580         updateTimeWith(*a);
581       const DataArrayDoubleCollection *b((*it).second);
582       if(b)
583         updateTimeWith(*b);
584     }
585 }
586
587 MEDCouplingCartesianAMRMesh *MEDCouplingDataForGodFather::getMyGodFather()
588 {
589   return _gf;
590 }
591
592 MEDCouplingDataForGodFather::MEDCouplingDataForGodFather(MEDCouplingCartesianAMRMesh *gf):_gf(gf),_tlc(gf)
593 {
594   if(!gf)
595     throw INTERP_KERNEL::Exception("MEDCouplingDataForGodFather constructor : A data has to be attached to a AMR Mesh instance !");
596   gf->incrRef();
597 }
598
599 void MEDCouplingDataForGodFather::checkGodFatherFrozen() const
600 {
601   _tlc.checkConst();
602 }
603
604 bool MEDCouplingDataForGodFather::changeGodFather(MEDCouplingCartesianAMRMesh *gf)
605 {
606   bool ret(_tlc.keepTrackOfNewTL(gf));
607   if(ret)
608     {
609       _gf=gf;
610       if(gf)
611         gf->incrRef();
612     }
613   return ret;
614 }
615
616 MEDCouplingDataForGodFather::MEDCouplingDataForGodFather(const MEDCouplingDataForGodFather& other, bool deepCpyGF):RefCountObject(other),_gf(other._gf),_tlc(other._gf)
617 {
618   other._tlc.checkConst();
619   if(deepCpyGF)
620     {
621       const MEDCouplingCartesianAMRMesh *gf(other._gf);
622       if(gf)
623         _gf=gf->deepCpy(0);
624       _tlc.keepTrackOfNewTL(_gf);
625     }
626 }
627
628 /*!
629  * 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.
630  */
631 MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::New(MEDCouplingCartesianAMRMesh *gf, const std::vector< std::pair<std::string,int> >& fieldNames, int ghostLev)
632 {
633   return new MEDCouplingAMRAttribute(gf,fieldNames,ghostLev);
634 }
635
636 MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::New(MEDCouplingCartesianAMRMesh *gf, const std::vector< std::pair<std::string, std::vector<std::string> > >& fieldNames, int ghostLev)
637 {
638   std::size_t sz(fieldNames.size());
639   std::vector< std::pair<std::string,int> > fieldNames2(sz);
640   std::vector< std::vector<std::string> > compNames(sz);
641   for(std::size_t i=0;i<sz;i++)
642     {
643       fieldNames2[i].first=fieldNames[i].first;
644       fieldNames2[i].second=(int)fieldNames[i].second.size();
645       compNames[i]=fieldNames[i].second;
646     }
647   MEDCouplingAutoRefCountObjectPtr<MEDCouplingAMRAttribute> ret(New(gf,fieldNames2,ghostLev));
648   ret->spillInfoOnComponents(compNames);
649   return ret.retn();
650 }
651
652 /*!
653  * Assign the info on components for all DataArrayDouble instance recursively stored in \a this.
654  * 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.
655  * The second dim of \a compNames represent the component names component per component corresponding to the field. The size of this 2nd dimension has
656  * to perfectly fit with those specified in MEDCouplingAMRAttribute::New.
657  */
658 void MEDCouplingAMRAttribute::spillInfoOnComponents(const std::vector< std::vector<std::string> >& compNames)
659 {
660   _tlc.checkConst();
661   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::iterator it=_levs.begin();it!=_levs.end();it++)
662     (*it)->spillInfoOnComponents(compNames);
663 }
664
665 /*!
666  * Assign nature for each fields in \a this.
667  * \param [in] nfs
668  */
669 void MEDCouplingAMRAttribute::spillNatures(const std::vector<NatureOfField>& nfs)
670 {
671   _tlc.checkConst();
672   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::iterator it=_levs.begin();it!=_levs.end();it++)
673     (*it)->spillNatures(nfs);
674 }
675
676 MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::deepCpy() const
677 {
678   return new MEDCouplingAMRAttribute(*this,true);
679 }
680
681 MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::deepCpyWithoutGodFather() const
682 {
683   return new MEDCouplingAMRAttribute(*this,false);
684 }
685
686 /*!
687  * 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).
688  *
689  */
690 int MEDCouplingAMRAttribute::getNumberOfLevels() const
691 {
692   checkGodFatherFrozen();
693   return (int)_levs.size();
694 }
695
696 /*!
697  * This method returns all DataArrayDouble instances lying on the specified mesh \a mesh.
698  * If \a mesh is not part of the progeny of god father object given at construction of \a this an exception will be thrown.
699  *
700  * \return std::vector<DataArrayDouble *> - DataArrayDouble instances to be deallocated by the caller (using decrRef).
701  * \sa retrieveFieldOn
702  */
703 std::vector<DataArrayDouble *> MEDCouplingAMRAttribute::retrieveFieldsOn(MEDCouplingCartesianAMRMeshGen *mesh) const
704 {
705   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
706     {
707       int tmp(-1);
708       if((*it)->presenceOf(mesh,tmp))
709         {
710           const DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp));
711           return ddc.retrieveFields();
712         }
713     }
714   throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::retrieveFieldsOn : the mesh specified is not in the progeny of this !");
715 }
716
717 /*!
718  * \sa retrieveFieldsOn
719  */
720 const DataArrayDouble *MEDCouplingAMRAttribute::getFieldOn(MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) const
721 {
722   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
723     {
724       int tmp(-1);
725       if((*it)->presenceOf(mesh,tmp))
726         {
727           const DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp));
728           return ddc.getFieldWithName(fieldName);
729         }
730     }
731   throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::retrieveFieldOn : the mesh specified is not in the progeny of this !");
732 }
733
734 /*!
735  * This method returns a field on an unstructured mesh the most refined as possible without overlap.
736  * Ghost part are not visible here.
737  *
738  * \return MEDCouplingFieldDouble * - a field on cells that the caller has to deal with (deallocate it).
739  */
740 MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnRecurseWithoutOverlapWithoutGhost(MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) const
741 {
742   std::vector<const DataArrayDouble *> recurseArrs;
743   std::size_t lev(0);
744   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++,lev++)
745     {
746       int tmp(-1);
747       if((*it)->presenceOf(mesh,tmp))
748         {
749           const DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp));
750           recurseArrs.push_back(ddc.getFieldWithName(fieldName));
751           break;
752         }
753     }
754   lev++;
755   for(std::size_t i=lev;i<_levs.size();i++)
756     {
757       const MEDCouplingGridCollection *gc(_levs[i]);
758       gc->fillIfInTheProgenyOf(fieldName,mesh,recurseArrs);
759     }
760   return mesh->buildCellFieldOnRecurseWithoutOverlapWithoutGhost(_ghost_lev,recurseArrs);
761 }
762
763 /*!
764  * This method builds a newly created field on cell just lying on mesh \a mesh without its eventual refinement.
765  * The output field also displays ghost cells.
766  *
767  * \return MEDCouplingFieldDouble * - a field on cells that the caller has to deal with (deallocate it).
768  *
769  * \sa buildCellFieldOnWithoutGhost
770  */
771 MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnWithGhost(MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) const
772 {
773   const DataArrayDouble *arr(0);
774   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
775     {
776       int tmp(-1);
777       if((*it)->presenceOf(mesh,tmp))
778         {
779           const DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp));
780           arr=ddc.getFieldWithName(fieldName);
781         }
782     }
783   if(!arr)
784     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::buildCellFieldOnWithGhost : the mesh specified is not in the progeny of this !");
785   MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> im(mesh->getImageMesh()->buildWithGhost(_ghost_lev));
786   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS));
787   ret->setMesh(im);
788   ret->setArray(const_cast<DataArrayDouble *>(arr));
789   ret->setName(arr->getName());
790   return ret.retn();
791 }
792
793 /*!
794  * This method builds a newly created field on cell just lying on mesh \a mesh without its eventual refinement.
795  * The output field does not display ghost cells.
796  *
797  * \return MEDCouplingFieldDouble * - a field on cells that the caller has to deal with (deallocate it).
798  *
799  * \sa buildCellFieldOnWithGhost
800  */
801 MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnWithoutGhost(MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) const
802 {
803   //tony
804   const DataArrayDouble *arr(0);
805   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
806     {
807       int tmp(-1);
808       if((*it)->presenceOf(mesh,tmp))
809         {
810           const DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp));
811           arr=ddc.getFieldWithName(fieldName);
812         }
813     }
814   if(!arr)
815     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::buildCellFieldOnWithoutGhost : the mesh specified is not in the progeny of this !");
816   //
817   MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> im(mesh->getImageMesh()->buildWithGhost(_ghost_lev));
818   std::vector<int> cgs(mesh->getImageMesh()->getCellGridStructure()),cgsWG(im->getCellGridStructure());
819   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr2(DataArrayDouble::New());
820   arr2->alloc(mesh->getImageMesh()->getNumberOfCells(),arr->getNumberOfComponents());
821   std::vector< std::pair<int,int> > cgs2(MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(cgs));
822   MEDCouplingStructuredMesh::ApplyGhostOnCompactFrmt(cgs2,_ghost_lev);
823   std::vector<int> fakeFactors(mesh->getImageMesh()->getSpaceDimension(),1);
824   MEDCouplingIMesh::SpreadCoarseToFine(arr,cgsWG,arr2,cgs2,fakeFactors);
825   arr2->copyStringInfoFrom(*arr);
826   //
827   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS));
828   ret->setMesh(mesh->getImageMesh());
829   ret->setArray(arr2);
830   ret->setName(arr->getName());
831   return ret.retn();
832 }
833
834 /*!
835  * This method synchronizes from fine to coarse direction arrays. This method makes the hypothesis that \a this has been allocated before using
836  * MEDCouplingAMRAttribute::alloc method.
837  * This method \b DOES \b NOT \b UPDATE the ghost zones (neither the fine not the coarse)
838  *
839  * \sa synchronizeFineToCoarseBetween
840  */
841 void MEDCouplingAMRAttribute::synchronizeFineToCoarse()
842 {
843   if(_levs.empty())
844     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineToCoarse : not any levels in this !");
845   std::size_t sz(_levs.size());
846   //
847   while(sz>1)
848     {
849       sz--;
850       synchronizeFineToCoarseByOneLevel((int)sz);
851     }
852 }
853
854 /*!
855  * This method allows to synchronizes fields on fine patches on level \a fromLev to coarser patches at \a toLev level.
856  * This method operates step by step performing the synchronization the \a fromLev to \a fromLev - 1, then \a fromLev -1 to \a fromLev - 2 ...
857  * until reaching \a toLev level.
858  * This method \b DOES \b NOT \b UPDATE the ghost zones (neither the fine not the coarse).
859  *
860  * \param [in] fromLev - an existing level considered as fine so bigger than \a toLev
861  * \param [in] toLev - an existing level considered as the target level to reach.
862  *
863  */
864 void MEDCouplingAMRAttribute::synchronizeFineToCoarseBetween(int fromLev, int toLev)
865 {
866   int nbl(getNumberOfLevels());
867   if(fromLev<0 || toLev<0 || fromLev>=nbl || toLev>=nbl)
868     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineToCoarseBetween : fromLev and toLev must be >= 0 and lower than number of levels in this !");
869   if(fromLev==toLev)
870     return ;//nothing to do
871   if(fromLev<toLev)
872     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineToCoarseBetween : the fromLev level is lower than toLev level ! Call synchronizeFineToCoarseBetween ");
873   for(int i=fromLev;i>toLev;i--)
874     synchronizeFineToCoarseByOneLevel(i);
875 }
876
877 /*!
878  * 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
879  * MEDCouplingAMRAttribute::alloc method.
880  * This method \b DOES \b UPDATE \b the \b ghost \b zone (contrary to synchronizeFineToCoarse method)
881  */
882 void MEDCouplingAMRAttribute::synchronizeCoarseToFine()
883 {
884   if(_levs.empty())
885     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeCoarseToFine : not any levels in this !");
886   std::size_t sz(_levs.size());
887   //
888   for(std::size_t i=0;i<sz-1;i++)
889     synchronizeCoarseToFineByOneLevel((int)i);
890 }
891
892 /*!
893  * This method allows to synchronizes fields on coarse patches on level \a fromLev to their respective refined patches at \a toLev level.
894  * This method operates step by step performing the synchronization the \a fromLev to \a fromLev + 1, then \a fromLev + 1 to \a fromLev + 2 ...
895  * until reaching \a toLev level.
896  * This method \b DOES \b UPDATE \b the \b ghost \b zone (contrary to synchronizeFineToCoarseBetween method)
897  *
898  * \param [in] fromLev - an existing level considered as coarse so lower than \a toLev
899  * \param [in] toLev - an existing level considered as the target level to reach.
900  */
901 void MEDCouplingAMRAttribute::synchronizeCoarseToFineBetween(int fromLev, int toLev)
902 {
903   int nbl(getNumberOfLevels());
904   if(fromLev<0 || toLev<0 || fromLev>=nbl || toLev>=nbl)
905     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeCoarseToFineBetween : fromLev and toLev must be >= 0 and lower than number of levels in this !");
906   if(fromLev==toLev)
907     return ;//nothing to do
908   if(fromLev>toLev)
909     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeCoarseToFineBetween : the fromLev level is greater than toLev level ! Call synchronizeFineToCoarseBetween instead !");
910   for(int i=fromLev;i<toLev;i++)
911     synchronizeCoarseToFineByOneLevel(i);
912 }
913
914 /*!
915  * This method synchronizes the ghost zone of all patches (excepted the god father one).
916  * This method operates in 4 steps. Larger is the number of steps more accurate is the information in the ghost zone.
917  *
918  * - firstly coarse to fine with no interactions between brother patches.
919  * - secondly connected brother patches in a same master patch are updated.
920  * - thirdly connected nephew patches are updated each other.
921  * - forthly nth generation cousin patches are updated each other.
922  *
923  * This method makes the hypothesis that \a this has been allocated before using MEDCouplingAMRAttribute::alloc method.
924  * So if \a _ghost_lev == 0 this method has no effect.
925  */
926 void MEDCouplingAMRAttribute::synchronizeAllGhostZones()
927 {
928   int sz(getNumberOfLevels());
929   if(sz==0)
930     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineEachOther : not any levels in this !");
931   // 1st - synchronize from coarse to the finest all the patches (excepted the god father one)
932   for(int i=1;i<sz;i++)
933     {
934       const MEDCouplingGridCollection *fine(_levs[i]),*coarse(_levs[i-1]);
935       MEDCouplingGridCollection::SynchronizeCoarseToFineOnlyInGhostZone(_ghost_lev,coarse,fine);
936     }
937   // 2nd - classical direct sublevel inside common patch
938   for(int i=1;i<sz;i++)
939     {
940       const MEDCouplingGridCollection *curLev(_levs[i]);
941       if(!curLev)
942         throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineEachOtherInGhostZone : presence of a NULL element !");
943       curLev->synchronizeFineEachOther(_ghost_lev,_neighbors[i]);
944     }
945   // 3rd - mixed level
946   for(std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >::const_iterator it=_mixed_lev_neighbors.begin();it!=_mixed_lev_neighbors.end();it++)
947     {
948       const DataArrayDoubleCollection *firstDAC(&findCollectionAttachedTo((*it).first->getMesh())),*secondDAC(&findCollectionAttachedTo((*it).second->getMesh()));
949       DataArrayDoubleCollection::SynchronizeGhostZoneOfOneUsingTwo(_ghost_lev,(*it).first,firstDAC,(*it).second,secondDAC);
950     }
951   // 4th - same level but with far ancestor.
952   for(int i=1;i<sz;i++)
953     {
954       const MEDCouplingGridCollection *fine(_levs[i]);
955       fine->synchronizeFineEachOtherExt(_ghost_lev,_cross_lev_neighbors[i]);
956     }
957 }
958
959 /*!
960  * This method synchronizes all direct children of \a mesh each other.
961  */
962 void MEDCouplingAMRAttribute::synchronizeAllGhostZonesOfDirectChidrenOf(const MEDCouplingCartesianAMRMeshGen *mesh)
963 {
964   if(!mesh)
965     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeAllGhostZonesOfDirectChidrenOf : input mesh is NULL !");
966   int level(mesh->getAbsoluteLevelRelativeTo(_gf)),sz(getNumberOfLevels());
967   if(level<0 || level>=sz-1)
968     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeAllGhostZonesOfDirectChidrenOf : the specified level does not exist ! Must be in [0,nbOfLevelsOfThis-1) !");
969   const std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >& itemsToFilter(_neighbors[level+1]);
970   std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > itemsToSync; itemsToSync.reserve(itemsToFilter.size());
971   for(std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >::const_iterator it=itemsToFilter.begin();it!=itemsToFilter.end();it++)
972     {
973       if((*it).first->getMesh()->getFather()==mesh && (*it).second->getMesh()->getFather()==mesh)
974         itemsToSync.push_back(std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *>((*it).first,(*it).second));
975     }
976   const MEDCouplingGridCollection *curLev(_levs[level+1]);
977   if(!curLev)
978     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeAllGhostZonesOfDirectChidrenOf : presence of a NULL element !");
979   curLev->synchronizeFineEachOther(_ghost_lev,itemsToSync);
980 }
981
982 /*!
983  * This method allocates all DataArrayDouble instances stored recursively in \a this.
984  *
985  * \sa dealloc
986  */
987 void MEDCouplingAMRAttribute::alloc()
988 {
989   _tlc.resetState();
990   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::iterator it=_levs.begin();it!=_levs.end();it++)
991     {
992       MEDCouplingGridCollection *elt(*it);
993       if(elt)
994         elt->alloc(_ghost_lev);
995       else
996         throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::alloc : internal error !");
997     }
998 }
999
1000 /*!
1001  * This method deallocates all DataArrayDouble instances stored recursively in \a this.
1002  * \sa alloc
1003  */
1004 void MEDCouplingAMRAttribute::dealloc()
1005 {
1006   _tlc.checkConst();
1007   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::iterator it=_levs.begin();it!=_levs.end();it++)
1008     {
1009       MEDCouplingGridCollection *elt(*it);
1010       if(elt)
1011         elt->dealloc();
1012       else
1013         throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::dealloc : internal error !");
1014     }
1015 }
1016
1017 bool MEDCouplingAMRAttribute::changeGodFather(MEDCouplingCartesianAMRMesh *gf)
1018 {
1019   bool ret(MEDCouplingDataForGodFather::changeGodFather(gf));
1020   return ret;
1021 }
1022
1023 std::size_t MEDCouplingAMRAttribute::getHeapMemorySizeWithoutChildren() const
1024 {
1025   std::size_t ret(sizeof(MEDCouplingAMRAttribute));
1026   ret+=_levs.capacity()*sizeof(MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection>);
1027   return ret;
1028 }
1029
1030 std::vector<const BigMemoryObject *> MEDCouplingAMRAttribute::getDirectChildren() const
1031 {
1032   std::vector<const BigMemoryObject *> ret;
1033   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
1034     {
1035       const MEDCouplingGridCollection *elt(*it);
1036       if(elt)
1037         ret.push_back(elt);
1038     }
1039   return ret;
1040 }
1041
1042 void MEDCouplingAMRAttribute::updateTime() const
1043 {//tony
1044 }
1045
1046 MEDCouplingAMRAttribute::MEDCouplingAMRAttribute(MEDCouplingCartesianAMRMesh *gf, const std::vector< std::pair<std::string,int> >& fieldNames, int ghostLev):MEDCouplingDataForGodFather(gf),_ghost_lev(ghostLev)
1047 {
1048   //gf non empty, checked by constructor
1049   int maxLev(gf->getMaxNumberOfLevelsRelativeToThis());
1050   _levs.resize(maxLev);
1051   for(int i=0;i<maxLev;i++)
1052     {
1053       std::vector<MEDCouplingCartesianAMRPatchGen *> patches(gf->retrieveGridsAt(i));
1054       std::size_t sz(patches.size());
1055       std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatchGen> > patchesSafe(patches.size());
1056       for(std::size_t j=0;j<sz;j++)
1057         patchesSafe[j]=patches[j];
1058       std::vector<const MEDCouplingCartesianAMRMeshGen *> ms(sz);
1059       for(std::size_t j=0;j<sz;j++)
1060         {
1061           ms[j]=patches[j]->getMesh();
1062         }
1063       _levs[i]=MEDCouplingGridCollection::New(ms,fieldNames);
1064     }
1065   // updates cross levels neighbors
1066   _neighbors.resize(_levs.size());
1067   _cross_lev_neighbors.resize(_levs.size());
1068   if(_levs.empty())
1069     throw INTERP_KERNEL::Exception("constructor of MEDCouplingAMRAttribute : not any levels in this !");
1070   std::size_t sz(_levs.size());
1071   for(std::size_t i=1;i<sz;i++)
1072     {
1073       const MEDCouplingGridCollection *fine(_levs[i]);
1074       if(!fine)
1075         throw INTERP_KERNEL::Exception("constructor of MEDCouplingAMRAttribute : presence of a NULL element !");
1076       _neighbors[i]=fine->findNeighbors(_ghost_lev);
1077       if(i!=sz-1)
1078         {
1079           for(std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >::const_iterator it=_neighbors[i].begin();it!=_neighbors[i].end();it++)
1080             {
1081               MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOf(_ghost_lev,(*it).first,(*it).second,_mixed_lev_neighbors);
1082               std::vector< std::vector < std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > > neighs2(MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOfSameLev(_ghost_lev,(*it).first,(*it).second));
1083               std::size_t fullLev(i+neighs2.size());
1084               if(fullLev>=sz)
1085                 throw INTERP_KERNEL::Exception("constructor of MEDCouplingAMRAttribute : internal error ! something is wrong in computation of cross level neighbors !");
1086               std::size_t ii(i+1);
1087               for(std::vector< std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > >::const_iterator it0=neighs2.begin();it0!=neighs2.end();it0++,ii++)
1088                 _cross_lev_neighbors[ii].insert(_cross_lev_neighbors[ii].end(),(*it0).begin(),(*it0).end());
1089             }
1090         }
1091     }
1092 }
1093
1094 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)
1095 {
1096   std::size_t sz(other._levs.size());
1097   for(std::size_t i=0;i<sz;i++)
1098     {
1099       const MEDCouplingGridCollection *elt(other._levs[i]);
1100       if(elt)
1101         {
1102           _levs[i]=other._levs[i]->deepCpy(_gf,other._gf);
1103         }
1104     }
1105   //_cross_lev_neighbors(other._cross_lev_neighbors)
1106   sz=other._neighbors.size();
1107   for(std::size_t i=0;i<sz;i++)
1108     {
1109       const std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >& neigh2(other._neighbors[i]);
1110       std::size_t sz2(neigh2.size());
1111       std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >& neigh3(_neighbors[i]);
1112       for(std::size_t j=0;j<sz2;j++)
1113         {
1114           const MEDCouplingCartesianAMRPatch *p1(neigh2[j].first),*p2(neigh2[j].second);
1115           std::vector<int> pp1(p1->getMesh()->getPositionRelativeTo(other._gf)),pp2(p2->getMesh()->getPositionRelativeTo(other._gf));
1116           neigh3[j].first=_gf->getPatchAtPosition(pp1);
1117           neigh3[j].second=_gf->getPatchAtPosition(pp2);
1118         }
1119     }
1120   //
1121   sz=other._mixed_lev_neighbors.size();
1122   for(std::size_t i=0;i<sz;i++)
1123     {
1124       const MEDCouplingCartesianAMRPatch *p1(other._mixed_lev_neighbors[i].first),*p2(other._mixed_lev_neighbors[i].second);
1125       std::vector<int> pp1(p1->getMesh()->getPositionRelativeTo(other._gf)),pp2(p2->getMesh()->getPositionRelativeTo(other._gf));
1126       _mixed_lev_neighbors[i].first=_gf->getPatchAtPosition(pp1);
1127       _mixed_lev_neighbors[i].second=_gf->getPatchAtPosition(pp2);
1128     }
1129   //
1130   sz=other._cross_lev_neighbors.size();
1131   for(std::size_t i=0;i<sz;i++)
1132     {
1133       const std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >& neigh2(other._cross_lev_neighbors[i]);
1134       std::size_t sz2(neigh2.size());
1135       std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >& neigh3(_cross_lev_neighbors[i]);
1136       for(std::size_t j=0;j<sz2;j++)
1137         {
1138           const MEDCouplingCartesianAMRPatch *p1(neigh2[j].first),*p2(neigh2[j].second);
1139           std::vector<int> pp1(p1->getMesh()->getPositionRelativeTo(other._gf)),pp2(p2->getMesh()->getPositionRelativeTo(other._gf));
1140           neigh3[j].first=_gf->getPatchAtPosition(pp1);
1141           neigh3[j].second=_gf->getPatchAtPosition(pp2);
1142         }
1143     }
1144 }
1145
1146 const DataArrayDoubleCollection& MEDCouplingAMRAttribute::findCollectionAttachedTo(const MEDCouplingCartesianAMRMeshGen *m) const
1147 {
1148   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
1149     {
1150       const MEDCouplingGridCollection *elt(*it);
1151       if(elt)
1152         {
1153           int tmp(-1);
1154           if(elt->presenceOf(m,tmp))
1155             {
1156               return elt->getFieldsAt(tmp);
1157             }
1158         }
1159     }
1160   throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::findCollectionAttachedTo : unable to find such part of mesh in this !");
1161 }
1162
1163 void MEDCouplingAMRAttribute::synchronizeFineToCoarseByOneLevel(int level)
1164 {
1165   int nbl(getNumberOfLevels());
1166   if(level<=0 || level>=nbl)
1167     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineToCoarseByOneLevel : the input level must be in ]0,nb_of_levels[ !");
1168   const MEDCouplingGridCollection *fine(_levs[level]),*coarse(_levs[level-1]);
1169   MEDCouplingGridCollection::SynchronizeFineToCoarse(_ghost_lev,fine,coarse);
1170 }
1171
1172 void MEDCouplingAMRAttribute::synchronizeCoarseToFineByOneLevel(int level)
1173 {
1174   int nbl(getNumberOfLevels());
1175   if(level<0 || level>=nbl-1)
1176     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineToCoarseByOneLevel : the input level must be in [0,nb_of_levels[ !");
1177   const MEDCouplingGridCollection *fine(_levs[level+1]),*coarse(_levs[level]);
1178   MEDCouplingGridCollection::SynchronizeCoarseToFine(_ghost_lev,coarse,fine);
1179 }