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