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