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