]> SALOME platform Git repositories - tools/medcoupling.git/blob - src/MEDLoader/MEDFileMesh.cxx
Salome HOME
Merge branch 'master' of ssh://git.salome-platform.org/tools/medcoupling
[tools/medcoupling.git] / src / MEDLoader / MEDFileMesh.cxx
1 // Copyright (C) 2007-2016  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 (CEA/DEN)
20
21 #include "MEDFileMesh.hxx"
22 #include "MEDFileUtilities.hxx"
23 #include "MEDFileFieldOverView.hxx"
24 #include "MEDFileField.hxx"
25 #include "MEDLoader.hxx"
26 #include "MEDFileSafeCaller.txx"
27 #include "MEDLoaderBase.hxx"
28
29 #include "MEDCouplingUMesh.hxx"
30
31 #include "InterpKernelAutoPtr.hxx"
32
33 #include <limits>
34 #include <cmath>
35
36 extern med_geometry_type typmai3[34];
37
38 using namespace MEDCoupling;
39
40 const char MEDFileMesh::DFT_FAM_NAME[]="FAMILLE_ZERO";
41
42 MEDFileMesh::MEDFileMesh():_order(-1),_iteration(-1),_time(0.),_univ_wr_status(true),_axis_type(AX_CART)
43 {
44 }
45
46 std::size_t MEDFileMesh::getHeapMemorySizeWithoutChildren() const
47 {
48   std::size_t ret(_dt_unit.capacity()+_name.capacity()+_univ_name.capacity()+_desc_name.capacity());
49   for(std::map<std::string, std::vector<std::string> >::const_iterator it=_groups.begin();it!=_groups.end();it++)
50     {
51       ret+=(*it).first.capacity()+(*it).second.capacity()*sizeof(std::string);
52       for(std::vector<std::string>::const_iterator it2=(*it).second.begin();it2!=(*it).second.end();it2++)
53         ret+=(*it2).capacity();
54     }
55   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
56     ret+=(*it).first.capacity()+sizeof(int);
57   return ret;
58 }
59
60 std::vector<const BigMemoryObject *> MEDFileMesh::getDirectChildrenWithNull() const
61 {
62   std::vector<const BigMemoryObject *> ret(1);
63   ret[0]=(const MEDFileEquivalences *)_equiv;
64   return ret;
65 }
66
67 /*!
68  * Returns a new MEDFileMesh holding the mesh data that has been read from a given MED
69  * file. The first mesh in the file is loaded.
70  *  \param [in] fileName - the name of MED file to read.
71  *  \return MEDFileMesh * - a new instance of MEDFileMesh. The caller is to delete this
72  *          mesh using decrRef() as it is no more needed. 
73  *  \throw If the file is not readable.
74  *  \throw If there is no meshes in the file.
75  *  \throw If the mesh in the file is of a not supported type.
76  */
77 MEDFileMesh *MEDFileMesh::New(const std::string& fileName, MEDFileMeshReadSelector *mrs)
78 {
79   std::vector<std::string> ms=MEDCoupling::GetMeshNames(fileName);
80   if(ms.empty())
81     {
82       std::ostringstream oss; oss << "MEDFileMesh::New : no meshes in file \"" << fileName << "\" !";
83       throw INTERP_KERNEL::Exception(oss.str().c_str());
84     }
85   MEDFileUtilities::CheckFileForRead(fileName);
86   MEDCoupling::MEDCouplingMeshType meshType;
87   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
88   int dt,it;
89   std::string dummy2;
90   MEDCoupling::MEDCouplingAxisType dummy3;
91   MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dummy3,dt,it,dummy2);
92   MCAuto<MEDFileMesh> ret;
93   switch(meshType)
94   {
95     case UNSTRUCTURED:
96       {
97         ret=MEDFileUMesh::New();
98         break;
99       }
100     case CARTESIAN:
101       {
102         ret=MEDFileCMesh::New();
103         break;
104       }
105     case CURVE_LINEAR:
106       {
107         ret=MEDFileCurveLinearMesh::New();
108         break;
109       }
110     default:
111       {
112         std::ostringstream oss; oss << "MEDFileMesh::New : MED file exists and has mesh '" << ms.front() << "' exists but unsupported type yet !";
113         throw INTERP_KERNEL::Exception(oss.str().c_str());
114       }
115   }
116   ret->loadLLWithAdditionalItems(fid,ms.front(),dt,it,mrs);
117   return ret.retn();
118 }
119
120 /*!
121  * Returns a new MEDFileMesh holding the mesh data that has been read from a given MED
122  * file. The mesh to load is specified by its name and numbers of a time step and an
123  * iteration.
124  *  \param [in] fileName - the name of MED file to read.
125  *  \param [in] mName - the name of the mesh to read.
126  *  \param [in] dt - the number of a time step.
127  *  \param [in] it - the number of an iteration.
128  *  \param [in] joints - the sub-domain joints to use instead of those that can be read
129  *          from the MED file. Usually this joints are those just read by another iteration
130  *          of mName mesh, when this method is called by MEDFileMeshMultiTS::New()
131  *  \return MEDFileMesh * - a new instance of MEDFileMesh. The caller is to delete this
132  *          mesh using decrRef() as it is no more needed. 
133  *  \throw If the file is not readable.
134  *  \throw If there is no mesh with given attributes in the file.
135  *  \throw If the mesh in the file is of a not supported type.
136  */
137 MEDFileMesh *MEDFileMesh::New(const std::string& fileName, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs, MEDFileJoints* joints)
138 {
139   MEDFileUtilities::CheckFileForRead(fileName);
140   MEDCoupling::MEDCouplingMeshType meshType;
141   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
142   int dummy0,dummy1;
143   std::string dummy2;
144   MEDCoupling::MEDCouplingAxisType dummy3;
145   MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy3,dummy0,dummy1,dummy2);
146   MCAuto<MEDFileMesh> ret;
147   switch(meshType)
148   {
149     case UNSTRUCTURED:
150       {
151         ret=MEDFileUMesh::New();
152         break;
153       }
154     case CARTESIAN:
155       {
156         ret=MEDFileCMesh::New();
157         break;
158       }
159     case CURVE_LINEAR:
160       {
161         ret=MEDFileCurveLinearMesh::New();
162         break;
163       }
164     default:
165       {
166         std::ostringstream oss; oss << "MEDFileMesh::New : MED file exists and has mesh '" << mName << "' exists but unsupported type yet !";
167         throw INTERP_KERNEL::Exception(oss.str().c_str());
168       }
169   }
170   ret->loadLLWithAdditionalItems(fid,mName,dt,it,mrs);
171   return ret.retn();
172 }
173
174 /*!
175  * Writes \a this mesh into an open MED file specified by its descriptor.
176  *  \param [in] fid - the MED file descriptor.
177  *  \throw If the mesh name is not set.
178  *  \throw If the file is open for reading only.
179  *  \throw If the writing mode == 1 and the same data is present in an existing file.
180  */
181 void MEDFileMesh::write(med_idt fid) const
182 {
183   if(!existsFamily(0))
184     const_cast<MEDFileMesh *>(this)->addFamily(DFT_FAM_NAME,0);
185   if(_name.empty())
186     throw INTERP_KERNEL::Exception("MEDFileMesh : name is empty. MED file ask for a NON EMPTY name !");
187   writeLL(fid);
188   writeJoints(fid);
189   const MEDFileEquivalences *eqs(_equiv);
190   if(eqs)
191     eqs->write(fid);
192 }
193
194 /*!
195  * Writes \a this mesh into a MED file specified by its name.
196  *  \param [in] fileName - the MED file name.
197  *  \param [in] mode - the writing mode. For more on \a mode, see \ref AdvMEDLoaderBasics.
198  * - 2 - erase; an existing file is removed.
199  * - 1 - append; same data should not be present in an existing file.
200  * - 0 - overwrite; same data present in an existing file is overwritten.
201  *  \throw If the mesh name is not set.
202  *  \throw If \a mode == 1 and the same data is present in an existing file.
203  */
204 void MEDFileMesh::write(const std::string& fileName, int mode) const
205 {
206   med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode);
207   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),medmod);
208   std::ostringstream oss; oss << "MEDFileMesh : error on attempt to write in file : \"" << fileName << "\""; 
209   MEDFileUtilities::CheckMEDCode(fid,fid,oss.str());
210   write(fid);
211 }
212
213 /*!
214  * Checks if \a this and another mesh are equal.
215  *  \param [in] other - the mesh to compare with.
216  *  \param [in] eps - a precision used to compare real values.
217  *  \param [in,out] what - the string returning description of unequal data.
218  *  \return bool - \c true if the meshes are equal, \c false, else.
219  */
220 bool MEDFileMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
221 {
222   if(_order!=other->_order)
223     {
224       what="Orders differ !";
225       return false;
226     }
227   if(_iteration!=other->_iteration)
228     {
229       what="Iterations differ !";
230       return false;
231     }
232   if(fabs(_time-other->_time)>eps)
233     {
234       what="Time values differ !";
235       return false;
236     }
237   if(_dt_unit!=other->_dt_unit)
238     {
239       what="Time units differ !";
240       return false;
241     }
242   if(_name!=other->_name)
243     {
244       what="Names differ !";
245       return false;
246     }
247   //univ_name has been ignored -> not a bug because it is a mutable attribute
248   if(_desc_name!=other->_desc_name)
249     {
250       what="Description names differ !";
251       return false;
252     }
253   if(!areGrpsEqual(other,what))
254     return false;
255   if(!areFamsEqual(other,what))
256     return false;
257   if(!areEquivalencesEqual(other,what))
258     return false;
259   return true;
260 }
261
262 void MEDFileMesh::setName(const std::string& name)
263 {
264   _name=name;
265 }
266
267 /*!
268  * Clears redundant attributes of incorporated data arrays.
269  */
270 void MEDFileMesh::clearNonDiscrAttributes() const
271 {
272
273 }
274
275 bool MEDFileMesh::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab)
276 {
277   for(std::vector< std::pair<std::string,std::string> >::const_iterator it=modifTab.begin();it!=modifTab.end();it++)
278     {
279       if((*it).first==_name)
280         {
281           _name=(*it).second;
282           return true;
283         }
284     }
285   return false;
286 }
287
288 /*!
289  * Copies data on groups and families from another mesh.
290  *  \param [in] other - the mesh to copy the data from.
291  */
292 void MEDFileMesh::copyFamGrpMapsFrom(const MEDFileMesh& other)
293 {
294   _groups=other._groups;
295   _families=other._families;
296 }
297
298
299 /*!
300  * This method clear all the groups in the map.
301  * So this method does not operate at all on arrays.
302  * So this method can lead to orphan families.
303  * 
304  * \sa MEDFileMesh::clearFamMap, MEDFileMesh::clearFamGrpMaps
305  */
306 void MEDFileMesh::clearGrpMap()
307 {
308   _groups.clear();
309 }
310
311 /*!
312  * This method clear all the families in the map.
313  * So this method does not operate at all on arrays.
314  * WARNING ! if there are some groups lying on cleared families, those groups will be impacted !
315  *
316  * \sa MEDFileMesh::clearFamMap, MEDFileMesh::clearFamGrpMaps
317  */
318 void MEDFileMesh::clearFamMap()
319 {
320   _families.clear();
321 }
322
323 /*!
324  * This method clear all the families and groups in the map.
325  * So this method does not operate at all on arrays.
326  * As all groups and families entry will be removed after 
327  * the call of MEDFileMesh::setFamilyFieldArr method with 0 or None (python) in the 2nd parameter can be useful to reduce the size of the object.
328  *
329  * \sa MEDFileMesh::clearFamMap, MEDFileMesh::clearFamMap
330  */
331 void MEDFileMesh::clearFamGrpMaps()
332 {
333   clearGrpMap();
334   clearFamMap();
335 }
336
337 /*!
338  * Returns names of families constituting a group.
339  *  \param [in] name - the name of the group of interest.
340  *  \return std::vector<std::string> - a sequence of names of the families.
341  *  \throw If the name of a nonexistent group is specified.
342  */
343 std::vector<std::string> MEDFileMesh::getFamiliesOnGroup(const std::string& name) const
344 {
345   std::string oname(name);
346   std::map<std::string, std::vector<std::string> >::const_iterator it=_groups.find(oname);
347   if(it==_groups.end())
348     {
349       std::vector<std::string> grps=getGroupsNames();
350       std::ostringstream oss; oss << "No such groupname \"" << name << "\" !\nAvailable groups are :";
351       std::copy(grps.begin(),grps.end(),std::ostream_iterator<std::string>(oss," "));
352       throw INTERP_KERNEL::Exception(oss.str().c_str());
353     }
354   return (*it).second;
355 }
356
357 /*!
358  * Returns names of families constituting some groups.
359  *  \param [in] grps - a sequence of names of groups of interest.
360  *  \return std::vector<std::string> - a sequence of names of the families.
361  *  \throw If a name of a nonexistent group is present in \a grps.
362  */
363 std::vector<std::string> MEDFileMesh::getFamiliesOnGroups(const std::vector<std::string>& grps) const
364 {
365   std::set<std::string> fams;
366   for(std::vector<std::string>::const_iterator it=grps.begin();it!=grps.end();it++)
367     {
368       std::map<std::string, std::vector<std::string> >::const_iterator it2=_groups.find(*it);
369       if(it2==_groups.end())
370         {
371           std::ostringstream oss; oss << "No such group in mesh \"" << _name << "\" : " << *it; 
372           std::vector<std::string> grps2=getGroupsNames(); oss << "\" !\nAvailable groups are :";
373           std::copy(grps2.begin(),grps2.end(),std::ostream_iterator<std::string>(oss," "));
374           throw INTERP_KERNEL::Exception(oss.str().c_str());
375         }
376       fams.insert((*it2).second.begin(),(*it2).second.end());
377     }
378   std::vector<std::string> fams2(fams.begin(),fams.end());
379   return fams2;
380 }
381
382 /*!
383  * Returns ids of families constituting a group.
384  *  \param [in] name - the name of the group of interest.
385  *  \return std::vector<int> - sequence of ids of the families.
386  *  \throw If the name of a nonexistent group is specified.
387  */
388 std::vector<int> MEDFileMesh::getFamiliesIdsOnGroup(const std::string& name) const
389 {
390   std::string oname(name);
391   std::map<std::string, std::vector<std::string> >::const_iterator it=_groups.find(oname);
392   std::vector<std::string> grps=getGroupsNames();
393   if(it==_groups.end())
394     {
395       std::ostringstream oss; oss << "No such groupname \"" << name << "\" !\nAvailable groups are :";
396       std::copy(grps.begin(),grps.end(),std::ostream_iterator<std::string>(oss," "));
397       throw INTERP_KERNEL::Exception(oss.str().c_str());
398     }
399   return getFamiliesIds((*it).second);
400 }
401
402 /*!
403  * Sets names of families constituting a group. If data on families of this group is
404  * already present, it is overwritten. Every family in \a fams is checked, and if a
405  family is not yet in \a this mesh, the default group id \c 0 is assigned to it.
406  *  \param [in] name - the name of the group of interest.
407  *  \param [in] fams - a sequence of names of families constituting the group.
408  */
409 void MEDFileMesh::setFamiliesOnGroup(const std::string& name, const std::vector<std::string>& fams)
410 {
411   std::string oname(name);
412   _groups[oname]=fams;
413   for(std::vector<std::string>::const_iterator it1=fams.begin();it1!=fams.end();it1++)
414     {
415       std::map<std::string,int>::iterator it2=_families.find(*it1);
416       if(it2==_families.end())
417         _families[*it1]=0;
418     }
419 }
420
421 /*!
422  * Sets families constituting a group. The families are specified by their ids.
423  * If a family name is not found by its id, an exception is thrown.
424  * If several families have same id, the first one in lexical order is taken.
425  *  \param [in] name - the name of the group of interest.
426  *  \param [in] famIds - a sequence of ids of families constituting the group.
427  *  \throw If a family name is not found by its id.
428  */
429 void MEDFileMesh::setFamiliesIdsOnGroup(const std::string& name, const std::vector<int>& famIds)
430 {
431   std::string oname(name);
432   std::vector<std::string> fams(famIds.size());
433   int i=0;
434   for(std::vector<int>::const_iterator it1=famIds.begin();it1!=famIds.end();it1++,i++)
435     {
436       std::string name2=getFamilyNameGivenId(*it1);
437       fams[i]=name2;
438     }
439   _groups[oname]=fams;
440 }
441
442 /*!
443  * Returns names of groups including a given family.
444  *  \param [in] name - the name of the family of interest.
445  *  \return std::vector<std::string> - a sequence of names of groups including the family.
446  */
447 std::vector<std::string> MEDFileMesh::getGroupsOnFamily(const std::string& name) const
448 {
449   std::vector<std::string> ret;
450   for(std::map<std::string, std::vector<std::string> >::const_iterator it1=_groups.begin();it1!=_groups.end();it1++)
451     {
452       for(std::vector<std::string>::const_iterator it2=(*it1).second.begin();it2!=(*it1).second.end();it2++)
453         if((*it2)==name)
454           {
455             ret.push_back((*it1).first);
456             break;
457           }
458     }
459   return ret;
460 }
461
462 /*!
463  * Adds an existing family to groups.
464  *  \param [in] famName - a name of family to add to \a grps.
465  *  \param [in] grps - a sequence of group names to add the family in.
466  *  \throw If a family named \a famName not yet exists.
467  */
468 void MEDFileMesh::setGroupsOnFamily(const std::string& famName, const std::vector<std::string>& grps)
469 {
470   std::string fName(famName);
471   const std::map<std::string,int>::const_iterator it=_families.find(fName);
472   if(it==_families.end())
473     {
474       std::vector<std::string> fams=getFamiliesNames();
475       std::ostringstream oss; oss << "No such familyname \"" << fName << "\" !\nAvailable families are :";
476       std::copy(fams.begin(),fams.end(),std::ostream_iterator<std::string>(oss," "));
477       throw INTERP_KERNEL::Exception(oss.str().c_str());
478     }
479   for(std::vector<std::string>::const_iterator it3=grps.begin();it3!=grps.end();it3++)
480     {
481       std::map< std::string, std::vector<std::string> >::iterator it2=_groups.find(*it3);
482       if(it2!=_groups.end())
483         (*it2).second.push_back(fName);
484       else
485         {
486           std::vector<std::string> grps2(1,fName);
487           _groups[*it3]=grps2;
488         }
489     }
490 }
491
492 /*!
493  * Returns names of all groups of \a this mesh.
494  *  \return std::vector<std::string> - a sequence of group names.
495  */
496 std::vector<std::string> MEDFileMesh::getGroupsNames() const
497 {
498   std::vector<std::string> ret(_groups.size());
499   int i=0;
500   for(std::map<std::string, std::vector<std::string> >::const_iterator it=_groups.begin();it!=_groups.end();it++,i++)
501     ret[i]=(*it).first;
502   return ret;
503 }
504
505 /*!
506  * Returns names of all families of \a this mesh.
507  *  \return std::vector<std::string> - a sequence of family names.
508  */
509 std::vector<std::string> MEDFileMesh::getFamiliesNames() const
510 {
511   std::vector<std::string> ret(_families.size());
512   int i=0;
513   for(std::map<std::string, int >::const_iterator it=_families.begin();it!=_families.end();it++,i++)
514     ret[i]=(*it).first;
515   return ret;
516 }
517
518 /*!
519  * Returns names of all families of \a this mesh but like they would be in file.
520  * This method is here only for MED file families gurus. If you are a kind user forget this method :-)
521  * This method is only useful for aggressive users that want to have in their file a same family lying both on cells and on nodes. This is not a good idea for lisibility !
522  * For your information internaly in memory such families are renamed to have a nicer API.
523  */
524 std::vector<std::string> MEDFileMesh::getFamiliesNamesWithFilePointOfView() const
525 {
526   std::vector<std::string> ret(getFamiliesNames());
527   MEDFileMeshL2::RenameFamiliesFromMemToFile(ret);
528   return ret;
529 }
530
531 /*!
532  * Returns names of groups that partly or fully appear on the level \a meshDimRelToMaxExt.
533  *  \param [in] meshDimRelToMaxExt - a relative dimension of interest.
534  *  \return std::vector<std::string> - a sequence of group names at \a meshDimRelToMaxExt
535  *          level. 
536  */
537 std::vector<std::string> MEDFileMesh::getGroupsOnSpecifiedLev(int meshDimRelToMaxExt) const
538 {
539   std::vector<std::string> ret;
540   std::vector<std::string> allGrps(getGroupsNames());
541   for(std::vector<std::string>::const_iterator it=allGrps.begin();it!=allGrps.end();it++)
542     {
543       std::vector<int> levs(getGrpNonEmptyLevelsExt((*it)));
544       if(std::find(levs.begin(),levs.end(),meshDimRelToMaxExt)!=levs.end())
545         ret.push_back(*it);
546     }
547   return ret;
548 }
549
550 /*!
551  * Returns all relative mesh levels (including nodes) where a given group is defined.
552  *  \param [in] grp - the name of the group of interest.
553  *  \return std::vector<int> - a sequence of the relative dimensions.
554  */
555 std::vector<int> MEDFileMesh::getGrpNonEmptyLevelsExt(const std::string& grp) const
556 {
557   std::vector<std::string> fams(getFamiliesOnGroup(grp));
558   return getFamsNonEmptyLevelsExt(fams);
559 }
560
561 /*!
562  * Returns all relative mesh levels (**excluding nodes**) where given groups are defined.
563  * To include nodes, call getGrpsNonEmptyLevelsExt() method.
564  *  \param [in] grps - a sequence of names of the groups of interest.
565  *  \return std::vector<int> - a sequence of the relative dimensions.
566  */
567 std::vector<int> MEDFileMesh::getGrpsNonEmptyLevels(const std::vector<std::string>& grps) const
568 {
569   std::vector<std::string> fams(getFamiliesOnGroups(grps));
570   return getFamsNonEmptyLevels(fams);
571 }
572
573 /*!
574  * Returns all relative mesh levels (including nodes) where given groups are defined.
575  *  \param [in] grps - a sequence of names of the groups of interest.
576  *  \return std::vector<int> - a sequence of the relative dimensions.
577  */
578 std::vector<int> MEDFileMesh::getGrpsNonEmptyLevelsExt(const std::vector<std::string>& grps) const
579 {
580   std::vector<std::string> fams(getFamiliesOnGroups(grps));
581   return getFamsNonEmptyLevelsExt(fams);
582 }
583
584 /*!
585  * Returns all relative mesh levels (**excluding nodes**) where a given group is defined.
586  * To include nodes, call getGrpNonEmptyLevelsExt() method.
587  *  \param [in] grp - the name of the group of interest.
588  *  \return std::vector<int> - a sequence of the relative dimensions.
589  */
590 std::vector<int> MEDFileMesh::getGrpNonEmptyLevels(const std::string& grp) const
591 {
592   std::vector<std::string> fams(getFamiliesOnGroup(grp));
593   return getFamsNonEmptyLevels(fams);
594 }
595
596 /*!
597  * Returns all relative mesh levels (**excluding nodes**) where a given family is defined.
598  * To include nodes, call getFamNonEmptyLevelsExt() method.
599  *  \param [in] fam - the name of the family of interest.
600  *  \return std::vector<int> - a sequence of the relative dimensions.
601  */
602 std::vector<int> MEDFileMesh::getFamNonEmptyLevels(const std::string& fam) const
603 {
604   std::vector<std::string> fams(1,std::string(fam));
605   return getFamsNonEmptyLevels(fams);
606 }
607
608 /*!
609  * Returns all relative mesh levels (including nodes) where a given family is defined.
610  *  \param [in] fam - the name of the family of interest.
611  *  \return std::vector<int> - a sequence of the relative dimensions.
612  */
613 std::vector<int> MEDFileMesh::getFamNonEmptyLevelsExt(const std::string& fam) const
614 {
615   std::vector<std::string> fams(1,std::string(fam));
616   return getFamsNonEmptyLevelsExt(fams);
617 }
618
619 std::string MEDFileMesh::GetMagicFamilyStr()
620 {
621   return std::string(MEDFileMeshL2::ZE_SEP_FOR_FAMILY_KILLERS);
622 }
623
624 /*!
625  * Changes a name of every family, included in one group only, to be same as the group name.
626  *  \throw If there are families with equal names in \a this mesh.
627  */
628 void MEDFileMesh::assignFamilyNameWithGroupName()
629 {
630   std::map<std::string, std::vector<std::string> > groups(_groups);
631   std::map<std::string,int> newFams;
632   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
633     {
634       std::vector<std::string> grps=getGroupsOnFamily((*it).first);
635       if(grps.size()==1 && groups[grps[0]].size()==1)
636         {
637           if(newFams.find(grps[0])!=newFams.end())
638             {
639               std::ostringstream oss; oss << "MEDFileMesh::assignFamilyNameWithGroupName : Family \"" << grps[0] << "\" already exists !";
640               throw INTERP_KERNEL::Exception(oss.str().c_str());
641             }
642           newFams[grps[0]]=(*it).second;
643           std::vector<std::string>& grps2=groups[grps[0]];
644           std::size_t pos=std::distance(grps2.begin(),std::find(grps2.begin(),grps2.end(),(*it).first));
645           grps2[pos]=grps[0];
646         }
647       else
648         {
649           if(newFams.find((*it).first)!=newFams.end())
650             {
651               std::ostringstream oss; oss << "MEDFileMesh::assignFamilyNameWithGroupName : Family \"" << (*it).first << "\" already exists !";
652               throw INTERP_KERNEL::Exception(oss.str().c_str());
653             }
654           newFams[(*it).first]=(*it).second;
655         }
656     }
657   _families=newFams;
658   _groups=groups;
659 }
660
661 /*!
662  * Removes all groups lying on no family. If there is no empty groups, \a this is let untouched.
663  * 
664  * \return the removed groups.
665  */
666 std::vector<std::string> MEDFileMesh::removeEmptyGroups()
667 {
668   std::vector<std::string> ret;
669   std::map<std::string, std::vector<std::string> > newGrps;
670   for(std::map<std::string, std::vector<std::string> >::const_iterator it=_groups.begin();it!=_groups.end();it++)
671     {
672       if((*it).second.empty())
673         ret.push_back((*it).first);
674       else
675         newGrps[(*it).first]=(*it).second;
676     }
677   if(!ret.empty())
678     _groups=newGrps;
679   return ret;
680 }
681
682 /*!
683  * Removes a group from \a this mesh.
684  *  \param [in] name - the name of the group to remove.
685  *  \throw If no group with such a \a name exists.
686  */
687 void MEDFileMesh::removeGroup(const std::string& name)
688 {
689   std::string oname(name);
690   std::map<std::string, std::vector<std::string> >::iterator it=_groups.find(oname);
691   std::vector<std::string> grps=getGroupsNames();
692   if(it==_groups.end())
693     {
694       std::ostringstream oss; oss << "No such groupname \"" << name << "\" !\nAvailable groups are :";
695       std::copy(grps.begin(),grps.end(),std::ostream_iterator<std::string>(oss," "));
696       throw INTERP_KERNEL::Exception(oss.str().c_str());
697     }
698   _groups.erase(it);
699 }
700
701 /*!
702  * Removes a family from \a this mesh.
703  *  \param [in] name - the name of the family to remove.
704  *  \throw If no family with such a \a name exists.
705  */
706 void MEDFileMesh::removeFamily(const std::string& name)
707 {
708   std::string oname(name);
709   std::map<std::string, int >::iterator it=_families.find(oname);
710   std::vector<std::string> fams=getFamiliesNames();
711   if(it==_families.end())
712     {
713       std::ostringstream oss; oss << "No such familyname \"" << name << "\" !\nAvailable families are :";
714       std::copy(fams.begin(),fams.end(),std::ostream_iterator<std::string>(oss," "));
715       throw INTERP_KERNEL::Exception(oss.str().c_str());
716     }
717   _families.erase(it);
718   for(std::map<std::string, std::vector<std::string> >::iterator it3=_groups.begin();it3!=_groups.end();it3++)
719     {
720       std::vector<std::string>& v=(*it3).second;
721       std::vector<std::string>::iterator it4=std::find(v.begin(),v.end(),oname);
722       if(it4!=v.end())
723         v.erase(it4);
724     }
725 }
726
727 /*!
728  * Removes all groups in \a this that are orphan. A group is orphan if this group lies on
729  * a set of families, themselves orphan. A family is said orphan if its id appears nowhere in
730  * family field whatever its level. This method also suppresses the orphan families.
731  * 
732  * \return - The list of removed groups names. 
733  *
734  * \sa MEDFileMesh::removeOrphanFamilies.
735  */
736 std::vector<std::string> MEDFileMesh::removeOrphanGroups()
737 {
738   removeOrphanFamilies();
739   return removeEmptyGroups();
740 }
741
742 /*!
743  * Removes all families in \a this that are orphan. A family is said orphan if its id appears nowhere in
744  * family field whatever its level. Groups are updated in consequence, that is to say all groups lying on orphan family, will see their families list modified.
745  * 
746  * \return - The list of removed families names.
747  * \sa MEDFileMesh::removeOrphanGroups.
748  */
749 std::vector<std::string> MEDFileMesh::removeOrphanFamilies()
750 {
751   MCAuto<DataArrayInt> allFamIdsInUse=computeAllFamilyIdsInUse();
752   std::vector<std::string> ret;
753   if(!((DataArrayInt*)allFamIdsInUse))
754     {
755       ret=getFamiliesNames();
756       _families.clear(); _groups.clear();
757       return ret;
758     }
759   std::map<std::string,int> famMap;
760   std::map<std::string, std::vector<std::string> > grps(_groups);
761   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
762     {
763       if(allFamIdsInUse->presenceOfValue((*it).second))
764         famMap[(*it).first]=(*it).second;
765       else
766         {
767           ret.push_back((*it).first);
768           std::vector<std::string> grpsOnEraseFam=getGroupsOnFamily((*it).first);
769           for(std::vector<std::string>::const_iterator it2=grpsOnEraseFam.begin();it2!=grpsOnEraseFam.end();it2++)
770             {
771               std::map<std::string, std::vector<std::string> >::iterator it3=grps.find(*it2);//it3!=grps.empty() thanks to copy
772               std::vector<std::string>& famv=(*it3).second;
773               std::vector<std::string>::iterator it4=std::find(famv.begin(),famv.end(),(*it).first);//it4!=famv.end() thanks to copy
774               famv.erase(it4);
775             }
776         }
777     }
778   if(!ret.empty())
779     { _families=famMap; _groups=grps; }
780   return ret;
781 }
782
783 /*!
784  * This method operates only on maps in \a this. The arrays are not considered here. So this method will remove a family (except "FAMILLE_ZERO" family) if no group lies on it whatever
785  * this family is orphan or not.
786  *
787  * \warning this method is different from removeOrphanFamilies that scans family field array to find orphan families.
788  */
789 void MEDFileMesh::removeFamiliesReferedByNoGroups()
790 {
791   std::map<std::string,int> fams;
792   std::set<std::string> sfams;
793   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
794     sfams.insert((*it).first);
795   for(std::map<std::string, std::vector<std::string> >::const_iterator it0=_groups.begin();it0!=_groups.end();it0++)
796     for(std::vector<std::string>::const_iterator it1=(*it0).second.begin();it1!=(*it0).second.end();it1++)
797       sfams.erase(*it1);
798   for(std::set<std::string>::const_iterator it=sfams.begin();it!=sfams.end();it++)
799     if(*it!=DFT_FAM_NAME)
800       _families.erase(*it);
801 }
802
803 /*!
804  * This method has no impact on groups. This method only works on families. This method firstly removes families not refered by any groups in \a this, then all unused entities
805  * are put as belonging to family 0 ("FAMILLE_ZERO"). Finally, all orphanFamilies are killed.
806  * This method raises an exception if "FAMILLE_ZERO" is already belonging to a group.
807  *
808  * \sa MEDFileMesh::removeOrphanFamilies
809  */
810 void MEDFileMesh::rearrangeFamilies()
811 {
812   checkOrphanFamilyZero();
813   removeFamiliesReferedByNoGroups();
814   //
815   std::vector<int> levels(getNonEmptyLevelsExt());
816   std::set<int> idsRefed;
817   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
818     idsRefed.insert((*it).second);
819   for(std::vector<int>::const_iterator it=levels.begin();it!=levels.end();it++)
820     {
821       const DataArrayInt *fams(0);
822       try
823       {
824           fams=getFamilyFieldAtLevel(*it);
825       }
826       catch(INTERP_KERNEL::Exception& e) { }
827       if(!fams)
828         continue;
829       std::vector<bool> v(fams->getNumberOfTuples(),false);
830       for(std::set<int>::const_iterator pt=idsRefed.begin();pt!=idsRefed.end();pt++)
831         fams->switchOnTupleEqualTo(*pt,v);
832       MCAuto<DataArrayInt> unfetchedIds(DataArrayInt::BuildListOfSwitchedOff(v));
833       if(!unfetchedIds->empty())
834         {
835           MCAuto<DataArrayInt> newFams(fams->deepCopy());
836           newFams->setPartOfValuesSimple3(0,unfetchedIds->begin(),unfetchedIds->end(),0,1,1);
837           setFamilyFieldArr(*it,newFams);
838         }
839     }
840   removeOrphanFamilies();
841 }
842
843 /*!
844  * This method only checks that "FAMILLE_ZERO" is orphan (not belonging to a group).
845  */
846 void MEDFileMesh::checkOrphanFamilyZero() const
847 {
848   for(std::map<std::string, std::vector<std::string> >::const_iterator it=_groups.begin();it!=_groups.end();it++)
849     {
850       if(std::find((*it).second.begin(),(*it).second.end(),DFT_FAM_NAME)!=(*it).second.end())
851         {
852           std::ostringstream oss; oss << "MEDFileMesh::rearrangeFamilies : Groups \"" << (*it).first << "\" is lying on family \"" << DFT_FAM_NAME << "\" !";
853           throw INTERP_KERNEL::Exception(oss.str().c_str());
854         }
855     }
856 }
857
858 /*!
859  * Renames a group in \a this mesh.
860  *  \param [in] oldName - a current name of the group to rename.
861  *  \param [in] newName - a new group name.
862  *  \throw If no group named \a oldName exists in \a this mesh.
863  *  \throw If a group named \a newName already exists.
864  */
865 void MEDFileMesh::changeGroupName(const std::string& oldName, const std::string& newName)
866 {
867   std::string oname(oldName);
868   std::map<std::string, std::vector<std::string> >::iterator it=_groups.find(oname);
869   std::vector<std::string> grps=getGroupsNames();
870   if(it==_groups.end())
871     {
872       std::ostringstream oss; oss << "No such groupname \"" << oldName << "\" !\nAvailable groups are :";
873       std::copy(grps.begin(),grps.end(),std::ostream_iterator<std::string>(oss," "));
874       throw INTERP_KERNEL::Exception(oss.str().c_str());
875     }
876   std::string nname(newName);
877   std::map<std::string, std::vector<std::string> >::iterator it2=_groups.find(nname);
878   if(it2!=_groups.end())
879     {
880       std::ostringstream oss; oss << "Such groupname \"" << newName << "\" already exists ! Kill it before !";
881       throw INTERP_KERNEL::Exception(oss.str().c_str());
882     }
883   std::vector<std::string> cpy=(*it).second;
884   _groups.erase(it);
885   _groups[newName]=cpy;
886 }
887
888 /*!
889  * Changes an id of a family in \a this mesh. 
890  * This method calls changeFamilyIdArr().
891  *  \param [in] oldId - a current id of the family.
892  *  \param [in] newId - a new family id.
893  */
894 void MEDFileMesh::changeFamilyId(int oldId, int newId)
895 {
896   changeFamilyIdArr(oldId,newId);
897   std::map<std::string,int> fam2;
898   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
899     {
900       if((*it).second==oldId)
901         fam2[(*it).first]=newId;
902       else
903         fam2[(*it).first]=(*it).second;
904     }
905   _families=fam2;
906 }
907
908 /*!
909  * Renames a family in \a this mesh.
910  *  \param [in] oldName - a current name of the family to rename.
911  *  \param [in] newName - a new family name.
912  *  \throw If no family named \a oldName exists in \a this mesh.
913  *  \throw If a family named \a newName already exists.
914  */
915 void MEDFileMesh::changeFamilyName(const std::string& oldName, const std::string& newName)
916 {
917   std::string oname(oldName);
918   std::map<std::string, int >::iterator it=_families.find(oname);
919   std::vector<std::string> fams=getFamiliesNames();
920   if(it==_families.end())
921     {
922       std::ostringstream oss; oss << "No such familyname \"" << oldName << "\" !\nAvailable families are :";
923       std::copy(fams.begin(),fams.end(),std::ostream_iterator<std::string>(oss," "));
924       throw INTERP_KERNEL::Exception(oss.str().c_str());
925     }
926   std::string nname(newName);
927   std::map<std::string, int >::iterator it2=_families.find(nname);
928   if(it2!=_families.end())
929     {
930       std::ostringstream oss; oss << "Such familyname \"" << newName << " already exists ! Kill it before !";
931       throw INTERP_KERNEL::Exception(oss.str().c_str());
932     }
933   int cpy=(*it).second;
934   _families.erase(it);
935   _families[newName]=cpy;
936   for(std::map<std::string, std::vector<std::string> >::iterator it3=_groups.begin();it3!=_groups.end();it3++)
937     {
938       std::vector<std::string>& v=(*it3).second;
939       std::vector<std::string>::iterator it4=std::find(v.begin(),v.end(),oname);
940       if(it4!=v.end())
941         (*it4)=nname;
942     }
943 }
944
945 /*!
946  * Checks if \a this and another mesh contains the same families.
947  *  \param [in] other - the mesh to compare with \a this one.
948  *  \param [in,out] what - an unused parameter.
949  *  \return bool - \c true if number of families and their ids are the same in the two
950  *          meshes. Families with the id == \c 0 are not considered.
951  */
952 bool MEDFileMesh::areFamsEqual(const MEDFileMesh *other, std::string& what) const
953 {
954   if(_families==other->_families)
955     return true;
956   std::map<std::string,int> fam0;
957   std::map<std::string,int> fam1;
958   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
959     if((*it).second!=0)
960       fam0[(*it).first]=(*it).second;
961   for(std::map<std::string,int>::const_iterator it=other->_families.begin();it!=other->_families.end();it++)
962     if((*it).second!=0)
963       fam1[(*it).first]=(*it).second;
964   return fam0==fam1;
965 }
966
967 /*!
968  * Checks if \a this and another mesh contains the same groups.
969  *  \param [in] other - the mesh to compare with \a this one.
970  *  \param [in,out] what - a string describing a difference of groups of the two meshes
971  *          in case if this method returns \c false.
972  *  \return bool - \c true if number of groups and families constituting them are the
973  *          same in the two meshes.
974  */
975 bool MEDFileMesh::areGrpsEqual(const MEDFileMesh *other, std::string& what) const
976 {
977   if(_groups==other->_groups)
978     return true;
979   bool ret=true;
980   std::size_t sz=_groups.size();
981   if(sz!=other->_groups.size())
982     {
983       what="Groups differ because not same number !\n";
984       ret=false;
985     }
986   if(ret)
987     {
988       std::map<std::string, std::vector<std::string> >::const_iterator it1=_groups.begin();
989       for(std::size_t i=0;i<sz && ret;i++,it1++)
990         {
991           std::map<std::string, std::vector<std::string> >::const_iterator it2=other->_groups.find((*it1).first);
992           if(it2!=other->_groups.end())
993             {
994               std::set<std::string> s1((*it1).second.begin(),(*it1).second.end());
995               std::set<std::string> s2((*it2).second.begin(),(*it2).second.end());
996               ret=(s1==s2);
997             }
998           else
999             {
1000               ret=false;
1001               what="A group in first mesh exists not in other !\n";
1002             }
1003         }
1004     }
1005   if(!ret)
1006     {
1007       std::ostringstream oss; oss << "Groups description differs :\n";
1008       oss << "First group description :\n";
1009       for(std::map<std::string, std::vector<std::string> >::const_iterator it=_groups.begin();it!=_groups.end();it++)
1010         {
1011           oss << " Group \"" << (*it).first << "\" on following families :\n";
1012           for(std::vector<std::string>::const_iterator it2=(*it).second.begin();it2!=(*it).second.end();it2++)
1013             oss << "    \"" << *it2 << "\n";
1014         }
1015       oss << "Second group description :\n";
1016       for(std::map<std::string, std::vector<std::string> >::const_iterator it=other->_groups.begin();it!=other->_groups.end();it++)
1017         {
1018           oss << " Group \"" << (*it).first << "\" on following families :\n";
1019           for(std::vector<std::string>::const_iterator it2=(*it).second.begin();it2!=(*it).second.end();it2++)
1020             oss << "    \"" << *it2 << "\n";
1021         }
1022       what+=oss.str();
1023     }
1024   return ret;
1025 }
1026
1027 /*!
1028  * Checks if a group with a given name exists in \a this mesh.
1029  *  \param [in] groupName - the group name.
1030  *  \return bool - \c true the group \a groupName exists in \a this mesh.
1031  */
1032 bool MEDFileMesh::existsGroup(const std::string& groupName) const
1033 {
1034   std::string grpName(groupName);
1035   return _groups.find(grpName)!=_groups.end();
1036 }
1037
1038 /*!
1039  * Checks if a family with a given id exists in \a this mesh.
1040  *  \param [in] famId - the family id.
1041  *  \return bool - \c true the family with the id \a famId exists in \a this mesh.
1042  */
1043 bool MEDFileMesh::existsFamily(int famId) const
1044 {
1045   for(std::map<std::string,int>::const_iterator it2=_families.begin();it2!=_families.end();it2++)
1046     if((*it2).second==famId)
1047       return true;
1048   return false;
1049 }
1050
1051 /*!
1052  * Checks if a family with a given name exists in \a this mesh.
1053  *  \param [in] familyName - the family name.
1054  *  \return bool - \c true the family \a familyName exists in \a this mesh.
1055  */
1056 bool MEDFileMesh::existsFamily(const std::string& familyName) const
1057 {
1058   std::string fname(familyName);
1059   return _families.find(fname)!=_families.end();
1060 }
1061
1062 /*!
1063  * Sets an id of a family.
1064  *  \param [in] familyName - the family name.
1065  *  \param [in] id - a new id of the family.
1066  */
1067 void MEDFileMesh::setFamilyId(const std::string& familyName, int id)
1068 {
1069   std::string fname(familyName);
1070   _families[fname]=id;
1071 }
1072
1073 void MEDFileMesh::setFamilyIdUnique(const std::string& familyName, int id)
1074 {
1075   std::string fname(familyName);
1076   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
1077     if((*it).second==id)
1078       {
1079         if((*it).first!=familyName)
1080           {
1081             std::ostringstream oss; oss << "MEDFileMesh::setFamilyIdUnique : Family id #" << id << " is already belonging to family with name \"" << (*it).first << "\" !";
1082             throw INTERP_KERNEL::Exception(oss.str().c_str());
1083           }
1084       }
1085   _families[fname]=id;
1086 }
1087
1088 /*!
1089  * Adds a family to \a this mesh.
1090  *  \param [in] familyName - a name of the family.
1091  *  \param [in] famId - an id of the family.
1092  *  \throw If a family with the same name or id already exists in \a this mesh.
1093  */
1094 void MEDFileMesh::addFamily(const std::string& familyName, int famId)
1095 {
1096   std::string fname(familyName);
1097   std::map<std::string,int>::const_iterator it=_families.find(fname);
1098   if(it==_families.end())
1099     {
1100       for(std::map<std::string,int>::const_iterator it2=_families.begin();it2!=_families.end();it2++)
1101         if((*it2).second==famId)
1102           {
1103             std::ostringstream oss;
1104             oss << "MEDFileMesh::addFamily : Family \"" << (*it2).first << "\" already exists with specified id : " << famId << " !";
1105             throw INTERP_KERNEL::Exception(oss.str().c_str());
1106           }
1107       _families[fname]=famId;
1108     }
1109   else
1110     {
1111       if((*it).second!=famId)
1112         {
1113           std::ostringstream oss;
1114           oss << "MEDFileMesh::addFamily : Family \"" << fname << "\" already exists but has id set to " << (*it).second << " different from asked famId " << famId << " !";
1115           throw INTERP_KERNEL::Exception(oss.str().c_str());
1116         }
1117     }
1118 }
1119
1120 /*!
1121  * Creates a group including all mesh entities of given dimension.
1122  * \warning This method does \b not guarantee that the created group includes mesh
1123  * entities of only \a meshDimRelToMaxExt dimension in the case if some family id is
1124  * present in family fields of different dimensions. To assure this, call
1125  * ensureDifferentFamIdsPerLevel() \b before calling this method.
1126  *  \param [in] meshDimRelToMaxExt - a relative dimension of mesh entities to include to
1127  *          the group.
1128  *  \param [in] groupName - a name of the new group.
1129  *  \throw If a group named \a groupName already exists.
1130  *  \throw If no mesh entities of dimension \a meshDimRelToMaxExt exist in \a this mesh.
1131  *  \throw If no family field of dimension \a meshDimRelToMaxExt is present in \a this mesh.
1132  */
1133 void MEDFileMesh::createGroupOnAll(int meshDimRelToMaxExt, const std::string& groupName)
1134 {
1135   std::string grpName(groupName);
1136   std::vector<int> levs=getNonEmptyLevelsExt();
1137   if(std::find(levs.begin(),levs.end(),meshDimRelToMaxExt)==levs.end())
1138     {
1139       std::ostringstream oss; oss << "MEDFileMesh::createGroupOnAll : The relative ext dimension " << meshDimRelToMaxExt << " is not available !" << std::endl;
1140       oss << "Available relative ext levels are : ";
1141       std::copy(levs.begin(),levs.end(),std::ostream_iterator<int>(oss," "));
1142       throw INTERP_KERNEL::Exception(oss.str().c_str());
1143     }
1144   if(existsGroup(groupName))
1145     {
1146       std::ostringstream oss; oss << "MEDFileMesh::createGroupOnAll : The groups \"" << grpName << "\" already exists in this !" << std::endl;
1147       oss << "Already existing groups are : ";
1148       std::copy(levs.begin(),levs.end(),std::ostream_iterator<int>(oss," "));
1149       oss << std::endl << "Please choose an another group name or call removeGroup(\"" << grpName << "\") method !";
1150       throw INTERP_KERNEL::Exception(oss.str().c_str());
1151     }
1152   const DataArrayInt *fieldFamIds=getFamilyFieldAtLevel(meshDimRelToMaxExt);
1153   if(fieldFamIds==0)
1154     throw INTERP_KERNEL::Exception("MEDFileMesh::createGroupOnAll : Family field arr ids is not defined for this level !");
1155   MCAuto<DataArrayInt> famIds=fieldFamIds->getDifferentValues();
1156   std::vector<std::string> familiesOnWholeGroup;
1157   for(const int *it=famIds->begin();it!=famIds->end();it++)
1158     {
1159       bool tmp;
1160       familiesOnWholeGroup.push_back(findOrCreateAndGiveFamilyWithId(*it,tmp));
1161     }
1162   _groups[grpName]=familiesOnWholeGroup;
1163 }
1164
1165 /*!
1166  * Ensures that given family ids do not present in family fields of dimensions different
1167  * than given ones. If a family id is present in the family fields of dimensions different
1168  * than the given ones, a new family is created and the whole data is updated accordingly.
1169  *  \param [in] famIds - a sequence of family ids to check.
1170  *  \param [in] vMeshDimRelToMaxExt - a sequence of relative dimensions to which the \a
1171  *          famIds should exclusively belong.
1172  *  \return bool - \c true if no modification is done in \a this mesh by this method.
1173  */
1174 bool MEDFileMesh::keepFamIdsOnlyOnLevs(const std::vector<int>& famIds, const std::vector<int>& vMeshDimRelToMaxExt)
1175 {
1176   std::set<int> levsInput(vMeshDimRelToMaxExt.begin(),vMeshDimRelToMaxExt.end());
1177   std::vector<int> levs=getNonEmptyLevelsExt();
1178   std::set<int> levs2(levs.begin(),levs.end());
1179   std::vector<int> levsToTest;
1180   std::set_difference(levs2.begin(),levs2.end(),levsInput.begin(),levsInput.end(),std::back_insert_iterator< std::vector<int> >(levsToTest));
1181   std::set<int> famIds2(famIds.begin(),famIds.end());
1182   bool ret=true;
1183   int maxFamId=1;
1184   if(!_families.empty())
1185     maxFamId=getMaxFamilyId()+1;
1186   std::vector<std::string> allFams=getFamiliesNames();
1187   for(std::vector<int>::const_iterator it=levsToTest.begin();it!=levsToTest.end();it++)
1188     {
1189       const DataArrayInt *fieldFamIds=getFamilyFieldAtLevel(*it);
1190       if(fieldFamIds)
1191         {
1192           MCAuto<DataArrayInt> famIds3=fieldFamIds->getDifferentValues();
1193           std::vector<int> tmp;
1194           std::set_intersection(famIds3->begin(),famIds3->end(),famIds2.begin(),famIds2.end(),std::back_insert_iterator< std::vector<int> >(tmp));
1195           for(std::vector<int>::const_iterator it2=tmp.begin();it2!=tmp.end();it2++)
1196             {
1197               ret=false;
1198               std::string famName=getFamilyNameGivenId(*it2);
1199               std::ostringstream oss; oss << "Family_" << maxFamId;
1200               std::string zeName=CreateNameNotIn(oss.str(),allFams);
1201               addFamilyOnAllGroupsHaving(famName,zeName);
1202               _families[zeName]=maxFamId;
1203               (const_cast<DataArrayInt *>(fieldFamIds))->changeValue(*it2,maxFamId);
1204               maxFamId++;
1205             }
1206         }
1207     }
1208   return ret;
1209 }
1210
1211 /*!
1212  * Adds a family to a given group in \a this mesh. If the group with a given name does
1213  * not exist, it is created.
1214  *  \param [in] grpName - the name of the group to add the family in.
1215  *  \param [in] famName - the name of the family to add to the group named \a grpName.
1216  *  \throw If \a grpName or \a famName is an empty string.
1217  *  \throw If no family named \a famName is present in \a this mesh.
1218  */
1219 void MEDFileMesh::addFamilyOnGrp(const std::string& grpName, const std::string& famName)
1220 {
1221   std::string grpn(grpName);
1222   std::string famn(famName);
1223   if(grpn.empty() || famn.empty())
1224     throw INTERP_KERNEL::Exception("MEDFileMesh::addFamilyOnGrp : input strings must be non null !");
1225   std::vector<std::string> fams=getFamiliesNames();
1226   if(std::find(fams.begin(),fams.end(),famn)==fams.end())
1227     {
1228       std::ostringstream oss; oss << "MEDFileMesh::addFamilyOnGrp : Family \"" << famn << "\" does not exist !" << std::endl;
1229       oss << "Create this family or choose an existing one ! Existing fams are : ";
1230       std::copy(fams.begin(),fams.end(),std::ostream_iterator<std::string>(oss," ")); oss << ".";
1231       throw INTERP_KERNEL::Exception(oss.str().c_str());
1232     }
1233   std::map<std::string, std::vector<std::string> >::iterator it=_groups.find(grpn);
1234   if(it==_groups.end())
1235     {
1236       _groups[grpn].push_back(famn);
1237     }
1238   else
1239     {
1240       std::vector<std::string>::iterator it2=std::find((*it).second.begin(),(*it).second.end(),famn);
1241       if(it2==(*it).second.end())
1242         (*it).second.push_back(famn);
1243     }
1244 }
1245
1246 /*!
1247  * This method adds to all groups lying on family with name 'famName' the other family name 'otherFamName'.
1248  * This method is quite underground because it can lead to unconsistency because family 'otherFamName' is \b not added into _families.
1249  * This method is used by MEDFileMesh::keepFamIdsOnlyOnLevs method.
1250  */
1251 void MEDFileMesh::addFamilyOnAllGroupsHaving(const std::string& famName, const std::string& otherFamName)
1252 {
1253   std::string famNameCpp(famName);
1254   std::string otherCpp(otherFamName);
1255   for(std::map<std::string, std::vector<std::string> >::iterator it=_groups.begin();it!=_groups.end();it++)
1256     {
1257       std::vector<std::string>& v=(*it).second;
1258       if(std::find(v.begin(),v.end(),famNameCpp)!=v.end())
1259         {
1260           v.push_back(otherCpp);
1261         }
1262     }
1263 }
1264
1265 /*!
1266  * \param [in] ids ids and group name of the new group to add. The ids should be sorted and different each other (MED file norm).
1267  * \parma [in,out] famArr family array on level of interest to be renumbered. The input pointer should be not \c NULL (no check of that will be performed)
1268  */
1269 void MEDFileMesh::addGroupUnderground(bool isNodeGroup, const DataArrayInt *ids, DataArrayInt *famArr)
1270 {
1271   if(!ids)
1272     throw INTERP_KERNEL::Exception("MEDFileUMesh::addGroup : NULL pointer in input !");
1273   std::string grpName(ids->getName());
1274   if(grpName.empty())
1275     throw INTERP_KERNEL::Exception("MEDFileUMesh::addGroup : empty group name ! MED file format do not accept empty group name !");
1276   ids->checkStrictlyMonotonic(true);
1277   famArr->incrRef(); MCAuto<DataArrayInt> famArrTmp(famArr);
1278   std::vector<std::string> grpsNames=getGroupsNames();
1279   if(std::find(grpsNames.begin(),grpsNames.end(),grpName)!=grpsNames.end())
1280     {
1281       std::ostringstream oss; oss << "MEDFileUMesh::addGroup : Group with name \"" << grpName << "\" already exists ! Destroy it before calling this method !";
1282       throw INTERP_KERNEL::Exception(oss.str().c_str());
1283     }
1284   std::list< MCAuto<DataArrayInt> > allFamIds(getAllNonNullFamilyIds());
1285   allFamIds.erase(std::find(allFamIds.begin(),allFamIds.end(),famArrTmp));
1286   MCAuto<DataArrayInt> famIds=famArr->selectByTupleIdSafe(ids->begin(),ids->end());
1287   MCAuto<DataArrayInt> diffFamIds=famIds->getDifferentValues();
1288   std::vector<int> familyIds;
1289   std::vector< MCAuto<DataArrayInt> > idsPerfamiliyIds;
1290   int maxVal=getTheMaxAbsFamilyId()+1;
1291   std::map<std::string,int> families(_families);
1292   std::map<std::string, std::vector<std::string> > groups(_groups);
1293   std::vector<std::string> fams;
1294   bool created(false);
1295   for(const int *famId=diffFamIds->begin();famId!=diffFamIds->end();famId++)
1296     {
1297       MCAuto<DataArrayInt> ids2Tmp=famIds->findIdsEqual(*famId);
1298       MCAuto<DataArrayInt> ids2=ids->selectByTupleId(ids2Tmp->begin(),ids2Tmp->end());
1299       MCAuto<DataArrayInt> ids1=famArr->findIdsEqual(*famId);
1300       MCAuto<DataArrayInt> ret0(ids1->buildSubstractionOptimized(ids2));
1301       if(ret0->empty())
1302         {
1303           bool isFamPresent=false;
1304           for(std::list< MCAuto<DataArrayInt> >::const_iterator itl=allFamIds.begin();itl!=allFamIds.end() && !isFamPresent;itl++)
1305             isFamPresent=(*itl)->presenceOfValue(*famId);
1306           if(!isFamPresent)
1307             { familyIds.push_back(*famId); idsPerfamiliyIds.push_back(ret0); fams.push_back(FindOrCreateAndGiveFamilyWithId(families,*famId,created)); } // adding *famId in grp
1308           else
1309             {
1310               familyIds.push_back(isNodeGroup?maxVal:-maxVal); idsPerfamiliyIds.push_back(ids2);
1311               std::string locFamName=FindOrCreateAndGiveFamilyWithId(families,isNodeGroup?maxVal:-maxVal,created);
1312               fams.push_back(locFamName);
1313               if(existsFamily(*famId))
1314                 {
1315                   std::string locFamName2=getFamilyNameGivenId(*famId); std::vector<std::string> v(2); v[0]=locFamName2; v[1]=locFamName;
1316                   ChangeAllGroupsContainingFamily(groups,getFamilyNameGivenId(*famId),v);
1317                 }
1318               maxVal++;
1319             } // modifying all other groups on *famId to lie on maxVal and lie the grp on maxVal
1320         }
1321       else
1322         {
1323           familyIds.push_back(isNodeGroup?maxVal:-maxVal); idsPerfamiliyIds.push_back(ret0); // modifying all other groups on *famId to lie on maxVal and on maxVal+1
1324           familyIds.push_back(isNodeGroup?maxVal+1:-maxVal-1); idsPerfamiliyIds.push_back(ids2);//grp lie only on maxVal+1
1325           std::string n2(FindOrCreateAndGiveFamilyWithId(families,isNodeGroup?maxVal+1:-maxVal-1,created)); fams.push_back(n2);
1326           if(existsFamily(*famId))
1327             {
1328               std::string n1(FindOrCreateAndGiveFamilyWithId(families,isNodeGroup?maxVal:-maxVal,created)); std::vector<std::string> v(2); v[0]=n1; v[1]=n2;
1329               ChangeAllGroupsContainingFamily(groups,getFamilyNameGivenId(*famId),v);
1330             }
1331           maxVal+=2;
1332         }
1333     }
1334   for(std::size_t i=0;i<familyIds.size();i++)
1335     {
1336       DataArrayInt *da=idsPerfamiliyIds[i];
1337       famArr->setPartOfValuesSimple3(familyIds[i],da->begin(),da->end(),0,1,1);
1338     }
1339   _families=families;
1340   _groups=groups;
1341   _groups[grpName]=fams;
1342 }
1343
1344 void MEDFileMesh::changeAllGroupsContainingFamily(const std::string& familyNameToChange, const std::vector<std::string>& newFamiliesNames)
1345 {
1346   ChangeAllGroupsContainingFamily(_groups,familyNameToChange,newFamiliesNames);
1347 }
1348
1349 void MEDFileMesh::ChangeAllGroupsContainingFamily(std::map<std::string, std::vector<std::string> >& groups, const std::string& familyNameToChange, const std::vector<std::string>& newFamiliesNames)
1350 {
1351   std::string fam(familyNameToChange);
1352   for(std::map<std::string, std::vector<std::string> >::iterator it=groups.begin();it!=groups.end();it++)
1353     {
1354       std::vector<std::string>& fams((*it).second);
1355       std::vector<std::string>::iterator it2=std::find(fams.begin(),fams.end(),fam);
1356       if(it2!=fams.end())
1357         {
1358           fams.erase(it2);
1359           fams.insert(fams.end(),newFamiliesNames.begin(),newFamiliesNames.end());
1360         }
1361     }
1362 }
1363
1364 /*!
1365  * Returns a name of the family having a given id or, if no such a family exists, creates
1366  * a new uniquely named family and returns its name.
1367  *  \param [in] id - the id of the family whose name is required.
1368  *  \param [out] created - returns \c true if the new family has been created, \c false, else.
1369  *  \return std::string - the name of the existing or the created family.
1370  *  \throw If it is not possible to create a unique family name.
1371  */
1372 std::string MEDFileMesh::findOrCreateAndGiveFamilyWithId(int id, bool& created)
1373 {
1374   return FindOrCreateAndGiveFamilyWithId(_families,id,created);
1375 }
1376
1377 /*!
1378  * If it exists a family whose family id is equal to 'id' this method behaves as MEDFileMesh::getFamilyNameGivenId.
1379  * In this case, 'this' internal states remains unchanged and 'created' out parameter will be set to false.
1380  * If there is no family whose family id is equal to 'id' a family is created with a name different from those
1381  * already existing. In this case 'created' will be returned with a value set to true, and internal state
1382  * will be modified.
1383  * This method will throws an exception if it is not possible to create a unique family name.
1384  */
1385 std::string MEDFileMesh::FindOrCreateAndGiveFamilyWithId(std::map<std::string,int>& families, int id, bool& created)
1386 {
1387   std::vector<std::string> famAlreadyExisting(families.size());
1388   int ii=0;
1389   for(std::map<std::string,int>::const_iterator it=families.begin();it!=families.end();it++,ii++)
1390     {
1391       if((*it).second!=id)
1392         {
1393           famAlreadyExisting[ii]=(*it).first;
1394         }
1395       else
1396         {
1397           created=false;
1398           return (*it).first;
1399         }
1400     }
1401   created=true;
1402   std::ostringstream oss; oss << "Family_" << id;
1403   std::string ret=CreateNameNotIn(oss.str(),famAlreadyExisting);
1404   families[ret]=id;
1405   return ret;
1406 }
1407
1408 /*!
1409  * Sets names and ids of all families in \a this mesh.
1410  *  \param [in] info - a map of a family name to a family id.
1411  */
1412 void MEDFileMesh::setFamilyInfo(const std::map<std::string,int>& info)
1413 {
1414   _families=info;
1415 }
1416
1417 /*!
1418  * Sets names of all groups and families constituting them in \a this mesh.
1419  *  \param [in] info - a map of a group name to a vector of names of families
1420  *          constituting the group.
1421  */
1422 void MEDFileMesh::setGroupInfo(const std::map<std::string, std::vector<std::string> >&info)
1423 {
1424   _groups=info;
1425 }
1426
1427 /*!
1428  * Returns an id of the family having a given name.
1429  *  \param [in] name - the name of the family of interest.
1430  *  \return int - the id of the family of interest.
1431  *  \throw If no family with such a \a name exists.
1432  */
1433 int MEDFileMesh::getFamilyId(const std::string& name) const
1434 {
1435   std::string oname(name);
1436   std::map<std::string, int>::const_iterator it=_families.find(oname);
1437   std::vector<std::string> fams=getFamiliesNames();
1438   if(it==_families.end())
1439     {
1440       std::ostringstream oss; oss << "No such familyname \"" << name << "\" !\nAvailable families are :";
1441       std::copy(fams.begin(),fams.end(),std::ostream_iterator<std::string>(oss," "));
1442       throw INTERP_KERNEL::Exception(oss.str().c_str());
1443     }
1444   return (*it).second;
1445 }
1446
1447 /*!
1448  * Returns ids of the families having given names.
1449  *  \param [in] fams - a sequence of the names of families of interest.
1450  *  \return std::vector<int> - a sequence of the ids of families of interest.
1451  *  \throw If \a fams contains a name of an inexistent family.
1452  */
1453 std::vector<int> MEDFileMesh::getFamiliesIds(const std::vector<std::string>& fams) const
1454 {
1455   std::vector<int> ret(fams.size());
1456   int i=0;
1457   for(std::vector<std::string>::const_iterator it=fams.begin();it!=fams.end();it++,i++)
1458     {
1459       std::map<std::string, int>::const_iterator it2=_families.find(*it);
1460       if(it2==_families.end())
1461         {
1462           std::vector<std::string> fams2=getFamiliesNames();
1463           std::ostringstream oss; oss << "No such familyname \"" << *it << "\" in input list !\nAvailable families are :";
1464           std::copy(fams2.begin(),fams2.end(),std::ostream_iterator<std::string>(oss," "));
1465           throw INTERP_KERNEL::Exception(oss.str().c_str());
1466         }
1467       ret[i]=(*it2).second;
1468     }
1469   return ret;
1470 }
1471
1472 /*!
1473  * Returns a maximal abs(id) of families in \a this mesh.
1474  *  \return int - the maximal norm of family id.
1475  *  \throw If there are no families in \a this mesh.
1476  */
1477 int MEDFileMesh::getMaxAbsFamilyId() const
1478 {
1479   if(_families.empty())
1480     throw INTERP_KERNEL::Exception("MEDFileMesh::getMaxFamilyId : no families set !");
1481   int ret=-std::numeric_limits<int>::max();
1482   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
1483     {
1484       ret=std::max(std::abs((*it).second),ret);
1485     }
1486   return ret;
1487 }
1488
1489 /*!
1490  * Returns a maximal id of families in \a this mesh.
1491  *  \return int - the maximal family id.
1492  *  \throw If there are no families in \a this mesh.
1493  */
1494 int MEDFileMesh::getMaxFamilyId() const
1495 {
1496   if(_families.empty())
1497     throw INTERP_KERNEL::Exception("MEDFileMesh::getMaxFamilyId : no families set !");
1498   int ret=-std::numeric_limits<int>::max();
1499   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
1500     {
1501       ret=std::max((*it).second,ret);
1502     }
1503   return ret;
1504 }
1505
1506 /*!
1507  * Returns a minimal id of families in \a this mesh.
1508  *  \return int - the minimal family id.
1509  *  \throw If there are no families in \a this mesh.
1510  */
1511 int MEDFileMesh::getMinFamilyId() const
1512 {
1513   if(_families.empty())
1514     throw INTERP_KERNEL::Exception("MEDFileMesh::getMinFamilyId : no families set !");
1515   int ret=std::numeric_limits<int>::max();
1516   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
1517     {
1518       ret=std::min((*it).second,ret);
1519     }
1520   return ret;
1521 }
1522
1523 /*!
1524  * Returns a maximal id of families in \a this mesh. Not only named families are
1525  * considered but all family fields as well.
1526  *  \return int - the maximal family id.
1527  */
1528 int MEDFileMesh::getTheMaxAbsFamilyId() const
1529 {
1530   int m1=-std::numeric_limits<int>::max();
1531   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
1532     m1=std::max(std::abs((*it).second),m1);
1533   int m2=getMaxAbsFamilyIdInArrays();
1534   return std::max(m1,m2);
1535 }
1536
1537 /*!
1538  * Returns a maximal id of families in \a this mesh. Not only named families are
1539  * considered but all family fields as well.
1540  *  \return int - the maximal family id.
1541  */
1542 int MEDFileMesh::getTheMaxFamilyId() const
1543 {
1544   int m1=-std::numeric_limits<int>::max();
1545   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
1546     m1=std::max((*it).second,m1);
1547   int m2=getMaxFamilyIdInArrays();
1548   return std::max(m1,m2);
1549 }
1550
1551 /*!
1552  * Returns a minimal id of families in \a this mesh. Not only named families are
1553  * considered but all family fields as well.
1554  *  \return int - the minimal family id.
1555  */
1556 int MEDFileMesh::getTheMinFamilyId() const
1557 {
1558   int m1=std::numeric_limits<int>::max();
1559   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
1560     m1=std::min((*it).second,m1);
1561   int m2=getMinFamilyIdInArrays();
1562   return std::min(m1,m2);
1563 }
1564
1565 /*!
1566  * This method only considers the maps. The contain of family array is ignored here.
1567  * 
1568  * \sa MEDFileMesh::computeAllFamilyIdsInUse
1569  */
1570 DataArrayInt *MEDFileMesh::getAllFamiliesIdsReferenced() const
1571 {
1572   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1573   std::set<int> v;
1574   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
1575     v.insert((*it).second);
1576   ret->alloc((int)v.size(),1);
1577   std::copy(v.begin(),v.end(),ret->getPointer());
1578   return ret.retn();
1579 }
1580
1581 /*!
1582  * This method does not consider map of family name, family id. Only family field array on different levels is considered.
1583  * 
1584  * \sa MEDFileMesh::getAllFamiliesIdsReferenced
1585  */
1586 DataArrayInt *MEDFileMesh::computeAllFamilyIdsInUse() const
1587 {
1588   std::vector<int> famLevs=getFamArrNonEmptyLevelsExt();
1589   MCAuto<DataArrayInt> ret;
1590   for(std::vector<int>::const_iterator it=famLevs.begin();it!=famLevs.end();it++)
1591     {
1592       const DataArrayInt *arr=getFamilyFieldAtLevel(*it);//arr not null due to spec of getFamArrNonEmptyLevelsExt
1593       MCAuto<DataArrayInt> dv=arr->getDifferentValues();
1594       if((DataArrayInt *) ret)
1595         ret=dv->buildUnion(ret);
1596       else
1597         ret=dv;
1598     }
1599   return ret.retn();
1600 }
1601
1602 /*!
1603  * true is returned if no modification has been needed. false if family
1604  * renumbering has been needed.       
1605  */
1606 bool MEDFileMesh::ensureDifferentFamIdsPerLevel()
1607 {
1608   std::vector<int> levs=getNonEmptyLevelsExt();
1609   std::set<int> allFamIds;
1610   int maxId=getMaxFamilyId()+1;
1611   std::map<int,std::vector<int> > famIdsToRenum;
1612   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
1613     {
1614       const DataArrayInt *fam=getFamilyFieldAtLevel(*it);
1615       if(fam)
1616         {
1617           MCAuto<DataArrayInt> tmp=fam->getDifferentValues();
1618           std::set<int> r2;
1619           std::set_intersection(tmp->begin(),tmp->end(),allFamIds.begin(),allFamIds.end(),std::inserter(r2,r2.end()));
1620           if(!r2.empty())
1621             famIdsToRenum[*it].insert(famIdsToRenum[*it].end(),r2.begin(),r2.end());
1622           std::set<int> r3;
1623           std::set_union(tmp->begin(),tmp->end(),allFamIds.begin(),allFamIds.end(),std::inserter(r3,r3.end()));
1624         }
1625     }
1626   if(famIdsToRenum.empty())
1627     return true;
1628   MCAuto<DataArrayInt> allIds=getAllFamiliesIdsReferenced();
1629   for(std::map<int,std::vector<int> >::const_iterator it2=famIdsToRenum.begin();it2!=famIdsToRenum.end();it2++)
1630     {
1631       DataArrayInt *fam=const_cast<DataArrayInt *>(getFamilyFieldAtLevel((*it2).first));
1632       int *famIdsToChange=fam->getPointer();
1633       std::map<int,int> ren;
1634       for(std::vector<int>::const_iterator it3=(*it2).second.begin();it3!=(*it2).second.end();it3++,maxId++)
1635         {
1636           if(allIds->presenceOfValue(*it3))
1637             {
1638               std::string famName=getFamilyNameGivenId(*it3);
1639               std::vector<std::string> grps=getGroupsOnFamily(famName);
1640               ren[*it3]=maxId;
1641               bool dummy;
1642               std::string newFam=findOrCreateAndGiveFamilyWithId(maxId,dummy);
1643               for(std::vector<std::string>::const_iterator it4=grps.begin();it4!=grps.end();it4++)
1644                 addFamilyOnGrp((*it4),newFam);
1645             }
1646         }
1647       MCAuto<DataArrayInt> ids=fam->findIdsEqualList(&(*it2).second[0],&(*it2).second[0]+(*it2).second.size());
1648       for(const int *id=ids->begin();id!=ids->end();id++)
1649         famIdsToChange[*id]=ren[famIdsToChange[*id]];
1650     }
1651   return false;
1652 }
1653
1654 /*!
1655  * This method normalizes fam id with the policy explained underneath. This policy is close to those implemented in SMESH.
1656  * Level #0 famids > 0, Level #-1 famids < 0, Level #-2 famids=0, Level #1 famids=0
1657  * This policy is those used by SMESH and Trio and that is the opposite of those in MED file.
1658  * This method will throw an exception if a same family id is detected in different level.
1659  * \warning This policy is the opposite of those in MED file documentation ...
1660  */
1661 void MEDFileMesh::normalizeFamIdsTrio()
1662 {
1663   ensureDifferentFamIdsPerLevel();
1664   MCAuto<DataArrayInt> allIds=getAllFamiliesIdsReferenced();
1665   std::vector<int> levs=getNonEmptyLevelsExt();
1666   std::set<int> levsS(levs.begin(),levs.end());
1667   std::set<std::string> famsFetched;
1668   std::map<std::string,int> families;
1669   if(std::find(levs.begin(),levs.end(),0)!=levs.end())
1670     {
1671       levsS.erase(0);
1672       const DataArrayInt *fam=getFamilyFieldAtLevel(0);
1673       if(fam)
1674         {
1675           int refId=1;
1676           MCAuto<DataArrayInt> tmp=fam->getDifferentValues();
1677           std::map<int,int> ren;
1678           for(const int *it=tmp->begin();it!=tmp->end();it++,refId++)
1679             ren[*it]=refId;
1680           int nbOfTuples=fam->getNumberOfTuples();
1681           int *start=const_cast<DataArrayInt *>(fam)->getPointer();
1682           for(int *w=start;w!=start+nbOfTuples;w++)
1683             *w=ren[*w];
1684           for(const int *it=tmp->begin();it!=tmp->end();it++)
1685             {
1686               if(allIds->presenceOfValue(*it))
1687                 {
1688                   std::string famName=getFamilyNameGivenId(*it);
1689                   families[famName]=ren[*it];
1690                   famsFetched.insert(famName);
1691                 }
1692             }
1693         }
1694     }
1695   if(std::find(levs.begin(),levs.end(),-1)!=levs.end())
1696     {
1697       levsS.erase(-1);
1698       const DataArrayInt *fam=getFamilyFieldAtLevel(-1);
1699       if(fam)
1700         {
1701           int refId=-1;
1702           MCAuto<DataArrayInt> tmp=fam->getDifferentValues();
1703           std::map<int,int> ren;
1704           for(const int *it=tmp->begin();it!=tmp->end();it++,refId--)
1705             ren[*it]=refId;
1706           int nbOfTuples=fam->getNumberOfTuples();
1707           int *start=const_cast<DataArrayInt *>(fam)->getPointer();
1708           for(int *w=start;w!=start+nbOfTuples;w++)
1709             *w=ren[*w];
1710           for(const int *it=tmp->begin();it!=tmp->end();it++)
1711             {
1712               if(allIds->presenceOfValue(*it))
1713                 {
1714                   std::string famName=getFamilyNameGivenId(*it);
1715                   families[famName]=ren[*it];
1716                   famsFetched.insert(famName);
1717                 }
1718             }
1719         }
1720     }
1721   for(std::set<int>::const_iterator it2=levsS.begin();it2!=levsS.end();it2++)
1722     {
1723       DataArrayInt *fam=const_cast<DataArrayInt*>(getFamilyFieldAtLevel(*it2));
1724       if(fam)
1725         {
1726           MCAuto<DataArrayInt> tmp=fam->getDifferentValues();
1727           fam->fillWithZero();
1728           for(const int *it3=tmp->begin();it3!=tmp->end();it3++)
1729             if(allIds->presenceOfValue(*it3))
1730               {
1731                 std::string famName=getFamilyNameGivenId(*it3);
1732                 families[famName]=0;
1733                 famsFetched.insert(famName);
1734               }
1735         }
1736     }
1737   //
1738   std::vector<std::string> allFams=getFamiliesNames();
1739   std::set<std::string> allFamsS(allFams.begin(),allFams.end());
1740   std::set<std::string> unFetchedIds;
1741   std::set_difference(allFamsS.begin(),allFamsS.end(),famsFetched.begin(),famsFetched.end(),std::inserter(unFetchedIds,unFetchedIds.end()));
1742   for(std::set<std::string>::const_iterator it4=unFetchedIds.begin();it4!=unFetchedIds.end();it4++)
1743     families[*it4]=_families[*it4];
1744   _families=families;
1745 }
1746
1747 /*!
1748  * This method normalizes fam id with the following policy.
1749  * Level #0 famids < 0, Level #-1 famids < 0 and for Level #1 famids >= 0
1750  * This policy is those defined in the MED file format but is the opposite of those implemented in SMESH and Trio.
1751  * This method will throw an exception if a same family id is detected in different level.
1752  */
1753 void MEDFileMesh::normalizeFamIdsMEDFile()
1754 {
1755   ensureDifferentFamIdsPerLevel();
1756   MCAuto<DataArrayInt> allIds=getAllFamiliesIdsReferenced();
1757   std::vector<int> levs=getNonEmptyLevelsExt();
1758   std::set<int> levsS(levs.begin(),levs.end());
1759   std::set<std::string> famsFetched;
1760   std::map<std::string,int> families;
1761   int refId=1;
1762   if(std::find(levs.begin(),levs.end(),1)!=levs.end())
1763     {
1764       levsS.erase(1);
1765       const DataArrayInt *fam=getFamilyFieldAtLevel(1);
1766       if(fam)
1767         {
1768           MCAuto<DataArrayInt> tmp=fam->getDifferentValues();
1769           std::map<int,int> ren;
1770           for(const int *it=tmp->begin();it!=tmp->end();it++,refId++)
1771             ren[*it]=refId;
1772           int nbOfTuples=fam->getNumberOfTuples();
1773           int *start=const_cast<DataArrayInt *>(fam)->getPointer();
1774           for(int *w=start;w!=start+nbOfTuples;w++)
1775             *w=ren[*w];
1776           for(const int *it=tmp->begin();it!=tmp->end();it++)
1777             {
1778               if(allIds->presenceOfValue(*it))
1779                 {
1780                   std::string famName=getFamilyNameGivenId(*it);
1781                   families[famName]=ren[*it];
1782                   famsFetched.insert(famName);
1783                 }
1784             }
1785         }
1786     }
1787   refId=-1;
1788   for(std::set<int>::const_reverse_iterator it2=levsS.rbegin();it2!=levsS.rend();it2++)
1789     {
1790       const DataArrayInt *fam=getFamilyFieldAtLevel(*it2);
1791       if(fam)
1792         {
1793           MCAuto<DataArrayInt> tmp=fam->getDifferentValues();
1794           std::map<int,int> ren;
1795           for(const int *it=tmp->begin();it!=tmp->end();it++,refId--)
1796             ren[*it]=refId;
1797           int nbOfTuples=fam->getNumberOfTuples();
1798           int *start=const_cast<DataArrayInt *>(fam)->getPointer();
1799           for(int *w=start;w!=start+nbOfTuples;w++)
1800             *w=ren[*w];
1801           for(const int *it=tmp->begin();it!=tmp->end();it++)
1802             {
1803               if(allIds->presenceOfValue(*it))
1804                 {
1805                   std::string famName=getFamilyNameGivenId(*it);
1806                   families[famName]=ren[*it];
1807                   famsFetched.insert(famName);
1808                 }
1809             }
1810         }
1811     }
1812   //
1813   std::vector<std::string> allFams=getFamiliesNames();
1814   std::set<std::string> allFamsS(allFams.begin(),allFams.end());
1815   std::set<std::string> unFetchedIds;
1816   std::set_difference(allFamsS.begin(),allFamsS.end(),famsFetched.begin(),famsFetched.end(),std::inserter(unFetchedIds,unFetchedIds.end()));
1817   for(std::set<std::string>::const_iterator it4=unFetchedIds.begin();it4!=unFetchedIds.end();it4++)
1818     families[*it4]=_families[*it4];
1819   _families=families;
1820 }
1821
1822 /*!
1823  * Returns a name of the family by its id. If there are several families having the given
1824  * id, the name first in lexical order is returned.
1825  *  \param [in] id - the id of the family whose name is required.
1826  *  \return std::string - the name of the found family.
1827  *  \throw If no family with the given \a id exists.
1828  */
1829 std::string MEDFileMesh::getFamilyNameGivenId(int id) const
1830 {
1831   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
1832     if((*it).second==id)
1833       return (*it).first;
1834   std::ostringstream oss; oss << "MEDFileUMesh::getFamilyNameGivenId : no such family id : " << id;
1835   throw INTERP_KERNEL::Exception(oss.str().c_str());
1836 }
1837
1838 /*!
1839  * Returns a string describing \a this mesh. This description includes the mesh name and
1840  * the mesh description string.
1841  *  \return std::string - the mesh information string.
1842  */
1843 std::string MEDFileMesh::simpleRepr() const
1844 {
1845   std::ostringstream oss;
1846   oss << "(*************************************)\n(* GENERAL INFORMATION ON THE MESH : *)\n(*************************************)\n";
1847   oss << "- Name of the mesh : <<" << getName() << ">>\n";
1848   oss << "- Description associated to the mesh : " << getDescription() << std::endl;
1849   return oss.str();
1850 }
1851
1852 /*!
1853  * This method is nearly like getFamilyFieldAtLevel method. Except that if the array does not exist at the specified level \a meshDimRelToMaxExt
1854  * an empty one is created.
1855  */
1856 DataArrayInt *MEDFileMesh::getOrCreateAndGetFamilyFieldAtLevel(int meshDimRelToMaxExt)
1857 {
1858   DataArrayInt *ret(getFamilyFieldAtLevel(meshDimRelToMaxExt));
1859   if(ret)
1860     return ret;
1861   MCAuto<DataArrayInt> arr(DataArrayInt::New());
1862   arr->alloc(getSizeAtLevel(meshDimRelToMaxExt),1);
1863   arr->fillWithZero();
1864   setFamilyFieldArr(meshDimRelToMaxExt,arr);
1865   return getFamilyFieldAtLevel(meshDimRelToMaxExt);
1866 }
1867
1868 /*!
1869  * Returns ids of mesh entities contained in a given group of a given dimension.
1870  *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
1871  *          are required.
1872  *  \param [in] grp - the name of the group of interest.
1873  *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
1874  *          returned instead of ids. 
1875  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
1876  *          numbers, if available and required, of mesh entities of the group. The caller
1877  *          is to delete this array using decrRef() as it is no more needed. 
1878  *  \throw If the name of a nonexistent group is specified.
1879  *  \throw If the family field is missing for \a meshDimRelToMaxExt.
1880  */
1881 DataArrayInt *MEDFileMesh::getGroupArr(int meshDimRelToMaxExt, const std::string& grp, bool renum) const
1882 {
1883   std::vector<std::string> tmp(1);
1884   tmp[0]=grp;
1885   DataArrayInt *ret=getGroupsArr(meshDimRelToMaxExt,tmp,renum);
1886   ret->setName(grp);
1887   return ret;
1888 }
1889
1890 /*!
1891  * Returns ids of mesh entities contained in given groups of a given dimension.
1892  *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
1893  *          are required.
1894  *  \param [in] grps - the names of the groups of interest.
1895  *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
1896  *          returned instead of ids.
1897  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
1898  *          numbers, if available and required, of mesh entities of the groups. The caller
1899  *          is to delete this array using decrRef() as it is no more needed. 
1900  *  \throw If the name of a nonexistent group is present in \a grps.
1901  *  \throw If the family field is missing for \a meshDimRelToMaxExt.
1902  */
1903 DataArrayInt *MEDFileMesh::getGroupsArr(int meshDimRelToMaxExt, const std::vector<std::string>& grps, bool renum) const
1904 {
1905   std::vector<std::string> fams2=getFamiliesOnGroups(grps);
1906   return getFamiliesArr(meshDimRelToMaxExt,fams2,renum);
1907 }
1908
1909 /*!
1910  * Returns ids of mesh entities contained in a given family of a given dimension.
1911  *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
1912  *          are required.
1913  *  \param [in] fam - the name of the family of interest.
1914  *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
1915  *          returned instead of ids. 
1916  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
1917  *          numbers, if available and required, of mesh entities of the family. The caller
1918  *          is to delete this array using decrRef() as it is no more needed. 
1919  *  \throw If the family field is missing for \a meshDimRelToMaxExt.
1920  */
1921 DataArrayInt *MEDFileMesh::getFamilyArr(int meshDimRelToMaxExt, const std::string& fam, bool renum) const
1922 {
1923   std::vector<std::string> tmp(1);
1924   tmp[0]=fam;
1925   DataArrayInt *ret=getFamiliesArr(meshDimRelToMaxExt,tmp,renum);
1926   ret->setName(fam);
1927   return ret;
1928 }
1929
1930 /*!
1931  * Returns ids of nodes contained in a given group.
1932  *  \param [in] grp - the name of the group of interest.
1933  *  \param [in] renum - if \c true, the optional numbers of nodes, if available, are
1934  *          returned instead of ids. 
1935  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
1936  *          numbers, if available and required, of nodes of the group. The caller
1937  *          is to delete this array using decrRef() as it is no more needed. 
1938  *  \throw If the name of a nonexistent group is specified.
1939  *  \throw If the family field is missing for nodes.
1940  */
1941 DataArrayInt *MEDFileMesh::getNodeGroupArr(const std::string& grp, bool renum) const
1942 {
1943   std::vector<std::string> tmp(1);
1944   tmp[0]=grp;
1945   DataArrayInt *ret=getNodeGroupsArr(tmp,renum);
1946   ret->setName(grp);
1947   return ret;
1948 }
1949
1950 /*!
1951  * Returns ids of nodes contained in given groups.
1952  *  \param [in] grps - the names of the groups of interest.
1953  *  \param [in] renum - if \c true, the optional numbers of nodes, if available, are
1954  *          returned instead of ids. 
1955  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
1956  *          numbers, if available and required, of nodes of the groups. The caller
1957  *          is to delete this array using decrRef() as it is no more needed. 
1958  *  \throw If the name of a nonexistent group is present in \a grps.
1959  *  \throw If the family field is missing for nodes.
1960  */
1961 DataArrayInt *MEDFileMesh::getNodeGroupsArr(const std::vector<std::string>& grps, bool renum) const
1962 {
1963   return getGroupsArr(1,grps,renum);
1964 }
1965
1966 /*!
1967  * Returns ids of nodes contained in a given group.
1968  *  \param [in] grp - the name of the group of interest.
1969  *  \param [in] renum - if \c true, the optional numbers of nodes, if available, are
1970  *          returned instead of ids. 
1971  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
1972  *          numbers, if available and required, of nodes of the group. The caller
1973  *          is to delete this array using decrRef() as it is no more needed. 
1974  *  \throw If the name of a nonexistent group is specified.
1975  *  \throw If the family field is missing for nodes.
1976  */
1977 DataArrayInt *MEDFileMesh::getNodeFamilyArr(const std::string& fam, bool renum) const
1978 {
1979   std::vector<std::string> tmp(1);
1980   tmp[0]=fam;
1981   DataArrayInt *ret=getNodeFamiliesArr(tmp,renum);
1982   ret->setName(fam);
1983   return ret;
1984 }
1985
1986 /*!
1987  * Returns ids of nodes contained in given families.
1988  *  \param [in] fams - the names of the families of interest.
1989  *  \param [in] renum - if \c true, the optional numbers of nodes, if available, are
1990  *          returned instead of ids. 
1991  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
1992  *          numbers, if available and required, of nodes of the families. The caller
1993  *          is to delete this array using decrRef() as it is no more needed. 
1994  *  \throw If the family field is missing for nodes.
1995  */
1996 DataArrayInt *MEDFileMesh::getNodeFamiliesArr(const std::vector<std::string>& fams, bool renum) const
1997 {
1998   return getFamiliesArr(1,fams,renum);
1999 }
2000
2001 /*!
2002  * Adds groups of given dimension and creates corresponding families and family fields
2003  * given ids of mesh entities of each group.
2004  *  \param [in] meshDimRelToMaxExt - the relative mesh dimension of given mesh entities.
2005  *  \param [in] grps - a sequence of arrays of ids each describing a group.
2006  *  \param [in] renum - \c true means that \a grps contains not ids but optional numbers
2007  *          of mesh entities.
2008  *  \throw If names of some groups in \a grps are equal.
2009  *  \throw If \a grps includes a group with an empty name.
2010  *  \throw If \a grps includes invalid ids (or numbers if \a renum == \c true ).
2011  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2012  */
2013 void MEDFileMesh::setGroupsAtLevel(int meshDimRelToMaxExt, const std::vector<const DataArrayInt *>& grps, bool renum)
2014 {
2015   if(grps.empty())
2016     return ;
2017   std::set<std::string> grpsName;
2018   std::vector<std::string> grpsName2(grps.size());
2019   int i=0;
2020
2021   for(std::vector<const DataArrayInt *>::const_iterator it=grps.begin();it!=grps.end();it++,i++)
2022     {
2023       grpsName.insert((*it)->getName());
2024       grpsName2[i]=(*it)->getName();
2025     }
2026   if(grpsName.size()!=grps.size())
2027     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsAtLevel : groups name must be different each other !");
2028   if(grpsName.find(std::string(""))!=grpsName.end())
2029     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsAtLevel : groups name must be different empty string !");
2030   int sz=getSizeAtLevel(meshDimRelToMaxExt);
2031   MCAuto<DataArrayInt> fam;
2032   std::vector< std::vector<int> > fidsOfGroups;
2033   if(!renum)
2034     {
2035       fam=DataArrayInt::MakePartition(grps,sz,fidsOfGroups);
2036     }
2037   else
2038     {
2039       std::vector< MCAuto<DataArrayInt> > grps2(grps.size());
2040       for(unsigned int ii=0;ii<grps.size();ii++)
2041         {
2042           grps2[ii]=MEDFileUMeshSplitL1::Renumber(getRevNumberFieldAtLevel(meshDimRelToMaxExt),grps[ii]);
2043           grps2[ii]->setName(grps[ii]->getName());
2044         }
2045       std::vector<const DataArrayInt *> grps3(grps2.begin(),grps2.end());
2046       fam=DataArrayInt::MakePartition(grps3,sz,fidsOfGroups);
2047     }
2048   int offset=1;
2049   if(!_families.empty())
2050     offset=getMaxAbsFamilyId()+1;
2051   TranslateFamilyIds(meshDimRelToMaxExt==1?offset:-offset,fam,fidsOfGroups);
2052   MCAuto<DataArrayInt> ids=fam->getDifferentValues();
2053   appendFamilyEntries(ids,fidsOfGroups,grpsName2);
2054   setFamilyFieldArr(meshDimRelToMaxExt,fam);
2055 }
2056
2057 /*!
2058  * This method append into '_families' attribute the families whose ids are in 'famIds'. Warning 'famIds' are expected to be ids
2059  * not in '_families'. Groups information are given in parameters in order to give to families representative names.
2060  * For the moment, the two last input parameters are not taken into account.
2061  */
2062 void MEDFileMesh::appendFamilyEntries(const DataArrayInt *famIds, const std::vector< std::vector<int> >& fidsOfGrps, const std::vector<std::string>& grpNames)
2063 {
2064   std::map<int,std::string> famInv;
2065   for(const int *it=famIds->begin();it!=famIds->end();it++)
2066     {
2067       std::ostringstream oss;
2068       oss << "Family_" << (*it);
2069       _families[oss.str()]=(*it);
2070       famInv[*it]=oss.str();
2071     }
2072   int i=0;
2073   for(std::vector< std::vector<int> >::const_iterator it1=fidsOfGrps.begin();it1!=fidsOfGrps.end();it1++,i++)
2074     {
2075       for(std::vector<int>::const_iterator it2=(*it1).begin();it2!=(*it1).end();it2++)
2076         {
2077           _groups[grpNames[i]].push_back(famInv[*it2]);
2078         }
2079     }
2080 }
2081
2082 std::vector<INTERP_KERNEL::NormalizedCellType> MEDFileMesh::getAllGeoTypes() const
2083 {
2084   std::vector<int> levs(getNonEmptyLevels());
2085   std::vector<INTERP_KERNEL::NormalizedCellType> ret;
2086   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
2087     {
2088       std::vector<INTERP_KERNEL::NormalizedCellType> elts(getGeoTypesAtLevel(*it));
2089       ret.insert(ret.end(),elts.begin(),elts.end());
2090     }
2091   return ret;
2092 }
2093
2094 std::vector<int> MEDFileMesh::getDistributionOfTypes(int meshDimRelToMax) const
2095 {
2096   MCAuto<MEDCouplingMesh> mLev(getMeshAtLevel(meshDimRelToMax));
2097   return mLev->getDistributionOfTypes();
2098 }
2099
2100 void MEDFileMesh::loadLLWithAdditionalItems(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
2101 {
2102   loadLL(fid,mName,dt,it,mrs);
2103   loadJointsFromFile(fid);
2104   loadEquivalences(fid);
2105 }
2106
2107 void MEDFileMesh::TranslateFamilyIds(int offset, DataArrayInt *famArr, std::vector< std::vector<int> >& famIdsPerGrp)
2108 {
2109   famArr->applyLin(offset>0?1:-1,offset,0);
2110   for(std::vector< std::vector<int> >::iterator it1=famIdsPerGrp.begin();it1!=famIdsPerGrp.end();it1++)
2111     {
2112       if(offset<0)
2113         std::transform((*it1).begin(),(*it1).end(),(*it1).begin(),std::negate<int>());
2114       std::transform((*it1).begin(),(*it1).end(),(*it1).begin(),std::bind2nd(std::plus<int>(),offset));
2115     }
2116 }
2117
2118 /*!
2119  * Warning no check is done on 'nameTry' in parameter. It should be non empty.
2120  * This method returns a name close to 'nameTry' so that it is not already into 'namesToAvoid'.
2121  * If this method fails to find such a name it will throw an exception.
2122  */
2123 std::string MEDFileMesh::CreateNameNotIn(const std::string& nameTry, const std::vector<std::string>& namesToAvoid)
2124 {
2125   //attempt #0
2126   if(std::find(namesToAvoid.begin(),namesToAvoid.end(),nameTry)==namesToAvoid.end())
2127     return nameTry;
2128   //attempt #1
2129   std::size_t len=nameTry.length();
2130   for(std::size_t ii=1;ii<len;ii++)
2131     {
2132       std::string tmp=nameTry.substr(ii,len-ii);
2133       if(std::find(namesToAvoid.begin(),namesToAvoid.end(),tmp)==namesToAvoid.end())
2134         return tmp;
2135     }
2136   //attempt #2
2137   if(len>=1)
2138     {
2139       for(std::size_t i=1;i<30;i++)
2140         {
2141           std::string tmp1(nameTry.at(0),i);
2142           tmp1+=nameTry;
2143           if(std::find(namesToAvoid.begin(),namesToAvoid.end(),tmp1)==namesToAvoid.end())
2144             return tmp1;
2145         }
2146     }
2147   //attempt #3
2148   std::string tmp2;
2149   for(std::vector<std::string>::const_iterator it2=namesToAvoid.begin();it2!=namesToAvoid.end();it2++)
2150     tmp2+=(*it2);
2151   if(std::find(namesToAvoid.begin(),namesToAvoid.end(),tmp2)==namesToAvoid.end())
2152     return tmp2;
2153   throw INTERP_KERNEL::Exception("MEDFileMesh::CreateNameNotIn : impossible to find a not already used name !");
2154 }
2155
2156 int MEDFileMesh::PutInThirdComponentOfCodeOffset(std::vector<int>& code, int strt)
2157 {
2158   std::size_t nbOfChunks=code.size()/3;
2159   if(code.size()%3!=0)
2160     throw INTERP_KERNEL::Exception("MEDFileMesh::PutInThirdComponentOfCodeOffset : code has invalid size : should be of size 3*x !");
2161   int ret=strt;
2162   for(std::size_t i=0;i<nbOfChunks;i++)
2163     {
2164       code[3*i+2]=ret;
2165       ret+=code[3*i+1];
2166     }
2167   return ret;
2168 }
2169
2170 /*!
2171  * This method should be called by any set* method of subclasses to deal automatically with _name attribute.
2172  * If _name attribute is empty the name of 'm' if taken as _name attribute.
2173  * If _name is not empty and that 'm' has the same name nothing is done.
2174  * If _name is not emplt and that 'm' has \b NOT the same name an exception is thrown.
2175  */
2176 void MEDFileMesh::dealWithTinyInfo(const MEDCouplingMesh *m)
2177 {
2178   if(!m)
2179     throw INTERP_KERNEL::Exception("MEDFileMesh::dealWithTinyInfo : input mesh in NULL !");
2180   if(_name.empty())
2181     _name=m->getName();
2182   else
2183     {
2184       std::string name(m->getName());
2185       if(!name.empty())
2186         {
2187           if(_name!=name)
2188             {
2189               std::ostringstream oss; oss << "MEDFileMesh::dealWithTinyInfo : name of current MEDfile mesh is '" << _name << "' whereas name of input mesh is : '";
2190               oss << name << "' ! Names must match !";
2191               throw INTERP_KERNEL::Exception(oss.str().c_str());
2192             }
2193         }
2194     }
2195   if(_desc_name.empty())
2196     _desc_name=m->getDescription();
2197   else
2198     {
2199       std::string name(m->getDescription());
2200       if(!name.empty())
2201         {
2202           if(_desc_name!=name)
2203             {
2204               std::ostringstream oss; oss << "MEDFileMesh::dealWithTinyInfo : description of current MEDfile mesh is '" << _desc_name << "' whereas name of input mesh is : '";
2205               oss << name << "' ! Names must match !";
2206               throw INTERP_KERNEL::Exception(oss.str().c_str());
2207             }
2208         }
2209     }
2210 }
2211
2212 void MEDFileMesh::getFamilyRepr(std::ostream& oss) const
2213 {
2214   oss << "(**************************)\n(* FAMILIES OF THE MESH : *)\n(**************************)\n";
2215   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
2216     {
2217       oss << "- Family with name \"" << (*it).first << "\" with number " << (*it).second << std::endl;
2218       oss << "  - Groups lying on this family : ";
2219       std::vector<std::string> grps=getGroupsOnFamily((*it).first);
2220       std::copy(grps.begin(),grps.end(),std::ostream_iterator<std::string>(oss," "));
2221       oss << std::endl << std::endl;
2222     }
2223 }
2224
2225 /*!
2226  * Returns a new MEDFileUMesh holding the mesh data that has been read from a given MED
2227  * file. The mesh to load is specified by its name and numbers of a time step and an
2228  * iteration.
2229  *  \param [in] fileName - the name of MED file to read.
2230  *  \param [in] mName - the name of the mesh to read.
2231  *  \param [in] dt - the number of a time step.
2232  *  \param [in] it - the number of an iteration.
2233  *  \return MEDFileUMesh * - a new instance of MEDFileUMesh. The caller is to delete this
2234  *          mesh using decrRef() as it is no more needed. 
2235  *  \throw If the file is not readable.
2236  *  \throw If there is no mesh with given attributes in the file.
2237  *  \throw If the mesh in the file is not an unstructured one.
2238  */
2239 MEDFileUMesh *MEDFileUMesh::New(const std::string& fileName, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
2240 {
2241   MEDFileUtilities::CheckFileForRead(fileName);
2242   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
2243   return new MEDFileUMesh(fid,mName,dt,it,mrs);
2244 }
2245
2246 /*!
2247  * Returns a new MEDFileUMesh holding the mesh data that has been read from a given MED
2248  * file. The first mesh in the file is loaded.
2249  *  \param [in] fileName - the name of MED file to read.
2250  *  \return MEDFileUMesh * - a new instance of MEDFileUMesh. The caller is to delete this
2251  *          mesh using decrRef() as it is no more needed. 
2252  *  \throw If the file is not readable.
2253  *  \throw If there is no meshes in the file.
2254  *  \throw If the mesh in the file is not an unstructured one.
2255  */
2256 MEDFileUMesh *MEDFileUMesh::New(const std::string& fileName, MEDFileMeshReadSelector *mrs)
2257 {
2258   std::vector<std::string> ms(MEDCoupling::GetMeshNames(fileName));
2259   if(ms.empty())
2260     {
2261       std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
2262       throw INTERP_KERNEL::Exception(oss.str().c_str());
2263     }
2264   MEDFileUtilities::CheckFileForRead(fileName);
2265   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
2266   int dt,it;
2267   MEDCoupling::MEDCouplingMeshType meshType;
2268   std::string dummy2;
2269   MEDCoupling::MEDCouplingAxisType dummy3;
2270   MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dummy3,dt,it,dummy2);
2271   return new MEDFileUMesh(fid,ms.front(),dt,it,mrs);
2272 }
2273
2274 /*!
2275  * Returns an empty instance of MEDFileUMesh.
2276  *  \return MEDFileUMesh * - a new instance of MEDFileUMesh. The caller is to delete this
2277  *          mesh using decrRef() as it is no more needed. 
2278  */
2279 MEDFileUMesh *MEDFileUMesh::New()
2280 {
2281   return new MEDFileUMesh;
2282 }
2283
2284 /*!
2285  * This method loads from file with name \a fileName the mesh called \a mName as New does. The difference is that
2286  * here only a part of cells contained in the file will be loaded. The selection of cell is specified using the two consecutive parameters
2287  * \a types and \a slicPerTyp. This method allows to load from a mesh (typically huge) in a MED file a part of cells of that mesh.
2288  * The part of cells is specified using triplet (start,stop,step) for each geometric type. Only nodes lying on selected cells will be loaded to reduce
2289  * at most the memory consumtion.
2290  *
2291  * \param [in] fileName - the name of the file.
2292  * \param [in] mName - the name of the mesh to be read.
2293  * \param [in] types - the list of the geo types of which some part will be taken. A geometric type in \a types must appear only once at most.
2294  * \param [in] slicPerType - an array of size 3 times larger than \a types that specifies for each type in \a types (in the same order) resp the start, the stop and the step.
2295  * \param [in] dt - the iteration, that is to say the first element of the pair that locates the asked time step.
2296  * \param [in] it - the order, that is to say the second element of the pair that locates the asked time step.
2297  * \param [in] mrs - the request for what to be loaded.
2298  * \return MEDFileUMesh * - a new instance of MEDFileUMesh. The caller is to delete this mesh using decrRef() as it is no more needed.
2299  */
2300 MEDFileUMesh *MEDFileUMesh::LoadPartOf(const std::string& fileName, const std::string& mName, const std::vector<INTERP_KERNEL::NormalizedCellType>& types, const std::vector<int>& slicPerTyp, int dt, int it, MEDFileMeshReadSelector *mrs)
2301 {
2302   MEDFileUtilities::CheckFileForRead(fileName);
2303   MEDFileUtilities::AutoFid fid(MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY));
2304   return MEDFileUMesh::LoadPartOf(fid,mName,types,slicPerTyp,dt,it,mrs);
2305 }
2306
2307 /*!
2308  * Please refer to the other MEDFileUMesh::LoadPartOf method that has the same semantic and the same parameter (excepted the first).
2309  * This method is \b NOT wrapped into python.
2310  */
2311 MEDFileUMesh *MEDFileUMesh::LoadPartOf(med_idt fid, const std::string& mName, const std::vector<INTERP_KERNEL::NormalizedCellType>& types, const std::vector<int>& slicPerTyp, int dt, int it, MEDFileMeshReadSelector *mrs)
2312 {
2313   MCAuto<MEDFileUMesh> ret(MEDFileUMesh::New());
2314   ret->loadPartUMeshFromFile(fid,mName,types,slicPerTyp,dt,it,mrs);
2315   return ret.retn();
2316 }
2317
2318 std::size_t MEDFileUMesh::getHeapMemorySizeWithoutChildren() const
2319 {
2320   std::size_t ret(MEDFileMesh::getHeapMemorySizeWithoutChildren());
2321   ret+=_ms.capacity()*(sizeof(MCAuto<MEDFileUMeshSplitL1>));
2322   return ret;
2323 }
2324
2325 std::vector<const BigMemoryObject *> MEDFileUMesh::getDirectChildrenWithNull() const
2326 {
2327   std::vector<const BigMemoryObject *> ret(MEDFileMesh::getDirectChildrenWithNull());
2328   ret.push_back((const DataArrayDouble*)_coords);
2329   ret.push_back((const DataArrayInt *)_fam_coords);
2330   ret.push_back((const DataArrayInt *)_num_coords);
2331   ret.push_back((const DataArrayInt *)_rev_num_coords);
2332   ret.push_back((const DataArrayAsciiChar *)_name_coords);
2333   ret.push_back((const PartDefinition *)_part_coords);
2334   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2335     ret.push_back((const MEDFileUMeshSplitL1*) *it);
2336   return ret;
2337 }
2338
2339 MEDFileMesh *MEDFileUMesh::shallowCpy() const
2340 {
2341   MCAuto<MEDFileUMesh> ret(new MEDFileUMesh(*this));
2342   return ret.retn();
2343 }
2344
2345 MEDFileMesh *MEDFileUMesh::createNewEmpty() const
2346 {
2347   return new MEDFileUMesh;
2348 }
2349
2350 MEDFileMesh *MEDFileUMesh::deepCopy() const
2351 {
2352   MCAuto<MEDFileUMesh> ret(new MEDFileUMesh(*this));
2353   ret->deepCpyEquivalences(*this);
2354   if((const DataArrayDouble*)_coords)
2355     ret->_coords=_coords->deepCopy();
2356   if((const DataArrayInt*)_fam_coords)
2357     ret->_fam_coords=_fam_coords->deepCopy();
2358   if((const DataArrayInt*)_num_coords)
2359     ret->_num_coords=_num_coords->deepCopy();
2360   if((const DataArrayInt*)_rev_num_coords)
2361     ret->_rev_num_coords=_rev_num_coords->deepCopy();
2362   if((const DataArrayAsciiChar*)_name_coords)
2363     ret->_name_coords=_name_coords->deepCopy();
2364   std::size_t i=0;
2365   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,i++)
2366     {
2367       if((const MEDFileUMeshSplitL1 *)(*it))
2368         ret->_ms[i]=(*it)->deepCopy(ret->_coords);
2369     }
2370   if((const PartDefinition*)_part_coords)
2371     ret->_part_coords=_part_coords->deepCopy();
2372   return ret.retn();
2373 }
2374
2375 /*!
2376  * Checks if \a this and another mesh are equal.
2377  *  \param [in] other - the mesh to compare with.
2378  *  \param [in] eps - a precision used to compare real values.
2379  *  \param [in,out] what - the string returning description of unequal data.
2380  *  \return bool - \c true if the meshes are equal, \c false, else.
2381  */
2382 bool MEDFileUMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
2383 {
2384   if(!MEDFileMesh::isEqual(other,eps,what))
2385     return false;
2386   const MEDFileUMesh *otherC=dynamic_cast<const MEDFileUMesh *>(other);
2387   if(!otherC)
2388     {
2389       what="Mesh types differ ! This is unstructured and other is NOT !";
2390       return false;
2391     }
2392   clearNonDiscrAttributes();
2393   otherC->clearNonDiscrAttributes();
2394   const DataArrayDouble *coo1=_coords;
2395   const DataArrayDouble *coo2=otherC->_coords;
2396   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
2397     {
2398       what="Mismatch of coordinates ! One is defined and not other !";
2399       return false;
2400     }
2401   if(coo1)
2402     {
2403       bool ret=coo1->isEqual(*coo2,eps);
2404       if(!ret)
2405         {
2406           what="Coords differ !";
2407           return false;
2408         }
2409     }
2410   const DataArrayInt *famc1=_fam_coords;
2411   const DataArrayInt *famc2=otherC->_fam_coords;
2412   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
2413     {
2414       what="Mismatch of families arr on nodes ! One is defined and not other !";
2415       return false;
2416     }
2417   if(famc1)
2418     {
2419       bool ret=famc1->isEqual(*famc2);
2420       if(!ret)
2421         {
2422           what="Families arr on node differ !";
2423           return false;
2424         }
2425     }
2426   const DataArrayInt *numc1=_num_coords;
2427   const DataArrayInt *numc2=otherC->_num_coords;
2428   if((numc1==0 && numc2!=0) || (numc1!=0 && numc2==0))
2429     {
2430       what="Mismatch of numbering arr on nodes ! One is defined and not other !";
2431       return false;
2432     }
2433   if(numc1)
2434     {
2435       bool ret=numc1->isEqual(*numc2);
2436       if(!ret)
2437         {
2438           what="Numbering arr on node differ !";
2439           return false;
2440         }
2441     }
2442   const DataArrayAsciiChar *namec1=_name_coords;
2443   const DataArrayAsciiChar *namec2=otherC->_name_coords;
2444   if((namec1==0 && namec2!=0) || (namec1!=0 && namec2==0))
2445     {
2446       what="Mismatch of naming arr on nodes ! One is defined and not other !";
2447       return false;
2448     }
2449   if(namec1)
2450     {
2451       bool ret=namec1->isEqual(*namec2);
2452       if(!ret)
2453         {
2454           what="Names arr on node differ !";
2455           return false;
2456         }
2457     }
2458   if(_ms.size()!=otherC->_ms.size())
2459     {
2460       what="Number of levels differs !";
2461       return false;
2462     }
2463   std::size_t sz=_ms.size();
2464   for(std::size_t i=0;i<sz;i++)
2465     {
2466       const MEDFileUMeshSplitL1 *s1=_ms[i];
2467       const MEDFileUMeshSplitL1 *s2=otherC->_ms[i];
2468       if((s1==0 && s2!=0) || (s1!=0 && s2==0))
2469         {
2470           what="Mismatch of presence of sub levels !";
2471           return false;
2472         }
2473       if(s1)
2474         {
2475           bool ret=s1->isEqual(s2,eps,what);
2476           if(!ret)
2477             return false;
2478         }
2479     }
2480   const PartDefinition *pd0(_part_coords),*pd1(otherC->_part_coords);
2481   if(!pd0 && !pd1)
2482     return true;
2483   if((!pd0 && pd1) || (pd0 && !pd1))
2484     {
2485       what=std::string("node part def is defined only for one among this or other !");
2486       return false;
2487     }
2488   return pd0->isEqual(pd1,what);
2489 }
2490
2491 /*!
2492  * Check that the current object MEDFileUMesh is consistent. This does not check the optional renumbering of
2493  * nodes and cells. This last item is important for SMESH, see checkSMESHConsistency().
2494  * \throw if any internal part (i.e. mesh sub-levels and single geometric-type meshes) are inconsistent
2495  * \throw if internal family array is inconsistent
2496  * \sa checkSMESHConsistency()
2497  */
2498 void MEDFileUMesh::checkConsistency() const
2499 {
2500   if(!_coords || !_coords->isAllocated())
2501     {
2502       if(!_ms.size())
2503         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkConsistency(): coords are null but some mesh parts are present!");
2504       if (!_fam_coords)
2505         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkConsistency(): coords are null but not the internal node family array!");
2506       if (!_num_coords || !_rev_num_coords)
2507         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkConsistency(): coords are null but not the internal node numbering array!");
2508     }
2509   else
2510     {
2511       int nbCoo = _coords->getNumberOfTuples();
2512       if (_fam_coords)
2513         _fam_coords->checkNbOfTuplesAndComp(nbCoo,1,"MEDFileUMesh::checkConsistency(): inconsistent internal node family array!");
2514       if (_num_coords)
2515         {
2516           _num_coords->checkNbOfTuplesAndComp(nbCoo,1,"MEDFileUMesh::checkConsistency(): inconsistent internal node numbering array!");
2517           int pos;
2518           int maxValue=_num_coords->getMaxValue(pos);
2519           if (!_rev_num_coords || _rev_num_coords->getNumberOfTuples() != (maxValue+1))
2520             throw INTERP_KERNEL::Exception("MEDFileUMesh::checkConsistency(): inconsistent internal revert node numbering array!");
2521         }
2522       if ((_num_coords && !_rev_num_coords) || (!_num_coords && _rev_num_coords))
2523         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkConsistency(): inconsistent internal numbering arrays (one is null)!");
2524       if (_num_coords && !_num_coords->hasUniqueValues())
2525         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkConsistency(): inconsistent internal node numbering array: duplicates found!");
2526       if (_name_coords)
2527         _name_coords->checkNbOfTuplesAndComp(nbCoo,MED_SNAME_SIZE,"MEDFileUMesh::checkConsistency(): inconsistent internal coord name array!");
2528       // Now sub part check:
2529       for (std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();
2530           it != _ms.end(); it++)
2531         (*it)->checkConsistency();
2532     }
2533 }
2534
2535 /**
2536  * Same as checkConsistency() but also checks that optional entities (edges, faces, volumes) numbers are
2537  * consistent, i.e. the numbering is either set to null for all sub-levels (thus letting SMESH numbers the
2538  * entities as it likes), or non overlapping between all sub-levels.
2539  * \throw if the condition above is not respected
2540  */
2541 void MEDFileUMesh::checkSMESHConsistency() const
2542 {
2543   checkConsistency();
2544   // For all sub-levels, numbering is either always null or with void intersection:
2545   if (_ms.size())
2546     {
2547       std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();
2548       std::vector< const DataArrayInt * > v;
2549       bool voidOrNot = ((*it)->_num == 0);
2550       for (it++; it != _ms.end(); it++)
2551         if( ((*it)->_num == 0) != voidOrNot )
2552           throw INTERP_KERNEL::Exception("MEDFileUMesh::checkConsistency(): inconsistent numbering between mesh sub-levels!");
2553         else if (!voidOrNot)
2554           v.push_back((*it)->_num);
2555       if (!voidOrNot)
2556         {
2557           // don't forget the 1st one:
2558           v.push_back(_ms[0]->_num);
2559           MCAuto<DataArrayInt> inter = DataArrayInt::BuildIntersection(v);
2560           if (inter->getNumberOfTuples())
2561             throw INTERP_KERNEL::Exception("MEDFileUMesh::checkConsistency(): overlapping entity numbering between mesh sub-levels!");
2562         }
2563     }
2564 }
2565
2566 /**
2567  * Reset optional node and cell numbering for all sub levels in this. This particularly useful to make
2568  * sure SMESH will handle the mesh correctly, as it tries to use those numbers if given.
2569  */
2570 void MEDFileUMesh::clearNodeAndCellNumbers()
2571 {
2572   _num_coords = 0;
2573   _rev_num_coords = 0;
2574   for (std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();
2575       it != _ms.end(); it++)
2576     {
2577       (*it)->_num = 0;
2578       (*it)->_rev_num = 0;
2579     }
2580 }
2581
2582 /*!
2583  * Clears redundant attributes of incorporated data arrays.
2584  */
2585 void MEDFileUMesh::clearNonDiscrAttributes() const
2586 {
2587   MEDFileMesh::clearNonDiscrAttributes();
2588   const DataArrayDouble *coo1=_coords;
2589   if(coo1)
2590     (const_cast<DataArrayDouble *>(coo1))->setName("");//This parameter is not discriminant for comparison
2591   const DataArrayInt *famc1=_fam_coords;
2592   if(famc1)
2593     (const_cast<DataArrayInt *>(famc1))->setName("");//This parameter is not discriminant for comparison
2594   const DataArrayInt *numc1=_num_coords;
2595   if(numc1)
2596     (const_cast<DataArrayInt *>(numc1))->setName("");//This parameter is not discriminant for comparison
2597   const DataArrayAsciiChar *namc1=_name_coords;
2598   if(namc1)
2599     (const_cast<DataArrayAsciiChar *>(namc1))->setName("");//This parameter is not discriminant for comparison
2600   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2601     {
2602       const MEDFileUMeshSplitL1 *tmp=(*it);
2603       if(tmp)
2604         tmp->clearNonDiscrAttributes();
2605     }
2606 }
2607
2608 void MEDFileUMesh::setName(const std::string& name)
2609 {
2610   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
2611     if((MEDFileUMeshSplitL1 *)(*it)!=0)
2612       (*it)->setName(name);
2613   MEDFileMesh::setName(name);
2614 }
2615
2616 MEDFileUMesh::MEDFileUMesh()
2617 {
2618 }
2619
2620 MEDFileUMesh::MEDFileUMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
2621 try
2622 {
2623     loadLLWithAdditionalItems(fid,mName,dt,it,mrs);
2624 }
2625 catch(INTERP_KERNEL::Exception& e)
2626 {
2627     throw e;
2628 }
2629
2630 /*!
2631  * This method loads only a part of specified cells (given by range of cell ID per geometric type)
2632  * See MEDFileUMesh::LoadPartOf for detailed description.
2633  *
2634  * \sa loadLL
2635  */
2636 void MEDFileUMesh::loadPartUMeshFromFile(med_idt fid, const std::string& mName, const std::vector<INTERP_KERNEL::NormalizedCellType>& types, const std::vector<int>& slicPerTyp, int dt, int it, MEDFileMeshReadSelector *mrs)
2637 {
2638   MEDFileUMeshL2 loaderl2;
2639   MEDCoupling::MEDCouplingMeshType meshType;
2640   int dummy0,dummy1;
2641   std::string dummy2;
2642   MEDCoupling::MEDCouplingAxisType dummy3;
2643   int mid(MEDFileUMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy3,dummy0,dummy1,dummy2));
2644   if(meshType!=UNSTRUCTURED)
2645     {
2646       std::ostringstream oss; oss << "loadPartUMeshFromFile : Trying to load as unstructured an existing mesh with name '" << mName << "' !";
2647       throw INTERP_KERNEL::Exception(oss.str().c_str());
2648     }
2649   loaderl2.loadPart(fid,mid,mName,types,slicPerTyp,dt,it,mrs);
2650   dispatchLoadedPart(fid,loaderl2,mName,mrs);
2651 }
2652
2653 /*!
2654  * \brief Write joints in a file
2655  */
2656 void MEDFileMesh::writeJoints(med_idt fid) const
2657 {
2658   if ( (const MEDFileJoints*) _joints )
2659     _joints->write(fid);
2660 }
2661
2662 /*!
2663  * \brief Load joints in a file or use provided ones
2664  */
2665 //================================================================================
2666 /*!
2667  * \brief Load joints in a file or use provided ones
2668  *  \param [in] fid - MED file descriptor
2669  *  \param [in] toUseInstedOfReading - optional joints to use instead of reading,
2670  *          Usually this joints are those just read by another iteration
2671  *          of namesake mesh, when this method is called by MEDFileMeshMultiTS::New()
2672  */
2673 //================================================================================
2674
2675 void MEDFileMesh::loadJointsFromFile(med_idt fid, MEDFileJoints* toUseInstedOfReading)
2676 {
2677   if ( toUseInstedOfReading )
2678     setJoints( toUseInstedOfReading );
2679   else
2680     _joints = MEDFileJoints::New( fid, _name );
2681 }
2682
2683 void MEDFileMesh::loadEquivalences(med_idt fid)
2684 {
2685   int nbOfEq(MEDFileEquivalences::PresenceOfEquivalences(fid,_name));
2686   if(nbOfEq>0)
2687     _equiv=MEDFileEquivalences::Load(fid,nbOfEq,this);
2688 }
2689
2690 void MEDFileMesh::deepCpyEquivalences(const MEDFileMesh& other)
2691 {
2692   const MEDFileEquivalences *equiv(other._equiv);
2693   if(equiv)
2694     _equiv=equiv->deepCopy(this);
2695 }
2696
2697 bool MEDFileMesh::areEquivalencesEqual(const MEDFileMesh *other, std::string& what) const
2698 {
2699   const MEDFileEquivalences *thisEq(_equiv),*otherEq(other->_equiv);
2700   if(!thisEq && !otherEq)
2701     return true;
2702   if(thisEq && otherEq)
2703     return thisEq->isEqual(otherEq,what);
2704   else
2705     {
2706       what+="Equivalence differs : defined in this and not in other (or reversely) !";
2707       return false;
2708     }
2709 }
2710
2711 void MEDFileMesh::getEquivalencesRepr(std::ostream& oss) const
2712 {
2713   const MEDFileEquivalences *equiv(_equiv);
2714   if(!equiv)
2715     return ;
2716   oss << "(******************************)\n(* EQUIVALENCES OF THE MESH : *)\n(******************************)\n";
2717   _equiv->getRepr(oss);
2718 }
2719
2720 void MEDFileMesh::checkCartesian() const
2721 {
2722   if(getAxisType()!=AX_CART)
2723     {
2724       std::ostringstream oss; oss << "MEDFileMesh::checkCartesian : request for method that is dedicated to a cartesian convention ! But you are not in cartesian convention (" << DataArray::GetAxisTypeRepr(getAxisType()) << ").";
2725       oss << std::endl << "To perform operation you have two possiblities :" << std::endl;
2726       oss << " - call setAxisType(AX_CART)" << std::endl;
2727       oss << " - call cartesianize()";
2728       throw INTERP_KERNEL::Exception(oss.str().c_str());
2729     }
2730 }
2731
2732 /*!
2733  * \brief Return number of joints, which is equal to number of adjacent mesh domains
2734  */
2735 int MEDFileMesh::getNumberOfJoints() const
2736 {
2737   return ( (const MEDFileJoints *) _joints ) ? _joints->getNumberOfJoints() : 0;
2738 }
2739
2740 /*!
2741  * \brief Return joints with all adjacent mesh domains
2742  */
2743 MEDFileJoints * MEDFileMesh::getJoints() const
2744 {
2745   return const_cast<MEDFileJoints*>(& (*_joints));
2746 }
2747
2748 void MEDFileMesh::setJoints( MEDFileJoints* joints )
2749 {
2750   if ( joints != _joints )
2751     {
2752       _joints = joints;
2753       if ( joints )
2754         joints->incrRef();
2755     }
2756 }
2757
2758 /*!
2759  * This method loads \b all \b the \b mesh \a mName in the file with \a fid descriptor.
2760  *
2761  * \sa loadPartUMeshFromFile
2762  */
2763 void MEDFileUMesh::loadLL(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
2764 {
2765   MEDFileUMeshL2 loaderl2;
2766   MEDCoupling::MEDCouplingMeshType meshType;
2767   int dummy0,dummy1;
2768   std::string dummy2;
2769   MEDCoupling::MEDCouplingAxisType axType;
2770   int mid(MEDFileUMeshL2::GetMeshIdFromName(fid,mName,meshType,axType,dummy0,dummy1,dummy2));
2771   setAxisType(axType);
2772   if(meshType!=UNSTRUCTURED)
2773     {
2774       std::ostringstream oss; oss << "Trying to load as unstructured an existing mesh with name '" << mName << "' !";
2775       throw INTERP_KERNEL::Exception(oss.str().c_str());
2776     }
2777   loaderl2.loadAll(fid,mid,mName,dt,it,mrs);
2778   dispatchLoadedPart(fid,loaderl2,mName,mrs);
2779 }
2780
2781 void MEDFileUMesh::dispatchLoadedPart(med_idt fid, const MEDFileUMeshL2& loaderl2, const std::string& mName, MEDFileMeshReadSelector *mrs)
2782 {
2783   int lev=loaderl2.getNumberOfLevels();
2784   _ms.resize(lev);
2785   for(int i=0;i<lev;i++)
2786     {
2787       if(!loaderl2.emptyLev(i))
2788         _ms[i]=new MEDFileUMeshSplitL1(loaderl2,mName,i);
2789       else
2790         _ms[i]=0;
2791     }
2792   MEDFileMeshL2::ReadFamiliesAndGrps(fid,mName,_families,_groups,mrs);
2793   //
2794   setName(loaderl2.getName());
2795   setDescription(loaderl2.getDescription());
2796   setUnivName(loaderl2.getUnivName());
2797   setIteration(loaderl2.getIteration());
2798   setOrder(loaderl2.getOrder());
2799   setTimeValue(loaderl2.getTime());
2800   setTimeUnit(loaderl2.getTimeUnit());
2801   _coords=loaderl2.getCoords();
2802   if(!mrs || mrs->isNodeFamilyFieldReading())
2803     _fam_coords=loaderl2.getCoordsFamily();
2804   if(!mrs || mrs->isNodeNumFieldReading())
2805     _num_coords=loaderl2.getCoordsNum();
2806   if(!mrs || mrs->isNodeNameFieldReading())
2807     _name_coords=loaderl2.getCoordsName();
2808   _part_coords=loaderl2.getPartDefOfCoo();
2809   computeRevNum();
2810 }
2811
2812 MEDFileUMesh::~MEDFileUMesh()
2813 {
2814 }
2815
2816 void MEDFileUMesh::writeLL(med_idt fid) const
2817 {
2818   const DataArrayDouble *coo=_coords;
2819   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
2820   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
2821   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
2822   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
2823   int spaceDim=coo?coo->getNumberOfComponents():0;
2824   int mdim(0);
2825   if(!_ms.empty())
2826     mdim=getMeshDimension();
2827   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
2828   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
2829   for(int i=0;i<spaceDim;i++)
2830     {
2831       std::string info=coo->getInfoOnComponent(i);
2832       std::string c,u;
2833       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
2834       MEDLoaderBase::safeStrCpy2(c.c_str(),MED_SNAME_SIZE-1,comp+i*MED_SNAME_SIZE,_too_long_str);//MED_TAILLE_PNOM-1 to avoid to write '\0' on next compo
2835       MEDLoaderBase::safeStrCpy2(u.c_str(),MED_SNAME_SIZE-1,unit+i*MED_SNAME_SIZE,_too_long_str);//MED_TAILLE_PNOM-1 to avoid to write '\0' on next compo
2836     }
2837   MEDFILESAFECALLERWR0(MEDmeshCr,(fid,maa,spaceDim,mdim,MED_UNSTRUCTURED_MESH,desc,"",MED_SORT_DTIT,MEDFileMeshL2::TraduceAxisTypeRev(getAxisType()),comp,unit));
2838   if(_univ_wr_status)
2839     MEDFILESAFECALLERWR0(MEDmeshUniversalNameWr,(fid,maa));
2840   std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE));
2841   MEDFileUMeshL2::WriteCoords(fid,meshName,_iteration,_order,_time,_coords,_fam_coords,_num_coords,_name_coords);
2842   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2843     if((const MEDFileUMeshSplitL1 *)(*it)!=0)
2844       (*it)->write(fid,meshName,mdim);
2845   MEDFileUMeshL2::WriteFamiliesAndGrps(fid,meshName,_families,_groups,_too_long_str);
2846 }
2847
2848 /*!
2849  * Returns relative dimensions of mesh entities (excluding nodes) present in \a this mesh.
2850  *  \return std::vector<int> - a sequence of the relative dimensions.
2851  */
2852 std::vector<int> MEDFileUMesh::getNonEmptyLevels() const
2853 {
2854   std::vector<int> ret;
2855   int lev=0;
2856   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
2857     if((const MEDFileUMeshSplitL1 *)(*it)!=0)
2858       if(!(*it)->empty())
2859         ret.push_back(lev);
2860   return ret;
2861 }
2862
2863 /*!
2864  * Returns relative dimensions of mesh entities (including nodes) present in \a this mesh.
2865  *  \return std::vector<int> - a sequence of the relative dimensions.
2866  */
2867 std::vector<int> MEDFileUMesh::getNonEmptyLevelsExt() const
2868 {
2869   std::vector<int> ret0=getNonEmptyLevels();
2870   if((const DataArrayDouble *) _coords)
2871     {
2872       std::vector<int> ret(ret0.size()+1);
2873       ret[0]=1;
2874       std::copy(ret0.begin(),ret0.end(),ret.begin()+1);
2875       return ret;
2876     }
2877   return ret0;
2878 }
2879
2880 std::vector<int> MEDFileUMesh::getFamArrNonEmptyLevelsExt() const
2881 {
2882   std::vector<int> ret;
2883   const DataArrayInt *famCoo(_fam_coords);
2884   if(famCoo)
2885     ret.push_back(1);
2886   int lev=0;
2887   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
2888     {
2889       const MEDFileUMeshSplitL1 *cur(*it);
2890       if(cur)
2891         if(cur->getFamilyField())
2892           ret.push_back(lev);
2893     }
2894   return ret;
2895 }
2896
2897 std::vector<int> MEDFileUMesh::getNumArrNonEmptyLevelsExt() const
2898 {
2899   std::vector<int> ret;
2900   const DataArrayInt *numCoo(_num_coords);
2901   if(numCoo)
2902     ret.push_back(1);
2903   int lev=0;
2904   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
2905     {
2906       const MEDFileUMeshSplitL1 *cur(*it);
2907       if(cur)
2908         if(cur->getNumberField())
2909           ret.push_back(lev);
2910     }
2911   return ret;
2912 }
2913
2914 std::vector<int> MEDFileUMesh::getNameArrNonEmptyLevelsExt() const
2915 {
2916   std::vector<int> ret;
2917   const DataArrayAsciiChar *nameCoo(_name_coords);
2918   if(nameCoo)
2919     ret.push_back(1);
2920   int lev=0;
2921   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
2922     {
2923       const MEDFileUMeshSplitL1 *cur(*it);
2924       if(cur)
2925         if(cur->getNameField())
2926           ret.push_back(lev);
2927     }
2928   return ret;
2929 }
2930
2931 /*!
2932  * Returns all relative mesh levels (**excluding nodes**) where given families are defined.
2933  * To include nodes, call getFamsNonEmptyLevelsExt() method.
2934  *  \param [in] fams - the name of the family of interest.
2935  *  \return std::vector<int> - a sequence of the relative dimensions.
2936  */
2937 std::vector<int> MEDFileUMesh::getFamsNonEmptyLevels(const std::vector<std::string>& fams) const
2938 {
2939   std::vector<int> ret;
2940   std::vector<int> levs(getNonEmptyLevels());
2941   std::vector<int> famIds(getFamiliesIds(fams));
2942   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
2943     if(_ms[-(*it)]->presenceOfOneFams(famIds))
2944       ret.push_back(*it);
2945   return ret;
2946 }
2947
2948 /*!
2949  * Returns all relative mesh levels (including nodes) where given families are defined.
2950  *  \param [in] fams - the names of the families of interest.
2951  *  \return std::vector<int> - a sequence of the relative dimensions.
2952  */
2953 std::vector<int> MEDFileUMesh::getFamsNonEmptyLevelsExt(const std::vector<std::string>& fams) const
2954 {
2955   std::vector<int> ret0(getFamsNonEmptyLevels(fams));
2956   const DataArrayInt *famCoords(_fam_coords);
2957   if(!famCoords)
2958     return ret0;
2959   std::vector<int> famIds(getFamiliesIds(fams));
2960   if(famCoords->presenceOfValue(famIds))
2961     {
2962       std::vector<int> ret(ret0.size()+1);
2963       ret[0]=1;
2964       std::copy(ret0.begin(),ret0.end(),ret.begin()+1);
2965       return ret;
2966     }
2967   else
2968     return ret0;
2969 }
2970
2971 int MEDFileUMesh::getMaxAbsFamilyIdInArrays() const
2972 {
2973   int ret=-std::numeric_limits<int>::max(),tmp=-1;
2974   if((const DataArrayInt *)_fam_coords)
2975     {
2976       int val=_fam_coords->getMaxValue(tmp);
2977       ret=std::max(ret,std::abs(val));
2978     }
2979   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2980     {
2981       if((const MEDFileUMeshSplitL1 *)(*it))
2982         {
2983           const DataArrayInt *da=(*it)->getFamilyField();
2984           if(da)
2985             {
2986               int val=da->getMaxValue(tmp);
2987               ret=std::max(ret,std::abs(val));
2988             }
2989         }
2990     }
2991   return ret;
2992 }
2993
2994 int MEDFileUMesh::getMaxFamilyIdInArrays() const
2995 {
2996   int ret=-std::numeric_limits<int>::max(),tmp=-1;
2997   if((const DataArrayInt *)_fam_coords)
2998     {
2999       int val=_fam_coords->getMaxValue(tmp);
3000       ret=std::max(ret,val);
3001     }
3002   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
3003     {
3004       if((const MEDFileUMeshSplitL1 *)(*it))
3005         {
3006           const DataArrayInt *da=(*it)->getFamilyField();
3007           if(da)
3008             {
3009               int val=da->getMaxValue(tmp);
3010               ret=std::max(ret,val);
3011             }
3012         }
3013     }
3014   return ret;
3015 }
3016
3017 int MEDFileUMesh::getMinFamilyIdInArrays() const
3018 {
3019   int ret=std::numeric_limits<int>::max(),tmp=-1;
3020   if((const DataArrayInt *)_fam_coords)
3021     {
3022       int val=_fam_coords->getMinValue(tmp);
3023       ret=std::min(ret,val);
3024     }
3025   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
3026     {
3027       if((const MEDFileUMeshSplitL1 *)(*it))
3028         {
3029           const DataArrayInt *da=(*it)->getFamilyField();
3030           if(da)
3031             {
3032               int val=da->getMinValue(tmp);
3033               ret=std::min(ret,val);
3034             }
3035         }
3036     }
3037   return ret;
3038 }
3039
3040 /*!
3041  * Returns the dimension on cells in \a this mesh.
3042  *  \return int - the mesh dimension.
3043  *  \throw If there are no cells in this mesh.
3044  */
3045 int MEDFileUMesh::getMeshDimension() const
3046 {
3047   int lev=0;
3048   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev++)
3049     if((const MEDFileUMeshSplitL1 *)(*it)!=0)
3050       return (*it)->getMeshDimension()+lev;
3051   throw INTERP_KERNEL::Exception("MEDFileUMesh::getMeshDimension : impossible to find a mesh dimension !");
3052 }
3053
3054 /*!
3055  * Returns the space dimension of \a this mesh that is equal to number of components in
3056  * the node coordinates array.
3057  *  \return int - the space dimension of \a this mesh.
3058  *  \throw If the node coordinates array is not available.
3059  */
3060 int MEDFileUMesh::getSpaceDimension() const
3061 {
3062   const DataArrayDouble *coo=_coords;
3063   if(!coo)
3064     throw INTERP_KERNEL::Exception(" MEDFileUMesh::getSpaceDimension : no coords set !");
3065   return coo->getNumberOfComponents();
3066 }
3067
3068 /*!
3069  * Returns a string describing \a this mesh.
3070  *  \return std::string - the mesh information string.
3071  */
3072 std::string MEDFileUMesh::simpleRepr() const
3073 {
3074   std::ostringstream oss;
3075   oss << MEDFileMesh::simpleRepr();
3076   const DataArrayDouble *coo=_coords;
3077   oss << "- The dimension of the space is ";
3078   static const char MSG1[]= "*** NO COORDS SET ***";
3079   static const char MSG2[]= "*** NO CONNECTIVITY SET FOR THIS LEVEL***";
3080   if(coo)
3081     oss << _coords->getNumberOfComponents() << std::endl;
3082   else
3083     oss << MSG1 << std::endl;
3084   oss << "- Type of the mesh : UNSTRUCTURED\n";
3085   oss << "- Number of nodes : ";
3086   if(coo)
3087     oss << _coords->getNumberOfTuples() << std::endl;
3088   else
3089     oss << MSG1 << std::endl;
3090   std::size_t nbOfLev=_ms.size();
3091   oss << "- Number of levels allocated : " << nbOfLev << std::endl;
3092   for(std::size_t i=0;i<nbOfLev;i++)
3093     {
3094       const MEDFileUMeshSplitL1 *lev=_ms[i];
3095       oss << "  - Level #" << -((int) i) << " has dimension : ";
3096       if(lev)
3097         {
3098           oss << lev->getMeshDimension() << std::endl;
3099           lev->simpleRepr(oss);
3100         }
3101       else
3102         oss << MSG2 << std::endl;
3103     }
3104   oss << "- Number of families : " << _families.size() << std::endl << std::endl;
3105   if(coo)
3106     {
3107       oss << "(***********************)\n(* NODES OF THE MESH : *)\n(***********************)\n";
3108       oss << "- Names of coordinates :" << std::endl;
3109       std::vector<std::string> vars=coo->getVarsOnComponent();
3110       std::copy(vars.begin(),vars.end(),std::ostream_iterator<std::string>(oss," "));
3111       oss << std::endl << "- Units of coordinates : " << std::endl;
3112       std::vector<std::string> units=coo->getUnitsOnComponent();
3113       std::copy(units.begin(),units.end(),std::ostream_iterator<std::string>(oss," "));
3114     }
3115   oss << std::endl << std::endl;
3116   getFamilyRepr(oss);
3117   getEquivalencesRepr(oss);
3118   return oss.str();
3119 }
3120
3121 /*!
3122  * Returns a full textual description of \a this mesh.
3123  *  \return std::string - the string holding the mesh description.
3124  */
3125 std::string MEDFileUMesh::advancedRepr() const
3126 {
3127   return simpleRepr();
3128 }
3129
3130 /*!
3131  * Returns number of mesh entities of a given relative dimension in \a this mesh.
3132  *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
3133  *  \return int - the number of entities.
3134  *  \throw If no mesh entities of dimension \a meshDimRelToMaxExt are available in \a this mesh.
3135  */
3136 int MEDFileUMesh::getSizeAtLevel(int meshDimRelToMaxExt) const
3137 {
3138   if(meshDimRelToMaxExt==1)
3139     {
3140       if(!((const DataArrayDouble *)_coords))
3141         throw INTERP_KERNEL::Exception("MEDFileUMesh::getSizeAtLevel : no coordinates specified !");
3142       return _coords->getNumberOfTuples();
3143     }
3144   return getMeshAtLevSafe(meshDimRelToMaxExt)->getSize();
3145 }
3146
3147 /*!
3148  * Returns the family field for mesh entities of a given dimension.
3149  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
3150  *  \return const DataArrayInt * - the family field. It is an array of ids of families
3151  *          each mesh entity belongs to. It can be \c NULL.
3152  */
3153 const DataArrayInt *MEDFileUMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) const
3154 {
3155   if(meshDimRelToMaxExt==1)
3156     return _fam_coords;
3157   const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMaxExt));
3158   return l1->getFamilyField();
3159 }
3160
3161 DataArrayInt *MEDFileUMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt)
3162 {
3163   if(meshDimRelToMaxExt==1)
3164     return _fam_coords;
3165   MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMaxExt));
3166   return l1->getFamilyField();
3167 }
3168
3169 /*!
3170  * Returns the optional numbers of mesh entities of a given dimension.
3171  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
3172  *  \return const DataArrayInt * - the array of the entity numbers.
3173  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3174  */
3175 const DataArrayInt *MEDFileUMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) const
3176 {
3177   if(meshDimRelToMaxExt==1)
3178     return _num_coords;
3179   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3180   return l1->getNumberField();
3181 }
3182
3183 const DataArrayAsciiChar *MEDFileUMesh::getNameFieldAtLevel(int meshDimRelToMaxExt) const
3184 {
3185   if(meshDimRelToMaxExt==1)
3186     return _name_coords;
3187   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3188   return l1->getNameField();
3189 }
3190
3191 /*!
3192  * This method returns for a specified relative level \a meshDimRelToMaxExt the part effectively read (if the instance is the result of the read of a file).
3193  *
3194  * \param [in] meshDimRelToMaxExt - the extended relative level for which the part definition is requested.
3195  * \param [in] gt - The input geometric type for which the part definition is requested.
3196  * \return the part definition owned by \a this. So no need to deallocate the returned instance.
3197  */
3198 const PartDefinition *MEDFileUMesh::getPartDefAtLevel(int meshDimRelToMaxExt, INTERP_KERNEL::NormalizedCellType gt) const
3199 {
3200   if(meshDimRelToMaxExt==1)
3201     return _part_coords;
3202   const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMaxExt));
3203   return l1->getPartDef(gt);
3204 }
3205
3206 int MEDFileUMesh::getNumberOfNodes() const
3207 {
3208   const DataArrayDouble *coo(_coords);
3209   if(!coo)
3210     throw INTERP_KERNEL::Exception(" MEDFileUMesh::getNumberOfNodes : no coords set !");
3211   return coo->getNumberOfTuples();
3212 }
3213
3214 int MEDFileUMesh::getNumberOfCellsAtLevel(int meshDimRelToMaxExt) const
3215 {
3216   const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMaxExt));
3217   return l1->getNumberOfCells();
3218 }
3219
3220 bool MEDFileUMesh::hasImplicitPart() const
3221 {
3222   return false;
3223 }
3224
3225 int MEDFileUMesh::buildImplicitPartIfAny(INTERP_KERNEL::NormalizedCellType gt) const
3226 {
3227   throw INTERP_KERNEL::Exception("MEDFileUMesh::buildImplicitPartIfAny : unstructured meshes do not have implicit part !");
3228 }
3229
3230 void MEDFileUMesh::releaseImplicitPartIfAny() const
3231 {
3232 }
3233
3234 void MEDFileUMesh::whichAreNodesFetched(const MEDFileField1TSStructItem& st, const MEDFileFieldGlobsReal *globs, std::vector<bool>& nodesFetched) const
3235 {
3236   std::size_t sz(st.getNumberOfItems());
3237   for(std::size_t i=0;i<sz;i++)
3238     {
3239       INTERP_KERNEL::NormalizedCellType curGt(st[i].getGeo());
3240       const MEDCoupling1GTUMesh *m(getDirectUndergroundSingleGeoTypeMesh(curGt));
3241       if(st[i].getPflName().empty())
3242         m->computeNodeIdsAlg(nodesFetched);
3243       else
3244         {
3245           const DataArrayInt *arr(globs->getProfile(st[i].getPflName()));
3246           MCAuto<MEDCoupling1GTUMesh> m2(dynamic_cast<MEDCoupling1GTUMesh *>(m->buildPartOfMySelf(arr->begin(),arr->end(),true)));
3247           m2->computeNodeIdsAlg(nodesFetched);
3248         }
3249     }
3250 }
3251
3252 MEDFileMesh *MEDFileUMesh::cartesianize() const
3253 {
3254   if(getAxisType()==AX_CART)
3255     {
3256       incrRef();
3257       return const_cast<MEDFileUMesh *>(this);
3258     }
3259   else
3260     {
3261       MCAuto<MEDFileUMesh> ret(new MEDFileUMesh(*this));
3262       const DataArrayDouble *coords(_coords);
3263       if(!coords)
3264         throw INTERP_KERNEL::Exception("MEDFileUMesh::cartesianize : coordinates are null !");
3265       MCAuto<DataArrayDouble> coordsCart(_coords->cartesianize(getAxisType()));
3266       for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=ret->_ms.begin();it!=ret->_ms.end();it++)
3267         if((const MEDFileUMeshSplitL1 *)(*it))
3268           *it=(*it)->shallowCpyUsingCoords(coordsCart);
3269       ret->_coords=coordsCart;
3270       ret->setAxisType(AX_CART);
3271       return ret.retn();
3272     }
3273 }
3274
3275 /*!
3276  * Returns the optional numbers of mesh entities of a given dimension transformed using
3277  * DataArrayInt::invertArrayN2O2O2N().
3278  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
3279  *  \return const DataArrayInt * - the array of the entity numbers transformed using
3280  *          DataArrayInt::invertArrayN2O2O2N().
3281  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3282  */
3283 const DataArrayInt *MEDFileUMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxExt) const
3284 {
3285   if(meshDimRelToMaxExt==1)
3286     {
3287       if(!((const DataArrayInt *)_num_coords))
3288         throw INTERP_KERNEL::Exception("MEDFileUMesh::getRevNumberFieldAtLevel : no coordinates renum specified !");
3289       return _rev_num_coords;
3290     }
3291   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3292   return l1->getRevNumberField();
3293 }
3294
3295 /*!
3296  * Returns a pointer to the node coordinates array of \a this mesh \b without
3297  * incrementing its reference counter, thus there is no need to decrRef() it by the caller.
3298  */
3299 DataArrayDouble *MEDFileUMesh::getCoords() const
3300 {
3301   checkCartesian();
3302   MCAuto<DataArrayDouble> tmp(_coords);
3303   if((DataArrayDouble *)tmp)
3304     {
3305       return tmp;
3306     }
3307   return 0;
3308 }
3309
3310 /*!
3311  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in a given
3312  * group of \a this mesh. Only mesh entities of a given dimension are included in the
3313  * new mesh.
3314  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
3315  *  \param [in] grp - the name of the group whose mesh entities are included in the
3316  *          new mesh.
3317  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
3318  *          according to the optional numbers of entities, if available.
3319  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
3320  *          delete this mesh using decrRef() as it is no more needed.
3321  *  \throw If the name of a nonexistent group is specified.
3322  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3323  */
3324 MEDCouplingUMesh *MEDFileUMesh::getGroup(int meshDimRelToMaxExt, const std::string& grp, bool renum) const
3325 {
3326   checkCartesian();
3327   synchronizeTinyInfoOnLeaves();
3328   std::vector<std::string> tmp(1);
3329   tmp[0]=grp;
3330   return getGroups(meshDimRelToMaxExt,tmp,renum);
3331 }
3332
3333 /*!
3334  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in given
3335  * groups of \a this mesh. Only mesh entities of a given dimension are included in the
3336  * new mesh.
3337  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
3338  *  \param [in] grps - a sequence of group names whose mesh entities are included in the
3339  *          new mesh.
3340  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
3341  *          according to the optional numbers of entities, if available.
3342  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
3343  *          delete this mesh using decrRef() as it is no more needed.
3344  *  \throw If a name of a nonexistent group is present in \a grps.
3345  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3346  */
3347 MEDCouplingUMesh *MEDFileUMesh::getGroups(int meshDimRelToMaxExt, const std::vector<std::string>& grps, bool renum) const
3348 {
3349   checkCartesian();
3350   synchronizeTinyInfoOnLeaves();
3351   std::vector<std::string> fams2=getFamiliesOnGroups(grps);
3352   MCAuto<MEDCouplingUMesh> zeRet=getFamilies(meshDimRelToMaxExt,fams2,renum);
3353   if(grps.size()==1 && ((MEDCouplingUMesh *)zeRet))
3354     zeRet->setName(grps[0]);
3355   return zeRet.retn();
3356 }
3357
3358 /*!
3359  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in a given
3360  * family of \a this mesh. Only mesh entities of a given dimension are included in the
3361  * new mesh.
3362  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
3363  *  \param [in] fam - the name of the family whose mesh entities are included in the
3364  *          new mesh.
3365  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
3366  *          according to the optional numbers of entities, if available.
3367  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
3368  *          delete this mesh using decrRef() as it is no more needed.
3369  *  \throw If a name of a nonexistent family is present in \a grps.
3370  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3371  */
3372 MEDCouplingUMesh *MEDFileUMesh::getFamily(int meshDimRelToMaxExt, const std::string& fam, bool renum) const
3373 {
3374   checkCartesian();
3375   synchronizeTinyInfoOnLeaves();
3376   std::vector<std::string> tmp(1);
3377   tmp[0]=fam;
3378   return getFamilies(meshDimRelToMaxExt,tmp,renum);
3379 }
3380
3381 /*!
3382  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in given
3383  * families of \a this mesh. Only mesh entities of a given dimension are included in the
3384  * new mesh.
3385  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
3386  *  \param [in] fams - a sequence of family names whose mesh entities are included in the
3387  *          new mesh.
3388  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
3389  *          according to the optional numbers of entities, if available.
3390  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
3391  *          delete this mesh using decrRef() as it is no more needed.
3392  *  \throw If a name of a nonexistent family is present in \a fams.
3393  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3394  */
3395 MEDCouplingUMesh *MEDFileUMesh::getFamilies(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const
3396 {
3397   checkCartesian();
3398   synchronizeTinyInfoOnLeaves();
3399   if(meshDimRelToMaxExt==1)
3400     {
3401       MCAuto<DataArrayInt> arr=getFamiliesArr(1,fams,renum);
3402       MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3403       MCAuto<DataArrayDouble> c=_coords->selectByTupleId(arr->getConstPointer(),arr->getConstPointer()+arr->getNbOfElems());
3404       ret->setCoords(c);
3405       return ret.retn();
3406     }
3407   std::vector<int> famIds=getFamiliesIds(fams);
3408   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3409   MCAuto<MEDCouplingUMesh> zeRet;
3410   if(!famIds.empty())
3411     zeRet=l1->getFamilyPart(&famIds[0],&famIds[0]+famIds.size(),renum);
3412   else
3413     zeRet=l1->getFamilyPart(0,0,renum);
3414   if(fams.size()==1 && ((MEDCouplingUMesh *)zeRet))
3415     zeRet->setName(fams[0]);
3416   return zeRet.retn();
3417 }
3418
3419 /*!
3420  * Returns ids of mesh entities contained in given families of a given dimension.
3421  *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
3422  *          are required.
3423  *  \param [in] fams - the names of the families of interest.
3424  *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
3425  *          returned instead of ids.
3426  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
3427  *          numbers, if available and required, of mesh entities of the families. The caller
3428  *          is to delete this array using decrRef() as it is no more needed. 
3429  *  \throw If the family field is missing for \a meshDimRelToMaxExt.
3430  */
3431 DataArrayInt *MEDFileUMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const
3432 {
3433   std::vector<int> famIds=getFamiliesIds(fams);
3434   if(meshDimRelToMaxExt==1)
3435     {
3436       if((const DataArrayInt *)_fam_coords)
3437         {
3438           MCAuto<DataArrayInt> da;
3439           if(!famIds.empty())
3440             da=_fam_coords->findIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
3441           else
3442             da=_fam_coords->findIdsEqualList(0,0);
3443           if(renum)
3444             return MEDFileUMeshSplitL1::Renumber(_num_coords,da);
3445           else
3446             return da.retn();
3447         }
3448       else
3449         throw INTERP_KERNEL::Exception("MEDFileUMesh::getFamiliesArr : no family array specified on nodes !");
3450     }
3451   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3452   if(!famIds.empty())
3453     return l1->getFamilyPartArr(&famIds[0],&famIds[0]+famIds.size(),renum);
3454   else
3455     return l1->getFamilyPartArr(0,0,renum);
3456 }
3457
3458 /*!
3459  * Returns a MEDCouplingUMesh of a given relative dimension.
3460  * \warning If \a meshDimRelToMaxExt == 1 (which means nodes), the returned mesh **is not
3461  * valid**. This is a feature, because MEDLoader does not create cells that do not exist! 
3462  * To build a valid MEDCouplingUMesh from the returned one in this case,
3463  * call MEDCouplingUMesh::Build0DMeshFromCoords().
3464  *  \param [in] meshDimRelToMax - the relative dimension of interest.
3465  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3466  *          optional numbers of mesh entities.
3467  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
3468  *          delete using decrRef() as it is no more needed. 
3469  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3470  */
3471 MEDCouplingUMesh *MEDFileUMesh::getMeshAtLevel(int meshDimRelToMaxExt, bool renum) const
3472 {
3473   checkCartesian();
3474   synchronizeTinyInfoOnLeaves();
3475   if(meshDimRelToMaxExt==1)
3476     {
3477       if(!renum)
3478         {
3479           MEDCouplingUMesh *umesh=MEDCouplingUMesh::New();
3480           MCAuto<DataArrayDouble> cc=_coords->deepCopy();
3481           umesh->setCoords(cc);
3482           MEDFileUMeshSplitL1::ClearNonDiscrAttributes(umesh);
3483           umesh->setName(getName());
3484           return umesh;
3485         }
3486     }
3487   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3488   return l1->getWholeMesh(renum);
3489 }
3490
3491 std::vector<int> MEDFileUMesh::getDistributionOfTypes(int meshDimRelToMax) const
3492 {
3493   const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMax));
3494   return l1->getDistributionOfTypes();
3495 }
3496
3497 /*!
3498  * Returns a MEDCouplingUMesh of a relative dimension == 0.
3499  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3500  *          optional numbers of mesh entities.
3501  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
3502  *          delete using decrRef() as it is no more needed. 
3503  *  \throw If there are no mesh entities of the relative dimension == 0 in \a this mesh.
3504  */
3505 MEDCouplingUMesh *MEDFileUMesh::getLevel0Mesh(bool renum) const
3506 {
3507   return getMeshAtLevel(0,renum);
3508 }
3509
3510 /*!
3511  * Returns a MEDCouplingUMesh of a relative dimension == -1.
3512  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3513  *          optional numbers of mesh entities.
3514  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
3515  *          delete using decrRef() as it is no more needed. 
3516  *  \throw If there are no mesh entities of the relative dimension == -1 in \a this mesh.
3517  */
3518 MEDCouplingUMesh *MEDFileUMesh::getLevelM1Mesh(bool renum) const
3519 {
3520   return getMeshAtLevel(-1,renum);
3521 }
3522
3523 /*!
3524  * Returns a MEDCouplingUMesh of a relative dimension == -2.
3525  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3526  *          optional numbers of mesh entities.
3527  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
3528  *          delete using decrRef() as it is no more needed. 
3529  *  \throw If there are no mesh entities of the relative dimension == -2 in \a this mesh.
3530  */
3531 MEDCouplingUMesh *MEDFileUMesh::getLevelM2Mesh(bool renum) const
3532 {
3533   return getMeshAtLevel(-2,renum);
3534 }
3535
3536 /*!
3537  * Returns a MEDCouplingUMesh of a relative dimension == -3.
3538  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3539  *          optional numbers of mesh entities.
3540  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
3541  *          delete using decrRef() as it is no more needed. 
3542  *  \throw If there are no mesh entities of the relative dimension == -3 in \a this mesh.
3543  */
3544 MEDCouplingUMesh *MEDFileUMesh::getLevelM3Mesh(bool renum) const
3545 {
3546   return getMeshAtLevel(-3,renum);
3547 }
3548
3549 /*!
3550  * This method is for advanced users. There is two storing strategy of mesh in \a this.
3551  * Either MEDCouplingUMesh, or vector of MEDCoupling1GTUMesh instances.
3552  * When assignement is done the first one is done, which is not optimal in write mode for MED file.
3553  * This method allows to switch from MEDCouplingUMesh mode to MEDCoupling1GTUMesh mode.
3554  */
3555 void MEDFileUMesh::forceComputationOfParts() const
3556 {
3557   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
3558     {
3559       const MEDFileUMeshSplitL1 *elt(*it);
3560       if(elt)
3561         elt->forceComputationOfParts();
3562     }
3563 }
3564
3565 /*!
3566  * This method returns a vector of mesh parts containing each exactly one geometric type.
3567  * This method will never launch an automatic computation of split by type (an INTERP_KERNEL::Exception will be then thrown).
3568  * This method is only for memory aware users.
3569  * The returned pointers are **NOT** new object pointer. No need to mange them.
3570  */
3571 std::vector<MEDCoupling1GTUMesh *> MEDFileUMesh::getDirectUndergroundSingleGeoTypeMeshes(int meshDimRelToMax) const
3572 {
3573   checkCartesian();
3574   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(meshDimRelToMax));
3575   return sp->getDirectUndergroundSingleGeoTypeMeshes();
3576 }
3577
3578 /*!
3579  * This method returns the part of \a this having the geometric type \a gt.
3580  * If such part is not existing an exception will be thrown.
3581  * The returned pointer is **NOT** new object pointer. No need to mange it.
3582  */
3583 MEDCoupling1GTUMesh *MEDFileUMesh::getDirectUndergroundSingleGeoTypeMesh(INTERP_KERNEL::NormalizedCellType gt) const
3584 {
3585   checkCartesian();
3586   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(gt));
3587   int lev=(int)cm.getDimension()-getMeshDimension();
3588   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(lev));
3589   return sp->getDirectUndergroundSingleGeoTypeMesh(gt);
3590 }
3591
3592 /*!
3593  * Given a relative level \a meshDimRelToMax it returns the sorted vector of geometric types present in \a this.
3594  * \throw if the reqsuested \a meshDimRelToMax does not exist.
3595  */
3596 std::vector<INTERP_KERNEL::NormalizedCellType> MEDFileUMesh::getGeoTypesAtLevel(int meshDimRelToMax) const
3597 {
3598   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(meshDimRelToMax));
3599   return sp->getGeoTypes();
3600 }
3601
3602 int MEDFileUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType ct) const
3603 {
3604   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(ct);
3605   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe( ((int)cm.getDimension())-getMeshDimension() ));
3606   return sp->getNumberOfCellsWithType(ct);
3607 }
3608
3609 /*!
3610  * This method extracts from whole family field ids the part relative to the input parameter \a gt.
3611  * \param [in] gt - the geometric type for which the family field is asked.
3612  * \return DataArrayInt * - a pointer to DataArrayInt that the caller is to
3613  *          delete using decrRef() as it is no more needed.
3614  * \sa MEDFileUMesh::extractNumberFieldOnGeoType
3615  */
3616 DataArrayInt *MEDFileUMesh::extractFamilyFieldOnGeoType(INTERP_KERNEL::NormalizedCellType gt) const
3617 {
3618   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
3619   int lev=(int)cm.getDimension()-getMeshDimension();
3620   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(lev));
3621   return sp->extractFamilyFieldOnGeoType(gt);
3622 }
3623
3624 /*!
3625  * This method extracts from whole number field ids the part relative to the input parameter \a gt.
3626  * \param [in] gt - the geometric type for which the number field is asked.
3627  * \return DataArrayInt * - a pointer to DataArrayInt that the caller is to
3628  *          delete using decrRef() as it is no more needed.
3629  * \sa MEDFileUMesh::extractFamilyFieldOnGeoType
3630  */
3631 DataArrayInt *MEDFileUMesh::extractNumberFieldOnGeoType(INTERP_KERNEL::NormalizedCellType gt) const
3632 {
3633   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
3634   int lev=(int)cm.getDimension()-getMeshDimension();
3635   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(lev));
3636   return sp->extractNumberFieldOnGeoType(gt);
3637 }
3638
3639 /*!
3640  * This method returns for specified geometric type \a gt the relative level to \a this.
3641  * If the relative level is empty an exception will be thrown.
3642  */
3643 int MEDFileUMesh::getRelativeLevOnGeoType(INTERP_KERNEL::NormalizedCellType gt) const
3644 {
3645   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
3646   int ret((int)cm.getDimension()-getMeshDimension());
3647   getMeshAtLevSafe(ret);//To test that returned value corresponds to a valid level.
3648   return ret;
3649 }
3650
3651 const MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt) const
3652 {
3653   if(meshDimRelToMaxExt==1)
3654     throw INTERP_KERNEL::Exception("Dimension request is invalid : asking for node level (1) !");
3655   if(meshDimRelToMaxExt>1)
3656     throw INTERP_KERNEL::Exception("Dimension request is invalid (>1) !");
3657   int tracucedRk=-meshDimRelToMaxExt;
3658   if(tracucedRk>=(int)_ms.size())
3659     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
3660   if((const MEDFileUMeshSplitL1 *)_ms[tracucedRk]==0)
3661     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3662   return _ms[tracucedRk];
3663 }
3664
3665 MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt)
3666 {
3667   if(meshDimRelToMaxExt==1)
3668     throw INTERP_KERNEL::Exception("Dimension request is invalid : asking for node level (1) !");
3669   if(meshDimRelToMaxExt>1)
3670     throw INTERP_KERNEL::Exception("Dimension request is invalid (>1) !");
3671   int tracucedRk=-meshDimRelToMaxExt;
3672   if(tracucedRk>=(int)_ms.size())
3673     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
3674   if((const MEDFileUMeshSplitL1 *)_ms[tracucedRk]==0)
3675     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3676   return _ms[tracucedRk];
3677 }
3678
3679 void MEDFileUMesh::checkMeshDimCoherency(int meshDim, int meshDimRelToMax) const
3680 {
3681   if(-meshDimRelToMax>=(int)_ms.size())
3682     throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMeshDimCoherency : The meshdim of mesh is not managed by 'this' !");
3683   int i=0;
3684   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,i++)
3685     {
3686       if(((const MEDFileUMeshSplitL1*) (*it))!=0)
3687         {
3688           int ref=(*it)->getMeshDimension();
3689           if(ref+i!=meshDim-meshDimRelToMax)
3690             throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMeshDimCoherency : no coherency between levels !");
3691         }
3692     }
3693 }
3694
3695 /*!
3696  * Sets the node coordinates array of \a this mesh.
3697  *  \param [in] coords - the new node coordinates array.
3698  *  \throw If \a coords == \c NULL.
3699  */
3700 void MEDFileUMesh::setCoords(DataArrayDouble *coords)
3701 {
3702   if(!coords)
3703     throw INTERP_KERNEL::Exception("MEDFileUMesh::setCoords : null pointer in input !");
3704   if(coords==(DataArrayDouble *)_coords)
3705     return ;
3706   coords->checkAllocated();
3707   int nbOfTuples=coords->getNumberOfTuples();
3708   _coords=coords;
3709   coords->incrRef();
3710   _fam_coords=DataArrayInt::New();
3711   _fam_coords->alloc(nbOfTuples,1);
3712   _fam_coords->fillWithZero();
3713   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
3714     if((MEDFileUMeshSplitL1 *)(*it))
3715       (*it)->setCoords(coords);
3716 }
3717
3718 /*!
3719  * Removes all groups of a given dimension in \a this mesh.
3720  *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
3721  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3722  */
3723 void MEDFileUMesh::eraseGroupsAtLevel(int meshDimRelToMaxExt)
3724 {
3725   if(meshDimRelToMaxExt==1)
3726     {
3727       if((DataArrayInt *)_fam_coords)
3728         _fam_coords->fillWithZero();
3729       return ;
3730     }
3731   MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3732   l1->eraseFamilyField();
3733   optimizeFamilies();
3734 }
3735
3736 /*!
3737  * Removes all families with ids not present in the family fields of \a this mesh.
3738  */
3739 void MEDFileUMesh::optimizeFamilies()
3740 {
3741   std::vector<int> levs=getNonEmptyLevelsExt();
3742   std::set<int> allFamsIds;
3743   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
3744     {
3745       const DataArrayInt *ffield=getFamilyFieldAtLevel(*it);
3746       MCAuto<DataArrayInt> ids=ffield->getDifferentValues();
3747       std::set<int> res;
3748       std::set_union(ids->begin(),ids->end(),allFamsIds.begin(),allFamsIds.end(),std::inserter(res,res.begin()));
3749       allFamsIds=res;
3750     }
3751   std::set<std::string> famNamesToKill;
3752   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
3753     {
3754       if(allFamsIds.find((*it).second)!=allFamsIds.end())
3755         famNamesToKill.insert((*it).first);
3756     }
3757   for(std::set<std::string>::const_iterator it=famNamesToKill.begin();it!=famNamesToKill.end();it++)
3758     _families.erase(*it);
3759   std::vector<std::string> grpNamesToKill;
3760   for(std::map<std::string, std::vector<std::string> >::iterator it=_groups.begin();it!=_groups.end();it++)
3761     {
3762       std::vector<std::string> tmp;
3763       for(std::vector<std::string>::const_iterator it2=(*it).second.begin();it2!=(*it).second.end();it2++)
3764         {
3765           if(famNamesToKill.find(*it2)==famNamesToKill.end())
3766             tmp.push_back(*it2);
3767         }
3768       if(!tmp.empty())
3769         (*it).second=tmp;
3770       else
3771         tmp.push_back((*it).first);
3772     }
3773   for(std::vector<std::string>::const_iterator it=grpNamesToKill.begin();it!=grpNamesToKill.end();it++)
3774     _groups.erase(*it);
3775 }
3776
3777 /**
3778  * \b this must be filled at level 0 and -1, typically the -1 level being (part of) the descending connectivity
3779  * of the top level. This method build a "crack", or an inner boundary, in \b this along the group of level -1 named grpNameM1.
3780  * The boundary is built according to the following method:
3781  *  - all nodes along the boundary which are not lying on an internal extremity of the (-1)-level group are duplicated (so the
3782  * coordinates array is extended).
3783  *  - new (-1)-level cells are built lying on those new nodes. So the edges/faces along the group are duplicated. A new group
3784  *  called "<grpNameM1>_dup" containing the effectively duplicated cells is created. Note that in 3D some cells of the group
3785  *  might not be duplicated at all.
3786  *  After this operation a top-level cell bordering the group will loose some neighbors (typically the cell which is  on the
3787  *  other side of the group is no more a neighbor)
3788  *   - finally, the connectivity of (part of) the top level-cells bordering the group is also modified so that some cells
3789  *  bordering the newly created boundary use the newly computed nodes.
3790  *  Finally note that optional cell numbers are also affected by this method and might become invalid for SMESH.
3791  *  Use clearNodeAndCellNumbers() afterwards to ensure a proper SMESH loading.
3792  *
3793  *  \param[in] grpNameM1 name of the (-1)-level group defining the boundary
3794  *  \param[out] nodesDuplicated ids of the initial nodes which have been duplicated (and whose copy is put at the end of
3795  *  the coord array)
3796  *  \param[out] cellsModified ids of the cells whose connectivity has been modified (to use the newly created nodes)
3797  *  \param[out] cellsNotModified ids of the rest of cells bordering the new boundary whose connectivity remains unchanged.
3798  *  \sa clearNodeAndCellNumbers()
3799  */
3800 void MEDFileUMesh::buildInnerBoundaryAlongM1Group(const std::string& grpNameM1, DataArrayInt *&nodesDuplicated,
3801                                            DataArrayInt *&cellsModified, DataArrayInt *&cellsNotModified)
3802 {
3803   typedef MCAuto<MEDCouplingUMesh> MUMesh;
3804   typedef MCAuto<DataArrayInt> DAInt;
3805
3806   std::vector<int> levs=getNonEmptyLevels();
3807   if(std::find(levs.begin(),levs.end(),0)==levs.end() || std::find(levs.begin(),levs.end(),-1)==levs.end())
3808     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildInnerBoundaryAlongM1Group : This method works only for mesh definied on level 0 and -1 !");
3809   MUMesh m0=getMeshAtLevel(0);
3810   MUMesh m1=getMeshAtLevel(-1);
3811   int nbNodes=m0->getNumberOfNodes();
3812   MUMesh m11=getGroup(-1,grpNameM1);
3813   DataArrayInt *tmp00=0,*tmp11=0,*tmp22=0;
3814   m0->findNodesToDuplicate(*m11,tmp00,tmp11,tmp22);
3815   DAInt nodeIdsToDuplicate(tmp00);
3816   DAInt cellsToModifyConn0(tmp11);
3817   DAInt cellsToModifyConn1(tmp22);
3818   MUMesh tmp0=static_cast<MEDCouplingUMesh *>(m0->buildPartOfMySelf(cellsToModifyConn0->begin(),cellsToModifyConn0->end(),true));
3819   // node renumbering of cells in m1 impacted by duplication of node but not in group 'grpNameM1' on level -1
3820   DAInt descTmp0=DataArrayInt::New(),descITmp0=DataArrayInt::New(),revDescTmp0=DataArrayInt::New(),revDescITmp0=DataArrayInt::New();
3821   MUMesh tmp0Desc=tmp0->buildDescendingConnectivity(descTmp0,descITmp0,revDescTmp0,revDescITmp0);
3822   descTmp0=0; descITmp0=0; revDescTmp0=0; revDescITmp0=0;
3823   DAInt cellsInM1ToRenumW2=tmp0Desc->getCellIdsLyingOnNodes(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),false);
3824   MUMesh cellsInM1ToRenumW3=static_cast<MEDCouplingUMesh *>(tmp0Desc->buildPartOfMySelf(cellsInM1ToRenumW2->begin(),cellsInM1ToRenumW2->end(),true));
3825   DataArrayInt *cellsInM1ToRenumW4Tmp=0;
3826   m1->areCellsIncludedIn(cellsInM1ToRenumW3,2,cellsInM1ToRenumW4Tmp);
3827   DAInt cellsInM1ToRenumW4(cellsInM1ToRenumW4Tmp);
3828   DAInt cellsInM1ToRenumW5=cellsInM1ToRenumW4->findIdsInRange(0,m1->getNumberOfCells());
3829   cellsInM1ToRenumW5->transformWithIndArr(cellsInM1ToRenumW4->begin(),cellsInM1ToRenumW4->end());
3830   DAInt grpIds=getGroupArr(-1,grpNameM1);
3831   DAInt cellsInM1ToRenum=cellsInM1ToRenumW5->buildSubstraction(grpIds);
3832   MUMesh m1Part=static_cast<MEDCouplingUMesh *>(m1->buildPartOfMySelf(cellsInM1ToRenum->begin(),cellsInM1ToRenum->end(),true));
3833   m1Part->duplicateNodesInConn(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),nbNodes);
3834   m1->setPartOfMySelf(cellsInM1ToRenum->begin(),cellsInM1ToRenum->end(),*m1Part);
3835   // end of node renumbering of cells in m1 impacted by duplication of node but not in group of level -1 'grpNameM1'
3836   tmp0->duplicateNodes(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end());
3837   m0->setCoords(tmp0->getCoords());
3838   m0->setPartOfMySelf(cellsToModifyConn0->begin(),cellsToModifyConn0->end(),*tmp0);
3839   _ms[0]->forceComputationOfParts();  // necessary because we modify the connectivity of some internal part
3840   m1->setCoords(m0->getCoords());
3841   _coords=m0->getCoords(); _coords->incrRef();
3842   // duplication of cells in group 'grpNameM1' on level -1, but not duplicating cells for which nothing has changed
3843   m11->duplicateNodesInConn(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),nbNodes); m11->setCoords(m0->getCoords());
3844   DataArrayInt * duplCells;
3845   m1->areCellsIncludedIn(m11, 0, duplCells);
3846   DAInt zeIds = duplCells->findIdsNotInRange(-1, m1->getNumberOfCells()-1); duplCells->decrRef();
3847   MUMesh m11Part=static_cast<MEDCouplingUMesh *>(m11->buildPartOfMySelf(zeIds->begin(),zeIds->end(),true));
3848   std::vector<const MEDCouplingUMesh *> v(2); v[0]=m1; v[1]=m11Part;
3849   MUMesh newm1=MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(v,tmp00,tmp11);
3850   DAInt szOfCellGrpOfSameType(tmp00);
3851   DAInt idInMsOfCellGrpOfSameType(tmp11);
3852   //
3853   newm1->setName(getName());
3854   const DataArrayInt *fam=getFamilyFieldAtLevel(-1);
3855   if(!fam)
3856     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildInnerBoundaryAlongM1Group(): internal error no family field !");
3857   DAInt newFam=DataArrayInt::New();
3858   newFam->alloc(newm1->getNumberOfCells(),1);
3859   // Get a new family ID: care must be taken if we need a positive ID or a negative one:
3860   // Positive ID for family of nodes, negative for all the rest.
3861   int idd;
3862   if (m1->getMeshDimension() == 0)
3863     idd=getMaxFamilyId()+1;
3864   else
3865     idd=getMinFamilyId()-1;
3866   int globStart=0,start=0,end,globEnd;
3867   int nbOfChunks=szOfCellGrpOfSameType->getNumberOfTuples();
3868   for(int i=0;i<nbOfChunks;i++)
3869     {
3870       globEnd=globStart+szOfCellGrpOfSameType->getIJ(i,0);
3871       if(idInMsOfCellGrpOfSameType->getIJ(i,0)==0)
3872         {
3873           end=start+szOfCellGrpOfSameType->getIJ(i,0);
3874           DAInt part=fam->selectByTupleIdSafeSlice(start,end,1);
3875           newFam->setPartOfValues1(part,globStart,globEnd,1,0,1,1,true);
3876           start=end;
3877         }
3878       else
3879         {
3880           newFam->setPartOfValuesSimple1(idd,globStart,globEnd,1,0,1,1);
3881         }
3882       globStart=globEnd;
3883     }
3884   newm1->setCoords(getCoords());
3885   setMeshAtLevel(-1,newm1);
3886   setFamilyFieldArr(-1,newFam);
3887   std::string grpName2(grpNameM1); grpName2+="_dup";
3888   addFamily(grpName2,idd);
3889   addFamilyOnGrp(grpName2,grpName2);
3890   //
3891   fam=_fam_coords;
3892   if(fam)
3893     {
3894       int newNbOfNodes=getCoords()->getNumberOfTuples();
3895       newFam=DataArrayInt::New(); newFam->alloc(newNbOfNodes,1);
3896       newFam->setPartOfValues1(fam,0,nbNodes,1,0,1,1,true);
3897       newFam->setPartOfValuesSimple1(0,nbNodes,newNbOfNodes,1,0,1,1);
3898       _fam_coords=newFam;
3899     }
3900
3901   _num_coords = 0;
3902   _rev_num_coords = 0;
3903   for (std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();
3904       it != _ms.end(); it++)
3905     {
3906       (*it)->_num = 0;
3907       (*it)->_rev_num = 0;
3908     }
3909   nodesDuplicated=nodeIdsToDuplicate.retn();
3910   cellsModified=cellsToModifyConn0.retn();
3911   cellsNotModified=cellsToModifyConn1.retn();
3912 }
3913
3914 /*! Similar to MEDCouplingUMesh::unPolyze():  converts all polygons (if \a this is a 2D mesh) or polyhedrons
3915  * (if \a this is a 3D mesh) to cells of classical types. The cells remain correctly sorted by geometric type
3916  * in this method.
3917  *
3918  * \param [out] oldCode retrieves the distribution of types before the call if true is returned
3919  * \param [out] newCode etrieves the distribution of types after the call if true is returned
3920  * \param [out] o2nRenumCell tells for **all levels** the old 2 new renumbering of cells.
3921  * 
3922  * \return false if no modification has been performed linked to the unpolyzation. Neither cell type, not cell numbers. When false is returned no need of field on cells or on gauss renumbering.
3923  * Inversely, if true is returned, it means that distribution of cell by geometric type has changed and field on cell and field on gauss point must be renumbered.
3924  */
3925 bool MEDFileUMesh::unPolyze(std::vector<int>& oldCode, std::vector<int>& newCode, DataArrayInt *& o2nRenumCell)
3926 {
3927   o2nRenumCell=0; oldCode.clear(); newCode.clear();
3928   std::vector<int> levs=getNonEmptyLevels();
3929   bool ret=false;
3930   std::vector< const DataArrayInt* > renumCellsSplited;//same than memorySaverIfThrow
3931   std::vector< MCAuto<DataArrayInt> > memorySaverIfThrow;//same than renumCellsSplited only in case of throw
3932   int start=0;
3933   int end=0;
3934   for(std::vector<int>::reverse_iterator it=levs.rbegin();it!=levs.rend();it++)
3935     {
3936       MCAuto<MEDCouplingUMesh> m=getMeshAtLevel(*it);
3937       std::vector<int> code1=m->getDistributionOfTypes();
3938       end=PutInThirdComponentOfCodeOffset(code1,start);
3939       oldCode.insert(oldCode.end(),code1.begin(),code1.end());
3940       bool hasChanged=m->unPolyze();
3941       DataArrayInt *fake=0;
3942       MCAuto<DataArrayInt> o2nCellsPart=m->getLevArrPerCellTypes(MEDCouplingUMesh::MEDMEM_ORDER,
3943           MEDCouplingUMesh::MEDMEM_ORDER+MEDCouplingUMesh::N_MEDMEM_ORDER,fake);
3944       fake->decrRef();
3945       renumCellsSplited.push_back(o2nCellsPart); memorySaverIfThrow.push_back(o2nCellsPart);
3946       if(hasChanged)
3947         {
3948           MCAuto<DataArrayInt> o2nCellsPart2=o2nCellsPart->buildPermArrPerLevel();
3949           m->renumberCells(o2nCellsPart2->getConstPointer(),false);
3950           ret=true;
3951           MCAuto<DataArrayInt> famField2,numField2;
3952           const DataArrayInt *famField=getFamilyFieldAtLevel(*it); if(famField) { famField->incrRef(); famField2=const_cast<DataArrayInt *>(famField); }
3953           const DataArrayInt *numField=getNumberFieldAtLevel(*it); if(numField) { numField->incrRef(); numField2=const_cast<DataArrayInt *>(numField); }
3954           setMeshAtLevel(*it,m);
3955           std::vector<int> code2=m->getDistributionOfTypes();
3956           end=PutInThirdComponentOfCodeOffset(code2,start);
3957           newCode.insert(newCode.end(),code2.begin(),code2.end());
3958           //
3959           if(o2nCellsPart2->isIota(o2nCellsPart2->getNumberOfTuples()))
3960             continue;
3961           if(famField)
3962             {
3963               MCAuto<DataArrayInt> newFamField=famField->renumber(o2nCellsPart2->getConstPointer());
3964               setFamilyFieldArr(*it,newFamField);
3965             }
3966           if(numField)
3967             {
3968               MCAuto<DataArrayInt> newNumField=numField->renumber(o2nCellsPart2->getConstPointer());
3969               setRenumFieldArr(*it,newNumField);
3970             }
3971         }
3972       else
3973         {
3974           newCode.insert(newCode.end(),code1.begin(),code1.end());
3975         }
3976       start=end;
3977     }
3978   if(ret)
3979     {
3980       MCAuto<DataArrayInt> renumCells=DataArrayInt::Aggregate(renumCellsSplited);
3981       MCAuto<DataArrayInt> o2nRenumCellRet=renumCells->buildPermArrPerLevel();
3982       o2nRenumCell=o2nRenumCellRet.retn();
3983     }
3984   return ret;
3985 }
3986
3987 /*! \cond HIDDEN_ITEMS */
3988 struct MEDLoaderAccVisit1
3989 {
3990   MEDLoaderAccVisit1():_new_nb_of_nodes(0) { }
3991   int operator()(bool val) { return val?_new_nb_of_nodes++:-1; }
3992   int _new_nb_of_nodes;
3993 };
3994 /*! \endcond */
3995
3996 /*!
3997  * Array returned is the correspondance in \b old \b to \b new format. The returned array is newly created and should be dealt by the caller.
3998  * The maximum value stored in returned array is the number of nodes of \a this minus 1 after call of this method.
3999  * The size of returned array is the number of nodes of the old (previous to the call of this method) number of nodes.
4000  * -1 values in returned array means that the corresponding old node is no more used.
4001  *
4002  * \return newly allocated array containing correspondance in \b old \b to \b new format. If all nodes in \a this are fetched \c NULL pointer is returned and nothing
4003  *         is modified in \a this.
4004  * \throw If no coordinates are set in \a this or if there is in any available mesh in \a this a cell having a nodal connectivity containing a node id not in the range of
4005  *  set coordinates.
4006  */
4007 DataArrayInt *MEDFileUMesh::zipCoords()
4008 {
4009   const DataArrayDouble *coo(getCoords());
4010   if(!coo)
4011     throw INTERP_KERNEL::Exception("MEDFileUMesh::zipCoords : no coordinates set in this !");
4012   int nbOfNodes(coo->getNumberOfTuples());
4013   std::vector<bool> nodeIdsInUse(nbOfNodes,false);
4014   std::vector<int> neLevs(getNonEmptyLevels());
4015   for(std::vector<int>::const_iterator lev=neLevs.begin();lev!=neLevs.end();lev++)
4016     {
4017       const MEDFileUMeshSplitL1 *zeLev(getMeshAtLevSafe(*lev));
4018       if(zeLev->isMeshStoredSplitByType())
4019         {
4020           std::vector<MEDCoupling1GTUMesh *> ms(zeLev->getDirectUndergroundSingleGeoTypeMeshes());
4021           for(std::vector<MEDCoupling1GTUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
4022             if(*it)
4023               (*it)->computeNodeIdsAlg(nodeIdsInUse);
4024         }
4025       else
4026         {
4027           MCAuto<MEDCouplingUMesh> mesh(zeLev->getWholeMesh(false));
4028           mesh->computeNodeIdsAlg(nodeIdsInUse);
4029         }
4030     }
4031   int nbrOfNodesInUse((int)std::count(nodeIdsInUse.begin(),nodeIdsInUse.end(),true));
4032   if(nbrOfNodesInUse==nbOfNodes)
4033     return 0;//no need to update _part_coords
4034   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodes,1);
4035   std::transform(nodeIdsInUse.begin(),nodeIdsInUse.end(),ret->getPointer(),MEDLoaderAccVisit1());
4036   MCAuto<DataArrayInt> ret2(ret->invertArrayO2N2N2OBis(nbrOfNodesInUse));
4037   MCAuto<DataArrayDouble> newCoords(coo->selectByTupleIdSafe(ret2->begin(),ret2->end()));
4038   MCAuto<DataArrayInt> newFamCoords;
4039   MCAuto<DataArrayAsciiChar> newNameCoords;
4040   if((const DataArrayInt *)_fam_coords)
4041     newFamCoords=_fam_coords->selectByTupleIdSafe(ret2->begin(),ret2->end());
4042   MCAuto<DataArrayInt> newNumCoords;
4043   if((const DataArrayInt *)_num_coords)
4044     newNumCoords=_num_coords->selectByTupleIdSafe(ret2->begin(),ret2->end());
4045   if((const DataArrayAsciiChar *)_name_coords)
4046     newNameCoords=static_cast<DataArrayAsciiChar *>(_name_coords->selectByTupleIdSafe(ret2->begin(),ret2->end()));
4047   _coords=newCoords; _fam_coords=newFamCoords; _num_coords=newNumCoords; _name_coords=newNameCoords; _rev_num_coords=0;
4048   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
4049     {
4050       if((MEDFileUMeshSplitL1*)*it)
4051         {
4052           (*it)->renumberNodesInConn(ret->begin());
4053           (*it)->setCoords(_coords);
4054         }
4055     }
4056   // updates _part_coords
4057   const PartDefinition *pc(_part_coords);
4058   if(pc)
4059     {
4060       MCAuto<PartDefinition> tmpPD(DataArrayPartDefinition::New(ret2));
4061       _part_coords=tmpPD->composeWith(pc);
4062     }
4063   return ret.retn();
4064 }
4065
4066 /*!
4067  * This method performs an extrusion along a path defined by \a m1D.
4068  * \a this is expected to be a mesh with max mesh dimension equal to 2.
4069  * \a m1D is expected to be a mesh with space dimesion equal to 3 and mesh dimension equal to 1.
4070  * Mesh dimensions of returned mesh is incremented by one compared to thoose in \a this.
4071  * This method scans all levels in \a this
4072  * and put them in the returned mesh. All groups in \a this are also put in the returned mesh.
4073  *
4074  * \param [in] m1D - the mesh defining the extrusion path.
4075  * \param [in] policy - defines the policy of extrusion (see MEDCouplingUMesh::buildExtrudedMesh for more details)
4076  * \return - a new reference on mesh (you have to deal with using decrRef). The returned mesh will have the same name than \a this.
4077  *
4078  * \sa MEDCouplingUMesh::buildExtrudedMesh
4079  */
4080 MEDFileUMesh *MEDFileUMesh::buildExtrudedMesh(const MEDCouplingUMesh *m1D, int policy) const
4081 {
4082   checkCartesian();
4083   if(getMeshDimension()!=2)
4084     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildExtrudedMesh : this is expected to be with mesh dimension equal to 2 !");
4085   MCAuto<MEDFileUMesh> ret(MEDFileUMesh::New());
4086   m1D->checkConsistencyLight();
4087   if(m1D->getMeshDimension()!=1)
4088     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildExtrudedMesh : input mesh must have a mesh dimension equal to one !");
4089   int nbRep(m1D->getNumberOfCells());
4090   std::vector<int> levs(getNonEmptyLevels());
4091   std::vector<std::string> grps(getGroupsNames());
4092   std::vector< MCAuto<MEDCouplingUMesh> > zeList;
4093   DataArrayDouble *coords(0);
4094   std::size_t nbOfLevsOut(levs.size()+1);
4095   std::vector< MCAuto<DataArrayInt> > o2ns(nbOfLevsOut);
4096   for(std::vector<int>::const_iterator lev=levs.begin();lev!=levs.end();lev++)
4097     {
4098       MCAuto<MEDCouplingUMesh> item(getMeshAtLevel(*lev));
4099       item=item->clone(false);
4100       item->changeSpaceDimension(3+(*lev),0.);//no problem non const but change DataArrayDouble for coordinates do not alter data
4101       MCAuto<MEDCouplingUMesh> tmp(static_cast<MEDCouplingUMesh *>(m1D->deepCopy()));
4102       tmp->changeSpaceDimension(3+(*lev),0.);
4103       MCAuto<MEDCouplingUMesh> elt(item->buildExtrudedMesh(tmp,policy));
4104       zeList.push_back(elt);
4105       if(*lev==0)
4106         coords=elt->getCoords();
4107     }
4108   if(!coords)
4109     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildExtrudedMesh : internal error !");
4110   for(std::vector< MCAuto<MEDCouplingUMesh> >::iterator it=zeList.begin();it!=zeList.end();it++)
4111     {
4112       (*it)->setName(getName());
4113       (*it)->setCoords(coords);
4114     }
4115   for(std::size_t ii=0;ii!=zeList.size();ii++)
4116     {
4117       int lev(levs[ii]);
4118       MCAuto<MEDCouplingUMesh> elt(zeList[ii]);
4119       if(lev<=-1)
4120         {
4121           MCAuto<MEDCouplingUMesh> elt1(getMeshAtLevel(lev+1));
4122           MCAuto<MEDCouplingUMesh> elt2(elt1->clone(false));
4123           MCAuto<DataArrayInt> tmp(elt2->getNodalConnectivity()->deepCopy());
4124           elt2->setConnectivity(tmp,elt2->getNodalConnectivityIndex());
4125           elt2->shiftNodeNumbersInConn(nbRep*elt1->getNumberOfNodes());
4126           elt1->setCoords(elt->getCoords()); elt2->setCoords(elt->getCoords());
4127           std::vector<const MEDCouplingUMesh *> elts(3);
4128           elts[0]=elt; elts[1]=elt1; elts[2]=elt2;
4129           elt=MEDCouplingUMesh::MergeUMeshesOnSameCoords(elts);
4130           elt->setName(getName());
4131         }
4132       //
4133       o2ns[ii]=elt->sortCellsInMEDFileFrmt();
4134       ret->setMeshAtLevel(lev,elt);
4135     }
4136   MCAuto<MEDCouplingUMesh> endLev(getMeshAtLevel(levs.back())),endLev2;
4137   endLev=endLev->clone(false); endLev->setCoords(coords);
4138   MCAuto<DataArrayInt> tmp(endLev->getNodalConnectivity()->deepCopy());
4139   endLev2=endLev->clone(false); endLev2->setConnectivity(tmp,endLev->getNodalConnectivityIndex());
4140   endLev2->shiftNodeNumbersInConn(nbRep*getNumberOfNodes());
4141   endLev=MEDCouplingUMesh::MergeUMeshesOnSameCoords(endLev,endLev2);
4142   o2ns[levs.size()]=endLev->sortCellsInMEDFileFrmt();
4143   endLev->setName(getName());
4144   ret->setMeshAtLevel(levs.back()-1,endLev);
4145   //
4146   for(std::size_t ii=0;ii!=zeList.size();ii++)
4147     {
4148       int lev(levs[ii]);
4149       std::vector< MCAuto<DataArrayInt> > outGrps;
4150       std::vector< const DataArrayInt * > outGrps2;
4151       if(lev<=-1)
4152         {
4153           for(std::vector<std::string>::const_iterator grp=grps.begin();grp!=grps.end();grp++)
4154             {
4155               MCAuto<DataArrayInt> grpArr(getGroupArr(lev+1,*grp));
4156               if(!grpArr->empty())
4157                 {
4158                   MCAuto<DataArrayInt> grpArr1(grpArr->deepCopy()),grpArr2(grpArr->deepCopy());
4159                   int offset0(zeList[ii]->getNumberOfCells());
4160                   int offset1(offset0+getNumberOfCellsAtLevel(lev+1));
4161                   grpArr1->applyLin(1,offset0); grpArr2->applyLin(1,offset1);
4162                   std::ostringstream oss; oss << grpArr2->getName() << "_top";
4163                   grpArr2->setName(oss.str());
4164                   grpArr1->transformWithIndArr(o2ns[ii]->begin(),o2ns[ii]->end());
4165                   grpArr2->transformWithIndArr(o2ns[ii]->begin(),o2ns[ii]->end());
4166                   outGrps.push_back(grpArr1); outGrps.push_back(grpArr2);
4167                   outGrps2.push_back(grpArr1); outGrps2.push_back(grpArr2);
4168                 }
4169             }
4170         }
4171       //
4172       for(std::vector<std::string>::const_iterator grp=grps.begin();grp!=grps.end();grp++)
4173         {
4174           MCAuto<DataArrayInt> grpArr(getGroupArr(lev,*grp));
4175           if(!grpArr->empty())
4176             {
4177               int nbCellsB4Extrusion(getNumberOfCellsAtLevel(lev));
4178               std::vector< MCAuto<DataArrayInt> > grpArrs(nbRep);
4179               std::vector< const DataArrayInt *> grpArrs2(nbRep);
4180               for(int iii=0;iii<nbRep;iii++)
4181                 {
4182                   grpArrs[iii]=grpArr->deepCopy(); grpArrs[iii]->applyLin(1,iii*nbCellsB4Extrusion);
4183                   grpArrs2[iii]=grpArrs[iii];
4184                 }
4185               MCAuto<DataArrayInt> grpArrExt(DataArrayInt::Aggregate(grpArrs2));
4186               grpArrExt->transformWithIndArr(o2ns[ii]->begin(),o2ns[ii]->end());
4187               std::ostringstream grpName; grpName << *grp << "_extruded";
4188               grpArrExt->setName(grpName.str());
4189               outGrps.push_back(grpArrExt);
4190               outGrps2.push_back(grpArrExt);
4191             }
4192         }
4193       ret->setGroupsAtLevel(lev,outGrps2);
4194     }
4195   std::vector< MCAuto<DataArrayInt> > outGrps;
4196   std::vector< const DataArrayInt * > outGrps2;
4197   for(std::vector<std::string>::const_iterator grp=grps.begin();grp!=grps.end();grp++)
4198     {
4199       MCAuto<DataArrayInt> grpArr1(getGroupArr(levs.back(),*grp));
4200       if(grpArr1->empty())
4201         continue;
4202       MCAuto<DataArrayInt> grpArr2(grpArr1->deepCopy());
4203       std::ostringstream grpName; grpName << *grp << "_top";
4204       grpArr2->setName(grpName.str());
4205       grpArr2->applyLin(1,getNumberOfCellsAtLevel(levs.back()));
4206       outGrps.push_back(grpArr1); outGrps.push_back(grpArr2);
4207       outGrps2.push_back(grpArr1); outGrps2.push_back(grpArr2);
4208     }
4209   ret->setGroupsAtLevel(levs.back()-1,outGrps2);
4210   return ret.retn();
4211 }
4212
4213 /*!
4214  * This method converts all linear cells in \a this into quadratic cells (following the \a conversionType policy).
4215  * All the cells converted are put in the returned instance. This method applies all the groups and families in \a this to returned instance.
4216  * Groups on nodes and families on nodes are copied directly to the returned instance without transformation.
4217  *
4218  * \param [in] conversionType - conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4219  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
4220  * \param [in] eps - detection threshold for coordinates.
4221  * \return A new instance that is the result of the conversion. The caller has the ownership of this returned instance.
4222  *
4223  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic , quadraticToLinear
4224  */
4225 MEDFileUMesh *MEDFileUMesh::linearToQuadratic(int conversionType, double eps) const
4226 {
4227   checkCartesian();
4228   MCAuto<MEDFileUMesh> ret(MEDFileUMesh::New());
4229   int initialNbNodes(getNumberOfNodes());
4230   MCAuto<MEDCouplingUMesh> m0Tmp(getMeshAtLevel(0));
4231   MCAuto<MEDCouplingUMesh> m0(dynamic_cast<MEDCouplingUMesh *>(m0Tmp->deepCopy()));
4232   {
4233     MCAuto<DataArrayInt> notUsed(m0->convertLinearCellsToQuadratic(conversionType));
4234   }
4235   DataArrayDouble *zeCoords(m0->getCoords());
4236   ret->setMeshAtLevel(0,m0);
4237   std::vector<int> levs(getNonEmptyLevels());
4238   const DataArrayInt *famField(getFamilyFieldAtLevel(0));
4239   if(famField)
4240     {
4241       MCAuto<DataArrayInt> famFieldCpy(famField->deepCopy());
4242       ret->setFamilyFieldArr(0,famFieldCpy);
4243     }
4244   famField=getFamilyFieldAtLevel(1);
4245   if(famField)
4246     {
4247       MCAuto<DataArrayInt> fam(DataArrayInt::New()); fam->alloc(zeCoords->getNumberOfTuples(),1);
4248       fam->fillWithZero();
4249       fam->setPartOfValues1(famField,0,initialNbNodes,1,0,1,1);
4250       ret->setFamilyFieldArr(1,fam);
4251     }
4252   ret->copyFamGrpMapsFrom(*this);
4253   MCAuto<DataArrayDouble> partZeCoords(zeCoords->selectByTupleIdSafeSlice(initialNbNodes,zeCoords->getNumberOfTuples(),1));
4254   for(std::vector<int>::const_iterator lev=levs.begin();lev!=levs.end();lev++)
4255     {
4256       if(*lev==0)
4257         continue;
4258       MCAuto<MEDCouplingUMesh> m1Tmp(getMeshAtLevel(*lev));
4259       MCAuto<MEDCouplingUMesh> m1(dynamic_cast<MEDCouplingUMesh *>(m1Tmp->deepCopy()));
4260       if(m1->getMeshDimension()!=0)
4261         {
4262           {
4263             MCAuto<DataArrayInt> notUsed(m1->convertLinearCellsToQuadratic(conversionType));
4264           }//kill unused notUsed var
4265           MCAuto<DataArrayDouble> m1Coords(m1->getCoords()->selectByTupleIdSafeSlice(initialNbNodes,m1->getNumberOfNodes(),1));
4266           DataArrayInt *b(0);
4267           bool a(partZeCoords->areIncludedInMe(m1Coords,eps,b));
4268           MCAuto<DataArrayInt> bSafe(b);
4269           if(!a)
4270             {
4271               std::ostringstream oss; oss << "MEDFileUMesh::linearCellsToQuadratic : for level " << *lev << " problem to identify nodes generated !";
4272               throw INTERP_KERNEL::Exception(oss.str().c_str());
4273             }
4274           b->applyLin(1,initialNbNodes);
4275           MCAuto<DataArrayInt> l0(DataArrayInt::New()); l0->alloc(initialNbNodes,1); l0->iota();
4276           std::vector<const DataArrayInt *> v(2); v[0]=l0; v[1]=b;
4277           MCAuto<DataArrayInt> renum(DataArrayInt::Aggregate(v));
4278           m1->renumberNodesInConn(renum->begin());
4279         }
4280       m1->setCoords(zeCoords);
4281       ret->setMeshAtLevel(*lev,m1);
4282       famField=getFamilyFieldAtLevel(*lev);
4283       if(famField)
4284         {
4285           MCAuto<DataArrayInt> famFieldCpy(famField->deepCopy());
4286           ret->setFamilyFieldArr(*lev,famFieldCpy);
4287         }
4288     }
4289   return ret.retn();
4290 }
4291
4292 /*!
4293  * This method converts all quadratic cells in \a this into linear cells.
4294  * All the cells converted are put in the returned instance. This method applies all the groups and families in \a this to returned instance.
4295  * Groups on nodes and families on nodes are copied directly to the returned instance without transformation.
4296  *
4297  * \param [in] eps - detection threshold for coordinates.
4298  * \return A new instance that is the result of the conversion. The caller has the ownership of this returned instance.
4299  *
4300  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic , linearToQuadratic
4301  */
4302 MEDFileUMesh *MEDFileUMesh::quadraticToLinear(double eps) const
4303 {
4304   checkCartesian();
4305   MCAuto<MEDFileUMesh> ret(MEDFileUMesh::New());
4306   MCAuto<MEDCouplingUMesh> m0Tmp(getMeshAtLevel(0));
4307   MCAuto<MEDCouplingUMesh> m0(dynamic_cast<MEDCouplingUMesh *>(m0Tmp->deepCopy()));
4308   m0->convertQuadraticCellsToLinear();
4309   m0->zipCoords();
4310   DataArrayDouble *zeCoords(m0->getCoords());
4311   ret->setMeshAtLevel(0,m0);
4312   std::vector<int> levs(getNonEmptyLevels());
4313   const DataArrayInt *famField(getFamilyFieldAtLevel(0));
4314   if(famField)
4315     {
4316       MCAuto<DataArrayInt> famFieldCpy(famField->deepCopy());
4317       ret->setFamilyFieldArr(0,famFieldCpy);
4318     }
4319   famField=getFamilyFieldAtLevel(1);
4320   if(famField)
4321     {
4322       MCAuto<DataArrayInt> fam(famField->selectByTupleIdSafeSlice(0,zeCoords->getNumberOfTuples(),1));
4323       ret->setFamilyFieldArr(1,fam);
4324     }
4325   ret->copyFamGrpMapsFrom(*this);
4326   for(std::vector<int>::const_iterator lev=levs.begin();lev!=levs.end();lev++)
4327     {
4328       if(*lev==0)
4329         continue;
4330       MCAuto<MEDCouplingUMesh> m1Tmp(getMeshAtLevel(*lev));
4331       MCAuto<MEDCouplingUMesh> m1(dynamic_cast<MEDCouplingUMesh *>(m1Tmp->deepCopy()));
4332       m1->convertQuadraticCellsToLinear();
4333       m1->zipCoords();
4334       DataArrayInt *b(0);
4335       bool a(zeCoords->areIncludedInMe(m1->getCoords(),eps,b));
4336       MCAuto<DataArrayInt> bSafe(b);
4337       if(!a)
4338         {
4339           std::ostringstream oss; oss << "MEDFileUMesh::quadraticToLinear : for level " << *lev << " problem to identify nodes generated !";
4340           throw INTERP_KERNEL::Exception(oss.str().c_str());
4341         }
4342       m1->renumberNodesInConn(b->begin());
4343       m1->setCoords(zeCoords);
4344       ret->setMeshAtLevel(*lev,m1);
4345       famField=getFamilyFieldAtLevel(*lev);
4346       if(famField)
4347         {
4348           MCAuto<DataArrayInt> famFieldCpy(famField->deepCopy());
4349           ret->setFamilyFieldArr(*lev,famFieldCpy);
4350         }
4351     }
4352   return ret.retn();
4353 }
4354
4355 void MEDFileUMesh::serialize(std::vector<double>& tinyDouble, std::vector<int>& tinyInt, std::vector<std::string>& tinyStr, std::vector< MCAuto<DataArrayInt> >& bigArraysI, MCAuto<DataArrayDouble>& bigArrayD)
4356 {
4357   clearNonDiscrAttributes();
4358   forceComputationOfParts();
4359   tinyDouble.clear(); tinyInt.clear(); tinyStr.clear(); bigArraysI.clear(); bigArrayD=0;
4360   std::vector<int> layer0;
4361   layer0.push_back(getAxisType());//0 i
4362   layer0.push_back(_order); //1 i
4363   layer0.push_back(_iteration);//2 i
4364   layer0.push_back(getSpaceDimension());//3 i
4365   tinyDouble.push_back(_time);//0 d
4366   tinyStr.push_back(_name);//0 s
4367   tinyStr.push_back(_desc_name);//1 s
4368   for(int i=0;i<getSpaceDimension();i++)
4369     tinyStr.push_back(_coords->getInfoOnComponent(i));
4370   layer0.push_back((int)_families.size());//4 i <- key info aa layer#0
4371   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
4372     {
4373       tinyStr.push_back((*it).first);
4374       layer0.push_back((*it).second);
4375     }
4376   layer0.push_back((int)_groups.size());//4+aa i <- key info bb layer#0
4377   for(std::map<std::string, std::vector<std::string> >::const_iterator it0=_groups.begin();it0!=_groups.end();it0++)
4378     {
4379       layer0.push_back((int)(*it0).second.size());
4380       tinyStr.push_back((*it0).first);
4381       for(std::vector<std::string>::const_iterator it1=((*it0).second).begin();it1!=((*it0).second).end();it1++)
4382         tinyStr.push_back(*it1);
4383     }
4384   // sizeof(layer0)==4+aa+1+bb layer#0
4385   bigArrayD=_coords;// 0 bd
4386   bigArraysI.push_back(_fam_coords);// 0 bi
4387   bigArraysI.push_back(_num_coords);// 1 bi
4388   const PartDefinition *pd(_part_coords);
4389   if(!pd)
4390     layer0.push_back(-1);
4391   else
4392     {
4393       std::vector<int> tmp0;
4394       pd->serialize(tmp0,bigArraysI);
4395       tinyInt.push_back(tmp0.size());
4396       tinyInt.insert(tinyInt.end(),tmp0.begin(),tmp0.end());
4397     }
4398   //
4399   std::vector<int> layer1;
4400   std::vector<int> levs(getNonEmptyLevels());
4401   layer1.push_back((int)levs.size());// 0 i <- key
4402   layer1.insert(layer1.end(),levs.begin(),levs.end());
4403   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
4404     {
4405       const MEDFileUMeshSplitL1 *lev(getMeshAtLevSafe(*it));
4406       lev->serialize(layer1,bigArraysI);
4407     }
4408   // put layers all together.
4409   tinyInt.push_back(layer0.size());
4410   tinyInt.insert(tinyInt.end(),layer0.begin(),layer0.end());
4411   tinyInt.push_back(layer1.size());
4412   tinyInt.insert(tinyInt.end(),layer1.begin(),layer1.end());
4413 }
4414
4415 void MEDFileUMesh::unserialize(std::vector<double>& tinyDouble, std::vector<int>& tinyInt, std::vector<std::string>& tinyStr,
4416                                std::vector< MCAuto<DataArrayInt> >& bigArraysI, MCAuto<DataArrayDouble>& bigArrayD)
4417 {
4418   int sz0(tinyInt[0]);
4419   std::vector<int> layer0(tinyInt.begin()+1,tinyInt.begin()+1+sz0);
4420   int sz1(tinyInt[sz0+1]);
4421   std::vector<int> layer1(tinyInt.begin()+2+sz0,tinyInt.begin()+2+sz0+sz1);
4422   //
4423   std::reverse(layer0.begin(),layer0.end());
4424   std::reverse(layer1.begin(),layer1.end());
4425   std::reverse(tinyDouble.begin(),tinyDouble.end());
4426   std::reverse(tinyStr.begin(),tinyStr.end());
4427   std::reverse(bigArraysI.begin(),bigArraysI.end());
4428   //
4429   setAxisType((MEDCouplingAxisType)layer0.back()); layer0.pop_back();
4430   _order=layer0.back(); layer0.pop_back();
4431   _iteration=layer0.back(); layer0.pop_back();
4432   int spaceDim(layer0.back()); layer0.pop_back();
4433   _time=tinyDouble.back(); tinyDouble.pop_back();
4434   _name=tinyStr.back(); tinyStr.pop_back();
4435   _desc_name=tinyStr.back(); tinyStr.pop_back();
4436   _coords=bigArrayD; _coords->rearrange(spaceDim);
4437   for(int i=0;i<spaceDim;i++)
4438     {
4439       _coords->setInfoOnComponent(i,tinyStr.back());
4440       tinyStr.pop_back();
4441     }
4442   int nbOfFams(layer0.back()); layer0.pop_back();
4443   _families.clear();
4444   for(int i=0;i<nbOfFams;i++)
4445     {
4446       _families[tinyStr.back()]=layer0.back();
4447       tinyStr.pop_back(); layer0.pop_back();
4448     }
4449   int nbGroups(layer0.back()); layer0.pop_back();
4450   _groups.clear();
4451   for(int i=0;i<nbGroups;i++)
4452     {
4453       std::string grpName(tinyStr.back()); tinyStr.pop_back();
4454       int nbOfFamsOnGrp(layer0.back()); layer0.pop_back();
4455       std::vector<std::string> fams(nbOfFamsOnGrp);
4456       for(int j=0;j<nbOfFamsOnGrp;j++)
4457         {
4458           fams[j]=tinyStr.back(); tinyStr.pop_back();
4459         }
4460       _groups[grpName]=fams;
4461     }
4462   _fam_coords=bigArraysI.back(); bigArraysI.pop_back();
4463   _num_coords=bigArraysI.back(); bigArraysI.pop_back();
4464   _part_coords=0;
4465   int isPd(layer0.back()); layer0.pop_back();
4466   if(isPd!=-1)
4467     {
4468       std::vector<int> tmp0(layer0.begin(),layer0.begin()+isPd);
4469       layer0.erase(layer0.begin(),layer0.begin()+isPd);
4470       _part_coords=PartDefinition::Unserialize(tmp0,bigArraysI);
4471     }
4472   if(!layer0.empty())
4473     throw INTERP_KERNEL::Exception("MEDFileUMesh::unserialize : something wrong during unserialization #1 !");
4474   //
4475   int nbLevs(layer1.back()); layer1.pop_back();
4476   std::vector<int> levs(layer1.rbegin(),layer1.rbegin()+nbLevs); layer1.erase(layer1.end()-nbLevs,layer1.end());
4477   _ms.clear();
4478   int maxLev(-(*std::min_element(levs.begin(),levs.end())));
4479   _ms.resize(maxLev+1);
4480   for(int i=0;i<nbLevs;i++)
4481     {
4482       int lev(levs[i]);
4483       int pos(-lev);
4484       _ms[pos]=MEDFileUMeshSplitL1::Unserialize(_name,_coords,layer1,bigArraysI);
4485     }
4486 }
4487
4488 /*!
4489  * Adds a group of nodes to \a this mesh.
4490  *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
4491  *          The ids should be sorted and different each other (MED file norm).
4492  *
4493  *  \warning this method can alter default "FAMILLE_ZERO" family.
4494  *  For users sensitive to this a call to MEDFileMesh::rearrangeFamilies will be necessary after addGroup session.
4495  *
4496  *  \throw If the node coordinates array is not set.
4497  *  \throw If \a ids == \c NULL.
4498  *  \throw If \a ids->getName() == "".
4499  *  \throw If \a ids does not respect the MED file norm.
4500  *  \throw If a group with name \a ids->getName() already exists.
4501  */
4502 void MEDFileUMesh::addNodeGroup(const DataArrayInt *ids)
4503 {
4504   const DataArrayDouble *coords(_coords);
4505   if(!coords)
4506     throw INTERP_KERNEL::Exception("MEDFileUMesh::addNodeGroup : no coords set !");
4507   int nbOfNodes(coords->getNumberOfTuples());
4508   if(!((DataArrayInt *)_fam_coords))
4509     { _fam_coords=DataArrayInt::New(); _fam_coords->alloc(nbOfNodes,1); _fam_coords->fillWithZero(); }
4510   //
4511   addGroupUnderground(true,ids,_fam_coords);
4512 }
4513
4514 /*!
4515  * Adds a group of nodes/cells/faces/edges to \a this mesh.
4516  *
4517  *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
4518  *          The ids should be sorted and different each other (MED file norm).
4519  *
4520  * \warning this method can alter default "FAMILLE_ZERO" family.
4521  * For users sensitive to this a call to MEDFileMesh::rearrangeFamilies will be necessary after addGroup session.
4522  *
4523  *  \throw If the node coordinates array is not set.
4524  *  \throw If \a ids == \c NULL.
4525  *  \throw If \a ids->getName() == "".
4526  *  \throw If \a ids does not respect the MED file norm.
4527  *  \throw If a group with name \a ids->getName() already exists.
4528  */
4529 void MEDFileUMesh::addGroup(int meshDimRelToMaxExt, const DataArrayInt *ids)
4530 {
4531   std::vector<int> levs(getNonEmptyLevelsExt());
4532   if(std::find(levs.begin(),levs.end(),meshDimRelToMaxExt)==levs.end())
4533     { 
4534       std::ostringstream oss; oss << "MEDFileUMesh::addGroup : level " << meshDimRelToMaxExt << " not available ! Should be in ";
4535       std::copy(levs.begin(),levs.end(),std::ostream_iterator<int>(oss," ")); oss << " !"; throw INTERP_KERNEL::Exception(oss.str().c_str());
4536     }
4537   if(meshDimRelToMaxExt==1)
4538     { addNodeGroup(ids); return ; }
4539   MEDFileUMeshSplitL1 *lev(getMeshAtLevSafe(meshDimRelToMaxExt));
4540   DataArrayInt *fam(lev->getOrCreateAndGetFamilyField());
4541   addGroupUnderground(false,ids,fam);
4542 }
4543
4544 /*!
4545  * Changes a name of a family specified by its id.
4546  *  \param [in] id - the id of the family of interest.
4547  *  \param [in] newFamName - the new family name.
4548  *  \throw If no family with the given \a id exists.
4549  */
4550 void MEDFileUMesh::setFamilyNameAttachedOnId(int id, const std::string& newFamName)
4551 {
4552   std::string oldName=getFamilyNameGivenId(id);
4553   _families.erase(oldName);
4554   _families[newFamName]=id;
4555 }
4556
4557 /*!
4558  * Removes a mesh of a given dimension.
4559  *  \param [in] meshDimRelToMax - the relative dimension of interest.
4560  *  \throw If there is no mesh at level \a meshDimRelToMax in \a this mesh.
4561  */
4562 void MEDFileUMesh::removeMeshAtLevel(int meshDimRelToMax)
4563 {
4564   std::vector<int> levSet=getNonEmptyLevels();
4565   std::vector<int>::const_iterator it=std::find(levSet.begin(),levSet.end(),meshDimRelToMax);
4566   if(it==levSet.end())
4567     throw INTERP_KERNEL::Exception("MEDFileUMesh::removeMeshAtLevel : the requested level is not existing !");
4568   int pos=(-meshDimRelToMax);
4569   _ms[pos]=0;
4570 }
4571
4572 /*!
4573  * Sets a new MEDCoupling1GTUMesh at a given level in \a this mesh.
4574  *  \param [in] meshDimRelToMax - a relative level to set the mesh at.
4575  *  \param [in] m - the new mesh to set.
4576  *  \throw If the name or the description of \a this mesh and \a m are not empty and are
4577  *         different. 
4578  *  \throw If the node coordinates array is set \a this in mesh and \a m refers to
4579  *         another node coordinates array.
4580  *  \throw If the mesh dimension of \a m does not correspond to \a meshDimRelToMax or
4581  *         to the existing meshes of other levels of \a this mesh.
4582  */
4583 void MEDFileUMesh::setMeshAtLevel(int meshDimRelToMax, MEDCoupling1GTUMesh *m)
4584 {
4585   MCAuto<MEDFileUMeshSplitL1> elt(new MEDFileUMeshSplitL1(m));
4586   checkAndGiveEntryInSplitL1(meshDimRelToMax,m)=elt;
4587 }
4588
4589 /*!
4590  * Sets a new MEDCouplingUMesh at a given level in \a this mesh.
4591  *  \param [in] meshDimRelToMax - a relative level to set the mesh at.
4592  *  \param [in] m - the new mesh to set.
4593  *  \param [in] newOrOld - if \c true, cells in \a m are sorted by type to be ready for 
4594  *         writing \a this mesh in a MED file.
4595  *  \throw If the name or the description of \a this mesh and \a m are not empty and are
4596  *         different. 
4597  *  \throw If the node coordinates array is set \a this in mesh and \a m refers to
4598  *         another node coordinates array.
4599  *  \throw If the mesh dimension of \a m does not correspond to \a meshDimRelToMax or
4600  *         to the existing meshes of other levels of \a this mesh.
4601  */
4602 void MEDFileUMesh::setMeshAtLevel(int meshDimRelToMax, MEDCouplingUMesh *m, bool newOrOld)
4603 {
4604   MCAuto<MEDFileUMeshSplitL1> elt(new MEDFileUMeshSplitL1(m,newOrOld));
4605   checkAndGiveEntryInSplitL1(meshDimRelToMax,m)=elt;
4606 }
4607
4608 MCAuto<MEDFileUMeshSplitL1>& MEDFileUMesh::checkAndGiveEntryInSplitL1(int meshDimRelToMax, MEDCouplingPointSet *m)
4609 {
4610   dealWithTinyInfo(m);
4611   std::vector<int> levSet=getNonEmptyLevels();
4612   if(std::find(levSet.begin(),levSet.end(),meshDimRelToMax)==levSet.end())
4613     {
4614       if((DataArrayDouble *)_coords==0)
4615         {
4616           DataArrayDouble *c=m->getCoords();
4617           if(c)
4618             c->incrRef();
4619           _coords=c;
4620         }
4621       if(m->getCoords()!=_coords)
4622         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshAtLevel : Invalid Given Mesh ! The coordinates are not the same ! try to use tryToShareSameCoords !");
4623       int sz=(-meshDimRelToMax)+1;
4624       if(sz>=(int)_ms.size())
4625         _ms.resize(sz);
4626       checkMeshDimCoherency(m->getMeshDimension(),meshDimRelToMax);
4627       return _ms[sz-1];
4628     }
4629   else
4630     return _ms[-meshDimRelToMax];
4631 }
4632
4633 /*!
4634  * This method allows to set at once the content of different levels in \a this.
4635  * This method is equivalent to a series of call to MEDFileUMesh::setMeshAtLevel.
4636  *
4637  * \param [in] ms - List of unstructured meshes lying on the same coordinates and having different mesh dimesnion.
4638  * \param [in] renum - the parameter (set to false by default) that tells the beheviour if there is a mesh on \a ms that is not geo type sorted.
4639  *                     If false, an exception ois thrown. If true the mesh is reordered automatically. It is highly recommanded to let this parameter to false.
4640  *
4641  * \throw If \a there is a null pointer in \a ms.
4642  * \sa MEDFileUMesh::setMeshAtLevel
4643  */
4644 void MEDFileUMesh::setMeshes(const std::vector<const MEDCouplingUMesh *>& ms, bool renum)
4645 {
4646   if(ms.empty())
4647     return ;
4648   const MEDCouplingUMesh *mRef=ms[0];
4649   if(!mRef)
4650     throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : null instance in the first element of input meshes !");
4651   std::string name(mRef->getName());
4652   const DataArrayDouble *coo(mRef->getCoords());
4653   std::set<int> s;
4654   int zeDim=-1;
4655   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
4656     {
4657       const MEDCouplingUMesh *cur(*it);
4658       if(!cur)
4659         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : null instance in input vector of meshes !");
4660       if(coo!=cur->getCoords())
4661         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : The input meshes do not share the same coordinates !");
4662       int mdim=cur->getMeshDimension();
4663       zeDim=std::max(zeDim,mdim);
4664       if(s.find(mdim)!=s.end())
4665         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : The input meshes must share the same coordinates pointer, and should have different mesh dimension each other !");
4666     }
4667   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
4668     {
4669       int mdim=(*it)->getMeshDimension();
4670       setName((*it)->getName());
4671       setMeshAtLevel(mdim-zeDim,const_cast<MEDCouplingUMesh *>(*it),renum);
4672     }
4673   setName(name);
4674 }
4675
4676 /*!
4677  * Creates one MEDCouplingUMesh at a given level in \a this mesh from a sequence of
4678  * meshes each representing a group, and creates corresponding groups in \a this mesh.
4679  * The given meshes must share the same node coordinates array.
4680  *  \param [in] meshDimRelToMax - the relative dimension to create the mesh and groups at.
4681  *  \param [in] ms - the sequence of meshes. Each mesh in \a ms represents a group to
4682  *          create in \a this mesh.
4683  *  \throw If \a ms is empty.
4684  *  \throw If dimension of meshes in \a ms does not correspond to \a meshDimRelToMax or
4685  *         to the existing meshes of other levels of \a this mesh.
4686  *  \throw If the meshes in \a ms do not share the same node coordinates array.
4687  *  \throw If the node coordinates array of \a this mesh (if any) is not the same as that
4688  *         of the given meshes.
4689  *  \throw If \a ms[ i ] is not well defined (MEDCouplingUMesh::checkConsistencyLight()).
4690  *  \throw If names of some meshes in \a ms are equal.
4691  *  \throw If \a ms includes a mesh with an empty name.
4692  */
4693 void MEDFileUMesh::setGroupsFromScratch(int meshDimRelToMax, const std::vector<const MEDCouplingUMesh *>& ms, bool renum)
4694 {
4695   if(ms.empty())
4696     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsFromScratch : expecting a non empty vector !");
4697   int sz=(-meshDimRelToMax)+1;
4698   if(sz>=(int)_ms.size())
4699     _ms.resize(sz);
4700   checkMeshDimCoherency(ms[0]->getMeshDimension(),meshDimRelToMax);
4701   DataArrayDouble *coo=checkMultiMesh(ms);
4702   if((DataArrayDouble *)_coords==0)
4703     {
4704       coo->incrRef();
4705       _coords=coo;
4706     }
4707   else
4708     if((DataArrayDouble *)_coords!=coo)
4709       throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsFromScratch : coordinates mismatches !");
4710   std::vector<DataArrayInt *> corr;
4711   MCAuto<MEDCouplingUMesh> m=MEDCouplingUMesh::FuseUMeshesOnSameCoords(ms,_zipconn_pol,corr);
4712   std::vector< MCAuto<DataArrayInt> > corr3(corr.begin(),corr.end());
4713   setMeshAtLevel(meshDimRelToMax,m,renum);
4714   std::vector<const DataArrayInt *> corr2(corr.begin(),corr.end());
4715   setGroupsAtLevel(meshDimRelToMax,corr2,true);
4716 }
4717
4718 /*!
4719  * Creates groups at a given level in \a this mesh from a sequence of
4720  * meshes each representing a group.
4721  * The given meshes must share the same node coordinates array.
4722  *  \param [in] meshDimRelToMax - the relative dimension to create the groups at.
4723  *  \param [in] ms - the sequence of meshes. Each mesh in \a ms represents a group to
4724  *         create in \a this mesh.
4725  *  \param [in] renum - if \c true, then the optional numbers of entities are taken into
4726  *         account. 
4727  *  \throw If \a ms is empty.
4728  *  \throw If dimension of meshes in \a ms does not correspond to \a meshDimRelToMax or
4729  *         to the existing meshes of other levels of \a this mesh.
4730  *  \throw If the meshes in \a ms do not share the same node coordinates array.
4731  *  \throw If the node coordinates array of \a this mesh (if any) is not the same as that
4732  *         of the given meshes.
4733  *  \throw If \a ms[ i ] is not well defined (MEDCouplingUMesh::checkConsistencyLight()).
4734  *  \throw If names of some meshes in \a ms are equal.
4735  *  \throw If \a ms includes a mesh with an empty name.
4736  */
4737 void MEDFileUMesh::setGroupsOnSetMesh(int meshDimRelToMax, const std::vector<const MEDCouplingUMesh *>& ms, bool renum)
4738 {
4739   if(ms.empty())
4740     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsOnSetMesh : expecting a non empty vector !");
4741   int sz=(-meshDimRelToMax)+1;
4742   if(sz>=(int)_ms.size())
4743     _ms.resize(sz);
4744   checkMeshDimCoherency(ms[0]->getMeshDimension(),meshDimRelToMax);
4745   DataArrayDouble *coo=checkMultiMesh(ms);
4746   if((DataArrayDouble *)_coords==0)
4747     {
4748       coo->incrRef();
4749       _coords=coo;
4750     }
4751   else
4752     if((DataArrayDouble *)_coords!=coo)
4753       throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsOnSetMesh : coordinates mismatches !");
4754   MEDCouplingUMesh *m=getMeshAtLevel(meshDimRelToMax,renum);
4755   std::vector< MCAuto<DataArrayInt> > corr(ms.size());
4756   int i=0;
4757   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++,i++)
4758     {
4759       DataArrayInt *arr=0;
4760       bool test=m->areCellsIncludedIn(*it,_zipconn_pol,arr);
4761       corr[i]=arr;
4762       if(!test)
4763         {
4764           std::ostringstream oss; oss << "MEDFileUMesh::setGroupsOnSetMesh : mesh #" << i << " is not part of whole mesh !";
4765           throw INTERP_KERNEL::Exception(oss.str().c_str());
4766         }
4767     }
4768   std::vector<const DataArrayInt *> corr2(corr.begin(),corr.end());
4769   setGroupsAtLevel(meshDimRelToMax,corr2,renum);
4770 }
4771
4772 DataArrayDouble *MEDFileUMesh::checkMultiMesh(const std::vector<const MEDCouplingUMesh *>& ms) const
4773 {
4774   const DataArrayDouble *ret=ms[0]->getCoords();
4775   int mdim=ms[0]->getMeshDimension();
4776   for(unsigned int i=1;i<ms.size();i++)
4777     {
4778       ms[i]->checkConsistencyLight();
4779       if(ms[i]->getCoords()!=ret)
4780         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMultiMesh : meshes must share the same coords !");
4781       if(ms[i]->getMeshDimension()!=mdim)
4782         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMultiMesh : meshes have not same mesh dimension !");
4783     }
4784   return const_cast<DataArrayDouble *>(ret);
4785 }
4786
4787 /*!
4788  * Sets the family field of a given relative dimension.
4789  *  \param [in] meshDimRelToMaxExt - the relative dimension of entities for which
4790  *          the family field is set.
4791  *  \param [in] famArr - the array of the family field.
4792  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4793  *  \throw If \a famArr has an invalid size.
4794  */
4795 void MEDFileUMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr)
4796 {
4797   if(meshDimRelToMaxExt==1)
4798     {
4799       if(!famArr)
4800         {
4801           _fam_coords=0;
4802           return ;
4803         }
4804       DataArrayDouble *coo(_coords);
4805       if(!coo)
4806         throw INTERP_KERNEL::Exception("MEDFileUMesh::setFamilyFieldArr : the coordinates have not been set !");
4807       famArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),1,"MEDFileUMesh::setFamilyFieldArr : Problem in size of node family arr ! ");
4808       famArr->incrRef();
4809       _fam_coords=famArr;
4810       return ;
4811     }
4812   if(meshDimRelToMaxExt>1)
4813     throw INTERP_KERNEL::Exception("MEDFileUMesh::setFamilyFieldArr : Dimension request is invalid (>1) !");
4814   int traducedRk=-meshDimRelToMaxExt;
4815   if(traducedRk>=(int)_ms.size())
4816     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
4817   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
4818     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
4819   return _ms[traducedRk]->setFamilyArr(famArr);
4820 }
4821
4822 /*!
4823  * Sets the optional numbers of mesh entities of a given dimension.
4824  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4825  *  \param [in] renumArr - the array of the numbers.
4826  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4827  *  \throw If \a renumArr has an invalid size.
4828  */
4829 void MEDFileUMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr)
4830 {
4831   if(meshDimRelToMaxExt==1)
4832     {
4833       if(!renumArr)
4834         {
4835           _num_coords=0;
4836           _rev_num_coords=0;
4837           return ;
4838         }
4839       DataArrayDouble *coo(_coords);
4840       if(!coo)
4841         throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumFieldArr : the coordinates have not been set !");
4842       renumArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),1,"MEDFileUMesh::setRenumArr : Problem in size of node numbering arr ! ");
4843       renumArr->incrRef();
4844       _num_coords=renumArr;
4845       computeRevNum();
4846       return ;
4847     }
4848   if(meshDimRelToMaxExt>1)
4849     throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumArr : Dimension request is invalid (>1) !");
4850   int traducedRk=-meshDimRelToMaxExt;
4851   if(traducedRk>=(int)_ms.size())
4852     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
4853   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
4854     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
4855   return _ms[traducedRk]->setRenumArr(renumArr);
4856 }
4857
4858 /*!
4859  * Sets the optional names of mesh entities of a given dimension.
4860  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4861  *  \param [in] nameArr - the array of the names.
4862  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4863  *  \throw If \a nameArr has an invalid size.
4864  */
4865 void MEDFileUMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr)
4866 {
4867   if(meshDimRelToMaxExt==1)
4868     {
4869       if(!nameArr)
4870         {
4871           _name_coords=0;
4872           return ;
4873         }
4874       DataArrayDouble *coo(_coords);
4875       if(!coo)
4876         throw INTERP_KERNEL::Exception("MEDFileUMesh::setNameFieldAtLevel : the coordinates have not been set !");
4877       nameArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),MED_SNAME_SIZE,"MEDFileUMesh::setNameFieldAtLevel : Problem in size of node numbering arr ! ");
4878       nameArr->incrRef();
4879       _name_coords=nameArr;
4880       return ;
4881     }
4882   if(meshDimRelToMaxExt>1)
4883     throw INTERP_KERNEL::Exception("MEDFileUMesh::setNameFieldAtLevel : Dimension request is invalid (>1) !");
4884   int traducedRk=-meshDimRelToMaxExt;
4885   if(traducedRk>=(int)_ms.size())
4886     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
4887   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
4888     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
4889   return _ms[traducedRk]->setNameArr(nameArr);
4890 }
4891
4892 void MEDFileUMesh::synchronizeTinyInfoOnLeaves() const
4893 {
4894   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
4895     if((const MEDFileUMeshSplitL1 *)(*it))
4896       (*it)->synchronizeTinyInfo(*this);
4897 }
4898
4899 /*!
4900  * This method is called by MEDFileMesh::changeFamilyId. It performs only one part of the family id modification.
4901  */
4902 void MEDFileUMesh::changeFamilyIdArr(int oldId, int newId)
4903 {
4904   DataArrayInt *arr=_fam_coords;
4905   if(arr)
4906     arr->changeValue(oldId,newId);
4907   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
4908     {
4909       MEDFileUMeshSplitL1 *sp=(*it);
4910       if(sp)
4911         {
4912           sp->changeFamilyIdArr(oldId,newId);
4913         }
4914     }
4915 }
4916
4917 std::list< MCAuto<DataArrayInt> > MEDFileUMesh::getAllNonNullFamilyIds() const
4918 {
4919   std::list< MCAuto<DataArrayInt> > ret;
4920   const DataArrayInt *da(_fam_coords);
4921   if(da)
4922     { da->incrRef(); ret.push_back(MCAuto<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
4923   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
4924     {
4925       const MEDFileUMeshSplitL1 *elt(*it);
4926       if(elt)
4927         {
4928           da=elt->getFamilyField();
4929           if(da)
4930             { da->incrRef(); ret.push_back(MCAuto<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
4931         }
4932     }
4933   return ret;
4934 }
4935
4936 void MEDFileUMesh::computeRevNum() const
4937 {
4938   if((const DataArrayInt *)_num_coords)
4939     {
4940       int pos;
4941       int maxValue=_num_coords->getMaxValue(pos);
4942       _rev_num_coords=_num_coords->invertArrayN2O2O2N(maxValue+1);
4943     }
4944 }
4945
4946 std::size_t MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren() const
4947 {
4948   return MEDFileMesh::getHeapMemorySizeWithoutChildren();
4949 }
4950
4951 std::vector<const BigMemoryObject *> MEDFileStructuredMesh::getDirectChildrenWithNull() const
4952 {
4953   std::vector<const BigMemoryObject *> ret(MEDFileMesh::getDirectChildrenWithNull());
4954   ret.push_back((const DataArrayInt *)_fam_nodes);
4955   ret.push_back((const DataArrayInt *)_num_nodes);
4956   ret.push_back((const DataArrayAsciiChar *)_names_nodes);
4957   ret.push_back((const DataArrayInt *)_fam_cells);
4958   ret.push_back((const DataArrayInt *)_num_cells);
4959   ret.push_back((const DataArrayAsciiChar *)_names_cells);
4960   ret.push_back((const DataArrayInt *)_fam_faces);
4961   ret.push_back((const DataArrayInt *)_num_faces);
4962   ret.push_back((const DataArrayInt *)_rev_num_nodes);
4963   ret.push_back((const DataArrayAsciiChar *)_names_faces);
4964   ret.push_back((const DataArrayInt *)_rev_num_cells);
4965   ret.push_back((const MEDCoupling1SGTUMesh*)_faces_if_necessary);
4966   return ret;
4967 }
4968
4969 int MEDFileStructuredMesh::getMaxAbsFamilyIdInArrays() const
4970 {
4971   int ret=-std::numeric_limits<int>::max(),tmp=-1;
4972   if((const DataArrayInt *)_fam_nodes)
4973     {
4974       int val=_fam_nodes->getMaxValue(tmp);
4975       ret=std::max(ret,std::abs(val));
4976     }
4977   if((const DataArrayInt *)_fam_cells)
4978     {
4979       int val=_fam_cells->getMaxValue(tmp);
4980       ret=std::max(ret,std::abs(val));
4981     }
4982   if((const DataArrayInt *)_fam_faces)
4983     {
4984       int val=_fam_faces->getMaxValue(tmp);
4985       ret=std::max(ret,std::abs(val));
4986     }
4987   return ret;
4988 }
4989
4990 int MEDFileStructuredMesh::getMaxFamilyIdInArrays() const
4991 {
4992   int ret=-std::numeric_limits<int>::max(),tmp=-1;
4993   if((const DataArrayInt *)_fam_nodes)
4994     {
4995       int val=_fam_nodes->getMaxValue(tmp);
4996       ret=std::max(ret,val);
4997     }
4998   if((const DataArrayInt *)_fam_cells)
4999     {
5000       int val=_fam_cells->getMaxValue(tmp);
5001       ret=std::max(ret,val);
5002     }
5003   if((const DataArrayInt *)_fam_faces)
5004     {
5005       int val=_fam_faces->getMaxValue(tmp);
5006       ret=std::max(ret,val);
5007     }
5008   return ret;
5009 }
5010
5011 int MEDFileStructuredMesh::getMinFamilyIdInArrays() const
5012 {
5013   int ret=std::numeric_limits<int>::max(),tmp=-1;
5014   if((const DataArrayInt *)_fam_nodes)
5015     {
5016       int val=_fam_nodes->getMinValue(tmp);
5017       ret=std::min(ret,val);
5018     }
5019   if((const DataArrayInt *)_fam_cells)
5020     {
5021       int val=_fam_cells->getMinValue(tmp);
5022       ret=std::min(ret,val);
5023     }
5024   if((const DataArrayInt *)_fam_faces)
5025     {
5026       int val=_fam_faces->getMinValue(tmp);
5027       ret=std::min(ret,val);
5028     }
5029   return ret;
5030 }
5031
5032 bool MEDFileStructuredMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
5033 {
5034   if(!MEDFileMesh::isEqual(other,eps,what))
5035     return false;
5036   const MEDFileStructuredMesh *otherC=dynamic_cast<const  MEDFileStructuredMesh *>(other);
5037   if(!otherC)
5038     {
5039       what="Mesh types differ ! This is structured and other is NOT !";
5040       return false;
5041     }
5042   const DataArrayInt *famc1=_fam_nodes;
5043   const DataArrayInt *famc2=otherC->_fam_nodes;
5044   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
5045     {
5046       what="Mismatch of families arr on nodes ! One is defined and not other !";
5047       return false;
5048     }
5049   if(famc1)
5050     {
5051       bool ret=famc1->isEqual(*famc2);
5052       if(!ret)
5053         {
5054           what="Families arr on nodes differ !";
5055           return false;
5056         }
5057     }
5058   famc1=_fam_cells;
5059   famc2=otherC->_fam_cells;
5060   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
5061     {
5062       what="Mismatch of families arr on cells ! One is defined and not other !";
5063       return false;
5064     }
5065   if(famc1)
5066     {
5067       bool ret=famc1->isEqual(*famc2);
5068       if(!ret)
5069         {
5070           what="Families arr on cells differ !";
5071           return false;
5072         }
5073     }
5074   famc1=_fam_faces;
5075   famc2=otherC->_fam_faces;
5076   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
5077     {
5078       what="Mismatch of families arr on faces ! One is defined and not other !";
5079       return false;
5080     }
5081   if(famc1)
5082     {
5083       bool ret=famc1->isEqual(*famc2);
5084       if(!ret)
5085         {
5086           what="Families arr on faces differ !";
5087           return false;
5088         }
5089     }
5090   famc1=_num_nodes;
5091   famc2=otherC->_num_nodes;
5092   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
5093     {
5094       what="Mismatch of numbering arr on nodes ! One is defined and not other !";
5095       return false;
5096     }
5097   if(famc1)
5098     {
5099       bool ret=famc1->isEqual(*famc2);
5100       if(!ret)
5101         {
5102           what="Numbering arr on nodes differ !";
5103           return false;
5104         }
5105     }
5106   famc1=_num_cells;
5107   famc2=otherC->_num_cells;
5108   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
5109     {
5110       what="Mismatch of numbering arr on cells ! One is defined and not other !";
5111       return false;
5112     }
5113   if(famc1)
5114     {
5115       bool ret=famc1->isEqual(*famc2);
5116       if(!ret)
5117         {
5118           what="Numbering arr on cells differ !";
5119           return false;
5120         }
5121     }
5122   famc1=_num_faces;
5123   famc2=otherC->_num_faces;
5124   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
5125     {
5126       what="Mismatch of numbering arr on faces ! One is defined and not other !";
5127       return false;
5128     }
5129   if(famc1)
5130     {
5131       bool ret=famc1->isEqual(*famc2);
5132       if(!ret)
5133         {
5134           what="Numbering arr on faces differ !";
5135           return false;
5136         }
5137     }
5138   const DataArrayAsciiChar *d1=_names_cells;
5139   const DataArrayAsciiChar *d2=otherC->_names_cells;
5140   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
5141     {
5142       what="Mismatch of naming arr on cells ! One is defined and not other !";
5143       return false;
5144     }
5145   if(d1)
5146     {
5147       bool ret=d1->isEqual(*d2);
5148       if(!ret)
5149         {
5150           what="Naming arr on cells differ !";
5151           return false;
5152         }
5153     }
5154   d1=_names_faces;
5155   d2=otherC->_names_faces;
5156   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
5157     {
5158       what="Mismatch of naming arr on faces ! One is defined and not other !";
5159       return false;
5160     }
5161   if(d1)
5162     {
5163       bool ret=d1->isEqual(*d2);
5164       if(!ret)
5165         {
5166           what="Naming arr on faces differ !";
5167           return false;
5168         }
5169     }
5170   d1=_names_nodes;
5171   d2=otherC->_names_nodes;
5172   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
5173     {
5174       what="Mismatch of naming arr on nodes ! One is defined and not other !";
5175       return false;
5176     }
5177   if(d1)
5178     {
5179       bool ret=d1->isEqual(*d2);
5180       if(!ret)
5181         {
5182           what="Naming arr on nodes differ !";
5183           return false;
5184         }
5185     }
5186   return true;
5187 }
5188
5189 void MEDFileStructuredMesh::clearNonDiscrAttributes() const
5190 {
5191   MEDFileMesh::clearNonDiscrAttributes();
5192   const DataArrayInt *tmp=_fam_nodes;
5193   if(tmp)
5194     (const_cast<DataArrayInt *>(tmp))->setName("");
5195   tmp=_num_nodes;
5196   if(tmp)
5197     (const_cast<DataArrayInt *>(tmp))->setName("");
5198   tmp=_fam_cells;
5199   if(tmp)
5200     (const_cast<DataArrayInt *>(tmp))->setName("");
5201   tmp=_num_cells;
5202   if(tmp)
5203     (const_cast<DataArrayInt *>(tmp))->setName("");
5204   tmp=_fam_faces;
5205   if(tmp)
5206     (const_cast<DataArrayInt *>(tmp))->setName("");
5207   tmp=_num_faces;
5208   if(tmp)
5209     (const_cast<DataArrayInt *>(tmp))->setName("");
5210 }
5211
5212 /*!
5213  * Returns ids of mesh entities contained in given families of a given dimension.
5214  *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
5215  *          are required.
5216  *  \param [in] fams - the names of the families of interest.
5217  *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
5218  *          returned instead of ids.
5219  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
5220  *          numbers, if available and required, of mesh entities of the families. The caller
5221  *          is to delete this array using decrRef() as it is no more needed. 
5222  *  \throw If the family field is missing for \a meshDimRelToMaxExt.
5223  */
5224 DataArrayInt *MEDFileStructuredMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const
5225 {
5226   std::vector<int> famIds(getFamiliesIds(fams));
5227   switch(meshDimRelToMaxExt)
5228   {
5229     case 1:
5230       {
5231         if((const DataArrayInt *)_fam_nodes)
5232           {
5233             MCAuto<DataArrayInt> da;
5234             if(!famIds.empty())
5235               da=_fam_nodes->findIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
5236             else
5237               da=_fam_nodes->findIdsEqualList(0,0);
5238             if(renum)
5239               return MEDFileUMeshSplitL1::Renumber(_num_nodes,da);
5240             else
5241               return da.retn();
5242           }
5243         else
5244           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on nodes !");
5245         break;
5246       }
5247     case 0:
5248       {
5249         if((const DataArrayInt *)_fam_cells)
5250           {
5251             MCAuto<DataArrayInt> da;
5252             if(!famIds.empty())
5253               da=_fam_cells->findIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
5254             else
5255               da=_fam_cells->findIdsEqualList(0,0);
5256             if(renum)
5257               return MEDFileUMeshSplitL1::Renumber(_num_cells,da);
5258             else
5259               return da.retn();
5260           }
5261         else
5262           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on cells !");
5263         break;
5264       }
5265     case -1:
5266       {
5267         if((const DataArrayInt *)_fam_faces)
5268           {
5269             MCAuto<DataArrayInt> da;
5270             if(!famIds.empty())
5271               da=_fam_faces->findIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
5272             else
5273               da=_fam_faces->findIdsEqualList(0,0);
5274             if(renum)
5275               return MEDFileUMeshSplitL1::Renumber(_num_faces,da);
5276             else
5277               return da.retn();
5278           }
5279         else
5280           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on faces !");
5281         break;
5282       }
5283     default:
5284       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : input meshDimRelative must be in [0,1,-1] !");
5285   }
5286   throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : unmanaged case !");
5287 }
5288
5289 /*!
5290  * Sets the family field of a given relative dimension.
5291  *  \param [in] meshDimRelToMaxExt - the relative dimension of entities for which
5292  *          the family field is set.
5293  *  \param [in] famArr - the array of the family field.
5294  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5295  *  \throw If \a famArr has an invalid size.
5296  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1 and \a meshDimRelToMaxExt != -1.
5297  */
5298 void MEDFileStructuredMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr)
5299 {
5300   const MEDCouplingStructuredMesh *mesh(getStructuredMesh());
5301   if(!mesh)
5302     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setFamilyFieldArr : no structured mesh specified ! Impossible to set family array !");
5303   switch(meshDimRelToMaxExt)
5304   {
5305     case 0:
5306       {
5307         int nbCells(mesh->getNumberOfCells());
5308         if(famArr)
5309           famArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of cells of mesh !");
5310         _fam_cells=famArr;
5311         break;
5312       }
5313     case 1:
5314       {
5315         int nbNodes(mesh->getNumberOfNodes());
5316         if(famArr)
5317           famArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !");
5318         _fam_nodes=famArr;
5319         break;
5320       }
5321     case -1:
5322       {
5323         int nbCells(mesh->getNumberOfCellsOfSubLevelMesh());
5324         if(famArr)
5325           famArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of faces of mesh !");
5326         _fam_faces=famArr;
5327         break;
5328       }
5329     default:
5330       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setFamilyFieldArr : Only available for levels 0 or 1 or -1 !");
5331   }
5332   if(famArr)
5333     famArr->incrRef();
5334 }
5335
5336 /*!
5337  * Sets the optional numbers of mesh entities of a given dimension.
5338  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5339  *  \param [in] renumArr - the array of the numbers.
5340  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5341  *  \throw If \a renumArr has an invalid size.
5342  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
5343  */
5344 void MEDFileStructuredMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr)
5345 {
5346   const MEDCouplingStructuredMesh *mesh=getStructuredMesh();
5347   if(!mesh)
5348     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : no structured mesh specified ! Impossible to set number array !");
5349   switch(meshDimRelToMaxExt)
5350   {
5351     case 0:
5352       {
5353         int nbCells=mesh->getNumberOfCells();
5354         renumArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Renum arr ! Mismatch with number of cells of mesh !");
5355         _num_cells=renumArr;
5356         break;
5357       }
5358     case 1:
5359       {
5360         int nbNodes=mesh->getNumberOfNodes();
5361         renumArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !");
5362         _num_nodes=renumArr;
5363         break;
5364       }
5365     case -1:
5366       {
5367         int nbCells=mesh->getNumberOfCellsOfSubLevelMesh();
5368         renumArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Renum arr ! Mismatch with number of faces of mesh !");
5369         _num_faces=renumArr;
5370         break;
5371       }
5372     default:
5373       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : Only available for levels 0 or 1 or -1 !");
5374   }
5375   if(renumArr)
5376     renumArr->incrRef();
5377 }
5378
5379 /*!
5380  * Sets the optional names of mesh entities of a given dimension.
5381  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5382  *  \param [in] nameArr - the array of the names.
5383  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5384  *  \throw If \a nameArr has an invalid size.
5385  */
5386 void MEDFileStructuredMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr)
5387 {
5388   const MEDCouplingStructuredMesh *mesh(getStructuredMesh());
5389   if(!mesh)
5390     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : no structured mesh specified ! Impossible to set names array !");
5391   switch(meshDimRelToMaxExt)
5392   {
5393     case 0:
5394       {
5395         int nbCells=mesh->getNumberOfCells();
5396         nameArr->checkNbOfTuplesAndComp(nbCells,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of cells of mesh !");
5397         _names_cells=nameArr;
5398         break;
5399       }
5400     case 1:
5401       {
5402         int nbNodes=mesh->getNumberOfNodes();
5403         nameArr->checkNbOfTuplesAndComp(nbNodes,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of nodes of mesh !");
5404         _names_nodes=nameArr;
5405         break;
5406       }
5407     case -1:
5408       {
5409         int nbCells=mesh->getNumberOfCellsOfSubLevelMesh();
5410         nameArr->checkNbOfTuplesAndComp(nbCells,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of faces of mesh !");
5411         _names_cells=nameArr;
5412       }
5413     default:
5414       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : Only available for levels 0 or 1 or -1 !");
5415   }
5416   if(nameArr)
5417     nameArr->incrRef();
5418 }
5419
5420 /*!
5421  * Adds a group of nodes to \a this mesh.
5422  *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
5423  *          The ids should be sorted and different each other (MED file norm).
5424  *
5425  *  \warning this method can alter default "FAMILLE_ZERO" family.
5426  *  For users sensitive to this a call to MEDFileMesh::rearrangeFamilies will be necessary after addGroup session.
5427  *
5428  *  \throw If the node coordinates array is not set.
5429  *  \throw If \a ids == \c NULL.
5430  *  \throw If \a ids->getName() == "".
5431  *  \throw If \a ids does not respect the MED file norm.
5432  *  \throw If a group with name \a ids->getName() already exists.
5433  */
5434 void MEDFileStructuredMesh::addNodeGroup(const DataArrayInt *ids)
5435 {
5436   addGroup(1,ids);
5437 }
5438
5439 /*!
5440  * Adds a group of nodes/cells/faces/edges to \a this mesh.
5441  *
5442  *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
5443  *          The ids should be sorted and different each other (MED file norm).
5444  *
5445  * \warning this method can alter default "FAMILLE_ZERO" family.
5446  * For users sensitive to this a call to MEDFileMesh::rearrangeFamilies will be necessary after addGroup session.
5447  *
5448  *  \throw If the node coordinates array is not set.
5449  *  \throw If \a ids == \c NULL.
5450  *  \throw If \a ids->getName() == "".
5451  *  \throw If \a ids does not respect the MED file norm.
5452  *  \throw If a group with name \a ids->getName() already exists.
5453  */
5454 void MEDFileStructuredMesh::addGroup(int meshDimRelToMaxExt, const DataArrayInt *ids)
5455 {
5456   DataArrayInt *fam(getOrCreateAndGetFamilyFieldAtLevel(meshDimRelToMaxExt));
5457   addGroupUnderground(false,ids,fam);
5458   return ;
5459 }
5460
5461 /*!
5462  * Returns the family field for mesh entities of a given dimension.
5463  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5464  *  \return const DataArrayInt * - the family field. It is an array of ids of families
5465  *          each mesh entity belongs to. It can be \c NULL.
5466  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
5467  */
5468 const DataArrayInt *MEDFileStructuredMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) const
5469 {
5470   switch(meshDimRelToMaxExt)
5471   {
5472     case 0:
5473       return _fam_cells;
5474     case 1:
5475       return _fam_nodes;
5476     case -1:
5477       return _fam_faces;
5478     default:
5479       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamilyFieldAtLevel : Only available for levels 0 or 1 or -1 !");
5480   }
5481 }
5482
5483 /*!
5484  * Returns the family field for mesh entities of a given dimension.
5485  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5486  *  \return const DataArrayInt * - the family field. It is an array of ids of families
5487  *          each mesh entity belongs to. It can be \c NULL.
5488  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
5489  */
5490 DataArrayInt *MEDFileStructuredMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt)
5491 {
5492   switch(meshDimRelToMaxExt)
5493   {
5494     case 0:
5495       return _fam_cells;
5496     case 1:
5497       return _fam_nodes;
5498     case -1:
5499       return _fam_faces;
5500     default:
5501       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamilyFieldAtLevel : Only available for levels 0 or 1 or -1 !");
5502   }
5503 }
5504
5505 /*!
5506  * Returns the optional numbers of mesh entities of a given dimension.
5507  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5508  *  \return const DataArrayInt * - the array of the entity numbers.
5509  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5510  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
5511  */
5512 const DataArrayInt *MEDFileStructuredMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) const
5513 {
5514   switch(meshDimRelToMaxExt)
5515   {
5516     case 0:
5517       return _num_cells;
5518     case 1:
5519       return _num_nodes;
5520     case -1:
5521       return _num_faces;
5522     default:
5523       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberFieldAtLevel : Only available for levels 0 or 1 or -1 !");
5524   }
5525 }
5526
5527 /*!
5528  * Returns the optional numbers of mesh entities of a given dimension transformed using
5529  * DataArrayInt::invertArrayN2O2O2N().
5530  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5531  *  \return const DataArrayInt * - the array of the entity numbers transformed using
5532  *          DataArrayInt::invertArrayN2O2O2N().
5533  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
5534  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5535  */
5536 const DataArrayInt *MEDFileStructuredMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxExt) const
5537 {
5538   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
5539     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getRevNumberFieldAtLevel : Only available for levels 0 or 1 !");
5540   if(meshDimRelToMaxExt==0)
5541     {
5542       if((const DataArrayInt *)_num_cells)
5543         {
5544           int pos;
5545           int maxValue=_num_cells->getMaxValue(pos);
5546           _rev_num_cells=_num_cells->invertArrayN2O2O2N(maxValue+1);
5547           return _rev_num_cells;
5548         }
5549       else
5550         throw INTERP_KERNEL::Exception("MEDFileCMesh::getRevNumberFieldAtLevel : no cell renumbering for a request on reverse numbering !");
5551     }
5552   else
5553     {
5554       if((const DataArrayInt *)_num_nodes)
5555         {
5556           int pos;
5557           int maxValue=_num_nodes->getMaxValue(pos);
5558           _rev_num_nodes=_num_nodes->invertArrayN2O2O2N(maxValue+1);
5559           return _rev_num_nodes;
5560         }
5561       else
5562         throw INTERP_KERNEL::Exception("MEDFileCMesh::getRevNumberFieldAtLevel : no node renumbering for a request on reverse numbering !");
5563     }
5564 }
5565
5566 const DataArrayAsciiChar *MEDFileStructuredMesh::getNameFieldAtLevel(int meshDimRelToMaxExt) const
5567 {
5568   switch(meshDimRelToMaxExt)
5569   {
5570     case 0:
5571       return _names_cells;
5572     case 1:
5573       return _names_nodes;
5574     case -1:
5575       return _names_faces;
5576     default:
5577       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNameFieldAtLevel : Only available for levels 0 or 1 or -1 !");
5578   }
5579 }
5580
5581 /*!
5582  * Returns relative dimensions of mesh entities (excluding nodes) present in \a this mesh.
5583  *  \return std::vector<int> - a sequence of the relative dimensions: [0].
5584  */
5585 std::vector<int> MEDFileStructuredMesh::getNonEmptyLevels() const
5586 {
5587   std::vector<int> ret(1);
5588   return ret;
5589 }
5590
5591 /*!
5592  * Returns relative dimensions of mesh entities (including nodes) present in \a this mesh.
5593  *  \return std::vector<int> - a sequence of the relative dimensions: [1,0].
5594  */
5595 std::vector<int> MEDFileStructuredMesh::getNonEmptyLevelsExt() const
5596 {
5597   std::vector<int> ret(2);
5598   ret[0]=1;
5599   return ret;
5600 }
5601
5602 /*!
5603  * Returns the set of extensive levels (nodes included) where not NULL family arr are defined.
5604  */
5605 std::vector<int> MEDFileStructuredMesh::getFamArrNonEmptyLevelsExt() const
5606 {
5607   std::vector<int> ret;
5608   const DataArrayInt *famNodes(_fam_nodes),*famCells(_fam_cells),*famFaces(_fam_faces);
5609   if(famNodes)
5610     ret.push_back(1);
5611   if(famCells)
5612     ret.push_back(0);
5613   if(famFaces)
5614     ret.push_back(-1);
5615   return ret;
5616 }
5617
5618 /*!
5619  * Returns the set of extensive levels (nodes included) where not NULL numbering arr are defined.
5620  */
5621 std::vector<int> MEDFileStructuredMesh::getNumArrNonEmptyLevelsExt() const
5622 {
5623   std::vector<int> ret;
5624   const DataArrayInt *numNodes(_num_nodes),*numCells(_num_cells),*numFaces(_num_faces);
5625   if(numNodes)
5626     ret.push_back(1);
5627   if(numCells)
5628     ret.push_back(0);
5629   if(numFaces)
5630     ret.push_back(-1);
5631   return ret;
5632 }
5633
5634 /*!
5635  * Returns the set of extensive levels (nodes included) where not NULL naming arr are defined.
5636  */
5637 std::vector<int> MEDFileStructuredMesh::getNameArrNonEmptyLevelsExt() const
5638 {
5639   std::vector<int> ret;
5640   const DataArrayAsciiChar *namesNodes(_names_nodes),*namesCells(_names_cells),*namesFaces(_names_faces);
5641   if(namesNodes)
5642     ret.push_back(1);
5643   if(namesCells)
5644     ret.push_back(0);
5645   if(namesFaces)
5646     ret.push_back(-1);
5647   return ret;
5648 }
5649
5650 /*!
5651  * no implementation here, it is not a bug, but intresically no polyhedra in \a this.
5652  */
5653 bool MEDFileStructuredMesh::unPolyze(std::vector<int>& oldCode, std::vector<int>& newCode, DataArrayInt *& o2nRenumCell)
5654 {
5655   oldCode.clear(); newCode.clear(); o2nRenumCell=0;
5656   return false;
5657 }
5658
5659 void MEDFileStructuredMesh::changeFamilyIdArr(int oldId, int newId)
5660 {
5661   DataArrayInt *arr=_fam_nodes;
5662   if(arr)
5663     arr->changeValue(oldId,newId);
5664   arr=_fam_cells;
5665   if(arr)
5666     arr->changeValue(oldId,newId);
5667   arr=_fam_faces;
5668   if(arr)
5669     arr->changeValue(oldId,newId);
5670 }
5671
5672 std::list< MCAuto<DataArrayInt> > MEDFileStructuredMesh::getAllNonNullFamilyIds() const
5673 {
5674   std::list< MCAuto<DataArrayInt> > ret;
5675   const DataArrayInt *da(_fam_nodes);
5676   if(da)
5677     { da->incrRef(); ret.push_back(MCAuto<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
5678   da=_fam_cells;
5679   if(da)
5680     { da->incrRef(); ret.push_back(MCAuto<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
5681   da=_fam_faces;
5682   if(da)
5683     { da->incrRef(); ret.push_back(MCAuto<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
5684   return ret;
5685 }
5686
5687 void MEDFileStructuredMesh::deepCpyAttributes()
5688 {
5689   if((const DataArrayInt*)_fam_nodes)
5690     _fam_nodes=_fam_nodes->deepCopy();
5691   if((const DataArrayInt*)_num_nodes)
5692     _num_nodes=_num_nodes->deepCopy();
5693   if((const DataArrayAsciiChar*)_names_nodes)
5694     _names_nodes=_names_nodes->deepCopy();
5695   if((const DataArrayInt*)_fam_cells)
5696     _fam_cells=_fam_cells->deepCopy();
5697   if((const DataArrayInt*)_num_cells)
5698     _num_cells=_num_cells->deepCopy();
5699   if((const DataArrayAsciiChar*)_names_cells)
5700     _names_cells=_names_cells->deepCopy();
5701   if((const DataArrayInt*)_fam_faces)
5702     _fam_faces=_fam_faces->deepCopy();
5703   if((const DataArrayInt*)_num_faces)
5704     _num_faces=_num_faces->deepCopy();
5705   if((const DataArrayAsciiChar*)_names_faces)
5706     _names_faces=_names_faces->deepCopy();
5707   if((const DataArrayInt*)_rev_num_nodes)
5708     _rev_num_nodes=_rev_num_nodes->deepCopy();
5709   if((const DataArrayInt*)_rev_num_cells)
5710     _rev_num_cells=_rev_num_cells->deepCopy();
5711 }
5712
5713 /*!
5714  * Returns a pointer to mesh at the specified level (here 0 is compulsary for cartesian mesh).
5715  * 
5716  * \return a pointer to cartesian mesh that need to be managed by the caller.
5717  * \warning the returned pointer has to be managed by the caller.
5718  */
5719
5720 /*!
5721  * Returns a pointer to MEDCouplingStructuredMesh held by \a this. 
5722  *  \param [in] meshDimRelToMax - it must be \c 0 or \c -1.
5723  *  \param [in] renum - it must be \c false.
5724  *  \return MEDCouplingMesh * - a pointer to MEDCouplingMesh that the caller is to
5725  *          delete using decrRef() as it is no more needed. 
5726  */
5727 MEDCouplingMesh *MEDFileStructuredMesh::getMeshAtLevel(int meshDimRelToMax, bool renum) const
5728 {
5729   checkCartesian();
5730   if(renum)
5731     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support renumbering ! To do it perform request of renum array directly !");
5732   const MEDCouplingStructuredMesh *m(getStructuredMesh());
5733   switch(meshDimRelToMax)
5734   {
5735     case 0:
5736       {
5737         if(m)
5738           m->incrRef();
5739         return const_cast<MEDCouplingStructuredMesh *>(m);
5740       }
5741     case -1:
5742       {
5743         if(!m)
5744           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getMeshAtLevel : level -1 requested must be non empty to be able to compute unstructured sub mesh !");
5745         buildMinusOneImplicitPartIfNeeded();
5746         MEDCoupling1SGTUMesh *ret(_faces_if_necessary);
5747         if(ret)
5748           ret->incrRef();
5749         return ret;
5750       }
5751     default:
5752       throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support multi level for mesh 0 expected as input !");
5753   }
5754 }
5755
5756 std::vector<int> MEDFileStructuredMesh::getFamsNonEmptyLevels(const std::vector<std::string>& fams) const
5757 {
5758   std::vector<int> ret;
5759   const DataArrayInt *famCells(_fam_cells),*famFaces(_fam_faces);
5760   if(famCells && famCells->presenceOfValue(ret))
5761     ret.push_back(0);
5762   if(famFaces && famFaces->presenceOfValue(ret))
5763     ret.push_back(-1);
5764   return ret;  
5765 }
5766
5767 std::vector<int> MEDFileStructuredMesh::getFamsNonEmptyLevelsExt(const std::vector<std::string>& fams) const
5768 {
5769   std::vector<int> ret(getFamsNonEmptyLevels(fams));
5770   const DataArrayInt *famNodes(_fam_nodes);
5771   if(famNodes && famNodes->presenceOfValue(ret))
5772     ret.push_back(1);
5773   return ret;  
5774 }
5775
5776 /*!
5777  * Returns number of mesh entities of a given relative dimension in \a this mesh.
5778  *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
5779  *  \return int - the number of entities.
5780  *  \throw If no mesh entities of dimension \a meshDimRelToMaxExt are available in \a this mesh.
5781  */
5782 int MEDFileStructuredMesh::getSizeAtLevel(int meshDimRelToMaxExt) const
5783 {
5784   const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
5785   if(!cmesh)
5786     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : No structured mesh set !");
5787   switch(meshDimRelToMaxExt)
5788   {
5789     case 0:
5790       return cmesh->getNumberOfCells();
5791     case 1:
5792       return cmesh->getNumberOfNodes();
5793     case -1:
5794       return cmesh->getNumberOfCellsOfSubLevelMesh();
5795     default:
5796       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : Only available for levels 0 or 1 or -1 !");
5797   }
5798 }
5799
5800 int MEDFileStructuredMesh::getNumberOfNodes() const
5801 {
5802   const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
5803   if(!cmesh)
5804     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberOfNodes : no cartesian mesh set !");
5805   return cmesh->getNumberOfNodes();
5806 }
5807
5808 int MEDFileStructuredMesh::getNumberOfCellsAtLevel(int meshDimRelToMaxExt) const
5809 {
5810   const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
5811   if(!cmesh)
5812     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberOfNodes : no cartesian mesh set !");
5813   switch(meshDimRelToMaxExt)
5814   {
5815     case 0:
5816       return cmesh->getNumberOfCells();
5817     case -1:
5818       return cmesh->getNumberOfCellsOfSubLevelMesh();
5819     default:
5820       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberOfNodes : only meshDimRelToMax=0 and meshDimRelToMax=-1 supported !");
5821     }
5822 }
5823
5824 bool MEDFileStructuredMesh::hasImplicitPart() const
5825 {
5826   return true;
5827 }
5828
5829 /*!
5830  * \sa MEDFileStructuredMesh::getImplicitFaceMesh
5831  */
5832 int MEDFileStructuredMesh::buildImplicitPartIfAny(INTERP_KERNEL::NormalizedCellType gt) const
5833 {
5834   static const char MSG[]="MEDFileStructuredMesh::buildImplicitPartIfAny : the given geo type is not manageable by a structured mesh !";
5835   const MEDCoupling1SGTUMesh *zeFaceMesh(_faces_if_necessary);
5836   if(!zeFaceMesh)
5837     {
5838       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(getMeshDimension())));
5839       if(cm.getReverseExtrudedType()!=gt)
5840         throw INTERP_KERNEL::Exception(MSG);
5841       buildImplicitPart();
5842       return getStructuredMesh()->getNumberOfCellsOfSubLevelMesh();
5843     }
5844   else
5845     {
5846       if(gt!=zeFaceMesh->getCellModelEnum())
5847         throw INTERP_KERNEL::Exception(MSG);
5848       return zeFaceMesh->getNumberOfCells();
5849     }
5850 }
5851
5852 void MEDFileStructuredMesh::buildMinusOneImplicitPartIfNeeded() const
5853 {
5854   const MEDCoupling1SGTUMesh *zeFaceMesh(_faces_if_necessary);
5855   if(!zeFaceMesh)
5856     buildImplicitPart();
5857 }
5858
5859 void MEDFileStructuredMesh::buildImplicitPart() const
5860 {
5861   const MEDCouplingStructuredMesh *mcmesh(getStructuredMesh());
5862   if(!mcmesh)
5863     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::buildImplicitPart : Unable to build the implicit part of structured mesh because no structured mesh at level 0 defined !");
5864   _faces_if_necessary=mcmesh->build1SGTSubLevelMesh();
5865 }
5866
5867 void MEDFileStructuredMesh::releaseImplicitPartIfAny() const
5868 {
5869   _faces_if_necessary=0;
5870 }
5871
5872 /*!
5873  * Retrieves the internal pointer (no decrRef requested) of the implicit face mesh if any.
5874  * To force to build it you can invoke MEDFileStructuredMesh::buildImplicitPartIfAny method.
5875  * 
5876  * \sa MEDFileStructuredMesh::buildImplicitPartIfAny
5877  */
5878 MEDCoupling1SGTUMesh *MEDFileStructuredMesh::getImplicitFaceMesh() const
5879 {
5880   checkCartesian();
5881   return _faces_if_necessary;
5882 }
5883
5884 std::vector<INTERP_KERNEL::NormalizedCellType> MEDFileStructuredMesh::getGeoTypesAtLevel(int meshDimRelToMax) const
5885 {
5886   const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
5887   if(!cmesh)
5888     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGeoTypesAtLevel : No structured mesh set !");
5889   switch(meshDimRelToMax)
5890   {
5891     case 0:
5892       {
5893         std::vector<INTERP_KERNEL::NormalizedCellType> ret(1,cmesh->getTypeOfCell(0));
5894         return ret;
5895       }
5896     case -1:
5897       {
5898         int mdim(cmesh->getMeshDimension());
5899         if(mdim<1)
5900           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGeoTypesAtLevel : only one level available for structured meshes ! Input 0 is mandatory or 0D mesh !");
5901         std::vector<INTERP_KERNEL::NormalizedCellType> ret(1,MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(mdim-1));
5902         return ret;
5903       }
5904     default:
5905       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGeoTypesAtLevel : only 2 levels available at most : 0 and -1 !");
5906   }
5907 }
5908
5909 int MEDFileStructuredMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType ct) const
5910 {
5911   if(ct!=MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(getMeshDimension()))
5912     return 0;
5913   else
5914     return getNumberOfCellsAtLevel(0);
5915 }
5916
5917 void MEDFileStructuredMesh::whichAreNodesFetched(const MEDFileField1TSStructItem& st, const MEDFileFieldGlobsReal *globs, std::vector<bool>& nodesFetched) const
5918 {
5919   if(st.getNumberOfItems()!=1)
5920     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : The sturture of field is not lying on single geo type ! it is not managed yet for structured mesh !");
5921   if(st[0].getGeo()!=MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(getMeshDimension()))
5922     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : The sturture of field is not lying on expected geo type !");
5923   if(getNumberOfNodes()!=(int)nodesFetched.size())
5924     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : invalid size of array !");
5925   if(st[0].getPflName().empty())
5926     {
5927       std::fill(nodesFetched.begin(),nodesFetched.end(),true);
5928       return ;
5929     }
5930   const DataArrayInt *arr(globs->getProfile(st[0].getPflName()));
5931   const MEDCouplingStructuredMesh *cmesh=getStructuredMesh();//cmesh not null because getNumberOfNodes called before
5932   int sz(nodesFetched.size());
5933   for(const int *work=arr->begin();work!=arr->end();work++)
5934     {
5935       std::vector<int> conn;
5936       cmesh->getNodeIdsOfCell(*work,conn);
5937       for(std::vector<int>::const_iterator it=conn.begin();it!=conn.end();it++)
5938         if(*it>=0 && *it<sz)
5939           nodesFetched[*it]=true;
5940         else
5941           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : internal error !");
5942     }
5943 }
5944
5945 med_geometry_type MEDFileStructuredMesh::GetGeoTypeFromMeshDim(int meshDim)
5946 {
5947   INTERP_KERNEL::NormalizedCellType ct(MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(meshDim));
5948   return typmai3[ct];
5949 }
5950
5951 void MEDFileStructuredMesh::LoadStrMeshDAFromFile(med_idt fid, int meshDim, int dt, int it, const std::string& mName, MEDFileMeshReadSelector *mrs,
5952                                                   MCAuto<DataArrayInt>& famCells, MCAuto<DataArrayInt>& numCells, MCAuto<DataArrayAsciiChar>& namesCells)
5953 {
5954   med_bool chgt=MED_FALSE,trsf=MED_FALSE;
5955   med_geometry_type geoTypeReq=MEDFileStructuredMesh::GetGeoTypeFromMeshDim(meshDim);
5956   int nbOfElt(0);
5957   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf);
5958   if(nbOfElt>0)
5959     {
5960       if(!mrs || mrs->isCellFamilyFieldReading())
5961         {
5962           famCells=DataArrayInt::New();
5963           famCells->alloc(nbOfElt,1);
5964           MEDFILESAFECALLERRD0(MEDmeshEntityFamilyNumberRd,(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,famCells->getPointer()));
5965         }
5966     }
5967   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,MED_NUMBER,MED_NODAL,&chgt,&trsf);
5968   if(nbOfElt>0)
5969     {
5970       if(!mrs || mrs->isCellNumFieldReading())
5971         {
5972           numCells=DataArrayInt::New();
5973           numCells->alloc(nbOfElt,1);
5974           MEDFILESAFECALLERRD0(MEDmeshEntityNumberRd,(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,numCells->getPointer()));
5975         }
5976     }
5977   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,MED_NAME,MED_NODAL,&chgt,&trsf);
5978   if(nbOfElt>0)
5979     {
5980       if(!mrs || mrs->isCellNameFieldReading())
5981         {
5982           namesCells=DataArrayAsciiChar::New();
5983           namesCells->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end
5984           MEDFILESAFECALLERRD0(MEDmeshEntityNameRd,(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,namesCells->getPointer()));
5985           namesCells->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end
5986         }
5987     }
5988 }
5989
5990 void MEDFileStructuredMesh::loadStrMeshFromFile(MEDFileStrMeshL2 *strm, med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
5991 {
5992   setName(strm->getName());
5993   setDescription(strm->getDescription());
5994   setUnivName(strm->getUnivName());
5995   setIteration(strm->getIteration());
5996   setOrder(strm->getOrder());
5997   setTimeValue(strm->getTime());
5998   setTimeUnit(strm->getTimeUnit());
5999   MEDFileMeshL2::ReadFamiliesAndGrps(fid,mName,_families,_groups,mrs);
6000   med_bool chgt=MED_FALSE,trsf=MED_FALSE;
6001   int nbOfElt(MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf));
6002   if(nbOfElt>0)
6003     {
6004       if(!mrs || mrs->isNodeFamilyFieldReading())
6005         {
6006           int nbNodes(getNumberOfNodes());
6007           if(nbOfElt>nbNodes)
6008             throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::loadStrMeshFromFile : invalid size of family node array regarding number of nodes in this ! File seems to be corrupted !");
6009           _fam_nodes=DataArrayInt::New();
6010           _fam_nodes->alloc(nbNodes,1);//yes nbNodes and not nbOfElt see next line.
6011           if(nbNodes>nbOfElt)//yes it appends some times... It explains surely the mdump implementation. Bug revealed by PARAVIS EDF #2475 on structured.med file where only 12 first nodes are !=0 so nbOfElt=12 and nbOfNodes=378...
6012             _fam_nodes->fillWithZero();
6013           MEDFILESAFECALLERRD0(MEDmeshEntityFamilyNumberRd,(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,_fam_nodes->getPointer()));
6014         }
6015     }
6016   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_NUMBER,MED_NODAL,&chgt,&trsf);
6017   if(nbOfElt>0)
6018     {
6019       if(!mrs || mrs->isNodeNumFieldReading())
6020         {
6021           _num_nodes=DataArrayInt::New();
6022           _num_nodes->alloc(nbOfElt,1);
6023           MEDFILESAFECALLERRD0(MEDmeshEntityNumberRd,(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,_num_nodes->getPointer()));
6024         }
6025     }
6026   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_NAME,MED_NODAL,&chgt,&trsf);
6027   if(nbOfElt>0)
6028     {
6029       if(!mrs || mrs->isNodeNameFieldReading())
6030         {
6031           _names_nodes=DataArrayAsciiChar::New();
6032           _names_nodes->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end
6033           MEDFILESAFECALLERRD0(MEDmeshEntityNameRd,(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,_names_nodes->getPointer()));
6034           _names_nodes->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end
6035         }
6036     }
6037   int meshDim(getStructuredMesh()->getMeshDimension());
6038   LoadStrMeshDAFromFile(fid,meshDim,dt,it,mName,mrs,_fam_cells,_num_cells,_names_cells);
6039   if(meshDim>=1)
6040     LoadStrMeshDAFromFile(fid,meshDim-1,dt,it,mName,mrs,_fam_faces,_num_faces,_names_faces);
6041 }
6042
6043 void MEDFileStructuredMesh::writeStructuredLL(med_idt fid, const std::string& maa) const
6044 {
6045   int meshDim(getStructuredMesh()->getMeshDimension());
6046   med_geometry_type geoTypeReq(GetGeoTypeFromMeshDim(meshDim)),geoTypeReq2(GetGeoTypeFromMeshDim(meshDim-1));
6047   //
6048   if((const DataArrayInt *)_fam_cells)
6049     MEDFILESAFECALLERWR0(MEDmeshEntityFamilyNumberWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq,_fam_cells->getNumberOfTuples(),_fam_cells->getConstPointer()));
6050   if((const DataArrayInt *)_fam_faces)
6051     MEDFILESAFECALLERWR0(MEDmeshEntityFamilyNumberWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq2,_fam_faces->getNumberOfTuples(),_fam_faces->getConstPointer()));
6052   if((const DataArrayInt *)_fam_nodes)
6053     MEDFILESAFECALLERWR0(MEDmeshEntityFamilyNumberWr,(fid,maa.c_str(),_iteration,_order,MED_NODE,MED_NONE,_fam_nodes->getNumberOfTuples(),_fam_nodes->getConstPointer()));
6054   if((const DataArrayInt *)_num_cells)
6055     MEDFILESAFECALLERWR0(MEDmeshEntityNumberWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq,_num_cells->getNumberOfTuples(),_num_cells->getConstPointer()));
6056   if((const DataArrayInt *)_num_faces)
6057     MEDFILESAFECALLERWR0(MEDmeshEntityNumberWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq2,_num_faces->getNumberOfTuples(),_num_faces->getConstPointer()));
6058   if((const DataArrayInt *)_num_nodes)
6059     MEDFILESAFECALLERWR0(MEDmeshEntityNumberWr,(fid,maa.c_str(),_iteration,_order,MED_NODE,MED_NONE,_num_nodes->getNumberOfTuples(),_num_nodes->getConstPointer()));
6060   if((const DataArrayAsciiChar *)_names_cells)
6061     {
6062       if(_names_cells->getNumberOfComponents()!=MED_SNAME_SIZE)
6063         {
6064           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on cells with number of components set to " << MED_SNAME_SIZE;
6065           oss << " ! The array has " << _names_cells->getNumberOfComponents() << " components !";
6066           throw INTERP_KERNEL::Exception(oss.str().c_str());
6067         }
6068       MEDFILESAFECALLERWR0(MEDmeshEntityNameWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq,_names_cells->getNumberOfTuples(),_names_cells->getConstPointer()));
6069     }
6070   if((const DataArrayAsciiChar *)_names_faces)
6071     {
6072       if(_names_faces->getNumberOfComponents()!=MED_SNAME_SIZE)
6073         {
6074           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on faces with number of components set to " << MED_SNAME_SIZE;
6075           oss << " ! The array has " << _names_faces->getNumberOfComponents() << " components !";
6076           throw INTERP_KERNEL::Exception(oss.str().c_str());
6077         }
6078       MEDFILESAFECALLERWR0(MEDmeshEntityNameWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq2,_names_faces->getNumberOfTuples(),_names_faces->getConstPointer()));
6079     }
6080   if((const DataArrayAsciiChar *)_names_nodes)
6081     {
6082       if(_names_nodes->getNumberOfComponents()!=MED_SNAME_SIZE)
6083         {
6084           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on nodes with number of components set to " << MED_SNAME_SIZE;
6085           oss << " ! The array has " << _names_cells->getNumberOfComponents() << " components !";
6086           throw INTERP_KERNEL::Exception(oss.str().c_str());
6087         }
6088       MEDFILESAFECALLERWR0(MEDmeshEntityNameWr,(fid,maa.c_str(),_iteration,_order,MED_NODE,MED_NONE,_names_nodes->getNumberOfTuples(),_names_nodes->getConstPointer()));
6089     }
6090   //
6091   MEDFileUMeshL2::WriteFamiliesAndGrps(fid,maa.c_str(),_families,_groups,_too_long_str);
6092 }
6093
6094 /*!
6095  * Returns an empty instance of MEDFileCMesh.
6096  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
6097  *          mesh using decrRef() as it is no more needed. 
6098  */
6099 MEDFileCMesh *MEDFileCMesh::New()
6100 {
6101   return new MEDFileCMesh;
6102 }
6103
6104 /*!
6105  * Returns a new MEDFileCMesh holding the mesh data that has been read from a given MED
6106  * file. The first mesh in the file is loaded.
6107  *  \param [in] fileName - the name of MED file to read.
6108  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
6109  *          mesh using decrRef() as it is no more needed. 
6110  *  \throw If the file is not readable.
6111  *  \throw If there is no meshes in the file.
6112  *  \throw If the mesh in the file is not a Cartesian one.
6113  */
6114 MEDFileCMesh *MEDFileCMesh::New(const std::string& fileName, MEDFileMeshReadSelector *mrs)
6115 {
6116   std::vector<std::string> ms(MEDCoupling::GetMeshNames(fileName));
6117   if(ms.empty())
6118     {
6119       std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
6120       throw INTERP_KERNEL::Exception(oss.str().c_str());
6121     }
6122   MEDFileUtilities::CheckFileForRead(fileName);
6123   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
6124   int dt,it;
6125   MEDCoupling::MEDCouplingMeshType meshType;
6126   std::string dummy2;
6127   MEDCoupling::MEDCouplingAxisType dummy3;
6128   MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dummy3,dt,it,dummy2);
6129   return new MEDFileCMesh(fid,ms.front(),dt,it,mrs);
6130 }
6131
6132 /*!
6133  * Returns a new MEDFileCMesh holding the mesh data that has been read from a given MED
6134  * file. The mesh to load is specified by its name and numbers of a time step and an
6135  * iteration.
6136  *  \param [in] fileName - the name of MED file to read.
6137  *  \param [in] mName - the name of the mesh to read.
6138  *  \param [in] dt - the number of a time step.
6139  *  \param [in] it - the number of an iteration.
6140  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
6141  *          mesh using decrRef() as it is no more needed. 
6142  *  \throw If the file is not readable.
6143  *  \throw If there is no mesh with given attributes in the file.
6144  *  \throw If the mesh in the file is not a Cartesian one.
6145  */
6146 MEDFileCMesh *MEDFileCMesh::New(const std::string& fileName, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6147 {
6148   MEDFileUtilities::CheckFileForRead(fileName);
6149   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
6150   return new MEDFileCMesh(fid,mName,dt,it,mrs);
6151 }
6152
6153 std::size_t MEDFileCMesh::getHeapMemorySizeWithoutChildren() const
6154 {
6155   return MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren();
6156 }
6157
6158 std::vector<const BigMemoryObject *> MEDFileCMesh::getDirectChildrenWithNull() const
6159 {
6160   std::vector<const BigMemoryObject *> ret(MEDFileStructuredMesh::getDirectChildrenWithNull());
6161   ret.push_back((const MEDCouplingCMesh *)_cmesh);
6162   return ret;
6163 }
6164
6165 /*!
6166  * Returns the dimension on cells in \a this mesh.
6167  *  \return int - the mesh dimension.
6168  *  \throw If there are no cells in this mesh.
6169  */
6170 int MEDFileCMesh::getMeshDimension() const
6171 {
6172   if(!((const MEDCouplingCMesh*)_cmesh))
6173     throw INTERP_KERNEL::Exception("MEDFileCMesh::getMeshDimension : unable to get meshdimension because no mesh set !");
6174   return _cmesh->getMeshDimension();
6175 }
6176
6177 /*!
6178  * Returns the dimension on nodes in \a this mesh.
6179  *  \return int - the space dimension.
6180  *  \throw If there are no cells in this mesh.
6181  */
6182 int MEDFileCMesh::getSpaceDimension() const
6183 {
6184   if(!((const MEDCouplingCMesh*)_cmesh))
6185     throw INTERP_KERNEL::Exception("MEDFileCMesh::getSpaceDimension : unable to get spacedimension because no mesh set !");
6186   return _cmesh->getSpaceDimension();
6187 }
6188
6189 /*!
6190  * Returns a string describing \a this mesh.
6191  *  \return std::string - the mesh information string.
6192  */
6193 std::string MEDFileCMesh::simpleRepr() const
6194 {
6195   return MEDFileStructuredMesh::simpleRepr();
6196 }
6197
6198 /*!
6199  * Returns a full textual description of \a this mesh.
6200  *  \return std::string - the string holding the mesh description.
6201  */
6202 std::string MEDFileCMesh::advancedRepr() const
6203 {
6204   return simpleRepr();
6205 }
6206
6207 MEDFileMesh *MEDFileCMesh::shallowCpy() const
6208 {
6209   MCAuto<MEDFileCMesh> ret(new MEDFileCMesh(*this));
6210   return ret.retn();
6211 }
6212
6213 MEDFileMesh *MEDFileCMesh::createNewEmpty() const
6214 {
6215   return new MEDFileCMesh;
6216 }
6217
6218 MEDFileMesh *MEDFileCMesh::deepCopy() const
6219 {
6220   MCAuto<MEDFileCMesh> ret(new MEDFileCMesh(*this));
6221   ret->deepCpyEquivalences(*this);
6222   if((const MEDCouplingCMesh*)_cmesh)
6223     ret->_cmesh=static_cast<MEDCouplingCMesh*>(_cmesh->deepCopy());
6224   ret->deepCpyAttributes();
6225   return ret.retn();
6226 }
6227
6228 /*!
6229  * Checks if \a this and another mesh are equal.
6230  *  \param [in] other - the mesh to compare with.
6231  *  \param [in] eps - a precision used to compare real values.
6232  *  \param [in,out] what - the string returning description of unequal data.
6233  *  \return bool - \c true if the meshes are equal, \c false, else.
6234  */
6235 bool MEDFileCMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
6236 {
6237   if(!MEDFileStructuredMesh::isEqual(other,eps,what))
6238     return false;
6239   const MEDFileCMesh *otherC=dynamic_cast<const MEDFileCMesh *>(other);
6240   if(!otherC)
6241     {
6242       what="Mesh types differ ! This is cartesian and other is NOT !";
6243       return false;
6244     }
6245   clearNonDiscrAttributes();
6246   otherC->clearNonDiscrAttributes();
6247   const MEDCouplingCMesh *coo1=_cmesh;
6248   const MEDCouplingCMesh *coo2=otherC->_cmesh;
6249   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
6250     {
6251       what="Mismatch of cartesian meshes ! One is defined and not other !";
6252       return false;
6253     }
6254   if(coo1)
6255     {
6256       bool ret=coo1->isEqual(coo2,eps);
6257       if(!ret)
6258         {
6259           what="cartesian meshes differ !";
6260           return false;
6261         }
6262     }
6263   return true;
6264 }
6265
6266 /*!
6267  * Clears redundant attributes of incorporated data arrays.
6268  */
6269 void MEDFileCMesh::clearNonDiscrAttributes() const
6270 {
6271   MEDFileStructuredMesh::clearNonDiscrAttributes();
6272   MEDFileUMeshSplitL1::ClearNonDiscrAttributes(_cmesh);//to it is not a bug umeshsplit have already the method implemented
6273 }
6274
6275 MEDFileCMesh::MEDFileCMesh()
6276 {
6277 }
6278
6279 MEDFileCMesh::MEDFileCMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6280 try
6281 {
6282     loadLLWithAdditionalItems(fid,mName,dt,it,mrs);
6283 }
6284 catch(INTERP_KERNEL::Exception& e)
6285 {
6286     throw e;
6287 }
6288
6289 void MEDFileCMesh::loadLL(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6290 {
6291   MEDCoupling::MEDCouplingMeshType meshType;
6292   int dummy0,dummy1;
6293   std::string dtunit;
6294   MEDCoupling::MEDCouplingAxisType axType;
6295   int mid=MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,axType,dummy0,dummy1,dtunit);
6296   if(meshType!=CARTESIAN)
6297     {
6298       std::ostringstream oss; oss << "Trying to load as cartesian an existing mesh with name '" << mName << "' that is NOT cartesian !";
6299       throw INTERP_KERNEL::Exception(oss.str().c_str());
6300     }
6301   MEDFileCMeshL2 loaderl2;
6302   loaderl2.loadAll(fid,mid,mName,dt,it);
6303   setAxisType(axType);
6304   MEDCouplingCMesh *mesh=loaderl2.getMesh();
6305   mesh->incrRef();
6306   _cmesh=mesh;
6307   loadStrMeshFromFile(&loaderl2,fid,mName,dt,it,mrs);
6308 }
6309
6310 /*!
6311  * Returns a const pointer to MEDCouplingCMesh held by \a this mesh.
6312  *  \return const MEDCouplingCMesh * - a pointer to the held MEDCouplingCMesh.
6313  */
6314 const MEDCouplingCMesh *MEDFileCMesh::getMesh() const
6315 {
6316   synchronizeTinyInfoOnLeaves();
6317   return _cmesh;
6318 }
6319
6320 const MEDCouplingStructuredMesh *MEDFileCMesh::getStructuredMesh() const
6321 {
6322   synchronizeTinyInfoOnLeaves();
6323   return _cmesh;
6324 }
6325
6326 /*!
6327  * Sets the MEDCouplingCMesh holding the data of \a this mesh.
6328  *  \param [in] m - the new MEDCouplingCMesh to refer to.
6329  *  \throw If the name or the description of \a this mesh and \a m are not empty and are
6330  *         different. 
6331  */
6332 void MEDFileCMesh::setMesh(MEDCouplingCMesh *m)
6333 {
6334   dealWithTinyInfo(m);
6335   if(m)
6336     m->incrRef();
6337   _cmesh=m;
6338 }
6339
6340 MEDFileMesh *MEDFileCMesh::cartesianize() const
6341 {
6342   if(getAxisType()==AX_CART)
6343     {
6344       incrRef();
6345       return const_cast<MEDFileCMesh *>(this);
6346     }
6347   else
6348     {
6349       const MEDCouplingCMesh *cmesh(getMesh());
6350       if(!cmesh)
6351         throw INTERP_KERNEL::Exception("MEDFileCMesh::cartesianize : impossible to turn into cartesian because the mesh is null !");
6352       MCAuto<MEDCouplingCurveLinearMesh> clmesh(cmesh->buildCurveLinear());
6353       MCAuto<DataArrayDouble> coords(clmesh->getCoords()->cartesianize(getAxisType()));
6354       clmesh->setCoords(coords);
6355       MCAuto<MEDFileCurveLinearMesh> ret(MEDFileCurveLinearMesh::New());
6356       ret->MEDFileStructuredMesh::operator=(*this);
6357       ret->setMesh(clmesh);
6358       ret->setAxisType(AX_CART);
6359       return ret.retn();
6360     }
6361 }
6362
6363 void MEDFileCMesh::writeLL(med_idt fid) const
6364 {
6365   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
6366   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
6367   INTERP_KERNEL::AutoPtr<char> dtunit=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE);
6368   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
6369   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
6370   MEDLoaderBase::safeStrCpy(_dt_unit.c_str(),MED_LNAME_SIZE,dtunit,_too_long_str);
6371   int spaceDim(_cmesh->getSpaceDimension());
6372   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
6373   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
6374   for(int i=0;i<spaceDim;i++)
6375     {
6376       std::string info(_cmesh->getCoordsAt(i)->getInfoOnComponent(0));
6377       std::string c,u;
6378       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
6379       MEDLoaderBase::safeStrCpy2(c.c_str(),MED_SNAME_SIZE-1,comp+i*MED_SNAME_SIZE,_too_long_str);//MED_TAILLE_PNOM-1 to avoid to write '\0' on next compo
6380       MEDLoaderBase::safeStrCpy2(u.c_str(),MED_SNAME_SIZE-1,unit+i*MED_SNAME_SIZE,_too_long_str);//MED_TAILLE_PNOM-1 to avoid to write '\0' on next compo
6381     }
6382   MEDFILESAFECALLERWR0(MEDmeshCr,(fid,maa,spaceDim,spaceDim,MED_STRUCTURED_MESH,desc,dtunit,MED_SORT_DTIT,MEDFileMeshL2::TraduceAxisTypeRev(getAxisType()),comp,unit));
6383   if(_univ_wr_status)
6384     MEDFILESAFECALLERWR0(MEDmeshUniversalNameWr,(fid,maa));
6385   MEDFILESAFECALLERWR0(MEDmeshGridTypeWr,(fid,maa,MEDFileMeshL2::TraduceAxisTypeRevStruct(getAxisType())));
6386   for(int i=0;i<spaceDim;i++)
6387     {
6388       const DataArrayDouble *da=_cmesh->getCoordsAt(i);
6389       MEDFILESAFECALLERWR0(MEDmeshGridIndexCoordinateWr,(fid,maa,_iteration,_order,_time,i+1,da->getNumberOfTuples(),da->getConstPointer()));
6390     }
6391   //
6392   std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE));
6393   MEDFileStructuredMesh::writeStructuredLL(fid,meshName);
6394 }
6395
6396 void MEDFileCMesh::synchronizeTinyInfoOnLeaves() const
6397 {
6398   const MEDCouplingCMesh *cmesh=_cmesh;
6399   if(!cmesh)
6400     return;
6401   (const_cast<MEDCouplingCMesh *>(cmesh))->setName(_name);
6402   (const_cast<MEDCouplingCMesh *>(cmesh))->setDescription(_desc_name);
6403   (const_cast<MEDCouplingCMesh *>(cmesh))->setTime(_time,_iteration,_order);
6404   (const_cast<MEDCouplingCMesh *>(cmesh))->setTimeUnit(_dt_unit);
6405 }
6406
6407 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New()
6408 {
6409   return new MEDFileCurveLinearMesh;
6410 }
6411
6412 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const std::string& fileName, MEDFileMeshReadSelector *mrs)
6413 {
6414   std::vector<std::string> ms(MEDCoupling::GetMeshNames(fileName));
6415   if(ms.empty())
6416     {
6417       std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
6418       throw INTERP_KERNEL::Exception(oss.str().c_str());
6419     }
6420   MEDFileUtilities::CheckFileForRead(fileName);
6421   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
6422   int dt,it;
6423   MEDCoupling::MEDCouplingMeshType meshType;
6424   MEDCoupling::MEDCouplingAxisType dummy3;
6425   std::string dummy2;
6426   MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dummy3,dt,it,dummy2);
6427   return new MEDFileCurveLinearMesh(fid,ms.front(),dt,it,mrs);
6428 }
6429
6430 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const std::string& fileName, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6431 {
6432   MEDFileUtilities::CheckFileForRead(fileName);
6433   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
6434   return new MEDFileCurveLinearMesh(fid,mName,dt,it,mrs);
6435 }
6436
6437 std::size_t MEDFileCurveLinearMesh::getHeapMemorySizeWithoutChildren() const
6438 {
6439   return MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren();
6440 }
6441
6442 std::vector<const BigMemoryObject *> MEDFileCurveLinearMesh::getDirectChildrenWithNull() const
6443 {
6444   std::vector<const BigMemoryObject *> ret(MEDFileStructuredMesh::getDirectChildrenWithNull());
6445   ret.push_back((const MEDCouplingCurveLinearMesh *)_clmesh);
6446   return ret;
6447 }
6448
6449 MEDFileMesh *MEDFileCurveLinearMesh::shallowCpy() const
6450 {
6451   MCAuto<MEDFileCurveLinearMesh> ret(new MEDFileCurveLinearMesh(*this));
6452   return ret.retn();
6453 }
6454
6455 MEDFileMesh *MEDFileCurveLinearMesh::createNewEmpty() const
6456 {
6457   return new MEDFileCurveLinearMesh;
6458 }
6459
6460 MEDFileMesh *MEDFileCurveLinearMesh::deepCopy() const
6461 {
6462   MCAuto<MEDFileCurveLinearMesh> ret(new MEDFileCurveLinearMesh(*this));
6463   ret->deepCpyEquivalences(*this);
6464   if((const MEDCouplingCurveLinearMesh*)_clmesh)
6465     ret->_clmesh=static_cast<MEDCouplingCurveLinearMesh*>(_clmesh->deepCopy());
6466   ret->deepCpyAttributes();
6467   return ret.retn();
6468 }
6469
6470 int MEDFileCurveLinearMesh::getMeshDimension() const
6471 {
6472   if(!((const MEDCouplingCurveLinearMesh*)_clmesh))
6473     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::getMeshDimension : unable to get meshdimension because no mesh set !");
6474   return _clmesh->getMeshDimension();
6475 }
6476
6477 std::string MEDFileCurveLinearMesh::simpleRepr() const
6478 {
6479   return MEDFileStructuredMesh::simpleRepr();
6480 }
6481
6482 std::string MEDFileCurveLinearMesh::advancedRepr() const
6483 {
6484   return simpleRepr();
6485 }
6486
6487 bool MEDFileCurveLinearMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
6488 {
6489   if(!MEDFileStructuredMesh::isEqual(other,eps,what))
6490     return false;
6491   const MEDFileCurveLinearMesh *otherC=dynamic_cast<const MEDFileCurveLinearMesh *>(other);
6492   if(!otherC)
6493     {
6494       what="Mesh types differ ! This is curve linear and other is NOT !";
6495       return false;
6496     }
6497   clearNonDiscrAttributes();
6498   otherC->clearNonDiscrAttributes();
6499   const MEDCouplingCurveLinearMesh *coo1=_clmesh;
6500   const MEDCouplingCurveLinearMesh *coo2=otherC->_clmesh;
6501   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
6502     {
6503       what="Mismatch of curve linear meshes ! One is defined and not other !";
6504       return false;
6505     }
6506   if(coo1)
6507     {
6508       bool ret=coo1->isEqual(coo2,eps);
6509       if(!ret)
6510         {
6511           what="curve linear meshes differ !";
6512           return false;
6513         }
6514     }
6515   return true;
6516 }
6517
6518 void MEDFileCurveLinearMesh::clearNonDiscrAttributes() const
6519 {
6520   MEDFileStructuredMesh::clearNonDiscrAttributes();
6521   MEDFileUMeshSplitL1::ClearNonDiscrAttributes(_clmesh);//to it is not a bug umeshsplit have already the method implemented
6522 }
6523
6524 void MEDFileCurveLinearMesh::synchronizeTinyInfoOnLeaves() const
6525 {
6526   const MEDCouplingCurveLinearMesh *clmesh=_clmesh;
6527   if(!clmesh)
6528     return;
6529   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setName(_name);
6530   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setDescription(_desc_name);
6531   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setTime(_time,_iteration,_order);
6532   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setTimeUnit(_dt_unit);
6533 }
6534
6535 const MEDCouplingCurveLinearMesh *MEDFileCurveLinearMesh::getMesh() const
6536 {
6537   synchronizeTinyInfoOnLeaves();
6538   return _clmesh;
6539 }
6540
6541 void MEDFileCurveLinearMesh::setMesh(MEDCouplingCurveLinearMesh *m)
6542 {
6543   dealWithTinyInfo(m);
6544   if(m)
6545     m->incrRef();
6546   _clmesh=m;
6547 }
6548
6549 MEDFileMesh *MEDFileCurveLinearMesh::cartesianize() const
6550 {
6551   if(getAxisType()==AX_CART)
6552     {
6553       incrRef();
6554       return const_cast<MEDFileCurveLinearMesh *>(this);
6555     }
6556   else
6557     {
6558       const MEDCouplingCurveLinearMesh *mesh(getMesh());
6559       if(!mesh)
6560         throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::cartesianize : impossible to turn into cartesian because the mesh is null !");
6561       const DataArrayDouble *coords(mesh->getCoords());
6562       if(!coords)
6563         throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::cartesianize : coordinate pointer in mesh is null !");
6564       MCAuto<MEDFileCurveLinearMesh> ret(new MEDFileCurveLinearMesh(*this));
6565       MCAuto<MEDCouplingCurveLinearMesh> mesh2(mesh->clone(false));
6566       MCAuto<DataArrayDouble> coordsCart(coords->cartesianize(getAxisType()));
6567       mesh2->setCoords(coordsCart);
6568       ret->setMesh(mesh2);
6569       ret->setAxisType(AX_CART);
6570       return ret.retn();
6571     }
6572 }
6573
6574 const MEDCouplingStructuredMesh *MEDFileCurveLinearMesh::getStructuredMesh() const
6575 {
6576   synchronizeTinyInfoOnLeaves();
6577   return _clmesh;
6578 }
6579
6580 MEDFileCurveLinearMesh::MEDFileCurveLinearMesh()
6581 {
6582 }
6583
6584 MEDFileCurveLinearMesh::MEDFileCurveLinearMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6585 try
6586 {
6587     loadLLWithAdditionalItems(fid,mName,dt,it,mrs);
6588 }
6589 catch(INTERP_KERNEL::Exception& e)
6590 {
6591     throw e;
6592 }
6593
6594 void MEDFileCurveLinearMesh::writeLL(med_idt fid) const
6595 {
6596   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
6597   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
6598   INTERP_KERNEL::AutoPtr<char> dtunit=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE);
6599   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
6600   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
6601   MEDLoaderBase::safeStrCpy(_dt_unit.c_str(),MED_LNAME_SIZE,dtunit,_too_long_str);
6602   int spaceDim=_clmesh->getSpaceDimension();
6603   int meshDim=_clmesh->getMeshDimension();
6604   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
6605   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
6606   const DataArrayDouble *coords=_clmesh->getCoords();
6607   if(!coords)
6608     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::writeLL : no coordinates set !");
6609   for(int i=0;i<spaceDim;i++)
6610     {
6611       std::string info(_clmesh->getCoords()->getInfoOnComponent(i));
6612       std::string c,u;
6613       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
6614       MEDLoaderBase::safeStrCpy2(c.c_str(),MED_SNAME_SIZE-1,comp+i*MED_SNAME_SIZE,_too_long_str);//MED_TAILLE_PNOM-1 to avoid to write '\0' on next compo
6615       MEDLoaderBase::safeStrCpy2(u.c_str(),MED_SNAME_SIZE-1,unit+i*MED_SNAME_SIZE,_too_long_str);//MED_TAILLE_PNOM-1 to avoid to write '\0' on next compo
6616     }
6617   MEDFILESAFECALLERWR0(MEDmeshCr,(fid,maa,spaceDim,meshDim,MED_STRUCTURED_MESH,desc,dtunit,MED_SORT_DTIT,MEDFileMeshL2::TraduceAxisTypeRev(getAxisType()),comp,unit));
6618   if(_univ_wr_status)
6619     MEDFILESAFECALLERWR0(MEDmeshUniversalNameWr,(fid,maa));
6620   MEDFILESAFECALLERWR0(MEDmeshGridTypeWr,(fid,maa,MED_CURVILINEAR_GRID));
6621   std::vector<int> nodeGridSt=_clmesh->getNodeGridStructure();
6622   MEDFILESAFECALLERWR0(MEDmeshGridStructWr,(fid,maa,_iteration,_order,_time,&nodeGridSt[0]));
6623
6624   MEDFILESAFECALLERWR0(MEDmeshNodeCoordinateWr,(fid,maa,_iteration,_order,_time,MED_FULL_INTERLACE,coords->getNumberOfTuples(),coords->begin()));
6625   //
6626   std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE));
6627   MEDFileStructuredMesh::writeStructuredLL(fid,meshName);
6628 }
6629
6630 void MEDFileCurveLinearMesh::loadLL(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6631 {
6632   MEDCoupling::MEDCouplingMeshType meshType;
6633   int dummy0,dummy1;
6634   std::string dtunit;
6635   MEDCoupling::MEDCouplingAxisType axType;
6636   int mid=MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,axType,dummy0,dummy1,dtunit);
6637   setAxisType(axType);
6638   if(meshType!=CURVE_LINEAR)
6639     {
6640       std::ostringstream oss; oss << "Trying to load as curve linear an existing mesh with name '" << mName << "' that is NOT curve linear !";
6641       throw INTERP_KERNEL::Exception(oss.str().c_str());
6642     }
6643   MEDFileCLMeshL2 loaderl2;
6644   loaderl2.loadAll(fid,mid,mName,dt,it);
6645   MEDCouplingCurveLinearMesh *mesh=loaderl2.getMesh();
6646   mesh->incrRef();
6647   _clmesh=mesh;
6648   loadStrMeshFromFile(&loaderl2,fid,mName,dt,it,mrs);
6649 }
6650
6651 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New()
6652 {
6653   return new MEDFileMeshMultiTS;
6654 }
6655
6656 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(const std::string& fileName)
6657 {
6658   return new MEDFileMeshMultiTS(fileName);
6659 }
6660
6661 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(const std::string& fileName, const std::string& mName)
6662 {
6663   return new MEDFileMeshMultiTS(fileName,mName);
6664 }
6665
6666 MEDFileMeshMultiTS *MEDFileMeshMultiTS::deepCopy() const
6667 {
6668   MCAuto<MEDFileMeshMultiTS> ret=MEDFileMeshMultiTS::New();
6669   std::vector< MCAuto<MEDFileMesh> > meshOneTs(_mesh_one_ts.size());
6670   std::size_t i=0;
6671   for(std::vector< MCAuto<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++,i++)
6672     if((const MEDFileMesh *)*it)
6673       meshOneTs[i]=(*it)->deepCopy();
6674   ret->_mesh_one_ts=meshOneTs;
6675   return ret.retn();
6676 }
6677
6678 std::size_t MEDFileMeshMultiTS::getHeapMemorySizeWithoutChildren() const
6679 {
6680   return _mesh_one_ts.capacity()*sizeof(MCAuto<MEDFileMesh>);
6681 }
6682
6683 std::vector<const BigMemoryObject *> MEDFileMeshMultiTS::getDirectChildrenWithNull() const
6684 {
6685   std::vector<const BigMemoryObject *> ret;
6686   for(std::vector< MCAuto<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
6687     ret.push_back((const MEDFileMesh *)*it);
6688   return ret;
6689 }
6690
6691 std::string MEDFileMeshMultiTS::getName() const
6692 {
6693   if(_mesh_one_ts.empty())
6694     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::getName : no time steps set !");
6695   return _mesh_one_ts[0]->getName();
6696 }
6697
6698 void MEDFileMeshMultiTS::setName(const std::string& newMeshName)
6699 {
6700   std::string oldName(getName());
6701   std::vector< std::pair<std::string,std::string> > v(1);
6702   v[0].first=oldName; v[0].second=newMeshName;
6703   changeNames(v);
6704 }
6705
6706 bool MEDFileMeshMultiTS::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab)
6707 {
6708   bool ret=false;
6709   for(std::vector< MCAuto<MEDFileMesh> >::iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
6710     {
6711       MEDFileMesh *cur(*it);
6712       if(cur)
6713         ret=cur->changeNames(modifTab) || ret;
6714     }
6715   return ret;
6716 }
6717
6718 void MEDFileMeshMultiTS::cartesianizeMe()
6719 {
6720   for(std::vector< MCAuto<MEDFileMesh> >::iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
6721     {
6722       MEDFileMesh *cur(*it);
6723       if(cur)
6724         {
6725           MCAuto<MEDFileMesh> ccur(cur->cartesianize());// Attention ! Do not wrap these two lines because memory leak !
6726           *it=ccur;
6727         }
6728     }
6729 }
6730
6731 MEDFileMesh *MEDFileMeshMultiTS::getOneTimeStep() const
6732 {
6733   if(_mesh_one_ts.empty())
6734     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::getOneTimeStep : empty time step set !");
6735   return const_cast<MEDFileMesh *>(static_cast<const MEDFileMesh *>(_mesh_one_ts[0]));
6736 }
6737
6738 void MEDFileMeshMultiTS::setOneTimeStep(MEDFileMesh *mesh1TimeStep)
6739 {
6740   if(!mesh1TimeStep)
6741     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::setOneTimeStep : input pointer should be different from 0 !");
6742   _mesh_one_ts.resize(1);
6743   mesh1TimeStep->incrRef();
6744   //MCAuto<MEDFileMesh> toto=mesh1TimeStep;
6745   _mesh_one_ts[0]=mesh1TimeStep;
6746 }
6747
6748 MEDFileJoints * MEDFileMeshMultiTS::getJoints() const
6749 {
6750   if ( MEDFileMesh* m = getOneTimeStep() )
6751     return m->getJoints();
6752   return 0;
6753 }
6754
6755 /*!
6756  * \brief Set Joints that are common to all time-stamps
6757  */
6758 void MEDFileMeshMultiTS::setJoints( MEDFileJoints* joints )
6759 {
6760   for(std::vector< MCAuto<MEDFileMesh> >::iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
6761     {
6762       (*it)->setJoints( joints );
6763     }
6764 }
6765
6766 void MEDFileMeshMultiTS::write(med_idt fid) const
6767 {
6768   MEDFileJoints *joints(getJoints());
6769   bool jointsWritten(false);
6770
6771   for(std::vector< MCAuto<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
6772     {
6773       if ( jointsWritten )
6774         const_cast<MEDFileMesh&>(**it).setJoints( 0 );
6775       else
6776         jointsWritten = true;
6777
6778       (*it)->copyOptionsFrom(*this);
6779       (*it)->write(fid);
6780     }
6781
6782   (const_cast<MEDFileMeshMultiTS*>(this))->setJoints( joints ); // restore joints
6783 }
6784
6785 void MEDFileMeshMultiTS::write(const std::string& fileName, int mode) const
6786 {
6787   med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode);
6788   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),medmod);
6789   std::ostringstream oss; oss << "MEDFileMesh : error on attempt to write in file : \"" << fileName << "\""; 
6790   MEDFileUtilities::CheckMEDCode(fid,fid,oss.str());
6791   write(fid);
6792 }
6793
6794 void MEDFileMeshMultiTS::loadFromFile(const std::string& fileName, const std::string& mName)
6795 {
6796   MEDFileJoints* joints = 0;
6797   if ( !_mesh_one_ts.empty() && getOneTimeStep() )
6798     {
6799       // joints of mName already read, pass them to MEDFileMesh::New() to prevent repeated reading
6800       joints = getOneTimeStep()->getJoints();
6801     }
6802
6803   _mesh_one_ts.clear();  //for the moment to be improved
6804   _mesh_one_ts.push_back( MEDFileMesh::New(fileName,mName,-1,-1,0, joints ));
6805 }
6806
6807 MEDFileMeshMultiTS::MEDFileMeshMultiTS()
6808 {
6809 }
6810
6811 MEDFileMeshMultiTS::MEDFileMeshMultiTS(const std::string& fileName)
6812 try
6813 {
6814   std::vector<std::string> ms(MEDCoupling::GetMeshNames(fileName));
6815     if(ms.empty())
6816       {
6817         std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
6818         throw INTERP_KERNEL::Exception(oss.str().c_str());
6819       }
6820     MEDFileUtilities::CheckFileForRead(fileName);
6821     MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
6822     int dt,it;
6823     MEDCoupling::MEDCouplingMeshType meshType;
6824     std::string dummy2;
6825     MEDCoupling::MEDCouplingAxisType dummy3;
6826     MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dummy3,dt,it,dummy2);
6827     loadFromFile(fileName,ms.front());
6828 }
6829 catch(INTERP_KERNEL::Exception& e)
6830 {
6831     throw e;
6832 }
6833
6834 MEDFileMeshMultiTS::MEDFileMeshMultiTS(const std::string& fileName, const std::string& mName)
6835 try
6836 {
6837     loadFromFile(fileName,mName);
6838 }
6839 catch(INTERP_KERNEL::Exception& e)
6840 {
6841     throw e;
6842 }
6843
6844 MEDFileMeshes *MEDFileMeshes::New()
6845 {
6846   return new MEDFileMeshes;
6847 }
6848
6849 MEDFileMeshes *MEDFileMeshes::New(const std::string& fileName)
6850 {
6851   return new MEDFileMeshes(fileName);
6852 }
6853
6854 void MEDFileMeshes::write(med_idt fid) const
6855 {
6856   checkConsistencyLight();
6857   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++)
6858     {
6859       (*it)->copyOptionsFrom(*this);
6860       (*it)->write(fid);
6861     }
6862 }
6863
6864 void MEDFileMeshes::write(const std::string& fileName, int mode) const
6865 {
6866   med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode);
6867   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),medmod);
6868   std::ostringstream oss; oss << "MEDFileMesh : error on attempt to write in file : \"" << fileName << "\""; 
6869   MEDFileUtilities::CheckMEDCode(fid,fid,oss.str());
6870   checkConsistencyLight();
6871   write(fid);
6872 }
6873
6874 int MEDFileMeshes::getNumberOfMeshes() const
6875 {
6876   return _meshes.size();
6877 }
6878
6879 MEDFileMeshesIterator *MEDFileMeshes::iterator()
6880 {
6881   return new MEDFileMeshesIterator(this);
6882 }
6883
6884 /** Return a borrowed reference (caller is not responsible) */
6885 MEDFileMesh *MEDFileMeshes::getMeshAtPos(int i) const
6886 {
6887   if(i<0 || i>=(int)_meshes.size())
6888     {
6889       std::ostringstream oss; oss << "MEDFileMeshes::getMeshAtPos : invalid mesh id given in parameter ! Should be in [0;" << _meshes.size() << ") !";
6890       throw INTERP_KERNEL::Exception(oss.str().c_str());
6891     }
6892   return _meshes[i]->getOneTimeStep();
6893 }
6894
6895 /** Return a borrowed reference (caller is not responsible) */
6896 MEDFileMesh *MEDFileMeshes::getMeshWithName(const std::string& mname) const
6897 {
6898   std::vector<std::string> ms=getMeshesNames();
6899   std::vector<std::string>::iterator it=std::find(ms.begin(),ms.end(),mname);
6900   if(it==ms.end())
6901     {
6902       std::ostringstream oss; oss << "MEDFileMeshes::getMeshWithName : Mesh  \"" << mname << "\" does not exist in this ! Existing are : ";
6903       std::copy(ms.begin(),ms.end(),std::ostream_iterator<std::string>(oss," "));
6904       throw INTERP_KERNEL::Exception(oss.str().c_str());
6905     }
6906   return getMeshAtPos((int)std::distance(ms.begin(),it));
6907 }
6908
6909 std::vector<std::string> MEDFileMeshes::getMeshesNames() const
6910 {
6911   std::vector<std::string> ret(_meshes.size());
6912   int i=0;
6913   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
6914     {
6915       const MEDFileMeshMultiTS *f=(*it);
6916       if(f)
6917         {
6918           ret[i]=f->getName();
6919         }
6920       else
6921         {
6922           std::ostringstream oss; oss << "MEDFileMeshes::getMeshesNames : At rank #" << i << " mesh is not defined !";
6923           throw INTERP_KERNEL::Exception(oss.str().c_str());
6924         }
6925     }
6926   return ret;
6927 }
6928
6929 bool MEDFileMeshes::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab)
6930 {
6931   bool ret=false;
6932   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::iterator it=_meshes.begin();it!=_meshes.end();it++)
6933     {
6934       MEDFileMeshMultiTS *cur(*it);
6935       if(cur)
6936         ret=cur->changeNames(modifTab) || ret;
6937     }
6938   return ret;
6939 }
6940
6941 void MEDFileMeshes::cartesianizeMe()
6942 {
6943   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::iterator it=_meshes.begin();it!=_meshes.end();it++)
6944     {
6945       MEDFileMeshMultiTS *cur(*it);
6946       if(cur)
6947         cur->cartesianizeMe();
6948     }
6949 }
6950
6951 void MEDFileMeshes::resize(int newSize)
6952 {
6953   _meshes.resize(newSize);
6954 }
6955
6956 void MEDFileMeshes::pushMesh(MEDFileMesh *mesh)
6957 {
6958   if(!mesh)
6959     throw INTERP_KERNEL::Exception("MEDFileMeshes::pushMesh : invalid input pointer ! should be different from 0 !");
6960   MEDFileMeshMultiTS *elt=MEDFileMeshMultiTS::New();
6961   elt->setOneTimeStep(mesh);
6962   _meshes.push_back(elt);
6963 }
6964
6965 void MEDFileMeshes::setMeshAtPos(int i, MEDFileMesh *mesh)
6966 {
6967   if(!mesh)
6968     throw INTERP_KERNEL::Exception("MEDFileMeshes::setMeshAtPos : invalid input pointer ! should be different from 0 !");
6969   if(i>=(int)_meshes.size())
6970     _meshes.resize(i+1);
6971   MEDFileMeshMultiTS *elt=MEDFileMeshMultiTS::New();
6972   elt->setOneTimeStep(mesh);
6973   _meshes[i]=elt;
6974 }
6975
6976 void MEDFileMeshes::destroyMeshAtPos(int i)
6977 {
6978   if(i<0 || i>=(int)_meshes.size())
6979     {
6980       std::ostringstream oss; oss << "MEDFileMeshes::destroyMeshAtPos : Invalid given id in input (" << i << ") should be in [0," << _meshes.size() << ") !";
6981       throw INTERP_KERNEL::Exception(oss.str().c_str());
6982     }
6983   _meshes.erase(_meshes.begin()+i);
6984 }
6985
6986 void MEDFileMeshes::loadFromFile(const std::string& fileName)
6987 {
6988   std::vector<std::string> ms(MEDCoupling::GetMeshNames(fileName));
6989   int i=0;
6990   _meshes.resize(ms.size());
6991   for(std::vector<std::string>::const_iterator it=ms.begin();it!=ms.end();it++,i++)
6992     _meshes[i]=MEDFileMeshMultiTS::New(fileName,(*it));
6993 }
6994
6995 MEDFileMeshes::MEDFileMeshes()
6996 {
6997 }
6998
6999 MEDFileMeshes::MEDFileMeshes(const std::string& fileName)
7000 try
7001 {
7002     loadFromFile(fileName);
7003 }
7004 catch(INTERP_KERNEL::Exception& /*e*/)
7005 {
7006 }
7007
7008 MEDFileMeshes *MEDFileMeshes::deepCopy() const
7009 {
7010   std::vector< MCAuto<MEDFileMeshMultiTS> > meshes(_meshes.size());
7011   std::size_t i=0;
7012   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
7013     if((const MEDFileMeshMultiTS *)*it)
7014       meshes[i]=(*it)->deepCopy();
7015   MCAuto<MEDFileMeshes> ret=MEDFileMeshes::New();
7016   ret->_meshes=meshes;
7017   return ret.retn();
7018 }
7019
7020 std::size_t MEDFileMeshes::getHeapMemorySizeWithoutChildren() const
7021 {
7022   return _meshes.capacity()*(sizeof(MCAuto<MEDFileMeshMultiTS>));
7023 }
7024
7025 std::vector<const BigMemoryObject *> MEDFileMeshes::getDirectChildrenWithNull() const
7026 {
7027   std::vector<const BigMemoryObject *> ret;
7028   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++)
7029     ret.push_back((const MEDFileMeshMultiTS *)*it);
7030   return ret;
7031 }
7032
7033 std::string MEDFileMeshes::simpleRepr() const
7034 {
7035   std::ostringstream oss;
7036   oss << "(*****************)\n(* MEDFileMeshes *)\n(*****************)\n\n";
7037   simpleReprWithoutHeader(oss);
7038   return oss.str();
7039 }
7040
7041 void MEDFileMeshes::simpleReprWithoutHeader(std::ostream& oss) const
7042 {
7043   int nbOfMeshes=getNumberOfMeshes();
7044   oss << "There are " << nbOfMeshes << " meshes with the following names : \n";
7045   std::vector<std::string> mns=getMeshesNames();
7046   for(int i=0;i<nbOfMeshes;i++)
7047     oss << "  - #" << i << " \"" << mns[i] << "\"\n";
7048 }
7049
7050 void MEDFileMeshes::checkConsistencyLight() const
7051 {
7052   static const char MSG[]="MEDFileMeshes::checkConsistencyLight : mesh at rank ";
7053   int i=0;
7054   std::set<std::string> s;
7055   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
7056     {
7057       const MEDFileMeshMultiTS *elt=(*it);
7058       if(!elt)
7059         {
7060           std::ostringstream oss; oss << MSG << i << "/" << _meshes.size() << " is empty !";
7061           throw INTERP_KERNEL::Exception(oss.str().c_str());
7062         }
7063       std::size_t sz=s.size();
7064       s.insert(std::string((*it)->getName()));
7065       if(s.size()==sz)
7066         {
7067           std::ostringstream oss; oss << MSG << i << " has a name (\"" << (*it)->getName() << "\") already used by an another mesh in list !";
7068           throw INTERP_KERNEL::Exception(oss.str().c_str());
7069         }
7070     }
7071 }
7072
7073 MEDFileMeshesIterator::MEDFileMeshesIterator(MEDFileMeshes *ms):_ms(ms),_iter_id(0),_nb_iter(0)
7074 {
7075   if(ms)
7076     {
7077       ms->incrRef();
7078       _nb_iter=ms->getNumberOfMeshes();
7079     }
7080 }
7081
7082 MEDFileMeshesIterator::~MEDFileMeshesIterator()
7083 {
7084 }
7085
7086 MEDFileMesh *MEDFileMeshesIterator::nextt()
7087 {
7088   if(_iter_id<_nb_iter)
7089     {
7090       MEDFileMeshes *ms(_ms);
7091       if(ms)
7092         return ms->getMeshAtPos(_iter_id++);
7093       else
7094         return 0;
7095     }
7096   else
7097     return 0;
7098 }