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