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