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