Salome HOME
Target MEDReader
[modules/med.git] / src / MEDLoader / MEDFileFieldOverView.cxx
1 // Copyright (C) 2007-2013  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.
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 (CEA/DEN)
20
21 #include "MEDFileFieldOverView.hxx"
22 #include "MEDFileField.hxx"
23 #include "MEDFileMesh.hxx"
24
25 #include "CellModel.hxx"
26
27 using namespace ParaMEDMEM;
28
29 const char MEDFileField1TSStructItem2::NEWLY_CREATED_PFL_NAME[]="???";
30
31 MEDFileMeshStruct *MEDFileMeshStruct::New(const MEDFileMesh *mesh)
32 {
33   return new MEDFileMeshStruct(mesh);
34 }
35
36 std::size_t MEDFileMeshStruct::getHeapMemorySize() const
37 {
38   std::size_t ret(0);
39   for(std::vector< std::vector<int> >::const_iterator it0=_geo_types_distrib.begin();it0!=_geo_types_distrib.end();it0++)
40     ret+=(*it0).capacity()*sizeof(int);
41   ret+=_geo_types_distrib.capacity()*sizeof(std::vector<int>);
42   return ret;
43 }
44
45 MEDFileMeshStruct::MEDFileMeshStruct(const MEDFileMesh *mesh):_mesh(mesh)
46 {
47   std::vector<int> levs=mesh->getNonEmptyLevels();
48   _name=mesh->getName();
49   _nb_nodes=mesh->getNumberOfNodes();
50   _geo_types_distrib.resize(levs.size());
51   for(std::vector<int>::const_iterator lev=levs.begin();lev!=levs.end();lev++)
52     {
53       MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> mLev=mesh->getGenMeshAtLevel(*lev);
54       _geo_types_distrib[-(*lev)]=mLev->getDistributionOfTypes();
55     }
56 }
57
58 int MEDFileMeshStruct::getLevelOfGeoType(INTERP_KERNEL::NormalizedCellType t) const throw(INTERP_KERNEL::Exception)
59 {
60   int j=0;
61   for(std::vector< std::vector<int> >::const_iterator it1=_geo_types_distrib.begin();it1!=_geo_types_distrib.end();it1++,j--)
62     {
63       std::size_t sz=(*it1).size();
64       if(sz%3!=0)
65         throw INTERP_KERNEL::Exception("MEDFileMeshStruct::getLevelOfGeoType : internal error in code !");
66       std::size_t nbGeo=sz/3;
67       for(std::size_t i=0;i<nbGeo;i++)
68         if((*it1)[3*i]==(int)t)
69           return j;
70     }
71   throw INTERP_KERNEL::Exception("MEDFileMeshStruct::getLevelOfGeoType : The specified geometric type is not present in the mesh structure !");
72 }
73
74 int MEDFileMeshStruct::getNumberOfElemsOfGeoType(INTERP_KERNEL::NormalizedCellType t) const throw(INTERP_KERNEL::Exception)
75 {
76   for(std::vector< std::vector<int> >::const_iterator it1=_geo_types_distrib.begin();it1!=_geo_types_distrib.end();it1++)
77     {
78       std::size_t sz=(*it1).size();
79       if(sz%3!=0)
80         throw INTERP_KERNEL::Exception("MEDFileMeshStruct::getNumberOfElemsOfGeoType : internal error in code !");
81       std::size_t nbGeo=sz/3;
82       for(std::size_t i=0;i<nbGeo;i++)
83         if((*it1)[3*i]==(int)t)
84           return (*it1)[3*i+1];
85     }
86   throw INTERP_KERNEL::Exception("The specified geometric type is not present in the mesh structure !");
87 }
88
89 int MEDFileMeshStruct::getNumberOfLevs() const
90 {
91   return (int)_geo_types_distrib.size();
92 }
93
94 int MEDFileMeshStruct::getNumberOfGeoTypesInLev(int relativeLev) const throw(INTERP_KERNEL::Exception)
95 {
96   int pos(-relativeLev);
97   if(pos<0 || pos>=_geo_types_distrib.size())
98     throw INTERP_KERNEL::Exception("MEDFileMeshStruct::getNumberOfGeoTypesInLev : invalid level specified !");
99   std::size_t sz=_geo_types_distrib[pos].size();
100   if(sz%3!=0)
101     throw INTERP_KERNEL::Exception("MEDFileMeshStruct::getNumberOfGeoTypesInLev : internal error in code !");
102   return (int)(sz/3);
103 }
104
105 //=
106
107 MEDFileField1TSStructItem2::MEDFileField1TSStructItem2()
108 {
109 }
110
111 MEDFileField1TSStructItem2::MEDFileField1TSStructItem2(INTERP_KERNEL::NormalizedCellType a, const std::pair<int,int>& b, const std::string& c, const std::string& d):_geo_type(a),_start_end(b),_pfl(DataArrayInt::New()),_loc(d),_nb_of_entity(-1)
112 {
113   _pfl->setName(c.c_str());
114 }
115
116 void MEDFileField1TSStructItem2::checkWithMeshStructForCells(const MEDFileMeshStruct *mst, const MEDFileFieldGlobsReal *globs) throw(INTERP_KERNEL::Exception)
117 {
118   int nbOfEnt=mst->getNumberOfElemsOfGeoType(_geo_type);
119   checkInRange(nbOfEnt,1,globs);
120 }
121
122 void MEDFileField1TSStructItem2::checkWithMeshStructForGaussNE(const MEDFileMeshStruct *mst, const MEDFileFieldGlobsReal *globs) throw(INTERP_KERNEL::Exception)
123 {
124   int nbOfEnt=mst->getNumberOfElemsOfGeoType(_geo_type);
125   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(_geo_type);
126   checkInRange(nbOfEnt,(int)cm.getNumberOfNodes(),globs);
127 }
128
129 void MEDFileField1TSStructItem2::checkWithMeshStructForGaussPT(const MEDFileMeshStruct *mst, const MEDFileFieldGlobsReal *globs) throw(INTERP_KERNEL::Exception)
130 {
131   if(!globs)
132     throw INTERP_KERNEL::Exception("MEDFileField1TSStructItem2::checkWithMeshStructForGaussPT : no globals specified !");
133   if(_loc.empty())
134     throw INTERP_KERNEL::Exception("MEDFileField1TSStructItem2::checkWithMeshStructForGaussPT : no localization specified !");
135   const MEDFileFieldLoc& loc=globs->getLocalization(_loc.c_str());
136   int nbOfEnt=mst->getNumberOfElemsOfGeoType(_geo_type);
137   checkInRange(nbOfEnt,loc.getNumberOfGaussPoints(),globs);
138 }
139
140 std::string MEDFileField1TSStructItem2::getPflName() const
141 {
142   return _pfl->getName();
143 }
144
145 const DataArrayInt *MEDFileField1TSStructItem2::getPfl(const MEDFileFieldGlobsReal *globs) const
146 {
147   if(!_pfl->isAllocated())
148     {
149       if(_pfl->getName().empty())
150         return 0;
151       else
152         return globs->getProfile(_pfl->getName().c_str());
153     }
154   else
155     return _pfl;
156 }
157
158 /*!
159  * \param [in] nbOfEntity - number of entity that can be either cells or nodes. Not other possiblity.
160  * \param [in] nip - number of integration points. 1 for ON_CELLS and NO_NODES
161  */
162 void MEDFileField1TSStructItem2::checkInRange(int nbOfEntity, int nip, const MEDFileFieldGlobsReal *globs) throw(INTERP_KERNEL::Exception)
163 {
164   _nb_of_entity=nbOfEntity;
165   if(_pfl->getName().empty())
166     {
167       if(nbOfEntity!=(_start_end.second-_start_end.first)/nip)
168         throw INTERP_KERNEL::Exception("MEDFileField1TSStructItem2::checkInRange : Mismatch between number of entities and size of node field !");
169       return ;
170     }
171   else
172     {
173       if(!globs)
174         throw INTERP_KERNEL::Exception("MEDFileField1TSStructItem2::checkInRange : Presence of a profile on field whereas no globals found in file !");
175       const DataArrayInt *pfl=globs->getProfile(_pfl->getName().c_str());
176       if(!pfl)
177         throw INTERP_KERNEL::Exception("MEDFileField1TSStructItem2::checkInRange : Presence of a profile on field whereas no such profile found in file !");
178       pfl->checkAllIdsInRange(0,nbOfEntity);
179     }
180 }
181
182 bool MEDFileField1TSStructItem2::isFastlyEqual(int& startExp, INTERP_KERNEL::NormalizedCellType gt, const char *pflName) const
183 {
184   if(startExp!=_start_end.first)
185     return false;
186   if(gt!=_geo_type)
187     return false;
188   if(getPflName()!=pflName)
189     return false;
190   startExp=_start_end.second;
191   return true;
192 }
193
194 bool MEDFileField1TSStructItem2::operator==(const MEDFileField1TSStructItem2& other) const throw(INTERP_KERNEL::Exception)
195 {
196   //_nb_of_entity is not taken into account here. It is not a bug, because no mesh consideration needed here to perform fast compare.
197   //idem for _loc. It is not an effective attribute for support comparison.
198   return _geo_type==other._geo_type && _start_end==other._start_end && _pfl->getName()==other._pfl->getName();
199 }
200
201 bool MEDFileField1TSStructItem2::isCellSupportEqual(const MEDFileField1TSStructItem2& other, const MEDFileFieldGlobsReal *globs) const throw(INTERP_KERNEL::Exception)
202 {
203   if(_geo_type!=other._geo_type)
204     return false;
205   if(_nb_of_entity!=other._nb_of_entity)
206     return false;
207   if((_pfl->getName().empty() && !other._pfl->getName().empty()) || (!_pfl->getName().empty() && other._pfl->getName().empty()))
208     return false;
209   if(_pfl->getName().empty() && other._pfl->getName().empty())
210     return true;
211   const DataArrayInt *pfl1(getPfl(globs)),*pfl2(other.getPfl(globs));
212   return pfl1->isEqualWithoutConsideringStr(*pfl2);
213 }
214
215 bool MEDFileField1TSStructItem2::isNodeSupportEqual(const MEDFileField1TSStructItem2& other, const MEDFileFieldGlobsReal *globs) const throw(INTERP_KERNEL::Exception)
216 {
217   return isCellSupportEqual(other,globs);
218 }
219
220 /*!
221  * \a objs must be non empty. \a objs should contain items having same geometric type.
222  */
223 MEDFileField1TSStructItem2 MEDFileField1TSStructItem2::BuildAggregationOf(const std::vector<const MEDFileField1TSStructItem2 *>& objs, const MEDFileFieldGlobsReal *globs) throw(INTERP_KERNEL::Exception)
224 {
225   if(objs.empty())
226     throw INTERP_KERNEL::Exception("MEDFileField1TSStructItem2::BuildAggregationOf : empty input !");
227   if(objs.size()==1)
228     return MEDFileField1TSStructItem2(*objs[0]);
229   INTERP_KERNEL::NormalizedCellType gt(objs[0]->_geo_type);
230   int nbEntityRef(objs[0]->_nb_of_entity);
231   std::size_t sz(objs.size());
232   std::vector<const DataArrayInt *> arrs(sz);
233   for(std::size_t i=0;i<sz;i++)
234     {
235       const MEDFileField1TSStructItem2 *obj(objs[i]);
236       if(gt!=obj->_geo_type)
237         throw INTERP_KERNEL::Exception("MEDFileField1TSStructItem2::BuildAggregationOf : invalid situation ! All input must have the same geo type !");
238       if(nbEntityRef!=obj->_nb_of_entity)
239         throw INTERP_KERNEL::Exception("MEDFileField1TSStructItem2::BuildAggregationOf : invalid situation ! All input must have the global nb of entity !");
240       if(obj->_pfl->getName().empty())
241         throw INTERP_KERNEL::Exception("MEDFileField1TSStructItem2::BuildAggregationOf : invalid situation ! Several same geo type chunk must all lie on profiles !");
242       arrs[i]=globs->getProfile(obj->_pfl->getName().c_str());
243     }
244   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr(DataArrayInt::Aggregate(arrs));
245   arr->sort();
246   int oldNbTuples(arr->getNumberOfTuples());
247   arr=arr->buildUnique();
248   if(oldNbTuples!=arr->getNumberOfTuples())
249     throw INTERP_KERNEL::Exception("MEDFileField1TSStructItem2::BuildAggregationOf : some entities are present several times !");
250   if(arr->isIdentity() && oldNbTuples==nbEntityRef)
251     {
252       std::pair<int,int> p(0,nbEntityRef);
253       std::string a,b;
254       MEDFileField1TSStructItem2 ret(gt,p,a,b);
255       ret._nb_of_entity=nbEntityRef;
256       return ret;
257     }
258   else
259     {
260       arr->setName(NEWLY_CREATED_PFL_NAME);
261       std::pair<int,int> p(0,oldNbTuples);
262       std::string a,b;
263       MEDFileField1TSStructItem2 ret(gt,p,a,b);
264       ret._nb_of_entity=nbEntityRef;
265       ret._pfl=arr;
266       return ret;
267     }
268 }
269
270 std::size_t MEDFileField1TSStructItem2::getHeapMemorySize() const
271 {
272   std::size_t ret(0);
273   const DataArrayInt *pfl(_pfl);
274   if(pfl)
275     ret+=pfl->getHeapMemorySize();
276   ret+=_loc.capacity();
277   return ret;
278 }
279
280 //=
281
282 MEDFileField1TSStructItem::MEDFileField1TSStructItem(TypeOfField a, const std::vector< MEDFileField1TSStructItem2 >& b):_computed(false),_type(a),_items(b)
283 {
284 }
285
286 void MEDFileField1TSStructItem::checkWithMeshStruct(const MEDFileMeshStruct *mst, const MEDFileFieldGlobsReal *globs) throw(INTERP_KERNEL::Exception)
287 {
288   switch(_type)
289     {
290     case ON_NODES:
291       {
292         int nbOfEnt=mst->getNumberOfNodes();
293         if(_items.size()!=1)
294           throw INTERP_KERNEL::Exception("MEDFileField1TSStructItem::checkWithMeshStruct : for nodes field only one subdivision supported !");
295         _items[0].checkInRange(nbOfEnt,1,globs);
296         break ;
297       }
298     case ON_CELLS:
299       {
300         for(std::vector< MEDFileField1TSStructItem2 >::iterator it=_items.begin();it!=_items.end();it++)
301           (*it).checkWithMeshStructForCells(mst,globs);
302         break;
303       }
304     case ON_GAUSS_NE:
305       {
306         for(std::vector< MEDFileField1TSStructItem2 >::iterator it=_items.begin();it!=_items.end();it++)
307           (*it).checkWithMeshStructForGaussNE(mst,globs);
308         break;
309       }
310     case ON_GAUSS_PT:
311       {
312         for(std::vector< MEDFileField1TSStructItem2 >::iterator it=_items.begin();it!=_items.end();it++)
313           (*it).checkWithMeshStructForGaussPT(mst,globs);
314         break;
315       }
316     default:
317       throw INTERP_KERNEL::Exception("MEDFileField1TSStructItem::checkWithMeshStruct : not managed field type !");
318     }
319 }
320
321 bool MEDFileField1TSStructItem::operator==(const MEDFileField1TSStructItem& other) const throw(INTERP_KERNEL::Exception)
322 {
323   if(_type!=other._type)
324     return false;
325   if(_items.size()!=other._items.size())
326     return false;
327   for(std::size_t i=0;i<_items.size();i++)
328     if(!(_items[i]==other._items[i]))
329       return false;
330   return true;
331 }
332
333 bool MEDFileField1TSStructItem::isCellSupportEqual(const MEDFileField1TSStructItem& other, const MEDFileFieldGlobsReal *globs) const throw(INTERP_KERNEL::Exception)
334 {
335   if(_type!=other._type)
336     return false;
337   if(_items.size()!=other._items.size())
338     return false;
339   for(std::size_t i=0;i<_items.size();i++)
340     if(!(_items[i].isCellSupportEqual(other._items[i],globs)))
341       return false;
342   return true;
343 }
344
345 bool MEDFileField1TSStructItem::isNodeSupportEqual(const MEDFileField1TSStructItem& other, const MEDFileFieldGlobsReal *globs) const throw(INTERP_KERNEL::Exception)
346 {
347   if(_type!=other._type)
348     return false;
349   if(_items.size()!=other._items.size())
350     return false;
351   for(std::size_t i=0;i<_items.size();i++)
352     if(!(_items[i].isNodeSupportEqual(other._items[i],globs)))
353       return false;
354   return true;
355 }
356
357 bool MEDFileField1TSStructItem::isEntityCell() const
358 {
359   if(_type==ON_NODES)
360     return false;
361   else
362     return true;
363 }
364
365 class CmpGeo
366 {
367 public:
368   CmpGeo(INTERP_KERNEL::NormalizedCellType geoTyp):_geo_type(geoTyp) { }
369   bool operator()(const std::pair< INTERP_KERNEL::NormalizedCellType, std::vector<std::size_t> > & v) const { return _geo_type==v.first; }
370 private:
371   INTERP_KERNEL::NormalizedCellType _geo_type;
372 };
373
374 MEDFileField1TSStructItem MEDFileField1TSStructItem::simplifyMeOnCellEntity(const MEDFileFieldGlobsReal *globs) const throw(INTERP_KERNEL::Exception)
375 {
376   if(!isEntityCell())
377     throw INTERP_KERNEL::Exception("MEDFileField1TSStructItem::simplifyMeOnCellEntity : must be on ON_CELLS, ON_GAUSS_NE or ON_GAUSS_PT !");
378   std::vector< std::pair< INTERP_KERNEL::NormalizedCellType, std::vector<std::size_t> > > m;
379   std::size_t i=0;
380   for(std::vector< MEDFileField1TSStructItem2 >::const_iterator it=_items.begin();it!=_items.end();it++,i++)
381     {
382       std::vector< std::pair< INTERP_KERNEL::NormalizedCellType, std::vector<std::size_t> > >::iterator it0(std::find_if(m.begin(),m.end(),CmpGeo((*it).getGeo())));
383       if(it0==m.end())
384         m.push_back(std::pair< INTERP_KERNEL::NormalizedCellType, std::vector<std::size_t> >((*it).getGeo(),std::vector<std::size_t>(1,i)));
385       else
386         (*it0).second.push_back(i);
387     }
388   if(m.size()==_items.size())
389     {
390       MEDFileField1TSStructItem ret(*this);
391       ret._type=ON_CELLS;
392       return ret;
393     }
394   std::size_t sz(m.size());
395   std::vector< MEDFileField1TSStructItem2 > items(sz);
396   for(i=0;i<sz;i++)
397     {
398       const std::vector<std::size_t>& ids=m[i].second;
399       std::vector<const MEDFileField1TSStructItem2 *>objs(ids.size());
400       for(std::size_t j=0;j<ids.size();j++)
401         objs[j]=&_items[ids[j]];
402       items[i]=MEDFileField1TSStructItem2::BuildAggregationOf(objs,globs);
403     }
404   MEDFileField1TSStructItem ret(ON_CELLS,items);
405   ret._computed=true;
406   return ret;
407 }
408
409 /*!
410  * \a this is expected to be ON_CELLS and simplified.
411  */
412 bool MEDFileField1TSStructItem::isCompatibleWithNodesDiscr(const MEDFileField1TSStructItem& other, const MEDFileMeshStruct *meshSt, const MEDFileFieldGlobsReal *globs) const throw(INTERP_KERNEL::Exception)
413 {
414   if(other._type!=ON_NODES)
415     throw INTERP_KERNEL::Exception("MEDFileField1TSStructItem::isCompatibleWithNodesDiscr : other must be on nodes !");
416   if(other._items.size()!=1)
417     throw INTERP_KERNEL::Exception("MEDFileField1TSStructItem::isCompatibleWithNodesDiscr : other is on nodes but number of subparts !");
418   int theFirstLevFull;
419   bool ret0=isFullyOnOneLev(meshSt,theFirstLevFull);
420   const MEDFileField1TSStructItem2& otherNodeIt(other._items[0]);
421   if(otherNodeIt.getPflName().empty())
422     {//on all nodes
423       if(!ret0)
424         return false;
425       return theFirstLevFull==0;
426     }
427   else
428     {
429       const DataArrayInt *pfl=globs->getProfile(otherNodeIt.getPflName().c_str());
430       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cpyPfl(pfl->deepCpy());
431       cpyPfl->sort();
432       int nbOfNodes(meshSt->getNumberOfNodes());
433       if(cpyPfl->isIdentity() && cpyPfl->getNumberOfTuples()==nbOfNodes)
434         {//on all nodes also !
435           if(!ret0)
436             return false;
437           return theFirstLevFull==0;
438         }
439       std::vector<bool> nodesFetched(nbOfNodes,false);
440       meshSt->getTheMesh()->whichAreNodesFetched(*this,globs,nodesFetched);
441       return cpyPfl->isFittingWith(nodesFetched);
442     }
443 }
444
445 bool MEDFileField1TSStructItem::isFullyOnOneLev(const MEDFileMeshStruct *meshSt, int& theFirstLevFull) const throw(INTERP_KERNEL::Exception)
446 {
447   if(_type!=ON_CELLS)
448     throw INTERP_KERNEL::Exception("MEDFileField1TSStructItem::isFullyOnOneLev : works only for ON_CELLS discretization !");
449   if(_items.empty())
450     throw INTERP_KERNEL::Exception("MEDFileField1TSStructItem::isFullyOnOneLev : items vector is empty !");
451   int nbOfLevs(meshSt->getNumberOfLevs());
452   if(nbOfLevs==0)
453     throw INTERP_KERNEL::Exception("MEDFileField1TSStructItem::isFullyOnOneLev : no levels in input mesh structure !");
454   std::vector<int> levs(nbOfLevs);
455   theFirstLevFull=1;
456   int nbOfGT=0;
457   std::set<INTERP_KERNEL::NormalizedCellType> gts;
458   for(std::vector< MEDFileField1TSStructItem2 >::const_iterator it=_items.begin();it!=_items.end();it++)
459     {
460       if(!(*it).getPflName().empty())
461         return false;
462       INTERP_KERNEL::NormalizedCellType gt((*it).getGeo());
463       if(gts.find(gt)!=gts.end())
464         throw INTERP_KERNEL::Exception("MEDFileField1TSStructItem::isFullyOnOneLev : internal error !");
465       gts.insert(gt);
466       int pos(meshSt->getLevelOfGeoType((*it).getGeo()));
467       levs[-pos]++;
468     }
469   for(int i=0;i<nbOfLevs;i++)
470     if(meshSt->getNumberOfGeoTypesInLev(-i)==levs[i])
471       { theFirstLevFull=-i; return true; }
472   return false;
473 }
474
475 const MEDFileField1TSStructItem2& MEDFileField1TSStructItem::operator[](std::size_t i) const throw(INTERP_KERNEL::Exception)
476 {
477   if(i<0 || i>=_items.size())
478     throw INTERP_KERNEL::Exception("MEDFileField1TSStructItem::operator[] : input is not in valid range !");
479   return _items[i];
480 }
481
482 std::size_t MEDFileField1TSStructItem::getHeapMemorySize() const
483 {
484   std::size_t ret(0);
485   for(std::vector< MEDFileField1TSStructItem2 >::const_iterator it=_items.begin();it!=_items.end();it++)
486     ret+=(*it).getHeapMemorySize();
487   ret+=_items.size()*sizeof(MEDFileField1TSStructItem2);
488   return ret;
489 }
490
491 MEDMeshMultiLev *MEDFileField1TSStructItem::buildFromScratchDataSetSupportOnCells(const MEDFileMeshStruct *mst, const MEDFileFieldGlobsReal *globs) const throw(INTERP_KERNEL::Exception)
492 {
493   std::vector<INTERP_KERNEL::NormalizedCellType> a0;
494   std::vector<const DataArrayInt *> a1;
495   std::vector<int> a2;
496   std::size_t i(0);
497   for(std::vector< MEDFileField1TSStructItem2 >::const_iterator it=_items.begin();it!=_items.end();it++,i++)
498     {
499       a0[i]=(*it).getGeo();
500       a1[i]=(*it).getPfl(globs);
501       a2[i]=mst->getNumberOfElemsOfGeoType((*it).getGeo());
502     }
503   return MEDMeshMultiLev::New(mst->getTheMesh(),a0,a1,a2);
504 }
505
506 //=
507
508 MEDFileField1TSStruct *MEDFileField1TSStruct::New(const MEDFileAnyTypeField1TS *ref, MEDFileMeshStruct *mst) throw(INTERP_KERNEL::Exception)
509 {
510   return new MEDFileField1TSStruct(ref,mst);
511 }
512
513 MEDFileField1TSStruct::MEDFileField1TSStruct(const MEDFileAnyTypeField1TS *ref, MEDFileMeshStruct *mst)
514 {
515   _already_checked.push_back(BuildItemFrom(ref,mst));
516 }
517
518 void MEDFileField1TSStruct::checkWithMeshStruct(MEDFileMeshStruct *mst, const MEDFileFieldGlobsReal *globs) throw(INTERP_KERNEL::Exception)
519 {
520   if(_already_checked.empty())
521     throw INTERP_KERNEL::Exception("MEDFileField1TSStruct::checkWithMeshStruct : not correctly initialized !");
522   _already_checked.back().checkWithMeshStruct(mst,globs);
523 }
524
525 bool MEDFileField1TSStruct::isEqualConsideringThePast(const MEDFileAnyTypeField1TS *other, const MEDFileMeshStruct *mst) const throw(INTERP_KERNEL::Exception)
526 {
527   MEDFileField1TSStructItem b(BuildItemFrom(other,mst));
528   for(std::vector<MEDFileField1TSStructItem>::const_iterator it=_already_checked.begin();it!=_already_checked.end();it++)
529     {
530       if((*it)==b)
531         return true;
532     }
533   return false;
534 }
535
536 /*!
537  * Not const because \a other structure will be added to the \c _already_checked attribute in case of success.
538  */
539 bool MEDFileField1TSStruct::isSupportSameAs(const MEDFileAnyTypeField1TS *other, const MEDFileMeshStruct *meshSt) throw(INTERP_KERNEL::Exception)
540 {
541   if(_already_checked.empty())
542     throw INTERP_KERNEL::Exception("MEDFileField1TSStruct::isSupportSameAs : no ref !");
543   MEDFileField1TSStructItem b(BuildItemFrom(other,meshSt));
544   if(!_already_checked[0].isEntityCell() || !b.isEntityCell())
545     throw INTERP_KERNEL::Exception("MEDFileField1TSStruct::isSupportSameAs : only available on cell entities !");
546   MEDFileField1TSStructItem other1(b.simplifyMeOnCellEntity(other));
547   int found=-1,i=0;
548   for(std::vector<MEDFileField1TSStructItem>::const_iterator it=_already_checked.begin();it!=_already_checked.end();it++,i++)
549     if((*it).isComputed())
550       { found=i; break; }
551   bool ret(false);
552   if(found==-1)
553     {
554       MEDFileField1TSStructItem this1(_already_checked[0].simplifyMeOnCellEntity(other));
555       ret=this1.isCellSupportEqual(other1,other);
556       if(ret)
557         _already_checked.push_back(this1);
558     }
559   else
560     ret=_already_checked[found].isCellSupportEqual(other1,other);
561   if(ret)
562     _already_checked.push_back(b);
563   return ret;
564 }
565
566 bool MEDFileField1TSStruct::isCompatibleWithNodesDiscr(const MEDFileAnyTypeField1TS *other, const MEDFileMeshStruct *meshSt) throw(INTERP_KERNEL::Exception)
567 {
568   if(_already_checked.empty())
569     throw INTERP_KERNEL::Exception("MEDFileField1TSStruct::isCompatibleWithNodesDiscr : no ref !");
570   if(!_already_checked[0].isEntityCell())
571     throw INTERP_KERNEL::Exception("MEDFileField1TSStruct::isCompatibleWithNodesDiscr : only available on cell entities !");
572   MEDFileField1TSStructItem other1(BuildItemFrom(other,meshSt));
573   //
574   int found=-1,i=0;
575   for(std::vector<MEDFileField1TSStructItem>::const_iterator it=_already_checked.begin();it!=_already_checked.end();it++,i++)
576     if((*it).isComputed())
577       { found=i; break; }
578   bool ret(false);
579   if(found==-1)
580     {
581       MEDFileField1TSStructItem this1(_already_checked[0].simplifyMeOnCellEntity(other));
582       ret=this1.isCompatibleWithNodesDiscr(other1,meshSt,other);
583       if(ret)
584         _already_checked.push_back(this1);
585     }
586   else
587     ret=_already_checked[found].isCompatibleWithNodesDiscr(other1,meshSt,other);
588   if(ret)
589     _already_checked.push_back(other1);
590   return ret;
591 }
592
593 std::size_t MEDFileField1TSStruct::getHeapMemorySize() const
594 {
595   std::size_t ret(0);
596   for(std::vector<MEDFileField1TSStructItem>::const_iterator it=_already_checked.begin();it!=_already_checked.end();it++)
597     ret+=(*it).getHeapMemorySize();
598   ret+=_already_checked.capacity()*sizeof(MEDFileField1TSStructItem);
599   return ret;
600 }
601
602 MEDFileField1TSStructItem MEDFileField1TSStruct::BuildItemFrom(const MEDFileAnyTypeField1TS *ref, const MEDFileMeshStruct *meshSt)
603 {
604   TypeOfField atype;
605   std::vector< MEDFileField1TSStructItem2 > anItems;
606   //
607   std::vector< std::vector<std::string> > pfls,locs;
608   std::vector< std::vector<TypeOfField> > typesF;
609   std::vector<INTERP_KERNEL::NormalizedCellType> geoTypes;
610   std::vector< std::vector<std::pair<int,int> > > strtEnds=ref->getFieldSplitedByType(0,geoTypes,typesF,pfls,locs);
611   std::size_t nbOfGeoTypes(geoTypes.size());
612   if(nbOfGeoTypes==0)
613     throw INTERP_KERNEL::Exception("MEDFileField1TSStruct : not null by empty ref  !");
614   bool isFirst=true;
615   for(std::size_t i=0;i<nbOfGeoTypes;i++)
616     {
617       std::size_t sz=typesF[i].size();
618       if(strtEnds[i].size()<1 || sz<1 || pfls[i].size()<1)
619         throw INTERP_KERNEL::Exception("MEDFileField1TSStruct : internal error #1 !");
620       //
621       if(isFirst)
622         atype=typesF[i][0];
623       isFirst=false;
624       //
625       for(std::size_t j=0;j<sz;j++)
626         {
627           if(atype==typesF[i][j])
628             anItems.push_back(MEDFileField1TSStructItem2(geoTypes[i],strtEnds[i][j],pfls[i][j],locs[i][j]));
629           else
630             throw INTERP_KERNEL::Exception("MEDFileField1TSStruct : can be applied only on single spatial discretization fields ! Call SplitPerDiscretization method !");
631         }
632     }
633   MEDFileField1TSStructItem ret(atype,anItems);
634   ret.checkWithMeshStruct(meshSt,ref);
635   return ret;
636 }
637
638 MEDMeshMultiLev *MEDFileField1TSStruct::buildFromScratchDataSetSupport(const MEDFileMeshStruct *mst, const MEDFileFieldGlobsReal *globs) const throw(INTERP_KERNEL::Exception)
639 {
640   if(_already_checked.empty())
641     throw INTERP_KERNEL::Exception("MEDFileField1TSStruct::buildFromScratchDataSetSupport : No outline structure in this !");
642   int pos0(-1),pos1(-1);
643   if(presenceOfCellDiscr(pos0))
644     {
645       MEDCouplingAutoRefCountObjectPtr<MEDMeshMultiLev> ret(_already_checked[pos0].buildFromScratchDataSetSupportOnCells(mst,globs));
646       if(presenceOfPartialNodeDiscr(pos1))
647         ret->setNodeReduction(_already_checked[pos1][0].getPfl(globs));
648       return ret.retn();
649     }
650   else
651     {
652       if(!presenceOfPartialNodeDiscr(pos1))
653         {//we have only all nodes, no cell definition info -> level 0;
654           std::vector<int> levs(1,0);
655           return MEDMeshMultiLev::New(mst->getTheMesh(),levs);
656         }
657       else
658         return MEDMeshMultiLev::NewOnlyOnNode(mst->getTheMesh(),_already_checked[pos1][0].getPfl(globs));
659     }
660 }
661
662 bool MEDFileField1TSStruct::isDataSetSupportFastlyEqualTo(const MEDFileField1TSStruct& other, const MEDFileFieldGlobsReal *globs) const throw(INTERP_KERNEL::Exception)
663 {
664   int b0,b1;
665   bool a0(presenceOfCellDiscr(b0)),a1(presenceOfPartialNodeDiscr(b1));
666   int d0,d1;
667   bool c0(other.presenceOfCellDiscr(d0)),c1(other.presenceOfPartialNodeDiscr(d1)); 
668   if(a0!=c0 || a1!=c1)
669     return false;
670   if(a0)
671     if(!_already_checked[b0].isCellSupportEqual(other._already_checked[d0],globs))
672       return false;
673   if(a1)
674     if(!_already_checked[b1].isNodeSupportEqual(other._already_checked[d1],globs))
675       return false;
676   return true;
677 }
678
679 /*!
680  * Returns true if presence in \a this of discretization ON_CELLS, ON_GAUSS_PT, ON_GAUSS_NE.
681  * If true is returned the pos of the easiest is returned. The easiest is the first element in \a this having the less splitted subparts.
682  */
683 bool MEDFileField1TSStruct::presenceOfCellDiscr(int& pos) const throw(INTERP_KERNEL::Exception)
684 {
685   std::size_t refSz(std::numeric_limits<std::size_t>::max());
686   bool ret(false);
687   int i(0);
688   for(std::vector<MEDFileField1TSStructItem>::const_iterator it=_already_checked.begin();it!=_already_checked.end();it++,i++)
689     {
690       if((*it).getType()!=ON_NODES)
691         {
692           ret=true;
693           std::size_t sz((*it).getNumberOfItems());
694           if(refSz>sz)
695             { pos=i; refSz=sz; }
696         }
697     }
698   if(refSz==0)
699     throw INTERP_KERNEL::Exception("MEDFileField1TSStruct::presenceOfCellDiscr : an element in this on entity CELL is empty !");
700   return ret;
701 }
702
703 /*!
704  * Returns true if presence in \a this of discretization ON_NODES.
705  * If true is returned the pos of the first element containing the single subpart.
706  */
707 bool MEDFileField1TSStruct::presenceOfPartialNodeDiscr(int& pos) const throw(INTERP_KERNEL::Exception)
708 {
709   int i(0);
710   for(std::vector<MEDFileField1TSStructItem>::const_iterator it=_already_checked.begin();it!=_already_checked.end();it++,i++)
711     {
712       if((*it).getType()==ON_NODES)
713         {
714           std::size_t sz((*it).getNumberOfItems());
715           if(sz==1)
716             {
717               if(!(*it)[0].getPflName().empty())
718                 { pos=i; return true; }
719             }
720           else
721             throw INTERP_KERNEL::Exception("MEDFileField1TSStruct::presenceOfPartialNodeDiscr : an element in this on entity NODE is split into several parts !");
722         }
723     }
724   return false;
725 }
726
727 //=
728
729 MEDFileFastCellSupportComparator *MEDFileFastCellSupportComparator::New(const MEDFileMeshStruct *m, const MEDFileAnyTypeFieldMultiTS *ref) throw(INTERP_KERNEL::Exception)
730 {
731   return new MEDFileFastCellSupportComparator(m,ref);
732 }
733
734 MEDFileFastCellSupportComparator::MEDFileFastCellSupportComparator(const MEDFileMeshStruct *m, const MEDFileAnyTypeFieldMultiTS *ref)
735 {
736   if(!m)
737     throw INTERP_KERNEL::Exception("MEDFileFastCellSupportComparator constructor : null input mesh struct !");
738   _mesh_comp=const_cast<MEDFileMeshStruct *>(m); _mesh_comp->incrRef();
739   int nbPts=ref->getNumberOfTS();
740   _f1ts_cmps.resize(nbPts);
741   for(int i=0;i<nbPts;i++)
742     {
743       MEDCouplingAutoRefCountObjectPtr<MEDFileAnyTypeField1TS> elt=ref->getTimeStepAtPos(i);
744       _f1ts_cmps[i]=MEDFileField1TSStruct::New(elt,_mesh_comp);
745       _f1ts_cmps[i]->checkWithMeshStruct(_mesh_comp,elt);
746     }
747 }
748
749 std::size_t MEDFileFastCellSupportComparator::getHeapMemorySize() const
750 {
751   std::size_t ret(0);
752   const MEDFileMeshStruct *mst(_mesh_comp);
753   if(mst)
754     ret+=mst->getHeapMemorySize();
755   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileField1TSStruct> >::const_iterator it=_f1ts_cmps.begin();it!=_f1ts_cmps.end();it++)
756     {
757       const MEDFileField1TSStruct *cur(*it);
758       if(cur)
759         ret+=cur->getHeapMemorySize()+sizeof(MEDFileField1TSStruct);
760     }
761   ret+=_f1ts_cmps.capacity()*sizeof(MEDCouplingAutoRefCountObjectPtr<MEDFileField1TSStruct>);
762   return ret;
763 }
764
765 bool MEDFileFastCellSupportComparator::isEqual(const MEDFileAnyTypeFieldMultiTS *other) throw(INTERP_KERNEL::Exception)
766 {
767   int nbPts=other->getNumberOfTS();
768   if(nbPts!=(int)_f1ts_cmps.size())
769     {
770       std::ostringstream oss; oss << "MEDFileFastCellSupportComparator::isEqual : unexpected nb of time steps in  input ! Should be " << _f1ts_cmps.size() << " it is in reality " << nbPts << " !";
771       throw INTERP_KERNEL::Exception(oss.str().c_str());
772     }
773   for(int i=0;i<nbPts;i++)
774     {
775       MEDCouplingAutoRefCountObjectPtr<MEDFileAnyTypeField1TS> elt=other->getTimeStepAtPos(i);
776       if(!_f1ts_cmps[i]->isEqualConsideringThePast(elt,_mesh_comp))
777         if(!_f1ts_cmps[i]->isSupportSameAs(elt,_mesh_comp))
778           return false;
779     }
780   return true;
781 }
782
783 bool MEDFileFastCellSupportComparator::isCompatibleWithNodesDiscr(const MEDFileAnyTypeFieldMultiTS *other) throw(INTERP_KERNEL::Exception)
784 {
785   int nbPts=other->getNumberOfTS();
786   if(nbPts!=(int)_f1ts_cmps.size())
787     {
788       std::ostringstream oss; oss << "MEDFileFastCellSupportComparator::isCompatibleWithNodesDiscr : unexpected nb of time steps in  input ! Should be " << _f1ts_cmps.size() << " it is in reality " << nbPts << " !";
789       throw INTERP_KERNEL::Exception(oss.str().c_str());
790     }
791   for(int i=0;i<nbPts;i++)
792     {
793       MEDCouplingAutoRefCountObjectPtr<MEDFileAnyTypeField1TS> elt=other->getTimeStepAtPos(i);
794       if(!_f1ts_cmps[i]->isCompatibleWithNodesDiscr(elt,_mesh_comp))
795         return false;
796     }
797   return true;
798 }
799
800 MEDMeshMultiLev *MEDFileFastCellSupportComparator::buildFromScratchDataSetSupport(int timeStepId, const MEDFileFieldGlobsReal *globs) const throw(INTERP_KERNEL::Exception)
801 {
802   if(timeStepId<0 || timeStepId>=(int)_f1ts_cmps.size())
803     {
804       std::ostringstream oss; oss << "MEDFileFastCellSupportComparator::buildFromScratchDataSetSupport : requested time step id #" << timeStepId << " is not in [0," << _f1ts_cmps.size() << ") !";
805       throw INTERP_KERNEL::Exception(oss.str().c_str());
806     }
807   const MEDFileField1TSStruct *obj(_f1ts_cmps[timeStepId]);
808   if(!obj)
809     {
810       std::ostringstream oss; oss << "MEDFileFastCellSupportComparator::buildFromScratchDataSetSupport : at time step id #" << timeStepId << " no field structure overview defined !";
811       throw INTERP_KERNEL::Exception(oss.str().c_str());
812     }
813   return obj->buildFromScratchDataSetSupport(_mesh_comp,globs);
814 }
815
816 bool MEDFileFastCellSupportComparator::isDataSetSupportEqualToThePreviousOne(int timeStepId, const MEDFileFieldGlobsReal *globs) const throw(INTERP_KERNEL::Exception)
817 {
818   if(timeStepId<=0 || timeStepId>=(int)_f1ts_cmps.size())
819     {
820       std::ostringstream oss; oss << "MEDFileFastCellSupportComparator::isDataSetSupportEqualToThePreviousOne : requested time step id #" << timeStepId << " is not in [1," << _f1ts_cmps.size() << ") !";
821       throw INTERP_KERNEL::Exception(oss.str().c_str());
822     }
823   const MEDFileField1TSStruct *obj(_f1ts_cmps[timeStepId]);
824   const MEDFileField1TSStruct *objRef(_f1ts_cmps[timeStepId-1]);
825   return objRef->isDataSetSupportFastlyEqualTo(*obj,globs);
826 }
827
828 //=
829
830 std::size_t MEDMeshMultiLev::getHeapMemorySize() const
831 {
832   return 0;
833 }
834
835 MEDMeshMultiLev *MEDMeshMultiLev::New(const MEDFileMesh *m, const std::vector<int>& levs) throw(INTERP_KERNEL::Exception)
836 {
837   if(!m)
838     throw INTERP_KERNEL::Exception("MEDMeshMultiLev::New : null input pointer !");
839   const MEDFileUMesh *um(dynamic_cast<const MEDFileUMesh *>(m));
840   if(um)
841     return MEDUMeshMultiLev::New(um,levs);
842   const MEDFileCMesh *cm(dynamic_cast<const MEDFileCMesh *>(m));
843   if(cm)
844     return MEDCMeshMultiLev::New(cm,levs);
845   const MEDFileCurveLinearMesh *clm(dynamic_cast<const MEDFileCurveLinearMesh *>(m));
846   if(clm)
847     return MEDCurveLinearMeshMultiLev::New(clm,levs);
848   throw INTERP_KERNEL::Exception("MEDMeshMultiLev::New : unrecognized type of mesh ! Must be in [MEDFileUMesh,MEDFileCMesh,MEDFileCurveLinearMesh] !");
849 }
850
851 MEDMeshMultiLev *MEDMeshMultiLev::New(const MEDFileMesh *m, const std::vector<INTERP_KERNEL::NormalizedCellType>& gts, const std::vector<const DataArrayInt *>& pfls, const std::vector<int>& nbEntities) throw(INTERP_KERNEL::Exception)
852 {
853   if(!m)
854     throw INTERP_KERNEL::Exception("MEDMeshMultiLev::New 2 : null input pointer !");
855   const MEDFileUMesh *um(dynamic_cast<const MEDFileUMesh *>(m));
856   if(um)
857     return MEDUMeshMultiLev::New(um,gts,pfls,nbEntities);
858   const MEDFileCMesh *cm(dynamic_cast<const MEDFileCMesh *>(m));
859   if(cm)
860     return MEDCMeshMultiLev::New(cm,gts,pfls,nbEntities);
861   const MEDFileCurveLinearMesh *clm(dynamic_cast<const MEDFileCurveLinearMesh *>(m));
862   if(clm)
863     return MEDCurveLinearMeshMultiLev::New(clm,gts,pfls,nbEntities);
864   throw INTERP_KERNEL::Exception("MEDMeshMultiLev::New 2 : unrecognized type of mesh ! Must be in [MEDFileUMesh,MEDFileCMesh,MEDFileCurveLinearMesh] !");
865 }
866
867 MEDMeshMultiLev *MEDMeshMultiLev::NewOnlyOnNode(const MEDFileMesh *m, const DataArrayInt *pflOnNode) throw(INTERP_KERNEL::Exception)
868 {
869   std::vector<int> levs(1,0);
870   MEDCouplingAutoRefCountObjectPtr<MEDMeshMultiLev> ret(MEDMeshMultiLev::New(m,levs));
871   ret->selectPartOfNodes(pflOnNode);
872   return ret.retn();
873 }
874
875 void MEDMeshMultiLev::setNodeReduction(const DataArrayInt *nr)
876 {
877   if(nr)
878     nr->incrRef();
879   _node_reduction=const_cast<DataArrayInt*>(nr);
880 }
881
882 bool MEDMeshMultiLev::isFastlyTheSameStruct(const MEDFileField1TSStructItem& fst, const MEDFileFieldGlobsReal *globs) const throw(INTERP_KERNEL::Exception)
883 {
884   if(fst.getType()==ON_NODES)
885     {
886       if(fst.getNumberOfItems()!=1)
887         throw INTERP_KERNEL::Exception("MEDMeshMultiLev::isFastlyTheSameStruct : unexpected situation for nodes !");
888       const MEDFileField1TSStructItem2& p(fst[0]);
889       std::string pflName(p.getPflName());
890       const DataArrayInt *nr(_node_reduction);
891       if(pflName.empty() && !nr)
892         return true;
893       if(pflName==nr->getName())
894         return true;
895       return false;
896     }
897   else
898     {
899       std::size_t sz(fst.getNumberOfItems());
900       if(sz!=_geo_types.size())
901         return false;
902       int strt(0);
903       for(std::size_t i=0;i<sz;i++)
904         {
905           const MEDFileField1TSStructItem2& p(fst[i]);
906           if(!p.isFastlyEqual(strt,_geo_types[i],getPflNameOfId(i).c_str()))
907             return false;
908         }
909       return true;
910     }
911 }
912
913 DataArray *MEDMeshMultiLev::buildDataArray(const MEDFileField1TSStructItem& fst, const MEDFileFieldGlobsReal *globs, const DataArray *vals) const throw(INTERP_KERNEL::Exception)
914 {
915   MEDCouplingAutoRefCountObjectPtr<DataArray> ret(const_cast<DataArray *>(vals)); ret->incrRef();
916   if(isFastlyTheSameStruct(fst,globs))
917     return ret.retn();
918   //else
919   //  return constructDataArray(fst,globs,vals);
920   return 0;
921 }
922
923 std::string MEDMeshMultiLev::getPflNameOfId(int id) const
924 {
925   std::size_t sz(_pfls.size());
926   if(id<0 || id>=sz)
927     throw INTERP_KERNEL::Exception("MEDMeshMultiLev::getPflNameOfId : invalid input id !");
928   const DataArrayInt *pfl(_pfls[id]);
929   if(!pfl)
930     return std::string("");
931   return pfl->getName();
932 }
933
934 MEDMeshMultiLev::MEDMeshMultiLev()
935 {
936 }
937
938 MEDMeshMultiLev::MEDMeshMultiLev(const std::vector<INTERP_KERNEL::NormalizedCellType>& gts, const std::vector<const DataArrayInt *>& pfls, const std::vector<int>& nbEntities):_geo_types(gts),_nb_entities(nbEntities)
939 {
940   std::size_t sz(_geo_types.size());
941   if(sz!=pfls.size() || sz!=nbEntities.size())
942     throw INTERP_KERNEL::Exception("MEDMeshMultiLev::MEDMeshMultiLev : input vector must have the same size !");
943   _pfls.resize(sz);
944   for(std::size_t i=0;i<sz;i++)
945     {
946       if(pfls[i])
947         pfls[i]->incrRef();
948       _pfls[i]=const_cast<DataArrayInt *>(pfls[i]);
949     }
950 }
951
952 MEDMeshMultiLev::MEDMeshMultiLev(const MEDMeshMultiLev& other):_pfls(other._pfls),_geo_types(other._geo_types),_nb_entities(other._nb_entities),_node_reduction(other._node_reduction)
953 {
954 }
955
956 //=
957
958 MEDUMeshMultiLev *MEDUMeshMultiLev::New(const MEDFileUMesh *m, const std::vector<int>& levs) throw(INTERP_KERNEL::Exception)
959 {
960   return new MEDUMeshMultiLev(m,levs);
961 }
962
963 MEDUMeshMultiLev::MEDUMeshMultiLev(const MEDFileUMesh *m, const std::vector<int>& levs)
964 {
965   if(!m)
966     throw INTERP_KERNEL::Exception("MEDUMeshMultiLev constructor : null input pointer !");
967   std::vector<MEDCoupling1GTUMesh *> v;
968   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
969     {
970       std::vector<MEDCoupling1GTUMesh *> vTmp(m->getDirectUndergroundSingleGeoTypeMeshes(*it));
971       v.insert(v.end(),vTmp.begin(),vTmp.end());
972     }
973   std::size_t sz(v.size());
974   _parts.resize(sz);
975   _pfls.resize(sz);
976   _geo_types.resize(sz);
977   for(std::size_t i=0;i<sz;i++)
978     {
979       MEDCoupling1GTUMesh *obj(v[i]);
980       if(obj)
981         obj->incrRef();
982       else
983         throw INTERP_KERNEL::Exception("MEDUMeshMultiLev constructor : presence of a null pointer !");
984       _parts[i]=obj;
985       _geo_types[i]=obj->getCellModelEnum();
986     }
987 }
988
989 MEDUMeshMultiLev *MEDUMeshMultiLev::New(const MEDFileUMesh *m, const std::vector<INTERP_KERNEL::NormalizedCellType>& gts, const std::vector<const DataArrayInt *>& pfls, const std::vector<int>& nbEntities) throw(INTERP_KERNEL::Exception)
990 {
991   return new MEDUMeshMultiLev(m,gts,pfls,nbEntities);
992 }
993
994 MEDUMeshMultiLev::MEDUMeshMultiLev(const MEDFileUMesh *m, const std::vector<INTERP_KERNEL::NormalizedCellType>& gts, const std::vector<const DataArrayInt *>& pfls, const std::vector<int>& nbEntities):MEDMeshMultiLev(gts,pfls,nbEntities)
995 {
996   std::size_t sz(gts.size());
997   _parts.resize(sz);
998   for(std::size_t i=0;i<sz;i++)
999     {
1000       MEDCoupling1GTUMesh *elt(m->getDirectUndergroundSingleGeoTypeMesh(gts[i]));
1001       if(elt)
1002         elt->incrRef();
1003       _parts[i]=elt;
1004     }
1005 }
1006
1007 void MEDUMeshMultiLev::selectPartOfNodes(const DataArrayInt *pflNodes) throw(INTERP_KERNEL::Exception)
1008 {
1009    if(!pflNodes || !pflNodes->isAllocated())
1010      return ;
1011    std::size_t sz(_parts.size());
1012    std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > a(sz);
1013    std::vector< const DataArrayInt *> aa(sz);
1014    for(std::size_t i=0;i<sz;i++)
1015      {
1016        
1017        const DataArrayInt *pfl(_pfls[i]);
1018        MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> m(_parts[i]);
1019        if(pfl)
1020          m=dynamic_cast<MEDCoupling1GTUMesh *>(_parts[i]->buildPartOfMySelfKeepCoords(pfl->begin(),pfl->end()));
1021        DataArrayInt *cellIds=0;
1022        m->fillCellIdsToKeepFromNodeIds(pflNodes->begin(),pflNodes->end(),true,cellIds);
1023        MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsSafe(cellIds);
1024        MEDCouplingAutoRefCountObjectPtr<MEDCouplingPointSet> m2(m->buildPartOfMySelfKeepCoords(cellIds->begin(),cellIds->end()));
1025        int tmp=-1;
1026        a[i]=m2->getNodeIdsInUse(tmp); aa[i]=a[i];
1027        if(pfl)
1028          _pfls[i]=pfl->selectByTupleIdSafe(cellIds->begin(),cellIds->end());
1029        else
1030          _pfls[i]=cellIdsSafe;
1031      }
1032    _node_reduction=DataArrayInt::Aggregate(aa);
1033    _node_reduction->sort(true);
1034    _node_reduction=_node_reduction->buildUnique();
1035 }
1036
1037 MEDMeshMultiLev *MEDUMeshMultiLev::prepare() const throw(INTERP_KERNEL::Exception)
1038 {
1039   return new MEDUMeshMultiLev(*this);
1040 }
1041
1042 MEDUMeshMultiLev::MEDUMeshMultiLev(const MEDUMeshMultiLev& other):MEDMeshMultiLev(other),_parts(other._parts)
1043 {
1044 }
1045
1046 MEDUMeshMultiLev::MEDUMeshMultiLev(const MEDStructuredMeshMultiLev& other, const MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh>& part):MEDMeshMultiLev(other)
1047 {
1048   _parts.resize(1);
1049   _parts[0]=part;
1050 }
1051
1052 //=
1053
1054 MEDStructuredMeshMultiLev::MEDStructuredMeshMultiLev()
1055 {
1056 }
1057
1058 MEDStructuredMeshMultiLev::MEDStructuredMeshMultiLev(const std::vector<INTERP_KERNEL::NormalizedCellType>& gts, const std::vector<const DataArrayInt *>& pfls, const std::vector<int>& nbEntities):MEDMeshMultiLev(gts,pfls,nbEntities)
1059 {
1060 }
1061
1062 void MEDStructuredMeshMultiLev::selectPartOfNodes(const DataArrayInt *pflNodes) throw(INTERP_KERNEL::Exception)
1063 {
1064   if(!pflNodes || !pflNodes->isAllocated())
1065     return ;
1066   std::vector<int> ngs(getNodeGridStructure());
1067   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(MEDCouplingStructuredMesh::Build1GTNodalConnectivity(&ngs[0],&ngs[0]+ngs.size()));
1068   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> m(MEDCoupling1SGTUMesh::New("",MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(ngs.size())));
1069   m->setNodalConnectivity(conn);
1070   const DataArrayInt *pfl(_pfls[0]);
1071   if(pfl)
1072     {
1073       m=dynamic_cast<MEDCoupling1SGTUMesh *>(m->buildPartOfMySelfKeepCoords(pfl->begin(),pfl->end()));
1074     }
1075   DataArrayInt *cellIds=0;
1076   m->fillCellIdsToKeepFromNodeIds(pflNodes->begin(),pflNodes->end(),true,cellIds);
1077   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsSafe(cellIds);
1078   MEDCouplingAutoRefCountObjectPtr<MEDCouplingPointSet> m2(m->buildPartOfMySelfKeepCoords(cellIds->begin(),cellIds->end()));
1079   int tmp=-1;
1080   _node_reduction=m2->getNodeIdsInUse(tmp);
1081   if(pfl)
1082     _pfls[0]=pfl->selectByTupleIdSafe(cellIds->begin(),cellIds->end());
1083   else
1084     _pfls[0]=cellIdsSafe;
1085 }
1086
1087 MEDStructuredMeshMultiLev::MEDStructuredMeshMultiLev(const MEDStructuredMeshMultiLev& other):MEDMeshMultiLev(other)
1088 {
1089 }
1090
1091 //=
1092
1093 MEDCMeshMultiLev *MEDCMeshMultiLev::New(const MEDFileCMesh *m, const std::vector<int>& levs) throw(INTERP_KERNEL::Exception)
1094 {
1095   return new MEDCMeshMultiLev(m,levs);
1096 }
1097
1098 MEDCMeshMultiLev *MEDCMeshMultiLev::New(const MEDFileCMesh *m, const std::vector<INTERP_KERNEL::NormalizedCellType>& gts, const std::vector<const DataArrayInt *>& pfls, const std::vector<int>& nbEntities) throw(INTERP_KERNEL::Exception)
1099 {
1100   return new MEDCMeshMultiLev(m,gts,pfls,nbEntities);
1101 }
1102
1103 MEDCMeshMultiLev::MEDCMeshMultiLev(const MEDFileCMesh *m, const std::vector<int>& levs)
1104 {
1105   if(!m)
1106     throw INTERP_KERNEL::Exception("MEDCMeshMultiLev constructor : null input pointer !");
1107   if(levs.size()!=1 || levs[0]!=0)
1108     throw INTERP_KERNEL::Exception("MEDCMeshMultiLev constructor : levels supported is 0 only !");
1109   int mdim(MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(m->getMeshDimension()));
1110   _coords.resize(mdim);
1111   for(int i=0;i<mdim;i++)
1112     {
1113       DataArrayDouble *elt(const_cast<DataArrayDouble *>(m->getMesh()->getCoordsAt(i)));
1114       if(!elt)
1115         throw INTERP_KERNEL::Exception("MEDCMeshMultiLev constructor 2 : presence of null pointer for an vector of double along an axis !");
1116       _coords[i]=elt;
1117     }
1118 }
1119
1120 MEDCMeshMultiLev::MEDCMeshMultiLev(const MEDFileCMesh *m, const std::vector<INTERP_KERNEL::NormalizedCellType>& gts, const std::vector<const DataArrayInt *>& pfls, const std::vector<int>& nbEntities):MEDStructuredMeshMultiLev(gts,pfls,nbEntities)
1121 {
1122   if(!m)
1123     throw INTERP_KERNEL::Exception("MEDCMeshMultiLev constructor 2 : null input pointer !");
1124   if(gts.size()!=1 || pfls.size()!=1)
1125     throw INTERP_KERNEL::Exception("MEDCMeshMultiLev constructor 2 : lengthes of gts and pfls must be equal to one !");
1126   int mdim(MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(m->getMeshDimension()));
1127   if(mdim!=gts[0])
1128     throw INTERP_KERNEL::Exception("MEDCMeshMultiLev constructor 2 : the unique geo type is invalid regarding meshdim !");
1129   _coords.resize(mdim);
1130   for(int i=0;i<mdim;i++)
1131     {
1132       DataArrayDouble *elt(const_cast<DataArrayDouble *>(m->getMesh()->getCoordsAt(i)));
1133       if(!elt)
1134         throw INTERP_KERNEL::Exception("MEDCMeshMultiLev constructor 2 : presence of null pointer for an vector of double along an axis !");
1135       _coords[i]=elt;
1136     }
1137 }
1138
1139 MEDCMeshMultiLev::MEDCMeshMultiLev(const MEDCMeshMultiLev& other):MEDStructuredMeshMultiLev(other)
1140 {
1141 }
1142
1143 std::vector<int> MEDCMeshMultiLev::getNodeGridStructure() const throw(INTERP_KERNEL::Exception)
1144 {
1145   std::vector<int> ret(_coords.size());
1146   for(std::size_t i=0;i<_coords.size();i++)
1147     ret[i]=_coords[i]->getNumberOfTuples();
1148   return ret;
1149 }
1150
1151 MEDMeshMultiLev *MEDCMeshMultiLev::prepare() const throw(INTERP_KERNEL::Exception)
1152 {
1153   const DataArrayInt *pfl(_pfls[0]),*nr(_node_reduction);
1154   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nnr;
1155   std::vector<int> cgs,ngs(getNodeGridStructure());
1156   cgs.resize(ngs.size());
1157   std::transform(ngs.begin(),ngs.end(),cgs.begin(),std::bind2nd(std::plus<int>(),-1));
1158   if(pfl)
1159     {
1160       std::vector< std::pair<int,int> > cellParts;
1161       if(MEDCouplingStructuredMesh::IsPartStructured(pfl->begin(),pfl->end(),cgs,cellParts))
1162         {
1163           MEDCouplingAutoRefCountObjectPtr<MEDCMeshMultiLev> ret(new MEDCMeshMultiLev(*this));
1164           if(nr)
1165             { nnr=nr->deepCpy(); nnr->sort(true); ret->setNodeReduction(nnr); }
1166           ret->_nb_entities[0]=pfl->getNumberOfTuples();
1167           ret->_pfls[0]=0;
1168           std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> > coords(_coords.size());
1169           for(std::size_t i=0;i<_coords.size();i++)
1170             coords[i]=_coords[i]->selectByTupleId2(cellParts[i].first,cellParts[i].second+1,1);
1171           ret->_coords=coords;
1172           return ret.retn();
1173         }
1174       else
1175         {
1176           MEDCouplingAutoRefCountObjectPtr<MEDCouplingCMesh> m(MEDCouplingCMesh::New());
1177           for(std::size_t i=0;i<ngs.size();i++)
1178             m->setCoordsAt(i,_coords[i]);
1179           MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> m2(m->build1SGTUnstructured());
1180           MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> m3=dynamic_cast<MEDCoupling1GTUMesh *>(m2->buildPartOfMySelfKeepCoords(pfl->begin(),pfl->end()));
1181           MEDCouplingAutoRefCountObjectPtr<MEDUMeshMultiLev> ret(new MEDUMeshMultiLev(*this,m3));
1182           if(nr)
1183             { m3->zipCoords(); nnr=nr->deepCpy(); nnr->sort(true); ret->setNodeReduction(nnr); }
1184           return ret.retn();
1185         }
1186     }
1187   else
1188     {
1189       MEDCouplingAutoRefCountObjectPtr<MEDCMeshMultiLev> ret(new MEDCMeshMultiLev(*this));
1190       if(nr)
1191         { nnr=nr->deepCpy(); nnr->sort(true); ret->setNodeReduction(nnr); }
1192       return ret.retn();
1193     }
1194 }
1195
1196 //=
1197
1198 MEDCurveLinearMeshMultiLev *MEDCurveLinearMeshMultiLev::New(const MEDFileCurveLinearMesh *m, const std::vector<int>& levs) throw(INTERP_KERNEL::Exception)
1199 {
1200   return new MEDCurveLinearMeshMultiLev(m,levs);
1201 }
1202
1203 MEDCurveLinearMeshMultiLev *MEDCurveLinearMeshMultiLev::New(const MEDFileCurveLinearMesh *m, const std::vector<INTERP_KERNEL::NormalizedCellType>& gts, const std::vector<const DataArrayInt *>& pfls, const std::vector<int>& nbEntities) throw(INTERP_KERNEL::Exception)
1204 {
1205   return new MEDCurveLinearMeshMultiLev(m,gts,pfls,nbEntities);
1206 }
1207
1208 MEDCurveLinearMeshMultiLev::MEDCurveLinearMeshMultiLev(const MEDFileCurveLinearMesh *m, const std::vector<int>& levs)
1209 {
1210   if(!m)
1211     throw INTERP_KERNEL::Exception("MEDCurveLinearMeshMultiLev constructor : null input pointer !");
1212   if(levs.size()!=1 || levs[0]!=0)
1213     throw INTERP_KERNEL::Exception("MEDCurveLinearMeshMultiLev constructor : levels supported is 0 only !");
1214   DataArrayDouble *coords(const_cast<DataArrayDouble *>(m->getMesh()->getCoords()));
1215   if(!coords)
1216     throw INTERP_KERNEL::Exception("MEDCurveLinearMeshMultiLev constructor 2 : no coords set !");
1217   coords->incrRef();
1218   _coords=coords;
1219   _structure=m->getMesh()->getNodeGridStructure();
1220 }
1221
1222 MEDCurveLinearMeshMultiLev::MEDCurveLinearMeshMultiLev(const MEDFileCurveLinearMesh *m, const std::vector<INTERP_KERNEL::NormalizedCellType>& gts, const std::vector<const DataArrayInt *>& pfls, const std::vector<int>& nbEntities):MEDStructuredMeshMultiLev(gts,pfls,nbEntities)
1223 {
1224   if(!m)
1225     throw INTERP_KERNEL::Exception("MEDCurveLinearMeshMultiLev constructor 2 : null input pointer !");
1226   if(gts.size()!=1 || pfls.size()!=1)
1227     throw INTERP_KERNEL::Exception("MEDCurveLinearMeshMultiLev constructor 2 : lengthes of gts and pfls must be equal to one !");
1228   int mdim(MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(m->getMeshDimension()));
1229   if(mdim!=gts[0])
1230     throw INTERP_KERNEL::Exception("MEDCurveLinearMeshMultiLev constructor 2 : the unique geo type is invalid regarding meshdim !");
1231   DataArrayDouble *coords(const_cast<DataArrayDouble *>(m->getMesh()->getCoords()));
1232   if(!coords)
1233     throw INTERP_KERNEL::Exception("MEDCurveLinearMeshMultiLev constructor 2 : no coords set !");
1234   coords->incrRef();
1235   _coords=coords;
1236   _structure=m->getMesh()->getNodeGridStructure();
1237 }
1238
1239 MEDCurveLinearMeshMultiLev::MEDCurveLinearMeshMultiLev(const MEDCurveLinearMeshMultiLev& other):MEDStructuredMeshMultiLev(other),_coords(other._coords),_structure(other._structure)
1240 {
1241 }
1242
1243 std::vector<int> MEDCurveLinearMeshMultiLev::getNodeGridStructure() const throw(INTERP_KERNEL::Exception)
1244 {
1245   return _structure;
1246 }
1247
1248 MEDMeshMultiLev *MEDCurveLinearMeshMultiLev::prepare() const throw(INTERP_KERNEL::Exception)
1249 {
1250   const DataArrayInt *pfl(_pfls[0]),*nr(_node_reduction);
1251   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nnr;
1252   std::vector<int> cgs,ngs(getNodeGridStructure());
1253   cgs.resize(ngs.size());
1254   std::transform(ngs.begin(),ngs.end(),cgs.begin(),std::bind2nd(std::plus<int>(),-1));
1255   if(pfl)
1256     {
1257       std::vector< std::pair<int,int> > cellParts,nodeParts;
1258       if(MEDCouplingStructuredMesh::IsPartStructured(pfl->begin(),pfl->end(),cgs,cellParts))
1259         {
1260           nodeParts=cellParts;
1261           std::vector<int> st(ngs.size());
1262           for(std::size_t i=0;i<ngs.size();i++)
1263             {
1264               nodeParts[i].second++;
1265               st[i]=nodeParts[i].second-nodeParts[i].first;
1266             }
1267           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> p(MEDCouplingStructuredMesh::BuildExplicitIdsFrom(ngs,nodeParts));
1268           MEDCouplingAutoRefCountObjectPtr<MEDCurveLinearMeshMultiLev> ret(new MEDCurveLinearMeshMultiLev(*this));
1269           if(nr)
1270             { nnr=nr->deepCpy(); nnr->sort(true); ret->setNodeReduction(nnr); }
1271           ret->_nb_entities[0]=pfl->getNumberOfTuples();
1272           ret->_pfls[0]=0;
1273           ret->_coords=_coords->selectByTupleIdSafe(p->begin(),p->end());
1274           ret->_structure=st;
1275           return ret.retn();
1276         }
1277       else
1278         {
1279           MEDCouplingAutoRefCountObjectPtr<MEDCouplingCurveLinearMesh> m(MEDCouplingCurveLinearMesh::New());
1280           m->setCoords(_coords); m->setNodeGridStructure(&_structure[0],&_structure[0]+_structure.size());
1281           MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> m2(m->build1SGTUnstructured());
1282           MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> m3=dynamic_cast<MEDCoupling1GTUMesh *>(m2->buildPartOfMySelfKeepCoords(pfl->begin(),pfl->end()));
1283           MEDCouplingAutoRefCountObjectPtr<MEDUMeshMultiLev> ret(new MEDUMeshMultiLev(*this,m3));
1284           if(nr)
1285             { m3->zipCoords(); nnr=nr->deepCpy(); nnr->sort(true); ret->setNodeReduction(nnr); }
1286           return ret.retn();
1287         }
1288     }
1289   else
1290     {
1291       MEDCouplingAutoRefCountObjectPtr<MEDCurveLinearMeshMultiLev> ret(new MEDCurveLinearMeshMultiLev(*this));
1292       if(nr)
1293         { nnr=nr->deepCpy(); nnr->sort(true); ret->setNodeReduction(nnr); }
1294       return ret.retn();
1295     }
1296 }