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