Salome HOME
Full synchronisation of patches across levels.
[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 void DataArrayDoubleCollection::allocTuples(int nbOfTuples)
36 {
37   std::size_t sz(_arrs.size());
38   for(std::size_t i=0;i<sz;i++)
39     _arrs[i]->reAlloc(nbOfTuples);
40 }
41
42 void DataArrayDoubleCollection::dellocTuples()
43 {
44   std::size_t sz(_arrs.size());
45   for(std::size_t i=0;i<sz;i++)
46     _arrs[i]->reAlloc(0);
47 }
48
49 void DataArrayDoubleCollection::spillInfoOnComponents(const std::vector< std::vector<std::string> >& compNames)
50 {
51   std::size_t sz(_arrs.size());
52   if(sz!=compNames.size())
53     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::spillInfoOnComponents : first size of compNames has to be equal to the number of fields defined !");
54   for(std::size_t i=0;i<sz;i++)
55     {
56       const std::vector<std::string>& names(compNames[i]);
57       _arrs[i]->setInfoOnComponents(names);
58     }
59 }
60
61 std::vector<DataArrayDouble *> DataArrayDoubleCollection::retrieveFields() const
62 {
63   std::size_t sz(_arrs.size());
64   std::vector<DataArrayDouble *> ret(sz);
65   for(std::size_t i=0;i<sz;i++)
66     {
67       const DataArrayDouble *tmp(_arrs[i]);
68       ret[i]=const_cast<DataArrayDouble *>(tmp);
69       if(ret[i])
70         ret[i]->incrRef();
71     }
72   return ret;
73 }
74
75 const DataArrayDouble *DataArrayDoubleCollection::getFieldWithName(const std::string& name) const
76 {
77   std::vector<std::string> vec;
78   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> >::const_iterator it=_arrs.begin();it!=_arrs.end();it++)
79     {
80       const DataArrayDouble *obj(*it);
81       if(obj)
82         {
83           if(obj->getName()==name)
84             return obj;
85           else
86             vec.push_back(obj->getName());
87         }
88     }
89   std::ostringstream oss; oss << "DataArrayDoubleCollection::getFieldWithName : fieldName \"" << name << "\" does not exist in this ! Possibilities are :";
90   std::copy(vec.begin(),vec.end(),std::ostream_iterator<std::string>(oss," "));
91   throw INTERP_KERNEL::Exception(oss.str().c_str());
92 }
93
94 void DataArrayDoubleCollection::SynchronizeFineToCoarse(int ghostLev, const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh, int patchId, const DataArrayDoubleCollection *fine, DataArrayDoubleCollection *coarse)
95 {
96   if(!fine || !coarse)
97     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeFineToCoarse : the input DataArrayDouble collections must be non NULL !");
98   std::size_t sz(coarse->_arrs.size());
99   if(fine->_arrs.size()!=sz)
100     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeFineToCoarse : the input DataArrayDouble collection must have the same size !");
101   for(std::size_t i=0;i<sz;i++)
102     fatherOfFineMesh->fillCellFieldComingFromPatchGhost(patchId,fine->_arrs[i],coarse->_arrs[i],ghostLev);
103 }
104
105 void DataArrayDoubleCollection::SynchronizeCoarseToFine(int ghostLev, const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh, int patchId, const DataArrayDoubleCollection *coarse, DataArrayDoubleCollection *fine)
106 {
107   if(!fine || !coarse)
108     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeCoarseToFine : the input DataArrayDouble collections must be non NULL !");
109   std::size_t sz(coarse->_arrs.size());
110   if(fine->_arrs.size()!=sz)
111     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeCoarseToFine : the input DataArrayDouble collection must have the same size !");
112   for(std::size_t i=0;i<sz;i++)
113     fatherOfFineMesh->fillCellFieldOnPatchGhost(patchId,coarse->_arrs[i],fine->_arrs[i],ghostLev);
114 }
115
116 void DataArrayDoubleCollection::SynchronizeFineEachOther(int patchId, int ghostLev, const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh, const std::vector<const MEDCouplingCartesianAMRMeshGen *>& children, const std::vector<DataArrayDoubleCollection *>& fieldsOnFine)
117 {
118   if(!fatherOfFineMesh)
119     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeFineEachOther : father is NULL !");
120   std::size_t sz(children.size());
121   if(fieldsOnFine.size()!=sz)
122     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeFineEachOther : sizes of vectors mismatch !");
123   if(sz<=1)
124     return ;
125   std::size_t nbOfCall(fieldsOnFine[0]->_arrs.size());
126   for(std::size_t i=0;i<sz;i++)
127     if(fatherOfFineMesh->getPatchIdFromChildMesh(children[i])!=(int)i)
128       throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeFineEachOther : internal error !");
129   for(std::size_t i=1;i<sz;i++)
130     if(nbOfCall!=fieldsOnFine[i]->_arrs.size())
131       throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeFineEachOther : the collection of DataArrayDouble must have all the same size !");
132   for(std::size_t i=0;i<nbOfCall;i++)
133     {
134       std::vector<const DataArrayDouble *> arrs(sz);
135       for(std::size_t j=0;j<sz;j++)
136         arrs[j]=fieldsOnFine[j]->_arrs[i];
137       fatherOfFineMesh->fillCellFieldOnPatchOnlyGhostAdv(patchId,ghostLev,arrs);
138     }
139 }
140
141 void DataArrayDoubleCollection::SynchronizeCoarseToFineOnlyInGhostZone(int ghostLev, const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh, int patchId, const DataArrayDoubleCollection *coarse, DataArrayDoubleCollection *fine)
142 {
143   if(!fine || !coarse)
144     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeCoarseToFineOnlyInGhostZone : the input DataArrayDouble collections must be non NULL !");
145   std::size_t sz(coarse->_arrs.size());
146   if(fine->_arrs.size()!=sz)
147     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeCoarseToFineOnlyInGhostZone : the input DataArrayDouble collection must have the same size !");
148   for(std::size_t i=0;i<sz;i++)
149     fatherOfFineMesh->fillCellFieldOnPatchOnlyOnGhostZone(patchId,coarse->_arrs[i],fine->_arrs[i],ghostLev);
150 }
151
152 void DataArrayDoubleCollection::synchronizeMyGhostZoneUsing(int ghostLev, const DataArrayDoubleCollection& other, const MEDCouplingCartesianAMRPatch *thisp, const MEDCouplingCartesianAMRPatch *otherp, const MEDCouplingCartesianAMRMeshGen *father) const
153 {
154   DataArrayDoubleCollection *thisNC(const_cast<DataArrayDoubleCollection *>(this));
155   std::size_t sz(_arrs.size());
156   if(other._arrs.size()!=sz)
157     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::synchronizeMyGhostZoneUsing : sizes of collections must match !");
158   for(std::size_t i=0;i<sz;i++)
159     father->fillCellFieldOnPatchOnlyOnGhostZoneWith(ghostLev,thisp,otherp,thisNC->_arrs[i],other._arrs[i]);
160 }
161
162 void DataArrayDoubleCollection::synchronizeMyGhostZoneUsingExt(int ghostLev, const DataArrayDoubleCollection& other, const MEDCouplingCartesianAMRPatch *thisp, const MEDCouplingCartesianAMRPatch *otherp) const
163 {
164   DataArrayDoubleCollection *thisNC(const_cast<DataArrayDoubleCollection *>(this));
165   std::size_t sz(_arrs.size());
166   if(other._arrs.size()!=sz)
167     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::synchronizeMyGhostZoneUsingExt : sizes of collections must match !");
168   for(std::size_t i=0;i<sz;i++)
169     MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoExt(ghostLev,thisp,otherp,thisNC->_arrs[i],other._arrs[i]);
170 }
171
172 DataArrayDoubleCollection::DataArrayDoubleCollection(const std::vector< std::pair<std::string,int> >& fieldNames):_arrs(fieldNames.size())
173 {
174   std::size_t sz(fieldNames.size());
175   std::vector<std::string> names(sz);
176   for(std::size_t i=0;i<sz;i++)
177     {
178       const std::pair<std::string,int>& info(fieldNames[i]);
179       _arrs[i]=DataArrayDouble::New();
180       _arrs[i]->alloc(0,info.second);
181       _arrs[i]->setName(info.first);
182       names[i]=info.second;
183     }
184   CheckDiscriminantNames(names);
185 }
186
187 std::size_t DataArrayDoubleCollection::getHeapMemorySizeWithoutChildren() const
188 {
189   std::size_t ret(sizeof(DataArrayDoubleCollection));
190   ret+=_arrs.capacity()*sizeof(MEDCouplingAutoRefCountObjectPtr<DataArrayDouble>);
191   return ret;
192 }
193
194 std::vector<const BigMemoryObject *> DataArrayDoubleCollection::getDirectChildren() const
195 {
196   std::vector<const BigMemoryObject *> ret;
197   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> >::const_iterator it=_arrs.begin();it!=_arrs.end();it++)
198     {
199       const DataArrayDouble *pt(*it);
200       if(pt)
201         ret.push_back(pt);
202     }
203   return ret;
204 }
205
206 void DataArrayDoubleCollection::updateTime() const
207 {
208   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> >::const_iterator it=_arrs.begin();it!=_arrs.end();it++)
209     {
210       const DataArrayDouble *pt(*it);
211       if(pt)
212         updateTimeWith(*pt);
213     }
214 }
215
216 void DataArrayDoubleCollection::CheckDiscriminantNames(const std::vector<std::string>& names)
217 {
218   std::set<std::string> s(names.begin(),names.end());
219   if(s.size()!=names.size())
220     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::CheckDiscriminantNames : The names of fields must be different each other ! It is not the case !");
221 }
222
223 MEDCouplingGridCollection *MEDCouplingGridCollection::New(const std::vector<const MEDCouplingCartesianAMRMeshGen *>& ms, const std::vector< std::pair<std::string,int> >& fieldNames)
224 {
225   return new MEDCouplingGridCollection(ms,fieldNames);
226 }
227
228 void MEDCouplingGridCollection::alloc(int ghostLev)
229 {
230   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
231     {
232       int nbTuples((*it).first->getNumberOfCellsAtCurrentLevelGhost(ghostLev));
233       DataArrayDoubleCollection *dadc((*it).second);
234       if(dadc)
235         dadc->allocTuples(nbTuples);
236       else
237         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::alloc : internal error !");
238     }
239 }
240
241 void MEDCouplingGridCollection::dealloc()
242 {
243   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
244     {
245       DataArrayDoubleCollection *dadc((*it).second);
246       if(dadc)
247         dadc->dellocTuples();
248       else
249         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::dealloc : internal error !");
250     }
251 }
252
253 void MEDCouplingGridCollection::spillInfoOnComponents(const std::vector< std::vector<std::string> >& compNames)
254 {
255   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
256     (*it).second->spillInfoOnComponents(compNames);
257 }
258
259 bool MEDCouplingGridCollection::presenceOf(const MEDCouplingCartesianAMRMeshGen *m, int& pos) const
260 {
261   int ret(0);
262   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++,ret++)
263     {
264       if((*it).first==m)
265         {
266           pos=ret;
267           return true;
268         }
269     }
270   return false;
271 }
272
273 const DataArrayDoubleCollection& MEDCouplingGridCollection::getFieldsAt(int pos) const
274 {
275   if(pos<0 || pos>(int)_map_of_dadc.size())
276     throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::getFieldsAt : invalid pos given in input ! Must be in [0,size) !");
277   return *_map_of_dadc[pos].second;
278 }
279
280 void MEDCouplingGridCollection::SynchronizeFineToCoarse(int ghostLev, const MEDCouplingGridCollection *fine, const MEDCouplingGridCollection *coarse)
281 {
282   if(!fine || !coarse)
283     throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeFineToCoarse : one or more input pointer is NULL !");
284   const std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >& mf(fine->_map_of_dadc);
285   const std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >& mc(coarse->_map_of_dadc);
286   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=mf.begin();it!=mf.end();it++)
287     {
288       const MEDCouplingCartesianAMRMeshGen *fineMesh((*it).first);
289       const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh(fineMesh->getFather());
290       bool found(false);
291       for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it0=mc.begin();it0!=mc.end() && !found;it0++)
292         {
293           if((*it0).first==fatherOfFineMesh)
294             {
295               found=true;
296               int patchId(fatherOfFineMesh->getPatchIdFromChildMesh(fineMesh));
297               const DataArrayDoubleCollection *coarseDaCol((*it0).second);
298               DataArrayDoubleCollection *coarseModified(const_cast<DataArrayDoubleCollection *>(coarseDaCol));//coarse values in DataArrayDouble will be altered
299               DataArrayDoubleCollection::SynchronizeFineToCoarse(ghostLev,fatherOfFineMesh,patchId,(*it).second,coarseModified);
300             }
301         }
302       if(!found)
303         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeFineToCoarse : a fine mesh is orphan regarding given coarse meshes !");
304     }
305 }
306
307 void MEDCouplingGridCollection::SynchronizeCoarseToFine(int ghostLev, const MEDCouplingGridCollection *coarse, const MEDCouplingGridCollection *fine)
308 {
309   if(!fine || !coarse)
310     throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeCoarseToFine : one or more input pointer is NULL !");
311   const std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >& mf(fine->_map_of_dadc);
312   const std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >& mc(coarse->_map_of_dadc);
313   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=mf.begin();it!=mf.end();it++)
314     {
315       const MEDCouplingCartesianAMRMeshGen *fineMesh((*it).first);
316       const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh(fineMesh->getFather());
317       bool found(false);
318       for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it0=mc.begin();it0!=mc.end() && !found;it0++)
319         {
320           if((*it0).first==fatherOfFineMesh)
321             {
322               found=true;
323               int patchId(fatherOfFineMesh->getPatchIdFromChildMesh(fineMesh));
324               const DataArrayDoubleCollection *fineDaCol((*it).second);
325               DataArrayDoubleCollection *fineModified(const_cast<DataArrayDoubleCollection *>(fineDaCol));//fine values in DataArrayDouble will be altered
326               DataArrayDoubleCollection::SynchronizeCoarseToFine(ghostLev,fatherOfFineMesh,patchId,(*it0).second,fineModified);
327             }
328         }
329       if(!found)
330         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeCoarseToFine : a fine mesh is orphan regarding given coarse meshes !");
331     }
332 }
333
334 /*!
335  * All the pairs in \a ps must share the same father. If not call synchronizeFineEachOtherExt instead.
336  *
337  * \sa synchronizeFineEachOtherExt
338  */
339 void MEDCouplingGridCollection::synchronizeFineEachOther(int ghostLev, const std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >& ps) const
340 {
341   for(std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >::const_iterator it=ps.begin();it!=ps.end();it++)
342     {
343       int p1,p2;
344       if(!presenceOf((*it).first->getMesh(),p1))
345         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::synchronizeFineEachOther : internal error #1 !");
346       if(!presenceOf((*it).second->getMesh(),p2))
347         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::synchronizeFineEachOther : internal error #2 !");
348       const DataArrayDoubleCollection& col1(getFieldsAt(p1));
349       const DataArrayDoubleCollection& col2(getFieldsAt(p2));
350       col1.synchronizeMyGhostZoneUsing(ghostLev,col2,(*it).first,(*it).second,(*it).first->getMesh()->getFather());
351     }
352 }
353
354 /*!
355  * This method is a generalization of synchronizeFineEachOther because elements in pairs are \b not sharing the same father but are neighbors nevertheless.
356  *
357  * \sa synchronizeFineEachOther
358  */
359 void MEDCouplingGridCollection::synchronizeFineEachOtherExt(int ghostLev, const std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >& ps) const
360 {
361   for(std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >::const_iterator it=ps.begin();it!=ps.end();it++)
362     {
363       int p1,p2;
364       if(!presenceOf((*it).first->getMesh(),p1))
365         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::synchronizeFineEachOtherExt : internal error #1 !");
366       if(!presenceOf((*it).second->getMesh(),p2))
367         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::synchronizeFineEachOtherExt : internal error #2 !");
368       const DataArrayDoubleCollection& col1(getFieldsAt(p1));
369       const DataArrayDoubleCollection& col2(getFieldsAt(p2));
370       col1.synchronizeMyGhostZoneUsingExt(ghostLev,col2,(*it).first,(*it).second);
371     }
372 }
373
374 /*!
375  * The pairs returned share the same direct father. The number of returned elements must be even.
376  */
377 std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > MEDCouplingGridCollection::findNeighbors(int ghostLev) const
378 {
379   std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > ret;
380   std::map<const MEDCouplingCartesianAMRMeshGen *,std::vector< const MEDCouplingCartesianAMRMeshGen * > > m;
381   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
382     {
383       const MEDCouplingCartesianAMRMeshGen *fineMesh((*it).first);
384       const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh(fineMesh->getFather());
385       m[fatherOfFineMesh].push_back(fineMesh);
386     }
387   for(std::map<const MEDCouplingCartesianAMRMeshGen *,std::vector< const MEDCouplingCartesianAMRMeshGen * > >::const_iterator it0=m.begin();it0!=m.end();it0++)
388     {
389       for(std::vector<const MEDCouplingCartesianAMRMeshGen *>::const_iterator it1=(*it0).second.begin();it1!=(*it0).second.end();it1++)
390         {
391           int patchId((*it0).first->getPatchIdFromChildMesh(*it1));
392           std::vector<int> neighs((*it0).first->getPatchIdsInTheNeighborhoodOf(patchId,ghostLev));
393           const MEDCouplingCartesianAMRPatch *pRef((*it0).first->getPatch(patchId));
394           for(std::vector<int>::const_iterator it2=neighs.begin();it2!=neighs.end();it2++)
395             {
396               const MEDCouplingCartesianAMRPatch *pLoc((*it0).first->getPatch(*it2));
397               ret.push_back(std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *>(pRef,pLoc));
398             }
399         }
400     }
401   if(ret.size()%2!=0)
402     throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::findNeighbors : something is wrong ! The number of neighbor pairs must be %2 ==0 !");
403   return ret;
404 }
405
406 void MEDCouplingGridCollection::SynchronizeCoarseToFineOnlyInGhostZone(int ghostLev, const MEDCouplingGridCollection *coarse, const MEDCouplingGridCollection *fine)
407 {
408   if(!fine || !coarse)
409     throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeCoarseToFineOnlyInGhostZone : one or more input pointer is NULL !");
410   const std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >& mf(fine->_map_of_dadc);
411   const std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >& mc(coarse->_map_of_dadc);
412   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=mf.begin();it!=mf.end();it++)
413     {
414       const MEDCouplingCartesianAMRMeshGen *fineMesh((*it).first);
415       const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh(fineMesh->getFather());
416       bool found(false);
417       for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it0=mc.begin();it0!=mc.end() && !found;it0++)
418         {
419           if((*it0).first==fatherOfFineMesh)
420             {
421               found=true;
422               int patchId(fatherOfFineMesh->getPatchIdFromChildMesh(fineMesh));
423               const DataArrayDoubleCollection *fineDaCol((*it).second);
424               DataArrayDoubleCollection *fineModified(const_cast<DataArrayDoubleCollection *>(fineDaCol));//fine values in DataArrayDouble will be altered
425               DataArrayDoubleCollection::SynchronizeCoarseToFineOnlyInGhostZone(ghostLev,fatherOfFineMesh,patchId,(*it0).second,fineModified);
426             }
427         }
428       if(!found)
429         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeCoarseToFineOnlyInGhostZone : a fine mesh is orphan regarding given coarse meshes !");
430     }
431 }
432
433 void MEDCouplingGridCollection::fillIfInTheProgenyOf(const std::string& fieldName, const MEDCouplingCartesianAMRMeshGen *head, std::vector<const DataArrayDouble *>& recurseArrs) const
434 {
435   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
436     {
437       const MEDCouplingCartesianAMRMeshGen *a((*it).first);
438       if(head==a || head->isObjectInTheProgeny(a))
439         {
440           const DataArrayDoubleCollection *gc((*it).second);
441           recurseArrs.push_back(gc->getFieldWithName(fieldName));
442         }
443     }
444 }
445
446 MEDCouplingGridCollection::MEDCouplingGridCollection(const std::vector<const MEDCouplingCartesianAMRMeshGen *>& ms, const std::vector< std::pair<std::string,int> >& fieldNames):_map_of_dadc(ms.size())
447 {
448   std::size_t sz(ms.size());
449   for(std::size_t i=0;i<sz;i++)
450     {
451       if(!ms[i])
452         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection constructor : presence of NULL MEDCouplingCartesianAMRMeshGen instance !");
453       _map_of_dadc[i].first=ms[i];
454       _map_of_dadc[i].second=DataArrayDoubleCollection::New(fieldNames);
455     }
456 }
457
458 std::size_t MEDCouplingGridCollection::getHeapMemorySizeWithoutChildren() const
459 {
460   std::size_t ret(sizeof(MEDCouplingGridCollection));
461   ret+=_map_of_dadc.capacity()*sizeof(std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> >);
462   return ret;
463 }
464
465 std::vector<const BigMemoryObject *> MEDCouplingGridCollection::getDirectChildren() const
466 {
467   std::vector<const BigMemoryObject *> ret;
468   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
469     {
470       const DataArrayDoubleCollection *col((*it).second);
471       if(col)
472         ret.push_back(col);
473     }
474   return ret;
475 }
476
477 void MEDCouplingGridCollection::updateTime() const
478 {
479   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
480     {
481       const MEDCouplingCartesianAMRMeshGen *a((*it).first);
482       if(a)
483         updateTimeWith(*a);
484       const DataArrayDoubleCollection *b((*it).second);
485       if(b)
486         updateTimeWith(*b);
487     }
488 }
489
490 /*!
491  * 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.
492  */
493 MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::New(MEDCouplingCartesianAMRMesh *gf, const std::vector< std::pair<std::string,int> >& fieldNames, int ghostLev)
494 {
495   return new MEDCouplingAMRAttribute(gf,fieldNames,ghostLev);
496 }
497
498 MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::New(MEDCouplingCartesianAMRMesh *gf, const std::vector< std::pair<std::string, std::vector<std::string> > >& fieldNames, int ghostLev)
499 {
500   std::size_t sz(fieldNames.size());
501   std::vector< std::pair<std::string,int> > fieldNames2(sz);
502   std::vector< std::vector<std::string> > compNames(sz);
503   for(std::size_t i=0;i<sz;i++)
504     {
505       fieldNames2[i].first=fieldNames[i].first;
506       fieldNames2[i].second=(int)fieldNames[i].second.size();
507       compNames[i]=fieldNames[i].second;
508     }
509   MEDCouplingAutoRefCountObjectPtr<MEDCouplingAMRAttribute> ret(New(gf,fieldNames2,ghostLev));
510   ret->spillInfoOnComponents(compNames);
511   return ret.retn();
512 }
513
514 /*!
515  * Assign the info on components for all DataArrayDouble instance recursively stored in \a this.
516  * 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.
517  * The second dim of \a compNames represent the component names component per component corresponding to the field. The size of this 2nd dimension has
518  * to perfectly fit with those specified in MEDCouplingAMRAttribute::New.
519  */
520 void MEDCouplingAMRAttribute::spillInfoOnComponents(const std::vector< std::vector<std::string> >& compNames)
521 {
522   _tlc.checkConst();
523   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::iterator it=_levs.begin();it!=_levs.end();it++)
524     (*it)->spillInfoOnComponents(compNames);
525 }
526
527 /*!
528  * This method returns all DataArrayDouble instances lying on the specified mesh \a mesh.
529  * If \a mesh is not part of the progeny of god father object given at construction of \a this an exception will be thrown.
530  *
531  * \return std::vector<DataArrayDouble *> - DataArrayDouble instances to be deallocated by the caller (using decrRef).
532  * \sa retrieveFieldOn
533  */
534 std::vector<DataArrayDouble *> MEDCouplingAMRAttribute::retrieveFieldsOn(MEDCouplingCartesianAMRMeshGen *mesh) const
535 {
536   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
537     {
538       int tmp(-1);
539       if((*it)->presenceOf(mesh,tmp))
540         {
541           const DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp));
542           return ddc.retrieveFields();
543         }
544     }
545   throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::retrieveFieldsOn : the mesh specified is not in the progeny of this !");
546 }
547
548 /*!
549  * \sa retrieveFieldsOn
550  */
551 const DataArrayDouble *MEDCouplingAMRAttribute::getFieldOn(MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) const
552 {
553   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
554     {
555       int tmp(-1);
556       if((*it)->presenceOf(mesh,tmp))
557         {
558           const DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp));
559           return ddc.getFieldWithName(fieldName);
560         }
561     }
562   throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::retrieveFieldOn : the mesh specified is not in the progeny of this !");
563 }
564
565 /*!
566  * This method returns a field on an unstructured mesh the most refined as possible without overlap.
567  * Ghost part are not visible here.
568  *
569  * \return MEDCouplingFieldDouble * - a field on cells that the caller has to deal with (deallocate it).
570  */
571 MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnRecurseWithoutOverlapWithoutGhost(MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) const
572 {
573   std::vector<const DataArrayDouble *> recurseArrs;
574   std::size_t lev(0);
575   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++,lev++)
576     {
577       int tmp(-1);
578       if((*it)->presenceOf(mesh,tmp))
579         {
580           const DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp));
581           recurseArrs.push_back(ddc.getFieldWithName(fieldName));
582           break;
583         }
584     }
585   lev++;
586   for(std::size_t i=lev;i<_levs.size();i++)
587     {
588       const MEDCouplingGridCollection *gc(_levs[i]);
589       gc->fillIfInTheProgenyOf(fieldName,mesh,recurseArrs);
590     }
591   return mesh->buildCellFieldOnRecurseWithoutOverlapWithoutGhost(_ghost_lev,recurseArrs);
592 }
593
594 /*!
595  * This method builds a newly created field on cell just lying on mesh \a mesh without its eventual refinement.
596  * The output field also displays ghost cells.
597  *
598  * \return MEDCouplingFieldDouble * - a field on cells that the caller has to deal with (deallocate it).
599  *
600  */
601 MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnWithGhost(MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) const
602 {
603   const DataArrayDouble *arr(0);
604   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
605     {
606       int tmp(-1);
607       if((*it)->presenceOf(mesh,tmp))
608         {
609           const DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp));
610           arr=ddc.getFieldWithName(fieldName);
611         }
612     }
613   if(!arr)
614     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::buildCellFieldOnWithGhost : the mesh specified is not in the progeny of this !");
615   MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> im(mesh->getImageMesh()->buildWithGhost(_ghost_lev));
616   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS));
617   ret->setMesh(im);
618   ret->setArray(const_cast<DataArrayDouble *>(arr));
619   ret->setName(arr->getName());
620   return ret.retn();
621 }
622
623 /*!
624  * This method synchronizes from fine to coarse direction arrays. This method makes the hypothesis that \a this has been allocated before using
625  * MEDCouplingAMRAttribute::alloc method.
626  */
627 void MEDCouplingAMRAttribute::synchronizeFineToCoarse()
628 {
629   if(_levs.empty())
630     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineToCoarse : not any levels in this !");
631   std::size_t sz(_levs.size());
632   //
633   while(sz>1)
634     {
635       sz--;
636       const MEDCouplingGridCollection *fine(_levs[sz]),*coarse(_levs[sz-1]);
637       MEDCouplingGridCollection::SynchronizeFineToCoarse(_ghost_lev,fine,coarse);
638     }
639 }
640
641 /*!
642  * 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
643  * MEDCouplingAMRAttribute::alloc method.
644  */
645 void MEDCouplingAMRAttribute::synchronizeCoarseToFine()
646 {
647   if(_levs.empty())
648     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeCoarseToFine : not any levels in this !");
649   std::size_t sz(_levs.size());
650   //
651   for(std::size_t i=1;i<sz;i++)
652     {
653       const MEDCouplingGridCollection *fine(_levs[i]),*coarse(_levs[i-1]);
654       MEDCouplingGridCollection::SynchronizeCoarseToFine(_ghost_lev,coarse,fine);
655     }
656 }
657
658 /*!
659  * This method performs coarse to fine spread only in the ghost zone.
660  * This method makes the hypothesis that \a this has been allocated before using MEDCouplingAMRAttribute::alloc method.
661  * So if \a _ghost_lev == 0 this method has no effect.
662  */
663 void MEDCouplingAMRAttribute::synchronizeCoarseToFineOnlyInGhostZone()
664 {
665   if(_levs.empty())
666     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeCoarseToFineOnlyInGhostZone : not any levels in this !");
667   std::size_t sz(_levs.size());
668   //
669   for(std::size_t i=1;i<sz;i++)
670     {
671       const MEDCouplingGridCollection *fine(_levs[i]),*coarse(_levs[i-1]);
672       MEDCouplingGridCollection::SynchronizeCoarseToFineOnlyInGhostZone(_ghost_lev,coarse,fine);
673     }
674 }
675
676 /*!
677  * This method synchronizes fine each other only in the ghost zone.
678  */
679 void MEDCouplingAMRAttribute::synchronizeFineEachOtherInGhostZone()
680 {
681   if(_levs.empty())
682     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineEachOther : not any levels in this !");
683   std::size_t sz(_levs.size());
684   //
685   for(std::size_t i=1;i<sz;i++)
686     {
687       const MEDCouplingGridCollection *fine(_levs[i]);
688       if(!fine)
689         throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineEachOtherInGhostZone : presence of a NULL element !");
690       fine->synchronizeFineEachOther(_ghost_lev,_neighbors[i]);
691     }
692   // cross lev
693   for(std::size_t i=1;i<sz;i++)
694     {
695       const MEDCouplingGridCollection *fine(_levs[i]);
696       fine->synchronizeFineEachOtherExt(_ghost_lev,_cross_lev_neighbors[i]);
697     }
698 }
699
700 /*!
701  * This method allocates all DataArrayDouble instances stored recursively in \a this.
702  *
703  * \sa dealloc
704  */
705 void MEDCouplingAMRAttribute::alloc()
706 {
707   _tlc.resetState();
708   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::iterator it=_levs.begin();it!=_levs.end();it++)
709     {
710       MEDCouplingGridCollection *elt(*it);
711       if(elt)
712         elt->alloc(_ghost_lev);
713       else
714         throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::alloc : internal error !");
715     }
716 }
717
718 /*!
719  * This method deallocates all DataArrayDouble instances stored recursively in \a this.
720  * \sa alloc
721  */
722 void MEDCouplingAMRAttribute::dealloc()
723 {
724   _tlc.checkConst();
725   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::iterator it=_levs.begin();it!=_levs.end();it++)
726     {
727       MEDCouplingGridCollection *elt(*it);
728       if(elt)
729         elt->dealloc();
730       else
731         throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::dealloc : internal error !");
732     }
733 }
734
735 bool MEDCouplingAMRAttribute::changeGodFather(MEDCouplingCartesianAMRMesh *gf)
736 {
737   bool ret(MEDCouplingDataForGodFather::changeGodFather(gf));
738   return ret;
739 }
740
741 std::size_t MEDCouplingAMRAttribute::getHeapMemorySizeWithoutChildren() const
742 {
743   std::size_t ret(sizeof(MEDCouplingAMRAttribute));
744   ret+=_levs.capacity()*sizeof(MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection>);
745   return ret;
746 }
747
748 std::vector<const BigMemoryObject *> MEDCouplingAMRAttribute::getDirectChildren() const
749 {
750   std::vector<const BigMemoryObject *> ret;
751   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
752     {
753       const MEDCouplingGridCollection *elt(*it);
754       if(elt)
755         ret.push_back(elt);
756     }
757   return ret;
758 }
759
760 void MEDCouplingAMRAttribute::updateTime() const
761 {//tony
762 }
763
764 MEDCouplingAMRAttribute::MEDCouplingAMRAttribute(MEDCouplingCartesianAMRMesh *gf, const std::vector< std::pair<std::string,int> >& fieldNames, int ghostLev):MEDCouplingDataForGodFather(gf),_ghost_lev(ghostLev)
765 {
766   //gf non empty, checked by constructor
767   int maxLev(gf->getMaxNumberOfLevelsRelativeToThis());
768   _levs.resize(maxLev);
769   for(int i=0;i<maxLev;i++)
770     {
771       std::vector<MEDCouplingCartesianAMRPatchGen *> patches(gf->retrieveGridsAt(i));
772       std::size_t sz(patches.size());
773       std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatchGen> > patchesSafe(patches.size());
774       for(std::size_t j=0;j<sz;j++)
775         patchesSafe[j]=patches[j];
776       std::vector<const MEDCouplingCartesianAMRMeshGen *> ms(sz);
777       for(std::size_t j=0;j<sz;j++)
778         {
779           ms[j]=patches[j]->getMesh();
780         }
781       _levs[i]=MEDCouplingGridCollection::New(ms,fieldNames);
782     }
783   // updates cross levels neighbors
784   _neighbors.resize(_levs.size());
785   _cross_lev_neighbors.resize(_levs.size());
786   if(_levs.empty())
787     throw INTERP_KERNEL::Exception("constructor of MEDCouplingAMRAttribute : not any levels in this !");
788   std::size_t sz(_levs.size());
789   for(std::size_t i=1;i<sz;i++)
790     {
791       const MEDCouplingGridCollection *fine(_levs[i]);
792       if(!fine)
793         throw INTERP_KERNEL::Exception("constructor of MEDCouplingAMRAttribute : presence of a NULL element !");
794       _neighbors[i]=fine->findNeighbors(_ghost_lev);
795       if(i!=sz-1)
796         {
797           for(std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >::const_iterator it=_neighbors[i].begin();it!=_neighbors[i].end();it++)
798             {
799               std::vector< std::vector < std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > > neighs2(MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOf(_ghost_lev,(*it).first,(*it).second));
800               std::size_t fullLev(i+neighs2.size());
801               if(fullLev>=sz)
802                 throw INTERP_KERNEL::Exception("constructor of MEDCouplingAMRAttribute : internal error ! something is wrong in computation of cross level neighbors !");
803               std::size_t ii(i+1);
804               for(std::vector< std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > >::const_iterator it0=neighs2.begin();it0!=neighs2.end();it0++,ii++)
805                 _cross_lev_neighbors[ii].insert(_cross_lev_neighbors[ii].end(),(*it0).begin(),(*it0).end());
806             }
807         }
808     }
809 }