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