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