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