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