Salome HOME
b9c1559dee304b9c7a093c58ff17ea489989673a
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingAMRAttribute.cxx
1 // Copyright (C) 2007-2014  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay
20
21 #include "MEDCouplingAMRAttribute.hxx"
22 #include "MEDCouplingFieldDouble.hxx"
23 #include "MEDCouplingMemArray.hxx"
24 #include "MEDCouplingIMesh.hxx"
25
26 #include <sstream>
27
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 MEDCouplingCartesianAMRMeshGen *MEDCouplingDataForGodFather::getMyGodFather()
588 {
589   return _gf;
590 }
591
592 MEDCouplingDataForGodFather::MEDCouplingDataForGodFather(MEDCouplingCartesianAMRMeshGen *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(MEDCouplingCartesianAMRMeshGen *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 MEDCouplingCartesianAMRMeshGen *gf(other._gf);
622       if(gf)
623         _gf=gf->deepCpy();
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(MEDCouplingCartesianAMRMeshGen *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(MEDCouplingCartesianAMRMeshGen *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  *
838  * \sa synchronizeFineToCoarseBetween
839  */
840 void MEDCouplingAMRAttribute::synchronizeFineToCoarse()
841 {
842   if(_levs.empty())
843     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineToCoarse : not any levels in this !");
844   std::size_t sz(_levs.size());
845   //
846   while(sz>1)
847     {
848       sz--;
849       synchronizeFineToCoarseByOneLevel((int)sz);
850     }
851 }
852
853 /*!
854  * This method allows to synchronizes fields on fine patches on level \a fromLev to coarser patches at \a toLev level.
855  * This method operates step by step performing the synchronization the \a fromLev to \a fromLev - 1, then \a fromLev -1 to \a fromLev - 2 ...
856  * until reaching \a toLev level.
857  *
858  * \param [in] fromLev - an existing level considered as fine so bigger than \a toLev
859  * \param [in] toLev - an existing level considered as the target level to reach.
860  *
861  */
862 void MEDCouplingAMRAttribute::synchronizeFineToCoarseBetween(int fromLev, int toLev)
863 {
864   int nbl(getNumberOfLevels());
865   if(fromLev<0 || toLev<0 || fromLev>=nbl || toLev>=nbl)
866     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineToCoarseBetween : fromLev and toLev must be >= 0 and lower than number of levels in this !");
867   if(fromLev==toLev)
868     return ;//nothing to do
869   if(fromLev<toLev)
870     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineToCoarseBetween : the fromLev level is lower than toLev level ! Call synchronizeFineToCoarseBetween ");
871   for(int i=fromLev;i>toLev;i--)
872     synchronizeFineToCoarseByOneLevel(i);
873 }
874
875 /*!
876  * 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
877  * MEDCouplingAMRAttribute::alloc method.
878  */
879 void MEDCouplingAMRAttribute::synchronizeCoarseToFine()
880 {
881   if(_levs.empty())
882     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeCoarseToFine : not any levels in this !");
883   std::size_t sz(_levs.size());
884   //
885   for(std::size_t i=0;i<sz-1;i++)
886     synchronizeCoarseToFineByOneLevel((int)i);
887 }
888
889 /*!
890  * This method allows to synchronizes fields on coarse patches on level \a fromLev to their respective refined patches at \a toLev level.
891  * This method operates step by step performing the synchronization the \a fromLev to \a fromLev + 1, then \a fromLev + 1 to \a fromLev + 2 ...
892  * until reaching \a toLev level.
893  *
894  * \param [in] fromLev - an existing level considered as coarse so lower than \a toLev
895  * \param [in] toLev - an existing level considered as the target level to reach.
896  */
897 void MEDCouplingAMRAttribute::synchronizeCoarseToFineBetween(int fromLev, int toLev)
898 {
899   int nbl(getNumberOfLevels());
900   if(fromLev<0 || toLev<0 || fromLev>=nbl || toLev>=nbl)
901     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeCoarseToFineBetween : fromLev and toLev must be >= 0 and lower than number of levels in this !");
902   if(fromLev==toLev)
903     return ;//nothing to do
904   if(fromLev>toLev)
905     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeCoarseToFineBetween : the fromLev level is greater than toLev level ! Call synchronizeFineToCoarseBetween instead !");
906   for(int i=fromLev;i<toLev;i++)
907     synchronizeCoarseToFineByOneLevel(i);
908 }
909
910 /*!
911  * This method synchronizes the ghost zone of all patches (excepted the god father one).
912  * This method operates in 4 steps. Larger is the number of steps more accurate is the information in the ghost zone.
913  *
914  * - firstly coarse to fine with no interactions between brother patches.
915  * - secondly connected brother patches in a same master patch are updated.
916  * - thirdly connected nephew patches are updated each other.
917  * - forthly nth generation cousin patches are updated each other.
918  *
919  * This method makes the hypothesis that \a this has been allocated before using MEDCouplingAMRAttribute::alloc method.
920  * So if \a _ghost_lev == 0 this method has no effect.
921  */
922 void MEDCouplingAMRAttribute::synchronizeAllGhostZones()
923 {
924   int sz(getNumberOfLevels());
925   if(sz==0)
926     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineEachOther : not any levels in this !");
927   // 1st - synchronize from coarse to the finest all the patches (excepted the god father one)
928   for(int i=1;i<sz;i++)
929     {
930       const MEDCouplingGridCollection *fine(_levs[i]),*coarse(_levs[i-1]);
931       MEDCouplingGridCollection::SynchronizeCoarseToFineOnlyInGhostZone(_ghost_lev,coarse,fine);
932     }
933   // 2nd - classical direct sublevel inside common patch
934   for(int i=1;i<sz;i++)
935     {
936       const MEDCouplingGridCollection *fine(_levs[i]);
937       if(!fine)
938         throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineEachOtherInGhostZone : presence of a NULL element !");
939       fine->synchronizeFineEachOther(_ghost_lev,_neighbors[i]);
940     }
941   // 3rd - mixed level
942   for(std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >::const_iterator it=_mixed_lev_neighbors.begin();it!=_mixed_lev_neighbors.end();it++)
943     {
944       const DataArrayDoubleCollection *firstDAC(&findCollectionAttachedTo((*it).first->getMesh())),*secondDAC(&findCollectionAttachedTo((*it).second->getMesh()));
945       DataArrayDoubleCollection::SynchronizeGhostZoneOfOneUsingTwo(_ghost_lev,(*it).first,firstDAC,(*it).second,secondDAC);
946     }
947   // 4th - same level but with far ancestor.
948   for(int i=1;i<sz;i++)
949     {
950       const MEDCouplingGridCollection *fine(_levs[i]);
951       fine->synchronizeFineEachOtherExt(_ghost_lev,_cross_lev_neighbors[i]);
952     }
953 }
954
955 /*!
956  * This method
957  */
958 void MEDCouplingAMRAttribute::synchronizeAllGhostZonesOfDirectChidrenOf(const MEDCouplingCartesianAMRMeshGen *mesh)
959 {
960   if(!mesh)
961     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeAllGhostZonesOfDirectChidrenOf : input mesh is NULL !");
962   int level(mesh->getAbsoluteLevelRelativeTo(_gf)),sz(getNumberOfLevels());
963   if(level<0 || level>=sz-1)
964     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeAllGhostZonesOfDirectChidrenOf : the specified level does not exist ! Must be in [0,nbOfLevelsOfThis-1) !");
965   const DataArrayDoubleCollection& colCoarse(findCollectionAttachedTo(mesh));
966   std::vector< const MEDCouplingCartesianAMRPatch *> directChildren(mesh->getPatches());
967   std::size_t nbOfDirChildren(directChildren.size());
968   for(std::size_t patchId=0;patchId<nbOfDirChildren;patchId++)
969     {
970       const DataArrayDoubleCollection& colFine(findCollectionAttachedTo(directChildren[patchId]->getMesh()));
971       DataArrayDoubleCollection *colFine2(const_cast<DataArrayDoubleCollection *>(&colFine));
972       DataArrayDoubleCollection::SynchronizeCoarseToFineOnlyInGhostZone(_ghost_lev,mesh,(int)patchId,&colCoarse,colFine2);
973     }
974 }
975
976 /*!
977  * This method allocates all DataArrayDouble instances stored recursively in \a this.
978  *
979  * \sa dealloc
980  */
981 void MEDCouplingAMRAttribute::alloc()
982 {
983   _tlc.resetState();
984   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::iterator it=_levs.begin();it!=_levs.end();it++)
985     {
986       MEDCouplingGridCollection *elt(*it);
987       if(elt)
988         elt->alloc(_ghost_lev);
989       else
990         throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::alloc : internal error !");
991     }
992 }
993
994 /*!
995  * This method deallocates all DataArrayDouble instances stored recursively in \a this.
996  * \sa alloc
997  */
998 void MEDCouplingAMRAttribute::dealloc()
999 {
1000   _tlc.checkConst();
1001   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::iterator it=_levs.begin();it!=_levs.end();it++)
1002     {
1003       MEDCouplingGridCollection *elt(*it);
1004       if(elt)
1005         elt->dealloc();
1006       else
1007         throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::dealloc : internal error !");
1008     }
1009 }
1010
1011 bool MEDCouplingAMRAttribute::changeGodFather(MEDCouplingCartesianAMRMeshGen *gf)
1012 {
1013   bool ret(MEDCouplingDataForGodFather::changeGodFather(gf));
1014   return ret;
1015 }
1016
1017 std::size_t MEDCouplingAMRAttribute::getHeapMemorySizeWithoutChildren() const
1018 {
1019   std::size_t ret(sizeof(MEDCouplingAMRAttribute));
1020   ret+=_levs.capacity()*sizeof(MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection>);
1021   return ret;
1022 }
1023
1024 std::vector<const BigMemoryObject *> MEDCouplingAMRAttribute::getDirectChildren() const
1025 {
1026   std::vector<const BigMemoryObject *> ret;
1027   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
1028     {
1029       const MEDCouplingGridCollection *elt(*it);
1030       if(elt)
1031         ret.push_back(elt);
1032     }
1033   return ret;
1034 }
1035
1036 void MEDCouplingAMRAttribute::updateTime() const
1037 {//tony
1038 }
1039
1040 MEDCouplingAMRAttribute::MEDCouplingAMRAttribute(MEDCouplingCartesianAMRMeshGen *gf, const std::vector< std::pair<std::string,int> >& fieldNames, int ghostLev):MEDCouplingDataForGodFather(gf),_ghost_lev(ghostLev)
1041 {
1042   //gf non empty, checked by constructor
1043   int maxLev(gf->getMaxNumberOfLevelsRelativeToThis());
1044   _levs.resize(maxLev);
1045   for(int i=0;i<maxLev;i++)
1046     {
1047       std::vector<MEDCouplingCartesianAMRPatchGen *> patches(gf->retrieveGridsAt(i));
1048       std::size_t sz(patches.size());
1049       std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatchGen> > patchesSafe(patches.size());
1050       for(std::size_t j=0;j<sz;j++)
1051         patchesSafe[j]=patches[j];
1052       std::vector<const MEDCouplingCartesianAMRMeshGen *> ms(sz);
1053       for(std::size_t j=0;j<sz;j++)
1054         {
1055           ms[j]=patches[j]->getMesh();
1056         }
1057       _levs[i]=MEDCouplingGridCollection::New(ms,fieldNames);
1058     }
1059   // updates cross levels neighbors
1060   _neighbors.resize(_levs.size());
1061   _cross_lev_neighbors.resize(_levs.size());
1062   if(_levs.empty())
1063     throw INTERP_KERNEL::Exception("constructor of MEDCouplingAMRAttribute : not any levels in this !");
1064   std::size_t sz(_levs.size());
1065   for(std::size_t i=1;i<sz;i++)
1066     {
1067       const MEDCouplingGridCollection *fine(_levs[i]);
1068       if(!fine)
1069         throw INTERP_KERNEL::Exception("constructor of MEDCouplingAMRAttribute : presence of a NULL element !");
1070       _neighbors[i]=fine->findNeighbors(_ghost_lev);
1071       if(i!=sz-1)
1072         {
1073           for(std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >::const_iterator it=_neighbors[i].begin();it!=_neighbors[i].end();it++)
1074             {
1075               MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOf(_ghost_lev,(*it).first,(*it).second,_mixed_lev_neighbors);
1076               std::vector< std::vector < std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > > neighs2(MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOfSameLev(_ghost_lev,(*it).first,(*it).second));
1077               std::size_t fullLev(i+neighs2.size());
1078               if(fullLev>=sz)
1079                 throw INTERP_KERNEL::Exception("constructor of MEDCouplingAMRAttribute : internal error ! something is wrong in computation of cross level neighbors !");
1080               std::size_t ii(i+1);
1081               for(std::vector< std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > >::const_iterator it0=neighs2.begin();it0!=neighs2.end();it0++,ii++)
1082                 _cross_lev_neighbors[ii].insert(_cross_lev_neighbors[ii].end(),(*it0).begin(),(*it0).end());
1083             }
1084         }
1085     }
1086 }
1087
1088 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)
1089 {
1090   std::size_t sz(other._levs.size());
1091   for(std::size_t i=0;i<sz;i++)
1092     {
1093       const MEDCouplingGridCollection *elt(other._levs[i]);
1094       if(elt)
1095         {
1096           _levs[i]=other._levs[i]->deepCpy(_gf,other._gf);
1097         }
1098     }
1099 }
1100
1101 const DataArrayDoubleCollection& MEDCouplingAMRAttribute::findCollectionAttachedTo(const MEDCouplingCartesianAMRMeshGen *m) const
1102 {
1103   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
1104     {
1105       const MEDCouplingGridCollection *elt(*it);
1106       if(elt)
1107         {
1108           int tmp(-1);
1109           if(elt->presenceOf(m,tmp))
1110             {
1111               return elt->getFieldsAt(tmp);
1112             }
1113         }
1114     }
1115   throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::findCollectionAttachedTo : unable to find such part of mesh in this !");
1116 }
1117
1118 void MEDCouplingAMRAttribute::synchronizeFineToCoarseByOneLevel(int level)
1119 {
1120   int nbl(getNumberOfLevels());
1121   if(level<=0 || level>=nbl)
1122     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineToCoarseByOneLevel : the input level must be in ]0,nb_of_levels[ !");
1123   const MEDCouplingGridCollection *fine(_levs[level]),*coarse(_levs[level-1]);
1124   MEDCouplingGridCollection::SynchronizeFineToCoarse(_ghost_lev,fine,coarse);
1125 }
1126
1127 void MEDCouplingAMRAttribute::synchronizeCoarseToFineByOneLevel(int level)
1128 {
1129   int nbl(getNumberOfLevels());
1130   if(level<0 || level>=nbl-1)
1131     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineToCoarseByOneLevel : the input level must be in [0,nb_of_levels[ !");
1132   const MEDCouplingGridCollection *fine(_levs[level+1]),*coarse(_levs[level]);
1133   MEDCouplingGridCollection::SynchronizeCoarseToFine(_ghost_lev,coarse,fine);
1134 }