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