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