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