Salome HOME
stash 4
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingAMRAttribute.cxx
1 // Copyright (C) 2007-2014  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay
20
21 #include "MEDCouplingAMRAttribute.hxx"
22 #include "MEDCouplingFieldDouble.hxx"
23 #include "MEDCouplingMemArray.hxx"
24 #include "MEDCouplingIMesh.hxx"
25
26 #include <sstream>
27
28 using namespace ParaMEDMEM;
29
30 DataArrayDoubleCollection *DataArrayDoubleCollection::New(const std::vector< std::pair<std::string,int> >& fieldNames)
31 {
32   return new DataArrayDoubleCollection(fieldNames);
33 }
34
35 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 DataArrayDoubleCollection::DataArrayDoubleCollection(const std::vector< std::pair<std::string,int> >& fieldNames):_arrs(fieldNames.size())
153 {
154   std::size_t sz(fieldNames.size());
155   std::vector<std::string> names(sz);
156   for(std::size_t i=0;i<sz;i++)
157     {
158       const std::pair<std::string,int>& info(fieldNames[i]);
159       _arrs[i]=DataArrayDouble::New();
160       _arrs[i]->alloc(0,info.second);
161       _arrs[i]->setName(info.first);
162       names[i]=info.second;
163     }
164   CheckDiscriminantNames(names);
165 }
166
167 std::size_t DataArrayDoubleCollection::getHeapMemorySizeWithoutChildren() const
168 {
169   std::size_t ret(sizeof(DataArrayDoubleCollection));
170   ret+=_arrs.capacity()*sizeof(MEDCouplingAutoRefCountObjectPtr<DataArrayDouble>);
171   return ret;
172 }
173
174 std::vector<const BigMemoryObject *> DataArrayDoubleCollection::getDirectChildren() const
175 {
176   std::vector<const BigMemoryObject *> ret;
177   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> >::const_iterator it=_arrs.begin();it!=_arrs.end();it++)
178     {
179       const DataArrayDouble *pt(*it);
180       if(pt)
181         ret.push_back(pt);
182     }
183   return ret;
184 }
185
186 void DataArrayDoubleCollection::updateTime() const
187 {
188   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> >::const_iterator it=_arrs.begin();it!=_arrs.end();it++)
189     {
190       const DataArrayDouble *pt(*it);
191       if(pt)
192         updateTimeWith(*pt);
193     }
194 }
195
196 void DataArrayDoubleCollection::CheckDiscriminantNames(const std::vector<std::string>& names)
197 {
198   std::set<std::string> s(names.begin(),names.end());
199   if(s.size()!=names.size())
200     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::CheckDiscriminantNames : The names of fields must be different each other ! It is not the case !");
201 }
202
203 MEDCouplingGridCollection *MEDCouplingGridCollection::New(const std::vector<const MEDCouplingCartesianAMRMeshGen *>& ms, const std::vector< std::pair<std::string,int> >& fieldNames)
204 {
205   return new MEDCouplingGridCollection(ms,fieldNames);
206 }
207
208 void MEDCouplingGridCollection::alloc(int ghostLev)
209 {
210   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
211     {
212       int nbTuples((*it).first->getNumberOfCellsAtCurrentLevelGhost(ghostLev));
213       DataArrayDoubleCollection *dadc((*it).second);
214       if(dadc)
215         dadc->allocTuples(nbTuples);
216       else
217         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::alloc : internal error !");
218     }
219 }
220
221 void MEDCouplingGridCollection::dealloc()
222 {
223   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
224     {
225       DataArrayDoubleCollection *dadc((*it).second);
226       if(dadc)
227         dadc->dellocTuples();
228       else
229         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::dealloc : internal error !");
230     }
231 }
232
233 void MEDCouplingGridCollection::spillInfoOnComponents(const std::vector< std::vector<std::string> >& compNames)
234 {
235   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
236     (*it).second->spillInfoOnComponents(compNames);
237 }
238
239 bool MEDCouplingGridCollection::presenceOf(const MEDCouplingCartesianAMRMeshGen *m, int& pos) const
240 {
241   int ret(0);
242   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++,ret++)
243     {
244       if((*it).first==m)
245         {
246           pos=ret;
247           return true;
248         }
249     }
250   return false;
251 }
252
253 const DataArrayDoubleCollection& MEDCouplingGridCollection::retrieveFieldsAt(int pos) const
254 {
255   if(pos<0 || pos>(int)_map_of_dadc.size())
256     throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::retrieveFieldsAt : invalid pos given in input ! Must be in [0,size) !");
257   return *_map_of_dadc[pos].second;
258 }
259
260 void MEDCouplingGridCollection::SynchronizeFineToCoarse(int ghostLev, const MEDCouplingGridCollection *fine, const MEDCouplingGridCollection *coarse)
261 {
262   if(!fine || !coarse)
263     throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeFineToCoarse : one or more input pointer is NULL !");
264   const std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >& mf(fine->_map_of_dadc);
265   const std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >& mc(coarse->_map_of_dadc);
266   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=mf.begin();it!=mf.end();it++)
267     {
268       const MEDCouplingCartesianAMRMeshGen *fineMesh((*it).first);
269       const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh(fineMesh->getFather());
270       bool found(false);
271       for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it0=mc.begin();it0!=mc.end() && !found;it0++)
272         {
273           if((*it0).first==fatherOfFineMesh)
274             {
275               found=true;
276               int patchId(fatherOfFineMesh->getPatchIdFromChildMesh(fineMesh));
277               const DataArrayDoubleCollection *coarseDaCol((*it0).second);
278               DataArrayDoubleCollection *coarseModified(const_cast<DataArrayDoubleCollection *>(coarseDaCol));//coarse values in DataArrayDouble will be altered
279               DataArrayDoubleCollection::SynchronizeFineToCoarse(ghostLev,fatherOfFineMesh,patchId,(*it).second,coarseModified);
280             }
281         }
282       if(!found)
283         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeFineToCoarse : a fine mesh is orphan regarding given coarse meshes !");
284     }
285 }
286
287 void MEDCouplingGridCollection::SynchronizeCoarseToFine(int ghostLev, const MEDCouplingGridCollection *coarse, const MEDCouplingGridCollection *fine)
288 {
289   if(!fine || !coarse)
290     throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeCoarseToFine : one or more input pointer is NULL !");
291   const std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >& mf(fine->_map_of_dadc);
292   const std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >& mc(coarse->_map_of_dadc);
293   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=mf.begin();it!=mf.end();it++)
294     {
295       const MEDCouplingCartesianAMRMeshGen *fineMesh((*it).first);
296       const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh(fineMesh->getFather());
297       bool found(false);
298       for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it0=mc.begin();it0!=mc.end() && !found;it0++)
299         {
300           if((*it0).first==fatherOfFineMesh)
301             {
302               found=true;
303               int patchId(fatherOfFineMesh->getPatchIdFromChildMesh(fineMesh));
304               const DataArrayDoubleCollection *fineDaCol((*it).second);
305               DataArrayDoubleCollection *fineModified(const_cast<DataArrayDoubleCollection *>(fineDaCol));//fine values in DataArrayDouble will be altered
306               DataArrayDoubleCollection::SynchronizeCoarseToFine(ghostLev,fatherOfFineMesh,patchId,(*it0).second,fineModified);
307             }
308         }
309       if(!found)
310         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeCoarseToFine : a fine mesh is orphan regarding given coarse meshes !");
311     }
312 }
313
314 void MEDCouplingGridCollection::synchronizeFineEachOther(int ghostLev) const
315 {
316   std::map<const MEDCouplingCartesianAMRMeshGen *,std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *, const DataArrayDoubleCollection *> > > m;
317   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
318     {
319       const MEDCouplingCartesianAMRMeshGen *fineMesh((*it).first);
320       const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh(fineMesh->getFather());
321       m[fatherOfFineMesh].push_back(std::pair<const MEDCouplingCartesianAMRMeshGen *, const DataArrayDoubleCollection *>(fineMesh,(*it).second));
322     }
323   for(std::map<const MEDCouplingCartesianAMRMeshGen *,std::vector<std::pair<const MEDCouplingCartesianAMRMeshGen *, const DataArrayDoubleCollection *> > >::const_iterator it0=m.begin();it0!=m.end();it0++)
324     {
325       std::size_t sz((*it0).second.size());
326       std::vector<const MEDCouplingCartesianAMRMeshGen *> v0(sz);
327       std::vector<DataArrayDoubleCollection *> v1(sz);
328       for(std::size_t i=0;i<sz;i++)
329         {
330           v0[i]=(*it0).second[i].first;
331           const DataArrayDoubleCollection *tmp((*it0).second[i].second);
332           v1[i]=const_cast<DataArrayDoubleCollection *>(tmp);
333         }
334       for(std::vector<std::pair<const MEDCouplingCartesianAMRMeshGen *, const DataArrayDoubleCollection *> >::const_iterator it1=(*it0).second.begin();it1!=(*it0).second.end();it1++)
335         {
336           int patchId((*it0).first->getPatchIdFromChildMesh((*it1).first));
337           DataArrayDoubleCollection::SynchronizeFineEachOther(patchId,ghostLev,(*it0).first,v0,v1);
338         }
339     }
340 }
341
342 void MEDCouplingGridCollection::SynchronizeCoarseToFineOnlyInGhostZone(int ghostLev, const MEDCouplingGridCollection *coarse, const MEDCouplingGridCollection *fine)
343 {
344   if(!fine || !coarse)
345     throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeCoarseToFineOnlyInGhostZone : one or more input pointer is NULL !");
346   const std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >& mf(fine->_map_of_dadc);
347   const std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >& mc(coarse->_map_of_dadc);
348   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=mf.begin();it!=mf.end();it++)
349     {
350       const MEDCouplingCartesianAMRMeshGen *fineMesh((*it).first);
351       const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh(fineMesh->getFather());
352       bool found(false);
353       for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it0=mc.begin();it0!=mc.end() && !found;it0++)
354         {
355           if((*it0).first==fatherOfFineMesh)
356             {
357               found=true;
358               int patchId(fatherOfFineMesh->getPatchIdFromChildMesh(fineMesh));
359               const DataArrayDoubleCollection *fineDaCol((*it).second);
360               DataArrayDoubleCollection *fineModified(const_cast<DataArrayDoubleCollection *>(fineDaCol));//fine values in DataArrayDouble will be altered
361               DataArrayDoubleCollection::SynchronizeCoarseToFineOnlyInGhostZone(ghostLev,fatherOfFineMesh,patchId,(*it0).second,fineModified);
362             }
363         }
364       if(!found)
365         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeCoarseToFineOnlyInGhostZone : a fine mesh is orphan regarding given coarse meshes !");
366     }
367 }
368
369 void MEDCouplingGridCollection::fillIfInTheProgenyOf(const std::string& fieldName, const MEDCouplingCartesianAMRMeshGen *head, std::vector<const DataArrayDouble *>& recurseArrs) const
370 {
371   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
372     {
373       const MEDCouplingCartesianAMRMeshGen *a((*it).first);
374       if(head==a || head->isObjectInTheProgeny(a))
375         {
376           const DataArrayDoubleCollection *gc((*it).second);
377           recurseArrs.push_back(gc->getFieldWithName(fieldName));
378         }
379     }
380 }
381
382 MEDCouplingGridCollection::MEDCouplingGridCollection(const std::vector<const MEDCouplingCartesianAMRMeshGen *>& ms, const std::vector< std::pair<std::string,int> >& fieldNames):_map_of_dadc(ms.size())
383 {
384   std::size_t sz(ms.size());
385   for(std::size_t i=0;i<sz;i++)
386     {
387       if(!ms[i])
388         throw INTERP_KERNEL::Exception("MEDCouplingGridCollection constructor : presence of NULL MEDCouplingCartesianAMRMeshGen instance !");
389       _map_of_dadc[i].first=ms[i];
390       _map_of_dadc[i].second=DataArrayDoubleCollection::New(fieldNames);
391     }
392 }
393
394 std::size_t MEDCouplingGridCollection::getHeapMemorySizeWithoutChildren() const
395 {
396   std::size_t ret(sizeof(MEDCouplingGridCollection));
397   ret+=_map_of_dadc.capacity()*sizeof(std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> >);
398   return ret;
399 }
400
401 std::vector<const BigMemoryObject *> MEDCouplingGridCollection::getDirectChildren() const
402 {
403   std::vector<const BigMemoryObject *> ret;
404   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
405     {
406       const DataArrayDoubleCollection *col((*it).second);
407       if(col)
408         ret.push_back(col);
409     }
410   return ret;
411 }
412
413 void MEDCouplingGridCollection::updateTime() const
414 {
415   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
416     {
417       const MEDCouplingCartesianAMRMeshGen *a((*it).first);
418       if(a)
419         updateTimeWith(*a);
420       const DataArrayDoubleCollection *b((*it).second);
421       if(b)
422         updateTimeWith(*b);
423     }
424 }
425
426 /*!
427  * 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.
428  */
429 MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::New(MEDCouplingCartesianAMRMesh *gf, const std::vector< std::pair<std::string,int> >& fieldNames)
430 {
431   return new MEDCouplingAMRAttribute(gf,fieldNames);
432 }
433
434 MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::New(MEDCouplingCartesianAMRMesh *gf, const std::vector< std::pair<std::string, std::vector<std::string> > >& fieldNames)
435 {
436   std::size_t sz(fieldNames.size());
437   std::vector< std::pair<std::string,int> > fieldNames2(sz);
438   std::vector< std::vector<std::string> > compNames(sz);
439   for(std::size_t i=0;i<sz;i++)
440     {
441       fieldNames2[i].first=fieldNames[i].first;
442       fieldNames2[i].second=(int)fieldNames[i].second.size();
443       compNames[i]=fieldNames[i].second;
444     }
445   MEDCouplingAutoRefCountObjectPtr<MEDCouplingAMRAttribute> ret(New(gf,fieldNames2));
446   ret->spillInfoOnComponents(compNames);
447   return ret.retn();
448 }
449
450 /*!
451  * Assign the info on components for all DataArrayDouble instance recursively stored in \a this.
452  * 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.
453  * The second dim of \a compNames represent the component names component per component corresponding to the field. The size of this 2nd dimension has
454  * to perfectly fit with those specified in MEDCouplingAMRAttribute::New.
455  */
456 void MEDCouplingAMRAttribute::spillInfoOnComponents(const std::vector< std::vector<std::string> >& compNames)
457 {
458   _tlc.checkConst();
459   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::iterator it=_levs.begin();it!=_levs.end();it++)
460     (*it)->spillInfoOnComponents(compNames);
461 }
462
463 /*!
464  * This method returns all DataArrayDouble instances lying on the specified mesh \a mesh.
465  * If \a mesh is not part of the progeny of god father object given at construction of \a this an exception will be thrown.
466  *
467  * \return std::vector<DataArrayDouble *> - DataArrayDouble instances to be deallocated by the caller (using decrRef).
468  * \sa retrieveFieldOn
469  */
470 std::vector<DataArrayDouble *> MEDCouplingAMRAttribute::retrieveFieldsOn(MEDCouplingCartesianAMRMeshGen *mesh) const
471 {
472   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
473     {
474       int tmp(-1);
475       if((*it)->presenceOf(mesh,tmp))
476         {
477           const DataArrayDoubleCollection& ddc((*it)->retrieveFieldsAt(tmp));
478           return ddc.retrieveFields();
479         }
480     }
481   throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::retrieveFieldsOn : the mesh specified is not in the progeny of this !");
482 }
483
484 /*!
485  * \sa retrieveFieldsOn
486  */
487 const DataArrayDouble *MEDCouplingAMRAttribute::getFieldOn(MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) const
488 {
489   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
490     {
491       int tmp(-1);
492       if((*it)->presenceOf(mesh,tmp))
493         {
494           const DataArrayDoubleCollection& ddc((*it)->retrieveFieldsAt(tmp));
495           return ddc.getFieldWithName(fieldName);
496         }
497     }
498   throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::retrieveFieldOn : the mesh specified is not in the progeny of this !");
499 }
500
501 /*!
502  * This method returns a field on an unstructured mesh the most refined as possible without overlap.
503  * Ghost part are not visible here.
504  *
505  * \return MEDCouplingFieldDouble * - a field on cells that the caller has to deal with (deallocate it).
506  */
507 MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnRecurseWithoutOverlapWithoutGhost(int ghostLev, MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) const
508 {
509   std::vector<const DataArrayDouble *> recurseArrs;
510   std::size_t lev(0);
511   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++,lev++)
512     {
513       int tmp(-1);
514       if((*it)->presenceOf(mesh,tmp))
515         {
516           const DataArrayDoubleCollection& ddc((*it)->retrieveFieldsAt(tmp));
517           recurseArrs.push_back(ddc.getFieldWithName(fieldName));
518           break;
519         }
520     }
521   lev++;
522   for(std::size_t i=lev;i<_levs.size();i++)
523     {
524       const MEDCouplingGridCollection *gc(_levs[i]);
525       gc->fillIfInTheProgenyOf(fieldName,mesh,recurseArrs);
526     }
527   return mesh->buildCellFieldOnRecurseWithoutOverlapWithoutGhost(ghostLev,recurseArrs);
528 }
529
530 /*!
531  * This method builds a newly created field on cell just lying on mesh \a mesh without its eventual refinement.
532  * The output field also displays ghost cells.
533  *
534  * \return MEDCouplingFieldDouble * - a field on cells that the caller has to deal with (deallocate it).
535  *
536  */
537 MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnWithGhost(int ghostLev, MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) const
538 {
539   const DataArrayDouble *arr(0);
540   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
541     {
542       int tmp(-1);
543       if((*it)->presenceOf(mesh,tmp))
544         {
545           const DataArrayDoubleCollection& ddc((*it)->retrieveFieldsAt(tmp));
546           arr=ddc.getFieldWithName(fieldName);
547         }
548     }
549   if(!arr)
550     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::buildCellFieldOnWithGhost : the mesh specified is not in the progeny of this !");
551   MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> im(mesh->getImageMesh()->buildWithGhost(ghostLev));
552   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS));
553   ret->setMesh(im);
554   ret->setArray(const_cast<DataArrayDouble *>(arr));
555   ret->setName(arr->getName());
556   return ret.retn();
557 }
558
559 /*!
560  * This method synchronizes from fine to coarse direction arrays. This method makes the hypothesis that \a this has been allocated before using
561  * MEDCouplingAMRAttribute::alloc method.
562  */
563 void MEDCouplingAMRAttribute::synchronizeFineToCoarse(int ghostLev)
564 {
565   if(_levs.empty())
566     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineToCoarse : not any levels in this !");
567   std::size_t sz(_levs.size());
568   //
569   while(sz>1)
570     {
571       sz--;
572       const MEDCouplingGridCollection *fine(_levs[sz]),*coarse(_levs[sz-1]);
573       MEDCouplingGridCollection::SynchronizeFineToCoarse(ghostLev,fine,coarse);
574     }
575 }
576
577 /*!
578  * This method synchronizes from coarse to fine arrays and fine to fine each other (if ghostLev is >0). This method makes the hypothesis that \a this has been allocated before using
579  * MEDCouplingAMRAttribute::alloc method.
580  */
581 void MEDCouplingAMRAttribute::synchronizeCoarseToFine(int ghostLev)
582 {
583   if(_levs.empty())
584     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeCoarseToFine : not any levels in this !");
585   std::size_t sz(_levs.size());
586   //
587   for(std::size_t i=1;i<sz;i++)
588     {
589       const MEDCouplingGridCollection *fine(_levs[i]),*coarse(_levs[i-1]);
590       MEDCouplingGridCollection::SynchronizeCoarseToFine(ghostLev,coarse,fine);
591     }
592 }
593
594 /*!
595  * This method performs coarse to fine spread only in the ghost zone.
596  * This method makes the hypothesis that \a this has been allocated before using MEDCouplingAMRAttribute::alloc method.
597  * So if \a ghostLev == 0 this method has no effect.
598  */
599 void MEDCouplingAMRAttribute::synchronizeCoarseToFineOnlyInGhostZone(int ghostLev)
600 {
601   if(_levs.empty())
602     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeCoarseToFineOnlyInGhostZone : not any levels in this !");
603   std::size_t sz(_levs.size());
604   //
605   for(std::size_t i=1;i<sz;i++)
606     {
607       const MEDCouplingGridCollection *fine(_levs[i]),*coarse(_levs[i-1]);
608       MEDCouplingGridCollection::SynchronizeCoarseToFineOnlyInGhostZone(ghostLev,coarse,fine);
609     }
610 }
611
612 /*!
613  * This method synchronizes fine each other only in the ghost zone.
614  */
615 void MEDCouplingAMRAttribute::synchronizeFineEachOtherInGhostZone(int ghostLev)
616 {
617   if(_levs.empty())
618     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineEachOther : not any levels in this !");
619   std::size_t sz(_levs.size());
620   //
621   for(std::size_t i=1;i<sz;i++)
622     {
623       const MEDCouplingGridCollection *fine(_levs[i]);
624       if(!fine)
625         throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineEachOtherInGhostZone : presence of a NULL element !");
626       fine->synchronizeFineEachOther(ghostLev);
627     }
628 }
629
630 /*!
631  * This method allocates all DataArrayDouble instances stored recursively in \a this.
632  *
633  * \param [in] ghostLev - The size of ghost zone.
634  *
635  * \sa dealloc
636  */
637 void MEDCouplingAMRAttribute::alloc(int ghostLev)
638 {
639   _tlc.resetState();
640   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::iterator it=_levs.begin();it!=_levs.end();it++)
641     {
642       MEDCouplingGridCollection *elt(*it);
643       if(elt)
644         elt->alloc(ghostLev);
645       else
646         throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::alloc : internal error !");
647     }
648 }
649
650 /*!
651  * This method deallocates all DataArrayDouble instances stored recursively in \a this.
652  * \sa alloc
653  */
654 void MEDCouplingAMRAttribute::dealloc()
655 {
656   _tlc.checkConst();
657   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::iterator it=_levs.begin();it!=_levs.end();it++)
658     {
659       MEDCouplingGridCollection *elt(*it);
660       if(elt)
661         elt->dealloc();
662       else
663         throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::dealloc : internal error !");
664     }
665 }
666
667 bool MEDCouplingAMRAttribute::changeGodFather(MEDCouplingCartesianAMRMesh *gf)
668 {
669   bool ret(MEDCouplingDataForGodFather::changeGodFather(gf));
670   return ret;
671 }
672
673 std::size_t MEDCouplingAMRAttribute::getHeapMemorySizeWithoutChildren() const
674 {
675   std::size_t ret(sizeof(MEDCouplingAMRAttribute));
676   ret+=_levs.capacity()*sizeof(MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection>);
677   return ret;
678 }
679
680 std::vector<const BigMemoryObject *> MEDCouplingAMRAttribute::getDirectChildren() const
681 {
682   std::vector<const BigMemoryObject *> ret;
683   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
684     {
685       const MEDCouplingGridCollection *elt(*it);
686       if(elt)
687         ret.push_back(elt);
688     }
689   return ret;
690 }
691
692 void MEDCouplingAMRAttribute::updateTime() const
693 {//tony
694 }
695
696 MEDCouplingAMRAttribute::MEDCouplingAMRAttribute(MEDCouplingCartesianAMRMesh *gf, const std::vector< std::pair<std::string,int> >& fieldNames):MEDCouplingDataForGodFather(gf)
697 {
698   //gf non empty, checked by constructor
699   int maxLev(gf->getMaxNumberOfLevelsRelativeToThis());
700   _levs.resize(maxLev);
701   for(int i=0;i<maxLev;i++)
702     {
703       std::vector<MEDCouplingCartesianAMRPatchGen *> patches(gf->retrieveGridsAt(i));
704       std::size_t sz(patches.size());
705       std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatchGen> > patchesSafe(patches.size());
706       for(std::size_t j=0;j<sz;j++)
707         patchesSafe[j]=patches[j];
708       std::vector<const MEDCouplingCartesianAMRMeshGen *> ms(sz);
709       for(std::size_t j=0;j<sz;j++)
710         {
711           ms[j]=patches[j]->getMesh();
712         }
713       _levs[i]=MEDCouplingGridCollection::New(ms,fieldNames);
714     }
715 }