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