Salome HOME
02be59c37deb6b9024b8bd0443a5a16a16929243
[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   _global_num_coords.nullify();
2633   for (std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=_ms.begin(); it != _ms.end(); it++)
2634     {
2635       (*it)->_num.nullify();
2636       (*it)->_rev_num.nullify();
2637       (*it)->_global_num.nullify();
2638     }
2639 }
2640
2641 /*!
2642  * Clears redundant attributes of incorporated data arrays.
2643  */
2644 void MEDFileUMesh::clearNonDiscrAttributes() const
2645 {
2646   MEDFileMesh::clearNonDiscrAttributes();
2647   if(_coords.isNotNull())
2648     _coords.iAmATrollConstCast()->setName("");//This parameter is not discriminant for comparison
2649   if(_fam_coords.isNotNull())
2650     _fam_coords.iAmATrollConstCast()->setName("");//This parameter is not discriminant for comparison
2651   if(_num_coords.isNotNull())
2652     _num_coords.iAmATrollConstCast()->setName("");//This parameter is not discriminant for comparison
2653   if(_name_coords.isNotNull())
2654     _name_coords.iAmATrollConstCast()->setName("");//This parameter is not discriminant for comparison
2655   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2656     {
2657       if((*it).isNotNull())
2658         (*it)->clearNonDiscrAttributes();
2659     }
2660 }
2661
2662 void MEDFileUMesh::setName(const std::string& name)
2663 {
2664   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
2665     if((*it).isNotNull())
2666       (*it)->setName(name);
2667   MEDFileMesh::setName(name);
2668 }
2669
2670 MEDFileUMesh::MEDFileUMesh()
2671 {
2672 }
2673
2674 MEDFileUMesh::MEDFileUMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
2675 try
2676 {
2677     loadLLWithAdditionalItems(fid,mName,dt,it,mrs);
2678 }
2679 catch(INTERP_KERNEL::Exception& e)
2680 {
2681     throw e;
2682 }
2683
2684 /*!
2685  * This method loads only a part of specified cells (given by range of cell ID per geometric type)
2686  * See MEDFileUMesh::LoadPartOf for detailed description.
2687  *
2688  * \sa loadLL
2689  */
2690 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)
2691 {
2692   MEDFileUMeshL2 loaderl2;
2693   MEDCoupling::MEDCouplingMeshType meshType;
2694   int dummy0,dummy1;
2695   std::string dummy2;
2696   MEDCoupling::MEDCouplingAxisType dummy3;
2697   INTERP_KERNEL::AutoCppPtr<MeshOrStructMeshCls> mid(MEDFileUMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy3,dummy0,dummy1,dummy2));
2698   if(meshType!=UNSTRUCTURED)
2699     {
2700       std::ostringstream oss; oss << "loadPartUMeshFromFile : Trying to load as unstructured an existing mesh with name '" << mName << "' !";
2701       throw INTERP_KERNEL::Exception(oss.str().c_str());
2702     }
2703   loaderl2.loadPart(fid,mid,mName,types,slicPerTyp,dt,it,mrs);
2704   dispatchLoadedPart(fid,loaderl2,mName,mrs);
2705 }
2706
2707 /*!
2708  * \brief Write joints in a file
2709  */
2710 void MEDFileMesh::writeJoints(med_idt fid) const
2711 {
2712   if ( _joints.isNotNull() )
2713     _joints->writeLL(fid);
2714 }
2715
2716 /*!
2717  * \brief Load joints in a file or use provided ones
2718  */
2719 //================================================================================
2720 /*!
2721  * \brief Load joints in a file or use provided ones
2722  *  \param [in] fid - MED file descriptor
2723  *  \param [in] toUseInstedOfReading - optional joints to use instead of reading,
2724  *          Usually this joints are those just read by another iteration
2725  *          of namesake mesh, when this method is called by MEDFileMeshMultiTS::New()
2726  */
2727 //================================================================================
2728
2729 void MEDFileMesh::loadJointsFromFile(med_idt fid, MEDFileJoints* toUseInstedOfReading)
2730 {
2731   if ( toUseInstedOfReading )
2732     setJoints( toUseInstedOfReading );
2733   else
2734     _joints = MEDFileJoints::New( fid, _name );
2735 }
2736
2737 void MEDFileMesh::loadEquivalences(med_idt fid)
2738 {
2739   int nbOfEq(MEDFileEquivalences::PresenceOfEquivalences(fid,_name));
2740   if(nbOfEq>0)
2741     _equiv=MEDFileEquivalences::Load(fid,nbOfEq,this);
2742 }
2743
2744 void MEDFileMesh::deepCpyEquivalences(const MEDFileMesh& other)
2745 {
2746   const MEDFileEquivalences *equiv(other._equiv);
2747   if(equiv)
2748     _equiv=equiv->deepCopy(this);
2749 }
2750
2751 bool MEDFileMesh::areEquivalencesEqual(const MEDFileMesh *other, std::string& what) const
2752 {
2753   const MEDFileEquivalences *thisEq(_equiv),*otherEq(other->_equiv);
2754   if(!thisEq && !otherEq)
2755     return true;
2756   if(thisEq && otherEq)
2757     return thisEq->isEqual(otherEq,what);
2758   else
2759     {
2760       what+="Equivalence differs : defined in this and not in other (or reversely) !";
2761       return false;
2762     }
2763 }
2764
2765 void MEDFileMesh::getEquivalencesRepr(std::ostream& oss) const
2766 {
2767   const MEDFileEquivalences *equiv(_equiv);
2768   if(!equiv)
2769     return ;
2770   oss << "(******************************)\n(* EQUIVALENCES OF THE MESH : *)\n(******************************)\n";
2771   _equiv->getRepr(oss);
2772 }
2773
2774 void MEDFileMesh::checkCartesian() const
2775 {
2776   if(getAxisType()!=AX_CART)
2777     {
2778       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()) << ").";
2779       oss << std::endl << "To perform operation you have two possiblities :" << std::endl;
2780       oss << " - call setAxisType(AX_CART)" << std::endl;
2781       oss << " - call cartesianize()";
2782       throw INTERP_KERNEL::Exception(oss.str().c_str());
2783     }
2784 }
2785
2786 /*!
2787  * \brief Return number of joints, which is equal to number of adjacent mesh domains
2788  */
2789 int MEDFileMesh::getNumberOfJoints() const
2790 {
2791   return ( (const MEDFileJoints *) _joints ) ? _joints->getNumberOfJoints() : 0;
2792 }
2793
2794 /*!
2795  * \brief Return joints with all adjacent mesh domains
2796  */
2797 MEDFileJoints * MEDFileMesh::getJoints() const
2798 {
2799   return const_cast<MEDFileJoints*>(& (*_joints));
2800 }
2801
2802 void MEDFileMesh::setJoints( MEDFileJoints* joints )
2803 {
2804   if ( joints != _joints )
2805     {
2806       _joints = joints;
2807       if ( joints )
2808         joints->incrRef();
2809     }
2810 }
2811
2812 /*!
2813  * This method loads \b all \b the \b mesh \a mName in the file with \a fid descriptor.
2814  *
2815  * \sa loadPartUMeshFromFile
2816  */
2817 void MEDFileUMesh::loadLL(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
2818 {
2819   MEDFileUMeshL2 loaderl2;
2820   MEDCoupling::MEDCouplingMeshType meshType;
2821   int dummy0,dummy1;
2822   std::string dummy2;
2823   MEDCoupling::MEDCouplingAxisType axType;
2824   INTERP_KERNEL::AutoCppPtr<MeshOrStructMeshCls> mid(MEDFileUMeshL2::GetMeshIdFromName(fid,mName,meshType,axType,dummy0,dummy1,dummy2));
2825   setAxisType(axType);
2826   if(meshType!=UNSTRUCTURED)
2827     {
2828       std::ostringstream oss; oss << "Trying to load as unstructured an existing mesh with name '" << mName << "' !";
2829       throw INTERP_KERNEL::Exception(oss.str().c_str());
2830     }
2831   loaderl2.loadAll(fid,mid,mName,dt,it,mrs);
2832   dispatchLoadedPart(fid,loaderl2,mName,mrs);
2833   // Structure element part...
2834   int nModels(-1);
2835   {
2836     med_bool chgt=MED_FALSE,trsf=MED_FALSE;
2837     nModels=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_STRUCT_ELEMENT,MED_GEO_ALL,MED_CONNECTIVITY,MED_NODAL,&chgt,&trsf);
2838   }
2839   if(nModels<=0)
2840     return ;
2841   _elt_str.resize(nModels);
2842   for(int i=0;i<nModels;i++)
2843     _elt_str[i]=MEDFileEltStruct4Mesh::New(fid,mName,dt,it,i,mrs);
2844 }
2845
2846 void MEDFileUMesh::dispatchLoadedPart(med_idt fid, const MEDFileUMeshL2& loaderl2, const std::string& mName, MEDFileMeshReadSelector *mrs)
2847 {
2848   int lev=loaderl2.getNumberOfLevels();
2849   _ms.resize(lev);
2850   for(int i=0;i<lev;i++)
2851     {
2852       if(!loaderl2.emptyLev(i))
2853         _ms[i]=new MEDFileUMeshSplitL1(loaderl2,mName,i);
2854       else
2855         _ms[i]=0;
2856     }
2857   MEDFileMeshL2::ReadFamiliesAndGrps(fid,mName,_families,_groups,mrs);
2858   //
2859   setName(loaderl2.getName());
2860   setDescription(loaderl2.getDescription());
2861   setUnivName(loaderl2.getUnivName());
2862   setIteration(loaderl2.getIteration());
2863   setOrder(loaderl2.getOrder());
2864   setTimeValue(loaderl2.getTime());
2865   setTimeUnit(loaderl2.getTimeUnit());
2866   _coords=loaderl2.getCoords();
2867   if(!mrs || mrs->isNodeFamilyFieldReading())
2868     _fam_coords=loaderl2.getCoordsFamily();
2869   if(!mrs || mrs->isNodeNumFieldReading())
2870     _num_coords=loaderl2.getCoordsNum();
2871   if(!mrs || mrs->isNodeNameFieldReading())
2872     _name_coords=loaderl2.getCoordsName();
2873   if(!mrs || mrs->isGlobalNodeNumFieldReading())
2874     _global_num_coords=loaderl2.getCoordsGlobalNum();
2875   _part_coords=loaderl2.getPartDefOfCoo();
2876   computeRevNum();
2877 }
2878
2879 MEDFileUMesh::~MEDFileUMesh()
2880 {
2881 }
2882
2883 void MEDFileUMesh::writeMeshLL(med_idt fid) const
2884 {
2885   const DataArrayDouble *coo=_coords;
2886   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
2887   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
2888   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
2889   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
2890   int spaceDim=coo?coo->getNumberOfComponents():0;
2891   int mdim(0);
2892   if(!_ms.empty())
2893     mdim=getMeshDimension();
2894   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
2895   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
2896   for(int i=0;i<spaceDim;i++)
2897     {
2898       std::string info=coo->getInfoOnComponent(i);
2899       std::string c,u;
2900       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
2901       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
2902       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
2903     }
2904   MEDFILESAFECALLERWR0(MEDmeshCr,(fid,maa,spaceDim,mdim,MED_UNSTRUCTURED_MESH,desc,"",MED_SORT_DTIT,MEDFileMeshL2::TraduceAxisTypeRev(getAxisType()),comp,unit));
2905   if(_univ_wr_status)
2906     MEDFILESAFECALLERWR0(MEDmeshUniversalNameWr,(fid,maa));
2907   std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE));
2908   MEDFileUMeshL2::WriteCoords(fid,meshName,_iteration,_order,_time,_coords,_fam_coords,_num_coords,_name_coords,_global_num_coords);
2909   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2910     if((const MEDFileUMeshSplitL1 *)(*it)!=0)
2911       (*it)->write(fid,meshName,mdim);
2912   MEDFileUMeshL2::WriteFamiliesAndGrps(fid,meshName,_families,_groups,_too_long_str);
2913 }
2914
2915 /*!
2916  * Returns relative dimensions of mesh entities (excluding nodes) present in \a this mesh.
2917  *  \return std::vector<int> - a sequence of the relative dimensions.
2918  */
2919 std::vector<int> MEDFileUMesh::getNonEmptyLevels() const
2920 {
2921   std::vector<int> ret;
2922   int lev=0;
2923   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
2924     if((const MEDFileUMeshSplitL1 *)(*it)!=0)
2925       if(!(*it)->empty())
2926         ret.push_back(lev);
2927   return ret;
2928 }
2929
2930 /*!
2931  * Returns relative dimensions of mesh entities (including nodes) present in \a this mesh.
2932  *  \return std::vector<int> - a sequence of the relative dimensions.
2933  */
2934 std::vector<int> MEDFileUMesh::getNonEmptyLevelsExt() const
2935 {
2936   std::vector<int> ret0=getNonEmptyLevels();
2937   if((const DataArrayDouble *) _coords)
2938     {
2939       std::vector<int> ret(ret0.size()+1);
2940       ret[0]=1;
2941       std::copy(ret0.begin(),ret0.end(),ret.begin()+1);
2942       return ret;
2943     }
2944   return ret0;
2945 }
2946
2947 std::vector<int> MEDFileUMesh::getFamArrNonEmptyLevelsExt() const
2948 {
2949   std::vector<int> ret;
2950   const DataArrayInt *famCoo(_fam_coords);
2951   if(famCoo)
2952     ret.push_back(1);
2953   int lev=0;
2954   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
2955     {
2956       const MEDFileUMeshSplitL1 *cur(*it);
2957       if(cur)
2958         if(cur->getFamilyField())
2959           ret.push_back(lev);
2960     }
2961   return ret;
2962 }
2963
2964 std::vector<int> MEDFileUMesh::getNumArrNonEmptyLevelsExt() const
2965 {
2966   std::vector<int> ret;
2967   if(_num_coords.isNotNull())
2968     ret.push_back(1);
2969   int lev=0;
2970   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
2971     {
2972       const MEDFileUMeshSplitL1 *cur(*it);
2973       if(cur)
2974         if(cur->getNumberField())
2975           ret.push_back(lev);
2976     }
2977   return ret;
2978 }
2979
2980 std::vector<int> MEDFileUMesh::getNameArrNonEmptyLevelsExt() const
2981 {
2982   std::vector<int> ret;
2983   const DataArrayAsciiChar *nameCoo(_name_coords);
2984   if(nameCoo)
2985     ret.push_back(1);
2986   int lev=0;
2987   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
2988     {
2989       const MEDFileUMeshSplitL1 *cur(*it);
2990       if(cur)
2991         if(cur->getNameField())
2992           ret.push_back(lev);
2993     }
2994   return ret;
2995 }
2996
2997 /*!
2998  * Returns all relative mesh levels (**excluding nodes**) where given families are defined.
2999  * To include nodes, call getFamsNonEmptyLevelsExt() method.
3000  *  \param [in] fams - the name of the family of interest.
3001  *  \return std::vector<int> - a sequence of the relative dimensions.
3002  */
3003 std::vector<int> MEDFileUMesh::getFamsNonEmptyLevels(const std::vector<std::string>& fams) const
3004 {
3005   std::vector<int> ret;
3006   std::vector<int> levs(getNonEmptyLevels());
3007   std::vector<int> famIds(getFamiliesIds(fams));
3008   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
3009     if(_ms[-(*it)]->presenceOfOneFams(famIds))
3010       ret.push_back(*it);
3011   return ret;
3012 }
3013
3014 /*!
3015  * Returns all relative mesh levels (including nodes) where given families are defined.
3016  *  \param [in] fams - the names of the families of interest.
3017  *  \return std::vector<int> - a sequence of the relative dimensions.
3018  */
3019 std::vector<int> MEDFileUMesh::getFamsNonEmptyLevelsExt(const std::vector<std::string>& fams) const
3020 {
3021   std::vector<int> ret0(getFamsNonEmptyLevels(fams));
3022   const DataArrayInt *famCoords(_fam_coords);
3023   if(!famCoords)
3024     return ret0;
3025   std::vector<int> famIds(getFamiliesIds(fams));
3026   if(famCoords->presenceOfValue(famIds))
3027     {
3028       std::vector<int> ret(ret0.size()+1);
3029       ret[0]=1;
3030       std::copy(ret0.begin(),ret0.end(),ret.begin()+1);
3031       return ret;
3032     }
3033   else
3034     return ret0;
3035 }
3036
3037 int MEDFileUMesh::getMaxAbsFamilyIdInArrays() const
3038 {
3039   int ret=-std::numeric_limits<int>::max(),tmp=-1;
3040   if((const DataArrayInt *)_fam_coords)
3041     {
3042       int val=_fam_coords->getMaxValue(tmp);
3043       ret=std::max(ret,std::abs(val));
3044     }
3045   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
3046     {
3047       if((const MEDFileUMeshSplitL1 *)(*it))
3048         {
3049           const DataArrayInt *da=(*it)->getFamilyField();
3050           if(da)
3051             {
3052               int val=da->getMaxValue(tmp);
3053               ret=std::max(ret,std::abs(val));
3054             }
3055         }
3056     }
3057   return ret;
3058 }
3059
3060 int MEDFileUMesh::getMaxFamilyIdInArrays() const
3061 {
3062   int ret=-std::numeric_limits<int>::max(),tmp=-1;
3063   if((const DataArrayInt *)_fam_coords)
3064     {
3065       int val=_fam_coords->getMaxValue(tmp);
3066       ret=std::max(ret,val);
3067     }
3068   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
3069     {
3070       if((const MEDFileUMeshSplitL1 *)(*it))
3071         {
3072           const DataArrayInt *da=(*it)->getFamilyField();
3073           if(da)
3074             {
3075               int val=da->getMaxValue(tmp);
3076               ret=std::max(ret,val);
3077             }
3078         }
3079     }
3080   return ret;
3081 }
3082
3083 int MEDFileUMesh::getMinFamilyIdInArrays() const
3084 {
3085   int ret=std::numeric_limits<int>::max(),tmp=-1;
3086   if((const DataArrayInt *)_fam_coords)
3087     {
3088       int val=_fam_coords->getMinValue(tmp);
3089       ret=std::min(ret,val);
3090     }
3091   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
3092     {
3093       if((const MEDFileUMeshSplitL1 *)(*it))
3094         {
3095           const DataArrayInt *da=(*it)->getFamilyField();
3096           if(da)
3097             {
3098               int val=da->getMinValue(tmp);
3099               ret=std::min(ret,val);
3100             }
3101         }
3102     }
3103   return ret;
3104 }
3105
3106 /*!
3107  * Returns the dimension on cells in \a this mesh.
3108  *  \return int - the mesh dimension.
3109  *  \throw If there are no cells in this mesh.
3110  */
3111 int MEDFileUMesh::getMeshDimension() const
3112 {
3113   int lev=0;
3114   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev++)
3115     if((const MEDFileUMeshSplitL1 *)(*it)!=0)
3116       return (*it)->getMeshDimension()+lev;
3117   throw INTERP_KERNEL::Exception("MEDFileUMesh::getMeshDimension : impossible to find a mesh dimension !");
3118 }
3119
3120 /*!
3121  * Returns the space dimension of \a this mesh that is equal to number of components in
3122  * the node coordinates array.
3123  *  \return int - the space dimension of \a this mesh.
3124  *  \throw If the node coordinates array is not available.
3125  */
3126 int MEDFileUMesh::getSpaceDimension() const
3127 {
3128   const DataArrayDouble *coo=_coords;
3129   if(!coo)
3130     throw INTERP_KERNEL::Exception(" MEDFileUMesh::getSpaceDimension : no coords set !");
3131   return coo->getNumberOfComponents();
3132 }
3133
3134 /*!
3135  * Returns a string describing \a this mesh.
3136  *  \return std::string - the mesh information string.
3137  */
3138 std::string MEDFileUMesh::simpleRepr() const
3139 {
3140   std::ostringstream oss;
3141   oss << MEDFileMesh::simpleRepr();
3142   const DataArrayDouble *coo=_coords;
3143   oss << "- The dimension of the space is ";
3144   static const char MSG1[]= "*** NO COORDS SET ***";
3145   static const char MSG2[]= "*** NO CONNECTIVITY SET FOR THIS LEVEL***";
3146   if(coo)
3147     oss << _coords->getNumberOfComponents() << std::endl;
3148   else
3149     oss << MSG1 << std::endl;
3150   oss << "- Type of the mesh : UNSTRUCTURED\n";
3151   oss << "- Number of nodes : ";
3152   if(coo)
3153     oss << _coords->getNumberOfTuples() << std::endl;
3154   else
3155     oss << MSG1 << std::endl;
3156   std::size_t nbOfLev=_ms.size();
3157   oss << "- Number of levels allocated : " << nbOfLev << std::endl;
3158   for(std::size_t i=0;i<nbOfLev;i++)
3159     {
3160       const MEDFileUMeshSplitL1 *lev=_ms[i];
3161       oss << "  - Level #" << -((int) i) << " has dimension : ";
3162       if(lev)
3163         {
3164           oss << lev->getMeshDimension() << std::endl;
3165           lev->simpleRepr(oss);
3166         }
3167       else
3168         oss << MSG2 << std::endl;
3169     }
3170   oss << "- Number of families : " << _families.size() << std::endl << std::endl;
3171   if(coo)
3172     {
3173       oss << "(***********************)\n(* NODES OF THE MESH : *)\n(***********************)\n";
3174       oss << "- Names of coordinates :" << std::endl;
3175       std::vector<std::string> vars=coo->getVarsOnComponent();
3176       std::copy(vars.begin(),vars.end(),std::ostream_iterator<std::string>(oss," "));
3177       oss << std::endl << "- Units of coordinates : " << std::endl;
3178       std::vector<std::string> units=coo->getUnitsOnComponent();
3179       std::copy(units.begin(),units.end(),std::ostream_iterator<std::string>(oss," "));
3180     }
3181   oss << std::endl << std::endl;
3182   getFamilyRepr(oss);
3183   getEquivalencesRepr(oss);
3184   return oss.str();
3185 }
3186
3187 /*!
3188  * Returns a full textual description of \a this mesh.
3189  *  \return std::string - the string holding the mesh description.
3190  */
3191 std::string MEDFileUMesh::advancedRepr() const
3192 {
3193   return simpleRepr();
3194 }
3195
3196 /*!
3197  * Returns number of mesh entities of a given relative dimension in \a this mesh.
3198  *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
3199  *  \return int - the number of entities.
3200  *  \throw If no mesh entities of dimension \a meshDimRelToMaxExt are available in \a this mesh.
3201  */
3202 int MEDFileUMesh::getSizeAtLevel(int meshDimRelToMaxExt) const
3203 {
3204   if(meshDimRelToMaxExt==1)
3205     {
3206       if(!((const DataArrayDouble *)_coords))
3207         throw INTERP_KERNEL::Exception("MEDFileUMesh::getSizeAtLevel : no coordinates specified !");
3208       return _coords->getNumberOfTuples();
3209     }
3210   return getMeshAtLevSafe(meshDimRelToMaxExt)->getSize();
3211 }
3212
3213 /*!
3214  * Returns the family field for mesh entities of a given dimension.
3215  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
3216  *  \return const DataArrayInt * - the family field. It is an array of ids of families
3217  *          each mesh entity belongs to. It can be \c NULL.
3218  */
3219 const DataArrayInt *MEDFileUMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) const
3220 {
3221   if(meshDimRelToMaxExt==1)
3222     return _fam_coords;
3223   const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMaxExt));
3224   return l1->getFamilyField();
3225 }
3226
3227 DataArrayInt *MEDFileUMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt)
3228 {
3229   if(meshDimRelToMaxExt==1)
3230     return _fam_coords;
3231   MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMaxExt));
3232   return l1->getFamilyField();
3233 }
3234
3235 /*!
3236  * Returns the optional numbers of mesh entities of a given dimension.
3237  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
3238  *  \return const DataArrayInt * - the array of the entity numbers.
3239  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3240  */
3241 const DataArrayInt *MEDFileUMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) const
3242 {
3243   if(meshDimRelToMaxExt==1)
3244     return _num_coords;
3245   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3246   return l1->getNumberField();
3247 }
3248
3249 const DataArrayAsciiChar *MEDFileUMesh::getNameFieldAtLevel(int meshDimRelToMaxExt) const
3250 {
3251   if(meshDimRelToMaxExt==1)
3252     return _name_coords;
3253   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3254   return l1->getNameField();
3255 }
3256
3257 MCAuto<DataArrayInt> MEDFileUMesh::getGlobalNumFieldAtLevel(int meshDimRelToMaxExt) const
3258 {
3259   if(meshDimRelToMaxExt!=1)
3260     throw INTERP_KERNEL::Exception("MEDFileUMesh::getGlobalNumFieldAtLevel : not implemented yet for structured mesh !");
3261   return _global_num_coords;
3262 }
3263
3264 /*!
3265  * 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).
3266  *
3267  * \param [in] meshDimRelToMaxExt - the extended relative level for which the part definition is requested.
3268  * \param [in] gt - The input geometric type for which the part definition is requested.
3269  * \return the part definition owned by \a this. So no need to deallocate the returned instance.
3270  */
3271 const PartDefinition *MEDFileUMesh::getPartDefAtLevel(int meshDimRelToMaxExt, INTERP_KERNEL::NormalizedCellType gt) const
3272 {
3273   if(meshDimRelToMaxExt==1)
3274     return _part_coords;
3275   const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMaxExt));
3276   return l1->getPartDef(gt);
3277 }
3278
3279 int MEDFileUMesh::getNumberOfNodes() const
3280 {
3281   const DataArrayDouble *coo(_coords);
3282   if(!coo)
3283     throw INTERP_KERNEL::Exception(" MEDFileUMesh::getNumberOfNodes : no coords set !");
3284   return coo->getNumberOfTuples();
3285 }
3286
3287 int MEDFileUMesh::getNumberOfCellsAtLevel(int meshDimRelToMaxExt) const
3288 {
3289   const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMaxExt));
3290   return l1->getNumberOfCells();
3291 }
3292
3293 bool MEDFileUMesh::hasImplicitPart() const
3294 {
3295   return false;
3296 }
3297
3298 int MEDFileUMesh::buildImplicitPartIfAny(INTERP_KERNEL::NormalizedCellType gt) const
3299 {
3300   throw INTERP_KERNEL::Exception("MEDFileUMesh::buildImplicitPartIfAny : unstructured meshes do not have implicit part !");
3301 }
3302
3303 void MEDFileUMesh::releaseImplicitPartIfAny() const
3304 {
3305 }
3306
3307 void MEDFileUMesh::whichAreNodesFetched(const MEDFileField1TSStructItem& st, const MEDFileFieldGlobsReal *globs, std::vector<bool>& nodesFetched) const
3308 {
3309   std::size_t sz(st.getNumberOfItems());
3310   for(std::size_t i=0;i<sz;i++)
3311     {
3312       INTERP_KERNEL::NormalizedCellType curGt(st[i].getGeo());
3313       const MEDCoupling1GTUMesh *m(getDirectUndergroundSingleGeoTypeMesh(curGt));
3314       if(st[i].getPflName().empty())
3315         m->computeNodeIdsAlg(nodesFetched);
3316       else
3317         {
3318           const DataArrayInt *arr(globs->getProfile(st[i].getPflName()));
3319           MCAuto<MEDCoupling1GTUMesh> m2(dynamic_cast<MEDCoupling1GTUMesh *>(m->buildPartOfMySelf(arr->begin(),arr->end(),true)));
3320           m2->computeNodeIdsAlg(nodesFetched);
3321         }
3322     }
3323 }
3324
3325 MEDFileMesh *MEDFileUMesh::cartesianize() const
3326 {
3327   if(getAxisType()==AX_CART)
3328     {
3329       incrRef();
3330       return const_cast<MEDFileUMesh *>(this);
3331     }
3332   else
3333     {
3334       MCAuto<MEDFileUMesh> ret(new MEDFileUMesh(*this));
3335       const DataArrayDouble *coords(_coords);
3336       if(!coords)
3337         throw INTERP_KERNEL::Exception("MEDFileUMesh::cartesianize : coordinates are null !");
3338       MCAuto<DataArrayDouble> coordsCart(_coords->cartesianize(getAxisType()));
3339       for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=ret->_ms.begin();it!=ret->_ms.end();it++)
3340         if((const MEDFileUMeshSplitL1 *)(*it))
3341           *it=(*it)->shallowCpyUsingCoords(coordsCart);
3342       ret->_coords=coordsCart;
3343       ret->setAxisType(AX_CART);
3344       return ret.retn();
3345     }
3346 }
3347
3348 bool MEDFileUMesh::presenceOfStructureElements() const
3349 {
3350   for(std::vector< MCAuto<MEDFileEltStruct4Mesh> >::const_iterator it=_elt_str.begin();it!=_elt_str.end();it++)
3351     if((*it).isNotNull())
3352       return true;
3353   return false;
3354 }
3355
3356 void MEDFileUMesh::killStructureElements()
3357 {
3358   _elt_str.clear();
3359 }
3360
3361 /*!
3362  * Returns the optional numbers of mesh entities of a given dimension transformed using
3363  * DataArrayInt::invertArrayN2O2O2N().
3364  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
3365  *  \return const DataArrayInt * - the array of the entity numbers transformed using
3366  *          DataArrayInt::invertArrayN2O2O2N().
3367  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3368  */
3369 const DataArrayInt *MEDFileUMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxExt) const
3370 {
3371   if(meshDimRelToMaxExt==1)
3372     {
3373       if(_num_coords.isNotNull())
3374         throw INTERP_KERNEL::Exception("MEDFileUMesh::getRevNumberFieldAtLevel : no coordinates renum specified !");
3375       return _rev_num_coords;
3376     }
3377   const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMaxExt));
3378   return l1->getRevNumberField();
3379 }
3380
3381 /*!
3382  * Returns a pointer to the node coordinates array of \a this mesh \b without
3383  * incrementing its reference counter, thus there is no need to decrRef() it by the caller.
3384  */
3385 DataArrayDouble *MEDFileUMesh::getCoords() const
3386 {
3387   checkCartesian();
3388   MCAuto<DataArrayDouble> tmp(_coords);
3389   if((DataArrayDouble *)tmp)
3390     {
3391       return tmp;
3392     }
3393   return 0;
3394 }
3395
3396 /*!
3397  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in a given
3398  * group of \a this mesh. Only mesh entities of a given dimension are included in the
3399  * new mesh.
3400  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
3401  *  \param [in] grp - the name of the group whose mesh entities are included in the
3402  *          new mesh.
3403  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
3404  *          according to the optional numbers of entities, if available.
3405  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
3406  *          delete this mesh using decrRef() as it is no more needed.
3407  *  \throw If the name of a nonexistent group is specified.
3408  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3409  */
3410 MEDCouplingUMesh *MEDFileUMesh::getGroup(int meshDimRelToMaxExt, const std::string& grp, bool renum) const
3411 {
3412   checkCartesian();
3413   synchronizeTinyInfoOnLeaves();
3414   std::vector<std::string> tmp(1);
3415   tmp[0]=grp;
3416   return getGroups(meshDimRelToMaxExt,tmp,renum);
3417 }
3418
3419 /*!
3420  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in given
3421  * groups of \a this mesh. Only mesh entities of a given dimension are included in the
3422  * new mesh.
3423  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
3424  *  \param [in] grps - a sequence of group names whose mesh entities are included in the
3425  *          new mesh.
3426  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
3427  *          according to the optional numbers of entities, if available.
3428  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
3429  *          delete this mesh using decrRef() as it is no more needed.
3430  *  \throw If a name of a nonexistent group is present in \a grps.
3431  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3432  */
3433 MEDCouplingUMesh *MEDFileUMesh::getGroups(int meshDimRelToMaxExt, const std::vector<std::string>& grps, bool renum) const
3434 {
3435   checkCartesian();
3436   synchronizeTinyInfoOnLeaves();
3437   std::vector<std::string> fams2=getFamiliesOnGroups(grps);
3438   MCAuto<MEDCouplingUMesh> zeRet=getFamilies(meshDimRelToMaxExt,fams2,renum);
3439   if(grps.size()==1 && ((MEDCouplingUMesh *)zeRet))
3440     zeRet->setName(grps[0]);
3441   return zeRet.retn();
3442 }
3443
3444 /*!
3445  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in a given
3446  * family of \a this mesh. Only mesh entities of a given dimension are included in the
3447  * new mesh.
3448  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
3449  *  \param [in] fam - the name of the family whose mesh entities are included in the
3450  *          new mesh.
3451  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
3452  *          according to the optional numbers of entities, if available.
3453  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
3454  *          delete this mesh using decrRef() as it is no more needed.
3455  *  \throw If a name of a nonexistent family is present in \a grps.
3456  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3457  */
3458 MEDCouplingUMesh *MEDFileUMesh::getFamily(int meshDimRelToMaxExt, const std::string& fam, bool renum) const
3459 {
3460   checkCartesian();
3461   synchronizeTinyInfoOnLeaves();
3462   std::vector<std::string> tmp(1);
3463   tmp[0]=fam;
3464   return getFamilies(meshDimRelToMaxExt,tmp,renum);
3465 }
3466
3467 /*!
3468  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in given
3469  * families of \a this mesh. Only mesh entities of a given dimension are included in the
3470  * new mesh.
3471  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
3472  *  \param [in] fams - a sequence of family names whose mesh entities are included in the
3473  *          new mesh.
3474  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
3475  *          according to the optional numbers of entities, if available.
3476  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
3477  *          delete this mesh using decrRef() as it is no more needed.
3478  *  \throw If a name of a nonexistent family is present in \a fams.
3479  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3480  */
3481 MEDCouplingUMesh *MEDFileUMesh::getFamilies(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const
3482 {
3483   checkCartesian();
3484   synchronizeTinyInfoOnLeaves();
3485   if(meshDimRelToMaxExt==1)
3486     {
3487       MCAuto<DataArrayInt> arr=getFamiliesArr(1,fams,renum);
3488       MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3489       MCAuto<DataArrayDouble> c=_coords->selectByTupleId(arr->getConstPointer(),arr->getConstPointer()+arr->getNbOfElems());
3490       ret->setCoords(c);
3491       return ret.retn();
3492     }
3493   std::vector<int> famIds=getFamiliesIds(fams);
3494   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3495   MCAuto<MEDCouplingUMesh> zeRet;
3496   if(!famIds.empty())
3497     zeRet=l1->getFamilyPart(&famIds[0],&famIds[0]+famIds.size(),renum);
3498   else
3499     zeRet=l1->getFamilyPart(0,0,renum);
3500   if(fams.size()==1 && ((MEDCouplingUMesh *)zeRet))
3501     zeRet->setName(fams[0]);
3502   return zeRet.retn();
3503 }
3504
3505 /*!
3506  * Returns ids of mesh entities contained in given families of a given dimension.
3507  *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
3508  *          are required.
3509  *  \param [in] fams - the names of the families of interest.
3510  *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
3511  *          returned instead of ids.
3512  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
3513  *          numbers, if available and required, of mesh entities of the families. The caller
3514  *          is to delete this array using decrRef() as it is no more needed. 
3515  *  \throw If the family field is missing for \a meshDimRelToMaxExt.
3516  */
3517 DataArrayInt *MEDFileUMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const
3518 {
3519   std::vector<int> famIds=getFamiliesIds(fams);
3520   if(meshDimRelToMaxExt==1)
3521     {
3522       if((const DataArrayInt *)_fam_coords)
3523         {
3524           MCAuto<DataArrayInt> da;
3525           if(!famIds.empty())
3526             da=_fam_coords->findIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
3527           else
3528             da=_fam_coords->findIdsEqualList(0,0);
3529           if(renum)
3530             return MEDFileUMeshSplitL1::Renumber(_num_coords,da);
3531           else
3532             return da.retn();
3533         }
3534       else
3535         throw INTERP_KERNEL::Exception("MEDFileUMesh::getFamiliesArr : no family array specified on nodes !");
3536     }
3537   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3538   if(!famIds.empty())
3539     return l1->getFamilyPartArr(&famIds[0],&famIds[0]+famIds.size(),renum);
3540   else
3541     return l1->getFamilyPartArr(0,0,renum);
3542 }
3543
3544 /*!
3545  * Returns a MEDCouplingUMesh of a given relative dimension.
3546  * \warning If \a meshDimRelToMaxExt == 1 (which means nodes), the returned mesh **is not
3547  * valid**. This is a feature, because MEDLoader does not create cells that do not exist! 
3548  * To build a valid MEDCouplingUMesh from the returned one in this case,
3549  * call MEDCouplingUMesh::Build0DMeshFromCoords().
3550  *  \param [in] meshDimRelToMax - the relative dimension of interest.
3551  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3552  *          optional numbers of mesh entities.
3553  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
3554  *          delete using decrRef() as it is no more needed. 
3555  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3556  */
3557 MEDCouplingUMesh *MEDFileUMesh::getMeshAtLevel(int meshDimRelToMaxExt, bool renum) const
3558 {
3559   checkCartesian();
3560   synchronizeTinyInfoOnLeaves();
3561   if(meshDimRelToMaxExt==1)
3562     {
3563       if(!renum)
3564         {
3565           MEDCouplingUMesh *umesh=MEDCouplingUMesh::New();
3566           MCAuto<DataArrayDouble> cc=_coords->deepCopy();
3567           umesh->setCoords(cc);
3568           MEDFileUMeshSplitL1::ClearNonDiscrAttributes(umesh);
3569           umesh->setName(getName());
3570           return umesh;
3571         }
3572     }
3573   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3574   return l1->getWholeMesh(renum);
3575 }
3576
3577 std::vector<int> MEDFileUMesh::getDistributionOfTypes(int meshDimRelToMax) const
3578 {
3579   const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMax));
3580   return l1->getDistributionOfTypes();
3581 }
3582
3583 /*!
3584  * Returns a MEDCouplingUMesh of a relative dimension == 0.
3585  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3586  *          optional numbers of mesh entities.
3587  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
3588  *          delete using decrRef() as it is no more needed. 
3589  *  \throw If there are no mesh entities of the relative dimension == 0 in \a this mesh.
3590  */
3591 MEDCouplingUMesh *MEDFileUMesh::getLevel0Mesh(bool renum) const
3592 {
3593   return getMeshAtLevel(0,renum);
3594 }
3595
3596 /*!
3597  * Returns a MEDCouplingUMesh of a relative dimension == -1.
3598  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3599  *          optional numbers of mesh entities.
3600  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
3601  *          delete using decrRef() as it is no more needed. 
3602  *  \throw If there are no mesh entities of the relative dimension == -1 in \a this mesh.
3603  */
3604 MEDCouplingUMesh *MEDFileUMesh::getLevelM1Mesh(bool renum) const
3605 {
3606   return getMeshAtLevel(-1,renum);
3607 }
3608
3609 /*!
3610  * Returns a MEDCouplingUMesh of a relative dimension == -2.
3611  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3612  *          optional numbers of mesh entities.
3613  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
3614  *          delete using decrRef() as it is no more needed. 
3615  *  \throw If there are no mesh entities of the relative dimension == -2 in \a this mesh.
3616  */
3617 MEDCouplingUMesh *MEDFileUMesh::getLevelM2Mesh(bool renum) const
3618 {
3619   return getMeshAtLevel(-2,renum);
3620 }
3621
3622 /*!
3623  * Returns a MEDCouplingUMesh of a relative dimension == -3.
3624  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3625  *          optional numbers of mesh entities.
3626  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
3627  *          delete using decrRef() as it is no more needed. 
3628  *  \throw If there are no mesh entities of the relative dimension == -3 in \a this mesh.
3629  */
3630 MEDCouplingUMesh *MEDFileUMesh::getLevelM3Mesh(bool renum) const
3631 {
3632   return getMeshAtLevel(-3,renum);
3633 }
3634
3635 /*!
3636  * This method is for advanced users. There is two storing strategy of mesh in \a this.
3637  * Either MEDCouplingUMesh, or vector of MEDCoupling1GTUMesh instances.
3638  * When assignement is done the first one is done, which is not optimal in write mode for MED file.
3639  * This method allows to switch from MEDCouplingUMesh mode to MEDCoupling1GTUMesh mode.
3640  */
3641 void MEDFileUMesh::forceComputationOfParts() const
3642 {
3643   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
3644     {
3645       const MEDFileUMeshSplitL1 *elt(*it);
3646       if(elt)
3647         elt->forceComputationOfParts();
3648     }
3649 }
3650
3651 /*!
3652  * This method returns a vector of mesh parts containing each exactly one geometric type.
3653  * This method will never launch an automatic computation of split by type (an INTERP_KERNEL::Exception will be then thrown).
3654  * This method is only for memory aware users.
3655  * The returned pointers are **NOT** new object pointer. No need to mange them.
3656  */
3657 std::vector<MEDCoupling1GTUMesh *> MEDFileUMesh::getDirectUndergroundSingleGeoTypeMeshes(int meshDimRelToMax) const
3658 {
3659   checkCartesian();
3660   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(meshDimRelToMax));
3661   return sp->getDirectUndergroundSingleGeoTypeMeshes();
3662 }
3663
3664 /*!
3665  * This method returns the part of \a this having the geometric type \a gt.
3666  * If such part is not existing an exception will be thrown.
3667  * The returned pointer is **NOT** new object pointer. No need to mange it.
3668  */
3669 MEDCoupling1GTUMesh *MEDFileUMesh::getDirectUndergroundSingleGeoTypeMesh(INTERP_KERNEL::NormalizedCellType gt) const
3670 {
3671   checkCartesian();
3672   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(gt));
3673   int lev=(int)cm.getDimension()-getMeshDimension();
3674   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(lev));
3675   return sp->getDirectUndergroundSingleGeoTypeMesh(gt);
3676 }
3677
3678 /*!
3679  * This method returns for each geo types in \a this number of cells with this geo type.
3680  * 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.
3681  * This method also returns the number of nodes of \a this (key associated is NORM_ERROR)
3682  *
3683  * \sa getDistributionOfTypes
3684  */
3685 std::vector< std::pair<int,int> > MEDFileUMesh::getAllDistributionOfTypes() const
3686 {
3687   std::vector< std::pair<int,int> > ret;
3688   std::vector<int> nel(getNonEmptyLevels());
3689   for(std::vector<int>::reverse_iterator it=nel.rbegin();it!=nel.rend();it++)
3690     {
3691       std::vector<INTERP_KERNEL::NormalizedCellType> gt(getGeoTypesAtLevel(*it));
3692       for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it1=gt.begin();it1!=gt.end();it1++)
3693         {
3694           int nbCells(getNumberOfCellsWithType(*it1));
3695           ret.push_back(std::pair<int,int>(*it1,nbCells));
3696         }
3697     }
3698   ret.push_back(std::pair<int,int>(INTERP_KERNEL::NORM_ERROR,getNumberOfNodes()));
3699   return ret;
3700 }
3701
3702 /*!
3703  * Given a relative level \a meshDimRelToMax it returns the sorted vector of geometric types present in \a this.
3704  * \throw if the reqsuested \a meshDimRelToMax does not exist.
3705  */
3706 std::vector<INTERP_KERNEL::NormalizedCellType> MEDFileUMesh::getGeoTypesAtLevel(int meshDimRelToMax) const
3707 {
3708   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(meshDimRelToMax));
3709   return sp->getGeoTypes();
3710 }
3711
3712 int MEDFileUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType ct) const
3713 {
3714   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(ct);
3715   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe( ((int)cm.getDimension())-getMeshDimension() ));
3716   return sp->getNumberOfCellsWithType(ct);
3717 }
3718
3719 /*!
3720  * This method extracts from whole family field ids the part relative to the input parameter \a gt.
3721  * \param [in] gt - the geometric type for which the family field is asked.
3722  * \return DataArrayInt * - a pointer to DataArrayInt that the caller is to
3723  *          delete using decrRef() as it is no more needed.
3724  * \sa MEDFileUMesh::extractNumberFieldOnGeoType
3725  */
3726 DataArrayInt *MEDFileUMesh::extractFamilyFieldOnGeoType(INTERP_KERNEL::NormalizedCellType gt) const
3727 {
3728   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
3729   int lev=(int)cm.getDimension()-getMeshDimension();
3730   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(lev));
3731   return sp->extractFamilyFieldOnGeoType(gt);
3732 }
3733
3734 /*!
3735  * This method extracts from whole number field ids the part relative to the input parameter \a gt.
3736  * \param [in] gt - the geometric type for which the number field is asked.
3737  * \return DataArrayInt * - a pointer to DataArrayInt that the caller is to
3738  *          delete using decrRef() as it is no more needed.
3739  * \sa MEDFileUMesh::extractFamilyFieldOnGeoType
3740  */
3741 DataArrayInt *MEDFileUMesh::extractNumberFieldOnGeoType(INTERP_KERNEL::NormalizedCellType gt) const
3742 {
3743   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
3744   int lev=(int)cm.getDimension()-getMeshDimension();
3745   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(lev));
3746   return sp->extractNumberFieldOnGeoType(gt);
3747 }
3748
3749 /*!
3750  * This method returns for specified geometric type \a gt the relative level to \a this.
3751  * If the relative level is empty an exception will be thrown.
3752  */
3753 int MEDFileUMesh::getRelativeLevOnGeoType(INTERP_KERNEL::NormalizedCellType gt) const
3754 {
3755   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
3756   int ret((int)cm.getDimension()-getMeshDimension());
3757   getMeshAtLevSafe(ret);//To test that returned value corresponds to a valid level.
3758   return ret;
3759 }
3760
3761 const MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt) const
3762 {
3763   if(meshDimRelToMaxExt==1)
3764     throw INTERP_KERNEL::Exception("Dimension request is invalid : asking for node level (1) !");
3765   if(meshDimRelToMaxExt>1)
3766     throw INTERP_KERNEL::Exception("Dimension request is invalid (>1) !");
3767   int tracucedRk=-meshDimRelToMaxExt;
3768   if(tracucedRk>=(int)_ms.size())
3769     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
3770   if((const MEDFileUMeshSplitL1 *)_ms[tracucedRk]==0)
3771     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3772   return _ms[tracucedRk];
3773 }
3774
3775 MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt)
3776 {
3777   if(meshDimRelToMaxExt==1)
3778     throw INTERP_KERNEL::Exception("Dimension request is invalid : asking for node level (1) !");
3779   if(meshDimRelToMaxExt>1)
3780     throw INTERP_KERNEL::Exception("Dimension request is invalid (>1) !");
3781   int tracucedRk=-meshDimRelToMaxExt;
3782   if(tracucedRk>=(int)_ms.size())
3783     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
3784   if((const MEDFileUMeshSplitL1 *)_ms[tracucedRk]==0)
3785     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3786   return _ms[tracucedRk];
3787 }
3788
3789 void MEDFileUMesh::checkMeshDimCoherency(int meshDim, int meshDimRelToMax) const
3790 {
3791   if(-meshDimRelToMax>=(int)_ms.size())
3792     throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMeshDimCoherency : The meshdim of mesh is not managed by 'this' !");
3793   int i=0;
3794   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,i++)
3795     {
3796       if(((const MEDFileUMeshSplitL1*) (*it))!=0)
3797         {
3798           int ref=(*it)->getMeshDimension();
3799           if(ref+i!=meshDim-meshDimRelToMax)
3800             throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMeshDimCoherency : no coherency between levels !");
3801         }
3802     }
3803 }
3804
3805 /*!
3806  * Sets the node coordinates array of \a this mesh.
3807  *  \param [in] coords - the new node coordinates array.
3808  *  \throw If \a coords == \c NULL.
3809  */
3810 void MEDFileUMesh::setCoords(DataArrayDouble *coords)
3811 {
3812   if(!coords)
3813     throw INTERP_KERNEL::Exception("MEDFileUMesh::setCoords : null pointer in input !");
3814   if(coords==(DataArrayDouble *)_coords)
3815     return ;
3816   coords->checkAllocated();
3817   int nbOfTuples(coords->getNumberOfTuples());
3818   _coords.takeRef(coords);
3819   _fam_coords=DataArrayInt::New();
3820   _fam_coords->alloc(nbOfTuples,1);
3821   _fam_coords->fillWithZero();
3822   _num_coords.nullify(); _rev_num_coords.nullify(); _name_coords.nullify(); _global_num_coords.nullify();
3823   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
3824     if((MEDFileUMeshSplitL1 *)(*it))
3825       (*it)->setCoords(coords);
3826 }
3827
3828 /*!
3829  * Change coords without changing anything concerning families and numbering on nodes.
3830  */
3831 void MEDFileUMesh::setCoordsForced(DataArrayDouble *coords)
3832 {
3833   if(!coords)
3834     throw INTERP_KERNEL::Exception("MEDFileUMesh::setCoordsForced : null pointer in input !");
3835   if(coords==(DataArrayDouble *)_coords)
3836     return ;
3837   coords->checkAllocated();
3838   int nbOfTuples(coords->getNumberOfTuples());
3839   if(_coords.isNull())
3840     {
3841       _coords=coords;
3842       coords->incrRef();
3843     }
3844   else
3845     {
3846       int oldNbTuples(_coords->getNumberOfTuples());
3847       if(oldNbTuples!=nbOfTuples)
3848         throw INTERP_KERNEL::Exception("MEDFileUMesh::setCoordsForced : number of tuples is not the same -> invoke setCoords instead !");
3849       _coords=coords;
3850       coords->incrRef();
3851     }
3852   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
3853     if((MEDFileUMeshSplitL1 *)(*it))
3854       (*it)->setCoords(coords);
3855 }
3856
3857 /*!
3858  * Removes all groups of a given dimension in \a this mesh.
3859  *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
3860  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3861  */
3862 void MEDFileUMesh::eraseGroupsAtLevel(int meshDimRelToMaxExt)
3863 {
3864   if(meshDimRelToMaxExt==1)
3865     {
3866       if((DataArrayInt *)_fam_coords)
3867         _fam_coords->fillWithZero();
3868       return ;
3869     }
3870   MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3871   l1->eraseFamilyField();
3872   optimizeFamilies();
3873 }
3874
3875 /*!
3876  * Removes all families with ids not present in the family fields of \a this mesh.
3877  */
3878 void MEDFileUMesh::optimizeFamilies()
3879 {
3880   std::vector<int> levs=getNonEmptyLevelsExt();
3881   std::set<int> allFamsIds;
3882   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
3883     {
3884       const DataArrayInt *ffield=getFamilyFieldAtLevel(*it);
3885       MCAuto<DataArrayInt> ids=ffield->getDifferentValues();
3886       std::set<int> res;
3887       std::set_union(ids->begin(),ids->end(),allFamsIds.begin(),allFamsIds.end(),std::inserter(res,res.begin()));
3888       allFamsIds=res;
3889     }
3890   std::set<std::string> famNamesToKill;
3891   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
3892     {
3893       if(allFamsIds.find((*it).second)!=allFamsIds.end())
3894         famNamesToKill.insert((*it).first);
3895     }
3896   for(std::set<std::string>::const_iterator it=famNamesToKill.begin();it!=famNamesToKill.end();it++)
3897     _families.erase(*it);
3898   std::vector<std::string> grpNamesToKill;
3899   for(std::map<std::string, std::vector<std::string> >::iterator it=_groups.begin();it!=_groups.end();it++)
3900     {
3901       std::vector<std::string> tmp;
3902       for(std::vector<std::string>::const_iterator it2=(*it).second.begin();it2!=(*it).second.end();it2++)
3903         {
3904           if(famNamesToKill.find(*it2)==famNamesToKill.end())
3905             tmp.push_back(*it2);
3906         }
3907       if(!tmp.empty())
3908         (*it).second=tmp;
3909       else
3910         tmp.push_back((*it).first);
3911     }
3912   for(std::vector<std::string>::const_iterator it=grpNamesToKill.begin();it!=grpNamesToKill.end();it++)
3913     _groups.erase(*it);
3914 }
3915
3916 /**
3917  * \b this must be filled at level 0 and -1, typically the -1 level being (part of) the descending connectivity
3918  * of the top level. This method build a "crack", or an inner boundary, in \b this along the group of level -1 named grpNameM1.
3919  * The boundary is built according to the following method:
3920  *  - all nodes along the boundary which are not lying on an internal extremity of the (-1)-level group are duplicated (so the
3921  * coordinates array is extended).
3922  *  - new (-1)-level cells are built lying on those new nodes. So the edges/faces along the group are duplicated. A new group
3923  *  called "<grpNameM1>_dup" containing the effectively duplicated cells is created. Note that in 3D some cells of the group
3924  *  might not be duplicated at all.
3925  *  After this operation a top-level cell bordering the group will loose some neighbors (typically the cell which is  on the
3926  *  other side of the group is no more a neighbor)
3927  *   - finally, the connectivity of (part of) the top level-cells bordering the group is also modified so that some cells
3928  *  bordering the newly created boundary use the newly computed nodes.
3929  *  Finally note that optional cell numbers are also affected by this method and might become invalid for SMESH.
3930  *  Use clearNodeAndCellNumbers() afterwards to ensure a proper SMESH loading.
3931  *
3932  *  \param[in] grpNameM1 name of the (-1)-level group defining the boundary
3933  *  \param[out] nodesDuplicated ids of the initial nodes which have been duplicated (and whose copy is put at the end of
3934  *  the coord array)
3935  *  \param[out] cellsModified ids of the cells whose connectivity has been modified (to use the newly created nodes)
3936  *  \param[out] cellsNotModified ids of the rest of cells bordering the new boundary whose connectivity remains unchanged.
3937  *  \sa clearNodeAndCellNumbers()
3938  */
3939 void MEDFileUMesh::buildInnerBoundaryAlongM1Group(const std::string& grpNameM1, DataArrayInt *&nodesDuplicated,
3940                                            DataArrayInt *&cellsModified, DataArrayInt *&cellsNotModified)
3941 {
3942   typedef MCAuto<MEDCouplingUMesh> MUMesh;
3943   typedef MCAuto<DataArrayInt> DAInt;
3944
3945   std::vector<int> levs=getNonEmptyLevels();
3946   if(std::find(levs.begin(),levs.end(),0)==levs.end() || std::find(levs.begin(),levs.end(),-1)==levs.end())
3947     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildInnerBoundaryAlongM1Group : This method works only for mesh definied on level 0 and -1 !");
3948   MUMesh m0=getMeshAtLevel(0);
3949   MUMesh m1=getMeshAtLevel(-1);
3950   int nbNodes=m0->getNumberOfNodes();
3951   MUMesh m11=getGroup(-1,grpNameM1);
3952   DataArrayInt *tmp00=0,*tmp11=0,*tmp22=0;
3953   m0->findNodesToDuplicate(*m11,tmp00,tmp11,tmp22);
3954   DAInt nodeIdsToDuplicate(tmp00);
3955   DAInt cellsToModifyConn0(tmp11);
3956   DAInt cellsToModifyConn1(tmp22);
3957   MUMesh tmp0=static_cast<MEDCouplingUMesh *>(m0->buildPartOfMySelf(cellsToModifyConn0->begin(),cellsToModifyConn0->end(),true));
3958   // node renumbering of cells in m1 impacted by duplication of node but not in group 'grpNameM1' on level -1
3959   DAInt descTmp0=DataArrayInt::New(),descITmp0=DataArrayInt::New(),revDescTmp0=DataArrayInt::New(),revDescITmp0=DataArrayInt::New();
3960   MUMesh tmp0Desc=tmp0->buildDescendingConnectivity(descTmp0,descITmp0,revDescTmp0,revDescITmp0);
3961   descTmp0=0; descITmp0=0; revDescTmp0=0; revDescITmp0=0;
3962   DAInt cellsInM1ToRenumW2=tmp0Desc->getCellIdsLyingOnNodes(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),false);
3963   MUMesh cellsInM1ToRenumW3=static_cast<MEDCouplingUMesh *>(tmp0Desc->buildPartOfMySelf(cellsInM1ToRenumW2->begin(),cellsInM1ToRenumW2->end(),true));
3964   DataArrayInt *cellsInM1ToRenumW4Tmp=0;
3965   m1->areCellsIncludedIn(cellsInM1ToRenumW3,2,cellsInM1ToRenumW4Tmp);
3966   DAInt cellsInM1ToRenumW4(cellsInM1ToRenumW4Tmp);
3967   DAInt cellsInM1ToRenumW5=cellsInM1ToRenumW4->findIdsInRange(0,m1->getNumberOfCells());
3968   cellsInM1ToRenumW5->transformWithIndArr(cellsInM1ToRenumW4->begin(),cellsInM1ToRenumW4->end());
3969   DAInt grpIds=getGroupArr(-1,grpNameM1);
3970   DAInt cellsInM1ToRenum=cellsInM1ToRenumW5->buildSubstraction(grpIds);
3971   MUMesh m1Part=static_cast<MEDCouplingUMesh *>(m1->buildPartOfMySelf(cellsInM1ToRenum->begin(),cellsInM1ToRenum->end(),true));
3972   m1Part->duplicateNodesInConn(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),nbNodes);
3973   m1->setPartOfMySelf(cellsInM1ToRenum->begin(),cellsInM1ToRenum->end(),*m1Part);
3974   // end of node renumbering of cells in m1 impacted by duplication of node but not in group of level -1 'grpNameM1'
3975   tmp0->duplicateNodes(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end());
3976   m0->setCoords(tmp0->getCoords());
3977   m0->setPartOfMySelf(cellsToModifyConn0->begin(),cellsToModifyConn0->end(),*tmp0);
3978   _ms[0]->forceComputationOfParts();  // necessary because we modify the connectivity of some internal part
3979   m1->setCoords(m0->getCoords());
3980   _coords=m0->getCoords(); _coords->incrRef();
3981   // duplication of cells in group 'grpNameM1' on level -1, but not duplicating cells for which nothing has changed
3982   m11->duplicateNodesInConn(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),nbNodes); m11->setCoords(m0->getCoords());
3983   DataArrayInt * duplCells;
3984   m1->areCellsIncludedIn(m11, 0, duplCells);
3985   DAInt zeIds = duplCells->findIdsNotInRange(-1, m1->getNumberOfCells()-1); duplCells->decrRef();
3986   MUMesh m11Part=static_cast<MEDCouplingUMesh *>(m11->buildPartOfMySelf(zeIds->begin(),zeIds->end(),true));
3987   std::vector<const MEDCouplingUMesh *> v(2); v[0]=m1; v[1]=m11Part;
3988   MUMesh newm1=MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(v,tmp00,tmp11);
3989   DAInt szOfCellGrpOfSameType(tmp00);
3990   DAInt idInMsOfCellGrpOfSameType(tmp11);
3991   //
3992   newm1->setName(getName());
3993   const DataArrayInt *fam=getFamilyFieldAtLevel(-1);
3994   if(!fam)
3995     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildInnerBoundaryAlongM1Group(): internal error no family field !");
3996   DAInt newFam=DataArrayInt::New();
3997   newFam->alloc(newm1->getNumberOfCells(),1);
3998   // Get a new family ID: care must be taken if we need a positive ID or a negative one:
3999   // Positive ID for family of nodes, negative for all the rest.
4000   int idd;
4001   if (m1->getMeshDimension() == 0)
4002     idd=getMaxFamilyId()+1;
4003   else
4004     idd=getMinFamilyId()-1;
4005   int globStart=0,start=0,end,globEnd;
4006   int nbOfChunks=szOfCellGrpOfSameType->getNumberOfTuples();
4007   for(int i=0;i<nbOfChunks;i++)
4008     {
4009       globEnd=globStart+szOfCellGrpOfSameType->getIJ(i,0);
4010       if(idInMsOfCellGrpOfSameType->getIJ(i,0)==0)
4011         {
4012           end=start+szOfCellGrpOfSameType->getIJ(i,0);
4013           DAInt part=fam->selectByTupleIdSafeSlice(start,end,1);
4014           newFam->setPartOfValues1(part,globStart,globEnd,1,0,1,1,true);
4015           start=end;
4016         }
4017       else
4018         {
4019           newFam->setPartOfValuesSimple1(idd,globStart,globEnd,1,0,1,1);
4020         }
4021       globStart=globEnd;
4022     }
4023   newm1->setCoords(getCoords());
4024   setMeshAtLevel(-1,newm1);
4025   setFamilyFieldArr(-1,newFam);
4026   std::string grpName2(grpNameM1); grpName2+="_dup";
4027   addFamily(grpName2,idd);
4028   addFamilyOnGrp(grpName2,grpName2);
4029   //
4030   fam=_fam_coords;
4031   if(fam)
4032     {
4033       int newNbOfNodes=getCoords()->getNumberOfTuples();
4034       newFam=DataArrayInt::New(); newFam->alloc(newNbOfNodes,1);
4035       newFam->setPartOfValues1(fam,0,nbNodes,1,0,1,1,true);
4036       newFam->setPartOfValuesSimple1(0,nbNodes,newNbOfNodes,1,0,1,1);
4037       _fam_coords=newFam;
4038     }
4039
4040   _num_coords.nullify(); _rev_num_coords.nullify(); _global_num_coords.nullify();
4041   
4042   for (std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();
4043       it != _ms.end(); it++)
4044     {
4045       (*it)->_num = 0;
4046       (*it)->_rev_num = 0;
4047     }
4048   nodesDuplicated=nodeIdsToDuplicate.retn();
4049   cellsModified=cellsToModifyConn0.retn();
4050   cellsNotModified=cellsToModifyConn1.retn();
4051 }
4052
4053 /*! Similar to MEDCouplingUMesh::unPolyze():  converts all polygons (if \a this is a 2D mesh) or polyhedrons
4054  * (if \a this is a 3D mesh) to cells of classical types. The cells remain correctly sorted by geometric type
4055  * in this method.
4056  *
4057  * \param [out] oldCode retrieves the distribution of types before the call if true is returned
4058  * \param [out] newCode etrieves the distribution of types after the call if true is returned
4059  * \param [out] o2nRenumCell tells for **all levels** the old 2 new renumbering of cells.
4060  * 
4061  * \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.
4062  * 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.
4063  */
4064 bool MEDFileUMesh::unPolyze(std::vector<int>& oldCode, std::vector<int>& newCode, DataArrayInt *& o2nRenumCell)
4065 {
4066   o2nRenumCell=0; oldCode.clear(); newCode.clear();
4067   std::vector<int> levs=getNonEmptyLevels();
4068   bool ret=false;
4069   std::vector< const DataArrayInt* > renumCellsSplited;//same than memorySaverIfThrow
4070   std::vector< MCAuto<DataArrayInt> > memorySaverIfThrow;//same than renumCellsSplited only in case of throw
4071   int start=0;
4072   int end=0;
4073   for(std::vector<int>::reverse_iterator it=levs.rbegin();it!=levs.rend();it++)
4074     {
4075       MCAuto<MEDCouplingUMesh> m=getMeshAtLevel(*it);
4076       std::vector<int> code1=m->getDistributionOfTypes();
4077       end=PutInThirdComponentOfCodeOffset(code1,start);
4078       oldCode.insert(oldCode.end(),code1.begin(),code1.end());
4079       bool hasChanged=m->unPolyze();
4080       DataArrayInt *fake=0;
4081       MCAuto<DataArrayInt> o2nCellsPart=m->getLevArrPerCellTypes(MEDCouplingUMesh::MEDMEM_ORDER,
4082           MEDCouplingUMesh::MEDMEM_ORDER+MEDCouplingUMesh::N_MEDMEM_ORDER,fake);
4083       fake->decrRef();
4084       renumCellsSplited.push_back(o2nCellsPart); memorySaverIfThrow.push_back(o2nCellsPart);
4085       if(hasChanged)
4086         {
4087           MCAuto<DataArrayInt> o2nCellsPart2=o2nCellsPart->buildPermArrPerLevel();
4088           m->renumberCells(o2nCellsPart2->getConstPointer(),false);
4089           ret=true;
4090           MCAuto<DataArrayInt> famField2,numField2;
4091           const DataArrayInt *famField=getFamilyFieldAtLevel(*it); if(famField) { famField->incrRef(); famField2=const_cast<DataArrayInt *>(famField); }
4092           const DataArrayInt *numField=getNumberFieldAtLevel(*it); if(numField) { numField->incrRef(); numField2=const_cast<DataArrayInt *>(numField); }
4093           setMeshAtLevel(*it,m);
4094           std::vector<int> code2=m->getDistributionOfTypes();
4095           end=PutInThirdComponentOfCodeOffset(code2,start);
4096           newCode.insert(newCode.end(),code2.begin(),code2.end());
4097           //
4098           if(o2nCellsPart2->isIota(o2nCellsPart2->getNumberOfTuples()))
4099             continue;
4100           if(famField)
4101             {
4102               MCAuto<DataArrayInt> newFamField=famField->renumber(o2nCellsPart2->getConstPointer());
4103               setFamilyFieldArr(*it,newFamField);
4104             }
4105           if(numField)
4106             {
4107               MCAuto<DataArrayInt> newNumField=numField->renumber(o2nCellsPart2->getConstPointer());
4108               setRenumFieldArr(*it,newNumField);
4109             }
4110         }
4111       else
4112         {
4113           newCode.insert(newCode.end(),code1.begin(),code1.end());
4114         }
4115       start=end;
4116     }
4117   if(ret)
4118     {
4119       MCAuto<DataArrayInt> renumCells=DataArrayInt::Aggregate(renumCellsSplited);
4120       MCAuto<DataArrayInt> o2nRenumCellRet=renumCells->buildPermArrPerLevel();
4121       o2nRenumCell=o2nRenumCellRet.retn();
4122     }
4123   return ret;
4124 }
4125
4126 /*! \cond HIDDEN_ITEMS */
4127 struct MEDLoaderAccVisit1
4128 {
4129   MEDLoaderAccVisit1():_new_nb_of_nodes(0) { }
4130   int operator()(bool val) { return val?_new_nb_of_nodes++:-1; }
4131   int _new_nb_of_nodes;
4132 };
4133 /*! \endcond */
4134
4135 /*!
4136  * 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.
4137  * The maximum value stored in returned array is the number of nodes of \a this minus 1 after call of this method.
4138  * The size of returned array is the number of nodes of the old (previous to the call of this method) number of nodes.
4139  * -1 values in returned array means that the corresponding old node is no more used.
4140  *
4141  * \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
4142  *         is modified in \a this.
4143  * \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
4144  *  set coordinates.
4145  */
4146 DataArrayInt *MEDFileUMesh::zipCoords()
4147 {
4148   const DataArrayDouble *coo(getCoords());
4149   if(!coo)
4150     throw INTERP_KERNEL::Exception("MEDFileUMesh::zipCoords : no coordinates set in this !");
4151   int nbOfNodes(coo->getNumberOfTuples());
4152   std::vector<bool> nodeIdsInUse(nbOfNodes,false);
4153   std::vector<int> neLevs(getNonEmptyLevels());
4154   for(std::vector<int>::const_iterator lev=neLevs.begin();lev!=neLevs.end();lev++)
4155     {
4156       const MEDFileUMeshSplitL1 *zeLev(getMeshAtLevSafe(*lev));
4157       if(zeLev->isMeshStoredSplitByType())
4158         {
4159           std::vector<MEDCoupling1GTUMesh *> ms(zeLev->getDirectUndergroundSingleGeoTypeMeshes());
4160           for(std::vector<MEDCoupling1GTUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
4161             if(*it)
4162               (*it)->computeNodeIdsAlg(nodeIdsInUse);
4163         }
4164       else
4165         {
4166           MCAuto<MEDCouplingUMesh> mesh(zeLev->getWholeMesh(false));
4167           mesh->computeNodeIdsAlg(nodeIdsInUse);
4168         }
4169     }
4170   int nbrOfNodesInUse((int)std::count(nodeIdsInUse.begin(),nodeIdsInUse.end(),true));
4171   if(nbrOfNodesInUse==nbOfNodes)
4172     return 0;//no need to update _part_coords
4173   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodes,1);
4174   std::transform(nodeIdsInUse.begin(),nodeIdsInUse.end(),ret->getPointer(),MEDLoaderAccVisit1());
4175   MCAuto<DataArrayInt> ret2(ret->invertArrayO2N2N2OBis(nbrOfNodesInUse));
4176   MCAuto<DataArrayDouble> newCoords(coo->selectByTupleIdSafe(ret2->begin(),ret2->end()));
4177   MCAuto<DataArrayInt> newFamCoords;
4178   MCAuto<DataArrayAsciiChar> newNameCoords;
4179   if((const DataArrayInt *)_fam_coords)
4180     newFamCoords=_fam_coords->selectByTupleIdSafe(ret2->begin(),ret2->end());
4181   MCAuto<DataArrayInt> newNumCoords,newGlobalNumCoords;
4182   if(_num_coords.isNotNull())
4183     newNumCoords=_num_coords->selectByTupleIdSafe(ret2->begin(),ret2->end());
4184   if(_global_num_coords.isNotNull())
4185     newGlobalNumCoords=_global_num_coords->selectByTupleIdSafe(ret2->begin(),ret2->end());
4186   if(_name_coords.isNotNull())
4187     newNameCoords=static_cast<DataArrayAsciiChar *>(_name_coords->selectByTupleIdSafe(ret2->begin(),ret2->end()));
4188   _coords=newCoords; _fam_coords=newFamCoords; _num_coords=newNumCoords; _global_num_coords=newGlobalNumCoords; _name_coords=newNameCoords; _rev_num_coords.nullify();
4189   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
4190     {
4191       if((MEDFileUMeshSplitL1*)*it)
4192         {
4193           (*it)->renumberNodesInConn(ret->begin());
4194           (*it)->setCoords(_coords);
4195         }
4196     }
4197   // updates _part_coords
4198   const PartDefinition *pc(_part_coords);
4199   if(pc)
4200     {
4201       MCAuto<PartDefinition> tmpPD(DataArrayPartDefinition::New(ret2));
4202       _part_coords=tmpPD->composeWith(pc);
4203     }
4204   return ret.retn();
4205 }
4206
4207 /*!
4208  * This method is a const method. It computes the minimal set of node ids covered by the cell extraction of \a this.
4209  * The extraction of \a this is specified by the extractDef \a input map.
4210  * This map tells for each level of cells, the cells kept in the extraction.
4211  * 
4212  * \return - a new reference of DataArrayInt that represents sorted node ids, the extraction is lying on.
4213  * \sa MEDFileField1TS::extractPart, MEDFileUMesh::extractPart
4214  */
4215 DataArrayInt *MEDFileUMesh::deduceNodeSubPartFromCellSubPart(const std::map<int, MCAuto<DataArrayInt> >& extractDef) const
4216 {
4217   std::vector<int> levs(getNonEmptyLevels());
4218   std::vector<bool> fetchedNodes(getNumberOfNodes(),false);
4219   for(std::map<int, MCAuto<DataArrayInt> >::const_iterator it=extractDef.begin();it!=extractDef.end();it++)
4220     {
4221       if((*it).first>1)
4222         throw INTERP_KERNEL::Exception("MEDFileUMesh::deduceNodeSubPartFromCellSubPart : invalid key ! Must be <=1 !");
4223       if((*it).second.isNull())
4224         throw INTERP_KERNEL::Exception("MEDFileUMesh::deduceNodeSubPartFromCellSubPart : presence of a value with null pointer !");
4225       if((*it).first==1)
4226         continue;
4227       if(std::find(levs.begin(),levs.end(),(*it).first)==levs.end())
4228         {
4229           std::ostringstream oss; oss << "MEDFileUMesh::deduceNodeSubPartFromCellSubPart : invalid level " << (*it).first << " ! Not present in this !";
4230           throw INTERP_KERNEL::Exception(oss.str());
4231         }
4232       MCAuto<MEDCouplingUMesh> m(getMeshAtLevel((*it).first));
4233       MCAuto<MEDCouplingUMesh> mPart(m->buildPartOfMySelf((*it).second->begin(),(*it).second->end(),true));
4234       mPart->computeNodeIdsAlg(fetchedNodes);
4235     }
4236   return DataArrayInt::BuildListOfSwitchedOn(fetchedNodes);
4237 }
4238
4239 /*!
4240  * This method returns a new MEDFileUMesh that is the result of the extraction of cells/nodes in \a this.
4241  * 
4242  * \return - a new reference of MEDFileUMesh
4243  * \sa MEDFileUMesh::deduceNodeSubPartFromCellSubPart, MEDFileFields::extractPart
4244  */
4245 MEDFileUMesh *MEDFileUMesh::extractPart(const std::map<int, MCAuto<DataArrayInt> >& extractDef) const
4246 {
4247   MCAuto<MEDFileUMesh> ret(MEDFileUMesh::New()); ret->setName(getName()); ret->copyFamGrpMapsFrom(*this);
4248   std::vector<int> levs(getNonEmptyLevels());
4249   for(std::map<int, MCAuto<DataArrayInt> >::const_iterator it=extractDef.begin();it!=extractDef.end();it++)
4250     {
4251       if((*it).first>1)
4252         throw INTERP_KERNEL::Exception("MEDFileUMesh::extractPart : invalid key ! Must be <=1 !");
4253       if((*it).second.isNull())
4254         throw INTERP_KERNEL::Exception("MEDFileUMesh::extractPart : presence of a value with null pointer !");
4255       if((*it).first==1)
4256         continue;
4257       if(std::find(levs.begin(),levs.end(),(*it).first)==levs.end())
4258         {
4259           std::ostringstream oss; oss << "MEDFileUMesh::extractPart : invalid level " << (*it).first << " ! Not present in this !";
4260           throw INTERP_KERNEL::Exception(oss.str());
4261         }
4262       MCAuto<MEDCouplingUMesh> m(getMeshAtLevel((*it).first));
4263       MCAuto<MEDCouplingUMesh> mPart(m->buildPartOfMySelf((*it).second->begin(),(*it).second->end(),true));
4264       ret->setMeshAtLevel((*it).first,mPart);
4265       const DataArrayInt *fam(getFamilyFieldAtLevel((*it).first)),*num(getNumberFieldAtLevel((*it).first));
4266       if(fam)
4267         {
4268           MCAuto<DataArrayInt> famPart(fam->selectByTupleIdSafe((*it).second->begin(),(*it).second->end()));
4269           ret->setFamilyFieldArr((*it).first,famPart);
4270         }
4271       if(num)
4272         {
4273           MCAuto<DataArrayInt> numPart(num->selectByTupleIdSafe((*it).second->begin(),(*it).second->end()));
4274           ret->setFamilyFieldArr((*it).first,numPart);
4275         }
4276     }
4277   std::map<int, MCAuto<DataArrayInt> >::const_iterator it2(extractDef.find(1));
4278   if(it2!=extractDef.end())
4279     {
4280       const DataArrayDouble *coo(ret->getCoords());
4281       if(!coo)
4282         throw INTERP_KERNEL::Exception("MEDFileUMesh::extractPart : trying to extract nodes whereas there is no nodes !");
4283       MCAuto<DataArrayInt> o2nNodes(((*it2).second)->invertArrayN2O2O2N(coo->getNumberOfTuples()));
4284       MCAuto<DataArrayDouble> cooPart(coo->selectByTupleIdSafe((*it2).second->begin(),(*it2).second->end()));
4285       ret->setCoords(cooPart);
4286       const DataArrayInt *fam(getFamilyFieldAtLevel(1)),*num(getNumberFieldAtLevel(1));
4287       if(fam)
4288         {
4289           MCAuto<DataArrayInt> famPart(fam->selectByTupleIdSafe((*it2).second->begin(),(*it2).second->end()));
4290           ret->setFamilyFieldArr(1,famPart);
4291         }
4292       if(num)
4293         {
4294           MCAuto<DataArrayInt> numPart(num->selectByTupleIdSafe((*it2).second->begin(),(*it2).second->end()));
4295           ret->setFamilyFieldArr(1,numPart);
4296         }
4297       for(std::map<int, MCAuto<DataArrayInt> >::const_iterator it3=extractDef.begin();it3!=extractDef.end();it3++)
4298         {
4299           if((*it3).first==1)
4300             continue;
4301           MCAuto<MEDCouplingUMesh> m(ret->getMeshAtLevel((*it3).first));
4302           m->renumberNodesInConn(o2nNodes->begin());
4303           ret->setMeshAtLevel((*it3).first,m);
4304         }
4305     }
4306   return ret.retn();
4307 }
4308
4309 /*!
4310  * This method performs an extrusion along a path defined by \a m1D.
4311  * \a this is expected to be a mesh with max mesh dimension equal to 2.
4312  * \a m1D is expected to be a mesh with space dimesion equal to 3 and mesh dimension equal to 1.
4313  * Mesh dimensions of returned mesh is incremented by one compared to thoose in \a this.
4314  * This method scans all levels in \a this
4315  * and put them in the returned mesh. All groups in \a this are also put in the returned mesh.
4316  *
4317  * \param [in] m1D - the mesh defining the extrusion path.
4318  * \param [in] policy - defines the policy of extrusion (see MEDCouplingUMesh::buildExtrudedMesh for more details)
4319  * \return - a new reference on mesh (you have to deal with using decrRef). The returned mesh will have the same name than \a this.
4320  *
4321  * \sa MEDCouplingUMesh::buildExtrudedMesh
4322  */
4323 MEDFileUMesh *MEDFileUMesh::buildExtrudedMesh(const MEDCouplingUMesh *m1D, int policy) const
4324 {
4325   checkCartesian();
4326   if(getMeshDimension()!=2)
4327     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildExtrudedMesh : this is expected to be with mesh dimension equal to 2 !");
4328   MCAuto<MEDFileUMesh> ret(MEDFileUMesh::New());
4329   m1D->checkConsistencyLight();
4330   if(m1D->getMeshDimension()!=1)
4331     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildExtrudedMesh : input mesh must have a mesh dimension equal to one !");
4332   int nbRep(m1D->getNumberOfCells());
4333   std::vector<int> levs(getNonEmptyLevels());
4334   std::vector<std::string> grps(getGroupsNames());
4335   std::vector< MCAuto<MEDCouplingUMesh> > zeList;
4336   DataArrayDouble *coords(0);
4337   std::size_t nbOfLevsOut(levs.size()+1);
4338   std::vector< MCAuto<DataArrayInt> > o2ns(nbOfLevsOut);
4339   for(std::vector<int>::const_iterator lev=levs.begin();lev!=levs.end();lev++)
4340     {
4341       MCAuto<MEDCouplingUMesh> item(getMeshAtLevel(*lev));
4342       item=item->clone(false);
4343       item->changeSpaceDimension(3+(*lev),0.);//no problem non const but change DataArrayDouble for coordinates do not alter data
4344       MCAuto<MEDCouplingUMesh> tmp(static_cast<MEDCouplingUMesh *>(m1D->deepCopy()));
4345       tmp->changeSpaceDimension(3+(*lev),0.);
4346       MCAuto<MEDCouplingUMesh> elt(item->buildExtrudedMesh(tmp,policy));
4347       zeList.push_back(elt);
4348       if(*lev==0)
4349         coords=elt->getCoords();
4350     }
4351   if(!coords)
4352     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildExtrudedMesh : internal error !");
4353   for(std::vector< MCAuto<MEDCouplingUMesh> >::iterator it=zeList.begin();it!=zeList.end();it++)
4354     {
4355       (*it)->setName(getName());
4356       (*it)->setCoords(coords);
4357     }
4358   for(std::size_t ii=0;ii!=zeList.size();ii++)
4359     {
4360       int lev(levs[ii]);
4361       MCAuto<MEDCouplingUMesh> elt(zeList[ii]);
4362       if(lev<=-1)
4363         {
4364           MCAuto<MEDCouplingUMesh> elt1(getMeshAtLevel(lev+1));
4365           MCAuto<MEDCouplingUMesh> elt2(elt1->clone(false));
4366           MCAuto<DataArrayInt> tmp(elt2->getNodalConnectivity()->deepCopy());
4367           elt2->setConnectivity(tmp,elt2->getNodalConnectivityIndex());
4368           elt2->shiftNodeNumbersInConn(nbRep*elt1->getNumberOfNodes());
4369           elt1->setCoords(elt->getCoords()); elt2->setCoords(elt->getCoords());
4370           std::vector<const MEDCouplingUMesh *> elts(3);
4371           elts[0]=elt; elts[1]=elt1; elts[2]=elt2;
4372           elt=MEDCouplingUMesh::MergeUMeshesOnSameCoords(elts);
4373           elt->setName(getName());
4374         }
4375       //
4376       o2ns[ii]=elt->sortCellsInMEDFileFrmt();
4377       ret->setMeshAtLevel(lev,elt);
4378     }
4379   MCAuto<MEDCouplingUMesh> endLev(getMeshAtLevel(levs.back())),endLev2;
4380   endLev=endLev->clone(false); endLev->setCoords(coords);
4381   MCAuto<DataArrayInt> tmp(endLev->getNodalConnectivity()->deepCopy());
4382   endLev2=endLev->clone(false); endLev2->setConnectivity(tmp,endLev->getNodalConnectivityIndex());
4383   endLev2->shiftNodeNumbersInConn(nbRep*getNumberOfNodes());
4384   endLev=MEDCouplingUMesh::MergeUMeshesOnSameCoords(endLev,endLev2);
4385   o2ns[levs.size()]=endLev->sortCellsInMEDFileFrmt();
4386   endLev->setName(getName());
4387   ret->setMeshAtLevel(levs.back()-1,endLev);
4388   //
4389   for(std::size_t ii=0;ii!=zeList.size();ii++)
4390     {
4391       int lev(levs[ii]);
4392       std::vector< MCAuto<DataArrayInt> > outGrps;
4393       std::vector< const DataArrayInt * > outGrps2;
4394       if(lev<=-1)
4395         {
4396           for(std::vector<std::string>::const_iterator grp=grps.begin();grp!=grps.end();grp++)
4397             {
4398               MCAuto<DataArrayInt> grpArr(getGroupArr(lev+1,*grp));
4399               if(!grpArr->empty())
4400                 {
4401                   MCAuto<DataArrayInt> grpArr1(grpArr->deepCopy()),grpArr2(grpArr->deepCopy());
4402                   int offset0(zeList[ii]->getNumberOfCells());
4403                   int offset1(offset0+getNumberOfCellsAtLevel(lev+1));
4404                   grpArr1->applyLin(1,offset0); grpArr2->applyLin(1,offset1);
4405                   std::ostringstream oss; oss << grpArr2->getName() << "_top";
4406                   grpArr2->setName(oss.str());
4407                   grpArr1->transformWithIndArr(o2ns[ii]->begin(),o2ns[ii]->end());
4408                   grpArr2->transformWithIndArr(o2ns[ii]->begin(),o2ns[ii]->end());
4409                   outGrps.push_back(grpArr1); outGrps.push_back(grpArr2);
4410                   outGrps2.push_back(grpArr1); outGrps2.push_back(grpArr2);
4411                 }
4412             }
4413         }
4414       //
4415       for(std::vector<std::string>::const_iterator grp=grps.begin();grp!=grps.end();grp++)
4416         {
4417           MCAuto<DataArrayInt> grpArr(getGroupArr(lev,*grp));
4418           if(!grpArr->empty())
4419             {
4420               int nbCellsB4Extrusion(getNumberOfCellsAtLevel(lev));
4421               std::vector< MCAuto<DataArrayInt> > grpArrs(nbRep);
4422               std::vector< const DataArrayInt *> grpArrs2(nbRep);
4423               for(int iii=0;iii<nbRep;iii++)
4424                 {
4425                   grpArrs[iii]=grpArr->deepCopy(); grpArrs[iii]->applyLin(1,iii*nbCellsB4Extrusion);
4426                   grpArrs2[iii]=grpArrs[iii];
4427                 }
4428               MCAuto<DataArrayInt> grpArrExt(DataArrayInt::Aggregate(grpArrs2));
4429               grpArrExt->transformWithIndArr(o2ns[ii]->begin(),o2ns[ii]->end());
4430               std::ostringstream grpName; grpName << *grp << "_extruded";
4431               grpArrExt->setName(grpName.str());
4432               outGrps.push_back(grpArrExt);
4433               outGrps2.push_back(grpArrExt);
4434             }
4435         }
4436       ret->setGroupsAtLevel(lev,outGrps2);
4437     }
4438   std::vector< MCAuto<DataArrayInt> > outGrps;
4439   std::vector< const DataArrayInt * > outGrps2;
4440   for(std::vector<std::string>::const_iterator grp=grps.begin();grp!=grps.end();grp++)
4441     {
4442       MCAuto<DataArrayInt> grpArr1(getGroupArr(levs.back(),*grp));
4443       if(grpArr1->empty())
4444         continue;
4445       MCAuto<DataArrayInt> grpArr2(grpArr1->deepCopy());
4446       std::ostringstream grpName; grpName << *grp << "_top";
4447       grpArr2->setName(grpName.str());
4448       grpArr2->applyLin(1,getNumberOfCellsAtLevel(levs.back()));
4449       outGrps.push_back(grpArr1); outGrps.push_back(grpArr2);
4450       outGrps2.push_back(grpArr1); outGrps2.push_back(grpArr2);
4451     }
4452   ret->setGroupsAtLevel(levs.back()-1,outGrps2);
4453   return ret.retn();
4454 }
4455
4456 /*!
4457  * This method converts all linear cells in \a this into quadratic cells (following the \a conversionType policy).
4458  * All the cells converted are put in the returned instance. This method applies all the groups and families in \a this to returned instance.
4459  * Groups on nodes and families on nodes are copied directly to the returned instance without transformation.
4460  *
4461  * \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
4462  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
4463  * \param [in] eps - detection threshold for coordinates.
4464  * \return A new instance that is the result of the conversion. The caller has the ownership of this returned instance.
4465  *
4466  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic , quadraticToLinear
4467  */
4468 MEDFileUMesh *MEDFileUMesh::linearToQuadratic(int conversionType, double eps) const
4469 {
4470   checkCartesian();
4471   MCAuto<MEDFileUMesh> ret(MEDFileUMesh::New());
4472   int initialNbNodes(getNumberOfNodes());
4473   MCAuto<MEDCouplingUMesh> m0Tmp(getMeshAtLevel(0));
4474   MCAuto<MEDCouplingUMesh> m0(dynamic_cast<MEDCouplingUMesh *>(m0Tmp->deepCopy()));
4475   {
4476     MCAuto<DataArrayInt> notUsed(m0->convertLinearCellsToQuadratic(conversionType));
4477   }
4478   DataArrayDouble *zeCoords(m0->getCoords());
4479   ret->setMeshAtLevel(0,m0);
4480   std::vector<int> levs(getNonEmptyLevels());
4481   const DataArrayInt *famField(getFamilyFieldAtLevel(0));
4482   if(famField)
4483     {
4484       MCAuto<DataArrayInt> famFieldCpy(famField->deepCopy());
4485       ret->setFamilyFieldArr(0,famFieldCpy);
4486     }
4487   famField=getFamilyFieldAtLevel(1);
4488   if(famField)
4489     {
4490       MCAuto<DataArrayInt> fam(DataArrayInt::New()); fam->alloc(zeCoords->getNumberOfTuples(),1);
4491       fam->fillWithZero();
4492       fam->setPartOfValues1(famField,0,initialNbNodes,1,0,1,1);
4493       ret->setFamilyFieldArr(1,fam);
4494     }
4495   ret->copyFamGrpMapsFrom(*this);
4496   MCAuto<DataArrayDouble> partZeCoords(zeCoords->selectByTupleIdSafeSlice(initialNbNodes,zeCoords->getNumberOfTuples(),1));
4497   for(std::vector<int>::const_iterator lev=levs.begin();lev!=levs.end();lev++)
4498     {
4499       if(*lev==0)
4500         continue;
4501       MCAuto<MEDCouplingUMesh> m1Tmp(getMeshAtLevel(*lev));
4502       MCAuto<MEDCouplingUMesh> m1(dynamic_cast<MEDCouplingUMesh *>(m1Tmp->deepCopy()));
4503       if(m1->getMeshDimension()!=0)
4504         {
4505           {
4506             MCAuto<DataArrayInt> notUsed(m1->convertLinearCellsToQuadratic(conversionType));
4507           }//kill unused notUsed var
4508           MCAuto<DataArrayDouble> m1Coords(m1->getCoords()->selectByTupleIdSafeSlice(initialNbNodes,m1->getNumberOfNodes(),1));
4509           DataArrayInt *b(0);
4510           bool a(partZeCoords->areIncludedInMe(m1Coords,eps,b));
4511           MCAuto<DataArrayInt> bSafe(b);
4512           if(!a)
4513             {
4514               std::ostringstream oss; oss << "MEDFileUMesh::linearCellsToQuadratic : for level " << *lev << " problem to identify nodes generated !";
4515               throw INTERP_KERNEL::Exception(oss.str().c_str());
4516             }
4517           b->applyLin(1,initialNbNodes);
4518           MCAuto<DataArrayInt> l0(DataArrayInt::New()); l0->alloc(initialNbNodes,1); l0->iota();
4519           std::vector<const DataArrayInt *> v(2); v[0]=l0; v[1]=b;
4520           MCAuto<DataArrayInt> renum(DataArrayInt::Aggregate(v));
4521           m1->renumberNodesInConn(renum->begin());
4522         }
4523       m1->setCoords(zeCoords);
4524       ret->setMeshAtLevel(*lev,m1);
4525       famField=getFamilyFieldAtLevel(*lev);
4526       if(famField)
4527         {
4528           MCAuto<DataArrayInt> famFieldCpy(famField->deepCopy());
4529           ret->setFamilyFieldArr(*lev,famFieldCpy);
4530         }
4531     }
4532   return ret.retn();
4533 }
4534
4535 /*!
4536  * This method converts all quadratic cells in \a this into linear cells.
4537  * All the cells converted are put in the returned instance. This method applies all the groups and families in \a this to returned instance.
4538  * Groups on nodes and families on nodes are copied directly to the returned instance without transformation.
4539  *
4540  * \param [in] eps - detection threshold for coordinates.
4541  * \return A new instance that is the result of the conversion. The caller has the ownership of this returned instance.
4542  *
4543  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic , linearToQuadratic
4544  */
4545 MEDFileUMesh *MEDFileUMesh::quadraticToLinear(double eps) const
4546 {
4547   checkCartesian();
4548   MCAuto<MEDFileUMesh> ret(MEDFileUMesh::New());
4549   MCAuto<MEDCouplingUMesh> m0Tmp(getMeshAtLevel(0));
4550   MCAuto<MEDCouplingUMesh> m0(dynamic_cast<MEDCouplingUMesh *>(m0Tmp->deepCopy()));
4551   m0->convertQuadraticCellsToLinear();
4552   m0->zipCoords();
4553   DataArrayDouble *zeCoords(m0->getCoords());
4554   ret->setMeshAtLevel(0,m0);
4555   std::vector<int> levs(getNonEmptyLevels());
4556   const DataArrayInt *famField(getFamilyFieldAtLevel(0));
4557   if(famField)
4558     {
4559       MCAuto<DataArrayInt> famFieldCpy(famField->deepCopy());
4560       ret->setFamilyFieldArr(0,famFieldCpy);
4561     }
4562   famField=getFamilyFieldAtLevel(1);
4563   if(famField)
4564     {
4565       MCAuto<DataArrayInt> fam(famField->selectByTupleIdSafeSlice(0,zeCoords->getNumberOfTuples(),1));
4566       ret->setFamilyFieldArr(1,fam);
4567     }
4568   ret->copyFamGrpMapsFrom(*this);
4569   for(std::vector<int>::const_iterator lev=levs.begin();lev!=levs.end();lev++)
4570     {
4571       if(*lev==0)
4572         continue;
4573       MCAuto<MEDCouplingUMesh> m1Tmp(getMeshAtLevel(*lev));
4574       MCAuto<MEDCouplingUMesh> m1(dynamic_cast<MEDCouplingUMesh *>(m1Tmp->deepCopy()));
4575       m1->convertQuadraticCellsToLinear();
4576       m1->zipCoords();
4577       DataArrayInt *b(0);
4578       bool a(zeCoords->areIncludedInMe(m1->getCoords(),eps,b));
4579       MCAuto<DataArrayInt> bSafe(b);
4580       if(!a)
4581         {
4582           std::ostringstream oss; oss << "MEDFileUMesh::quadraticToLinear : for level " << *lev << " problem to identify nodes generated !";
4583           throw INTERP_KERNEL::Exception(oss.str().c_str());
4584         }
4585       m1->renumberNodesInConn(b->begin());
4586       m1->setCoords(zeCoords);
4587       ret->setMeshAtLevel(*lev,m1);
4588       famField=getFamilyFieldAtLevel(*lev);
4589       if(famField)
4590         {
4591           MCAuto<DataArrayInt> famFieldCpy(famField->deepCopy());
4592           ret->setFamilyFieldArr(*lev,famFieldCpy);
4593         }
4594     }
4595   return ret.retn();
4596 }
4597
4598 /*!
4599  * Computes the symmetry of \a this.
4600  * \return a new object.
4601  */
4602 MCAuto<MEDFileUMesh> MEDFileUMesh::symmetry3DPlane(const double point[3], const double normalVector[3]) const
4603 {
4604   MCAuto<MEDFileUMesh> ret(deepCopy());
4605   DataArrayDouble *myCoo(getCoords());
4606   if(myCoo)
4607     {
4608       MCAuto<DataArrayDouble> newCoo(myCoo->symmetry3DPlane(point,normalVector));
4609       ret->setCoordsForced(newCoo);
4610     }
4611   return ret;
4612 }
4613
4614 MCAuto<MEDFileUMesh> MEDFileUMesh::Aggregate(const std::vector<const MEDFileUMesh *>& meshes)
4615 {
4616   if(meshes.empty())
4617     throw INTERP_KERNEL::Exception("MEDFileUMesh::Aggregate : empty input vector !");
4618   std::size_t sz(meshes.size()),i(0);
4619   std::vector<const DataArrayDouble *> coos(sz);
4620   std::vector<const DataArrayInt *> fam_coos(sz),num_coos(sz);
4621   for(std::vector<const MEDFileUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,i++)
4622     {
4623       if(!(*it))
4624         throw INTERP_KERNEL::Exception("MEDFileUMesh::Aggregate : presence of NULL pointer in input vector !");
4625       coos[i]=(*it)->getCoords();
4626       fam_coos[i]=(*it)->getFamilyFieldAtLevel(1);
4627       num_coos[i]=(*it)->getNumberFieldAtLevel(1);
4628     }
4629   const MEDFileUMesh *ref(meshes[0]);
4630   int spaceDim(ref->getSpaceDimension()),meshDim(ref->getMeshDimension());
4631   std::vector<int> levs(ref->getNonEmptyLevels());
4632   std::map<int, std::vector<const DataArrayInt *> > m_fam,m_renum;
4633   std::map<int, std::vector< MCAuto< MEDCouplingUMesh > > > m_mesh2;
4634   std::map<int, std::vector<const MEDCouplingUMesh *> > m_mesh;
4635   std::map<std::string,int> map1;
4636   std::map<std::string, std::vector<std::string> > map2;
4637   for(std::vector<const MEDFileUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,i++)
4638     {
4639       if((*it)->getSpaceDimension()!=spaceDim)
4640         throw INTERP_KERNEL::Exception("MEDFileUMesh::Aggregate : space dimension must be homogeneous !");
4641       if((*it)->getMeshDimension()!=meshDim)
4642         throw INTERP_KERNEL::Exception("MEDFileUMesh::Aggregate : mesh dimension must be homogeneous !");
4643       if((*it)->getNonEmptyLevels()!=levs)
4644         throw INTERP_KERNEL::Exception("MEDFileUMesh::Aggregate : levels must be the same for elements in input vector !");
4645       for(std::vector<int>::const_iterator it2=levs.begin();it2!=levs.end();it2++)
4646         {
4647           MCAuto<MEDCouplingUMesh> locMesh((*it)->getMeshAtLevel(*it2));
4648           m_mesh[*it2].push_back(locMesh); m_mesh2[*it2].push_back(locMesh);
4649           m_fam[*it2].push_back((*it)->getFamilyFieldAtLevel(*it2));
4650           m_renum[*it2].push_back((*it)->getNumberFieldAtLevel(*it2));
4651         }
4652       const std::map<std::string,int>& locMap1((*it)->getFamilyInfo());
4653       for(std::map<std::string,int>::const_iterator it3=locMap1.begin();it3!=locMap1.end();it3++)
4654         map1[(*it3).first]=(*it3).second;
4655       const std::map<std::string, std::vector<std::string> >& locMap2((*it)->getGroupInfo());
4656       for(std::map<std::string, std::vector<std::string> >::const_iterator it4=locMap2.begin();it4!=locMap2.end();it4++)
4657         map2[(*it4).first]=(*it4).second;
4658     }
4659   // Easy part : nodes
4660   MCAuto<MEDFileUMesh> ret(MEDFileUMesh::New());
4661   MCAuto<DataArrayDouble> coo(DataArrayDouble::Aggregate(coos));
4662   ret->setCoords(coo);
4663   if(std::find(fam_coos.begin(),fam_coos.end(),(const DataArrayInt *)0)==fam_coos.end())
4664     {
4665       MCAuto<DataArrayInt> fam_coo(DataArrayInt::Aggregate(fam_coos));
4666       ret->setFamilyFieldArr(1,fam_coo);
4667     }
4668   if(std::find(num_coos.begin(),num_coos.end(),(const DataArrayInt *)0)==num_coos.end())
4669     {
4670       MCAuto<DataArrayInt> num_coo(DataArrayInt::Aggregate(num_coos));
4671       ret->setRenumFieldArr(1,num_coo);
4672     }
4673   // cells
4674   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
4675     {
4676       std::map<int, std::vector<const MEDCouplingUMesh *> >::const_iterator it2(m_mesh.find(*it));
4677       if(it2==m_mesh.end())
4678         throw INTERP_KERNEL::Exception("MEDFileUMesh::Aggregate : internal error 1 !");
4679       MCAuto<MEDCouplingUMesh> mesh(MEDCouplingUMesh::MergeUMeshes((*it2).second));
4680       mesh->setCoords(coo); mesh->setName(ref->getName());
4681       MCAuto<DataArrayInt> renum(mesh->sortCellsInMEDFileFrmt());
4682       ret->setMeshAtLevel(*it,mesh);
4683       std::map<int, std::vector<const DataArrayInt *> >::const_iterator it3(m_fam.find(*it)),it4(m_renum.find(*it));
4684       if(it3!=m_fam.end())
4685         {
4686           const std::vector<const DataArrayInt *>& fams((*it3).second);
4687           if(std::find(fams.begin(),fams.end(),(const DataArrayInt *)0)==fams.end())
4688             {
4689               MCAuto<DataArrayInt> famm(DataArrayInt::Aggregate(fams));
4690               famm->renumberInPlace(renum->begin());
4691               ret->setFamilyFieldArr(*it,famm);
4692             }
4693         }
4694       if(it4!=m_renum.end())
4695         {
4696           const std::vector<const DataArrayInt *>& renums((*it4).second);
4697           if(std::find(renums.begin(),renums.end(),(const DataArrayInt *)0)==renums.end())
4698             {
4699               MCAuto<DataArrayInt> renumm(DataArrayInt::Aggregate(renums));
4700               renumm->renumberInPlace(renum->begin());
4701               ret->setRenumFieldArr(*it,renumm);
4702             }
4703         }
4704     }
4705   //
4706   ret->setFamilyInfo(map1);
4707   ret->setGroupInfo(map2);
4708   ret->setName(ref->getName());
4709   return ret;
4710 }
4711
4712 MEDCouplingMappedExtrudedMesh *MEDFileUMesh::convertToExtrudedMesh() const
4713 {
4714   if(getMeshDimension()!=3)
4715     throw INTERP_KERNEL::Exception("MEDFileUMesh::convertToExtrudedMesh : works only for 3D mesh !");
4716   MCAuto<MEDCouplingUMesh> m3D(getMeshAtLevel(0)),m2D(getMeshAtLevel(-1));
4717   if(m3D.isNull() || m2D.isNull())
4718     throw INTERP_KERNEL::Exception("MEDFileUMesh::convertToExtrudedMesh : this must be defined both at level 0 and level -1 !");
4719   int zeId(std::numeric_limits<int>::max()-getFamilyId(GetSpeStr4ExtMesh()));
4720   MCAuto<MEDCouplingMappedExtrudedMesh> ret(MEDCouplingMappedExtrudedMesh::New(m3D,m2D,zeId));
4721   return ret.retn();
4722 }
4723
4724 void MEDFileUMesh::serialize(std::vector<double>& tinyDouble, std::vector<int>& tinyInt, std::vector<std::string>& tinyStr, std::vector< MCAuto<DataArrayInt> >& bigArraysI, MCAuto<DataArrayDouble>& bigArrayD)
4725 {
4726   clearNonDiscrAttributes();
4727   forceComputationOfParts();
4728   tinyDouble.clear(); tinyInt.clear(); tinyStr.clear(); bigArraysI.clear(); bigArrayD=0;
4729   std::vector<int> layer0;
4730   layer0.push_back(getAxisType());//0 i
4731   layer0.push_back(_order); //1 i
4732   layer0.push_back(_iteration);//2 i
4733   layer0.push_back(getSpaceDimension());//3 i
4734   tinyDouble.push_back(_time);//0 d
4735   tinyStr.push_back(_name);//0 s
4736   tinyStr.push_back(_desc_name);//1 s
4737   for(int i=0;i<getSpaceDimension();i++)
4738     tinyStr.push_back(_coords->getInfoOnComponent(i));
4739   layer0.push_back((int)_families.size());//4 i <- key info aa layer#0
4740   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
4741     {
4742       tinyStr.push_back((*it).first);
4743       layer0.push_back((*it).second);
4744     }
4745   layer0.push_back((int)_groups.size());//4+aa i <- key info bb layer#0
4746   for(std::map<std::string, std::vector<std::string> >::const_iterator it0=_groups.begin();it0!=_groups.end();it0++)
4747     {
4748       layer0.push_back((int)(*it0).second.size());
4749       tinyStr.push_back((*it0).first);
4750       for(std::vector<std::string>::const_iterator it1=((*it0).second).begin();it1!=((*it0).second).end();it1++)
4751         tinyStr.push_back(*it1);
4752     }
4753   // sizeof(layer0)==4+aa+1+bb layer#0
4754   bigArrayD=_coords;// 0 bd
4755   bigArraysI.push_back(_fam_coords);// 0 bi
4756   bigArraysI.push_back(_num_coords);// 1 bi
4757   const PartDefinition *pd(_part_coords);
4758   if(!pd)
4759     layer0.push_back(-1);
4760   else
4761     {
4762       std::vector<int> tmp0;
4763       pd->serialize(tmp0,bigArraysI);
4764       tinyInt.push_back(tmp0.size());
4765       tinyInt.insert(tinyInt.end(),tmp0.begin(),tmp0.end());
4766     }
4767   //
4768   std::vector<int> layer1;
4769   std::vector<int> levs(getNonEmptyLevels());
4770   layer1.push_back((int)levs.size());// 0 i <- key
4771   layer1.insert(layer1.end(),levs.begin(),levs.end());
4772   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
4773     {
4774       const MEDFileUMeshSplitL1 *lev(getMeshAtLevSafe(*it));
4775       lev->serialize(layer1,bigArraysI);
4776     }
4777   // put layers all together.
4778   tinyInt.push_back(layer0.size());
4779   tinyInt.insert(tinyInt.end(),layer0.begin(),layer0.end());
4780   tinyInt.push_back(layer1.size());
4781   tinyInt.insert(tinyInt.end(),layer1.begin(),layer1.end());
4782 }
4783
4784 void MEDFileUMesh::unserialize(std::vector<double>& tinyDouble, std::vector<int>& tinyInt, std::vector<std::string>& tinyStr,
4785                                std::vector< MCAuto<DataArrayInt> >& bigArraysI, MCAuto<DataArrayDouble>& bigArrayD)
4786 {
4787   int sz0(tinyInt[0]);
4788   std::vector<int> layer0(tinyInt.begin()+1,tinyInt.begin()+1+sz0);
4789   int sz1(tinyInt[sz0+1]);
4790   std::vector<int> layer1(tinyInt.begin()+2+sz0,tinyInt.begin()+2+sz0+sz1);
4791   //
4792   std::reverse(layer0.begin(),layer0.end());
4793   std::reverse(layer1.begin(),layer1.end());
4794   std::reverse(tinyDouble.begin(),tinyDouble.end());
4795   std::reverse(tinyStr.begin(),tinyStr.end());
4796   std::reverse(bigArraysI.begin(),bigArraysI.end());
4797   //
4798   setAxisType((MEDCouplingAxisType)layer0.back()); layer0.pop_back();
4799   _order=layer0.back(); layer0.pop_back();
4800   _iteration=layer0.back(); layer0.pop_back();
4801   int spaceDim(layer0.back()); layer0.pop_back();
4802   _time=tinyDouble.back(); tinyDouble.pop_back();
4803   _name=tinyStr.back(); tinyStr.pop_back();
4804   _desc_name=tinyStr.back(); tinyStr.pop_back();
4805   _coords=bigArrayD; _coords->rearrange(spaceDim);
4806   for(int i=0;i<spaceDim;i++)
4807     {
4808       _coords->setInfoOnComponent(i,tinyStr.back());
4809       tinyStr.pop_back();
4810     }
4811   int nbOfFams(layer0.back()); layer0.pop_back();
4812   _families.clear();
4813   for(int i=0;i<nbOfFams;i++)
4814     {
4815       _families[tinyStr.back()]=layer0.back();
4816       tinyStr.pop_back(); layer0.pop_back();
4817     }
4818   int nbGroups(layer0.back()); layer0.pop_back();
4819   _groups.clear();
4820   for(int i=0;i<nbGroups;i++)
4821     {
4822       std::string grpName(tinyStr.back()); tinyStr.pop_back();
4823       int nbOfFamsOnGrp(layer0.back()); layer0.pop_back();
4824       std::vector<std::string> fams(nbOfFamsOnGrp);
4825       for(int j=0;j<nbOfFamsOnGrp;j++)
4826         {
4827           fams[j]=tinyStr.back(); tinyStr.pop_back();
4828         }
4829       _groups[grpName]=fams;
4830     }
4831   _fam_coords=bigArraysI.back(); bigArraysI.pop_back();
4832   _num_coords=bigArraysI.back(); bigArraysI.pop_back();
4833   _part_coords=0;
4834   int isPd(layer0.back()); layer0.pop_back();
4835   if(isPd!=-1)
4836     {
4837       std::vector<int> tmp0(layer0.begin(),layer0.begin()+isPd);
4838       layer0.erase(layer0.begin(),layer0.begin()+isPd);
4839       _part_coords=PartDefinition::Unserialize(tmp0,bigArraysI);
4840     }
4841   if(!layer0.empty())
4842     throw INTERP_KERNEL::Exception("MEDFileUMesh::unserialize : something wrong during unserialization #1 !");
4843   //
4844   int nbLevs(layer1.back()); layer1.pop_back();
4845   std::vector<int> levs(layer1.rbegin(),layer1.rbegin()+nbLevs); layer1.erase(layer1.end()-nbLevs,layer1.end());
4846   _ms.clear();
4847   int maxLev(-(*std::min_element(levs.begin(),levs.end())));
4848   _ms.resize(maxLev+1);
4849   for(int i=0;i<nbLevs;i++)
4850     {
4851       int lev(levs[i]);
4852       int pos(-lev);
4853       _ms[pos]=MEDFileUMeshSplitL1::Unserialize(_name,_coords,layer1,bigArraysI);
4854     }
4855 }
4856
4857 /*!
4858  * Adds a group of nodes to \a this mesh.
4859  *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
4860  *          The ids should be sorted and different each other (MED file norm).
4861  *
4862  *  \warning this method can alter default "FAMILLE_ZERO" family.
4863  *  For users sensitive to this a call to MEDFileMesh::rearrangeFamilies will be necessary after addGroup session.
4864  *
4865  *  \throw If the node coordinates array is not set.
4866  *  \throw If \a ids == \c NULL.
4867  *  \throw If \a ids->getName() == "".
4868  *  \throw If \a ids does not respect the MED file norm.
4869  *  \throw If a group with name \a ids->getName() already exists.
4870  */
4871 void MEDFileUMesh::addNodeGroup(const DataArrayInt *ids)
4872 {
4873   const DataArrayDouble *coords(_coords);
4874   if(!coords)
4875     throw INTERP_KERNEL::Exception("MEDFileUMesh::addNodeGroup : no coords set !");
4876   int nbOfNodes(coords->getNumberOfTuples());
4877   if(!((DataArrayInt *)_fam_coords))
4878     { _fam_coords=DataArrayInt::New(); _fam_coords->alloc(nbOfNodes,1); _fam_coords->fillWithZero(); }
4879   //
4880   addGroupUnderground(true,ids,_fam_coords);
4881 }
4882
4883 /*!
4884  * Adds a group of nodes/cells/faces/edges to \a this mesh.
4885  *
4886  *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
4887  *          The ids should be sorted and different each other (MED file norm).
4888  *
4889  * \warning this method can alter default "FAMILLE_ZERO" family.
4890  * For users sensitive to this a call to MEDFileMesh::rearrangeFamilies will be necessary after addGroup session.
4891  *
4892  *  \throw If the node coordinates array is not set.
4893  *  \throw If \a ids == \c NULL.
4894  *  \throw If \a ids->getName() == "".
4895  *  \throw If \a ids does not respect the MED file norm.
4896  *  \throw If a group with name \a ids->getName() already exists.
4897  */
4898 void MEDFileUMesh::addGroup(int meshDimRelToMaxExt, const DataArrayInt *ids)
4899 {
4900   std::vector<int> levs(getNonEmptyLevelsExt());
4901   if(std::find(levs.begin(),levs.end(),meshDimRelToMaxExt)==levs.end())
4902     { 
4903       std::ostringstream oss; oss << "MEDFileUMesh::addGroup : level " << meshDimRelToMaxExt << " not available ! Should be in ";
4904       std::copy(levs.begin(),levs.end(),std::ostream_iterator<int>(oss," ")); oss << " !"; throw INTERP_KERNEL::Exception(oss.str().c_str());
4905     }
4906   if(meshDimRelToMaxExt==1)
4907     { addNodeGroup(ids); return ; }
4908   MEDFileUMeshSplitL1 *lev(getMeshAtLevSafe(meshDimRelToMaxExt));
4909   DataArrayInt *fam(lev->getOrCreateAndGetFamilyField());
4910   addGroupUnderground(false,ids,fam);
4911 }
4912
4913 /*!
4914  * Changes a name of a family specified by its id.
4915  *  \param [in] id - the id of the family of interest.
4916  *  \param [in] newFamName - the new family name.
4917  *  \throw If no family with the given \a id exists.
4918  */
4919 void MEDFileUMesh::setFamilyNameAttachedOnId(int id, const std::string& newFamName)
4920 {
4921   std::string oldName=getFamilyNameGivenId(id);
4922   _families.erase(oldName);
4923   _families[newFamName]=id;
4924 }
4925
4926 /*!
4927  * Removes a mesh of a given dimension.
4928  *  \param [in] meshDimRelToMax - the relative dimension of interest.
4929  *  \throw If there is no mesh at level \a meshDimRelToMax in \a this mesh.
4930  */
4931 void MEDFileUMesh::removeMeshAtLevel(int meshDimRelToMax)
4932 {
4933   std::vector<int> levSet=getNonEmptyLevels();
4934   std::vector<int>::const_iterator it=std::find(levSet.begin(),levSet.end(),meshDimRelToMax);
4935   if(it==levSet.end())
4936     throw INTERP_KERNEL::Exception("MEDFileUMesh::removeMeshAtLevel : the requested level is not existing !");
4937   int pos=(-meshDimRelToMax);
4938   _ms[pos]=0;
4939 }
4940
4941 /*!
4942  * Sets a new MEDCoupling1GTUMesh at a given level in \a this mesh.
4943  *  \param [in] meshDimRelToMax - a relative level to set the mesh at.
4944  *  \param [in] m - the new mesh to set.
4945  *  \throw If the name or the description of \a this mesh and \a m are not empty and are
4946  *         different. 
4947  *  \throw If the node coordinates array is set \a this in mesh and \a m refers to
4948  *         another node coordinates array.
4949  *  \throw If the mesh dimension of \a m does not correspond to \a meshDimRelToMax or
4950  *         to the existing meshes of other levels of \a this mesh.
4951  */
4952 void MEDFileUMesh::setMeshAtLevel(int meshDimRelToMax, MEDCoupling1GTUMesh *m)
4953 {
4954   MCAuto<MEDFileUMeshSplitL1> elt(new MEDFileUMeshSplitL1(m));
4955   checkAndGiveEntryInSplitL1(meshDimRelToMax,m)=elt;
4956 }
4957
4958 /*!
4959  * Sets a new MEDCouplingUMesh at a given level in \a this mesh.
4960  *  \param [in] meshDimRelToMax - a relative level to set the mesh at.
4961  *  \param [in] m - the new mesh to set.
4962  *  \param [in] newOrOld - if \c true, cells in \a m are sorted by type to be ready for 
4963  *         writing \a this mesh in a MED file.
4964  *  \throw If the name or the description of \a this mesh and \a m are not empty and are
4965  *         different. 
4966  *  \throw If the node coordinates array is set \a this in mesh and \a m refers to
4967  *         another node coordinates array.
4968  *  \throw If the mesh dimension of \a m does not correspond to \a meshDimRelToMax or
4969  *         to the existing meshes of other levels of \a this mesh.
4970  */
4971 void MEDFileUMesh::setMeshAtLevel(int meshDimRelToMax, MEDCouplingUMesh *m, bool newOrOld)
4972 {
4973   MCAuto<MEDFileUMeshSplitL1> elt(new MEDFileUMeshSplitL1(m,newOrOld));
4974   checkAndGiveEntryInSplitL1(meshDimRelToMax,m)=elt;
4975 }
4976
4977 MCAuto<MEDFileUMeshSplitL1>& MEDFileUMesh::checkAndGiveEntryInSplitL1(int meshDimRelToMax, MEDCouplingPointSet *m)
4978 {
4979   dealWithTinyInfo(m);
4980   std::vector<int> levSet=getNonEmptyLevels();
4981   if(std::find(levSet.begin(),levSet.end(),meshDimRelToMax)==levSet.end())
4982     {
4983       if((DataArrayDouble *)_coords==0)
4984         {
4985           DataArrayDouble *c=m->getCoords();
4986           if(c)
4987             c->incrRef();
4988           _coords=c;
4989         }
4990       if(m->getCoords()!=_coords)
4991         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshAtLevel : Invalid Given Mesh ! The coordinates are not the same ! try to use tryToShareSameCoords !");
4992       int sz=(-meshDimRelToMax)+1;
4993       if(sz>=(int)_ms.size())
4994         _ms.resize(sz);
4995       checkMeshDimCoherency(m->getMeshDimension(),meshDimRelToMax);
4996       return _ms[sz-1];
4997     }
4998   else
4999     return _ms[-meshDimRelToMax];
5000 }
5001
5002 /*!
5003  * This method allows to set at once the content of different levels in \a this.
5004  * This method is equivalent to a series of call to MEDFileUMesh::setMeshAtLevel.
5005  *
5006  * \param [in] ms - List of unstructured meshes lying on the same coordinates and having different mesh dimesnion.
5007  * \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.
5008  *                     If false, an exception ois thrown. If true the mesh is reordered automatically. It is highly recommanded to let this parameter to false.
5009  *
5010  * \throw If \a there is a null pointer in \a ms.
5011  * \sa MEDFileUMesh::setMeshAtLevel
5012  */
5013 void MEDFileUMesh::setMeshes(const std::vector<const MEDCouplingUMesh *>& ms, bool renum)
5014 {
5015   if(ms.empty())
5016     return ;
5017   const MEDCouplingUMesh *mRef=ms[0];
5018   if(!mRef)
5019     throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : null instance in the first element of input meshes !");
5020   std::string name(mRef->getName());
5021   const DataArrayDouble *coo(mRef->getCoords());
5022   std::set<int> s;
5023   int zeDim=-1;
5024   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
5025     {
5026       const MEDCouplingUMesh *cur(*it);
5027       if(!cur)
5028         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : null instance in input vector of meshes !");
5029       if(coo!=cur->getCoords())
5030         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : The input meshes do not share the same coordinates !");
5031       int mdim=cur->getMeshDimension();
5032       zeDim=std::max(zeDim,mdim);
5033       if(s.find(mdim)!=s.end())
5034         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : The input meshes must share the same coordinates pointer, and should have different mesh dimension each other !");
5035     }
5036   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
5037     {
5038       int mdim=(*it)->getMeshDimension();
5039       setName((*it)->getName());
5040       setMeshAtLevel(mdim-zeDim,const_cast<MEDCouplingUMesh *>(*it),renum);
5041     }
5042   setName(name);
5043 }
5044
5045 /*!
5046  * Creates one MEDCouplingUMesh at a given level in \a this mesh from a sequence of
5047  * meshes each representing a group, and creates corresponding groups in \a this mesh.
5048  * The given meshes must share the same node coordinates array.
5049  *  \param [in] meshDimRelToMax - the relative dimension to create the mesh and groups at.
5050  *  \param [in] ms - the sequence of meshes. Each mesh in \a ms represents a group to
5051  *          create in \a this mesh.
5052  *  \throw If \a ms is empty.
5053  *  \throw If dimension of meshes in \a ms does not correspond to \a meshDimRelToMax or
5054  *         to the existing meshes of other levels of \a this mesh.
5055  *  \throw If the meshes in \a ms do not share the same node coordinates array.
5056  *  \throw If the node coordinates array of \a this mesh (if any) is not the same as that
5057  *         of the given meshes.
5058  *  \throw If \a ms[ i ] is not well defined (MEDCouplingUMesh::checkConsistencyLight()).
5059  *  \throw If names of some meshes in \a ms are equal.
5060  *  \throw If \a ms includes a mesh with an empty name.
5061  */
5062 void MEDFileUMesh::setGroupsFromScratch(int meshDimRelToMax, const std::vector<const MEDCouplingUMesh *>& ms, bool renum)
5063 {
5064   if(ms.empty())
5065     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsFromScratch : expecting a non empty vector !");
5066   int sz=(-meshDimRelToMax)+1;
5067   if(sz>=(int)_ms.size())
5068     _ms.resize(sz);
5069   checkMeshDimCoherency(ms[0]->getMeshDimension(),meshDimRelToMax);
5070   DataArrayDouble *coo=checkMultiMesh(ms);
5071   if((DataArrayDouble *)_coords==0)
5072     {
5073       coo->incrRef();
5074       _coords=coo;
5075     }
5076   else
5077     if((DataArrayDouble *)_coords!=coo)
5078       throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsFromScratch : coordinates mismatches !");
5079   std::vector<DataArrayInt *> corr;
5080   MCAuto<MEDCouplingUMesh> m=MEDCouplingUMesh::FuseUMeshesOnSameCoords(ms,_zipconn_pol,corr);
5081   std::vector< MCAuto<DataArrayInt> > corr3(corr.begin(),corr.end());
5082   setMeshAtLevel(meshDimRelToMax,m,renum);
5083   std::vector<const DataArrayInt *> corr2(corr.begin(),corr.end());
5084   setGroupsAtLevel(meshDimRelToMax,corr2,true);
5085 }
5086
5087 /*!
5088  * Creates groups at a given level in \a this mesh from a sequence of
5089  * meshes each representing a group.
5090  * The given meshes must share the same node coordinates array.
5091  *  \param [in] meshDimRelToMax - the relative dimension to create the groups at.
5092  *  \param [in] ms - the sequence of meshes. Each mesh in \a ms represents a group to
5093  *         create in \a this mesh.
5094  *  \param [in] renum - if \c true, then the optional numbers of entities are taken into
5095  *         account. 
5096  *  \throw If \a ms is empty.
5097  *  \throw If dimension of meshes in \a ms does not correspond to \a meshDimRelToMax or
5098  *         to the existing meshes of other levels of \a this mesh.
5099  *  \throw If the meshes in \a ms do not share the same node coordinates array.
5100  *  \throw If the node coordinates array of \a this mesh (if any) is not the same as that
5101  *         of the given meshes.
5102  *  \throw If \a ms[ i ] is not well defined (MEDCouplingUMesh::checkConsistencyLight()).
5103  *  \throw If names of some meshes in \a ms are equal.
5104  *  \throw If \a ms includes a mesh with an empty name.
5105  */
5106 void MEDFileUMesh::setGroupsOnSetMesh(int meshDimRelToMax, const std::vector<const MEDCouplingUMesh *>& ms, bool renum)
5107 {
5108   if(ms.empty())
5109     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsOnSetMesh : expecting a non empty vector !");
5110   int sz=(-meshDimRelToMax)+1;
5111   if(sz>=(int)_ms.size())
5112     _ms.resize(sz);
5113   checkMeshDimCoherency(ms[0]->getMeshDimension(),meshDimRelToMax);
5114   DataArrayDouble *coo=checkMultiMesh(ms);
5115   if((DataArrayDouble *)_coords==0)
5116     {
5117       coo->incrRef();
5118       _coords=coo;
5119     }
5120   else
5121     if((DataArrayDouble *)_coords!=coo)
5122       throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsOnSetMesh : coordinates mismatches !");
5123   MEDCouplingUMesh *m=getMeshAtLevel(meshDimRelToMax,renum);
5124   std::vector< MCAuto<DataArrayInt> > corr(ms.size());
5125   int i=0;
5126   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++,i++)
5127     {
5128       DataArrayInt *arr=0;
5129       bool test=m->areCellsIncludedIn(*it,_zipconn_pol,arr);
5130       corr[i]=arr;
5131       if(!test)
5132         {
5133           std::ostringstream oss; oss << "MEDFileUMesh::setGroupsOnSetMesh : mesh #" << i << " is not part of whole mesh !";
5134           throw INTERP_KERNEL::Exception(oss.str().c_str());
5135         }
5136     }
5137   std::vector<const DataArrayInt *> corr2(corr.begin(),corr.end());
5138   setGroupsAtLevel(meshDimRelToMax,corr2,renum);
5139 }
5140
5141 DataArrayDouble *MEDFileUMesh::checkMultiMesh(const std::vector<const MEDCouplingUMesh *>& ms) const
5142 {
5143   const DataArrayDouble *ret=ms[0]->getCoords();
5144   int mdim=ms[0]->getMeshDimension();
5145   for(unsigned int i=1;i<ms.size();i++)
5146     {
5147       ms[i]->checkConsistencyLight();
5148       if(ms[i]->getCoords()!=ret)
5149         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMultiMesh : meshes must share the same coords !");
5150       if(ms[i]->getMeshDimension()!=mdim)
5151         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMultiMesh : meshes have not same mesh dimension !");
5152     }
5153   return const_cast<DataArrayDouble *>(ret);
5154 }
5155
5156 /*!
5157  * Sets the family field of a given relative dimension.
5158  *  \param [in] meshDimRelToMaxExt - the relative dimension of entities for which
5159  *          the family field is set.
5160  *  \param [in] famArr - the array of the family field.
5161  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5162  *  \throw If \a famArr has an invalid size.
5163  */
5164 void MEDFileUMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr)
5165 {
5166   if(meshDimRelToMaxExt==1)
5167     {
5168       if(!famArr)
5169         {
5170           _fam_coords=0;
5171           return ;
5172         }
5173       DataArrayDouble *coo(_coords);
5174       if(!coo)
5175         throw INTERP_KERNEL::Exception("MEDFileUMesh::setFamilyFieldArr : the coordinates have not been set !");
5176       famArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),1,"MEDFileUMesh::setFamilyFieldArr : Problem in size of node family arr ! ");
5177       _fam_coords.takeRef(famArr);
5178       return ;
5179     }
5180   if(meshDimRelToMaxExt>1)
5181     throw INTERP_KERNEL::Exception("MEDFileUMesh::setFamilyFieldArr : Dimension request is invalid (>1) !");
5182   int traducedRk=-meshDimRelToMaxExt;
5183   if(traducedRk>=(int)_ms.size())
5184     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
5185   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
5186     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
5187   return _ms[traducedRk]->setFamilyArr(famArr);
5188 }
5189
5190 /*!
5191  * Sets the optional numbers of mesh entities of a given dimension.
5192  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5193  *  \param [in] renumArr - the array of the numbers.
5194  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5195  *  \throw If \a renumArr has an invalid size.
5196  */
5197 void MEDFileUMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr)
5198 {
5199   if(meshDimRelToMaxExt==1)
5200     {
5201       if(!renumArr)
5202         {
5203           _num_coords.nullify();
5204           _rev_num_coords.nullify();
5205           return ;
5206         }
5207       if(_coords.isNull())
5208         throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumFieldArr : the coordinates have not been set !");
5209       renumArr->checkNbOfTuplesAndComp(_coords->getNumberOfTuples(),1,"MEDFileUMesh::setRenumArr : Problem in size of node numbering arr ! ");
5210       _num_coords.takeRef(renumArr);
5211       computeRevNum();
5212       return ;
5213     }
5214   if(meshDimRelToMaxExt>1)
5215     throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumArr : Dimension request is invalid (>1) !");
5216   int traducedRk=-meshDimRelToMaxExt;
5217   if(traducedRk>=(int)_ms.size())
5218     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
5219   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
5220     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
5221   return _ms[traducedRk]->setRenumArr(renumArr);
5222 }
5223
5224 /*!
5225  * Sets the optional names of mesh entities of a given dimension.
5226  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5227  *  \param [in] nameArr - the array of the names.
5228  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5229  *  \throw If \a nameArr has an invalid size.
5230  */
5231 void MEDFileUMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr)
5232 {
5233   if(meshDimRelToMaxExt==1)
5234     {
5235       if(!nameArr)
5236         {
5237           _name_coords=0;
5238           return ;
5239         }
5240       DataArrayDouble *coo(_coords);
5241       if(!coo)
5242         throw INTERP_KERNEL::Exception("MEDFileUMesh::setNameFieldAtLevel : the coordinates have not been set !");
5243       nameArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),MED_SNAME_SIZE,"MEDFileUMesh::setNameFieldAtLevel : Problem in size of node numbering arr ! ");
5244       _name_coords.takeRef(nameArr);
5245       return ;
5246     }
5247   if(meshDimRelToMaxExt>1)
5248     throw INTERP_KERNEL::Exception("MEDFileUMesh::setNameFieldAtLevel : Dimension request is invalid (>1) !");
5249   int traducedRk=-meshDimRelToMaxExt;
5250   if(traducedRk>=(int)_ms.size())
5251     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
5252   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
5253     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
5254   return _ms[traducedRk]->setNameArr(nameArr);
5255 }
5256
5257 void MEDFileUMesh::setGlobalNumFieldAtLevel(int meshDimRelToMaxExt, DataArrayInt *globalNumArr)
5258 {
5259   if(meshDimRelToMaxExt!=1)
5260     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGlobalNumFieldAtLevel : Only implemented for meshDimRelToMaxExt==1 for the moment !");
5261   _global_num_coords.takeRef(globalNumArr);
5262 }
5263
5264 void MEDFileUMesh::synchronizeTinyInfoOnLeaves() const
5265 {
5266   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
5267     if((const MEDFileUMeshSplitL1 *)(*it))
5268       (*it)->synchronizeTinyInfo(*this);
5269 }
5270
5271 /*!
5272  * This method is called by MEDFileMesh::changeFamilyId. It performs only one part of the family id modification.
5273  */
5274 void MEDFileUMesh::changeFamilyIdArr(int oldId, int newId)
5275 {
5276   DataArrayInt *arr=_fam_coords;
5277   if(arr)
5278     arr->changeValue(oldId,newId);
5279   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
5280     {
5281       MEDFileUMeshSplitL1 *sp=(*it);
5282       if(sp)
5283         {
5284           sp->changeFamilyIdArr(oldId,newId);
5285         }
5286     }
5287 }
5288
5289 std::list< MCAuto<DataArrayInt> > MEDFileUMesh::getAllNonNullFamilyIds() const
5290 {
5291   std::list< MCAuto<DataArrayInt> > ret;
5292   const DataArrayInt *da(_fam_coords);
5293   if(da)
5294     { da->incrRef(); ret.push_back(MCAuto<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
5295   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
5296     {
5297       const MEDFileUMeshSplitL1 *elt(*it);
5298       if(elt)
5299         {
5300           da=elt->getFamilyField();
5301           if(da)
5302             { da->incrRef(); ret.push_back(MCAuto<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
5303         }
5304     }
5305   return ret;
5306 }
5307
5308 void MEDFileUMesh::computeRevNum() const
5309 {
5310   if(_num_coords.isNotNull())
5311     {
5312       int pos;
5313       int maxValue=_num_coords->getMaxValue(pos);
5314       _rev_num_coords=_num_coords->invertArrayN2O2O2N(maxValue+1);
5315     }
5316 }
5317
5318 std::size_t MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren() const
5319 {
5320   return MEDFileMesh::getHeapMemorySizeWithoutChildren();
5321 }
5322
5323 std::vector<const BigMemoryObject *> MEDFileStructuredMesh::getDirectChildrenWithNull() const
5324 {
5325   std::vector<const BigMemoryObject *> ret(MEDFileMesh::getDirectChildrenWithNull());
5326   ret.push_back((const DataArrayInt *)_fam_nodes);
5327   ret.push_back((const DataArrayInt *)_num_nodes);
5328   ret.push_back((const DataArrayAsciiChar *)_names_nodes);
5329   ret.push_back((const DataArrayInt *)_fam_cells);
5330   ret.push_back((const DataArrayInt *)_num_cells);
5331   ret.push_back((const DataArrayAsciiChar *)_names_cells);
5332   ret.push_back((const DataArrayInt *)_fam_faces);
5333   ret.push_back((const DataArrayInt *)_num_faces);
5334   ret.push_back((const DataArrayInt *)_rev_num_nodes);
5335   ret.push_back((const DataArrayAsciiChar *)_names_faces);
5336   ret.push_back((const DataArrayInt *)_rev_num_cells);
5337   ret.push_back((const MEDCoupling1SGTUMesh*)_faces_if_necessary);
5338   return ret;
5339 }
5340
5341 int MEDFileStructuredMesh::getMaxAbsFamilyIdInArrays() const
5342 {
5343   int ret=-std::numeric_limits<int>::max(),tmp=-1;
5344   if((const DataArrayInt *)_fam_nodes)
5345     {
5346       int val=_fam_nodes->getMaxValue(tmp);
5347       ret=std::max(ret,std::abs(val));
5348     }
5349   if((const DataArrayInt *)_fam_cells)
5350     {
5351       int val=_fam_cells->getMaxValue(tmp);
5352       ret=std::max(ret,std::abs(val));
5353     }
5354   if((const DataArrayInt *)_fam_faces)
5355     {
5356       int val=_fam_faces->getMaxValue(tmp);
5357       ret=std::max(ret,std::abs(val));
5358     }
5359   return ret;
5360 }
5361
5362 int MEDFileStructuredMesh::getMaxFamilyIdInArrays() const
5363 {
5364   int ret=-std::numeric_limits<int>::max(),tmp=-1;
5365   if((const DataArrayInt *)_fam_nodes)
5366     {
5367       int val=_fam_nodes->getMaxValue(tmp);
5368       ret=std::max(ret,val);
5369     }
5370   if((const DataArrayInt *)_fam_cells)
5371     {
5372       int val=_fam_cells->getMaxValue(tmp);
5373       ret=std::max(ret,val);
5374     }
5375   if((const DataArrayInt *)_fam_faces)
5376     {
5377       int val=_fam_faces->getMaxValue(tmp);
5378       ret=std::max(ret,val);
5379     }
5380   return ret;
5381 }
5382
5383 int MEDFileStructuredMesh::getMinFamilyIdInArrays() const
5384 {
5385   int ret=std::numeric_limits<int>::max(),tmp=-1;
5386   if((const DataArrayInt *)_fam_nodes)
5387     {
5388       int val=_fam_nodes->getMinValue(tmp);
5389       ret=std::min(ret,val);
5390     }
5391   if((const DataArrayInt *)_fam_cells)
5392     {
5393       int val=_fam_cells->getMinValue(tmp);
5394       ret=std::min(ret,val);
5395     }
5396   if((const DataArrayInt *)_fam_faces)
5397     {
5398       int val=_fam_faces->getMinValue(tmp);
5399       ret=std::min(ret,val);
5400     }
5401   return ret;
5402 }
5403
5404 bool MEDFileStructuredMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
5405 {
5406   if(!MEDFileMesh::isEqual(other,eps,what))
5407     return false;
5408   const MEDFileStructuredMesh *otherC=dynamic_cast<const  MEDFileStructuredMesh *>(other);
5409   if(!otherC)
5410     {
5411       what="Mesh types differ ! This is structured and other is NOT !";
5412       return false;
5413     }
5414   const DataArrayInt *famc1=_fam_nodes;
5415   const DataArrayInt *famc2=otherC->_fam_nodes;
5416   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
5417     {
5418       what="Mismatch of families arr on nodes ! One is defined and not other !";
5419       return false;
5420     }
5421   if(famc1)
5422     {
5423       bool ret=famc1->isEqual(*famc2);
5424       if(!ret)
5425         {
5426           what="Families arr on nodes differ !";
5427           return false;
5428         }
5429     }
5430   famc1=_fam_cells;
5431   famc2=otherC->_fam_cells;
5432   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
5433     {
5434       what="Mismatch of families arr on cells ! One is defined and not other !";
5435       return false;
5436     }
5437   if(famc1)
5438     {
5439       bool ret=famc1->isEqual(*famc2);
5440       if(!ret)
5441         {
5442           what="Families arr on cells differ !";
5443           return false;
5444         }
5445     }
5446   famc1=_fam_faces;
5447   famc2=otherC->_fam_faces;
5448   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
5449     {
5450       what="Mismatch of families arr on faces ! One is defined and not other !";
5451       return false;
5452     }
5453   if(famc1)
5454     {
5455       bool ret=famc1->isEqual(*famc2);
5456       if(!ret)
5457         {
5458           what="Families arr on faces differ !";
5459           return false;
5460         }
5461     }
5462   famc1=_num_nodes;
5463   famc2=otherC->_num_nodes;
5464   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
5465     {
5466       what="Mismatch of numbering arr on nodes ! One is defined and not other !";
5467       return false;
5468     }
5469   if(famc1)
5470     {
5471       bool ret=famc1->isEqual(*famc2);
5472       if(!ret)
5473         {
5474           what="Numbering arr on nodes differ !";
5475           return false;
5476         }
5477     }
5478   famc1=_num_cells;
5479   famc2=otherC->_num_cells;
5480   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
5481     {
5482       what="Mismatch of numbering arr on cells ! One is defined and not other !";
5483       return false;
5484     }
5485   if(famc1)
5486     {
5487       bool ret=famc1->isEqual(*famc2);
5488       if(!ret)
5489         {
5490           what="Numbering arr on cells differ !";
5491           return false;
5492         }
5493     }
5494   famc1=_num_faces;
5495   famc2=otherC->_num_faces;
5496   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
5497     {
5498       what="Mismatch of numbering arr on faces ! One is defined and not other !";
5499       return false;
5500     }
5501   if(famc1)
5502     {
5503       bool ret=famc1->isEqual(*famc2);
5504       if(!ret)
5505         {
5506           what="Numbering arr on faces differ !";
5507           return false;
5508         }
5509     }
5510   const DataArrayAsciiChar *d1=_names_cells;
5511   const DataArrayAsciiChar *d2=otherC->_names_cells;
5512   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
5513     {
5514       what="Mismatch of naming arr on cells ! One is defined and not other !";
5515       return false;
5516     }
5517   if(d1)
5518     {
5519       bool ret=d1->isEqual(*d2);
5520       if(!ret)
5521         {
5522           what="Naming arr on cells differ !";
5523           return false;
5524         }
5525     }
5526   d1=_names_faces;
5527   d2=otherC->_names_faces;
5528   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
5529     {
5530       what="Mismatch of naming arr on faces ! One is defined and not other !";
5531       return false;
5532     }
5533   if(d1)
5534     {
5535       bool ret=d1->isEqual(*d2);
5536       if(!ret)
5537         {
5538           what="Naming arr on faces differ !";
5539           return false;
5540         }
5541     }
5542   d1=_names_nodes;
5543   d2=otherC->_names_nodes;
5544   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
5545     {
5546       what="Mismatch of naming arr on nodes ! One is defined and not other !";
5547       return false;
5548     }
5549   if(d1)
5550     {
5551       bool ret=d1->isEqual(*d2);
5552       if(!ret)
5553         {
5554           what="Naming arr on nodes differ !";
5555           return false;
5556         }
5557     }
5558   return true;
5559 }
5560
5561 void MEDFileStructuredMesh::clearNonDiscrAttributes() const
5562 {
5563   MEDFileMesh::clearNonDiscrAttributes();
5564   const DataArrayInt *tmp=_fam_nodes;
5565   if(tmp)
5566     (const_cast<DataArrayInt *>(tmp))->setName("");
5567   tmp=_num_nodes;
5568   if(tmp)
5569     (const_cast<DataArrayInt *>(tmp))->setName("");
5570   tmp=_fam_cells;
5571   if(tmp)
5572     (const_cast<DataArrayInt *>(tmp))->setName("");
5573   tmp=_num_cells;
5574   if(tmp)
5575     (const_cast<DataArrayInt *>(tmp))->setName("");
5576   tmp=_fam_faces;
5577   if(tmp)
5578     (const_cast<DataArrayInt *>(tmp))->setName("");
5579   tmp=_num_faces;
5580   if(tmp)
5581     (const_cast<DataArrayInt *>(tmp))->setName("");
5582 }
5583
5584 /*!
5585  * Returns ids of mesh entities contained in given families of a given dimension.
5586  *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
5587  *          are required.
5588  *  \param [in] fams - the names of the families of interest.
5589  *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
5590  *          returned instead of ids.
5591  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
5592  *          numbers, if available and required, of mesh entities of the families. The caller
5593  *          is to delete this array using decrRef() as it is no more needed. 
5594  *  \throw If the family field is missing for \a meshDimRelToMaxExt.
5595  */
5596 DataArrayInt *MEDFileStructuredMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const
5597 {
5598   std::vector<int> famIds(getFamiliesIds(fams));
5599   switch(meshDimRelToMaxExt)
5600   {
5601     case 1:
5602       {
5603         if((const DataArrayInt *)_fam_nodes)
5604           {
5605             MCAuto<DataArrayInt> da;
5606             if(!famIds.empty())
5607               da=_fam_nodes->findIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
5608             else
5609               da=_fam_nodes->findIdsEqualList(0,0);
5610             if(renum)
5611               return MEDFileUMeshSplitL1::Renumber(_num_nodes,da);
5612             else
5613               return da.retn();
5614           }
5615         else
5616           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on nodes !");
5617         break;
5618       }
5619     case 0:
5620       {
5621         if((const DataArrayInt *)_fam_cells)
5622           {
5623             MCAuto<DataArrayInt> da;
5624             if(!famIds.empty())
5625               da=_fam_cells->findIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
5626             else
5627               da=_fam_cells->findIdsEqualList(0,0);
5628             if(renum)
5629               return MEDFileUMeshSplitL1::Renumber(_num_cells,da);
5630             else
5631               return da.retn();
5632           }
5633         else
5634           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on cells !");
5635         break;
5636       }
5637     case -1:
5638       {
5639         if((const DataArrayInt *)_fam_faces)
5640           {
5641             MCAuto<DataArrayInt> da;
5642             if(!famIds.empty())
5643               da=_fam_faces->findIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
5644             else
5645               da=_fam_faces->findIdsEqualList(0,0);
5646             if(renum)
5647               return MEDFileUMeshSplitL1::Renumber(_num_faces,da);
5648             else
5649               return da.retn();
5650           }
5651         else
5652           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on faces !");
5653         break;
5654       }
5655     default:
5656       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : input meshDimRelative must be in [0,1,-1] !");
5657   }
5658   throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : unmanaged case !");
5659 }
5660
5661 /*!
5662  * Sets the family field of a given relative dimension.
5663  *  \param [in] meshDimRelToMaxExt - the relative dimension of entities for which
5664  *          the family field is set.
5665  *  \param [in] famArr - the array of the family field.
5666  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5667  *  \throw If \a famArr has an invalid size.
5668  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1 and \a meshDimRelToMaxExt != -1.
5669  */
5670 void MEDFileStructuredMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr)
5671 {
5672   const MEDCouplingStructuredMesh *mesh(getStructuredMesh());
5673   if(!mesh)
5674     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setFamilyFieldArr : no structured mesh specified ! Impossible to set family array !");
5675   switch(meshDimRelToMaxExt)
5676   {
5677     case 0:
5678       {
5679         int nbCells(mesh->getNumberOfCells());
5680         if(famArr)
5681           famArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of cells of mesh !");
5682         _fam_cells=famArr;
5683         break;
5684       }
5685     case 1:
5686       {
5687         int nbNodes(mesh->getNumberOfNodes());
5688         if(famArr)
5689           famArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !");
5690         _fam_nodes=famArr;
5691         break;
5692       }
5693     case -1:
5694       {
5695         int nbCells(mesh->getNumberOfCellsOfSubLevelMesh());
5696         if(famArr)
5697           famArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of faces of mesh !");
5698         _fam_faces=famArr;
5699         break;
5700       }
5701     default:
5702       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setFamilyFieldArr : Only available for levels 0 or 1 or -1 !");
5703   }
5704   if(famArr)
5705     famArr->incrRef();
5706 }
5707
5708 /*!
5709  * Sets the optional numbers of mesh entities of a given dimension.
5710  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5711  *  \param [in] renumArr - the array of the numbers.
5712  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5713  *  \throw If \a renumArr has an invalid size.
5714  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
5715  */
5716 void MEDFileStructuredMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr)
5717 {
5718   const MEDCouplingStructuredMesh *mesh=getStructuredMesh();
5719   if(!mesh)
5720     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : no structured mesh specified ! Impossible to set number array !");
5721   switch(meshDimRelToMaxExt)
5722   {
5723     case 0:
5724       {
5725         int nbCells=mesh->getNumberOfCells();
5726         renumArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Renum arr ! Mismatch with number of cells of mesh !");
5727         _num_cells=renumArr;
5728         break;
5729       }
5730     case 1:
5731       {
5732         int nbNodes=mesh->getNumberOfNodes();
5733         renumArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !");
5734         _num_nodes=renumArr;
5735         break;
5736       }
5737     case -1:
5738       {
5739         int nbCells=mesh->getNumberOfCellsOfSubLevelMesh();
5740         renumArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Renum arr ! Mismatch with number of faces of mesh !");
5741         _num_faces=renumArr;
5742         break;
5743       }
5744     default:
5745       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : Only available for levels 0 or 1 or -1 !");
5746   }
5747   if(renumArr)
5748     renumArr->incrRef();
5749 }
5750
5751 /*!
5752  * Sets the optional names of mesh entities of a given dimension.
5753  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5754  *  \param [in] nameArr - the array of the names.
5755  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5756  *  \throw If \a nameArr has an invalid size.
5757  */
5758 void MEDFileStructuredMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr)
5759 {
5760   const MEDCouplingStructuredMesh *mesh(getStructuredMesh());
5761   if(!mesh)
5762     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : no structured mesh specified ! Impossible to set names array !");
5763   switch(meshDimRelToMaxExt)
5764   {
5765     case 0:
5766       {
5767         int nbCells=mesh->getNumberOfCells();
5768         nameArr->checkNbOfTuplesAndComp(nbCells,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of cells of mesh !");
5769         _names_cells=nameArr;
5770         break;
5771       }
5772     case 1:
5773       {
5774         int nbNodes=mesh->getNumberOfNodes();
5775         nameArr->checkNbOfTuplesAndComp(nbNodes,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of nodes of mesh !");
5776         _names_nodes=nameArr;
5777         break;
5778       }
5779     case -1:
5780       {
5781         int nbCells=mesh->getNumberOfCellsOfSubLevelMesh();
5782         nameArr->checkNbOfTuplesAndComp(nbCells,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of faces of mesh !");
5783         _names_cells=nameArr;
5784       }
5785     default:
5786       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : Only available for levels 0 or 1 or -1 !");
5787   }
5788   if(nameArr)
5789     nameArr->incrRef();
5790 }
5791
5792 void MEDFileStructuredMesh::setGlobalNumFieldAtLevel(int meshDimRelToMaxExt, DataArrayInt *globalNumArr)
5793 {
5794   throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setGlobalNumFieldAtLevel : not implemented yet !");
5795 }
5796
5797 /*!
5798  * Adds a group of nodes to \a this mesh.
5799  *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
5800  *          The ids should be sorted and different each other (MED file norm).
5801  *
5802  *  \warning this method can alter default "FAMILLE_ZERO" family.
5803  *  For users sensitive to this a call to MEDFileMesh::rearrangeFamilies will be necessary after addGroup session.
5804  *
5805  *  \throw If the node coordinates array is not set.
5806  *  \throw If \a ids == \c NULL.
5807  *  \throw If \a ids->getName() == "".
5808  *  \throw If \a ids does not respect the MED file norm.
5809  *  \throw If a group with name \a ids->getName() already exists.
5810  */
5811 void MEDFileStructuredMesh::addNodeGroup(const DataArrayInt *ids)
5812 {
5813   addGroup(1,ids);
5814 }
5815
5816 /*!
5817  * Adds a group of nodes/cells/faces/edges to \a this mesh.
5818  *
5819  *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
5820  *          The ids should be sorted and different each other (MED file norm).
5821  *
5822  * \warning this method can alter default "FAMILLE_ZERO" family.
5823  * For users sensitive to this a call to MEDFileMesh::rearrangeFamilies will be necessary after addGroup session.
5824  *
5825  *  \throw If the node coordinates array is not set.
5826  *  \throw If \a ids == \c NULL.
5827  *  \throw If \a ids->getName() == "".
5828  *  \throw If \a ids does not respect the MED file norm.
5829  *  \throw If a group with name \a ids->getName() already exists.
5830  */
5831 void MEDFileStructuredMesh::addGroup(int meshDimRelToMaxExt, const DataArrayInt *ids)
5832 {
5833   DataArrayInt *fam(getOrCreateAndGetFamilyFieldAtLevel(meshDimRelToMaxExt));
5834   addGroupUnderground(false,ids,fam);
5835   return ;
5836 }
5837
5838 /*!
5839  * Returns the family field for mesh entities of a given dimension.
5840  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5841  *  \return const DataArrayInt * - the family field. It is an array of ids of families
5842  *          each mesh entity belongs to. It can be \c NULL.
5843  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
5844  */
5845 const DataArrayInt *MEDFileStructuredMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) const
5846 {
5847   switch(meshDimRelToMaxExt)
5848   {
5849     case 0:
5850       return _fam_cells;
5851     case 1:
5852       return _fam_nodes;
5853     case -1:
5854       return _fam_faces;
5855     default:
5856       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamilyFieldAtLevel : Only available for levels 0 or 1 or -1 !");
5857   }
5858 }
5859
5860 /*!
5861  * Returns the family field for mesh entities of a given dimension.
5862  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5863  *  \return const DataArrayInt * - the family field. It is an array of ids of families
5864  *          each mesh entity belongs to. It can be \c NULL.
5865  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
5866  */
5867 DataArrayInt *MEDFileStructuredMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt)
5868 {
5869   switch(meshDimRelToMaxExt)
5870   {
5871     case 0:
5872       return _fam_cells;
5873     case 1:
5874       return _fam_nodes;
5875     case -1:
5876       return _fam_faces;
5877     default:
5878       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamilyFieldAtLevel : Only available for levels 0 or 1 or -1 !");
5879   }
5880 }
5881
5882 /*!
5883  * Returns the optional numbers of mesh entities of a given dimension.
5884  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5885  *  \return const DataArrayInt * - the array of the entity numbers.
5886  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5887  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
5888  */
5889 const DataArrayInt *MEDFileStructuredMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) const
5890 {
5891   switch(meshDimRelToMaxExt)
5892   {
5893     case 0:
5894       return _num_cells;
5895     case 1:
5896       return _num_nodes;
5897     case -1:
5898       return _num_faces;
5899     default:
5900       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberFieldAtLevel : Only available for levels 0 or 1 or -1 !");
5901   }
5902 }
5903
5904 /*!
5905  * Returns the optional numbers of mesh entities of a given dimension transformed using
5906  * DataArrayInt::invertArrayN2O2O2N().
5907  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5908  *  \return const DataArrayInt * - the array of the entity numbers transformed using
5909  *          DataArrayInt::invertArrayN2O2O2N().
5910  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
5911  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5912  */
5913 const DataArrayInt *MEDFileStructuredMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxExt) const
5914 {
5915   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
5916     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getRevNumberFieldAtLevel : Only available for levels 0 or 1 !");
5917   if(meshDimRelToMaxExt==0)
5918     {
5919       if((const DataArrayInt *)_num_cells)
5920         {
5921           int pos;
5922           int maxValue=_num_cells->getMaxValue(pos);
5923           _rev_num_cells=_num_cells->invertArrayN2O2O2N(maxValue+1);
5924           return _rev_num_cells;
5925         }
5926       else
5927         throw INTERP_KERNEL::Exception("MEDFileCMesh::getRevNumberFieldAtLevel : no cell renumbering for a request on reverse numbering !");
5928     }
5929   else
5930     {
5931       if((const DataArrayInt *)_num_nodes)
5932         {
5933           int pos;
5934           int maxValue=_num_nodes->getMaxValue(pos);
5935           _rev_num_nodes=_num_nodes->invertArrayN2O2O2N(maxValue+1);
5936           return _rev_num_nodes;
5937         }
5938       else
5939         throw INTERP_KERNEL::Exception("MEDFileCMesh::getRevNumberFieldAtLevel : no node renumbering for a request on reverse numbering !");
5940     }
5941 }
5942
5943 const DataArrayAsciiChar *MEDFileStructuredMesh::getNameFieldAtLevel(int meshDimRelToMaxExt) const
5944 {
5945   switch(meshDimRelToMaxExt)
5946   {
5947     case 0:
5948       return _names_cells;
5949     case 1:
5950       return _names_nodes;
5951     case -1:
5952       return _names_faces;
5953     default:
5954       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNameFieldAtLevel : Only available for levels 0 or 1 or -1 !");
5955   }
5956 }
5957
5958 MCAuto<DataArrayInt> MEDFileStructuredMesh::getGlobalNumFieldAtLevel(int meshDimRelToMaxExt) const
5959 {
5960   throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGlobalNumFieldAtLevel : not implemented yet for structured mesh !");
5961 }
5962
5963 /*!
5964  * Returns relative dimensions of mesh entities (excluding nodes) present in \a this mesh.
5965  *  \return std::vector<int> - a sequence of the relative dimensions: [0].
5966  */
5967 std::vector<int> MEDFileStructuredMesh::getNonEmptyLevels() const
5968 {
5969   std::vector<int> ret(1);
5970   return ret;
5971 }
5972
5973 /*!
5974  * Returns relative dimensions of mesh entities (including nodes) present in \a this mesh.
5975  *  \return std::vector<int> - a sequence of the relative dimensions: [1,0].
5976  */
5977 std::vector<int> MEDFileStructuredMesh::getNonEmptyLevelsExt() const
5978 {
5979   std::vector<int> ret(2);
5980   ret[0]=1;
5981   return ret;
5982 }
5983
5984 /*!
5985  * Returns the set of extensive levels (nodes included) where not NULL family arr are defined.
5986  */
5987 std::vector<int> MEDFileStructuredMesh::getFamArrNonEmptyLevelsExt() const
5988 {
5989   std::vector<int> ret;
5990   const DataArrayInt *famNodes(_fam_nodes),*famCells(_fam_cells),*famFaces(_fam_faces);
5991   if(famNodes)
5992     ret.push_back(1);
5993   if(famCells)
5994     ret.push_back(0);
5995   if(famFaces)
5996     ret.push_back(-1);
5997   return ret;
5998 }
5999
6000 /*!
6001  * Returns the set of extensive levels (nodes included) where not NULL numbering arr are defined.
6002  */
6003 std::vector<int> MEDFileStructuredMesh::getNumArrNonEmptyLevelsExt() const
6004 {
6005   std::vector<int> ret;
6006   const DataArrayInt *numNodes(_num_nodes),*numCells(_num_cells),*numFaces(_num_faces);
6007   if(numNodes)
6008     ret.push_back(1);
6009   if(numCells)
6010     ret.push_back(0);
6011   if(numFaces)
6012     ret.push_back(-1);
6013   return ret;
6014 }
6015
6016 /*!
6017  * Returns the set of extensive levels (nodes included) where not NULL naming arr are defined.
6018  */
6019 std::vector<int> MEDFileStructuredMesh::getNameArrNonEmptyLevelsExt() const
6020 {
6021   std::vector<int> ret;
6022   const DataArrayAsciiChar *namesNodes(_names_nodes),*namesCells(_names_cells),*namesFaces(_names_faces);
6023   if(namesNodes)
6024     ret.push_back(1);
6025   if(namesCells)
6026     ret.push_back(0);
6027   if(namesFaces)
6028     ret.push_back(-1);
6029   return ret;
6030 }
6031
6032 /*!
6033  * no implementation here, it is not a bug, but intresically no polyhedra in \a this.
6034  */
6035 bool MEDFileStructuredMesh::unPolyze(std::vector<int>& oldCode, std::vector<int>& newCode, DataArrayInt *& o2nRenumCell)
6036 {
6037   oldCode.clear(); newCode.clear(); o2nRenumCell=0;
6038   return false;
6039 }
6040
6041 void MEDFileStructuredMesh::changeFamilyIdArr(int oldId, int newId)
6042 {
6043   DataArrayInt *arr=_fam_nodes;
6044   if(arr)
6045     arr->changeValue(oldId,newId);
6046   arr=_fam_cells;
6047   if(arr)
6048     arr->changeValue(oldId,newId);
6049   arr=_fam_faces;
6050   if(arr)
6051     arr->changeValue(oldId,newId);
6052 }
6053
6054 std::list< MCAuto<DataArrayInt> > MEDFileStructuredMesh::getAllNonNullFamilyIds() const
6055 {
6056   std::list< MCAuto<DataArrayInt> > ret;
6057   const DataArrayInt *da(_fam_nodes);
6058   if(da)
6059     { da->incrRef(); ret.push_back(MCAuto<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
6060   da=_fam_cells;
6061   if(da)
6062     { da->incrRef(); ret.push_back(MCAuto<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
6063   da=_fam_faces;
6064   if(da)
6065     { da->incrRef(); ret.push_back(MCAuto<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
6066   return ret;
6067 }
6068
6069 void MEDFileStructuredMesh::deepCpyAttributes()
6070 {
6071   if((const DataArrayInt*)_fam_nodes)
6072     _fam_nodes=_fam_nodes->deepCopy();
6073   if((const DataArrayInt*)_num_nodes)
6074     _num_nodes=_num_nodes->deepCopy();
6075   if((const DataArrayAsciiChar*)_names_nodes)
6076     _names_nodes=_names_nodes->deepCopy();
6077   if((const DataArrayInt*)_fam_cells)
6078     _fam_cells=_fam_cells->deepCopy();
6079   if((const DataArrayInt*)_num_cells)
6080     _num_cells=_num_cells->deepCopy();
6081   if((const DataArrayAsciiChar*)_names_cells)
6082     _names_cells=_names_cells->deepCopy();
6083   if((const DataArrayInt*)_fam_faces)
6084     _fam_faces=_fam_faces->deepCopy();
6085   if((const DataArrayInt*)_num_faces)
6086     _num_faces=_num_faces->deepCopy();
6087   if((const DataArrayAsciiChar*)_names_faces)
6088     _names_faces=_names_faces->deepCopy();
6089   if((const DataArrayInt*)_rev_num_nodes)
6090     _rev_num_nodes=_rev_num_nodes->deepCopy();
6091   if((const DataArrayInt*)_rev_num_cells)
6092     _rev_num_cells=_rev_num_cells->deepCopy();
6093 }
6094
6095 /*!
6096  * Returns a pointer to mesh at the specified level (here 0 is compulsary for cartesian mesh).
6097  * 
6098  * \return a pointer to cartesian mesh that need to be managed by the caller.
6099  * \warning the returned pointer has to be managed by the caller.
6100  */
6101
6102 /*!
6103  * Returns a pointer to MEDCouplingStructuredMesh held by \a this. 
6104  *  \param [in] meshDimRelToMax - it must be \c 0 or \c -1.
6105  *  \param [in] renum - it must be \c false.
6106  *  \return MEDCouplingMesh * - a pointer to MEDCouplingMesh that the caller is to
6107  *          delete using decrRef() as it is no more needed. 
6108  */
6109 MEDCouplingMesh *MEDFileStructuredMesh::getMeshAtLevel(int meshDimRelToMax, bool renum) const
6110 {
6111   checkCartesian();
6112   if(renum)
6113     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support renumbering ! To do it perform request of renum array directly !");
6114   const MEDCouplingStructuredMesh *m(getStructuredMesh());
6115   switch(meshDimRelToMax)
6116   {
6117     case 0:
6118       {
6119         if(m)
6120           m->incrRef();
6121         return const_cast<MEDCouplingStructuredMesh *>(m);
6122       }
6123     case -1:
6124       {
6125         if(!m)
6126           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getMeshAtLevel : level -1 requested must be non empty to be able to compute unstructured sub mesh !");
6127         buildMinusOneImplicitPartIfNeeded();
6128         MEDCoupling1SGTUMesh *ret(_faces_if_necessary);
6129         if(ret)
6130           ret->incrRef();
6131         return ret;
6132       }
6133     default:
6134       throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support multi level for mesh 0 expected as input !");
6135   }
6136 }
6137
6138 std::vector<int> MEDFileStructuredMesh::getFamsNonEmptyLevels(const std::vector<std::string>& fams) const
6139 {
6140   std::vector<int> ret;
6141   const DataArrayInt *famCells(_fam_cells),*famFaces(_fam_faces);
6142   if(famCells && famCells->presenceOfValue(ret))
6143     ret.push_back(0);
6144   if(famFaces && famFaces->presenceOfValue(ret))
6145     ret.push_back(-1);
6146   return ret;  
6147 }
6148
6149 std::vector<int> MEDFileStructuredMesh::getFamsNonEmptyLevelsExt(const std::vector<std::string>& fams) const
6150 {
6151   std::vector<int> ret(getFamsNonEmptyLevels(fams));
6152   const DataArrayInt *famNodes(_fam_nodes);
6153   if(famNodes && famNodes->presenceOfValue(ret))
6154     ret.push_back(1);
6155   return ret;  
6156 }
6157
6158 /*!
6159  * Returns number of mesh entities of a given relative dimension in \a this mesh.
6160  *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
6161  *  \return int - the number of entities.
6162  *  \throw If no mesh entities of dimension \a meshDimRelToMaxExt are available in \a this mesh.
6163  */
6164 int MEDFileStructuredMesh::getSizeAtLevel(int meshDimRelToMaxExt) const
6165 {
6166   const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
6167   if(!cmesh)
6168     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : No structured mesh set !");
6169   switch(meshDimRelToMaxExt)
6170   {
6171     case 0:
6172       return cmesh->getNumberOfCells();
6173     case 1:
6174       return cmesh->getNumberOfNodes();
6175     case -1:
6176       return cmesh->getNumberOfCellsOfSubLevelMesh();
6177     default:
6178       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : Only available for levels 0 or 1 or -1 !");
6179   }
6180 }
6181
6182 int MEDFileStructuredMesh::getNumberOfNodes() const
6183 {
6184   const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
6185   if(!cmesh)
6186     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberOfNodes : no cartesian mesh set !");
6187   return cmesh->getNumberOfNodes();
6188 }
6189
6190 int MEDFileStructuredMesh::getNumberOfCellsAtLevel(int meshDimRelToMaxExt) const
6191 {
6192   const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
6193   if(!cmesh)
6194     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberOfNodes : no cartesian mesh set !");
6195   switch(meshDimRelToMaxExt)
6196   {
6197     case 0:
6198       return cmesh->getNumberOfCells();
6199     case -1:
6200       return cmesh->getNumberOfCellsOfSubLevelMesh();
6201     default:
6202       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberOfNodes : only meshDimRelToMax=0 and meshDimRelToMax=-1 supported !");
6203     }
6204 }
6205
6206 bool MEDFileStructuredMesh::hasImplicitPart() const
6207 {
6208   return true;
6209 }
6210
6211 /*!
6212  * \sa MEDFileStructuredMesh::getImplicitFaceMesh
6213  */
6214 int MEDFileStructuredMesh::buildImplicitPartIfAny(INTERP_KERNEL::NormalizedCellType gt) const
6215 {
6216   static const char MSG[]="MEDFileStructuredMesh::buildImplicitPartIfAny : the given geo type is not manageable by a structured mesh !";
6217   const MEDCoupling1SGTUMesh *zeFaceMesh(_faces_if_necessary);
6218   if(!zeFaceMesh)
6219     {
6220       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(getMeshDimension())));
6221       if(cm.getReverseExtrudedType()!=gt)
6222         throw INTERP_KERNEL::Exception(MSG);
6223       buildImplicitPart();
6224       return getStructuredMesh()->getNumberOfCellsOfSubLevelMesh();
6225     }
6226   else
6227     {
6228       if(gt!=zeFaceMesh->getCellModelEnum())
6229         throw INTERP_KERNEL::Exception(MSG);
6230       return zeFaceMesh->getNumberOfCells();
6231     }
6232 }
6233
6234 void MEDFileStructuredMesh::buildMinusOneImplicitPartIfNeeded() const
6235 {
6236   const MEDCoupling1SGTUMesh *zeFaceMesh(_faces_if_necessary);
6237   if(!zeFaceMesh)
6238     buildImplicitPart();
6239 }
6240
6241 void MEDFileStructuredMesh::buildImplicitPart() const
6242 {
6243   const MEDCouplingStructuredMesh *mcmesh(getStructuredMesh());
6244   if(!mcmesh)
6245     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::buildImplicitPart : Unable to build the implicit part of structured mesh because no structured mesh at level 0 defined !");
6246   _faces_if_necessary=mcmesh->build1SGTSubLevelMesh();
6247 }
6248
6249 void MEDFileStructuredMesh::releaseImplicitPartIfAny() const
6250 {
6251   _faces_if_necessary=0;
6252 }
6253
6254 /*!
6255  * Retrieves the internal pointer (no decrRef requested) of the implicit face mesh if any.
6256  * To force to build it you can invoke MEDFileStructuredMesh::buildImplicitPartIfAny method.
6257  * 
6258  * \sa MEDFileStructuredMesh::buildImplicitPartIfAny
6259  */
6260 MEDCoupling1SGTUMesh *MEDFileStructuredMesh::getImplicitFaceMesh() const
6261 {
6262   checkCartesian();
6263   return _faces_if_necessary;
6264 }
6265
6266 std::vector<INTERP_KERNEL::NormalizedCellType> MEDFileStructuredMesh::getGeoTypesAtLevel(int meshDimRelToMax) const
6267 {
6268   const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
6269   if(!cmesh)
6270     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGeoTypesAtLevel : No structured mesh set !");
6271   switch(meshDimRelToMax)
6272   {
6273     case 0:
6274       {
6275         std::vector<INTERP_KERNEL::NormalizedCellType> ret(1,cmesh->getTypeOfCell(0));
6276         return ret;
6277       }
6278     case -1:
6279       {
6280         int mdim(cmesh->getMeshDimension());
6281         if(mdim<1)
6282           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGeoTypesAtLevel : only one level available for structured meshes ! Input 0 is mandatory or 0D mesh !");
6283         std::vector<INTERP_KERNEL::NormalizedCellType> ret(1,MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(mdim-1));
6284         return ret;
6285       }
6286     default:
6287       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGeoTypesAtLevel : only 2 levels available at most : 0 and -1 !");
6288   }
6289 }
6290
6291 int MEDFileStructuredMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType ct) const
6292 {
6293   if(ct!=MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(getMeshDimension()))
6294     return 0;
6295   else
6296     return getNumberOfCellsAtLevel(0);
6297 }
6298
6299 void MEDFileStructuredMesh::whichAreNodesFetched(const MEDFileField1TSStructItem& st, const MEDFileFieldGlobsReal *globs, std::vector<bool>& nodesFetched) const
6300 {
6301   if(st.getNumberOfItems()!=1)
6302     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 !");
6303   if(st[0].getGeo()!=MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(getMeshDimension()))
6304     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : The sturture of field is not lying on expected geo type !");
6305   if(getNumberOfNodes()!=(int)nodesFetched.size())
6306     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : invalid size of array !");
6307   if(st[0].getPflName().empty())
6308     {
6309       std::fill(nodesFetched.begin(),nodesFetched.end(),true);
6310       return ;
6311     }
6312   const DataArrayInt *arr(globs->getProfile(st[0].getPflName()));
6313   const MEDCouplingStructuredMesh *cmesh=getStructuredMesh();//cmesh not null because getNumberOfNodes called before
6314   int sz(nodesFetched.size());
6315   for(const int *work=arr->begin();work!=arr->end();work++)
6316     {
6317       std::vector<int> conn;
6318       cmesh->getNodeIdsOfCell(*work,conn);
6319       for(std::vector<int>::const_iterator it=conn.begin();it!=conn.end();it++)
6320         if(*it>=0 && *it<sz)
6321           nodesFetched[*it]=true;
6322         else
6323           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : internal error !");
6324     }
6325 }
6326
6327 med_geometry_type MEDFileStructuredMesh::GetGeoTypeFromMeshDim(int meshDim)
6328 {
6329   INTERP_KERNEL::NormalizedCellType ct(MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(meshDim));
6330   return typmai3[ct];
6331 }
6332
6333 void MEDFileStructuredMesh::LoadStrMeshDAFromFile(med_idt fid, int meshDim, int dt, int it, const std::string& mName, MEDFileMeshReadSelector *mrs,
6334                                                   MCAuto<DataArrayInt>& famCells, MCAuto<DataArrayInt>& numCells, MCAuto<DataArrayAsciiChar>& namesCells)
6335 {
6336   med_bool chgt=MED_FALSE,trsf=MED_FALSE;
6337   med_geometry_type geoTypeReq=MEDFileStructuredMesh::GetGeoTypeFromMeshDim(meshDim);
6338   int nbOfElt(0);
6339   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf);
6340   if(nbOfElt>0)
6341     {
6342       if(!mrs || mrs->isCellFamilyFieldReading())
6343         {
6344           famCells=DataArrayInt::New();
6345           famCells->alloc(nbOfElt,1);
6346           MEDFILESAFECALLERRD0(MEDmeshEntityFamilyNumberRd,(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,famCells->getPointer()));
6347         }
6348     }
6349   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,MED_NUMBER,MED_NODAL,&chgt,&trsf);
6350   if(nbOfElt>0)
6351     {
6352       if(!mrs || mrs->isCellNumFieldReading())
6353         {
6354           numCells=DataArrayInt::New();
6355           numCells->alloc(nbOfElt,1);
6356           MEDFILESAFECALLERRD0(MEDmeshEntityNumberRd,(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,numCells->getPointer()));
6357         }
6358     }
6359   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,MED_NAME,MED_NODAL,&chgt,&trsf);
6360   if(nbOfElt>0)
6361     {
6362       if(!mrs || mrs->isCellNameFieldReading())
6363         {
6364           namesCells=DataArrayAsciiChar::New();
6365           namesCells->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end
6366           MEDFILESAFECALLERRD0(MEDmeshEntityNameRd,(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,namesCells->getPointer()));
6367           namesCells->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end
6368         }
6369     }
6370 }
6371
6372 void MEDFileStructuredMesh::loadStrMeshFromFile(MEDFileStrMeshL2 *strm, med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6373 {
6374   setName(strm->getName());
6375   setDescription(strm->getDescription());
6376   setUnivName(strm->getUnivName());
6377   setIteration(strm->getIteration());
6378   setOrder(strm->getOrder());
6379   setTimeValue(strm->getTime());
6380   setTimeUnit(strm->getTimeUnit());
6381   MEDFileMeshL2::ReadFamiliesAndGrps(fid,mName,_families,_groups,mrs);
6382   med_bool chgt=MED_FALSE,trsf=MED_FALSE;
6383   int nbOfElt(MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf));
6384   if(nbOfElt>0)
6385     {
6386       if(!mrs || mrs->isNodeFamilyFieldReading())
6387         {
6388           int nbNodes(getNumberOfNodes());
6389           if(nbOfElt>nbNodes)
6390             throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::loadStrMeshFromFile : invalid size of family node array regarding number of nodes in this ! File seems to be corrupted !");
6391           _fam_nodes=DataArrayInt::New();
6392           _fam_nodes->alloc(nbNodes,1);//yes nbNodes and not nbOfElt see next line.
6393           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...
6394             _fam_nodes->fillWithZero();
6395           MEDFILESAFECALLERRD0(MEDmeshEntityFamilyNumberRd,(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,_fam_nodes->getPointer()));
6396         }
6397     }
6398   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_NUMBER,MED_NODAL,&chgt,&trsf);
6399   if(nbOfElt>0)
6400     {
6401       if(!mrs || mrs->isNodeNumFieldReading())
6402         {
6403           _num_nodes=DataArrayInt::New();
6404           _num_nodes->alloc(nbOfElt,1);
6405           MEDFILESAFECALLERRD0(MEDmeshEntityNumberRd,(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,_num_nodes->getPointer()));
6406         }
6407     }
6408   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_NAME,MED_NODAL,&chgt,&trsf);
6409   if(nbOfElt>0)
6410     {
6411       if(!mrs || mrs->isNodeNameFieldReading())
6412         {
6413           _names_nodes=DataArrayAsciiChar::New();
6414           _names_nodes->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end
6415           MEDFILESAFECALLERRD0(MEDmeshEntityNameRd,(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,_names_nodes->getPointer()));
6416           _names_nodes->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end
6417         }
6418     }
6419   int meshDim(getStructuredMesh()->getMeshDimension());
6420   LoadStrMeshDAFromFile(fid,meshDim,dt,it,mName,mrs,_fam_cells,_num_cells,_names_cells);
6421   if(meshDim>=1)
6422     LoadStrMeshDAFromFile(fid,meshDim-1,dt,it,mName,mrs,_fam_faces,_num_faces,_names_faces);
6423 }
6424
6425 void MEDFileStructuredMesh::writeStructuredLL(med_idt fid, const std::string& maa) const
6426 {
6427   int meshDim(getStructuredMesh()->getMeshDimension());
6428   med_geometry_type geoTypeReq(GetGeoTypeFromMeshDim(meshDim)),geoTypeReq2(GetGeoTypeFromMeshDim(meshDim-1));
6429   //
6430   if((const DataArrayInt *)_fam_cells)
6431     MEDFILESAFECALLERWR0(MEDmeshEntityFamilyNumberWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq,_fam_cells->getNumberOfTuples(),_fam_cells->getConstPointer()));
6432   if((const DataArrayInt *)_fam_faces)
6433     MEDFILESAFECALLERWR0(MEDmeshEntityFamilyNumberWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq2,_fam_faces->getNumberOfTuples(),_fam_faces->getConstPointer()));
6434   if((const DataArrayInt *)_fam_nodes)
6435     MEDFILESAFECALLERWR0(MEDmeshEntityFamilyNumberWr,(fid,maa.c_str(),_iteration,_order,MED_NODE,MED_NONE,_fam_nodes->getNumberOfTuples(),_fam_nodes->getConstPointer()));
6436   if((const DataArrayInt *)_num_cells)
6437     MEDFILESAFECALLERWR0(MEDmeshEntityNumberWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq,_num_cells->getNumberOfTuples(),_num_cells->getConstPointer()));
6438   if((const DataArrayInt *)_num_faces)
6439     MEDFILESAFECALLERWR0(MEDmeshEntityNumberWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq2,_num_faces->getNumberOfTuples(),_num_faces->getConstPointer()));
6440   if((const DataArrayInt *)_num_nodes)
6441     MEDFILESAFECALLERWR0(MEDmeshEntityNumberWr,(fid,maa.c_str(),_iteration,_order,MED_NODE,MED_NONE,_num_nodes->getNumberOfTuples(),_num_nodes->getConstPointer()));
6442   if((const DataArrayAsciiChar *)_names_cells)
6443     {
6444       if(_names_cells->getNumberOfComponents()!=MED_SNAME_SIZE)
6445         {
6446           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on cells with number of components set to " << MED_SNAME_SIZE;
6447           oss << " ! The array has " << _names_cells->getNumberOfComponents() << " components !";
6448           throw INTERP_KERNEL::Exception(oss.str().c_str());
6449         }
6450       MEDFILESAFECALLERWR0(MEDmeshEntityNameWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq,_names_cells->getNumberOfTuples(),_names_cells->getConstPointer()));
6451     }
6452   if((const DataArrayAsciiChar *)_names_faces)
6453     {
6454       if(_names_faces->getNumberOfComponents()!=MED_SNAME_SIZE)
6455         {
6456           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on faces with number of components set to " << MED_SNAME_SIZE;
6457           oss << " ! The array has " << _names_faces->getNumberOfComponents() << " components !";
6458           throw INTERP_KERNEL::Exception(oss.str().c_str());
6459         }
6460       MEDFILESAFECALLERWR0(MEDmeshEntityNameWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq2,_names_faces->getNumberOfTuples(),_names_faces->getConstPointer()));
6461     }
6462   if((const DataArrayAsciiChar *)_names_nodes)
6463     {
6464       if(_names_nodes->getNumberOfComponents()!=MED_SNAME_SIZE)
6465         {
6466           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on nodes with number of components set to " << MED_SNAME_SIZE;
6467           oss << " ! The array has " << _names_cells->getNumberOfComponents() << " components !";
6468           throw INTERP_KERNEL::Exception(oss.str().c_str());
6469         }
6470       MEDFILESAFECALLERWR0(MEDmeshEntityNameWr,(fid,maa.c_str(),_iteration,_order,MED_NODE,MED_NONE,_names_nodes->getNumberOfTuples(),_names_nodes->getConstPointer()));
6471     }
6472   //
6473   MEDFileUMeshL2::WriteFamiliesAndGrps(fid,maa.c_str(),_families,_groups,_too_long_str);
6474 }
6475
6476 /*!
6477  * Returns an empty instance of MEDFileCMesh.
6478  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
6479  *          mesh using decrRef() as it is no more needed. 
6480  */
6481 MEDFileCMesh *MEDFileCMesh::New()
6482 {
6483   return new MEDFileCMesh;
6484 }
6485
6486 /*!
6487  * Returns a new MEDFileCMesh holding the mesh data that has been read from a given MED
6488  * file. The first mesh in the file is loaded.
6489  *  \param [in] fileName - the name of MED file to read.
6490  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
6491  *          mesh using decrRef() as it is no more needed. 
6492  *  \throw If the file is not readable.
6493  *  \throw If there is no meshes in the file.
6494  *  \throw If the mesh in the file is not a Cartesian one.
6495  */
6496 MEDFileCMesh *MEDFileCMesh::New(const std::string& fileName, MEDFileMeshReadSelector *mrs)
6497 {
6498   MEDFileUtilities::AutoFid fid(OpenMEDFileForRead(fileName));
6499   return New(fid,mrs);
6500 }
6501
6502 MEDFileCMesh *MEDFileCMesh::New(med_idt fid, MEDFileMeshReadSelector *mrs)
6503 {
6504   return NewForTheFirstMeshInFile<MEDFileCMesh>(fid,mrs);
6505 }
6506
6507 /*!
6508  * Returns a new MEDFileCMesh holding the mesh data that has been read from a given MED
6509  * file. The mesh to load is specified by its name and numbers of a time step and an
6510  * iteration.
6511  *  \param [in] fileName - the name of MED file to read.
6512  *  \param [in] mName - the name of the mesh to read.
6513  *  \param [in] dt - the number of a time step.
6514  *  \param [in] it - the number of an iteration.
6515  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
6516  *          mesh using decrRef() as it is no more needed. 
6517  *  \throw If the file is not readable.
6518  *  \throw If there is no mesh with given attributes in the file.
6519  *  \throw If the mesh in the file is not a Cartesian one.
6520  */
6521 MEDFileCMesh *MEDFileCMesh::New(const std::string& fileName, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6522 {
6523   MEDFileUtilities::AutoFid fid(OpenMEDFileForRead(fileName));
6524   return New(fid,mName,dt,it,mrs);
6525 }
6526
6527 MEDFileCMesh *MEDFileCMesh::New(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6528 {
6529   return new MEDFileCMesh(fid,mName,dt,it,mrs);
6530 }
6531
6532 std::size_t MEDFileCMesh::getHeapMemorySizeWithoutChildren() const
6533 {
6534   return MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren();
6535 }
6536
6537 std::vector<const BigMemoryObject *> MEDFileCMesh::getDirectChildrenWithNull() const
6538 {
6539   std::vector<const BigMemoryObject *> ret(MEDFileStructuredMesh::getDirectChildrenWithNull());
6540   ret.push_back((const MEDCouplingCMesh *)_cmesh);
6541   return ret;
6542 }
6543
6544 /*!
6545  * Returns the dimension on cells in \a this mesh.
6546  *  \return int - the mesh dimension.
6547  *  \throw If there are no cells in this mesh.
6548  */
6549 int MEDFileCMesh::getMeshDimension() const
6550 {
6551   if(!((const MEDCouplingCMesh*)_cmesh))
6552     throw INTERP_KERNEL::Exception("MEDFileCMesh::getMeshDimension : unable to get meshdimension because no mesh set !");
6553   return _cmesh->getMeshDimension();
6554 }
6555
6556 /*!
6557  * Returns the dimension on nodes in \a this mesh.
6558  *  \return int - the space dimension.
6559  *  \throw If there are no cells in this mesh.
6560  */
6561 int MEDFileCMesh::getSpaceDimension() const
6562 {
6563   if(!((const MEDCouplingCMesh*)_cmesh))
6564     throw INTERP_KERNEL::Exception("MEDFileCMesh::getSpaceDimension : unable to get spacedimension because no mesh set !");
6565   return _cmesh->getSpaceDimension();
6566 }
6567
6568 /*!
6569  * Returns a string describing \a this mesh.
6570  *  \return std::string - the mesh information string.
6571  */
6572 std::string MEDFileCMesh::simpleRepr() const
6573 {
6574   return MEDFileStructuredMesh::simpleRepr();
6575 }
6576
6577 /*!
6578  * Returns a full textual description of \a this mesh.
6579  *  \return std::string - the string holding the mesh description.
6580  */
6581 std::string MEDFileCMesh::advancedRepr() const
6582 {
6583   return simpleRepr();
6584 }
6585
6586 MEDFileCMesh *MEDFileCMesh::shallowCpy() const
6587 {
6588   MCAuto<MEDFileCMesh> ret(new MEDFileCMesh(*this));
6589   return ret.retn();
6590 }
6591
6592 MEDFileMesh *MEDFileCMesh::createNewEmpty() const
6593 {
6594   return new MEDFileCMesh;
6595 }
6596
6597 MEDFileCMesh *MEDFileCMesh::deepCopy() const
6598 {
6599   MCAuto<MEDFileCMesh> ret(new MEDFileCMesh(*this));
6600   ret->deepCpyEquivalences(*this);
6601   if((const MEDCouplingCMesh*)_cmesh)
6602     ret->_cmesh=static_cast<MEDCouplingCMesh*>(_cmesh->deepCopy());
6603   ret->deepCpyAttributes();
6604   return ret.retn();
6605 }
6606
6607 /*!
6608  * Checks if \a this and another mesh are equal.
6609  *  \param [in] other - the mesh to compare with.
6610  *  \param [in] eps - a precision used to compare real values.
6611  *  \param [in,out] what - the string returning description of unequal data.
6612  *  \return bool - \c true if the meshes are equal, \c false, else.
6613  */
6614 bool MEDFileCMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
6615 {
6616   if(!MEDFileStructuredMesh::isEqual(other,eps,what))
6617     return false;
6618   const MEDFileCMesh *otherC=dynamic_cast<const MEDFileCMesh *>(other);
6619   if(!otherC)
6620     {
6621       what="Mesh types differ ! This is cartesian and other is NOT !";
6622       return false;
6623     }
6624   clearNonDiscrAttributes();
6625   otherC->clearNonDiscrAttributes();
6626   const MEDCouplingCMesh *coo1=_cmesh;
6627   const MEDCouplingCMesh *coo2=otherC->_cmesh;
6628   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
6629     {
6630       what="Mismatch of cartesian meshes ! One is defined and not other !";
6631       return false;
6632     }
6633   if(coo1)
6634     {
6635       bool ret=coo1->isEqual(coo2,eps);
6636       if(!ret)
6637         {
6638           what="cartesian meshes differ !";
6639           return false;
6640         }
6641     }
6642   return true;
6643 }
6644
6645 /*!
6646  * Clears redundant attributes of incorporated data arrays.
6647  */
6648 void MEDFileCMesh::clearNonDiscrAttributes() const
6649 {
6650   MEDFileStructuredMesh::clearNonDiscrAttributes();
6651   MEDFileUMeshSplitL1::ClearNonDiscrAttributes(_cmesh);//to it is not a bug umeshsplit have already the method implemented
6652 }
6653
6654 MEDFileCMesh::MEDFileCMesh()
6655 {
6656 }
6657
6658 MEDFileCMesh::MEDFileCMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6659 try
6660 {
6661     loadLLWithAdditionalItems(fid,mName,dt,it,mrs);
6662 }
6663 catch(INTERP_KERNEL::Exception& e)
6664 {
6665     throw e;
6666 }
6667
6668 void MEDFileCMesh::loadLL(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6669 {
6670   MEDCoupling::MEDCouplingMeshType meshType;
6671   int dummy0,dummy1;
6672   std::string dtunit;
6673   MEDCoupling::MEDCouplingAxisType axType;
6674   INTERP_KERNEL::AutoCppPtr<MeshOrStructMeshCls> mid(MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,axType,dummy0,dummy1,dtunit));
6675   if(meshType!=CARTESIAN)
6676     {
6677       std::ostringstream oss; oss << "Trying to load as cartesian an existing mesh with name '" << mName << "' that is NOT cartesian !";
6678       throw INTERP_KERNEL::Exception(oss.str().c_str());
6679     }
6680   MEDFileCMeshL2 loaderl2;
6681   loaderl2.loadAll(fid,mid,mName,dt,it);
6682   setAxisType(axType);
6683   MEDCouplingCMesh *mesh=loaderl2.getMesh();
6684   mesh->incrRef();
6685   _cmesh=mesh;
6686   loadStrMeshFromFile(&loaderl2,fid,mName,dt,it,mrs);
6687 }
6688
6689 /*!
6690  * Returns a const pointer to MEDCouplingCMesh held by \a this mesh.
6691  *  \return const MEDCouplingCMesh * - a pointer to the held MEDCouplingCMesh.
6692  */
6693 const MEDCouplingCMesh *MEDFileCMesh::getMesh() const
6694 {
6695   synchronizeTinyInfoOnLeaves();
6696   return _cmesh;
6697 }
6698
6699 const MEDCouplingStructuredMesh *MEDFileCMesh::getStructuredMesh() const
6700 {
6701   synchronizeTinyInfoOnLeaves();
6702   return _cmesh;
6703 }
6704
6705 /*!
6706  * Sets the MEDCouplingCMesh holding the data of \a this mesh.
6707  *  \param [in] m - the new MEDCouplingCMesh to refer to.
6708  *  \throw If the name or the description of \a this mesh and \a m are not empty and are
6709  *         different. 
6710  */
6711 void MEDFileCMesh::setMesh(MEDCouplingCMesh *m)
6712 {
6713   dealWithTinyInfo(m);
6714   if(m)
6715     m->incrRef();
6716   _cmesh=m;
6717 }
6718
6719 MEDFileMesh *MEDFileCMesh::cartesianize() const
6720 {
6721   if(getAxisType()==AX_CART)
6722     {
6723       incrRef();
6724       return const_cast<MEDFileCMesh *>(this);
6725     }
6726   else
6727     {
6728       const MEDCouplingCMesh *cmesh(getMesh());
6729       if(!cmesh)
6730         throw INTERP_KERNEL::Exception("MEDFileCMesh::cartesianize : impossible to turn into cartesian because the mesh is null !");
6731       MCAuto<MEDCouplingCurveLinearMesh> clmesh(cmesh->buildCurveLinear());
6732       MCAuto<DataArrayDouble> coords(clmesh->getCoords()->cartesianize(getAxisType()));
6733       clmesh->setCoords(coords);
6734       MCAuto<MEDFileCurveLinearMesh> ret(MEDFileCurveLinearMesh::New());
6735       ret->MEDFileStructuredMesh::operator=(*this);
6736       ret->setMesh(clmesh);
6737       ret->setAxisType(AX_CART);
6738       return ret.retn();
6739     }
6740 }
6741
6742 void MEDFileCMesh::writeMeshLL(med_idt fid) const
6743 {
6744   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
6745   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
6746   INTERP_KERNEL::AutoPtr<char> dtunit=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE);
6747   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
6748   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
6749   MEDLoaderBase::safeStrCpy(_dt_unit.c_str(),MED_LNAME_SIZE,dtunit,_too_long_str);
6750   int spaceDim(_cmesh->getSpaceDimension());
6751   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
6752   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
6753   for(int i=0;i<spaceDim;i++)
6754     {
6755       std::string info(_cmesh->getCoordsAt(i)->getInfoOnComponent(0));
6756       std::string c,u;
6757       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
6758       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
6759       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
6760     }
6761   MEDFILESAFECALLERWR0(MEDmeshCr,(fid,maa,spaceDim,spaceDim,MED_STRUCTURED_MESH,desc,dtunit,MED_SORT_DTIT,MEDFileMeshL2::TraduceAxisTypeRev(getAxisType()),comp,unit));
6762   if(_univ_wr_status)
6763     MEDFILESAFECALLERWR0(MEDmeshUniversalNameWr,(fid,maa));
6764   MEDFILESAFECALLERWR0(MEDmeshGridTypeWr,(fid,maa,MEDFileMeshL2::TraduceAxisTypeRevStruct(getAxisType())));
6765   for(int i=0;i<spaceDim;i++)
6766     {
6767       const DataArrayDouble *da=_cmesh->getCoordsAt(i);
6768       MEDFILESAFECALLERWR0(MEDmeshGridIndexCoordinateWr,(fid,maa,_iteration,_order,_time,i+1,da->getNumberOfTuples(),da->getConstPointer()));
6769     }
6770   //
6771   std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE));
6772   MEDFileStructuredMesh::writeStructuredLL(fid,meshName);
6773 }
6774
6775 void MEDFileCMesh::synchronizeTinyInfoOnLeaves() const
6776 {
6777   const MEDCouplingCMesh *cmesh=_cmesh;
6778   if(!cmesh)
6779     return;
6780   (const_cast<MEDCouplingCMesh *>(cmesh))->setName(_name);
6781   (const_cast<MEDCouplingCMesh *>(cmesh))->setDescription(_desc_name);
6782   (const_cast<MEDCouplingCMesh *>(cmesh))->setTime(_time,_iteration,_order);
6783   (const_cast<MEDCouplingCMesh *>(cmesh))->setTimeUnit(_dt_unit);
6784 }
6785
6786 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New()
6787 {
6788   return new MEDFileCurveLinearMesh;
6789 }
6790
6791 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(med_idt fid, MEDFileMeshReadSelector *mrs)
6792 {
6793   return NewForTheFirstMeshInFile<MEDFileCurveLinearMesh>(fid,mrs);
6794 }
6795
6796 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const std::string& fileName, MEDFileMeshReadSelector *mrs)
6797 {
6798   MEDFileUtilities::AutoFid fid(OpenMEDFileForRead(fileName));
6799   return New(fid,mrs);
6800 }
6801
6802 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const std::string& fileName, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6803 {
6804   MEDFileUtilities::AutoFid fid(OpenMEDFileForRead(fileName));
6805   return New(fid,mName,dt,it,mrs);
6806 }
6807
6808 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6809 {
6810   return new MEDFileCurveLinearMesh(fid,mName,dt,it,mrs);
6811 }
6812
6813 std::size_t MEDFileCurveLinearMesh::getHeapMemorySizeWithoutChildren() const
6814 {
6815   return MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren();
6816 }
6817
6818 std::vector<const BigMemoryObject *> MEDFileCurveLinearMesh::getDirectChildrenWithNull() const
6819 {
6820   std::vector<const BigMemoryObject *> ret(MEDFileStructuredMesh::getDirectChildrenWithNull());
6821   ret.push_back((const MEDCouplingCurveLinearMesh *)_clmesh);
6822   return ret;
6823 }
6824
6825 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::shallowCpy() const
6826 {
6827   MCAuto<MEDFileCurveLinearMesh> ret(new MEDFileCurveLinearMesh(*this));
6828   return ret.retn();
6829 }
6830
6831 MEDFileMesh *MEDFileCurveLinearMesh::createNewEmpty() const
6832 {
6833   return new MEDFileCurveLinearMesh;
6834 }
6835
6836 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::deepCopy() const
6837 {
6838   MCAuto<MEDFileCurveLinearMesh> ret(new MEDFileCurveLinearMesh(*this));
6839   ret->deepCpyEquivalences(*this);
6840   if((const MEDCouplingCurveLinearMesh*)_clmesh)
6841     ret->_clmesh=static_cast<MEDCouplingCurveLinearMesh*>(_clmesh->deepCopy());
6842   ret->deepCpyAttributes();
6843   return ret.retn();
6844 }
6845
6846 int MEDFileCurveLinearMesh::getMeshDimension() const
6847 {
6848   if(!((const MEDCouplingCurveLinearMesh*)_clmesh))
6849     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::getMeshDimension : unable to get meshdimension because no mesh set !");
6850   return _clmesh->getMeshDimension();
6851 }
6852
6853 std::string MEDFileCurveLinearMesh::simpleRepr() const
6854 {
6855   return MEDFileStructuredMesh::simpleRepr();
6856 }
6857
6858 std::string MEDFileCurveLinearMesh::advancedRepr() const
6859 {
6860   return simpleRepr();
6861 }
6862
6863 bool MEDFileCurveLinearMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
6864 {
6865   if(!MEDFileStructuredMesh::isEqual(other,eps,what))
6866     return false;
6867   const MEDFileCurveLinearMesh *otherC=dynamic_cast<const MEDFileCurveLinearMesh *>(other);
6868   if(!otherC)
6869     {
6870       what="Mesh types differ ! This is curve linear and other is NOT !";
6871       return false;
6872     }
6873   clearNonDiscrAttributes();
6874   otherC->clearNonDiscrAttributes();
6875   const MEDCouplingCurveLinearMesh *coo1=_clmesh;
6876   const MEDCouplingCurveLinearMesh *coo2=otherC->_clmesh;
6877   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
6878     {
6879       what="Mismatch of curve linear meshes ! One is defined and not other !";
6880       return false;
6881     }
6882   if(coo1)
6883     {
6884       bool ret=coo1->isEqual(coo2,eps);
6885       if(!ret)
6886         {
6887           what="curve linear meshes differ !";
6888           return false;
6889         }
6890     }
6891   return true;
6892 }
6893
6894 void MEDFileCurveLinearMesh::clearNonDiscrAttributes() const
6895 {
6896   MEDFileStructuredMesh::clearNonDiscrAttributes();
6897   MEDFileUMeshSplitL1::ClearNonDiscrAttributes(_clmesh);//to it is not a bug umeshsplit have already the method implemented
6898 }
6899
6900 void MEDFileCurveLinearMesh::synchronizeTinyInfoOnLeaves() const
6901 {
6902   const MEDCouplingCurveLinearMesh *clmesh=_clmesh;
6903   if(!clmesh)
6904     return;
6905   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setName(_name);
6906   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setDescription(_desc_name);
6907   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setTime(_time,_iteration,_order);
6908   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setTimeUnit(_dt_unit);
6909 }
6910
6911 const MEDCouplingCurveLinearMesh *MEDFileCurveLinearMesh::getMesh() const
6912 {
6913   synchronizeTinyInfoOnLeaves();
6914   return _clmesh;
6915 }
6916
6917 void MEDFileCurveLinearMesh::setMesh(MEDCouplingCurveLinearMesh *m)
6918 {
6919   dealWithTinyInfo(m);
6920   if(m)
6921     m->incrRef();
6922   _clmesh=m;
6923 }
6924
6925 MEDFileMesh *MEDFileCurveLinearMesh::cartesianize() const
6926 {
6927   if(getAxisType()==AX_CART)
6928     {
6929       incrRef();
6930       return const_cast<MEDFileCurveLinearMesh *>(this);
6931     }
6932   else
6933     {
6934       const MEDCouplingCurveLinearMesh *mesh(getMesh());
6935       if(!mesh)
6936         throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::cartesianize : impossible to turn into cartesian because the mesh is null !");
6937       const DataArrayDouble *coords(mesh->getCoords());
6938       if(!coords)
6939         throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::cartesianize : coordinate pointer in mesh is null !");
6940       MCAuto<MEDFileCurveLinearMesh> ret(new MEDFileCurveLinearMesh(*this));
6941       MCAuto<MEDCouplingCurveLinearMesh> mesh2(mesh->clone(false));
6942       MCAuto<DataArrayDouble> coordsCart(coords->cartesianize(getAxisType()));
6943       mesh2->setCoords(coordsCart);
6944       ret->setMesh(mesh2);
6945       ret->setAxisType(AX_CART);
6946       return ret.retn();
6947     }
6948 }
6949
6950 const MEDCouplingStructuredMesh *MEDFileCurveLinearMesh::getStructuredMesh() const
6951 {
6952   synchronizeTinyInfoOnLeaves();
6953   return _clmesh;
6954 }
6955
6956 MEDFileCurveLinearMesh::MEDFileCurveLinearMesh()
6957 {
6958 }
6959
6960 MEDFileCurveLinearMesh::MEDFileCurveLinearMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6961 try
6962 {
6963     loadLLWithAdditionalItems(fid,mName,dt,it,mrs);
6964 }
6965 catch(INTERP_KERNEL::Exception& e)
6966 {
6967     throw e;
6968 }
6969
6970 void MEDFileCurveLinearMesh::writeMeshLL(med_idt fid) const
6971 {
6972   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
6973   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
6974   INTERP_KERNEL::AutoPtr<char> dtunit=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE);
6975   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
6976   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
6977   MEDLoaderBase::safeStrCpy(_dt_unit.c_str(),MED_LNAME_SIZE,dtunit,_too_long_str);
6978   int spaceDim=_clmesh->getSpaceDimension();
6979   int meshDim=_clmesh->getMeshDimension();
6980   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
6981   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
6982   const DataArrayDouble *coords=_clmesh->getCoords();
6983   if(!coords)
6984     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::writeMeshLL : no coordinates set !");
6985   for(int i=0;i<spaceDim;i++)
6986     {
6987       std::string info(_clmesh->getCoords()->getInfoOnComponent(i));
6988       std::string c,u;
6989       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
6990       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
6991       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
6992     }
6993   MEDFILESAFECALLERWR0(MEDmeshCr,(fid,maa,spaceDim,meshDim,MED_STRUCTURED_MESH,desc,dtunit,MED_SORT_DTIT,MEDFileMeshL2::TraduceAxisTypeRev(getAxisType()),comp,unit));
6994   if(_univ_wr_status)
6995     MEDFILESAFECALLERWR0(MEDmeshUniversalNameWr,(fid,maa));
6996   MEDFILESAFECALLERWR0(MEDmeshGridTypeWr,(fid,maa,MED_CURVILINEAR_GRID));
6997   std::vector<int> nodeGridSt=_clmesh->getNodeGridStructure();
6998   MEDFILESAFECALLERWR0(MEDmeshGridStructWr,(fid,maa,_iteration,_order,_time,&nodeGridSt[0]));
6999
7000   MEDFILESAFECALLERWR0(MEDmeshNodeCoordinateWr,(fid,maa,_iteration,_order,_time,MED_FULL_INTERLACE,coords->getNumberOfTuples(),coords->begin()));
7001   //
7002   std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE));
7003   MEDFileStructuredMesh::writeStructuredLL(fid,meshName);
7004 }
7005
7006 void MEDFileCurveLinearMesh::loadLL(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
7007 {
7008   MEDCoupling::MEDCouplingMeshType meshType;
7009   int dummy0,dummy1;
7010   std::string dtunit;
7011   MEDCoupling::MEDCouplingAxisType axType;
7012   INTERP_KERNEL::AutoCppPtr<MeshOrStructMeshCls> mid(MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,axType,dummy0,dummy1,dtunit));
7013   setAxisType(axType);
7014   if(meshType!=CURVE_LINEAR)
7015     {
7016       std::ostringstream oss; oss << "Trying to load as curve linear an existing mesh with name '" << mName << "' that is NOT curve linear !";
7017       throw INTERP_KERNEL::Exception(oss.str().c_str());
7018     }
7019   MEDFileCLMeshL2 loaderl2;
7020   loaderl2.loadAll(fid,mid,mName,dt,it);
7021   MEDCouplingCurveLinearMesh *mesh=loaderl2.getMesh();
7022   mesh->incrRef();
7023   _clmesh=mesh;
7024   loadStrMeshFromFile(&loaderl2,fid,mName,dt,it,mrs);
7025 }
7026
7027 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New()
7028 {
7029   return new MEDFileMeshMultiTS;
7030 }
7031
7032 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(med_idt fid)
7033 {
7034   return new MEDFileMeshMultiTS(fid);
7035 }
7036
7037 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(const std::string& fileName)
7038 {
7039   MEDFileUtilities::AutoFid fid(OpenMEDFileForRead(fileName));
7040   return New(fid);
7041 }
7042
7043 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(med_idt fid, const std::string& mName)
7044 {
7045   return new MEDFileMeshMultiTS(fid,mName);
7046 }
7047
7048 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(const std::string& fileName, const std::string& mName)
7049 {
7050   MEDFileUtilities::AutoFid fid(OpenMEDFileForRead(fileName));
7051   return New(fid,mName);
7052 }
7053
7054 MEDFileMeshMultiTS *MEDFileMeshMultiTS::deepCopy() const
7055 {
7056   MCAuto<MEDFileMeshMultiTS> ret(MEDFileMeshMultiTS::New());
7057   std::vector< MCAuto<MEDFileMesh> > meshOneTs(_mesh_one_ts.size());
7058   std::size_t i(0);
7059   for(std::vector< MCAuto<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++,i++)
7060     if((const MEDFileMesh *)*it)
7061       meshOneTs[i]=(*it)->deepCopy();
7062   ret->_mesh_one_ts=meshOneTs;
7063   return ret.retn();
7064 }
7065
7066 std::size_t MEDFileMeshMultiTS::getHeapMemorySizeWithoutChildren() const
7067 {
7068   return _mesh_one_ts.capacity()*sizeof(MCAuto<MEDFileMesh>);
7069 }
7070
7071 std::vector<const BigMemoryObject *> MEDFileMeshMultiTS::getDirectChildrenWithNull() const
7072 {
7073   std::vector<const BigMemoryObject *> ret;
7074   for(std::vector< MCAuto<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
7075     ret.push_back((const MEDFileMesh *)*it);
7076   return ret;
7077 }
7078
7079 std::string MEDFileMeshMultiTS::getName() const
7080 {
7081   if(_mesh_one_ts.empty())
7082     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::getName : no time steps set !");
7083   return _mesh_one_ts[0]->getName();
7084 }
7085
7086 void MEDFileMeshMultiTS::setName(const std::string& newMeshName)
7087 {
7088   std::string oldName(getName());
7089   std::vector< std::pair<std::string,std::string> > v(1);
7090   v[0].first=oldName; v[0].second=newMeshName;
7091   changeNames(v);
7092 }
7093
7094 bool MEDFileMeshMultiTS::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab)
7095 {
7096   bool ret=false;
7097   for(std::vector< MCAuto<MEDFileMesh> >::iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
7098     {
7099       MEDFileMesh *cur(*it);
7100       if(cur)
7101         ret=cur->changeNames(modifTab) || ret;
7102     }
7103   return ret;
7104 }
7105
7106 void MEDFileMeshMultiTS::cartesianizeMe()
7107 {
7108   for(std::vector< MCAuto<MEDFileMesh> >::iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
7109     {
7110       MEDFileMesh *cur(*it);
7111       if(cur)
7112         {
7113           MCAuto<MEDFileMesh> ccur(cur->cartesianize());// Attention ! Do not wrap these two lines because memory leak !
7114           *it=ccur;
7115         }
7116     }
7117 }
7118
7119 MEDFileMesh *MEDFileMeshMultiTS::getOneTimeStep() const
7120 {
7121   if(_mesh_one_ts.empty())
7122     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::getOneTimeStep : empty time step set !");
7123   return const_cast<MEDFileMesh *>(static_cast<const MEDFileMesh *>(_mesh_one_ts[0]));
7124 }
7125
7126 void MEDFileMeshMultiTS::setOneTimeStep(MEDFileMesh *mesh1TimeStep)
7127 {
7128   if(!mesh1TimeStep)
7129     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::setOneTimeStep : input pointer should be different from 0 !");
7130   _mesh_one_ts.resize(1);
7131   mesh1TimeStep->incrRef();
7132   //MCAuto<MEDFileMesh> toto=mesh1TimeStep;
7133   _mesh_one_ts[0]=mesh1TimeStep;
7134 }
7135
7136 MEDFileJoints * MEDFileMeshMultiTS::getJoints() const
7137 {
7138   if ( MEDFileMesh* m = getOneTimeStep() )
7139     return m->getJoints();
7140   return 0;
7141 }
7142
7143 /*!
7144  * \brief Set Joints that are common to all time-stamps
7145  */
7146 void MEDFileMeshMultiTS::setJoints( MEDFileJoints* joints )
7147 {
7148   for(std::vector< MCAuto<MEDFileMesh> >::iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
7149     {
7150       (*it)->setJoints( joints );
7151     }
7152 }
7153
7154 bool MEDFileMeshMultiTS::presenceOfStructureElements() const
7155 {
7156   for(std::vector< MCAuto<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
7157     if((*it).isNotNull())
7158       if((*it)->presenceOfStructureElements())
7159         return true;
7160   return false;
7161 }
7162
7163 void MEDFileMeshMultiTS::killStructureElements()
7164 {
7165   for(std::vector< MCAuto<MEDFileMesh> >::iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
7166     if((*it).isNotNull())
7167       (*it)->killStructureElements();
7168 }
7169
7170 void MEDFileMeshMultiTS::writeLL(med_idt fid) const
7171 {
7172   MEDFileJoints *joints(getJoints());
7173   bool jointsWritten(false);
7174
7175   for(std::vector< MCAuto<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
7176     {
7177       if ( jointsWritten )
7178         const_cast<MEDFileMesh&>(**it).setJoints( 0 );
7179       else
7180         jointsWritten = true;
7181
7182       (*it)->copyOptionsFrom(*this);
7183       (*it)->writeLL(fid);
7184     }
7185
7186   (const_cast<MEDFileMeshMultiTS*>(this))->setJoints( joints ); // restore joints
7187 }
7188
7189 void MEDFileMeshMultiTS::loadFromFile(med_idt fid, const std::string& mName)
7190 {
7191   MEDFileJoints *joints(0);
7192   if ( !_mesh_one_ts.empty() && getOneTimeStep() )
7193     {
7194       // joints of mName already read, pass them to MEDFileMesh::New() to prevent repeated reading
7195       joints = getOneTimeStep()->getJoints();
7196     }
7197   _mesh_one_ts.clear();  //for the moment to be improved
7198   _mesh_one_ts.push_back( MEDFileMesh::New(fid,mName,-1,-1,0, joints ));
7199 }
7200
7201 MEDFileMeshMultiTS::MEDFileMeshMultiTS()
7202 {
7203 }
7204
7205 MEDFileMeshMultiTS::MEDFileMeshMultiTS(med_idt fid)
7206 try
7207 {
7208   std::vector<std::string> ms(MEDLoaderNS::getMeshNamesFid(fid));
7209     if(ms.empty())
7210       {
7211         std::ostringstream oss; oss << "MEDFileMeshMultiTS : no meshes in file \"" << FileNameFromFID(fid) << "\" !";
7212         throw INTERP_KERNEL::Exception(oss.str().c_str());
7213       }
7214     int dt,it;
7215     MEDCoupling::MEDCouplingMeshType meshType;
7216     std::string dummy2;
7217     MEDCoupling::MEDCouplingAxisType dummy3;
7218     MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dummy3,dt,it,dummy2);
7219     loadFromFile(fid,ms.front());
7220 }
7221 catch(INTERP_KERNEL::Exception& e)
7222 {
7223     throw e;
7224 }
7225
7226 MEDFileMeshMultiTS::MEDFileMeshMultiTS(med_idt fid, const std::string& mName)
7227 try
7228 {
7229     loadFromFile(fid,mName);
7230 }
7231 catch(INTERP_KERNEL::Exception& e)
7232 {
7233     throw e;
7234 }
7235
7236 MEDFileMeshes *MEDFileMeshes::New()
7237 {
7238   return new MEDFileMeshes;
7239 }
7240
7241 MEDFileMeshes *MEDFileMeshes::New(med_idt fid)
7242 {
7243   return new MEDFileMeshes(fid);
7244 }
7245
7246 MEDFileMeshes *MEDFileMeshes::New(const std::string& fileName)
7247 {
7248   MEDFileUtilities::AutoFid fid(OpenMEDFileForRead(fileName));
7249   return New(fid);
7250 }
7251
7252 void MEDFileMeshes::writeLL(med_idt fid) const
7253 {
7254   checkConsistencyLight();
7255   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++)
7256     {
7257       (*it)->copyOptionsFrom(*this);
7258       (*it)->writeLL(fid);
7259     }
7260 }
7261
7262 //  MEDFileMeshes::writ checkConsistencyLight();
7263
7264 int MEDFileMeshes::getNumberOfMeshes() const
7265 {
7266   return _meshes.size();
7267 }
7268
7269 MEDFileMeshesIterator *MEDFileMeshes::iterator()
7270 {
7271   return new MEDFileMeshesIterator(this);
7272 }
7273
7274 /** Return a borrowed reference (caller is not responsible) */
7275 MEDFileMesh *MEDFileMeshes::getMeshAtPos(int i) const
7276 {
7277   if(i<0 || i>=(int)_meshes.size())
7278     {
7279       std::ostringstream oss; oss << "MEDFileMeshes::getMeshAtPos : invalid mesh id given in parameter ! Should be in [0;" << _meshes.size() << ") !";
7280       throw INTERP_KERNEL::Exception(oss.str().c_str());
7281     }
7282   return _meshes[i]->getOneTimeStep();
7283 }
7284
7285 /** Return a borrowed reference (caller is not responsible) */
7286 MEDFileMesh *MEDFileMeshes::getMeshWithName(const std::string& mname) const
7287 {
7288   std::vector<std::string> ms=getMeshesNames();
7289   std::vector<std::string>::iterator it=std::find(ms.begin(),ms.end(),mname);
7290   if(it==ms.end())
7291     {
7292       std::ostringstream oss; oss << "MEDFileMeshes::getMeshWithName : Mesh  \"" << mname << "\" does not exist in this ! Existing are : ";
7293       std::copy(ms.begin(),ms.end(),std::ostream_iterator<std::string>(oss," "));
7294       throw INTERP_KERNEL::Exception(oss.str().c_str());
7295     }
7296   return getMeshAtPos((int)std::distance(ms.begin(),it));
7297 }
7298
7299 std::vector<std::string> MEDFileMeshes::getMeshesNames() const
7300 {
7301   std::vector<std::string> ret(_meshes.size());
7302   int i=0;
7303   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
7304     {
7305       const MEDFileMeshMultiTS *f=(*it);
7306       if(f)
7307         {
7308           ret[i]=f->getName();
7309         }
7310       else
7311         {
7312           std::ostringstream oss; oss << "MEDFileMeshes::getMeshesNames : At rank #" << i << " mesh is not defined !";
7313           throw INTERP_KERNEL::Exception(oss.str().c_str());
7314         }
7315     }
7316   return ret;
7317 }
7318
7319 bool MEDFileMeshes::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab)
7320 {
7321   bool ret=false;
7322   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::iterator it=_meshes.begin();it!=_meshes.end();it++)
7323     {
7324       MEDFileMeshMultiTS *cur(*it);
7325       if(cur)
7326         ret=cur->changeNames(modifTab) || ret;
7327     }
7328   return ret;
7329 }
7330
7331 void MEDFileMeshes::cartesianizeMe()
7332 {
7333   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::iterator it=_meshes.begin();it!=_meshes.end();it++)
7334     {
7335       MEDFileMeshMultiTS *cur(*it);
7336       if(cur)
7337         cur->cartesianizeMe();
7338     }
7339 }
7340
7341 void MEDFileMeshes::resize(int newSize)
7342 {
7343   _meshes.resize(newSize);
7344 }
7345
7346 void MEDFileMeshes::pushMesh(MEDFileMesh *mesh)
7347 {
7348   if(!mesh)
7349     throw INTERP_KERNEL::Exception("MEDFileMeshes::pushMesh : invalid input pointer ! should be different from 0 !");
7350   MEDFileMeshMultiTS *elt=MEDFileMeshMultiTS::New();
7351   elt->setOneTimeStep(mesh);
7352   _meshes.push_back(elt);
7353 }
7354
7355 void MEDFileMeshes::setMeshAtPos(int i, MEDFileMesh *mesh)
7356 {
7357   if(!mesh)
7358     throw INTERP_KERNEL::Exception("MEDFileMeshes::setMeshAtPos : invalid input pointer ! should be different from 0 !");
7359   if(i>=(int)_meshes.size())
7360     _meshes.resize(i+1);
7361   MEDFileMeshMultiTS *elt=MEDFileMeshMultiTS::New();
7362   elt->setOneTimeStep(mesh);
7363   _meshes[i]=elt;
7364 }
7365
7366 void MEDFileMeshes::destroyMeshAtPos(int i)
7367 {
7368   if(i<0 || i>=(int)_meshes.size())
7369     {
7370       std::ostringstream oss; oss << "MEDFileMeshes::destroyMeshAtPos : Invalid given id in input (" << i << ") should be in [0," << _meshes.size() << ") !";
7371       throw INTERP_KERNEL::Exception(oss.str().c_str());
7372     }
7373   _meshes.erase(_meshes.begin()+i);
7374 }
7375
7376 void MEDFileMeshes::loadFromFile(med_idt fid)
7377 {
7378   std::vector<std::string> ms(MEDLoaderNS::getMeshNamesFid(fid));
7379   int i=0;
7380   _meshes.resize(ms.size());
7381   for(std::vector<std::string>::const_iterator it=ms.begin();it!=ms.end();it++,i++)
7382     _meshes[i]=MEDFileMeshMultiTS::New(fid,(*it));
7383 }
7384
7385 MEDFileMeshes::MEDFileMeshes()
7386 {
7387 }
7388
7389 MEDFileMeshes::MEDFileMeshes(med_idt fid)
7390 try
7391 {
7392     loadFromFile(fid);
7393 }
7394 catch(INTERP_KERNEL::Exception& /*e*/)
7395 {
7396 }
7397
7398 MEDFileMeshes *MEDFileMeshes::deepCopy() const
7399 {
7400   std::vector< MCAuto<MEDFileMeshMultiTS> > meshes(_meshes.size());
7401   std::size_t i=0;
7402   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
7403     if((const MEDFileMeshMultiTS *)*it)
7404       meshes[i]=(*it)->deepCopy();
7405   MCAuto<MEDFileMeshes> ret(MEDFileMeshes::New());
7406   ret->_meshes=meshes;
7407   return ret.retn();
7408 }
7409
7410 std::size_t MEDFileMeshes::getHeapMemorySizeWithoutChildren() const
7411 {
7412   return _meshes.capacity()*(sizeof(MCAuto<MEDFileMeshMultiTS>));
7413 }
7414
7415 std::vector<const BigMemoryObject *> MEDFileMeshes::getDirectChildrenWithNull() const
7416 {
7417   std::vector<const BigMemoryObject *> ret;
7418   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++)
7419     ret.push_back((const MEDFileMeshMultiTS *)*it);
7420   return ret;
7421 }
7422
7423 std::string MEDFileMeshes::simpleRepr() const
7424 {
7425   std::ostringstream oss;
7426   oss << "(*****************)\n(* MEDFileMeshes *)\n(*****************)\n\n";
7427   simpleReprWithoutHeader(oss);
7428   return oss.str();
7429 }
7430
7431 void MEDFileMeshes::simpleReprWithoutHeader(std::ostream& oss) const
7432 {
7433   int nbOfMeshes=getNumberOfMeshes();
7434   oss << "There are " << nbOfMeshes << " meshes with the following names : \n";
7435   std::vector<std::string> mns=getMeshesNames();
7436   for(int i=0;i<nbOfMeshes;i++)
7437     oss << "  - #" << i << " \"" << mns[i] << "\"\n";
7438 }
7439
7440 void MEDFileMeshes::checkConsistencyLight() const
7441 {
7442   static const char MSG[]="MEDFileMeshes::checkConsistencyLight : mesh at rank ";
7443   int i=0;
7444   std::set<std::string> s;
7445   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
7446     {
7447       const MEDFileMeshMultiTS *elt=(*it);
7448       if(!elt)
7449         {
7450           std::ostringstream oss; oss << MSG << i << "/" << _meshes.size() << " is empty !";
7451           throw INTERP_KERNEL::Exception(oss.str().c_str());
7452         }
7453       std::size_t sz=s.size();
7454       s.insert(std::string((*it)->getName()));
7455       if(s.size()==sz)
7456         {
7457           std::ostringstream oss; oss << MSG << i << " has a name (\"" << (*it)->getName() << "\") already used by an another mesh in list !";
7458           throw INTERP_KERNEL::Exception(oss.str().c_str());
7459         }
7460     }
7461 }
7462
7463 bool MEDFileMeshes::presenceOfStructureElements() const
7464 {
7465   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++)
7466     if((*it).isNotNull())
7467       if((*it)->presenceOfStructureElements())
7468         return true;
7469   return false;
7470 }
7471
7472 void MEDFileMeshes::killStructureElements()
7473 {
7474   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::iterator it=_meshes.begin();it!=_meshes.end();it++)
7475     if((*it).isNotNull())
7476       (*it)->killStructureElements();
7477 }
7478
7479 MEDFileMeshesIterator::MEDFileMeshesIterator(MEDFileMeshes *ms):_ms(ms),_iter_id(0),_nb_iter(0)
7480 {
7481   if(ms)
7482     {
7483       ms->incrRef();
7484       _nb_iter=ms->getNumberOfMeshes();
7485     }
7486 }
7487
7488 MEDFileMeshesIterator::~MEDFileMeshesIterator()
7489 {
7490 }
7491
7492 MEDFileMesh *MEDFileMeshesIterator::nextt()
7493 {
7494   if(_iter_id<_nb_iter)
7495     {
7496       MEDFileMeshes *ms(_ms);
7497       if(ms)
7498         return ms->getMeshAtPos(_iter_id++);
7499       else
7500         return 0;
7501     }
7502   else
7503     return 0;
7504 }
7505
7506 INTERP_KERNEL::NormalizedCellType MEDFileMesh::ConvertFromMEDFileGeoType(med_geometry_type geoType)
7507 {
7508   med_geometry_type *pos(std::find(typmai,typmai+MED_N_CELL_FIXED_GEO,geoType));
7509   if(pos==typmai+MED_N_CELL_FIXED_GEO)
7510     {
7511       if(geoType==MED_NO_GEOTYPE)
7512         return INTERP_KERNEL::NORM_ERROR;
7513       std::ostringstream oss; oss << "MEDFileMesh::ConvertFromMEDFileGeoType : no entry with " << geoType << " !"; 
7514       throw INTERP_KERNEL::Exception(oss.str());
7515     }
7516   return typmai2[std::distance(typmai,pos)];
7517 }
7518
7519 TypeOfField MEDFileMesh::ConvertFromMEDFileEntity(med_entity_type etype)
7520 {
7521   switch(etype)
7522     {
7523     case MED_NODE:
7524       return ON_NODES;
7525     case MED_CELL:
7526       return ON_CELLS;
7527     default:
7528       {
7529         std::ostringstream oss; oss << "EDFileMesh::ConvertFromMEDFileEntity : not recognized entity " << etype << " !";
7530         throw INTERP_KERNEL::Exception(oss.str());
7531       }
7532     }
7533 }
7534
7535