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