]> SALOME platform Git repositories - tools/medcoupling.git/blob - src/MEDLoader/MEDFileMesh.cxx
Salome HOME
Doc fix and enhancement.
[tools/medcoupling.git] / src / MEDLoader / MEDFileMesh.cxx
1 // Copyright (C) 2007-2015  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.
3784  *  After this operation a top-level cell bordering the group will loose some neighbors (typically the cell which is  on the
3785  *  other side of the group is no more a neighbor)
3786  *   - finally, the connectivity of (part of) the top level-cells bordering the group is also modified so that some cells
3787  *  bordering the newly created boundary use the newly computed nodes.
3788  *  Finally note that optional cell numbers are also affected by this method and might become invalid for SMESH.
3789  *  Use clearNodeAndCellNumbers() afterwards to ensure a proper SMESH loading.
3790  *
3791  *  \param[in] grpNameM1 name of the (-1)-level group defining the boundary
3792  *  \param[out] nodesDuplicated ids of the initial nodes which have been duplicated (and whose copy is put at the end of
3793  *  the coord array)
3794  *  \param[out] cellsModified ids of the cells whose connectivity has been modified (to use the newly created nodes)
3795  *  \param[out] cellsNotModified ids of the rest of cells bordering the new boundary whose connectivity remains unchanged.
3796  *  \sa clearNodeAndCellNumbers()
3797  */
3798 void MEDFileUMesh::buildInnerBoundaryAlongM1Group(const std::string& grpNameM1, DataArrayInt *&nodesDuplicated,
3799                                            DataArrayInt *&cellsModified, DataArrayInt *&cellsNotModified)
3800 {
3801   std::vector<int> levs=getNonEmptyLevels();
3802   if(std::find(levs.begin(),levs.end(),0)==levs.end() || std::find(levs.begin(),levs.end(),-1)==levs.end())
3803     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildInnerBoundaryAlongM1Group : This method works only for mesh definied on level 0 and -1 !");
3804   MCAuto<MEDCouplingUMesh> m0=getMeshAtLevel(0);
3805   MCAuto<MEDCouplingUMesh> m1=getMeshAtLevel(-1);
3806   int nbNodes=m0->getNumberOfNodes();
3807   MCAuto<MEDCouplingUMesh> m11=getGroup(-1,grpNameM1);
3808   DataArrayInt *tmp00=0,*tmp11=0,*tmp22=0;
3809   m0->findNodesToDuplicate(*m11,tmp00,tmp11,tmp22);
3810   MCAuto<DataArrayInt> nodeIdsToDuplicate(tmp00);
3811   MCAuto<DataArrayInt> cellsToModifyConn0(tmp11);
3812   MCAuto<DataArrayInt> cellsToModifyConn1(tmp22);
3813   MCAuto<MEDCouplingUMesh> tmp0=static_cast<MEDCouplingUMesh *>(m0->buildPartOfMySelf(cellsToModifyConn0->begin(),cellsToModifyConn0->end(),true));
3814   // node renumbering of cells in m1 impacted by duplication of node but not in group 'grpNameM1' on level -1
3815   MCAuto<DataArrayInt> descTmp0=DataArrayInt::New(),descITmp0=DataArrayInt::New(),revDescTmp0=DataArrayInt::New(),revDescITmp0=DataArrayInt::New();
3816   MCAuto<MEDCouplingUMesh> tmp0Desc=tmp0->buildDescendingConnectivity(descTmp0,descITmp0,revDescTmp0,revDescITmp0);
3817   descTmp0=0; descITmp0=0; revDescTmp0=0; revDescITmp0=0;
3818   MCAuto<DataArrayInt> cellsInM1ToRenumW2=tmp0Desc->getCellIdsLyingOnNodes(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),false);
3819   MCAuto<MEDCouplingUMesh> cellsInM1ToRenumW3=static_cast<MEDCouplingUMesh *>(tmp0Desc->buildPartOfMySelf(cellsInM1ToRenumW2->begin(),cellsInM1ToRenumW2->end(),true));
3820   DataArrayInt *cellsInM1ToRenumW4Tmp=0;
3821   m1->areCellsIncludedIn(cellsInM1ToRenumW3,2,cellsInM1ToRenumW4Tmp);
3822   MCAuto<DataArrayInt> cellsInM1ToRenumW4(cellsInM1ToRenumW4Tmp);
3823   MCAuto<DataArrayInt> cellsInM1ToRenumW5=cellsInM1ToRenumW4->findIdsInRange(0,m1->getNumberOfCells());
3824   cellsInM1ToRenumW5->transformWithIndArr(cellsInM1ToRenumW4->begin(),cellsInM1ToRenumW4->end());
3825   MCAuto<DataArrayInt> grpIds=getGroupArr(-1,grpNameM1);
3826   MCAuto<DataArrayInt> cellsInM1ToRenum=cellsInM1ToRenumW5->buildSubstraction(grpIds);
3827   MCAuto<MEDCouplingUMesh> m1Part=static_cast<MEDCouplingUMesh *>(m1->buildPartOfMySelf(cellsInM1ToRenum->begin(),cellsInM1ToRenum->end(),true));
3828   m1Part->duplicateNodesInConn(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),nbNodes);
3829   m1->setPartOfMySelf(cellsInM1ToRenum->begin(),cellsInM1ToRenum->end(),*m1Part);
3830   // end of node renumbering of cells in m1 impacted by duplication of node but not in group of level -1 'grpNameM1'
3831   tmp0->duplicateNodes(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end());
3832   m0->setCoords(tmp0->getCoords());
3833   m0->setPartOfMySelf(cellsToModifyConn0->begin(),cellsToModifyConn0->end(),*tmp0);
3834   m1->setCoords(m0->getCoords());
3835   _coords=m0->getCoords(); _coords->incrRef();
3836   // duplication of cells in group 'grpNameM1' on level -1
3837   m11->duplicateNodesInConn(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),nbNodes); m11->setCoords(m0->getCoords());
3838   std::vector<const MEDCouplingUMesh *> v(2); v[0]=m1; v[1]=m11;
3839   MCAuto<MEDCouplingUMesh> newm1=MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(v,tmp00,tmp11);
3840   MCAuto<DataArrayInt> szOfCellGrpOfSameType(tmp00);
3841   MCAuto<DataArrayInt> idInMsOfCellGrpOfSameType(tmp11);
3842   //
3843   newm1->setName(getName());
3844   const DataArrayInt *fam=getFamilyFieldAtLevel(-1);
3845   if(!fam)
3846     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildInnerBoundaryAlongM1Group : internal problem !");
3847   MCAuto<DataArrayInt> newFam=DataArrayInt::New();
3848   newFam->alloc(newm1->getNumberOfCells(),1);
3849   // Get a new family ID: care must be taken if we need a positive ID or a negative one:
3850   // Positive ID for family of nodes, negative for all the rest.
3851   int idd;
3852   if (m1->getMeshDimension() == 0)
3853     idd=getMaxFamilyId()+1;
3854   else
3855     idd=getMinFamilyId()-1;
3856   int globStart=0,start=0,end,globEnd;
3857   int nbOfChunks=szOfCellGrpOfSameType->getNumberOfTuples();
3858   for(int i=0;i<nbOfChunks;i++)
3859     {
3860       globEnd=globStart+szOfCellGrpOfSameType->getIJ(i,0);
3861       if(idInMsOfCellGrpOfSameType->getIJ(i,0)==0)
3862         {
3863           end=start+szOfCellGrpOfSameType->getIJ(i,0);
3864           MCAuto<DataArrayInt> part=fam->selectByTupleIdSafeSlice(start,end,1);
3865           newFam->setPartOfValues1(part,globStart,globEnd,1,0,1,1,true);
3866           start=end;
3867         }
3868       else
3869         {
3870           newFam->setPartOfValuesSimple1(idd,globStart,globEnd,1,0,1,1);
3871         }
3872       globStart=globEnd;
3873     }
3874   newm1->setCoords(getCoords());
3875   setMeshAtLevel(-1,newm1);
3876   setFamilyFieldArr(-1,newFam);
3877   std::string grpName2(grpNameM1); grpName2+="_dup";
3878   addFamily(grpName2,idd);
3879   addFamilyOnGrp(grpName2,grpName2);
3880   //
3881   fam=_fam_coords;
3882   if(fam)
3883     {
3884       int newNbOfNodes=getCoords()->getNumberOfTuples();
3885       newFam=DataArrayInt::New(); newFam->alloc(newNbOfNodes,1);
3886       newFam->setPartOfValues1(fam,0,nbNodes,1,0,1,1,true);
3887       newFam->setPartOfValuesSimple1(0,nbNodes,newNbOfNodes,1,0,1,1);
3888       _fam_coords=newFam;
3889     }
3890
3891   nodesDuplicated=nodeIdsToDuplicate.retn();
3892   cellsModified=cellsToModifyConn0.retn();
3893   cellsNotModified=cellsToModifyConn1.retn();
3894 }
3895
3896 /*! Similar to MEDCouplingUMesh::unPolyze():  converts all polygons (if \a this is a 2D mesh) or polyhedrons
3897  * (if \a this is a 3D mesh) to cells of classical types. The cells remain correctly sorted by geometric type
3898  * in this method.
3899  *
3900  * \param [out] oldCode retrieves the distribution of types before the call if true is returned
3901  * \param [out] newCode etrieves the distribution of types after the call if true is returned
3902  * \param [out] o2nRenumCell tells for **all levels** the old 2 new renumbering of cells.
3903  * 
3904  * \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.
3905  * 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.
3906  */
3907 bool MEDFileUMesh::unPolyze(std::vector<int>& oldCode, std::vector<int>& newCode, DataArrayInt *& o2nRenumCell)
3908 {
3909   o2nRenumCell=0; oldCode.clear(); newCode.clear();
3910   std::vector<int> levs=getNonEmptyLevels();
3911   bool ret=false;
3912   std::vector< const DataArrayInt* > renumCellsSplited;//same than memorySaverIfThrow
3913   std::vector< MCAuto<DataArrayInt> > memorySaverIfThrow;//same than renumCellsSplited only in case of throw
3914   int start=0;
3915   int end=0;
3916   for(std::vector<int>::reverse_iterator it=levs.rbegin();it!=levs.rend();it++)
3917     {
3918       MCAuto<MEDCouplingUMesh> m=getMeshAtLevel(*it);
3919       std::vector<int> code1=m->getDistributionOfTypes();
3920       end=PutInThirdComponentOfCodeOffset(code1,start);
3921       oldCode.insert(oldCode.end(),code1.begin(),code1.end());
3922       bool hasChanged=m->unPolyze();
3923       DataArrayInt *fake=0;
3924       MCAuto<DataArrayInt> o2nCellsPart=m->getLevArrPerCellTypes(MEDCouplingUMesh::MEDMEM_ORDER,
3925           MEDCouplingUMesh::MEDMEM_ORDER+MEDCouplingUMesh::N_MEDMEM_ORDER,fake);
3926       fake->decrRef();
3927       renumCellsSplited.push_back(o2nCellsPart); memorySaverIfThrow.push_back(o2nCellsPart);
3928       if(hasChanged)
3929         {
3930           MCAuto<DataArrayInt> o2nCellsPart2=o2nCellsPart->buildPermArrPerLevel();
3931           m->renumberCells(o2nCellsPart2->getConstPointer(),false);
3932           ret=true;
3933           MCAuto<DataArrayInt> famField2,numField2;
3934           const DataArrayInt *famField=getFamilyFieldAtLevel(*it); if(famField) { famField->incrRef(); famField2=const_cast<DataArrayInt *>(famField); }
3935           const DataArrayInt *numField=getNumberFieldAtLevel(*it); if(numField) { numField->incrRef(); numField2=const_cast<DataArrayInt *>(numField); }
3936           setMeshAtLevel(*it,m);
3937           std::vector<int> code2=m->getDistributionOfTypes();
3938           end=PutInThirdComponentOfCodeOffset(code2,start);
3939           newCode.insert(newCode.end(),code2.begin(),code2.end());
3940           //
3941           if(o2nCellsPart2->isIota(o2nCellsPart2->getNumberOfTuples()))
3942             continue;
3943           if(famField)
3944             {
3945               MCAuto<DataArrayInt> newFamField=famField->renumber(o2nCellsPart2->getConstPointer());
3946               setFamilyFieldArr(*it,newFamField);
3947             }
3948           if(numField)
3949             {
3950               MCAuto<DataArrayInt> newNumField=numField->renumber(o2nCellsPart2->getConstPointer());
3951               setRenumFieldArr(*it,newNumField);
3952             }
3953         }
3954       else
3955         {
3956           newCode.insert(newCode.end(),code1.begin(),code1.end());
3957         }
3958       start=end;
3959     }
3960   if(ret)
3961     {
3962       MCAuto<DataArrayInt> renumCells=DataArrayInt::Aggregate(renumCellsSplited);
3963       MCAuto<DataArrayInt> o2nRenumCellRet=renumCells->buildPermArrPerLevel();
3964       o2nRenumCell=o2nRenumCellRet.retn();
3965     }
3966   return ret;
3967 }
3968
3969 /*! \cond HIDDEN_ITEMS */
3970 struct MEDLoaderAccVisit1
3971 {
3972   MEDLoaderAccVisit1():_new_nb_of_nodes(0) { }
3973   int operator()(bool val) { return val?_new_nb_of_nodes++:-1; }
3974   int _new_nb_of_nodes;
3975 };
3976 /*! \endcond */
3977
3978 /*!
3979  * 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.
3980  * The maximum value stored in returned array is the number of nodes of \a this minus 1 after call of this method.
3981  * The size of returned array is the number of nodes of the old (previous to the call of this method) number of nodes.
3982  * -1 values in returned array means that the corresponding old node is no more used.
3983  *
3984  * \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
3985  *         is modified in \a this.
3986  * \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
3987  *  set coordinates.
3988  */
3989 DataArrayInt *MEDFileUMesh::zipCoords()
3990 {
3991   const DataArrayDouble *coo(getCoords());
3992   if(!coo)
3993     throw INTERP_KERNEL::Exception("MEDFileUMesh::zipCoords : no coordinates set in this !");
3994   int nbOfNodes(coo->getNumberOfTuples());
3995   std::vector<bool> nodeIdsInUse(nbOfNodes,false);
3996   std::vector<int> neLevs(getNonEmptyLevels());
3997   for(std::vector<int>::const_iterator lev=neLevs.begin();lev!=neLevs.end();lev++)
3998     {
3999       const MEDFileUMeshSplitL1 *zeLev(getMeshAtLevSafe(*lev));
4000       if(zeLev->isMeshStoredSplitByType())
4001         {
4002           std::vector<MEDCoupling1GTUMesh *> ms(zeLev->getDirectUndergroundSingleGeoTypeMeshes());
4003           for(std::vector<MEDCoupling1GTUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
4004             if(*it)
4005               (*it)->computeNodeIdsAlg(nodeIdsInUse);
4006         }
4007       else
4008         {
4009           MCAuto<MEDCouplingUMesh> mesh(zeLev->getWholeMesh(false));
4010           mesh->computeNodeIdsAlg(nodeIdsInUse);
4011         }
4012     }
4013   int nbrOfNodesInUse((int)std::count(nodeIdsInUse.begin(),nodeIdsInUse.end(),true));
4014   if(nbrOfNodesInUse==nbOfNodes)
4015     return 0;//no need to update _part_coords
4016   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodes,1);
4017   std::transform(nodeIdsInUse.begin(),nodeIdsInUse.end(),ret->getPointer(),MEDLoaderAccVisit1());
4018   MCAuto<DataArrayInt> ret2(ret->invertArrayO2N2N2OBis(nbrOfNodesInUse));
4019   MCAuto<DataArrayDouble> newCoords(coo->selectByTupleIdSafe(ret2->begin(),ret2->end()));
4020   MCAuto<DataArrayInt> newFamCoords;
4021   MCAuto<DataArrayAsciiChar> newNameCoords;
4022   if((const DataArrayInt *)_fam_coords)
4023     newFamCoords=_fam_coords->selectByTupleIdSafe(ret2->begin(),ret2->end());
4024   MCAuto<DataArrayInt> newNumCoords;
4025   if((const DataArrayInt *)_num_coords)
4026     newNumCoords=_num_coords->selectByTupleIdSafe(ret2->begin(),ret2->end());
4027   if((const DataArrayAsciiChar *)_name_coords)
4028     newNameCoords=static_cast<DataArrayAsciiChar *>(_name_coords->selectByTupleIdSafe(ret2->begin(),ret2->end()));
4029   _coords=newCoords; _fam_coords=newFamCoords; _num_coords=newNumCoords; _name_coords=newNameCoords; _rev_num_coords=0;
4030   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
4031     {
4032       if((MEDFileUMeshSplitL1*)*it)
4033         {
4034           (*it)->renumberNodesInConn(ret->begin());
4035           (*it)->setCoords(_coords);
4036         }
4037     }
4038   // updates _part_coords
4039   const PartDefinition *pc(_part_coords);
4040   if(pc)
4041     {
4042       MCAuto<PartDefinition> tmpPD(DataArrayPartDefinition::New(ret2));
4043       _part_coords=tmpPD->composeWith(pc);
4044     }
4045   return ret.retn();
4046 }
4047
4048 /*!
4049  * This method performs an extrusion along a path defined by \a m1D.
4050  * \a this is expected to be a mesh with max mesh dimension equal to 2.
4051  * \a m1D is expected to be a mesh with space dimesion equal to 3 and mesh dimension equal to 1.
4052  * Mesh dimensions of returned mesh is incremented by one compared to thoose in \a this.
4053  * This method scans all levels in \a this
4054  * and put them in the returned mesh. All groups in \a this are also put in the returned mesh.
4055  *
4056  * \param [in] m1D - the mesh defining the extrusion path.
4057  * \param [in] policy - defines the policy of extrusion (see MEDCouplingUMesh::buildExtrudedMesh for more details)
4058  * \return - a new reference on mesh (you have to deal with using decrRef). The returned mesh will have the same name than \a this.
4059  *
4060  * \sa MEDCouplingUMesh::buildExtrudedMesh
4061  */
4062 MEDFileUMesh *MEDFileUMesh::buildExtrudedMesh(const MEDCouplingUMesh *m1D, int policy) const
4063 {
4064   checkCartesian();
4065   if(getMeshDimension()!=2)
4066     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildExtrudedMesh : this is expected to be with mesh dimension equal to 2 !");
4067   MCAuto<MEDFileUMesh> ret(MEDFileUMesh::New());
4068   m1D->checkConsistencyLight();
4069   if(m1D->getMeshDimension()!=1)
4070     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildExtrudedMesh : input mesh must have a mesh dimension equal to one !");
4071   int nbRep(m1D->getNumberOfCells());
4072   std::vector<int> levs(getNonEmptyLevels());
4073   std::vector<std::string> grps(getGroupsNames());
4074   std::vector< MCAuto<MEDCouplingUMesh> > zeList;
4075   DataArrayDouble *coords(0);
4076   std::size_t nbOfLevsOut(levs.size()+1);
4077   std::vector< MCAuto<DataArrayInt> > o2ns(nbOfLevsOut);
4078   for(std::vector<int>::const_iterator lev=levs.begin();lev!=levs.end();lev++)
4079     {
4080       MCAuto<MEDCouplingUMesh> item(getMeshAtLevel(*lev));
4081       item=item->clone(false);
4082       item->changeSpaceDimension(3+(*lev),0.);//no problem non const but change DataArrayDouble for coordinates do not alter data
4083       MCAuto<MEDCouplingUMesh> tmp(static_cast<MEDCouplingUMesh *>(m1D->deepCopy()));
4084       tmp->changeSpaceDimension(3+(*lev),0.);
4085       MCAuto<MEDCouplingUMesh> elt(item->buildExtrudedMesh(tmp,policy));
4086       zeList.push_back(elt);
4087       if(*lev==0)
4088         coords=elt->getCoords();
4089     }
4090   if(!coords)
4091     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildExtrudedMesh : internal error !");
4092   for(std::vector< MCAuto<MEDCouplingUMesh> >::iterator it=zeList.begin();it!=zeList.end();it++)
4093     {
4094       (*it)->setName(getName());
4095       (*it)->setCoords(coords);
4096     }
4097   for(std::size_t ii=0;ii!=zeList.size();ii++)
4098     {
4099       int lev(levs[ii]);
4100       MCAuto<MEDCouplingUMesh> elt(zeList[ii]);
4101       if(lev<=-1)
4102         {
4103           MCAuto<MEDCouplingUMesh> elt1(getMeshAtLevel(lev+1));
4104           MCAuto<MEDCouplingUMesh> elt2(elt1->clone(false));
4105           MCAuto<DataArrayInt> tmp(elt2->getNodalConnectivity()->deepCopy());
4106           elt2->setConnectivity(tmp,elt2->getNodalConnectivityIndex());
4107           elt2->shiftNodeNumbersInConn(nbRep*elt1->getNumberOfNodes());
4108           elt1->setCoords(elt->getCoords()); elt2->setCoords(elt->getCoords());
4109           std::vector<const MEDCouplingUMesh *> elts(3);
4110           elts[0]=elt; elts[1]=elt1; elts[2]=elt2;
4111           elt=MEDCouplingUMesh::MergeUMeshesOnSameCoords(elts);
4112           elt->setName(getName());
4113         }
4114       //
4115       o2ns[ii]=elt->sortCellsInMEDFileFrmt();
4116       ret->setMeshAtLevel(lev,elt);
4117     }
4118   MCAuto<MEDCouplingUMesh> endLev(getMeshAtLevel(levs.back())),endLev2;
4119   endLev=endLev->clone(false); endLev->setCoords(coords);
4120   MCAuto<DataArrayInt> tmp(endLev->getNodalConnectivity()->deepCopy());
4121   endLev2=endLev->clone(false); endLev2->setConnectivity(tmp,endLev->getNodalConnectivityIndex());
4122   endLev2->shiftNodeNumbersInConn(nbRep*getNumberOfNodes());
4123   endLev=MEDCouplingUMesh::MergeUMeshesOnSameCoords(endLev,endLev2);
4124   o2ns[levs.size()]=endLev->sortCellsInMEDFileFrmt();
4125   endLev->setName(getName());
4126   ret->setMeshAtLevel(levs.back()-1,endLev);
4127   //
4128   for(std::size_t ii=0;ii!=zeList.size();ii++)
4129     {
4130       int lev(levs[ii]);
4131       std::vector< MCAuto<DataArrayInt> > outGrps;
4132       std::vector< const DataArrayInt * > outGrps2;
4133       if(lev<=-1)
4134         {
4135           for(std::vector<std::string>::const_iterator grp=grps.begin();grp!=grps.end();grp++)
4136             {
4137               MCAuto<DataArrayInt> grpArr(getGroupArr(lev+1,*grp));
4138               if(!grpArr->empty())
4139                 {
4140                   MCAuto<DataArrayInt> grpArr1(grpArr->deepCopy()),grpArr2(grpArr->deepCopy());
4141                   int offset0(zeList[ii]->getNumberOfCells());
4142                   int offset1(offset0+getNumberOfCellsAtLevel(lev+1));
4143                   grpArr1->applyLin(1,offset0); grpArr2->applyLin(1,offset1);
4144                   std::ostringstream oss; oss << grpArr2->getName() << "_top";
4145                   grpArr2->setName(oss.str());
4146                   grpArr1->transformWithIndArr(o2ns[ii]->begin(),o2ns[ii]->end());
4147                   grpArr2->transformWithIndArr(o2ns[ii]->begin(),o2ns[ii]->end());
4148                   outGrps.push_back(grpArr1); outGrps.push_back(grpArr2);
4149                   outGrps2.push_back(grpArr1); outGrps2.push_back(grpArr2);
4150                 }
4151             }
4152         }
4153       //
4154       for(std::vector<std::string>::const_iterator grp=grps.begin();grp!=grps.end();grp++)
4155         {
4156           MCAuto<DataArrayInt> grpArr(getGroupArr(lev,*grp));
4157           if(!grpArr->empty())
4158             {
4159               int nbCellsB4Extrusion(getNumberOfCellsAtLevel(lev));
4160               std::vector< MCAuto<DataArrayInt> > grpArrs(nbRep);
4161               std::vector< const DataArrayInt *> grpArrs2(nbRep);
4162               for(int iii=0;iii<nbRep;iii++)
4163                 {
4164                   grpArrs[iii]=grpArr->deepCopy(); grpArrs[iii]->applyLin(1,iii*nbCellsB4Extrusion);
4165                   grpArrs2[iii]=grpArrs[iii];
4166                 }
4167               MCAuto<DataArrayInt> grpArrExt(DataArrayInt::Aggregate(grpArrs2));
4168               grpArrExt->transformWithIndArr(o2ns[ii]->begin(),o2ns[ii]->end());
4169               std::ostringstream grpName; grpName << *grp << "_extruded";
4170               grpArrExt->setName(grpName.str());
4171               outGrps.push_back(grpArrExt);
4172               outGrps2.push_back(grpArrExt);
4173             }
4174         }
4175       ret->setGroupsAtLevel(lev,outGrps2);
4176     }
4177   std::vector< MCAuto<DataArrayInt> > outGrps;
4178   std::vector< const DataArrayInt * > outGrps2;
4179   for(std::vector<std::string>::const_iterator grp=grps.begin();grp!=grps.end();grp++)
4180     {
4181       MCAuto<DataArrayInt> grpArr1(getGroupArr(levs.back(),*grp));
4182       if(grpArr1->empty())
4183         continue;
4184       MCAuto<DataArrayInt> grpArr2(grpArr1->deepCopy());
4185       std::ostringstream grpName; grpName << *grp << "_top";
4186       grpArr2->setName(grpName.str());
4187       grpArr2->applyLin(1,getNumberOfCellsAtLevel(levs.back()));
4188       outGrps.push_back(grpArr1); outGrps.push_back(grpArr2);
4189       outGrps2.push_back(grpArr1); outGrps2.push_back(grpArr2);
4190     }
4191   ret->setGroupsAtLevel(levs.back()-1,outGrps2);
4192   return ret.retn();
4193 }
4194
4195 /*!
4196  * This method converts all linear cells in \a this into quadratic cells (following the \a conversionType policy).
4197  * All the cells converted are put in the returned instance. This method applies all the groups and families in \a this to returned instance.
4198  * Groups on nodes and families on nodes are copied directly to the returned instance without transformation.
4199  *
4200  * \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
4201  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
4202  * \param [in] eps - detection threshold for coordinates.
4203  * \return A new instance that is the result of the conversion. The caller has the ownership of this returned instance.
4204  *
4205  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic , quadraticToLinear
4206  */
4207 MEDFileUMesh *MEDFileUMesh::linearToQuadratic(int conversionType, double eps) const
4208 {
4209   checkCartesian();
4210   MCAuto<MEDFileUMesh> ret(MEDFileUMesh::New());
4211   int initialNbNodes(getNumberOfNodes());
4212   MCAuto<MEDCouplingUMesh> m0Tmp(getMeshAtLevel(0));
4213   MCAuto<MEDCouplingUMesh> m0(dynamic_cast<MEDCouplingUMesh *>(m0Tmp->deepCopy()));
4214   {
4215     MCAuto<DataArrayInt> notUsed(m0->convertLinearCellsToQuadratic(conversionType));
4216   }
4217   DataArrayDouble *zeCoords(m0->getCoords());
4218   ret->setMeshAtLevel(0,m0);
4219   std::vector<int> levs(getNonEmptyLevels());
4220   const DataArrayInt *famField(getFamilyFieldAtLevel(0));
4221   if(famField)
4222     {
4223       MCAuto<DataArrayInt> famFieldCpy(famField->deepCopy());
4224       ret->setFamilyFieldArr(0,famFieldCpy);
4225     }
4226   famField=getFamilyFieldAtLevel(1);
4227   if(famField)
4228     {
4229       MCAuto<DataArrayInt> fam(DataArrayInt::New()); fam->alloc(zeCoords->getNumberOfTuples(),1);
4230       fam->fillWithZero();
4231       fam->setPartOfValues1(famField,0,initialNbNodes,1,0,1,1);
4232       ret->setFamilyFieldArr(1,fam);
4233     }
4234   ret->copyFamGrpMapsFrom(*this);
4235   MCAuto<DataArrayDouble> partZeCoords(zeCoords->selectByTupleIdSafeSlice(initialNbNodes,zeCoords->getNumberOfTuples(),1));
4236   for(std::vector<int>::const_iterator lev=levs.begin();lev!=levs.end();lev++)
4237     {
4238       if(*lev==0)
4239         continue;
4240       MCAuto<MEDCouplingUMesh> m1Tmp(getMeshAtLevel(*lev));
4241       MCAuto<MEDCouplingUMesh> m1(dynamic_cast<MEDCouplingUMesh *>(m1Tmp->deepCopy()));
4242       if(m1->getMeshDimension()!=0)
4243         {
4244           {
4245             MCAuto<DataArrayInt> notUsed(m1->convertLinearCellsToQuadratic(conversionType));
4246           }//kill unused notUsed var
4247           MCAuto<DataArrayDouble> m1Coords(m1->getCoords()->selectByTupleIdSafeSlice(initialNbNodes,m1->getNumberOfNodes(),1));
4248           DataArrayInt *b(0);
4249           bool a(partZeCoords->areIncludedInMe(m1Coords,eps,b));
4250           MCAuto<DataArrayInt> bSafe(b);
4251           if(!a)
4252             {
4253               std::ostringstream oss; oss << "MEDFileUMesh::linearCellsToQuadratic : for level " << *lev << " problem to identify nodes generated !";
4254               throw INTERP_KERNEL::Exception(oss.str().c_str());
4255             }
4256           b->applyLin(1,initialNbNodes);
4257           MCAuto<DataArrayInt> l0(DataArrayInt::New()); l0->alloc(initialNbNodes,1); l0->iota();
4258           std::vector<const DataArrayInt *> v(2); v[0]=l0; v[1]=b;
4259           MCAuto<DataArrayInt> renum(DataArrayInt::Aggregate(v));
4260           m1->renumberNodesInConn(renum->begin());
4261         }
4262       m1->setCoords(zeCoords);
4263       ret->setMeshAtLevel(*lev,m1);
4264       famField=getFamilyFieldAtLevel(*lev);
4265       if(famField)
4266         {
4267           MCAuto<DataArrayInt> famFieldCpy(famField->deepCopy());
4268           ret->setFamilyFieldArr(*lev,famFieldCpy);
4269         }
4270     }
4271   return ret.retn();
4272 }
4273
4274 /*!
4275  * This method converts all quadratic cells in \a this into linear cells.
4276  * All the cells converted are put in the returned instance. This method applies all the groups and families in \a this to returned instance.
4277  * Groups on nodes and families on nodes are copied directly to the returned instance without transformation.
4278  *
4279  * \param [in] eps - detection threshold for coordinates.
4280  * \return A new instance that is the result of the conversion. The caller has the ownership of this returned instance.
4281  *
4282  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic , linearToQuadratic
4283  */
4284 MEDFileUMesh *MEDFileUMesh::quadraticToLinear(double eps) const
4285 {
4286   checkCartesian();
4287   MCAuto<MEDFileUMesh> ret(MEDFileUMesh::New());
4288   MCAuto<MEDCouplingUMesh> m0Tmp(getMeshAtLevel(0));
4289   MCAuto<MEDCouplingUMesh> m0(dynamic_cast<MEDCouplingUMesh *>(m0Tmp->deepCopy()));
4290   m0->convertQuadraticCellsToLinear();
4291   m0->zipCoords();
4292   DataArrayDouble *zeCoords(m0->getCoords());
4293   ret->setMeshAtLevel(0,m0);
4294   std::vector<int> levs(getNonEmptyLevels());
4295   const DataArrayInt *famField(getFamilyFieldAtLevel(0));
4296   if(famField)
4297     {
4298       MCAuto<DataArrayInt> famFieldCpy(famField->deepCopy());
4299       ret->setFamilyFieldArr(0,famFieldCpy);
4300     }
4301   famField=getFamilyFieldAtLevel(1);
4302   if(famField)
4303     {
4304       MCAuto<DataArrayInt> fam(famField->selectByTupleIdSafeSlice(0,zeCoords->getNumberOfTuples(),1));
4305       ret->setFamilyFieldArr(1,fam);
4306     }
4307   ret->copyFamGrpMapsFrom(*this);
4308   for(std::vector<int>::const_iterator lev=levs.begin();lev!=levs.end();lev++)
4309     {
4310       if(*lev==0)
4311         continue;
4312       MCAuto<MEDCouplingUMesh> m1Tmp(getMeshAtLevel(*lev));
4313       MCAuto<MEDCouplingUMesh> m1(dynamic_cast<MEDCouplingUMesh *>(m1Tmp->deepCopy()));
4314       m1->convertQuadraticCellsToLinear();
4315       m1->zipCoords();
4316       DataArrayInt *b(0);
4317       bool a(zeCoords->areIncludedInMe(m1->getCoords(),eps,b));
4318       MCAuto<DataArrayInt> bSafe(b);
4319       if(!a)
4320         {
4321           std::ostringstream oss; oss << "MEDFileUMesh::quadraticToLinear : for level " << *lev << " problem to identify nodes generated !";
4322           throw INTERP_KERNEL::Exception(oss.str().c_str());
4323         }
4324       m1->renumberNodesInConn(b->begin());
4325       m1->setCoords(zeCoords);
4326       ret->setMeshAtLevel(*lev,m1);
4327       famField=getFamilyFieldAtLevel(*lev);
4328       if(famField)
4329         {
4330           MCAuto<DataArrayInt> famFieldCpy(famField->deepCopy());
4331           ret->setFamilyFieldArr(*lev,famFieldCpy);
4332         }
4333     }
4334   return ret.retn();
4335 }
4336
4337 void MEDFileUMesh::serialize(std::vector<double>& tinyDouble, std::vector<int>& tinyInt, std::vector<std::string>& tinyStr, std::vector< MCAuto<DataArrayInt> >& bigArraysI, MCAuto<DataArrayDouble>& bigArrayD)
4338 {
4339   clearNonDiscrAttributes();
4340   forceComputationOfParts();
4341   tinyDouble.clear(); tinyInt.clear(); tinyStr.clear(); bigArraysI.clear(); bigArrayD=0;
4342   std::vector<int> layer0;
4343   layer0.push_back(getAxisType());//0 i
4344   layer0.push_back(_order); //1 i
4345   layer0.push_back(_iteration);//2 i
4346   layer0.push_back(getSpaceDimension());//3 i
4347   tinyDouble.push_back(_time);//0 d
4348   tinyStr.push_back(_name);//0 s
4349   tinyStr.push_back(_desc_name);//1 s
4350   for(int i=0;i<getSpaceDimension();i++)
4351     tinyStr.push_back(_coords->getInfoOnComponent(i));
4352   layer0.push_back((int)_families.size());//4 i <- key info aa layer#0
4353   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
4354     {
4355       tinyStr.push_back((*it).first);
4356       layer0.push_back((*it).second);
4357     }
4358   layer0.push_back((int)_groups.size());//4+aa i <- key info bb layer#0
4359   for(std::map<std::string, std::vector<std::string> >::const_iterator it0=_groups.begin();it0!=_groups.end();it0++)
4360     {
4361       layer0.push_back((int)(*it0).second.size());
4362       tinyStr.push_back((*it0).first);
4363       for(std::vector<std::string>::const_iterator it1=((*it0).second).begin();it1!=((*it0).second).end();it1++)
4364         tinyStr.push_back(*it1);
4365     }
4366   // sizeof(layer0)==4+aa+1+bb layer#0
4367   bigArrayD=_coords;// 0 bd
4368   bigArraysI.push_back(_fam_coords);// 0 bi
4369   bigArraysI.push_back(_num_coords);// 1 bi
4370   const PartDefinition *pd(_part_coords);
4371   if(!pd)
4372     layer0.push_back(-1);
4373   else
4374     {
4375       std::vector<int> tmp0;
4376       pd->serialize(tmp0,bigArraysI);
4377       tinyInt.push_back(tmp0.size());
4378       tinyInt.insert(tinyInt.end(),tmp0.begin(),tmp0.end());
4379     }
4380   //
4381   std::vector<int> layer1;
4382   std::vector<int> levs(getNonEmptyLevels());
4383   layer1.push_back((int)levs.size());// 0 i <- key
4384   layer1.insert(layer1.end(),levs.begin(),levs.end());
4385   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
4386     {
4387       const MEDFileUMeshSplitL1 *lev(getMeshAtLevSafe(*it));
4388       lev->serialize(layer1,bigArraysI);
4389     }
4390   // put layers all together.
4391   tinyInt.push_back(layer0.size());
4392   tinyInt.insert(tinyInt.end(),layer0.begin(),layer0.end());
4393   tinyInt.push_back(layer1.size());
4394   tinyInt.insert(tinyInt.end(),layer1.begin(),layer1.end());
4395 }
4396
4397 void MEDFileUMesh::unserialize(std::vector<double>& tinyDouble, std::vector<int>& tinyInt, std::vector<std::string>& tinyStr,
4398                                std::vector< MCAuto<DataArrayInt> >& bigArraysI, MCAuto<DataArrayDouble>& bigArrayD)
4399 {
4400   int sz0(tinyInt[0]);
4401   std::vector<int> layer0(tinyInt.begin()+1,tinyInt.begin()+1+sz0);
4402   int sz1(tinyInt[sz0+1]);
4403   std::vector<int> layer1(tinyInt.begin()+2+sz0,tinyInt.begin()+2+sz0+sz1);
4404   //
4405   std::reverse(layer0.begin(),layer0.end());
4406   std::reverse(layer1.begin(),layer1.end());
4407   std::reverse(tinyDouble.begin(),tinyDouble.end());
4408   std::reverse(tinyStr.begin(),tinyStr.end());
4409   std::reverse(bigArraysI.begin(),bigArraysI.end());
4410   //
4411   setAxisType((MEDCouplingAxisType)layer0.back()); layer0.pop_back();
4412   _order=layer0.back(); layer0.pop_back();
4413   _iteration=layer0.back(); layer0.pop_back();
4414   int spaceDim(layer0.back()); layer0.pop_back();
4415   _time=tinyDouble.back(); tinyDouble.pop_back();
4416   _name=tinyStr.back(); tinyStr.pop_back();
4417   _desc_name=tinyStr.back(); tinyStr.pop_back();
4418   _coords=bigArrayD; _coords->rearrange(spaceDim);
4419   for(int i=0;i<spaceDim;i++)
4420     {
4421       _coords->setInfoOnComponent(i,tinyStr.back());
4422       tinyStr.pop_back();
4423     }
4424   int nbOfFams(layer0.back()); layer0.pop_back();
4425   _families.clear();
4426   for(int i=0;i<nbOfFams;i++)
4427     {
4428       _families[tinyStr.back()]=layer0.back();
4429       tinyStr.pop_back(); layer0.pop_back();
4430     }
4431   int nbGroups(layer0.back()); layer0.pop_back();
4432   _groups.clear();
4433   for(int i=0;i<nbGroups;i++)
4434     {
4435       std::string grpName(tinyStr.back()); tinyStr.pop_back();
4436       int nbOfFamsOnGrp(layer0.back()); layer0.pop_back();
4437       std::vector<std::string> fams(nbOfFamsOnGrp);
4438       for(int j=0;j<nbOfFamsOnGrp;j++)
4439         {
4440           fams[j]=tinyStr.back(); tinyStr.pop_back();
4441         }
4442       _groups[grpName]=fams;
4443     }
4444   _fam_coords=bigArraysI.back(); bigArraysI.pop_back();
4445   _num_coords=bigArraysI.back(); bigArraysI.pop_back();
4446   _part_coords=0;
4447   int isPd(layer0.back()); layer0.pop_back();
4448   if(isPd!=-1)
4449     {
4450       std::vector<int> tmp0(layer0.begin(),layer0.begin()+isPd);
4451       layer0.erase(layer0.begin(),layer0.begin()+isPd);
4452       _part_coords=PartDefinition::Unserialize(tmp0,bigArraysI);
4453     }
4454   if(!layer0.empty())
4455     throw INTERP_KERNEL::Exception("MEDFileUMesh::unserialize : something wrong during unserialization #1 !");
4456   //
4457   int nbLevs(layer1.back()); layer1.pop_back();
4458   std::vector<int> levs(layer1.rbegin(),layer1.rbegin()+nbLevs); layer1.erase(layer1.end()-nbLevs,layer1.end());
4459   _ms.clear();
4460   int maxLev(-(*std::min_element(levs.begin(),levs.end())));
4461   _ms.resize(maxLev+1);
4462   for(int i=0;i<nbLevs;i++)
4463     {
4464       int lev(levs[i]);
4465       int pos(-lev);
4466       _ms[pos]=MEDFileUMeshSplitL1::Unserialize(_name,_coords,layer1,bigArraysI);
4467     }
4468 }
4469
4470 /*!
4471  * Adds a group of nodes to \a this mesh.
4472  *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
4473  *          The ids should be sorted and different each other (MED file norm).
4474  *
4475  *  \warning this method can alter default "FAMILLE_ZERO" family.
4476  *  For users sensitive to this a call to MEDFileMesh::rearrangeFamilies will be necessary after addGroup session.
4477  *
4478  *  \throw If the node coordinates array is not set.
4479  *  \throw If \a ids == \c NULL.
4480  *  \throw If \a ids->getName() == "".
4481  *  \throw If \a ids does not respect the MED file norm.
4482  *  \throw If a group with name \a ids->getName() already exists.
4483  */
4484 void MEDFileUMesh::addNodeGroup(const DataArrayInt *ids)
4485 {
4486   const DataArrayDouble *coords(_coords);
4487   if(!coords)
4488     throw INTERP_KERNEL::Exception("MEDFileUMesh::addNodeGroup : no coords set !");
4489   int nbOfNodes(coords->getNumberOfTuples());
4490   if(!((DataArrayInt *)_fam_coords))
4491     { _fam_coords=DataArrayInt::New(); _fam_coords->alloc(nbOfNodes,1); _fam_coords->fillWithZero(); }
4492   //
4493   addGroupUnderground(true,ids,_fam_coords);
4494 }
4495
4496 /*!
4497  * Adds a group of nodes/cells/faces/edges to \a this mesh.
4498  *
4499  *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
4500  *          The ids should be sorted and different each other (MED file norm).
4501  *
4502  * \warning this method can alter default "FAMILLE_ZERO" family.
4503  * For users sensitive to this a call to MEDFileMesh::rearrangeFamilies will be necessary after addGroup session.
4504  *
4505  *  \throw If the node coordinates array is not set.
4506  *  \throw If \a ids == \c NULL.
4507  *  \throw If \a ids->getName() == "".
4508  *  \throw If \a ids does not respect the MED file norm.
4509  *  \throw If a group with name \a ids->getName() already exists.
4510  */
4511 void MEDFileUMesh::addGroup(int meshDimRelToMaxExt, const DataArrayInt *ids)
4512 {
4513   std::vector<int> levs(getNonEmptyLevelsExt());
4514   if(std::find(levs.begin(),levs.end(),meshDimRelToMaxExt)==levs.end())
4515     { 
4516       std::ostringstream oss; oss << "MEDFileUMesh::addGroup : level " << meshDimRelToMaxExt << " not available ! Should be in ";
4517       std::copy(levs.begin(),levs.end(),std::ostream_iterator<int>(oss," ")); oss << " !"; throw INTERP_KERNEL::Exception(oss.str().c_str());
4518     }
4519   if(meshDimRelToMaxExt==1)
4520     { addNodeGroup(ids); return ; }
4521   MEDFileUMeshSplitL1 *lev(getMeshAtLevSafe(meshDimRelToMaxExt));
4522   DataArrayInt *fam(lev->getOrCreateAndGetFamilyField());
4523   addGroupUnderground(false,ids,fam);
4524 }
4525
4526 /*!
4527  * Changes a name of a family specified by its id.
4528  *  \param [in] id - the id of the family of interest.
4529  *  \param [in] newFamName - the new family name.
4530  *  \throw If no family with the given \a id exists.
4531  */
4532 void MEDFileUMesh::setFamilyNameAttachedOnId(int id, const std::string& newFamName)
4533 {
4534   std::string oldName=getFamilyNameGivenId(id);
4535   _families.erase(oldName);
4536   _families[newFamName]=id;
4537 }
4538
4539 /*!
4540  * Removes a mesh of a given dimension.
4541  *  \param [in] meshDimRelToMax - the relative dimension of interest.
4542  *  \throw If there is no mesh at level \a meshDimRelToMax in \a this mesh.
4543  */
4544 void MEDFileUMesh::removeMeshAtLevel(int meshDimRelToMax)
4545 {
4546   std::vector<int> levSet=getNonEmptyLevels();
4547   std::vector<int>::const_iterator it=std::find(levSet.begin(),levSet.end(),meshDimRelToMax);
4548   if(it==levSet.end())
4549     throw INTERP_KERNEL::Exception("MEDFileUMesh::removeMeshAtLevel : the requested level is not existing !");
4550   int pos=(-meshDimRelToMax);
4551   _ms[pos]=0;
4552 }
4553
4554 /*!
4555  * Sets a new MEDCoupling1GTUMesh at a given level in \a this mesh.
4556  *  \param [in] meshDimRelToMax - a relative level to set the mesh at.
4557  *  \param [in] m - the new mesh to set.
4558  *  \throw If the name or the description of \a this mesh and \a m are not empty and are
4559  *         different. 
4560  *  \throw If the node coordinates array is set \a this in mesh and \a m refers to
4561  *         another node coordinates array.
4562  *  \throw If the mesh dimension of \a m does not correspond to \a meshDimRelToMax or
4563  *         to the existing meshes of other levels of \a this mesh.
4564  */
4565 void MEDFileUMesh::setMeshAtLevel(int meshDimRelToMax, MEDCoupling1GTUMesh *m)
4566 {
4567   MCAuto<MEDFileUMeshSplitL1> elt(new MEDFileUMeshSplitL1(m));
4568   checkAndGiveEntryInSplitL1(meshDimRelToMax,m)=elt;
4569 }
4570
4571 /*!
4572  * Sets a new MEDCouplingUMesh at a given level in \a this mesh.
4573  *  \param [in] meshDimRelToMax - a relative level to set the mesh at.
4574  *  \param [in] m - the new mesh to set.
4575  *  \param [in] newOrOld - if \c true, cells in \a m are sorted by type to be ready for 
4576  *         writing \a this mesh in a MED file.
4577  *  \throw If the name or the description of \a this mesh and \a m are not empty and are
4578  *         different. 
4579  *  \throw If the node coordinates array is set \a this in mesh and \a m refers to
4580  *         another node coordinates array.
4581  *  \throw If the mesh dimension of \a m does not correspond to \a meshDimRelToMax or
4582  *         to the existing meshes of other levels of \a this mesh.
4583  */
4584 void MEDFileUMesh::setMeshAtLevel(int meshDimRelToMax, MEDCouplingUMesh *m, bool newOrOld)
4585 {
4586   MCAuto<MEDFileUMeshSplitL1> elt(new MEDFileUMeshSplitL1(m,newOrOld));
4587   checkAndGiveEntryInSplitL1(meshDimRelToMax,m)=elt;
4588 }
4589
4590 MCAuto<MEDFileUMeshSplitL1>& MEDFileUMesh::checkAndGiveEntryInSplitL1(int meshDimRelToMax, MEDCouplingPointSet *m)
4591 {
4592   dealWithTinyInfo(m);
4593   std::vector<int> levSet=getNonEmptyLevels();
4594   if(std::find(levSet.begin(),levSet.end(),meshDimRelToMax)==levSet.end())
4595     {
4596       if((DataArrayDouble *)_coords==0)
4597         {
4598           DataArrayDouble *c=m->getCoords();
4599           if(c)
4600             c->incrRef();
4601           _coords=c;
4602         }
4603       if(m->getCoords()!=_coords)
4604         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshAtLevel : Invalid Given Mesh ! The coordinates are not the same ! try to use tryToShareSameCoords !");
4605       int sz=(-meshDimRelToMax)+1;
4606       if(sz>=(int)_ms.size())
4607         _ms.resize(sz);
4608       checkMeshDimCoherency(m->getMeshDimension(),meshDimRelToMax);
4609       return _ms[sz-1];
4610     }
4611   else
4612     return _ms[-meshDimRelToMax];
4613 }
4614
4615 /*!
4616  * This method allows to set at once the content of different levels in \a this.
4617  * This method is equivalent to a series of call to MEDFileUMesh::setMeshAtLevel.
4618  *
4619  * \param [in] ms - List of unstructured meshes lying on the same coordinates and having different mesh dimesnion.
4620  * \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.
4621  *                     If false, an exception ois thrown. If true the mesh is reordered automatically. It is highly recommanded to let this parameter to false.
4622  *
4623  * \throw If \a there is a null pointer in \a ms.
4624  * \sa MEDFileUMesh::setMeshAtLevel
4625  */
4626 void MEDFileUMesh::setMeshes(const std::vector<const MEDCouplingUMesh *>& ms, bool renum)
4627 {
4628   if(ms.empty())
4629     return ;
4630   const MEDCouplingUMesh *mRef=ms[0];
4631   if(!mRef)
4632     throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : null instance in the first element of input meshes !");
4633   std::string name(mRef->getName());
4634   const DataArrayDouble *coo(mRef->getCoords());
4635   std::set<int> s;
4636   int zeDim=-1;
4637   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
4638     {
4639       const MEDCouplingUMesh *cur(*it);
4640       if(!cur)
4641         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : null instance in input vector of meshes !");
4642       if(coo!=cur->getCoords())
4643         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : The input meshes do not share the same coordinates !");
4644       int mdim=cur->getMeshDimension();
4645       zeDim=std::max(zeDim,mdim);
4646       if(s.find(mdim)!=s.end())
4647         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : The input meshes must share the same coordinates pointer, and should have different mesh dimension each other !");
4648     }
4649   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
4650     {
4651       int mdim=(*it)->getMeshDimension();
4652       setName((*it)->getName());
4653       setMeshAtLevel(mdim-zeDim,const_cast<MEDCouplingUMesh *>(*it),renum);
4654     }
4655   setName(name);
4656 }
4657
4658 /*!
4659  * Creates one MEDCouplingUMesh at a given level in \a this mesh from a sequence of
4660  * meshes each representing a group, and creates corresponding groups in \a this mesh.
4661  * The given meshes must share the same node coordinates array.
4662  *  \param [in] meshDimRelToMax - the relative dimension to create the mesh and groups at.
4663  *  \param [in] ms - the sequence of meshes. Each mesh in \a ms represents a group to
4664  *          create in \a this mesh.
4665  *  \throw If \a ms is empty.
4666  *  \throw If dimension of meshes in \a ms does not correspond to \a meshDimRelToMax or
4667  *         to the existing meshes of other levels of \a this mesh.
4668  *  \throw If the meshes in \a ms do not share the same node coordinates array.
4669  *  \throw If the node coordinates array of \a this mesh (if any) is not the same as that
4670  *         of the given meshes.
4671  *  \throw If \a ms[ i ] is not well defined (MEDCouplingUMesh::checkConsistencyLight()).
4672  *  \throw If names of some meshes in \a ms are equal.
4673  *  \throw If \a ms includes a mesh with an empty name.
4674  */
4675 void MEDFileUMesh::setGroupsFromScratch(int meshDimRelToMax, const std::vector<const MEDCouplingUMesh *>& ms, bool renum)
4676 {
4677   if(ms.empty())
4678     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsFromScratch : expecting a non empty vector !");
4679   int sz=(-meshDimRelToMax)+1;
4680   if(sz>=(int)_ms.size())
4681     _ms.resize(sz);
4682   checkMeshDimCoherency(ms[0]->getMeshDimension(),meshDimRelToMax);
4683   DataArrayDouble *coo=checkMultiMesh(ms);
4684   if((DataArrayDouble *)_coords==0)
4685     {
4686       coo->incrRef();
4687       _coords=coo;
4688     }
4689   else
4690     if((DataArrayDouble *)_coords!=coo)
4691       throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsFromScratch : coordinates mismatches !");
4692   std::vector<DataArrayInt *> corr;
4693   MCAuto<MEDCouplingUMesh> m=MEDCouplingUMesh::FuseUMeshesOnSameCoords(ms,_zipconn_pol,corr);
4694   std::vector< MCAuto<DataArrayInt> > corr3(corr.begin(),corr.end());
4695   setMeshAtLevel(meshDimRelToMax,m,renum);
4696   std::vector<const DataArrayInt *> corr2(corr.begin(),corr.end());
4697   setGroupsAtLevel(meshDimRelToMax,corr2,true);
4698 }
4699
4700 /*!
4701  * Creates groups at a given level in \a this mesh from a sequence of
4702  * meshes each representing a group.
4703  * The given meshes must share the same node coordinates array.
4704  *  \param [in] meshDimRelToMax - the relative dimension to create the groups at.
4705  *  \param [in] ms - the sequence of meshes. Each mesh in \a ms represents a group to
4706  *         create in \a this mesh.
4707  *  \param [in] renum - if \c true, then the optional numbers of entities are taken into
4708  *         account. 
4709  *  \throw If \a ms is empty.
4710  *  \throw If dimension of meshes in \a ms does not correspond to \a meshDimRelToMax or
4711  *         to the existing meshes of other levels of \a this mesh.
4712  *  \throw If the meshes in \a ms do not share the same node coordinates array.
4713  *  \throw If the node coordinates array of \a this mesh (if any) is not the same as that
4714  *         of the given meshes.
4715  *  \throw If \a ms[ i ] is not well defined (MEDCouplingUMesh::checkConsistencyLight()).
4716  *  \throw If names of some meshes in \a ms are equal.
4717  *  \throw If \a ms includes a mesh with an empty name.
4718  */
4719 void MEDFileUMesh::setGroupsOnSetMesh(int meshDimRelToMax, const std::vector<const MEDCouplingUMesh *>& ms, bool renum)
4720 {
4721   if(ms.empty())
4722     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsOnSetMesh : expecting a non empty vector !");
4723   int sz=(-meshDimRelToMax)+1;
4724   if(sz>=(int)_ms.size())
4725     _ms.resize(sz);
4726   checkMeshDimCoherency(ms[0]->getMeshDimension(),meshDimRelToMax);
4727   DataArrayDouble *coo=checkMultiMesh(ms);
4728   if((DataArrayDouble *)_coords==0)
4729     {
4730       coo->incrRef();
4731       _coords=coo;
4732     }
4733   else
4734     if((DataArrayDouble *)_coords!=coo)
4735       throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsOnSetMesh : coordinates mismatches !");
4736   MEDCouplingUMesh *m=getMeshAtLevel(meshDimRelToMax,renum);
4737   std::vector< MCAuto<DataArrayInt> > corr(ms.size());
4738   int i=0;
4739   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++,i++)
4740     {
4741       DataArrayInt *arr=0;
4742       bool test=m->areCellsIncludedIn(*it,_zipconn_pol,arr);
4743       corr[i]=arr;
4744       if(!test)
4745         {
4746           std::ostringstream oss; oss << "MEDFileUMesh::setGroupsOnSetMesh : mesh #" << i << " is not part of whole mesh !";
4747           throw INTERP_KERNEL::Exception(oss.str().c_str());
4748         }
4749     }
4750   std::vector<const DataArrayInt *> corr2(corr.begin(),corr.end());
4751   setGroupsAtLevel(meshDimRelToMax,corr2,renum);
4752 }
4753
4754 DataArrayDouble *MEDFileUMesh::checkMultiMesh(const std::vector<const MEDCouplingUMesh *>& ms) const
4755 {
4756   const DataArrayDouble *ret=ms[0]->getCoords();
4757   int mdim=ms[0]->getMeshDimension();
4758   for(unsigned int i=1;i<ms.size();i++)
4759     {
4760       ms[i]->checkConsistencyLight();
4761       if(ms[i]->getCoords()!=ret)
4762         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMultiMesh : meshes must share the same coords !");
4763       if(ms[i]->getMeshDimension()!=mdim)
4764         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMultiMesh : meshes have not same mesh dimension !");
4765     }
4766   return const_cast<DataArrayDouble *>(ret);
4767 }
4768
4769 /*!
4770  * Sets the family field of a given relative dimension.
4771  *  \param [in] meshDimRelToMaxExt - the relative dimension of entities for which
4772  *          the family field is set.
4773  *  \param [in] famArr - the array of the family field.
4774  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4775  *  \throw If \a famArr has an invalid size.
4776  */
4777 void MEDFileUMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr)
4778 {
4779   if(meshDimRelToMaxExt==1)
4780     {
4781       if(!famArr)
4782         {
4783           _fam_coords=0;
4784           return ;
4785         }
4786       DataArrayDouble *coo(_coords);
4787       if(!coo)
4788         throw INTERP_KERNEL::Exception("MEDFileUMesh::setFamilyFieldArr : the coordinates have not been set !");
4789       famArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),1,"MEDFileUMesh::setFamilyFieldArr : Problem in size of node family arr ! ");
4790       famArr->incrRef();
4791       _fam_coords=famArr;
4792       return ;
4793     }
4794   if(meshDimRelToMaxExt>1)
4795     throw INTERP_KERNEL::Exception("MEDFileUMesh::setFamilyFieldArr : Dimension request is invalid (>1) !");
4796   int traducedRk=-meshDimRelToMaxExt;
4797   if(traducedRk>=(int)_ms.size())
4798     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
4799   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
4800     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
4801   return _ms[traducedRk]->setFamilyArr(famArr);
4802 }
4803
4804 /*!
4805  * Sets the optional numbers of mesh entities of a given dimension.
4806  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4807  *  \param [in] renumArr - the array of the numbers.
4808  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4809  *  \throw If \a renumArr has an invalid size.
4810  */
4811 void MEDFileUMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr)
4812 {
4813   if(meshDimRelToMaxExt==1)
4814     {
4815       if(!renumArr)
4816         {
4817           _num_coords=0;
4818           _rev_num_coords=0;
4819           return ;
4820         }
4821       DataArrayDouble *coo(_coords);
4822       if(!coo)
4823         throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumFieldArr : the coordinates have not been set !");
4824       renumArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),1,"MEDFileUMesh::setRenumArr : Problem in size of node numbering arr ! ");
4825       renumArr->incrRef();
4826       _num_coords=renumArr;
4827       computeRevNum();
4828       return ;
4829     }
4830   if(meshDimRelToMaxExt>1)
4831     throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumArr : Dimension request is invalid (>1) !");
4832   int traducedRk=-meshDimRelToMaxExt;
4833   if(traducedRk>=(int)_ms.size())
4834     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
4835   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
4836     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
4837   return _ms[traducedRk]->setRenumArr(renumArr);
4838 }
4839
4840 /*!
4841  * Sets the optional names of mesh entities of a given dimension.
4842  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4843  *  \param [in] nameArr - the array of the names.
4844  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4845  *  \throw If \a nameArr has an invalid size.
4846  */
4847 void MEDFileUMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr)
4848 {
4849   if(meshDimRelToMaxExt==1)
4850     {
4851       if(!nameArr)
4852         {
4853           _name_coords=0;
4854           return ;
4855         }
4856       DataArrayDouble *coo(_coords);
4857       if(!coo)
4858         throw INTERP_KERNEL::Exception("MEDFileUMesh::setNameFieldAtLevel : the coordinates have not been set !");
4859       nameArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),MED_SNAME_SIZE,"MEDFileUMesh::setNameFieldAtLevel : Problem in size of node numbering arr ! ");
4860       nameArr->incrRef();
4861       _name_coords=nameArr;
4862       return ;
4863     }
4864   if(meshDimRelToMaxExt>1)
4865     throw INTERP_KERNEL::Exception("MEDFileUMesh::setNameFieldAtLevel : Dimension request is invalid (>1) !");
4866   int traducedRk=-meshDimRelToMaxExt;
4867   if(traducedRk>=(int)_ms.size())
4868     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
4869   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
4870     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
4871   return _ms[traducedRk]->setNameArr(nameArr);
4872 }
4873
4874 void MEDFileUMesh::synchronizeTinyInfoOnLeaves() const
4875 {
4876   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
4877     if((const MEDFileUMeshSplitL1 *)(*it))
4878       (*it)->synchronizeTinyInfo(*this);
4879 }
4880
4881 /*!
4882  * This method is called by MEDFileMesh::changeFamilyId. It performs only one part of the family id modification.
4883  */
4884 void MEDFileUMesh::changeFamilyIdArr(int oldId, int newId)
4885 {
4886   DataArrayInt *arr=_fam_coords;
4887   if(arr)
4888     arr->changeValue(oldId,newId);
4889   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
4890     {
4891       MEDFileUMeshSplitL1 *sp=(*it);
4892       if(sp)
4893         {
4894           sp->changeFamilyIdArr(oldId,newId);
4895         }
4896     }
4897 }
4898
4899 std::list< MCAuto<DataArrayInt> > MEDFileUMesh::getAllNonNullFamilyIds() const
4900 {
4901   std::list< MCAuto<DataArrayInt> > ret;
4902   const DataArrayInt *da(_fam_coords);
4903   if(da)
4904     { da->incrRef(); ret.push_back(MCAuto<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
4905   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
4906     {
4907       const MEDFileUMeshSplitL1 *elt(*it);
4908       if(elt)
4909         {
4910           da=elt->getFamilyField();
4911           if(da)
4912             { da->incrRef(); ret.push_back(MCAuto<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
4913         }
4914     }
4915   return ret;
4916 }
4917
4918 void MEDFileUMesh::computeRevNum() const
4919 {
4920   if((const DataArrayInt *)_num_coords)
4921     {
4922       int pos;
4923       int maxValue=_num_coords->getMaxValue(pos);
4924       _rev_num_coords=_num_coords->invertArrayN2O2O2N(maxValue+1);
4925     }
4926 }
4927
4928 std::size_t MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren() const
4929 {
4930   return MEDFileMesh::getHeapMemorySizeWithoutChildren();
4931 }
4932
4933 std::vector<const BigMemoryObject *> MEDFileStructuredMesh::getDirectChildrenWithNull() const
4934 {
4935   std::vector<const BigMemoryObject *> ret(MEDFileMesh::getDirectChildrenWithNull());
4936   ret.push_back((const DataArrayInt *)_fam_nodes);
4937   ret.push_back((const DataArrayInt *)_num_nodes);
4938   ret.push_back((const DataArrayAsciiChar *)_names_nodes);
4939   ret.push_back((const DataArrayInt *)_fam_cells);
4940   ret.push_back((const DataArrayInt *)_num_cells);
4941   ret.push_back((const DataArrayAsciiChar *)_names_cells);
4942   ret.push_back((const DataArrayInt *)_fam_faces);
4943   ret.push_back((const DataArrayInt *)_num_faces);
4944   ret.push_back((const DataArrayInt *)_rev_num_nodes);
4945   ret.push_back((const DataArrayAsciiChar *)_names_faces);
4946   ret.push_back((const DataArrayInt *)_rev_num_cells);
4947   ret.push_back((const MEDCoupling1SGTUMesh*)_faces_if_necessary);
4948   return ret;
4949 }
4950
4951 int MEDFileStructuredMesh::getMaxAbsFamilyIdInArrays() const
4952 {
4953   int ret=-std::numeric_limits<int>::max(),tmp=-1;
4954   if((const DataArrayInt *)_fam_nodes)
4955     {
4956       int val=_fam_nodes->getMaxValue(tmp);
4957       ret=std::max(ret,std::abs(val));
4958     }
4959   if((const DataArrayInt *)_fam_cells)
4960     {
4961       int val=_fam_cells->getMaxValue(tmp);
4962       ret=std::max(ret,std::abs(val));
4963     }
4964   if((const DataArrayInt *)_fam_faces)
4965     {
4966       int val=_fam_faces->getMaxValue(tmp);
4967       ret=std::max(ret,std::abs(val));
4968     }
4969   return ret;
4970 }
4971
4972 int MEDFileStructuredMesh::getMaxFamilyIdInArrays() const
4973 {
4974   int ret=-std::numeric_limits<int>::max(),tmp=-1;
4975   if((const DataArrayInt *)_fam_nodes)
4976     {
4977       int val=_fam_nodes->getMaxValue(tmp);
4978       ret=std::max(ret,val);
4979     }
4980   if((const DataArrayInt *)_fam_cells)
4981     {
4982       int val=_fam_cells->getMaxValue(tmp);
4983       ret=std::max(ret,val);
4984     }
4985   if((const DataArrayInt *)_fam_faces)
4986     {
4987       int val=_fam_faces->getMaxValue(tmp);
4988       ret=std::max(ret,val);
4989     }
4990   return ret;
4991 }
4992
4993 int MEDFileStructuredMesh::getMinFamilyIdInArrays() const
4994 {
4995   int ret=std::numeric_limits<int>::max(),tmp=-1;
4996   if((const DataArrayInt *)_fam_nodes)
4997     {
4998       int val=_fam_nodes->getMinValue(tmp);
4999       ret=std::min(ret,val);
5000     }
5001   if((const DataArrayInt *)_fam_cells)
5002     {
5003       int val=_fam_cells->getMinValue(tmp);
5004       ret=std::min(ret,val);
5005     }
5006   if((const DataArrayInt *)_fam_faces)
5007     {
5008       int val=_fam_faces->getMinValue(tmp);
5009       ret=std::min(ret,val);
5010     }
5011   return ret;
5012 }
5013
5014 bool MEDFileStructuredMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
5015 {
5016   if(!MEDFileMesh::isEqual(other,eps,what))
5017     return false;
5018   const MEDFileStructuredMesh *otherC=dynamic_cast<const  MEDFileStructuredMesh *>(other);
5019   if(!otherC)
5020     {
5021       what="Mesh types differ ! This is structured and other is NOT !";
5022       return false;
5023     }
5024   const DataArrayInt *famc1=_fam_nodes;
5025   const DataArrayInt *famc2=otherC->_fam_nodes;
5026   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
5027     {
5028       what="Mismatch of families arr on nodes ! One is defined and not other !";
5029       return false;
5030     }
5031   if(famc1)
5032     {
5033       bool ret=famc1->isEqual(*famc2);
5034       if(!ret)
5035         {
5036           what="Families arr on nodes differ !";
5037           return false;
5038         }
5039     }
5040   famc1=_fam_cells;
5041   famc2=otherC->_fam_cells;
5042   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
5043     {
5044       what="Mismatch of families arr on cells ! One is defined and not other !";
5045       return false;
5046     }
5047   if(famc1)
5048     {
5049       bool ret=famc1->isEqual(*famc2);
5050       if(!ret)
5051         {
5052           what="Families arr on cells differ !";
5053           return false;
5054         }
5055     }
5056   famc1=_fam_faces;
5057   famc2=otherC->_fam_faces;
5058   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
5059     {
5060       what="Mismatch of families arr on faces ! One is defined and not other !";
5061       return false;
5062     }
5063   if(famc1)
5064     {
5065       bool ret=famc1->isEqual(*famc2);
5066       if(!ret)
5067         {
5068           what="Families arr on faces differ !";
5069           return false;
5070         }
5071     }
5072   famc1=_num_nodes;
5073   famc2=otherC->_num_nodes;
5074   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
5075     {
5076       what="Mismatch of numbering arr on nodes ! One is defined and not other !";
5077       return false;
5078     }
5079   if(famc1)
5080     {
5081       bool ret=famc1->isEqual(*famc2);
5082       if(!ret)
5083         {
5084           what="Numbering arr on nodes differ !";
5085           return false;
5086         }
5087     }
5088   famc1=_num_cells;
5089   famc2=otherC->_num_cells;
5090   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
5091     {
5092       what="Mismatch of numbering arr on cells ! One is defined and not other !";
5093       return false;
5094     }
5095   if(famc1)
5096     {
5097       bool ret=famc1->isEqual(*famc2);
5098       if(!ret)
5099         {
5100           what="Numbering arr on cells differ !";
5101           return false;
5102         }
5103     }
5104   famc1=_num_faces;
5105   famc2=otherC->_num_faces;
5106   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
5107     {
5108       what="Mismatch of numbering arr on faces ! One is defined and not other !";
5109       return false;
5110     }
5111   if(famc1)
5112     {
5113       bool ret=famc1->isEqual(*famc2);
5114       if(!ret)
5115         {
5116           what="Numbering arr on faces differ !";
5117           return false;
5118         }
5119     }
5120   const DataArrayAsciiChar *d1=_names_cells;
5121   const DataArrayAsciiChar *d2=otherC->_names_cells;
5122   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
5123     {
5124       what="Mismatch of naming arr on cells ! One is defined and not other !";
5125       return false;
5126     }
5127   if(d1)
5128     {
5129       bool ret=d1->isEqual(*d2);
5130       if(!ret)
5131         {
5132           what="Naming arr on cells differ !";
5133           return false;
5134         }
5135     }
5136   d1=_names_faces;
5137   d2=otherC->_names_faces;
5138   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
5139     {
5140       what="Mismatch of naming arr on faces ! One is defined and not other !";
5141       return false;
5142     }
5143   if(d1)
5144     {
5145       bool ret=d1->isEqual(*d2);
5146       if(!ret)
5147         {
5148           what="Naming arr on faces differ !";
5149           return false;
5150         }
5151     }
5152   d1=_names_nodes;
5153   d2=otherC->_names_nodes;
5154   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
5155     {
5156       what="Mismatch of naming arr on nodes ! One is defined and not other !";
5157       return false;
5158     }
5159   if(d1)
5160     {
5161       bool ret=d1->isEqual(*d2);
5162       if(!ret)
5163         {
5164           what="Naming arr on nodes differ !";
5165           return false;
5166         }
5167     }
5168   return true;
5169 }
5170
5171 void MEDFileStructuredMesh::clearNonDiscrAttributes() const
5172 {
5173   MEDFileMesh::clearNonDiscrAttributes();
5174   const DataArrayInt *tmp=_fam_nodes;
5175   if(tmp)
5176     (const_cast<DataArrayInt *>(tmp))->setName("");
5177   tmp=_num_nodes;
5178   if(tmp)
5179     (const_cast<DataArrayInt *>(tmp))->setName("");
5180   tmp=_fam_cells;
5181   if(tmp)
5182     (const_cast<DataArrayInt *>(tmp))->setName("");
5183   tmp=_num_cells;
5184   if(tmp)
5185     (const_cast<DataArrayInt *>(tmp))->setName("");
5186   tmp=_fam_faces;
5187   if(tmp)
5188     (const_cast<DataArrayInt *>(tmp))->setName("");
5189   tmp=_num_faces;
5190   if(tmp)
5191     (const_cast<DataArrayInt *>(tmp))->setName("");
5192 }
5193
5194 /*!
5195  * Returns ids of mesh entities contained in given families of a given dimension.
5196  *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
5197  *          are required.
5198  *  \param [in] fams - the names of the families of interest.
5199  *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
5200  *          returned instead of ids.
5201  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
5202  *          numbers, if available and required, of mesh entities of the families. The caller
5203  *          is to delete this array using decrRef() as it is no more needed. 
5204  *  \throw If the family field is missing for \a meshDimRelToMaxExt.
5205  */
5206 DataArrayInt *MEDFileStructuredMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const
5207 {
5208   std::vector<int> famIds(getFamiliesIds(fams));
5209   switch(meshDimRelToMaxExt)
5210   {
5211     case 1:
5212       {
5213         if((const DataArrayInt *)_fam_nodes)
5214           {
5215             MCAuto<DataArrayInt> da;
5216             if(!famIds.empty())
5217               da=_fam_nodes->findIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
5218             else
5219               da=_fam_nodes->findIdsEqualList(0,0);
5220             if(renum)
5221               return MEDFileUMeshSplitL1::Renumber(_num_nodes,da);
5222             else
5223               return da.retn();
5224           }
5225         else
5226           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on nodes !");
5227         break;
5228       }
5229     case 0:
5230       {
5231         if((const DataArrayInt *)_fam_cells)
5232           {
5233             MCAuto<DataArrayInt> da;
5234             if(!famIds.empty())
5235               da=_fam_cells->findIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
5236             else
5237               da=_fam_cells->findIdsEqualList(0,0);
5238             if(renum)
5239               return MEDFileUMeshSplitL1::Renumber(_num_cells,da);
5240             else
5241               return da.retn();
5242           }
5243         else
5244           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on cells !");
5245         break;
5246       }
5247     case -1:
5248       {
5249         if((const DataArrayInt *)_fam_faces)
5250           {
5251             MCAuto<DataArrayInt> da;
5252             if(!famIds.empty())
5253               da=_fam_faces->findIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
5254             else
5255               da=_fam_faces->findIdsEqualList(0,0);
5256             if(renum)
5257               return MEDFileUMeshSplitL1::Renumber(_num_faces,da);
5258             else
5259               return da.retn();
5260           }
5261         else
5262           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on faces !");
5263         break;
5264       }
5265     default:
5266       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : input meshDimRelative must be in [0,1,-1] !");
5267   }
5268   throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : unmanaged case !");
5269 }
5270
5271 /*!
5272  * Sets the family field of a given relative dimension.
5273  *  \param [in] meshDimRelToMaxExt - the relative dimension of entities for which
5274  *          the family field is set.
5275  *  \param [in] famArr - the array of the family field.
5276  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5277  *  \throw If \a famArr has an invalid size.
5278  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1 and \a meshDimRelToMaxExt != -1.
5279  */
5280 void MEDFileStructuredMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr)
5281 {
5282   const MEDCouplingStructuredMesh *mesh(getStructuredMesh());
5283   if(!mesh)
5284     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setFamilyFieldArr : no structured mesh specified ! Impossible to set family array !");
5285   switch(meshDimRelToMaxExt)
5286   {
5287     case 0:
5288       {
5289         int nbCells=mesh->getNumberOfCells();
5290         famArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of cells of mesh !");
5291         _fam_cells=famArr;
5292         break;
5293       }
5294     case 1:
5295       {
5296         int nbNodes=mesh->getNumberOfNodes();
5297         famArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !");
5298         _fam_nodes=famArr;
5299         break;
5300       }
5301     case -1:
5302       {
5303         int nbCells=mesh->getNumberOfCellsOfSubLevelMesh();
5304         famArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of faces of mesh !");
5305         _fam_faces=famArr;
5306         break;
5307       }
5308     default:
5309       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setFamilyFieldArr : Only available for levels 0 or 1 or -1 !");
5310   }
5311   if(famArr)
5312     famArr->incrRef();
5313 }
5314
5315 /*!
5316  * Sets the optional numbers of mesh entities of a given dimension.
5317  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5318  *  \param [in] renumArr - the array of the numbers.
5319  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5320  *  \throw If \a renumArr has an invalid size.
5321  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
5322  */
5323 void MEDFileStructuredMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr)
5324 {
5325   const MEDCouplingStructuredMesh *mesh=getStructuredMesh();
5326   if(!mesh)
5327     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : no structured mesh specified ! Impossible to set number array !");
5328   switch(meshDimRelToMaxExt)
5329   {
5330     case 0:
5331       {
5332         int nbCells=mesh->getNumberOfCells();
5333         renumArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Renum arr ! Mismatch with number of cells of mesh !");
5334         _num_cells=renumArr;
5335         break;
5336       }
5337     case 1:
5338       {
5339         int nbNodes=mesh->getNumberOfNodes();
5340         renumArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !");
5341         _num_nodes=renumArr;
5342         break;
5343       }
5344     case -1:
5345       {
5346         int nbCells=mesh->getNumberOfCellsOfSubLevelMesh();
5347         renumArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Renum arr ! Mismatch with number of faces of mesh !");
5348         _num_faces=renumArr;
5349         break;
5350       }
5351     default:
5352       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : Only available for levels 0 or 1 or -1 !");
5353   }
5354   if(renumArr)
5355     renumArr->incrRef();
5356 }
5357
5358 /*!
5359  * Sets the optional names of mesh entities of a given dimension.
5360  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5361  *  \param [in] nameArr - the array of the names.
5362  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5363  *  \throw If \a nameArr has an invalid size.
5364  */
5365 void MEDFileStructuredMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr)
5366 {
5367   const MEDCouplingStructuredMesh *mesh(getStructuredMesh());
5368   if(!mesh)
5369     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : no structured mesh specified ! Impossible to set names array !");
5370   switch(meshDimRelToMaxExt)
5371   {
5372     case 0:
5373       {
5374         int nbCells=mesh->getNumberOfCells();
5375         nameArr->checkNbOfTuplesAndComp(nbCells,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of cells of mesh !");
5376         _names_cells=nameArr;
5377         break;
5378       }
5379     case 1:
5380       {
5381         int nbNodes=mesh->getNumberOfNodes();
5382         nameArr->checkNbOfTuplesAndComp(nbNodes,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of nodes of mesh !");
5383         _names_nodes=nameArr;
5384         break;
5385       }
5386     case -1:
5387       {
5388         int nbCells=mesh->getNumberOfCellsOfSubLevelMesh();
5389         nameArr->checkNbOfTuplesAndComp(nbCells,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of faces of mesh !");
5390         _names_cells=nameArr;
5391       }
5392     default:
5393       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : Only available for levels 0 or 1 or -1 !");
5394   }
5395   if(nameArr)
5396     nameArr->incrRef();
5397 }
5398
5399 /*!
5400  * Adds a group of nodes to \a this mesh.
5401  *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
5402  *          The ids should be sorted and different each other (MED file norm).
5403  *
5404  *  \warning this method can alter default "FAMILLE_ZERO" family.
5405  *  For users sensitive to this a call to MEDFileMesh::rearrangeFamilies will be necessary after addGroup session.
5406  *
5407  *  \throw If the node coordinates array is not set.
5408  *  \throw If \a ids == \c NULL.
5409  *  \throw If \a ids->getName() == "".
5410  *  \throw If \a ids does not respect the MED file norm.
5411  *  \throw If a group with name \a ids->getName() already exists.
5412  */
5413 void MEDFileStructuredMesh::addNodeGroup(const DataArrayInt *ids)
5414 {
5415   addGroup(1,ids);
5416 }
5417
5418 /*!
5419  * Adds a group of nodes/cells/faces/edges to \a this mesh.
5420  *
5421  *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
5422  *          The ids should be sorted and different each other (MED file norm).
5423  *
5424  * \warning this method can alter default "FAMILLE_ZERO" family.
5425  * For users sensitive to this a call to MEDFileMesh::rearrangeFamilies will be necessary after addGroup session.
5426  *
5427  *  \throw If the node coordinates array is not set.
5428  *  \throw If \a ids == \c NULL.
5429  *  \throw If \a ids->getName() == "".
5430  *  \throw If \a ids does not respect the MED file norm.
5431  *  \throw If a group with name \a ids->getName() already exists.
5432  */
5433 void MEDFileStructuredMesh::addGroup(int meshDimRelToMaxExt, const DataArrayInt *ids)
5434 {
5435   DataArrayInt *fam(getOrCreateAndGetFamilyFieldAtLevel(meshDimRelToMaxExt));
5436   addGroupUnderground(false,ids,fam);
5437   return ;
5438 }
5439
5440 /*!
5441  * Returns the family field for mesh entities of a given dimension.
5442  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5443  *  \return const DataArrayInt * - the family field. It is an array of ids of families
5444  *          each mesh entity belongs to. It can be \c NULL.
5445  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
5446  */
5447 const DataArrayInt *MEDFileStructuredMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) const
5448 {
5449   switch(meshDimRelToMaxExt)
5450   {
5451     case 0:
5452       return _fam_cells;
5453     case 1:
5454       return _fam_nodes;
5455     case -1:
5456       return _fam_faces;
5457     default:
5458       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamilyFieldAtLevel : Only available for levels 0 or 1 or -1 !");
5459   }
5460 }
5461
5462 /*!
5463  * Returns the family field for mesh entities of a given dimension.
5464  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5465  *  \return const DataArrayInt * - the family field. It is an array of ids of families
5466  *          each mesh entity belongs to. It can be \c NULL.
5467  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
5468  */
5469 DataArrayInt *MEDFileStructuredMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt)
5470 {
5471   switch(meshDimRelToMaxExt)
5472   {
5473     case 0:
5474       return _fam_cells;
5475     case 1:
5476       return _fam_nodes;
5477     case -1:
5478       return _fam_faces;
5479     default:
5480       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamilyFieldAtLevel : Only available for levels 0 or 1 or -1 !");
5481   }
5482 }
5483
5484 /*!
5485  * Returns the optional numbers of mesh entities of a given dimension.
5486  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5487  *  \return const DataArrayInt * - the array of the entity numbers.
5488  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5489  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
5490  */
5491 const DataArrayInt *MEDFileStructuredMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) const
5492 {
5493   switch(meshDimRelToMaxExt)
5494   {
5495     case 0:
5496       return _num_cells;
5497     case 1:
5498       return _num_nodes;
5499     case -1:
5500       return _num_faces;
5501     default:
5502       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberFieldAtLevel : Only available for levels 0 or 1 or -1 !");
5503   }
5504 }
5505
5506 /*!
5507  * Returns the optional numbers of mesh entities of a given dimension transformed using
5508  * DataArrayInt::invertArrayN2O2O2N().
5509  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5510  *  \return const DataArrayInt * - the array of the entity numbers transformed using
5511  *          DataArrayInt::invertArrayN2O2O2N().
5512  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
5513  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5514  */
5515 const DataArrayInt *MEDFileStructuredMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxExt) const
5516 {
5517   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
5518     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getRevNumberFieldAtLevel : Only available for levels 0 or 1 !");
5519   if(meshDimRelToMaxExt==0)
5520     {
5521       if((const DataArrayInt *)_num_cells)
5522         {
5523           int pos;
5524           int maxValue=_num_cells->getMaxValue(pos);
5525           _rev_num_cells=_num_cells->invertArrayN2O2O2N(maxValue+1);
5526           return _rev_num_cells;
5527         }
5528       else
5529         throw INTERP_KERNEL::Exception("MEDFileCMesh::getRevNumberFieldAtLevel : no cell renumbering for a request on reverse numbering !");
5530     }
5531   else
5532     {
5533       if((const DataArrayInt *)_num_nodes)
5534         {
5535           int pos;
5536           int maxValue=_num_nodes->getMaxValue(pos);
5537           _rev_num_nodes=_num_nodes->invertArrayN2O2O2N(maxValue+1);
5538           return _rev_num_nodes;
5539         }
5540       else
5541         throw INTERP_KERNEL::Exception("MEDFileCMesh::getRevNumberFieldAtLevel : no node renumbering for a request on reverse numbering !");
5542     }
5543 }
5544
5545 const DataArrayAsciiChar *MEDFileStructuredMesh::getNameFieldAtLevel(int meshDimRelToMaxExt) const
5546 {
5547   switch(meshDimRelToMaxExt)
5548   {
5549     case 0:
5550       return _names_cells;
5551     case 1:
5552       return _names_nodes;
5553     case -1:
5554       return _names_faces;
5555     default:
5556       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNameFieldAtLevel : Only available for levels 0 or 1 or -1 !");
5557   }
5558 }
5559
5560 /*!
5561  * Returns relative dimensions of mesh entities (excluding nodes) present in \a this mesh.
5562  *  \return std::vector<int> - a sequence of the relative dimensions: [0].
5563  */
5564 std::vector<int> MEDFileStructuredMesh::getNonEmptyLevels() const
5565 {
5566   std::vector<int> ret(1);
5567   return ret;
5568 }
5569
5570 /*!
5571  * Returns relative dimensions of mesh entities (including nodes) present in \a this mesh.
5572  *  \return std::vector<int> - a sequence of the relative dimensions: [1,0].
5573  */
5574 std::vector<int> MEDFileStructuredMesh::getNonEmptyLevelsExt() const
5575 {
5576   std::vector<int> ret(2);
5577   ret[0]=1;
5578   return ret;
5579 }
5580
5581 /*!
5582  * Returns the set of extensive levels (nodes included) where not NULL family arr are defined.
5583  */
5584 std::vector<int> MEDFileStructuredMesh::getFamArrNonEmptyLevelsExt() const
5585 {
5586   std::vector<int> ret;
5587   const DataArrayInt *famNodes(_fam_nodes),*famCells(_fam_cells),*famFaces(_fam_faces);
5588   if(famNodes)
5589     ret.push_back(1);
5590   if(famCells)
5591     ret.push_back(0);
5592   if(famFaces)
5593     ret.push_back(-1);
5594   return ret;
5595 }
5596
5597 /*!
5598  * Returns the set of extensive levels (nodes included) where not NULL numbering arr are defined.
5599  */
5600 std::vector<int> MEDFileStructuredMesh::getNumArrNonEmptyLevelsExt() const
5601 {
5602   std::vector<int> ret;
5603   const DataArrayInt *numNodes(_num_nodes),*numCells(_num_cells),*numFaces(_num_faces);
5604   if(numNodes)
5605     ret.push_back(1);
5606   if(numCells)
5607     ret.push_back(0);
5608   if(numFaces)
5609     ret.push_back(-1);
5610   return ret;
5611 }
5612
5613 /*!
5614  * Returns the set of extensive levels (nodes included) where not NULL naming arr are defined.
5615  */
5616 std::vector<int> MEDFileStructuredMesh::getNameArrNonEmptyLevelsExt() const
5617 {
5618   std::vector<int> ret;
5619   const DataArrayAsciiChar *namesNodes(_names_nodes),*namesCells(_names_cells),*namesFaces(_names_faces);
5620   if(namesNodes)
5621     ret.push_back(1);
5622   if(namesCells)
5623     ret.push_back(0);
5624   if(namesFaces)
5625     ret.push_back(-1);
5626   return ret;
5627 }
5628
5629 /*!
5630  * no implementation here, it is not a bug, but intresically no polyhedra in \a this.
5631  */
5632 bool MEDFileStructuredMesh::unPolyze(std::vector<int>& oldCode, std::vector<int>& newCode, DataArrayInt *& o2nRenumCell)
5633 {
5634   oldCode.clear(); newCode.clear(); o2nRenumCell=0;
5635   return false;
5636 }
5637
5638 void MEDFileStructuredMesh::changeFamilyIdArr(int oldId, int newId)
5639 {
5640   DataArrayInt *arr=_fam_nodes;
5641   if(arr)
5642     arr->changeValue(oldId,newId);
5643   arr=_fam_cells;
5644   if(arr)
5645     arr->changeValue(oldId,newId);
5646   arr=_fam_faces;
5647   if(arr)
5648     arr->changeValue(oldId,newId);
5649 }
5650
5651 std::list< MCAuto<DataArrayInt> > MEDFileStructuredMesh::getAllNonNullFamilyIds() const
5652 {
5653   std::list< MCAuto<DataArrayInt> > ret;
5654   const DataArrayInt *da(_fam_nodes);
5655   if(da)
5656     { da->incrRef(); ret.push_back(MCAuto<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
5657   da=_fam_cells;
5658   if(da)
5659     { da->incrRef(); ret.push_back(MCAuto<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
5660   da=_fam_faces;
5661   if(da)
5662     { da->incrRef(); ret.push_back(MCAuto<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
5663   return ret;
5664 }
5665
5666 void MEDFileStructuredMesh::deepCpyAttributes()
5667 {
5668   if((const DataArrayInt*)_fam_nodes)
5669     _fam_nodes=_fam_nodes->deepCopy();
5670   if((const DataArrayInt*)_num_nodes)
5671     _num_nodes=_num_nodes->deepCopy();
5672   if((const DataArrayAsciiChar*)_names_nodes)
5673     _names_nodes=_names_nodes->deepCopy();
5674   if((const DataArrayInt*)_fam_cells)
5675     _fam_cells=_fam_cells->deepCopy();
5676   if((const DataArrayInt*)_num_cells)
5677     _num_cells=_num_cells->deepCopy();
5678   if((const DataArrayAsciiChar*)_names_cells)
5679     _names_cells=_names_cells->deepCopy();
5680   if((const DataArrayInt*)_fam_faces)
5681     _fam_faces=_fam_faces->deepCopy();
5682   if((const DataArrayInt*)_num_faces)
5683     _num_faces=_num_faces->deepCopy();
5684   if((const DataArrayAsciiChar*)_names_faces)
5685     _names_faces=_names_faces->deepCopy();
5686   if((const DataArrayInt*)_rev_num_nodes)
5687     _rev_num_nodes=_rev_num_nodes->deepCopy();
5688   if((const DataArrayInt*)_rev_num_cells)
5689     _rev_num_cells=_rev_num_cells->deepCopy();
5690 }
5691
5692 /*!
5693  * Returns a pointer to mesh at the specified level (here 0 is compulsary for cartesian mesh).
5694  * 
5695  * \return a pointer to cartesian mesh that need to be managed by the caller.
5696  * \warning the returned pointer has to be managed by the caller.
5697  */
5698
5699 /*!
5700  * Returns a pointer to MEDCouplingStructuredMesh held by \a this. 
5701  *  \param [in] meshDimRelToMax - it must be \c 0 or \c -1.
5702  *  \param [in] renum - it must be \c false.
5703  *  \return MEDCouplingMesh * - a pointer to MEDCouplingMesh that the caller is to
5704  *          delete using decrRef() as it is no more needed. 
5705  */
5706 MEDCouplingMesh *MEDFileStructuredMesh::getMeshAtLevel(int meshDimRelToMax, bool renum) const
5707 {
5708   checkCartesian();
5709   if(renum)
5710     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support renumbering ! To do it perform request of renum array directly !");
5711   const MEDCouplingStructuredMesh *m(getStructuredMesh());
5712   switch(meshDimRelToMax)
5713   {
5714     case 0:
5715       {
5716         if(m)
5717           m->incrRef();
5718         return const_cast<MEDCouplingStructuredMesh *>(m);
5719       }
5720     case -1:
5721       {
5722         if(!m)
5723           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getMeshAtLevel : level -1 requested must be non empty to be able to compute unstructured sub mesh !");
5724         buildMinusOneImplicitPartIfNeeded();
5725         MEDCoupling1SGTUMesh *ret(_faces_if_necessary);
5726         if(ret)
5727           ret->incrRef();
5728         return ret;
5729       }
5730     default:
5731       throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support multi level for mesh 0 expected as input !");
5732   }
5733 }
5734
5735 std::vector<int> MEDFileStructuredMesh::getFamsNonEmptyLevels(const std::vector<std::string>& fams) const
5736 {
5737   std::vector<int> ret;
5738   const DataArrayInt *famCells(_fam_cells),*famFaces(_fam_faces);
5739   if(famCells && famCells->presenceOfValue(ret))
5740     ret.push_back(0);
5741   if(famFaces && famFaces->presenceOfValue(ret))
5742     ret.push_back(-1);
5743   return ret;  
5744 }
5745
5746 std::vector<int> MEDFileStructuredMesh::getFamsNonEmptyLevelsExt(const std::vector<std::string>& fams) const
5747 {
5748   std::vector<int> ret(getFamsNonEmptyLevels(fams));
5749   const DataArrayInt *famNodes(_fam_nodes);
5750   if(famNodes && famNodes->presenceOfValue(ret))
5751     ret.push_back(1);
5752   return ret;  
5753 }
5754
5755 /*!
5756  * Returns number of mesh entities of a given relative dimension in \a this mesh.
5757  *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
5758  *  \return int - the number of entities.
5759  *  \throw If no mesh entities of dimension \a meshDimRelToMaxExt are available in \a this mesh.
5760  */
5761 int MEDFileStructuredMesh::getSizeAtLevel(int meshDimRelToMaxExt) const
5762 {
5763   const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
5764   if(!cmesh)
5765     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : No structured mesh set !");
5766   switch(meshDimRelToMaxExt)
5767   {
5768     case 0:
5769       return cmesh->getNumberOfCells();
5770     case 1:
5771       return cmesh->getNumberOfNodes();
5772     case -1:
5773       return cmesh->getNumberOfCellsOfSubLevelMesh();
5774     default:
5775       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : Only available for levels 0 or 1 or -1 !");
5776   }
5777 }
5778
5779 int MEDFileStructuredMesh::getNumberOfNodes() const
5780 {
5781   const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
5782   if(!cmesh)
5783     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberOfNodes : no cartesian mesh set !");
5784   return cmesh->getNumberOfNodes();
5785 }
5786
5787 int MEDFileStructuredMesh::getNumberOfCellsAtLevel(int meshDimRelToMaxExt) const
5788 {
5789   const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
5790   if(!cmesh)
5791     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberOfNodes : no cartesian mesh set !");
5792   switch(meshDimRelToMaxExt)
5793   {
5794     case 0:
5795       return cmesh->getNumberOfCells();
5796     case -1:
5797       return cmesh->getNumberOfCellsOfSubLevelMesh();
5798     default:
5799       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberOfNodes : only meshDimRelToMax=0 and meshDimRelToMax=-1 supported !");
5800     }
5801 }
5802
5803 bool MEDFileStructuredMesh::hasImplicitPart() const
5804 {
5805   return true;
5806 }
5807
5808 /*!
5809  * \sa MEDFileStructuredMesh::getImplicitFaceMesh
5810  */
5811 int MEDFileStructuredMesh::buildImplicitPartIfAny(INTERP_KERNEL::NormalizedCellType gt) const
5812 {
5813   static const char MSG[]="MEDFileStructuredMesh::buildImplicitPartIfAny : the given geo type is not manageable by a structured mesh !";
5814   const MEDCoupling1SGTUMesh *zeFaceMesh(_faces_if_necessary);
5815   if(!zeFaceMesh)
5816     {
5817       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(getMeshDimension())));
5818       if(cm.getReverseExtrudedType()!=gt)
5819         throw INTERP_KERNEL::Exception(MSG);
5820       buildImplicitPart();
5821       return getStructuredMesh()->getNumberOfCellsOfSubLevelMesh();
5822     }
5823   else
5824     {
5825       if(gt!=zeFaceMesh->getCellModelEnum())
5826         throw INTERP_KERNEL::Exception(MSG);
5827       return zeFaceMesh->getNumberOfCells();
5828     }
5829 }
5830
5831 void MEDFileStructuredMesh::buildMinusOneImplicitPartIfNeeded() const
5832 {
5833   const MEDCoupling1SGTUMesh *zeFaceMesh(_faces_if_necessary);
5834   if(!zeFaceMesh)
5835     buildImplicitPart();
5836 }
5837
5838 void MEDFileStructuredMesh::buildImplicitPart() const
5839 {
5840   const MEDCouplingStructuredMesh *mcmesh(getStructuredMesh());
5841   if(!mcmesh)
5842     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::buildImplicitPart : Unable to build the implicit part of structured mesh because no structured mesh at level 0 defined !");
5843   _faces_if_necessary=mcmesh->build1SGTSubLevelMesh();
5844 }
5845
5846 void MEDFileStructuredMesh::releaseImplicitPartIfAny() const
5847 {
5848   _faces_if_necessary=0;
5849 }
5850
5851 /*!
5852  * Retrieves the internal pointer (no decrRef requested) of the implicit face mesh if any.
5853  * To force to build it you can invoke MEDFileStructuredMesh::buildImplicitPartIfAny method.
5854  * 
5855  * \sa MEDFileStructuredMesh::buildImplicitPartIfAny
5856  */
5857 MEDCoupling1SGTUMesh *MEDFileStructuredMesh::getImplicitFaceMesh() const
5858 {
5859   checkCartesian();
5860   return _faces_if_necessary;
5861 }
5862
5863 std::vector<INTERP_KERNEL::NormalizedCellType> MEDFileStructuredMesh::getGeoTypesAtLevel(int meshDimRelToMax) const
5864 {
5865   const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
5866   if(!cmesh)
5867     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGeoTypesAtLevel : No structured mesh set !");
5868   switch(meshDimRelToMax)
5869   {
5870     case 0:
5871       {
5872         std::vector<INTERP_KERNEL::NormalizedCellType> ret(1,cmesh->getTypeOfCell(0));
5873         return ret;
5874       }
5875     case -1:
5876       {
5877         int mdim(cmesh->getMeshDimension());
5878         if(mdim<1)
5879           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGeoTypesAtLevel : only one level available for structured meshes ! Input 0 is mandatory or 0D mesh !");
5880         std::vector<INTERP_KERNEL::NormalizedCellType> ret(1,MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(mdim-1));
5881         return ret;
5882       }
5883     default:
5884       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGeoTypesAtLevel : only 2 levels available at most : 0 and -1 !");
5885   }
5886 }
5887
5888 int MEDFileStructuredMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType ct) const
5889 {
5890   if(ct!=MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(getMeshDimension()))
5891     return 0;
5892   else
5893     return getNumberOfCellsAtLevel(0);
5894 }
5895
5896 void MEDFileStructuredMesh::whichAreNodesFetched(const MEDFileField1TSStructItem& st, const MEDFileFieldGlobsReal *globs, std::vector<bool>& nodesFetched) const
5897 {
5898   if(st.getNumberOfItems()!=1)
5899     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 !");
5900   if(st[0].getGeo()!=MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(getMeshDimension()))
5901     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : The sturture of field is not lying on expected geo type !");
5902   if(getNumberOfNodes()!=(int)nodesFetched.size())
5903     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : invalid size of array !");
5904   if(st[0].getPflName().empty())
5905     {
5906       std::fill(nodesFetched.begin(),nodesFetched.end(),true);
5907       return ;
5908     }
5909   const DataArrayInt *arr(globs->getProfile(st[0].getPflName()));
5910   const MEDCouplingStructuredMesh *cmesh=getStructuredMesh();//cmesh not null because getNumberOfNodes called before
5911   int sz(nodesFetched.size());
5912   for(const int *work=arr->begin();work!=arr->end();work++)
5913     {
5914       std::vector<int> conn;
5915       cmesh->getNodeIdsOfCell(*work,conn);
5916       for(std::vector<int>::const_iterator it=conn.begin();it!=conn.end();it++)
5917         if(*it>=0 && *it<sz)
5918           nodesFetched[*it]=true;
5919         else
5920           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : internal error !");
5921     }
5922 }
5923
5924 med_geometry_type MEDFileStructuredMesh::GetGeoTypeFromMeshDim(int meshDim)
5925 {
5926   INTERP_KERNEL::NormalizedCellType ct(MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(meshDim));
5927   return typmai3[ct];
5928 }
5929
5930 void MEDFileStructuredMesh::LoadStrMeshDAFromFile(med_idt fid, int meshDim, int dt, int it, const std::string& mName, MEDFileMeshReadSelector *mrs,
5931                                                   MCAuto<DataArrayInt>& famCells, MCAuto<DataArrayInt>& numCells, MCAuto<DataArrayAsciiChar>& namesCells)
5932 {
5933   med_bool chgt=MED_FALSE,trsf=MED_FALSE;
5934   med_geometry_type geoTypeReq=MEDFileStructuredMesh::GetGeoTypeFromMeshDim(meshDim);
5935   int nbOfElt(0);
5936   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf);
5937   if(nbOfElt>0)
5938     {
5939       if(!mrs || mrs->isCellFamilyFieldReading())
5940         {
5941           famCells=DataArrayInt::New();
5942           famCells->alloc(nbOfElt,1);
5943           MEDFILESAFECALLERRD0(MEDmeshEntityFamilyNumberRd,(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,famCells->getPointer()));
5944         }
5945     }
5946   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,MED_NUMBER,MED_NODAL,&chgt,&trsf);
5947   if(nbOfElt>0)
5948     {
5949       if(!mrs || mrs->isCellNumFieldReading())
5950         {
5951           numCells=DataArrayInt::New();
5952           numCells->alloc(nbOfElt,1);
5953           MEDFILESAFECALLERRD0(MEDmeshEntityNumberRd,(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,numCells->getPointer()));
5954         }
5955     }
5956   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,MED_NAME,MED_NODAL,&chgt,&trsf);
5957   if(nbOfElt>0)
5958     {
5959       if(!mrs || mrs->isCellNameFieldReading())
5960         {
5961           namesCells=DataArrayAsciiChar::New();
5962           namesCells->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end
5963           MEDFILESAFECALLERRD0(MEDmeshEntityNameRd,(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,namesCells->getPointer()));
5964           namesCells->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end
5965         }
5966     }
5967 }
5968
5969 void MEDFileStructuredMesh::loadStrMeshFromFile(MEDFileStrMeshL2 *strm, med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
5970 {
5971   setName(strm->getName());
5972   setDescription(strm->getDescription());
5973   setUnivName(strm->getUnivName());
5974   setIteration(strm->getIteration());
5975   setOrder(strm->getOrder());
5976   setTimeValue(strm->getTime());
5977   setTimeUnit(strm->getTimeUnit());
5978   MEDFileMeshL2::ReadFamiliesAndGrps(fid,mName,_families,_groups,mrs);
5979   med_bool chgt=MED_FALSE,trsf=MED_FALSE;
5980   int nbOfElt(MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf));
5981   if(nbOfElt>0)
5982     {
5983       if(!mrs || mrs->isNodeFamilyFieldReading())
5984         {
5985           int nbNodes(getNumberOfNodes());
5986           if(nbOfElt>nbNodes)
5987             throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::loadStrMeshFromFile : invalid size of family node array regarding number of nodes in this ! File seems to be corrupted !");
5988           _fam_nodes=DataArrayInt::New();
5989           _fam_nodes->alloc(nbNodes,1);//yes nbNodes and not nbOfElt see next line.
5990           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...
5991             _fam_nodes->fillWithZero();
5992           MEDFILESAFECALLERRD0(MEDmeshEntityFamilyNumberRd,(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,_fam_nodes->getPointer()));
5993         }
5994     }
5995   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_NUMBER,MED_NODAL,&chgt,&trsf);
5996   if(nbOfElt>0)
5997     {
5998       if(!mrs || mrs->isNodeNumFieldReading())
5999         {
6000           _num_nodes=DataArrayInt::New();
6001           _num_nodes->alloc(nbOfElt,1);
6002           MEDFILESAFECALLERRD0(MEDmeshEntityNumberRd,(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,_num_nodes->getPointer()));
6003         }
6004     }
6005   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_NAME,MED_NODAL,&chgt,&trsf);
6006   if(nbOfElt>0)
6007     {
6008       if(!mrs || mrs->isNodeNameFieldReading())
6009         {
6010           _names_nodes=DataArrayAsciiChar::New();
6011           _names_nodes->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end
6012           MEDFILESAFECALLERRD0(MEDmeshEntityNameRd,(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,_names_nodes->getPointer()));
6013           _names_nodes->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end
6014         }
6015     }
6016   int meshDim(getStructuredMesh()->getMeshDimension());
6017   LoadStrMeshDAFromFile(fid,meshDim,dt,it,mName,mrs,_fam_cells,_num_cells,_names_cells);
6018   if(meshDim>=1)
6019     LoadStrMeshDAFromFile(fid,meshDim-1,dt,it,mName,mrs,_fam_faces,_num_faces,_names_faces);
6020 }
6021
6022 void MEDFileStructuredMesh::writeStructuredLL(med_idt fid, const std::string& maa) const
6023 {
6024   int meshDim(getStructuredMesh()->getMeshDimension());
6025   med_geometry_type geoTypeReq(GetGeoTypeFromMeshDim(meshDim)),geoTypeReq2(GetGeoTypeFromMeshDim(meshDim-1));
6026   //
6027   if((const DataArrayInt *)_fam_cells)
6028     MEDFILESAFECALLERWR0(MEDmeshEntityFamilyNumberWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq,_fam_cells->getNumberOfTuples(),_fam_cells->getConstPointer()));
6029   if((const DataArrayInt *)_fam_faces)
6030     MEDFILESAFECALLERWR0(MEDmeshEntityFamilyNumberWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq2,_fam_faces->getNumberOfTuples(),_fam_faces->getConstPointer()));
6031   if((const DataArrayInt *)_fam_nodes)
6032     MEDFILESAFECALLERWR0(MEDmeshEntityFamilyNumberWr,(fid,maa.c_str(),_iteration,_order,MED_NODE,MED_NONE,_fam_nodes->getNumberOfTuples(),_fam_nodes->getConstPointer()));
6033   if((const DataArrayInt *)_num_cells)
6034     MEDFILESAFECALLERWR0(MEDmeshEntityNumberWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq,_num_cells->getNumberOfTuples(),_num_cells->getConstPointer()));
6035   if((const DataArrayInt *)_num_faces)
6036     MEDFILESAFECALLERWR0(MEDmeshEntityNumberWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq2,_num_faces->getNumberOfTuples(),_num_faces->getConstPointer()));
6037   if((const DataArrayInt *)_num_nodes)
6038     MEDFILESAFECALLERWR0(MEDmeshEntityNumberWr,(fid,maa.c_str(),_iteration,_order,MED_NODE,MED_NONE,_num_nodes->getNumberOfTuples(),_num_nodes->getConstPointer()));
6039   if((const DataArrayAsciiChar *)_names_cells)
6040     {
6041       if(_names_cells->getNumberOfComponents()!=MED_SNAME_SIZE)
6042         {
6043           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on cells with number of components set to " << MED_SNAME_SIZE;
6044           oss << " ! The array has " << _names_cells->getNumberOfComponents() << " components !";
6045           throw INTERP_KERNEL::Exception(oss.str().c_str());
6046         }
6047       MEDFILESAFECALLERWR0(MEDmeshEntityNameWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq,_names_cells->getNumberOfTuples(),_names_cells->getConstPointer()));
6048     }
6049   if((const DataArrayAsciiChar *)_names_faces)
6050     {
6051       if(_names_faces->getNumberOfComponents()!=MED_SNAME_SIZE)
6052         {
6053           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on faces with number of components set to " << MED_SNAME_SIZE;
6054           oss << " ! The array has " << _names_faces->getNumberOfComponents() << " components !";
6055           throw INTERP_KERNEL::Exception(oss.str().c_str());
6056         }
6057       MEDFILESAFECALLERWR0(MEDmeshEntityNameWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq2,_names_faces->getNumberOfTuples(),_names_faces->getConstPointer()));
6058     }
6059   if((const DataArrayAsciiChar *)_names_nodes)
6060     {
6061       if(_names_nodes->getNumberOfComponents()!=MED_SNAME_SIZE)
6062         {
6063           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on nodes with number of components set to " << MED_SNAME_SIZE;
6064           oss << " ! The array has " << _names_cells->getNumberOfComponents() << " components !";
6065           throw INTERP_KERNEL::Exception(oss.str().c_str());
6066         }
6067       MEDFILESAFECALLERWR0(MEDmeshEntityNameWr,(fid,maa.c_str(),_iteration,_order,MED_NODE,MED_NONE,_names_nodes->getNumberOfTuples(),_names_nodes->getConstPointer()));
6068     }
6069   //
6070   MEDFileUMeshL2::WriteFamiliesAndGrps(fid,maa.c_str(),_families,_groups,_too_long_str);
6071 }
6072
6073 /*!
6074  * Returns an empty instance of MEDFileCMesh.
6075  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
6076  *          mesh using decrRef() as it is no more needed. 
6077  */
6078 MEDFileCMesh *MEDFileCMesh::New()
6079 {
6080   return new MEDFileCMesh;
6081 }
6082
6083 /*!
6084  * Returns a new MEDFileCMesh holding the mesh data that has been read from a given MED
6085  * file. The first mesh in the file is loaded.
6086  *  \param [in] fileName - the name of MED file to read.
6087  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
6088  *          mesh using decrRef() as it is no more needed. 
6089  *  \throw If the file is not readable.
6090  *  \throw If there is no meshes in the file.
6091  *  \throw If the mesh in the file is not a Cartesian one.
6092  */
6093 MEDFileCMesh *MEDFileCMesh::New(const std::string& fileName, MEDFileMeshReadSelector *mrs)
6094 {
6095   std::vector<std::string> ms(MEDCoupling::GetMeshNames(fileName));
6096   if(ms.empty())
6097     {
6098       std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
6099       throw INTERP_KERNEL::Exception(oss.str().c_str());
6100     }
6101   MEDFileUtilities::CheckFileForRead(fileName);
6102   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
6103   int dt,it;
6104   MEDCoupling::MEDCouplingMeshType meshType;
6105   std::string dummy2;
6106   MEDCoupling::MEDCouplingAxisType dummy3;
6107   MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dummy3,dt,it,dummy2);
6108   return new MEDFileCMesh(fid,ms.front(),dt,it,mrs);
6109 }
6110
6111 /*!
6112  * Returns a new MEDFileCMesh holding the mesh data that has been read from a given MED
6113  * file. The mesh to load is specified by its name and numbers of a time step and an
6114  * iteration.
6115  *  \param [in] fileName - the name of MED file to read.
6116  *  \param [in] mName - the name of the mesh to read.
6117  *  \param [in] dt - the number of a time step.
6118  *  \param [in] it - the number of an iteration.
6119  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
6120  *          mesh using decrRef() as it is no more needed. 
6121  *  \throw If the file is not readable.
6122  *  \throw If there is no mesh with given attributes in the file.
6123  *  \throw If the mesh in the file is not a Cartesian one.
6124  */
6125 MEDFileCMesh *MEDFileCMesh::New(const std::string& fileName, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6126 {
6127   MEDFileUtilities::CheckFileForRead(fileName);
6128   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
6129   return new MEDFileCMesh(fid,mName,dt,it,mrs);
6130 }
6131
6132 std::size_t MEDFileCMesh::getHeapMemorySizeWithoutChildren() const
6133 {
6134   return MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren();
6135 }
6136
6137 std::vector<const BigMemoryObject *> MEDFileCMesh::getDirectChildrenWithNull() const
6138 {
6139   std::vector<const BigMemoryObject *> ret(MEDFileStructuredMesh::getDirectChildrenWithNull());
6140   ret.push_back((const MEDCouplingCMesh *)_cmesh);
6141   return ret;
6142 }
6143
6144 /*!
6145  * Returns the dimension on cells in \a this mesh.
6146  *  \return int - the mesh dimension.
6147  *  \throw If there are no cells in this mesh.
6148  */
6149 int MEDFileCMesh::getMeshDimension() const
6150 {
6151   if(!((const MEDCouplingCMesh*)_cmesh))
6152     throw INTERP_KERNEL::Exception("MEDFileCMesh::getMeshDimension : unable to get meshdimension because no mesh set !");
6153   return _cmesh->getMeshDimension();
6154 }
6155
6156 /*!
6157  * Returns the dimension on nodes in \a this mesh.
6158  *  \return int - the space dimension.
6159  *  \throw If there are no cells in this mesh.
6160  */
6161 int MEDFileCMesh::getSpaceDimension() const
6162 {
6163   if(!((const MEDCouplingCMesh*)_cmesh))
6164     throw INTERP_KERNEL::Exception("MEDFileCMesh::getSpaceDimension : unable to get spacedimension because no mesh set !");
6165   return _cmesh->getSpaceDimension();
6166 }
6167
6168 /*!
6169  * Returns a string describing \a this mesh.
6170  *  \return std::string - the mesh information string.
6171  */
6172 std::string MEDFileCMesh::simpleRepr() const
6173 {
6174   return MEDFileStructuredMesh::simpleRepr();
6175 }
6176
6177 /*!
6178  * Returns a full textual description of \a this mesh.
6179  *  \return std::string - the string holding the mesh description.
6180  */
6181 std::string MEDFileCMesh::advancedRepr() const
6182 {
6183   return simpleRepr();
6184 }
6185
6186 MEDFileMesh *MEDFileCMesh::shallowCpy() const
6187 {
6188   MCAuto<MEDFileCMesh> ret(new MEDFileCMesh(*this));
6189   return ret.retn();
6190 }
6191
6192 MEDFileMesh *MEDFileCMesh::createNewEmpty() const
6193 {
6194   return new MEDFileCMesh;
6195 }
6196
6197 MEDFileMesh *MEDFileCMesh::deepCopy() const
6198 {
6199   MCAuto<MEDFileCMesh> ret(new MEDFileCMesh(*this));
6200   ret->deepCpyEquivalences(*this);
6201   if((const MEDCouplingCMesh*)_cmesh)
6202     ret->_cmesh=static_cast<MEDCouplingCMesh*>(_cmesh->deepCopy());
6203   ret->deepCpyAttributes();
6204   return ret.retn();
6205 }
6206
6207 /*!
6208  * Checks if \a this and another mesh are equal.
6209  *  \param [in] other - the mesh to compare with.
6210  *  \param [in] eps - a precision used to compare real values.
6211  *  \param [in,out] what - the string returning description of unequal data.
6212  *  \return bool - \c true if the meshes are equal, \c false, else.
6213  */
6214 bool MEDFileCMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
6215 {
6216   if(!MEDFileStructuredMesh::isEqual(other,eps,what))
6217     return false;
6218   const MEDFileCMesh *otherC=dynamic_cast<const MEDFileCMesh *>(other);
6219   if(!otherC)
6220     {
6221       what="Mesh types differ ! This is cartesian and other is NOT !";
6222       return false;
6223     }
6224   clearNonDiscrAttributes();
6225   otherC->clearNonDiscrAttributes();
6226   const MEDCouplingCMesh *coo1=_cmesh;
6227   const MEDCouplingCMesh *coo2=otherC->_cmesh;
6228   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
6229     {
6230       what="Mismatch of cartesian meshes ! One is defined and not other !";
6231       return false;
6232     }
6233   if(coo1)
6234     {
6235       bool ret=coo1->isEqual(coo2,eps);
6236       if(!ret)
6237         {
6238           what="cartesian meshes differ !";
6239           return false;
6240         }
6241     }
6242   return true;
6243 }
6244
6245 /*!
6246  * Clears redundant attributes of incorporated data arrays.
6247  */
6248 void MEDFileCMesh::clearNonDiscrAttributes() const
6249 {
6250   MEDFileStructuredMesh::clearNonDiscrAttributes();
6251   MEDFileUMeshSplitL1::ClearNonDiscrAttributes(_cmesh);//to it is not a bug umeshsplit have already the method implemented
6252 }
6253
6254 MEDFileCMesh::MEDFileCMesh()
6255 {
6256 }
6257
6258 MEDFileCMesh::MEDFileCMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6259 try
6260 {
6261     loadLLWithAdditionalItems(fid,mName,dt,it,mrs);
6262 }
6263 catch(INTERP_KERNEL::Exception& e)
6264 {
6265     throw e;
6266 }
6267
6268 void MEDFileCMesh::loadLL(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6269 {
6270   MEDCoupling::MEDCouplingMeshType meshType;
6271   int dummy0,dummy1;
6272   std::string dtunit;
6273   MEDCoupling::MEDCouplingAxisType axType;
6274   int mid=MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,axType,dummy0,dummy1,dtunit);
6275   if(meshType!=CARTESIAN)
6276     {
6277       std::ostringstream oss; oss << "Trying to load as cartesian an existing mesh with name '" << mName << "' that is NOT cartesian !";
6278       throw INTERP_KERNEL::Exception(oss.str().c_str());
6279     }
6280   MEDFileCMeshL2 loaderl2;
6281   loaderl2.loadAll(fid,mid,mName,dt,it);
6282   setAxisType(axType);
6283   MEDCouplingCMesh *mesh=loaderl2.getMesh();
6284   mesh->incrRef();
6285   _cmesh=mesh;
6286   loadStrMeshFromFile(&loaderl2,fid,mName,dt,it,mrs);
6287 }
6288
6289 /*!
6290  * Returns a const pointer to MEDCouplingCMesh held by \a this mesh.
6291  *  \return const MEDCouplingCMesh * - a pointer to the held MEDCouplingCMesh.
6292  */
6293 const MEDCouplingCMesh *MEDFileCMesh::getMesh() const
6294 {
6295   synchronizeTinyInfoOnLeaves();
6296   return _cmesh;
6297 }
6298
6299 const MEDCouplingStructuredMesh *MEDFileCMesh::getStructuredMesh() const
6300 {
6301   synchronizeTinyInfoOnLeaves();
6302   return _cmesh;
6303 }
6304
6305 /*!
6306  * Sets the MEDCouplingCMesh holding the data of \a this mesh.
6307  *  \param [in] m - the new MEDCouplingCMesh to refer to.
6308  *  \throw If the name or the description of \a this mesh and \a m are not empty and are
6309  *         different. 
6310  */
6311 void MEDFileCMesh::setMesh(MEDCouplingCMesh *m)
6312 {
6313   dealWithTinyInfo(m);
6314   if(m)
6315     m->incrRef();
6316   _cmesh=m;
6317 }
6318
6319 MEDFileMesh *MEDFileCMesh::cartesianize() const
6320 {
6321   if(getAxisType()==AX_CART)
6322     {
6323       incrRef();
6324       return const_cast<MEDFileCMesh *>(this);
6325     }
6326   else
6327     {
6328       const MEDCouplingCMesh *cmesh(getMesh());
6329       if(!cmesh)
6330         throw INTERP_KERNEL::Exception("MEDFileCMesh::cartesianize : impossible to turn into cartesian because the mesh is null !");
6331       MCAuto<MEDCouplingCurveLinearMesh> clmesh(cmesh->buildCurveLinear());
6332       MCAuto<DataArrayDouble> coords(clmesh->getCoords()->cartesianize(getAxisType()));
6333       clmesh->setCoords(coords);
6334       MCAuto<MEDFileCurveLinearMesh> ret(MEDFileCurveLinearMesh::New());
6335       ret->MEDFileStructuredMesh::operator=(*this);
6336       ret->setMesh(clmesh);
6337       ret->setAxisType(AX_CART);
6338       return ret.retn();
6339     }
6340 }
6341
6342 void MEDFileCMesh::writeLL(med_idt fid) const
6343 {
6344   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
6345   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
6346   INTERP_KERNEL::AutoPtr<char> dtunit=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE);
6347   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
6348   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
6349   MEDLoaderBase::safeStrCpy(_dt_unit.c_str(),MED_LNAME_SIZE,dtunit,_too_long_str);
6350   int spaceDim(_cmesh->getSpaceDimension());
6351   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
6352   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
6353   for(int i=0;i<spaceDim;i++)
6354     {
6355       std::string info(_cmesh->getCoordsAt(i)->getInfoOnComponent(0));
6356       std::string c,u;
6357       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
6358       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
6359       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
6360     }
6361   MEDFILESAFECALLERWR0(MEDmeshCr,(fid,maa,spaceDim,spaceDim,MED_STRUCTURED_MESH,desc,dtunit,MED_SORT_DTIT,MEDFileMeshL2::TraduceAxisTypeRev(getAxisType()),comp,unit));
6362   if(_univ_wr_status)
6363     MEDFILESAFECALLERWR0(MEDmeshUniversalNameWr,(fid,maa));
6364   MEDFILESAFECALLERWR0(MEDmeshGridTypeWr,(fid,maa,MEDFileMeshL2::TraduceAxisTypeRevStruct(getAxisType())));
6365   for(int i=0;i<spaceDim;i++)
6366     {
6367       const DataArrayDouble *da=_cmesh->getCoordsAt(i);
6368       MEDFILESAFECALLERWR0(MEDmeshGridIndexCoordinateWr,(fid,maa,_iteration,_order,_time,i+1,da->getNumberOfTuples(),da->getConstPointer()));
6369     }
6370   //
6371   std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE));
6372   MEDFileStructuredMesh::writeStructuredLL(fid,meshName);
6373 }
6374
6375 void MEDFileCMesh::synchronizeTinyInfoOnLeaves() const
6376 {
6377   const MEDCouplingCMesh *cmesh=_cmesh;
6378   if(!cmesh)
6379     return;
6380   (const_cast<MEDCouplingCMesh *>(cmesh))->setName(_name);
6381   (const_cast<MEDCouplingCMesh *>(cmesh))->setDescription(_desc_name);
6382   (const_cast<MEDCouplingCMesh *>(cmesh))->setTime(_time,_iteration,_order);
6383   (const_cast<MEDCouplingCMesh *>(cmesh))->setTimeUnit(_dt_unit);
6384 }
6385
6386 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New()
6387 {
6388   return new MEDFileCurveLinearMesh;
6389 }
6390
6391 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const std::string& fileName, MEDFileMeshReadSelector *mrs)
6392 {
6393   std::vector<std::string> ms(MEDCoupling::GetMeshNames(fileName));
6394   if(ms.empty())
6395     {
6396       std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
6397       throw INTERP_KERNEL::Exception(oss.str().c_str());
6398     }
6399   MEDFileUtilities::CheckFileForRead(fileName);
6400   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
6401   int dt,it;
6402   MEDCoupling::MEDCouplingMeshType meshType;
6403   MEDCoupling::MEDCouplingAxisType dummy3;
6404   std::string dummy2;
6405   MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dummy3,dt,it,dummy2);
6406   return new MEDFileCurveLinearMesh(fid,ms.front(),dt,it,mrs);
6407 }
6408
6409 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const std::string& fileName, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6410 {
6411   MEDFileUtilities::CheckFileForRead(fileName);
6412   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
6413   return new MEDFileCurveLinearMesh(fid,mName,dt,it,mrs);
6414 }
6415
6416 std::size_t MEDFileCurveLinearMesh::getHeapMemorySizeWithoutChildren() const
6417 {
6418   return MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren();
6419 }
6420
6421 std::vector<const BigMemoryObject *> MEDFileCurveLinearMesh::getDirectChildrenWithNull() const
6422 {
6423   std::vector<const BigMemoryObject *> ret(MEDFileStructuredMesh::getDirectChildrenWithNull());
6424   ret.push_back((const MEDCouplingCurveLinearMesh *)_clmesh);
6425   return ret;
6426 }
6427
6428 MEDFileMesh *MEDFileCurveLinearMesh::shallowCpy() const
6429 {
6430   MCAuto<MEDFileCurveLinearMesh> ret(new MEDFileCurveLinearMesh(*this));
6431   return ret.retn();
6432 }
6433
6434 MEDFileMesh *MEDFileCurveLinearMesh::createNewEmpty() const
6435 {
6436   return new MEDFileCurveLinearMesh;
6437 }
6438
6439 MEDFileMesh *MEDFileCurveLinearMesh::deepCopy() const
6440 {
6441   MCAuto<MEDFileCurveLinearMesh> ret(new MEDFileCurveLinearMesh(*this));
6442   ret->deepCpyEquivalences(*this);
6443   if((const MEDCouplingCurveLinearMesh*)_clmesh)
6444     ret->_clmesh=static_cast<MEDCouplingCurveLinearMesh*>(_clmesh->deepCopy());
6445   ret->deepCpyAttributes();
6446   return ret.retn();
6447 }
6448
6449 int MEDFileCurveLinearMesh::getMeshDimension() const
6450 {
6451   if(!((const MEDCouplingCurveLinearMesh*)_clmesh))
6452     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::getMeshDimension : unable to get meshdimension because no mesh set !");
6453   return _clmesh->getMeshDimension();
6454 }
6455
6456 std::string MEDFileCurveLinearMesh::simpleRepr() const
6457 {
6458   return MEDFileStructuredMesh::simpleRepr();
6459 }
6460
6461 std::string MEDFileCurveLinearMesh::advancedRepr() const
6462 {
6463   return simpleRepr();
6464 }
6465
6466 bool MEDFileCurveLinearMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
6467 {
6468   if(!MEDFileStructuredMesh::isEqual(other,eps,what))
6469     return false;
6470   const MEDFileCurveLinearMesh *otherC=dynamic_cast<const MEDFileCurveLinearMesh *>(other);
6471   if(!otherC)
6472     {
6473       what="Mesh types differ ! This is curve linear and other is NOT !";
6474       return false;
6475     }
6476   clearNonDiscrAttributes();
6477   otherC->clearNonDiscrAttributes();
6478   const MEDCouplingCurveLinearMesh *coo1=_clmesh;
6479   const MEDCouplingCurveLinearMesh *coo2=otherC->_clmesh;
6480   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
6481     {
6482       what="Mismatch of curve linear meshes ! One is defined and not other !";
6483       return false;
6484     }
6485   if(coo1)
6486     {
6487       bool ret=coo1->isEqual(coo2,eps);
6488       if(!ret)
6489         {
6490           what="curve linear meshes differ !";
6491           return false;
6492         }
6493     }
6494   return true;
6495 }
6496
6497 void MEDFileCurveLinearMesh::clearNonDiscrAttributes() const
6498 {
6499   MEDFileStructuredMesh::clearNonDiscrAttributes();
6500   MEDFileUMeshSplitL1::ClearNonDiscrAttributes(_clmesh);//to it is not a bug umeshsplit have already the method implemented
6501 }
6502
6503 void MEDFileCurveLinearMesh::synchronizeTinyInfoOnLeaves() const
6504 {
6505   const MEDCouplingCurveLinearMesh *clmesh=_clmesh;
6506   if(!clmesh)
6507     return;
6508   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setName(_name);
6509   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setDescription(_desc_name);
6510   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setTime(_time,_iteration,_order);
6511   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setTimeUnit(_dt_unit);
6512 }
6513
6514 const MEDCouplingCurveLinearMesh *MEDFileCurveLinearMesh::getMesh() const
6515 {
6516   synchronizeTinyInfoOnLeaves();
6517   return _clmesh;
6518 }
6519
6520 void MEDFileCurveLinearMesh::setMesh(MEDCouplingCurveLinearMesh *m)
6521 {
6522   dealWithTinyInfo(m);
6523   if(m)
6524     m->incrRef();
6525   _clmesh=m;
6526 }
6527
6528 MEDFileMesh *MEDFileCurveLinearMesh::cartesianize() const
6529 {
6530   if(getAxisType()==AX_CART)
6531     {
6532       incrRef();
6533       return const_cast<MEDFileCurveLinearMesh *>(this);
6534     }
6535   else
6536     {
6537       const MEDCouplingCurveLinearMesh *mesh(getMesh());
6538       if(!mesh)
6539         throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::cartesianize : impossible to turn into cartesian because the mesh is null !");
6540       const DataArrayDouble *coords(mesh->getCoords());
6541       if(!coords)
6542         throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::cartesianize : coordinate pointer in mesh is null !");
6543       MCAuto<MEDFileCurveLinearMesh> ret(new MEDFileCurveLinearMesh(*this));
6544       MCAuto<MEDCouplingCurveLinearMesh> mesh2(mesh->clone(false));
6545       MCAuto<DataArrayDouble> coordsCart(coords->cartesianize(getAxisType()));
6546       mesh2->setCoords(coordsCart);
6547       ret->setMesh(mesh2);
6548       ret->setAxisType(AX_CART);
6549       return ret.retn();
6550     }
6551 }
6552
6553 const MEDCouplingStructuredMesh *MEDFileCurveLinearMesh::getStructuredMesh() const
6554 {
6555   synchronizeTinyInfoOnLeaves();
6556   return _clmesh;
6557 }
6558
6559 MEDFileCurveLinearMesh::MEDFileCurveLinearMesh()
6560 {
6561 }
6562
6563 MEDFileCurveLinearMesh::MEDFileCurveLinearMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6564 try
6565 {
6566     loadLLWithAdditionalItems(fid,mName,dt,it,mrs);
6567 }
6568 catch(INTERP_KERNEL::Exception& e)
6569 {
6570     throw e;
6571 }
6572
6573 void MEDFileCurveLinearMesh::writeLL(med_idt fid) const
6574 {
6575   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
6576   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
6577   INTERP_KERNEL::AutoPtr<char> dtunit=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE);
6578   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
6579   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
6580   MEDLoaderBase::safeStrCpy(_dt_unit.c_str(),MED_LNAME_SIZE,dtunit,_too_long_str);
6581   int spaceDim=_clmesh->getSpaceDimension();
6582   int meshDim=_clmesh->getMeshDimension();
6583   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
6584   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
6585   const DataArrayDouble *coords=_clmesh->getCoords();
6586   if(!coords)
6587     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::writeLL : no coordinates set !");
6588   for(int i=0;i<spaceDim;i++)
6589     {
6590       std::string info(_clmesh->getCoords()->getInfoOnComponent(i));
6591       std::string c,u;
6592       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
6593       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
6594       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
6595     }
6596   MEDFILESAFECALLERWR0(MEDmeshCr,(fid,maa,spaceDim,meshDim,MED_STRUCTURED_MESH,desc,dtunit,MED_SORT_DTIT,MEDFileMeshL2::TraduceAxisTypeRev(getAxisType()),comp,unit));
6597   if(_univ_wr_status)
6598     MEDFILESAFECALLERWR0(MEDmeshUniversalNameWr,(fid,maa));
6599   MEDFILESAFECALLERWR0(MEDmeshGridTypeWr,(fid,maa,MED_CURVILINEAR_GRID));
6600   std::vector<int> nodeGridSt=_clmesh->getNodeGridStructure();
6601   MEDFILESAFECALLERWR0(MEDmeshGridStructWr,(fid,maa,_iteration,_order,_time,&nodeGridSt[0]));
6602
6603   MEDFILESAFECALLERWR0(MEDmeshNodeCoordinateWr,(fid,maa,_iteration,_order,_time,MED_FULL_INTERLACE,coords->getNumberOfTuples(),coords->begin()));
6604   //
6605   std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE));
6606   MEDFileStructuredMesh::writeStructuredLL(fid,meshName);
6607 }
6608
6609 void MEDFileCurveLinearMesh::loadLL(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6610 {
6611   MEDCoupling::MEDCouplingMeshType meshType;
6612   int dummy0,dummy1;
6613   std::string dtunit;
6614   MEDCoupling::MEDCouplingAxisType axType;
6615   int mid=MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,axType,dummy0,dummy1,dtunit);
6616   setAxisType(axType);
6617   if(meshType!=CURVE_LINEAR)
6618     {
6619       std::ostringstream oss; oss << "Trying to load as curve linear an existing mesh with name '" << mName << "' that is NOT curve linear !";
6620       throw INTERP_KERNEL::Exception(oss.str().c_str());
6621     }
6622   MEDFileCLMeshL2 loaderl2;
6623   loaderl2.loadAll(fid,mid,mName,dt,it);
6624   MEDCouplingCurveLinearMesh *mesh=loaderl2.getMesh();
6625   mesh->incrRef();
6626   _clmesh=mesh;
6627   loadStrMeshFromFile(&loaderl2,fid,mName,dt,it,mrs);
6628 }
6629
6630 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New()
6631 {
6632   return new MEDFileMeshMultiTS;
6633 }
6634
6635 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(const std::string& fileName)
6636 {
6637   return new MEDFileMeshMultiTS(fileName);
6638 }
6639
6640 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(const std::string& fileName, const std::string& mName)
6641 {
6642   return new MEDFileMeshMultiTS(fileName,mName);
6643 }
6644
6645 MEDFileMeshMultiTS *MEDFileMeshMultiTS::deepCopy() const
6646 {
6647   MCAuto<MEDFileMeshMultiTS> ret=MEDFileMeshMultiTS::New();
6648   std::vector< MCAuto<MEDFileMesh> > meshOneTs(_mesh_one_ts.size());
6649   std::size_t i=0;
6650   for(std::vector< MCAuto<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++,i++)
6651     if((const MEDFileMesh *)*it)
6652       meshOneTs[i]=(*it)->deepCopy();
6653   ret->_mesh_one_ts=meshOneTs;
6654   return ret.retn();
6655 }
6656
6657 std::size_t MEDFileMeshMultiTS::getHeapMemorySizeWithoutChildren() const
6658 {
6659   return _mesh_one_ts.capacity()*sizeof(MCAuto<MEDFileMesh>);
6660 }
6661
6662 std::vector<const BigMemoryObject *> MEDFileMeshMultiTS::getDirectChildrenWithNull() const
6663 {
6664   std::vector<const BigMemoryObject *> ret;
6665   for(std::vector< MCAuto<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
6666     ret.push_back((const MEDFileMesh *)*it);
6667   return ret;
6668 }
6669
6670 std::string MEDFileMeshMultiTS::getName() const
6671 {
6672   if(_mesh_one_ts.empty())
6673     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::getName : no time steps set !");
6674   return _mesh_one_ts[0]->getName();
6675 }
6676
6677 void MEDFileMeshMultiTS::setName(const std::string& newMeshName)
6678 {
6679   std::string oldName(getName());
6680   std::vector< std::pair<std::string,std::string> > v(1);
6681   v[0].first=oldName; v[0].second=newMeshName;
6682   changeNames(v);
6683 }
6684
6685 bool MEDFileMeshMultiTS::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab)
6686 {
6687   bool ret=false;
6688   for(std::vector< MCAuto<MEDFileMesh> >::iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
6689     {
6690       MEDFileMesh *cur(*it);
6691       if(cur)
6692         ret=cur->changeNames(modifTab) || ret;
6693     }
6694   return ret;
6695 }
6696
6697 void MEDFileMeshMultiTS::cartesianizeMe()
6698 {
6699   for(std::vector< MCAuto<MEDFileMesh> >::iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
6700     {
6701       MEDFileMesh *cur(*it);
6702       if(cur)
6703         {
6704           MCAuto<MEDFileMesh> ccur(cur->cartesianize());// Attention ! Do not wrap these two lines because memory leak !
6705           *it=ccur;
6706         }
6707     }
6708 }
6709
6710 MEDFileMesh *MEDFileMeshMultiTS::getOneTimeStep() const
6711 {
6712   if(_mesh_one_ts.empty())
6713     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::getOneTimeStep : empty time step set !");
6714   return const_cast<MEDFileMesh *>(static_cast<const MEDFileMesh *>(_mesh_one_ts[0]));
6715 }
6716
6717 void MEDFileMeshMultiTS::setOneTimeStep(MEDFileMesh *mesh1TimeStep)
6718 {
6719   if(!mesh1TimeStep)
6720     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::setOneTimeStep : input pointer should be different from 0 !");
6721   _mesh_one_ts.resize(1);
6722   mesh1TimeStep->incrRef();
6723   //MCAuto<MEDFileMesh> toto=mesh1TimeStep;
6724   _mesh_one_ts[0]=mesh1TimeStep;
6725 }
6726
6727 MEDFileJoints * MEDFileMeshMultiTS::getJoints() const
6728 {
6729   if ( MEDFileMesh* m = getOneTimeStep() )
6730     return m->getJoints();
6731   return 0;
6732 }
6733
6734 /*!
6735  * \brief Set Joints that are common to all time-stamps
6736  */
6737 void MEDFileMeshMultiTS::setJoints( MEDFileJoints* joints )
6738 {
6739   for(std::vector< MCAuto<MEDFileMesh> >::iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
6740     {
6741       (*it)->setJoints( joints );
6742     }
6743 }
6744
6745 void MEDFileMeshMultiTS::write(med_idt fid) const
6746 {
6747   MEDFileJoints *joints(getJoints());
6748   bool jointsWritten(false);
6749
6750   for(std::vector< MCAuto<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
6751     {
6752       if ( jointsWritten )
6753         const_cast<MEDFileMesh&>(**it).setJoints( 0 );
6754       else
6755         jointsWritten = true;
6756
6757       (*it)->copyOptionsFrom(*this);
6758       (*it)->write(fid);
6759     }
6760
6761   (const_cast<MEDFileMeshMultiTS*>(this))->setJoints( joints ); // restore joints
6762 }
6763
6764 void MEDFileMeshMultiTS::write(const std::string& fileName, int mode) const
6765 {
6766   med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode);
6767   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),medmod);
6768   std::ostringstream oss; oss << "MEDFileMesh : error on attempt to write in file : \"" << fileName << "\""; 
6769   MEDFileUtilities::CheckMEDCode(fid,fid,oss.str());
6770   write(fid);
6771 }
6772
6773 void MEDFileMeshMultiTS::loadFromFile(const std::string& fileName, const std::string& mName)
6774 {
6775   MEDFileJoints* joints = 0;
6776   if ( !_mesh_one_ts.empty() && getOneTimeStep() )
6777     {
6778       // joints of mName already read, pass them to MEDFileMesh::New() to prevent repeated reading
6779       joints = getOneTimeStep()->getJoints();
6780     }
6781
6782   _mesh_one_ts.clear();  //for the moment to be improved
6783   _mesh_one_ts.push_back( MEDFileMesh::New(fileName,mName,-1,-1,0, joints ));
6784 }
6785
6786 MEDFileMeshMultiTS::MEDFileMeshMultiTS()
6787 {
6788 }
6789
6790 MEDFileMeshMultiTS::MEDFileMeshMultiTS(const std::string& fileName)
6791 try
6792 {
6793   std::vector<std::string> ms(MEDCoupling::GetMeshNames(fileName));
6794     if(ms.empty())
6795       {
6796         std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
6797         throw INTERP_KERNEL::Exception(oss.str().c_str());
6798       }
6799     MEDFileUtilities::CheckFileForRead(fileName);
6800     MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
6801     int dt,it;
6802     MEDCoupling::MEDCouplingMeshType meshType;
6803     std::string dummy2;
6804     MEDCoupling::MEDCouplingAxisType dummy3;
6805     MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dummy3,dt,it,dummy2);
6806     loadFromFile(fileName,ms.front());
6807 }
6808 catch(INTERP_KERNEL::Exception& e)
6809 {
6810     throw e;
6811 }
6812
6813 MEDFileMeshMultiTS::MEDFileMeshMultiTS(const std::string& fileName, const std::string& mName)
6814 try
6815 {
6816     loadFromFile(fileName,mName);
6817 }
6818 catch(INTERP_KERNEL::Exception& e)
6819 {
6820     throw e;
6821 }
6822
6823 MEDFileMeshes *MEDFileMeshes::New()
6824 {
6825   return new MEDFileMeshes;
6826 }
6827
6828 MEDFileMeshes *MEDFileMeshes::New(const std::string& fileName)
6829 {
6830   return new MEDFileMeshes(fileName);
6831 }
6832
6833 void MEDFileMeshes::write(med_idt fid) const
6834 {
6835   checkConsistencyLight();
6836   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++)
6837     {
6838       (*it)->copyOptionsFrom(*this);
6839       (*it)->write(fid);
6840     }
6841 }
6842
6843 void MEDFileMeshes::write(const std::string& fileName, int mode) const
6844 {
6845   med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode);
6846   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),medmod);
6847   std::ostringstream oss; oss << "MEDFileMesh : error on attempt to write in file : \"" << fileName << "\""; 
6848   MEDFileUtilities::CheckMEDCode(fid,fid,oss.str());
6849   checkConsistencyLight();
6850   write(fid);
6851 }
6852
6853 int MEDFileMeshes::getNumberOfMeshes() const
6854 {
6855   return _meshes.size();
6856 }
6857
6858 MEDFileMeshesIterator *MEDFileMeshes::iterator()
6859 {
6860   return new MEDFileMeshesIterator(this);
6861 }
6862
6863 /** Return a borrowed reference (caller is not responsible) */
6864 MEDFileMesh *MEDFileMeshes::getMeshAtPos(int i) const
6865 {
6866   if(i<0 || i>=(int)_meshes.size())
6867     {
6868       std::ostringstream oss; oss << "MEDFileMeshes::getMeshAtPos : invalid mesh id given in parameter ! Should be in [0;" << _meshes.size() << ") !";
6869       throw INTERP_KERNEL::Exception(oss.str().c_str());
6870     }
6871   return _meshes[i]->getOneTimeStep();
6872 }
6873
6874 /** Return a borrowed reference (caller is not responsible) */
6875 MEDFileMesh *MEDFileMeshes::getMeshWithName(const std::string& mname) const
6876 {
6877   std::vector<std::string> ms=getMeshesNames();
6878   std::vector<std::string>::iterator it=std::find(ms.begin(),ms.end(),mname);
6879   if(it==ms.end())
6880     {
6881       std::ostringstream oss; oss << "MEDFileMeshes::getMeshWithName : Mesh  \"" << mname << "\" does not exist in this ! Existing are : ";
6882       std::copy(ms.begin(),ms.end(),std::ostream_iterator<std::string>(oss," "));
6883       throw INTERP_KERNEL::Exception(oss.str().c_str());
6884     }
6885   return getMeshAtPos((int)std::distance(ms.begin(),it));
6886 }
6887
6888 std::vector<std::string> MEDFileMeshes::getMeshesNames() const
6889 {
6890   std::vector<std::string> ret(_meshes.size());
6891   int i=0;
6892   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
6893     {
6894       const MEDFileMeshMultiTS *f=(*it);
6895       if(f)
6896         {
6897           ret[i]=f->getName();
6898         }
6899       else
6900         {
6901           std::ostringstream oss; oss << "MEDFileMeshes::getMeshesNames : At rank #" << i << " mesh is not defined !";
6902           throw INTERP_KERNEL::Exception(oss.str().c_str());
6903         }
6904     }
6905   return ret;
6906 }
6907
6908 bool MEDFileMeshes::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab)
6909 {
6910   bool ret=false;
6911   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::iterator it=_meshes.begin();it!=_meshes.end();it++)
6912     {
6913       MEDFileMeshMultiTS *cur(*it);
6914       if(cur)
6915         ret=cur->changeNames(modifTab) || ret;
6916     }
6917   return ret;
6918 }
6919
6920 void MEDFileMeshes::cartesianizeMe()
6921 {
6922   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::iterator it=_meshes.begin();it!=_meshes.end();it++)
6923     {
6924       MEDFileMeshMultiTS *cur(*it);
6925       if(cur)
6926         cur->cartesianizeMe();
6927     }
6928 }
6929
6930 void MEDFileMeshes::resize(int newSize)
6931 {
6932   _meshes.resize(newSize);
6933 }
6934
6935 void MEDFileMeshes::pushMesh(MEDFileMesh *mesh)
6936 {
6937   if(!mesh)
6938     throw INTERP_KERNEL::Exception("MEDFileMeshes::pushMesh : invalid input pointer ! should be different from 0 !");
6939   MEDFileMeshMultiTS *elt=MEDFileMeshMultiTS::New();
6940   elt->setOneTimeStep(mesh);
6941   _meshes.push_back(elt);
6942 }
6943
6944 void MEDFileMeshes::setMeshAtPos(int i, MEDFileMesh *mesh)
6945 {
6946   if(!mesh)
6947     throw INTERP_KERNEL::Exception("MEDFileMeshes::setMeshAtPos : invalid input pointer ! should be different from 0 !");
6948   if(i>=(int)_meshes.size())
6949     _meshes.resize(i+1);
6950   MEDFileMeshMultiTS *elt=MEDFileMeshMultiTS::New();
6951   elt->setOneTimeStep(mesh);
6952   _meshes[i]=elt;
6953 }
6954
6955 void MEDFileMeshes::destroyMeshAtPos(int i)
6956 {
6957   if(i<0 || i>=(int)_meshes.size())
6958     {
6959       std::ostringstream oss; oss << "MEDFileMeshes::destroyMeshAtPos : Invalid given id in input (" << i << ") should be in [0," << _meshes.size() << ") !";
6960       throw INTERP_KERNEL::Exception(oss.str().c_str());
6961     }
6962   _meshes.erase(_meshes.begin()+i);
6963 }
6964
6965 void MEDFileMeshes::loadFromFile(const std::string& fileName)
6966 {
6967   std::vector<std::string> ms(MEDCoupling::GetMeshNames(fileName));
6968   int i=0;
6969   _meshes.resize(ms.size());
6970   for(std::vector<std::string>::const_iterator it=ms.begin();it!=ms.end();it++,i++)
6971     _meshes[i]=MEDFileMeshMultiTS::New(fileName,(*it));
6972 }
6973
6974 MEDFileMeshes::MEDFileMeshes()
6975 {
6976 }
6977
6978 MEDFileMeshes::MEDFileMeshes(const std::string& fileName)
6979 try
6980 {
6981     loadFromFile(fileName);
6982 }
6983 catch(INTERP_KERNEL::Exception& /*e*/)
6984 {
6985 }
6986
6987 MEDFileMeshes *MEDFileMeshes::deepCopy() const
6988 {
6989   std::vector< MCAuto<MEDFileMeshMultiTS> > meshes(_meshes.size());
6990   std::size_t i=0;
6991   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
6992     if((const MEDFileMeshMultiTS *)*it)
6993       meshes[i]=(*it)->deepCopy();
6994   MCAuto<MEDFileMeshes> ret=MEDFileMeshes::New();
6995   ret->_meshes=meshes;
6996   return ret.retn();
6997 }
6998
6999 std::size_t MEDFileMeshes::getHeapMemorySizeWithoutChildren() const
7000 {
7001   return _meshes.capacity()*(sizeof(MCAuto<MEDFileMeshMultiTS>));
7002 }
7003
7004 std::vector<const BigMemoryObject *> MEDFileMeshes::getDirectChildrenWithNull() const
7005 {
7006   std::vector<const BigMemoryObject *> ret;
7007   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++)
7008     ret.push_back((const MEDFileMeshMultiTS *)*it);
7009   return ret;
7010 }
7011
7012 std::string MEDFileMeshes::simpleRepr() const
7013 {
7014   std::ostringstream oss;
7015   oss << "(*****************)\n(* MEDFileMeshes *)\n(*****************)\n\n";
7016   simpleReprWithoutHeader(oss);
7017   return oss.str();
7018 }
7019
7020 void MEDFileMeshes::simpleReprWithoutHeader(std::ostream& oss) const
7021 {
7022   int nbOfMeshes=getNumberOfMeshes();
7023   oss << "There are " << nbOfMeshes << " meshes with the following names : \n";
7024   std::vector<std::string> mns=getMeshesNames();
7025   for(int i=0;i<nbOfMeshes;i++)
7026     oss << "  - #" << i << " \"" << mns[i] << "\"\n";
7027 }
7028
7029 void MEDFileMeshes::checkConsistencyLight() const
7030 {
7031   static const char MSG[]="MEDFileMeshes::checkConsistencyLight : mesh at rank ";
7032   int i=0;
7033   std::set<std::string> s;
7034   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
7035     {
7036       const MEDFileMeshMultiTS *elt=(*it);
7037       if(!elt)
7038         {
7039           std::ostringstream oss; oss << MSG << i << "/" << _meshes.size() << " is empty !";
7040           throw INTERP_KERNEL::Exception(oss.str().c_str());
7041         }
7042       std::size_t sz=s.size();
7043       s.insert(std::string((*it)->getName()));
7044       if(s.size()==sz)
7045         {
7046           std::ostringstream oss; oss << MSG << i << " has a name (\"" << (*it)->getName() << "\") already used by an another mesh in list !";
7047           throw INTERP_KERNEL::Exception(oss.str().c_str());
7048         }
7049     }
7050 }
7051
7052 MEDFileMeshesIterator::MEDFileMeshesIterator(MEDFileMeshes *ms):_ms(ms),_iter_id(0),_nb_iter(0)
7053 {
7054   if(ms)
7055     {
7056       ms->incrRef();
7057       _nb_iter=ms->getNumberOfMeshes();
7058     }
7059 }
7060
7061 MEDFileMeshesIterator::~MEDFileMeshesIterator()
7062 {
7063 }
7064
7065 MEDFileMesh *MEDFileMeshesIterator::nextt()
7066 {
7067   if(_iter_id<_nb_iter)
7068     {
7069       MEDFileMeshes *ms(_ms);
7070       if(ms)
7071         return ms->getMeshAtPos(_iter_id++);
7072       else
7073         return 0;
7074     }
7075   else
7076     return 0;
7077 }