Salome HOME
Merge branch 'master' of ssh://git.salome-platform.org/tools/medcoupling
[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 refered 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 dependant 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 *)_rev_num_coords);
2361   ret.push_back((const DataArrayAsciiChar *)_name_coords);
2362   ret.push_back((const PartDefinition *)_part_coords);
2363   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2364     ret.push_back((const MEDFileUMeshSplitL1*) *it);
2365   for(std::vector< MCAuto<MEDFileEltStruct4Mesh> >::const_iterator it=_elt_str.begin();it!=_elt_str.end();it++)
2366     ret.push_back((const MEDFileEltStruct4Mesh *)*it);
2367   return ret;
2368 }
2369
2370 MEDFileUMesh *MEDFileUMesh::shallowCpy() const
2371 {
2372   MCAuto<MEDFileUMesh> ret(new MEDFileUMesh(*this));
2373   return ret.retn();
2374 }
2375
2376 MEDFileMesh *MEDFileUMesh::createNewEmpty() const
2377 {
2378   return new MEDFileUMesh;
2379 }
2380
2381 MEDFileUMesh *MEDFileUMesh::deepCopy() const
2382 {
2383   MCAuto<MEDFileUMesh> ret(new MEDFileUMesh(*this));
2384   ret->deepCpyEquivalences(*this);
2385   if((const DataArrayDouble*)_coords)
2386     ret->_coords=_coords->deepCopy();
2387   if((const DataArrayInt*)_fam_coords)
2388     ret->_fam_coords=_fam_coords->deepCopy();
2389   if((const DataArrayInt*)_num_coords)
2390     ret->_num_coords=_num_coords->deepCopy();
2391   if((const DataArrayInt*)_rev_num_coords)
2392     ret->_rev_num_coords=_rev_num_coords->deepCopy();
2393   if((const DataArrayAsciiChar*)_name_coords)
2394     ret->_name_coords=_name_coords->deepCopy();
2395   std::size_t i=0;
2396   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,i++)
2397     {
2398       if((const MEDFileUMeshSplitL1 *)(*it))
2399         ret->_ms[i]=(*it)->deepCopy(ret->_coords);
2400     }
2401   if((const PartDefinition*)_part_coords)
2402     ret->_part_coords=_part_coords->deepCopy();
2403   return ret.retn();
2404 }
2405
2406 /*!
2407  * Checks if \a this and another mesh are equal.
2408  *  \param [in] other - the mesh to compare with.
2409  *  \param [in] eps - a precision used to compare real values.
2410  *  \param [in,out] what - the string returning description of unequal data.
2411  *  \return bool - \c true if the meshes are equal, \c false, else.
2412  */
2413 bool MEDFileUMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
2414 {
2415   if(!MEDFileMesh::isEqual(other,eps,what))
2416     return false;
2417   const MEDFileUMesh *otherC=dynamic_cast<const MEDFileUMesh *>(other);
2418   if(!otherC)
2419     {
2420       what="Mesh types differ ! This is unstructured and other is NOT !";
2421       return false;
2422     }
2423   clearNonDiscrAttributes();
2424   otherC->clearNonDiscrAttributes();
2425   const DataArrayDouble *coo1=_coords;
2426   const DataArrayDouble *coo2=otherC->_coords;
2427   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
2428     {
2429       what="Mismatch of coordinates ! One is defined and not other !";
2430       return false;
2431     }
2432   if(coo1)
2433     {
2434       bool ret=coo1->isEqual(*coo2,eps);
2435       if(!ret)
2436         {
2437           what="Coords differ !";
2438           return false;
2439         }
2440     }
2441   const DataArrayInt *famc1=_fam_coords;
2442   const DataArrayInt *famc2=otherC->_fam_coords;
2443   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
2444     {
2445       what="Mismatch of families arr on nodes ! One is defined and not other !";
2446       return false;
2447     }
2448   if(famc1)
2449     {
2450       bool ret=famc1->isEqual(*famc2);
2451       if(!ret)
2452         {
2453           what="Families arr on node differ !";
2454           return false;
2455         }
2456     }
2457   const DataArrayInt *numc1=_num_coords;
2458   const DataArrayInt *numc2=otherC->_num_coords;
2459   if((numc1==0 && numc2!=0) || (numc1!=0 && numc2==0))
2460     {
2461       what="Mismatch of numbering arr on nodes ! One is defined and not other !";
2462       return false;
2463     }
2464   if(numc1)
2465     {
2466       bool ret=numc1->isEqual(*numc2);
2467       if(!ret)
2468         {
2469           what="Numbering arr on node differ !";
2470           return false;
2471         }
2472     }
2473   const DataArrayAsciiChar *namec1=_name_coords;
2474   const DataArrayAsciiChar *namec2=otherC->_name_coords;
2475   if((namec1==0 && namec2!=0) || (namec1!=0 && namec2==0))
2476     {
2477       what="Mismatch of naming arr on nodes ! One is defined and not other !";
2478       return false;
2479     }
2480   if(namec1)
2481     {
2482       bool ret=namec1->isEqual(*namec2);
2483       if(!ret)
2484         {
2485           what="Names arr on node differ !";
2486           return false;
2487         }
2488     }
2489   if(_ms.size()!=otherC->_ms.size())
2490     {
2491       what="Number of levels differs !";
2492       return false;
2493     }
2494   std::size_t sz=_ms.size();
2495   for(std::size_t i=0;i<sz;i++)
2496     {
2497       const MEDFileUMeshSplitL1 *s1=_ms[i];
2498       const MEDFileUMeshSplitL1 *s2=otherC->_ms[i];
2499       if((s1==0 && s2!=0) || (s1!=0 && s2==0))
2500         {
2501           what="Mismatch of presence of sub levels !";
2502           return false;
2503         }
2504       if(s1)
2505         {
2506           bool ret=s1->isEqual(s2,eps,what);
2507           if(!ret)
2508             return false;
2509         }
2510     }
2511   const PartDefinition *pd0(_part_coords),*pd1(otherC->_part_coords);
2512   if(!pd0 && !pd1)
2513     return true;
2514   if((!pd0 && pd1) || (pd0 && !pd1))
2515     {
2516       what=std::string("node part def is defined only for one among this or other !");
2517       return false;
2518     }
2519   return pd0->isEqual(pd1,what);
2520 }
2521
2522 /*!
2523  * Check that the current object MEDFileUMesh is consistent. This does not check the optional renumbering of
2524  * nodes and cells. This last item is important for SMESH, see checkSMESHConsistency().
2525  * \throw if any internal part (i.e. mesh sub-levels and single geometric-type meshes) are inconsistent
2526  * \throw if internal family array is inconsistent
2527  * \sa checkSMESHConsistency()
2528  */
2529 void MEDFileUMesh::checkConsistency() const
2530 {
2531   if(!_coords || !_coords->isAllocated())
2532     {
2533       if(!_ms.size())
2534         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkConsistency(): coords are null but some mesh parts are present!");
2535       if (!_fam_coords)
2536         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkConsistency(): coords are null but not the internal node family array!");
2537       if (!_num_coords || !_rev_num_coords)
2538         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkConsistency(): coords are null but not the internal node numbering array!");
2539     }
2540   else
2541     {
2542       int nbCoo = _coords->getNumberOfTuples();
2543       if (_fam_coords)
2544         _fam_coords->checkNbOfTuplesAndComp(nbCoo,1,"MEDFileUMesh::checkConsistency(): inconsistent internal node family array!");
2545       if (_num_coords)
2546         {
2547           _num_coords->checkNbOfTuplesAndComp(nbCoo,1,"MEDFileUMesh::checkConsistency(): inconsistent internal node numbering array!");
2548           int pos;
2549           int maxValue=_num_coords->getMaxValue(pos);
2550           if (!_rev_num_coords || _rev_num_coords->getNumberOfTuples() != (maxValue+1))
2551             throw INTERP_KERNEL::Exception("MEDFileUMesh::checkConsistency(): inconsistent internal revert node numbering array!");
2552         }
2553       if ((_num_coords && !_rev_num_coords) || (!_num_coords && _rev_num_coords))
2554         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkConsistency(): inconsistent internal numbering arrays (one is null)!");
2555       if (_num_coords && !_num_coords->hasUniqueValues())
2556         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkConsistency(): inconsistent internal node numbering array: duplicates found!");
2557       if (_name_coords)
2558         _name_coords->checkNbOfTuplesAndComp(nbCoo,MED_SNAME_SIZE,"MEDFileUMesh::checkConsistency(): inconsistent internal coord name array!");
2559       // Now sub part check:
2560       for (std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();
2561           it != _ms.end(); it++)
2562         (*it)->checkConsistency();
2563     }
2564 }
2565
2566 /**
2567  * Same as checkConsistency() but also checks that optional entities (edges, faces, volumes) numbers are
2568  * consistent, i.e. the numbering is either set to null for all sub-levels (thus letting SMESH numbers the
2569  * entities as it likes), or non overlapping between all sub-levels.
2570  * \throw if the condition above is not respected
2571  */
2572 void MEDFileUMesh::checkSMESHConsistency() const
2573 {
2574   checkConsistency();
2575   // For all sub-levels, numbering is either always null or with void intersection:
2576   if (_ms.size())
2577     {
2578       std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();
2579       std::vector< const DataArrayInt * > v;
2580       bool voidOrNot = ((*it)->_num == 0);
2581       for (it++; it != _ms.end(); it++)
2582         if( ((*it)->_num == 0) != voidOrNot )
2583           throw INTERP_KERNEL::Exception("MEDFileUMesh::checkConsistency(): inconsistent numbering between mesh sub-levels!");
2584         else if (!voidOrNot)
2585           v.push_back((*it)->_num);
2586       if (!voidOrNot)
2587         {
2588           // don't forget the 1st one:
2589           v.push_back(_ms[0]->_num);
2590           MCAuto<DataArrayInt> inter = DataArrayInt::BuildIntersection(v);
2591           if (inter->getNumberOfTuples())
2592             throw INTERP_KERNEL::Exception("MEDFileUMesh::checkConsistency(): overlapping entity numbering between mesh sub-levels!");
2593         }
2594     }
2595 }
2596
2597 /**
2598  * Reset optional node and cell numbering for all sub levels in this. This particularly useful to make
2599  * sure SMESH will handle the mesh correctly, as it tries to use those numbers if given.
2600  */
2601 void MEDFileUMesh::clearNodeAndCellNumbers()
2602 {
2603   _num_coords = 0;
2604   _rev_num_coords = 0;
2605   for (std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();
2606       it != _ms.end(); it++)
2607     {
2608       (*it)->_num = 0;
2609       (*it)->_rev_num = 0;
2610     }
2611 }
2612
2613 /*!
2614  * Clears redundant attributes of incorporated data arrays.
2615  */
2616 void MEDFileUMesh::clearNonDiscrAttributes() const
2617 {
2618   MEDFileMesh::clearNonDiscrAttributes();
2619   const DataArrayDouble *coo1=_coords;
2620   if(coo1)
2621     (const_cast<DataArrayDouble *>(coo1))->setName("");//This parameter is not discriminant for comparison
2622   const DataArrayInt *famc1=_fam_coords;
2623   if(famc1)
2624     (const_cast<DataArrayInt *>(famc1))->setName("");//This parameter is not discriminant for comparison
2625   const DataArrayInt *numc1=_num_coords;
2626   if(numc1)
2627     (const_cast<DataArrayInt *>(numc1))->setName("");//This parameter is not discriminant for comparison
2628   const DataArrayAsciiChar *namc1=_name_coords;
2629   if(namc1)
2630     (const_cast<DataArrayAsciiChar *>(namc1))->setName("");//This parameter is not discriminant for comparison
2631   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2632     {
2633       const MEDFileUMeshSplitL1 *tmp=(*it);
2634       if(tmp)
2635         tmp->clearNonDiscrAttributes();
2636     }
2637 }
2638
2639 void MEDFileUMesh::setName(const std::string& name)
2640 {
2641   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
2642     if((MEDFileUMeshSplitL1 *)(*it)!=0)
2643       (*it)->setName(name);
2644   MEDFileMesh::setName(name);
2645 }
2646
2647 MEDFileUMesh::MEDFileUMesh()
2648 {
2649 }
2650
2651 MEDFileUMesh::MEDFileUMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
2652 try
2653 {
2654     loadLLWithAdditionalItems(fid,mName,dt,it,mrs);
2655 }
2656 catch(INTERP_KERNEL::Exception& e)
2657 {
2658     throw e;
2659 }
2660
2661 /*!
2662  * This method loads only a part of specified cells (given by range of cell ID per geometric type)
2663  * See MEDFileUMesh::LoadPartOf for detailed description.
2664  *
2665  * \sa loadLL
2666  */
2667 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)
2668 {
2669   MEDFileUMeshL2 loaderl2;
2670   MEDCoupling::MEDCouplingMeshType meshType;
2671   int dummy0,dummy1;
2672   std::string dummy2;
2673   MEDCoupling::MEDCouplingAxisType dummy3;
2674   INTERP_KERNEL::AutoCppPtr<MeshOrStructMeshCls> mid(MEDFileUMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy3,dummy0,dummy1,dummy2));
2675   if(meshType!=UNSTRUCTURED)
2676     {
2677       std::ostringstream oss; oss << "loadPartUMeshFromFile : Trying to load as unstructured an existing mesh with name '" << mName << "' !";
2678       throw INTERP_KERNEL::Exception(oss.str().c_str());
2679     }
2680   loaderl2.loadPart(fid,mid,mName,types,slicPerTyp,dt,it,mrs);
2681   dispatchLoadedPart(fid,loaderl2,mName,mrs);
2682 }
2683
2684 /*!
2685  * \brief Write joints in a file
2686  */
2687 void MEDFileMesh::writeJoints(med_idt fid) const
2688 {
2689   if ( _joints.isNotNull() )
2690     _joints->writeLL(fid);
2691 }
2692
2693 /*!
2694  * \brief Load joints in a file or use provided ones
2695  */
2696 //================================================================================
2697 /*!
2698  * \brief Load joints in a file or use provided ones
2699  *  \param [in] fid - MED file descriptor
2700  *  \param [in] toUseInstedOfReading - optional joints to use instead of reading,
2701  *          Usually this joints are those just read by another iteration
2702  *          of namesake mesh, when this method is called by MEDFileMeshMultiTS::New()
2703  */
2704 //================================================================================
2705
2706 void MEDFileMesh::loadJointsFromFile(med_idt fid, MEDFileJoints* toUseInstedOfReading)
2707 {
2708   if ( toUseInstedOfReading )
2709     setJoints( toUseInstedOfReading );
2710   else
2711     _joints = MEDFileJoints::New( fid, _name );
2712 }
2713
2714 void MEDFileMesh::loadEquivalences(med_idt fid)
2715 {
2716   int nbOfEq(MEDFileEquivalences::PresenceOfEquivalences(fid,_name));
2717   if(nbOfEq>0)
2718     _equiv=MEDFileEquivalences::Load(fid,nbOfEq,this);
2719 }
2720
2721 void MEDFileMesh::deepCpyEquivalences(const MEDFileMesh& other)
2722 {
2723   const MEDFileEquivalences *equiv(other._equiv);
2724   if(equiv)
2725     _equiv=equiv->deepCopy(this);
2726 }
2727
2728 bool MEDFileMesh::areEquivalencesEqual(const MEDFileMesh *other, std::string& what) const
2729 {
2730   const MEDFileEquivalences *thisEq(_equiv),*otherEq(other->_equiv);
2731   if(!thisEq && !otherEq)
2732     return true;
2733   if(thisEq && otherEq)
2734     return thisEq->isEqual(otherEq,what);
2735   else
2736     {
2737       what+="Equivalence differs : defined in this and not in other (or reversely) !";
2738       return false;
2739     }
2740 }
2741
2742 void MEDFileMesh::getEquivalencesRepr(std::ostream& oss) const
2743 {
2744   const MEDFileEquivalences *equiv(_equiv);
2745   if(!equiv)
2746     return ;
2747   oss << "(******************************)\n(* EQUIVALENCES OF THE MESH : *)\n(******************************)\n";
2748   _equiv->getRepr(oss);
2749 }
2750
2751 void MEDFileMesh::checkCartesian() const
2752 {
2753   if(getAxisType()!=AX_CART)
2754     {
2755       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()) << ").";
2756       oss << std::endl << "To perform operation you have two possiblities :" << std::endl;
2757       oss << " - call setAxisType(AX_CART)" << std::endl;
2758       oss << " - call cartesianize()";
2759       throw INTERP_KERNEL::Exception(oss.str().c_str());
2760     }
2761 }
2762
2763 /*!
2764  * \brief Return number of joints, which is equal to number of adjacent mesh domains
2765  */
2766 int MEDFileMesh::getNumberOfJoints() const
2767 {
2768   return ( (const MEDFileJoints *) _joints ) ? _joints->getNumberOfJoints() : 0;
2769 }
2770
2771 /*!
2772  * \brief Return joints with all adjacent mesh domains
2773  */
2774 MEDFileJoints * MEDFileMesh::getJoints() const
2775 {
2776   return const_cast<MEDFileJoints*>(& (*_joints));
2777 }
2778
2779 void MEDFileMesh::setJoints( MEDFileJoints* joints )
2780 {
2781   if ( joints != _joints )
2782     {
2783       _joints = joints;
2784       if ( joints )
2785         joints->incrRef();
2786     }
2787 }
2788
2789 /*!
2790  * This method loads \b all \b the \b mesh \a mName in the file with \a fid descriptor.
2791  *
2792  * \sa loadPartUMeshFromFile
2793  */
2794 void MEDFileUMesh::loadLL(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
2795 {
2796   MEDFileUMeshL2 loaderl2;
2797   MEDCoupling::MEDCouplingMeshType meshType;
2798   int dummy0,dummy1;
2799   std::string dummy2;
2800   MEDCoupling::MEDCouplingAxisType axType;
2801   INTERP_KERNEL::AutoCppPtr<MeshOrStructMeshCls> mid(MEDFileUMeshL2::GetMeshIdFromName(fid,mName,meshType,axType,dummy0,dummy1,dummy2));
2802   setAxisType(axType);
2803   if(meshType!=UNSTRUCTURED)
2804     {
2805       std::ostringstream oss; oss << "Trying to load as unstructured an existing mesh with name '" << mName << "' !";
2806       throw INTERP_KERNEL::Exception(oss.str().c_str());
2807     }
2808   loaderl2.loadAll(fid,mid,mName,dt,it,mrs);
2809   dispatchLoadedPart(fid,loaderl2,mName,mrs);
2810   // Structure element part...
2811   int nModels(-1);
2812   {
2813     med_bool chgt=MED_FALSE,trsf=MED_FALSE;
2814     nModels=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_STRUCT_ELEMENT,MED_GEO_ALL,MED_CONNECTIVITY,MED_NODAL,&chgt,&trsf);
2815   }
2816   if(nModels<=0)
2817     return ;
2818   _elt_str.resize(nModels);
2819   for(int i=0;i<nModels;i++)
2820     _elt_str[i]=MEDFileEltStruct4Mesh::New(fid,mName,dt,it,i,mrs);
2821 }
2822
2823 void MEDFileUMesh::dispatchLoadedPart(med_idt fid, const MEDFileUMeshL2& loaderl2, const std::string& mName, MEDFileMeshReadSelector *mrs)
2824 {
2825   int lev=loaderl2.getNumberOfLevels();
2826   _ms.resize(lev);
2827   for(int i=0;i<lev;i++)
2828     {
2829       if(!loaderl2.emptyLev(i))
2830         _ms[i]=new MEDFileUMeshSplitL1(loaderl2,mName,i);
2831       else
2832         _ms[i]=0;
2833     }
2834   MEDFileMeshL2::ReadFamiliesAndGrps(fid,mName,_families,_groups,mrs);
2835   //
2836   setName(loaderl2.getName());
2837   setDescription(loaderl2.getDescription());
2838   setUnivName(loaderl2.getUnivName());
2839   setIteration(loaderl2.getIteration());
2840   setOrder(loaderl2.getOrder());
2841   setTimeValue(loaderl2.getTime());
2842   setTimeUnit(loaderl2.getTimeUnit());
2843   _coords=loaderl2.getCoords();
2844   if(!mrs || mrs->isNodeFamilyFieldReading())
2845     _fam_coords=loaderl2.getCoordsFamily();
2846   if(!mrs || mrs->isNodeNumFieldReading())
2847     _num_coords=loaderl2.getCoordsNum();
2848   if(!mrs || mrs->isNodeNameFieldReading())
2849     _name_coords=loaderl2.getCoordsName();
2850   _part_coords=loaderl2.getPartDefOfCoo();
2851   computeRevNum();
2852 }
2853
2854 MEDFileUMesh::~MEDFileUMesh()
2855 {
2856 }
2857
2858 void MEDFileUMesh::writeMeshLL(med_idt fid) const
2859 {
2860   const DataArrayDouble *coo=_coords;
2861   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
2862   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
2863   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
2864   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
2865   int spaceDim=coo?coo->getNumberOfComponents():0;
2866   int mdim(0);
2867   if(!_ms.empty())
2868     mdim=getMeshDimension();
2869   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
2870   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
2871   for(int i=0;i<spaceDim;i++)
2872     {
2873       std::string info=coo->getInfoOnComponent(i);
2874       std::string c,u;
2875       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
2876       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
2877       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
2878     }
2879   MEDFILESAFECALLERWR0(MEDmeshCr,(fid,maa,spaceDim,mdim,MED_UNSTRUCTURED_MESH,desc,"",MED_SORT_DTIT,MEDFileMeshL2::TraduceAxisTypeRev(getAxisType()),comp,unit));
2880   if(_univ_wr_status)
2881     MEDFILESAFECALLERWR0(MEDmeshUniversalNameWr,(fid,maa));
2882   std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE));
2883   MEDFileUMeshL2::WriteCoords(fid,meshName,_iteration,_order,_time,_coords,_fam_coords,_num_coords,_name_coords);
2884   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2885     if((const MEDFileUMeshSplitL1 *)(*it)!=0)
2886       (*it)->write(fid,meshName,mdim);
2887   MEDFileUMeshL2::WriteFamiliesAndGrps(fid,meshName,_families,_groups,_too_long_str);
2888 }
2889
2890 /*!
2891  * Returns relative dimensions of mesh entities (excluding nodes) present in \a this mesh.
2892  *  \return std::vector<int> - a sequence of the relative dimensions.
2893  */
2894 std::vector<int> MEDFileUMesh::getNonEmptyLevels() const
2895 {
2896   std::vector<int> ret;
2897   int lev=0;
2898   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
2899     if((const MEDFileUMeshSplitL1 *)(*it)!=0)
2900       if(!(*it)->empty())
2901         ret.push_back(lev);
2902   return ret;
2903 }
2904
2905 /*!
2906  * Returns relative dimensions of mesh entities (including nodes) present in \a this mesh.
2907  *  \return std::vector<int> - a sequence of the relative dimensions.
2908  */
2909 std::vector<int> MEDFileUMesh::getNonEmptyLevelsExt() const
2910 {
2911   std::vector<int> ret0=getNonEmptyLevels();
2912   if((const DataArrayDouble *) _coords)
2913     {
2914       std::vector<int> ret(ret0.size()+1);
2915       ret[0]=1;
2916       std::copy(ret0.begin(),ret0.end(),ret.begin()+1);
2917       return ret;
2918     }
2919   return ret0;
2920 }
2921
2922 std::vector<int> MEDFileUMesh::getFamArrNonEmptyLevelsExt() const
2923 {
2924   std::vector<int> ret;
2925   const DataArrayInt *famCoo(_fam_coords);
2926   if(famCoo)
2927     ret.push_back(1);
2928   int lev=0;
2929   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
2930     {
2931       const MEDFileUMeshSplitL1 *cur(*it);
2932       if(cur)
2933         if(cur->getFamilyField())
2934           ret.push_back(lev);
2935     }
2936   return ret;
2937 }
2938
2939 std::vector<int> MEDFileUMesh::getNumArrNonEmptyLevelsExt() const
2940 {
2941   std::vector<int> ret;
2942   const DataArrayInt *numCoo(_num_coords);
2943   if(numCoo)
2944     ret.push_back(1);
2945   int lev=0;
2946   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
2947     {
2948       const MEDFileUMeshSplitL1 *cur(*it);
2949       if(cur)
2950         if(cur->getNumberField())
2951           ret.push_back(lev);
2952     }
2953   return ret;
2954 }
2955
2956 std::vector<int> MEDFileUMesh::getNameArrNonEmptyLevelsExt() const
2957 {
2958   std::vector<int> ret;
2959   const DataArrayAsciiChar *nameCoo(_name_coords);
2960   if(nameCoo)
2961     ret.push_back(1);
2962   int lev=0;
2963   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
2964     {
2965       const MEDFileUMeshSplitL1 *cur(*it);
2966       if(cur)
2967         if(cur->getNameField())
2968           ret.push_back(lev);
2969     }
2970   return ret;
2971 }
2972
2973 /*!
2974  * Returns all relative mesh levels (**excluding nodes**) where given families are defined.
2975  * To include nodes, call getFamsNonEmptyLevelsExt() method.
2976  *  \param [in] fams - the name of the family of interest.
2977  *  \return std::vector<int> - a sequence of the relative dimensions.
2978  */
2979 std::vector<int> MEDFileUMesh::getFamsNonEmptyLevels(const std::vector<std::string>& fams) const
2980 {
2981   std::vector<int> ret;
2982   std::vector<int> levs(getNonEmptyLevels());
2983   std::vector<int> famIds(getFamiliesIds(fams));
2984   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
2985     if(_ms[-(*it)]->presenceOfOneFams(famIds))
2986       ret.push_back(*it);
2987   return ret;
2988 }
2989
2990 /*!
2991  * Returns all relative mesh levels (including nodes) where given families are defined.
2992  *  \param [in] fams - the names of the families of interest.
2993  *  \return std::vector<int> - a sequence of the relative dimensions.
2994  */
2995 std::vector<int> MEDFileUMesh::getFamsNonEmptyLevelsExt(const std::vector<std::string>& fams) const
2996 {
2997   std::vector<int> ret0(getFamsNonEmptyLevels(fams));
2998   const DataArrayInt *famCoords(_fam_coords);
2999   if(!famCoords)
3000     return ret0;
3001   std::vector<int> famIds(getFamiliesIds(fams));
3002   if(famCoords->presenceOfValue(famIds))
3003     {
3004       std::vector<int> ret(ret0.size()+1);
3005       ret[0]=1;
3006       std::copy(ret0.begin(),ret0.end(),ret.begin()+1);
3007       return ret;
3008     }
3009   else
3010     return ret0;
3011 }
3012
3013 int MEDFileUMesh::getMaxAbsFamilyIdInArrays() const
3014 {
3015   int ret=-std::numeric_limits<int>::max(),tmp=-1;
3016   if((const DataArrayInt *)_fam_coords)
3017     {
3018       int val=_fam_coords->getMaxValue(tmp);
3019       ret=std::max(ret,std::abs(val));
3020     }
3021   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
3022     {
3023       if((const MEDFileUMeshSplitL1 *)(*it))
3024         {
3025           const DataArrayInt *da=(*it)->getFamilyField();
3026           if(da)
3027             {
3028               int val=da->getMaxValue(tmp);
3029               ret=std::max(ret,std::abs(val));
3030             }
3031         }
3032     }
3033   return ret;
3034 }
3035
3036 int MEDFileUMesh::getMaxFamilyIdInArrays() const
3037 {
3038   int ret=-std::numeric_limits<int>::max(),tmp=-1;
3039   if((const DataArrayInt *)_fam_coords)
3040     {
3041       int val=_fam_coords->getMaxValue(tmp);
3042       ret=std::max(ret,val);
3043     }
3044   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
3045     {
3046       if((const MEDFileUMeshSplitL1 *)(*it))
3047         {
3048           const DataArrayInt *da=(*it)->getFamilyField();
3049           if(da)
3050             {
3051               int val=da->getMaxValue(tmp);
3052               ret=std::max(ret,val);
3053             }
3054         }
3055     }
3056   return ret;
3057 }
3058
3059 int MEDFileUMesh::getMinFamilyIdInArrays() const
3060 {
3061   int ret=std::numeric_limits<int>::max(),tmp=-1;
3062   if((const DataArrayInt *)_fam_coords)
3063     {
3064       int val=_fam_coords->getMinValue(tmp);
3065       ret=std::min(ret,val);
3066     }
3067   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
3068     {
3069       if((const MEDFileUMeshSplitL1 *)(*it))
3070         {
3071           const DataArrayInt *da=(*it)->getFamilyField();
3072           if(da)
3073             {
3074               int val=da->getMinValue(tmp);
3075               ret=std::min(ret,val);
3076             }
3077         }
3078     }
3079   return ret;
3080 }
3081
3082 /*!
3083  * Returns the dimension on cells in \a this mesh.
3084  *  \return int - the mesh dimension.
3085  *  \throw If there are no cells in this mesh.
3086  */
3087 int MEDFileUMesh::getMeshDimension() const
3088 {
3089   int lev=0;
3090   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev++)
3091     if((const MEDFileUMeshSplitL1 *)(*it)!=0)
3092       return (*it)->getMeshDimension()+lev;
3093   throw INTERP_KERNEL::Exception("MEDFileUMesh::getMeshDimension : impossible to find a mesh dimension !");
3094 }
3095
3096 /*!
3097  * Returns the space dimension of \a this mesh that is equal to number of components in
3098  * the node coordinates array.
3099  *  \return int - the space dimension of \a this mesh.
3100  *  \throw If the node coordinates array is not available.
3101  */
3102 int MEDFileUMesh::getSpaceDimension() const
3103 {
3104   const DataArrayDouble *coo=_coords;
3105   if(!coo)
3106     throw INTERP_KERNEL::Exception(" MEDFileUMesh::getSpaceDimension : no coords set !");
3107   return coo->getNumberOfComponents();
3108 }
3109
3110 /*!
3111  * Returns a string describing \a this mesh.
3112  *  \return std::string - the mesh information string.
3113  */
3114 std::string MEDFileUMesh::simpleRepr() const
3115 {
3116   std::ostringstream oss;
3117   oss << MEDFileMesh::simpleRepr();
3118   const DataArrayDouble *coo=_coords;
3119   oss << "- The dimension of the space is ";
3120   static const char MSG1[]= "*** NO COORDS SET ***";
3121   static const char MSG2[]= "*** NO CONNECTIVITY SET FOR THIS LEVEL***";
3122   if(coo)
3123     oss << _coords->getNumberOfComponents() << std::endl;
3124   else
3125     oss << MSG1 << std::endl;
3126   oss << "- Type of the mesh : UNSTRUCTURED\n";
3127   oss << "- Number of nodes : ";
3128   if(coo)
3129     oss << _coords->getNumberOfTuples() << std::endl;
3130   else
3131     oss << MSG1 << std::endl;
3132   std::size_t nbOfLev=_ms.size();
3133   oss << "- Number of levels allocated : " << nbOfLev << std::endl;
3134   for(std::size_t i=0;i<nbOfLev;i++)
3135     {
3136       const MEDFileUMeshSplitL1 *lev=_ms[i];
3137       oss << "  - Level #" << -((int) i) << " has dimension : ";
3138       if(lev)
3139         {
3140           oss << lev->getMeshDimension() << std::endl;
3141           lev->simpleRepr(oss);
3142         }
3143       else
3144         oss << MSG2 << std::endl;
3145     }
3146   oss << "- Number of families : " << _families.size() << std::endl << std::endl;
3147   if(coo)
3148     {
3149       oss << "(***********************)\n(* NODES OF THE MESH : *)\n(***********************)\n";
3150       oss << "- Names of coordinates :" << std::endl;
3151       std::vector<std::string> vars=coo->getVarsOnComponent();
3152       std::copy(vars.begin(),vars.end(),std::ostream_iterator<std::string>(oss," "));
3153       oss << std::endl << "- Units of coordinates : " << std::endl;
3154       std::vector<std::string> units=coo->getUnitsOnComponent();
3155       std::copy(units.begin(),units.end(),std::ostream_iterator<std::string>(oss," "));
3156     }
3157   oss << std::endl << std::endl;
3158   getFamilyRepr(oss);
3159   getEquivalencesRepr(oss);
3160   return oss.str();
3161 }
3162
3163 /*!
3164  * Returns a full textual description of \a this mesh.
3165  *  \return std::string - the string holding the mesh description.
3166  */
3167 std::string MEDFileUMesh::advancedRepr() const
3168 {
3169   return simpleRepr();
3170 }
3171
3172 /*!
3173  * Returns number of mesh entities of a given relative dimension in \a this mesh.
3174  *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
3175  *  \return int - the number of entities.
3176  *  \throw If no mesh entities of dimension \a meshDimRelToMaxExt are available in \a this mesh.
3177  */
3178 int MEDFileUMesh::getSizeAtLevel(int meshDimRelToMaxExt) const
3179 {
3180   if(meshDimRelToMaxExt==1)
3181     {
3182       if(!((const DataArrayDouble *)_coords))
3183         throw INTERP_KERNEL::Exception("MEDFileUMesh::getSizeAtLevel : no coordinates specified !");
3184       return _coords->getNumberOfTuples();
3185     }
3186   return getMeshAtLevSafe(meshDimRelToMaxExt)->getSize();
3187 }
3188
3189 /*!
3190  * Returns the family field for mesh entities of a given dimension.
3191  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
3192  *  \return const DataArrayInt * - the family field. It is an array of ids of families
3193  *          each mesh entity belongs to. It can be \c NULL.
3194  */
3195 const DataArrayInt *MEDFileUMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) const
3196 {
3197   if(meshDimRelToMaxExt==1)
3198     return _fam_coords;
3199   const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMaxExt));
3200   return l1->getFamilyField();
3201 }
3202
3203 DataArrayInt *MEDFileUMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt)
3204 {
3205   if(meshDimRelToMaxExt==1)
3206     return _fam_coords;
3207   MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMaxExt));
3208   return l1->getFamilyField();
3209 }
3210
3211 /*!
3212  * Returns the optional numbers of mesh entities of a given dimension.
3213  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
3214  *  \return const DataArrayInt * - the array of the entity numbers.
3215  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3216  */
3217 const DataArrayInt *MEDFileUMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) const
3218 {
3219   if(meshDimRelToMaxExt==1)
3220     return _num_coords;
3221   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3222   return l1->getNumberField();
3223 }
3224
3225 const DataArrayAsciiChar *MEDFileUMesh::getNameFieldAtLevel(int meshDimRelToMaxExt) const
3226 {
3227   if(meshDimRelToMaxExt==1)
3228     return _name_coords;
3229   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3230   return l1->getNameField();
3231 }
3232
3233 /*!
3234  * 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).
3235  *
3236  * \param [in] meshDimRelToMaxExt - the extended relative level for which the part definition is requested.
3237  * \param [in] gt - The input geometric type for which the part definition is requested.
3238  * \return the part definition owned by \a this. So no need to deallocate the returned instance.
3239  */
3240 const PartDefinition *MEDFileUMesh::getPartDefAtLevel(int meshDimRelToMaxExt, INTERP_KERNEL::NormalizedCellType gt) const
3241 {
3242   if(meshDimRelToMaxExt==1)
3243     return _part_coords;
3244   const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMaxExt));
3245   return l1->getPartDef(gt);
3246 }
3247
3248 int MEDFileUMesh::getNumberOfNodes() const
3249 {
3250   const DataArrayDouble *coo(_coords);
3251   if(!coo)
3252     throw INTERP_KERNEL::Exception(" MEDFileUMesh::getNumberOfNodes : no coords set !");
3253   return coo->getNumberOfTuples();
3254 }
3255
3256 int MEDFileUMesh::getNumberOfCellsAtLevel(int meshDimRelToMaxExt) const
3257 {
3258   const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMaxExt));
3259   return l1->getNumberOfCells();
3260 }
3261
3262 bool MEDFileUMesh::hasImplicitPart() const
3263 {
3264   return false;
3265 }
3266
3267 int MEDFileUMesh::buildImplicitPartIfAny(INTERP_KERNEL::NormalizedCellType gt) const
3268 {
3269   throw INTERP_KERNEL::Exception("MEDFileUMesh::buildImplicitPartIfAny : unstructured meshes do not have implicit part !");
3270 }
3271
3272 void MEDFileUMesh::releaseImplicitPartIfAny() const
3273 {
3274 }
3275
3276 void MEDFileUMesh::whichAreNodesFetched(const MEDFileField1TSStructItem& st, const MEDFileFieldGlobsReal *globs, std::vector<bool>& nodesFetched) const
3277 {
3278   std::size_t sz(st.getNumberOfItems());
3279   for(std::size_t i=0;i<sz;i++)
3280     {
3281       INTERP_KERNEL::NormalizedCellType curGt(st[i].getGeo());
3282       const MEDCoupling1GTUMesh *m(getDirectUndergroundSingleGeoTypeMesh(curGt));
3283       if(st[i].getPflName().empty())
3284         m->computeNodeIdsAlg(nodesFetched);
3285       else
3286         {
3287           const DataArrayInt *arr(globs->getProfile(st[i].getPflName()));
3288           MCAuto<MEDCoupling1GTUMesh> m2(dynamic_cast<MEDCoupling1GTUMesh *>(m->buildPartOfMySelf(arr->begin(),arr->end(),true)));
3289           m2->computeNodeIdsAlg(nodesFetched);
3290         }
3291     }
3292 }
3293
3294 MEDFileMesh *MEDFileUMesh::cartesianize() const
3295 {
3296   if(getAxisType()==AX_CART)
3297     {
3298       incrRef();
3299       return const_cast<MEDFileUMesh *>(this);
3300     }
3301   else
3302     {
3303       MCAuto<MEDFileUMesh> ret(new MEDFileUMesh(*this));
3304       const DataArrayDouble *coords(_coords);
3305       if(!coords)
3306         throw INTERP_KERNEL::Exception("MEDFileUMesh::cartesianize : coordinates are null !");
3307       MCAuto<DataArrayDouble> coordsCart(_coords->cartesianize(getAxisType()));
3308       for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=ret->_ms.begin();it!=ret->_ms.end();it++)
3309         if((const MEDFileUMeshSplitL1 *)(*it))
3310           *it=(*it)->shallowCpyUsingCoords(coordsCart);
3311       ret->_coords=coordsCart;
3312       ret->setAxisType(AX_CART);
3313       return ret.retn();
3314     }
3315 }
3316
3317 bool MEDFileUMesh::presenceOfStructureElements() const
3318 {
3319   for(std::vector< MCAuto<MEDFileEltStruct4Mesh> >::const_iterator it=_elt_str.begin();it!=_elt_str.end();it++)
3320     if((*it).isNotNull())
3321       return true;
3322   return false;
3323 }
3324
3325 void MEDFileUMesh::killStructureElements()
3326 {
3327   _elt_str.clear();
3328 }
3329
3330 /*!
3331  * Returns the optional numbers of mesh entities of a given dimension transformed using
3332  * DataArrayInt::invertArrayN2O2O2N().
3333  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
3334  *  \return const DataArrayInt * - the array of the entity numbers transformed using
3335  *          DataArrayInt::invertArrayN2O2O2N().
3336  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3337  */
3338 const DataArrayInt *MEDFileUMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxExt) const
3339 {
3340   if(meshDimRelToMaxExt==1)
3341     {
3342       if(!((const DataArrayInt *)_num_coords))
3343         throw INTERP_KERNEL::Exception("MEDFileUMesh::getRevNumberFieldAtLevel : no coordinates renum specified !");
3344       return _rev_num_coords;
3345     }
3346   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3347   return l1->getRevNumberField();
3348 }
3349
3350 /*!
3351  * Returns a pointer to the node coordinates array of \a this mesh \b without
3352  * incrementing its reference counter, thus there is no need to decrRef() it by the caller.
3353  */
3354 DataArrayDouble *MEDFileUMesh::getCoords() const
3355 {
3356   checkCartesian();
3357   MCAuto<DataArrayDouble> tmp(_coords);
3358   if((DataArrayDouble *)tmp)
3359     {
3360       return tmp;
3361     }
3362   return 0;
3363 }
3364
3365 /*!
3366  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in a given
3367  * group of \a this mesh. Only mesh entities of a given dimension are included in the
3368  * new mesh.
3369  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
3370  *  \param [in] grp - the name of the group whose mesh entities are included in the
3371  *          new mesh.
3372  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
3373  *          according to the optional numbers of entities, if available.
3374  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
3375  *          delete this mesh using decrRef() as it is no more needed.
3376  *  \throw If the name of a nonexistent group is specified.
3377  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3378  */
3379 MEDCouplingUMesh *MEDFileUMesh::getGroup(int meshDimRelToMaxExt, const std::string& grp, bool renum) const
3380 {
3381   checkCartesian();
3382   synchronizeTinyInfoOnLeaves();
3383   std::vector<std::string> tmp(1);
3384   tmp[0]=grp;
3385   return getGroups(meshDimRelToMaxExt,tmp,renum);
3386 }
3387
3388 /*!
3389  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in given
3390  * groups of \a this mesh. Only mesh entities of a given dimension are included in the
3391  * new mesh.
3392  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
3393  *  \param [in] grps - a sequence of group names whose mesh entities are included in the
3394  *          new mesh.
3395  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
3396  *          according to the optional numbers of entities, if available.
3397  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
3398  *          delete this mesh using decrRef() as it is no more needed.
3399  *  \throw If a name of a nonexistent group is present in \a grps.
3400  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3401  */
3402 MEDCouplingUMesh *MEDFileUMesh::getGroups(int meshDimRelToMaxExt, const std::vector<std::string>& grps, bool renum) const
3403 {
3404   checkCartesian();
3405   synchronizeTinyInfoOnLeaves();
3406   std::vector<std::string> fams2=getFamiliesOnGroups(grps);
3407   MCAuto<MEDCouplingUMesh> zeRet=getFamilies(meshDimRelToMaxExt,fams2,renum);
3408   if(grps.size()==1 && ((MEDCouplingUMesh *)zeRet))
3409     zeRet->setName(grps[0]);
3410   return zeRet.retn();
3411 }
3412
3413 /*!
3414  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in a given
3415  * family of \a this mesh. Only mesh entities of a given dimension are included in the
3416  * new mesh.
3417  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
3418  *  \param [in] fam - the name of the family whose mesh entities are included in the
3419  *          new mesh.
3420  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
3421  *          according to the optional numbers of entities, if available.
3422  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
3423  *          delete this mesh using decrRef() as it is no more needed.
3424  *  \throw If a name of a nonexistent family is present in \a grps.
3425  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3426  */
3427 MEDCouplingUMesh *MEDFileUMesh::getFamily(int meshDimRelToMaxExt, const std::string& fam, bool renum) const
3428 {
3429   checkCartesian();
3430   synchronizeTinyInfoOnLeaves();
3431   std::vector<std::string> tmp(1);
3432   tmp[0]=fam;
3433   return getFamilies(meshDimRelToMaxExt,tmp,renum);
3434 }
3435
3436 /*!
3437  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in given
3438  * families of \a this mesh. Only mesh entities of a given dimension are included in the
3439  * new mesh.
3440  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
3441  *  \param [in] fams - a sequence of family names whose mesh entities are included in the
3442  *          new mesh.
3443  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
3444  *          according to the optional numbers of entities, if available.
3445  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
3446  *          delete this mesh using decrRef() as it is no more needed.
3447  *  \throw If a name of a nonexistent family is present in \a fams.
3448  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3449  */
3450 MEDCouplingUMesh *MEDFileUMesh::getFamilies(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const
3451 {
3452   checkCartesian();
3453   synchronizeTinyInfoOnLeaves();
3454   if(meshDimRelToMaxExt==1)
3455     {
3456       MCAuto<DataArrayInt> arr=getFamiliesArr(1,fams,renum);
3457       MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3458       MCAuto<DataArrayDouble> c=_coords->selectByTupleId(arr->getConstPointer(),arr->getConstPointer()+arr->getNbOfElems());
3459       ret->setCoords(c);
3460       return ret.retn();
3461     }
3462   std::vector<int> famIds=getFamiliesIds(fams);
3463   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3464   MCAuto<MEDCouplingUMesh> zeRet;
3465   if(!famIds.empty())
3466     zeRet=l1->getFamilyPart(&famIds[0],&famIds[0]+famIds.size(),renum);
3467   else
3468     zeRet=l1->getFamilyPart(0,0,renum);
3469   if(fams.size()==1 && ((MEDCouplingUMesh *)zeRet))
3470     zeRet->setName(fams[0]);
3471   return zeRet.retn();
3472 }
3473
3474 /*!
3475  * Returns ids of mesh entities contained in given families of a given dimension.
3476  *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
3477  *          are required.
3478  *  \param [in] fams - the names of the families of interest.
3479  *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
3480  *          returned instead of ids.
3481  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
3482  *          numbers, if available and required, of mesh entities of the families. The caller
3483  *          is to delete this array using decrRef() as it is no more needed. 
3484  *  \throw If the family field is missing for \a meshDimRelToMaxExt.
3485  */
3486 DataArrayInt *MEDFileUMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const
3487 {
3488   std::vector<int> famIds=getFamiliesIds(fams);
3489   if(meshDimRelToMaxExt==1)
3490     {
3491       if((const DataArrayInt *)_fam_coords)
3492         {
3493           MCAuto<DataArrayInt> da;
3494           if(!famIds.empty())
3495             da=_fam_coords->findIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
3496           else
3497             da=_fam_coords->findIdsEqualList(0,0);
3498           if(renum)
3499             return MEDFileUMeshSplitL1::Renumber(_num_coords,da);
3500           else
3501             return da.retn();
3502         }
3503       else
3504         throw INTERP_KERNEL::Exception("MEDFileUMesh::getFamiliesArr : no family array specified on nodes !");
3505     }
3506   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3507   if(!famIds.empty())
3508     return l1->getFamilyPartArr(&famIds[0],&famIds[0]+famIds.size(),renum);
3509   else
3510     return l1->getFamilyPartArr(0,0,renum);
3511 }
3512
3513 /*!
3514  * Returns a MEDCouplingUMesh of a given relative dimension.
3515  * \warning If \a meshDimRelToMaxExt == 1 (which means nodes), the returned mesh **is not
3516  * valid**. This is a feature, because MEDLoader does not create cells that do not exist! 
3517  * To build a valid MEDCouplingUMesh from the returned one in this case,
3518  * call MEDCouplingUMesh::Build0DMeshFromCoords().
3519  *  \param [in] meshDimRelToMax - the relative dimension of interest.
3520  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3521  *          optional numbers of mesh entities.
3522  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
3523  *          delete using decrRef() as it is no more needed. 
3524  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3525  */
3526 MEDCouplingUMesh *MEDFileUMesh::getMeshAtLevel(int meshDimRelToMaxExt, bool renum) const
3527 {
3528   checkCartesian();
3529   synchronizeTinyInfoOnLeaves();
3530   if(meshDimRelToMaxExt==1)
3531     {
3532       if(!renum)
3533         {
3534           MEDCouplingUMesh *umesh=MEDCouplingUMesh::New();
3535           MCAuto<DataArrayDouble> cc=_coords->deepCopy();
3536           umesh->setCoords(cc);
3537           MEDFileUMeshSplitL1::ClearNonDiscrAttributes(umesh);
3538           umesh->setName(getName());
3539           return umesh;
3540         }
3541     }
3542   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3543   return l1->getWholeMesh(renum);
3544 }
3545
3546 std::vector<int> MEDFileUMesh::getDistributionOfTypes(int meshDimRelToMax) const
3547 {
3548   const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMax));
3549   return l1->getDistributionOfTypes();
3550 }
3551
3552 /*!
3553  * Returns a MEDCouplingUMesh of a relative dimension == 0.
3554  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3555  *          optional numbers of mesh entities.
3556  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
3557  *          delete using decrRef() as it is no more needed. 
3558  *  \throw If there are no mesh entities of the relative dimension == 0 in \a this mesh.
3559  */
3560 MEDCouplingUMesh *MEDFileUMesh::getLevel0Mesh(bool renum) const
3561 {
3562   return getMeshAtLevel(0,renum);
3563 }
3564
3565 /*!
3566  * Returns a MEDCouplingUMesh of a relative dimension == -1.
3567  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3568  *          optional numbers of mesh entities.
3569  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
3570  *          delete using decrRef() as it is no more needed. 
3571  *  \throw If there are no mesh entities of the relative dimension == -1 in \a this mesh.
3572  */
3573 MEDCouplingUMesh *MEDFileUMesh::getLevelM1Mesh(bool renum) const
3574 {
3575   return getMeshAtLevel(-1,renum);
3576 }
3577
3578 /*!
3579  * Returns a MEDCouplingUMesh of a relative dimension == -2.
3580  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3581  *          optional numbers of mesh entities.
3582  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
3583  *          delete using decrRef() as it is no more needed. 
3584  *  \throw If there are no mesh entities of the relative dimension == -2 in \a this mesh.
3585  */
3586 MEDCouplingUMesh *MEDFileUMesh::getLevelM2Mesh(bool renum) const
3587 {
3588   return getMeshAtLevel(-2,renum);
3589 }
3590
3591 /*!
3592  * Returns a MEDCouplingUMesh of a relative dimension == -3.
3593  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3594  *          optional numbers of mesh entities.
3595  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
3596  *          delete using decrRef() as it is no more needed. 
3597  *  \throw If there are no mesh entities of the relative dimension == -3 in \a this mesh.
3598  */
3599 MEDCouplingUMesh *MEDFileUMesh::getLevelM3Mesh(bool renum) const
3600 {
3601   return getMeshAtLevel(-3,renum);
3602 }
3603
3604 /*!
3605  * This method is for advanced users. There is two storing strategy of mesh in \a this.
3606  * Either MEDCouplingUMesh, or vector of MEDCoupling1GTUMesh instances.
3607  * When assignement is done the first one is done, which is not optimal in write mode for MED file.
3608  * This method allows to switch from MEDCouplingUMesh mode to MEDCoupling1GTUMesh mode.
3609  */
3610 void MEDFileUMesh::forceComputationOfParts() const
3611 {
3612   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
3613     {
3614       const MEDFileUMeshSplitL1 *elt(*it);
3615       if(elt)
3616         elt->forceComputationOfParts();
3617     }
3618 }
3619
3620 /*!
3621  * This method returns a vector of mesh parts containing each exactly one geometric type.
3622  * This method will never launch an automatic computation of split by type (an INTERP_KERNEL::Exception will be then thrown).
3623  * This method is only for memory aware users.
3624  * The returned pointers are **NOT** new object pointer. No need to mange them.
3625  */
3626 std::vector<MEDCoupling1GTUMesh *> MEDFileUMesh::getDirectUndergroundSingleGeoTypeMeshes(int meshDimRelToMax) const
3627 {
3628   checkCartesian();
3629   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(meshDimRelToMax));
3630   return sp->getDirectUndergroundSingleGeoTypeMeshes();
3631 }
3632
3633 /*!
3634  * This method returns the part of \a this having the geometric type \a gt.
3635  * If such part is not existing an exception will be thrown.
3636  * The returned pointer is **NOT** new object pointer. No need to mange it.
3637  */
3638 MEDCoupling1GTUMesh *MEDFileUMesh::getDirectUndergroundSingleGeoTypeMesh(INTERP_KERNEL::NormalizedCellType gt) const
3639 {
3640   checkCartesian();
3641   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(gt));
3642   int lev=(int)cm.getDimension()-getMeshDimension();
3643   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(lev));
3644   return sp->getDirectUndergroundSingleGeoTypeMesh(gt);
3645 }
3646
3647 /*!
3648  * This method returns for each geo types in \a this number of cells with this geo type.
3649  * 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.
3650  * This method also returns the number of nodes of \a this (key associated is NORM_ERROR)
3651  *
3652  * \sa getDistributionOfTypes
3653  */
3654 std::vector< std::pair<int,int> > MEDFileUMesh::getAllDistributionOfTypes() const
3655 {
3656   std::vector< std::pair<int,int> > ret;
3657   std::vector<int> nel(getNonEmptyLevels());
3658   for(std::vector<int>::reverse_iterator it=nel.rbegin();it!=nel.rend();it++)
3659     {
3660       std::vector<INTERP_KERNEL::NormalizedCellType> gt(getGeoTypesAtLevel(*it));
3661       for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it1=gt.begin();it1!=gt.end();it1++)
3662         {
3663           int nbCells(getNumberOfCellsWithType(*it1));
3664           ret.push_back(std::pair<int,int>(*it1,nbCells));
3665         }
3666     }
3667   ret.push_back(std::pair<int,int>(INTERP_KERNEL::NORM_ERROR,getNumberOfNodes()));
3668   return ret;
3669 }
3670
3671 /*!
3672  * Given a relative level \a meshDimRelToMax it returns the sorted vector of geometric types present in \a this.
3673  * \throw if the reqsuested \a meshDimRelToMax does not exist.
3674  */
3675 std::vector<INTERP_KERNEL::NormalizedCellType> MEDFileUMesh::getGeoTypesAtLevel(int meshDimRelToMax) const
3676 {
3677   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(meshDimRelToMax));
3678   return sp->getGeoTypes();
3679 }
3680
3681 int MEDFileUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType ct) const
3682 {
3683   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(ct);
3684   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe( ((int)cm.getDimension())-getMeshDimension() ));
3685   return sp->getNumberOfCellsWithType(ct);
3686 }
3687
3688 /*!
3689  * This method extracts from whole family field ids the part relative to the input parameter \a gt.
3690  * \param [in] gt - the geometric type for which the family field is asked.
3691  * \return DataArrayInt * - a pointer to DataArrayInt that the caller is to
3692  *          delete using decrRef() as it is no more needed.
3693  * \sa MEDFileUMesh::extractNumberFieldOnGeoType
3694  */
3695 DataArrayInt *MEDFileUMesh::extractFamilyFieldOnGeoType(INTERP_KERNEL::NormalizedCellType gt) const
3696 {
3697   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
3698   int lev=(int)cm.getDimension()-getMeshDimension();
3699   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(lev));
3700   return sp->extractFamilyFieldOnGeoType(gt);
3701 }
3702
3703 /*!
3704  * This method extracts from whole number field ids the part relative to the input parameter \a gt.
3705  * \param [in] gt - the geometric type for which the number field is asked.
3706  * \return DataArrayInt * - a pointer to DataArrayInt that the caller is to
3707  *          delete using decrRef() as it is no more needed.
3708  * \sa MEDFileUMesh::extractFamilyFieldOnGeoType
3709  */
3710 DataArrayInt *MEDFileUMesh::extractNumberFieldOnGeoType(INTERP_KERNEL::NormalizedCellType gt) const
3711 {
3712   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
3713   int lev=(int)cm.getDimension()-getMeshDimension();
3714   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(lev));
3715   return sp->extractNumberFieldOnGeoType(gt);
3716 }
3717
3718 /*!
3719  * This method returns for specified geometric type \a gt the relative level to \a this.
3720  * If the relative level is empty an exception will be thrown.
3721  */
3722 int MEDFileUMesh::getRelativeLevOnGeoType(INTERP_KERNEL::NormalizedCellType gt) const
3723 {
3724   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
3725   int ret((int)cm.getDimension()-getMeshDimension());
3726   getMeshAtLevSafe(ret);//To test that returned value corresponds to a valid level.
3727   return ret;
3728 }
3729
3730 const MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt) const
3731 {
3732   if(meshDimRelToMaxExt==1)
3733     throw INTERP_KERNEL::Exception("Dimension request is invalid : asking for node level (1) !");
3734   if(meshDimRelToMaxExt>1)
3735     throw INTERP_KERNEL::Exception("Dimension request is invalid (>1) !");
3736   int tracucedRk=-meshDimRelToMaxExt;
3737   if(tracucedRk>=(int)_ms.size())
3738     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
3739   if((const MEDFileUMeshSplitL1 *)_ms[tracucedRk]==0)
3740     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3741   return _ms[tracucedRk];
3742 }
3743
3744 MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt)
3745 {
3746   if(meshDimRelToMaxExt==1)
3747     throw INTERP_KERNEL::Exception("Dimension request is invalid : asking for node level (1) !");
3748   if(meshDimRelToMaxExt>1)
3749     throw INTERP_KERNEL::Exception("Dimension request is invalid (>1) !");
3750   int tracucedRk=-meshDimRelToMaxExt;
3751   if(tracucedRk>=(int)_ms.size())
3752     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
3753   if((const MEDFileUMeshSplitL1 *)_ms[tracucedRk]==0)
3754     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3755   return _ms[tracucedRk];
3756 }
3757
3758 void MEDFileUMesh::checkMeshDimCoherency(int meshDim, int meshDimRelToMax) const
3759 {
3760   if(-meshDimRelToMax>=(int)_ms.size())
3761     throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMeshDimCoherency : The meshdim of mesh is not managed by 'this' !");
3762   int i=0;
3763   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,i++)
3764     {
3765       if(((const MEDFileUMeshSplitL1*) (*it))!=0)
3766         {
3767           int ref=(*it)->getMeshDimension();
3768           if(ref+i!=meshDim-meshDimRelToMax)
3769             throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMeshDimCoherency : no coherency between levels !");
3770         }
3771     }
3772 }
3773
3774 /*!
3775  * Sets the node coordinates array of \a this mesh.
3776  *  \param [in] coords - the new node coordinates array.
3777  *  \throw If \a coords == \c NULL.
3778  */
3779 void MEDFileUMesh::setCoords(DataArrayDouble *coords)
3780 {
3781   if(!coords)
3782     throw INTERP_KERNEL::Exception("MEDFileUMesh::setCoords : null pointer in input !");
3783   if(coords==(DataArrayDouble *)_coords)
3784     return ;
3785   coords->checkAllocated();
3786   int nbOfTuples(coords->getNumberOfTuples());
3787   _coords=coords;
3788   coords->incrRef();
3789   _fam_coords=DataArrayInt::New();
3790   _fam_coords->alloc(nbOfTuples,1);
3791   _fam_coords->fillWithZero();
3792   _num_coords=0; _rev_num_coords=0; _name_coords=0;
3793   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
3794     if((MEDFileUMeshSplitL1 *)(*it))
3795       (*it)->setCoords(coords);
3796 }
3797
3798 /*!
3799  * Change coords without changing anything concerning families and numbering on nodes.
3800  */
3801 void MEDFileUMesh::setCoordsForced(DataArrayDouble *coords)
3802 {
3803   if(!coords)
3804     throw INTERP_KERNEL::Exception("MEDFileUMesh::setCoordsForced : null pointer in input !");
3805   if(coords==(DataArrayDouble *)_coords)
3806     return ;
3807   coords->checkAllocated();
3808   int nbOfTuples(coords->getNumberOfTuples());
3809   if(_coords.isNull())
3810     {
3811       _coords=coords;
3812       coords->incrRef();
3813     }
3814   else
3815     {
3816       int oldNbTuples(_coords->getNumberOfTuples());
3817       if(oldNbTuples!=nbOfTuples)
3818         throw INTERP_KERNEL::Exception("MEDFileUMesh::setCoordsForced : number of tuples is not the same -> invoke setCoords instead !");
3819       _coords=coords;
3820       coords->incrRef();
3821     }
3822   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
3823     if((MEDFileUMeshSplitL1 *)(*it))
3824       (*it)->setCoords(coords);
3825 }
3826
3827 /*!
3828  * Removes all groups of a given dimension in \a this mesh.
3829  *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
3830  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3831  */
3832 void MEDFileUMesh::eraseGroupsAtLevel(int meshDimRelToMaxExt)
3833 {
3834   if(meshDimRelToMaxExt==1)
3835     {
3836       if((DataArrayInt *)_fam_coords)
3837         _fam_coords->fillWithZero();
3838       return ;
3839     }
3840   MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3841   l1->eraseFamilyField();
3842   optimizeFamilies();
3843 }
3844
3845 /*!
3846  * Removes all families with ids not present in the family fields of \a this mesh.
3847  */
3848 void MEDFileUMesh::optimizeFamilies()
3849 {
3850   std::vector<int> levs=getNonEmptyLevelsExt();
3851   std::set<int> allFamsIds;
3852   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
3853     {
3854       const DataArrayInt *ffield=getFamilyFieldAtLevel(*it);
3855       MCAuto<DataArrayInt> ids=ffield->getDifferentValues();
3856       std::set<int> res;
3857       std::set_union(ids->begin(),ids->end(),allFamsIds.begin(),allFamsIds.end(),std::inserter(res,res.begin()));
3858       allFamsIds=res;
3859     }
3860   std::set<std::string> famNamesToKill;
3861   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
3862     {
3863       if(allFamsIds.find((*it).second)!=allFamsIds.end())
3864         famNamesToKill.insert((*it).first);
3865     }
3866   for(std::set<std::string>::const_iterator it=famNamesToKill.begin();it!=famNamesToKill.end();it++)
3867     _families.erase(*it);
3868   std::vector<std::string> grpNamesToKill;
3869   for(std::map<std::string, std::vector<std::string> >::iterator it=_groups.begin();it!=_groups.end();it++)
3870     {
3871       std::vector<std::string> tmp;
3872       for(std::vector<std::string>::const_iterator it2=(*it).second.begin();it2!=(*it).second.end();it2++)
3873         {
3874           if(famNamesToKill.find(*it2)==famNamesToKill.end())
3875             tmp.push_back(*it2);
3876         }
3877       if(!tmp.empty())
3878         (*it).second=tmp;
3879       else
3880         tmp.push_back((*it).first);
3881     }
3882   for(std::vector<std::string>::const_iterator it=grpNamesToKill.begin();it!=grpNamesToKill.end();it++)
3883     _groups.erase(*it);
3884 }
3885
3886 /**
3887  * \b this must be filled at level 0 and -1, typically the -1 level being (part of) the descending connectivity
3888  * of the top level. This method build a "crack", or an inner boundary, in \b this along the group of level -1 named grpNameM1.
3889  * The boundary is built according to the following method:
3890  *  - all nodes along the boundary which are not lying on an internal extremity of the (-1)-level group are duplicated (so the
3891  * coordinates array is extended).
3892  *  - new (-1)-level cells are built lying on those new nodes. So the edges/faces along the group are duplicated. A new group
3893  *  called "<grpNameM1>_dup" containing the effectively duplicated cells is created. Note that in 3D some cells of the group
3894  *  might not be duplicated at all.
3895  *  After this operation a top-level cell bordering the group will loose some neighbors (typically the cell which is  on the
3896  *  other side of the group is no more a neighbor)
3897  *   - finally, the connectivity of (part of) the top level-cells bordering the group is also modified so that some cells
3898  *  bordering the newly created boundary use the newly computed nodes.
3899  *  Finally note that optional cell numbers are also affected by this method and might become invalid for SMESH.
3900  *  Use clearNodeAndCellNumbers() afterwards to ensure a proper SMESH loading.
3901  *
3902  *  \param[in] grpNameM1 name of the (-1)-level group defining the boundary
3903  *  \param[out] nodesDuplicated ids of the initial nodes which have been duplicated (and whose copy is put at the end of
3904  *  the coord array)
3905  *  \param[out] cellsModified ids of the cells whose connectivity has been modified (to use the newly created nodes)
3906  *  \param[out] cellsNotModified ids of the rest of cells bordering the new boundary whose connectivity remains unchanged.
3907  *  \sa clearNodeAndCellNumbers()
3908  */
3909 void MEDFileUMesh::buildInnerBoundaryAlongM1Group(const std::string& grpNameM1, DataArrayInt *&nodesDuplicated,
3910                                            DataArrayInt *&cellsModified, DataArrayInt *&cellsNotModified)
3911 {
3912   typedef MCAuto<MEDCouplingUMesh> MUMesh;
3913   typedef MCAuto<DataArrayInt> DAInt;
3914
3915   std::vector<int> levs=getNonEmptyLevels();
3916   if(std::find(levs.begin(),levs.end(),0)==levs.end() || std::find(levs.begin(),levs.end(),-1)==levs.end())
3917     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildInnerBoundaryAlongM1Group : This method works only for mesh definied on level 0 and -1 !");
3918   MUMesh m0=getMeshAtLevel(0);
3919   MUMesh m1=getMeshAtLevel(-1);
3920   int nbNodes=m0->getNumberOfNodes();
3921   MUMesh m11=getGroup(-1,grpNameM1);
3922   DataArrayInt *tmp00=0,*tmp11=0,*tmp22=0;
3923   m0->findNodesToDuplicate(*m11,tmp00,tmp11,tmp22);
3924   DAInt nodeIdsToDuplicate(tmp00);
3925   DAInt cellsToModifyConn0(tmp11);
3926   DAInt cellsToModifyConn1(tmp22);
3927   MUMesh tmp0=static_cast<MEDCouplingUMesh *>(m0->buildPartOfMySelf(cellsToModifyConn0->begin(),cellsToModifyConn0->end(),true));
3928   // node renumbering of cells in m1 impacted by duplication of node but not in group 'grpNameM1' on level -1
3929   DAInt descTmp0=DataArrayInt::New(),descITmp0=DataArrayInt::New(),revDescTmp0=DataArrayInt::New(),revDescITmp0=DataArrayInt::New();
3930   MUMesh tmp0Desc=tmp0->buildDescendingConnectivity(descTmp0,descITmp0,revDescTmp0,revDescITmp0);
3931   descTmp0=0; descITmp0=0; revDescTmp0=0; revDescITmp0=0;
3932   DAInt cellsInM1ToRenumW2=tmp0Desc->getCellIdsLyingOnNodes(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),false);
3933   MUMesh cellsInM1ToRenumW3=static_cast<MEDCouplingUMesh *>(tmp0Desc->buildPartOfMySelf(cellsInM1ToRenumW2->begin(),cellsInM1ToRenumW2->end(),true));
3934   DataArrayInt *cellsInM1ToRenumW4Tmp=0;
3935   m1->areCellsIncludedIn(cellsInM1ToRenumW3,2,cellsInM1ToRenumW4Tmp);
3936   DAInt cellsInM1ToRenumW4(cellsInM1ToRenumW4Tmp);
3937   DAInt cellsInM1ToRenumW5=cellsInM1ToRenumW4->findIdsInRange(0,m1->getNumberOfCells());
3938   cellsInM1ToRenumW5->transformWithIndArr(cellsInM1ToRenumW4->begin(),cellsInM1ToRenumW4->end());
3939   DAInt grpIds=getGroupArr(-1,grpNameM1);
3940   DAInt cellsInM1ToRenum=cellsInM1ToRenumW5->buildSubstraction(grpIds);
3941   MUMesh m1Part=static_cast<MEDCouplingUMesh *>(m1->buildPartOfMySelf(cellsInM1ToRenum->begin(),cellsInM1ToRenum->end(),true));
3942   m1Part->duplicateNodesInConn(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),nbNodes);
3943   m1->setPartOfMySelf(cellsInM1ToRenum->begin(),cellsInM1ToRenum->end(),*m1Part);
3944   // end of node renumbering of cells in m1 impacted by duplication of node but not in group of level -1 'grpNameM1'
3945   tmp0->duplicateNodes(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end());
3946   m0->setCoords(tmp0->getCoords());
3947   m0->setPartOfMySelf(cellsToModifyConn0->begin(),cellsToModifyConn0->end(),*tmp0);
3948   _ms[0]->forceComputationOfParts();  // necessary because we modify the connectivity of some internal part
3949   m1->setCoords(m0->getCoords());
3950   _coords=m0->getCoords(); _coords->incrRef();
3951   // duplication of cells in group 'grpNameM1' on level -1, but not duplicating cells for which nothing has changed
3952   m11->duplicateNodesInConn(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),nbNodes); m11->setCoords(m0->getCoords());
3953   DataArrayInt * duplCells;
3954   m1->areCellsIncludedIn(m11, 0, duplCells);
3955   DAInt zeIds = duplCells->findIdsNotInRange(-1, m1->getNumberOfCells()-1); duplCells->decrRef();
3956   MUMesh m11Part=static_cast<MEDCouplingUMesh *>(m11->buildPartOfMySelf(zeIds->begin(),zeIds->end(),true));
3957   std::vector<const MEDCouplingUMesh *> v(2); v[0]=m1; v[1]=m11Part;
3958   MUMesh newm1=MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(v,tmp00,tmp11);
3959   DAInt szOfCellGrpOfSameType(tmp00);
3960   DAInt idInMsOfCellGrpOfSameType(tmp11);
3961   //
3962   newm1->setName(getName());
3963   const DataArrayInt *fam=getFamilyFieldAtLevel(-1);
3964   if(!fam)
3965     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildInnerBoundaryAlongM1Group(): internal error no family field !");
3966   DAInt newFam=DataArrayInt::New();
3967   newFam->alloc(newm1->getNumberOfCells(),1);
3968   // Get a new family ID: care must be taken if we need a positive ID or a negative one:
3969   // Positive ID for family of nodes, negative for all the rest.
3970   int idd;
3971   if (m1->getMeshDimension() == 0)
3972     idd=getMaxFamilyId()+1;
3973   else
3974     idd=getMinFamilyId()-1;
3975   int globStart=0,start=0,end,globEnd;
3976   int nbOfChunks=szOfCellGrpOfSameType->getNumberOfTuples();
3977   for(int i=0;i<nbOfChunks;i++)
3978     {
3979       globEnd=globStart+szOfCellGrpOfSameType->getIJ(i,0);
3980       if(idInMsOfCellGrpOfSameType->getIJ(i,0)==0)
3981         {
3982           end=start+szOfCellGrpOfSameType->getIJ(i,0);
3983           DAInt part=fam->selectByTupleIdSafeSlice(start,end,1);
3984           newFam->setPartOfValues1(part,globStart,globEnd,1,0,1,1,true);
3985           start=end;
3986         }
3987       else
3988         {
3989           newFam->setPartOfValuesSimple1(idd,globStart,globEnd,1,0,1,1);
3990         }
3991       globStart=globEnd;
3992     }
3993   newm1->setCoords(getCoords());
3994   setMeshAtLevel(-1,newm1);
3995   setFamilyFieldArr(-1,newFam);
3996   std::string grpName2(grpNameM1); grpName2+="_dup";
3997   addFamily(grpName2,idd);
3998   addFamilyOnGrp(grpName2,grpName2);
3999   //
4000   fam=_fam_coords;
4001   if(fam)
4002     {
4003       int newNbOfNodes=getCoords()->getNumberOfTuples();
4004       newFam=DataArrayInt::New(); newFam->alloc(newNbOfNodes,1);
4005       newFam->setPartOfValues1(fam,0,nbNodes,1,0,1,1,true);
4006       newFam->setPartOfValuesSimple1(0,nbNodes,newNbOfNodes,1,0,1,1);
4007       _fam_coords=newFam;
4008     }
4009
4010   _num_coords = 0;
4011   _rev_num_coords = 0;
4012   for (std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();
4013       it != _ms.end(); it++)
4014     {
4015       (*it)->_num = 0;
4016       (*it)->_rev_num = 0;
4017     }
4018   nodesDuplicated=nodeIdsToDuplicate.retn();
4019   cellsModified=cellsToModifyConn0.retn();
4020   cellsNotModified=cellsToModifyConn1.retn();
4021 }
4022
4023 /*! Similar to MEDCouplingUMesh::unPolyze():  converts all polygons (if \a this is a 2D mesh) or polyhedrons
4024  * (if \a this is a 3D mesh) to cells of classical types. The cells remain correctly sorted by geometric type
4025  * in this method.
4026  *
4027  * \param [out] oldCode retrieves the distribution of types before the call if true is returned
4028  * \param [out] newCode etrieves the distribution of types after the call if true is returned
4029  * \param [out] o2nRenumCell tells for **all levels** the old 2 new renumbering of cells.
4030  * 
4031  * \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.
4032  * 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.
4033  */
4034 bool MEDFileUMesh::unPolyze(std::vector<int>& oldCode, std::vector<int>& newCode, DataArrayInt *& o2nRenumCell)
4035 {
4036   o2nRenumCell=0; oldCode.clear(); newCode.clear();
4037   std::vector<int> levs=getNonEmptyLevels();
4038   bool ret=false;
4039   std::vector< const DataArrayInt* > renumCellsSplited;//same than memorySaverIfThrow
4040   std::vector< MCAuto<DataArrayInt> > memorySaverIfThrow;//same than renumCellsSplited only in case of throw
4041   int start=0;
4042   int end=0;
4043   for(std::vector<int>::reverse_iterator it=levs.rbegin();it!=levs.rend();it++)
4044     {
4045       MCAuto<MEDCouplingUMesh> m=getMeshAtLevel(*it);
4046       std::vector<int> code1=m->getDistributionOfTypes();
4047       end=PutInThirdComponentOfCodeOffset(code1,start);
4048       oldCode.insert(oldCode.end(),code1.begin(),code1.end());
4049       bool hasChanged=m->unPolyze();
4050       DataArrayInt *fake=0;
4051       MCAuto<DataArrayInt> o2nCellsPart=m->getLevArrPerCellTypes(MEDCouplingUMesh::MEDMEM_ORDER,
4052           MEDCouplingUMesh::MEDMEM_ORDER+MEDCouplingUMesh::N_MEDMEM_ORDER,fake);
4053       fake->decrRef();
4054       renumCellsSplited.push_back(o2nCellsPart); memorySaverIfThrow.push_back(o2nCellsPart);
4055       if(hasChanged)
4056         {
4057           MCAuto<DataArrayInt> o2nCellsPart2=o2nCellsPart->buildPermArrPerLevel();
4058           m->renumberCells(o2nCellsPart2->getConstPointer(),false);
4059           ret=true;
4060           MCAuto<DataArrayInt> famField2,numField2;
4061           const DataArrayInt *famField=getFamilyFieldAtLevel(*it); if(famField) { famField->incrRef(); famField2=const_cast<DataArrayInt *>(famField); }
4062           const DataArrayInt *numField=getNumberFieldAtLevel(*it); if(numField) { numField->incrRef(); numField2=const_cast<DataArrayInt *>(numField); }
4063           setMeshAtLevel(*it,m);
4064           std::vector<int> code2=m->getDistributionOfTypes();
4065           end=PutInThirdComponentOfCodeOffset(code2,start);
4066           newCode.insert(newCode.end(),code2.begin(),code2.end());
4067           //
4068           if(o2nCellsPart2->isIota(o2nCellsPart2->getNumberOfTuples()))
4069             continue;
4070           if(famField)
4071             {
4072               MCAuto<DataArrayInt> newFamField=famField->renumber(o2nCellsPart2->getConstPointer());
4073               setFamilyFieldArr(*it,newFamField);
4074             }
4075           if(numField)
4076             {
4077               MCAuto<DataArrayInt> newNumField=numField->renumber(o2nCellsPart2->getConstPointer());
4078               setRenumFieldArr(*it,newNumField);
4079             }
4080         }
4081       else
4082         {
4083           newCode.insert(newCode.end(),code1.begin(),code1.end());
4084         }
4085       start=end;
4086     }
4087   if(ret)
4088     {
4089       MCAuto<DataArrayInt> renumCells=DataArrayInt::Aggregate(renumCellsSplited);
4090       MCAuto<DataArrayInt> o2nRenumCellRet=renumCells->buildPermArrPerLevel();
4091       o2nRenumCell=o2nRenumCellRet.retn();
4092     }
4093   return ret;
4094 }
4095
4096 /*! \cond HIDDEN_ITEMS */
4097 struct MEDLoaderAccVisit1
4098 {
4099   MEDLoaderAccVisit1():_new_nb_of_nodes(0) { }
4100   int operator()(bool val) { return val?_new_nb_of_nodes++:-1; }
4101   int _new_nb_of_nodes;
4102 };
4103 /*! \endcond */
4104
4105 /*!
4106  * 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.
4107  * The maximum value stored in returned array is the number of nodes of \a this minus 1 after call of this method.
4108  * The size of returned array is the number of nodes of the old (previous to the call of this method) number of nodes.
4109  * -1 values in returned array means that the corresponding old node is no more used.
4110  *
4111  * \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
4112  *         is modified in \a this.
4113  * \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
4114  *  set coordinates.
4115  */
4116 DataArrayInt *MEDFileUMesh::zipCoords()
4117 {
4118   const DataArrayDouble *coo(getCoords());
4119   if(!coo)
4120     throw INTERP_KERNEL::Exception("MEDFileUMesh::zipCoords : no coordinates set in this !");
4121   int nbOfNodes(coo->getNumberOfTuples());
4122   std::vector<bool> nodeIdsInUse(nbOfNodes,false);
4123   std::vector<int> neLevs(getNonEmptyLevels());
4124   for(std::vector<int>::const_iterator lev=neLevs.begin();lev!=neLevs.end();lev++)
4125     {
4126       const MEDFileUMeshSplitL1 *zeLev(getMeshAtLevSafe(*lev));
4127       if(zeLev->isMeshStoredSplitByType())
4128         {
4129           std::vector<MEDCoupling1GTUMesh *> ms(zeLev->getDirectUndergroundSingleGeoTypeMeshes());
4130           for(std::vector<MEDCoupling1GTUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
4131             if(*it)
4132               (*it)->computeNodeIdsAlg(nodeIdsInUse);
4133         }
4134       else
4135         {
4136           MCAuto<MEDCouplingUMesh> mesh(zeLev->getWholeMesh(false));
4137           mesh->computeNodeIdsAlg(nodeIdsInUse);
4138         }
4139     }
4140   int nbrOfNodesInUse((int)std::count(nodeIdsInUse.begin(),nodeIdsInUse.end(),true));
4141   if(nbrOfNodesInUse==nbOfNodes)
4142     return 0;//no need to update _part_coords
4143   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodes,1);
4144   std::transform(nodeIdsInUse.begin(),nodeIdsInUse.end(),ret->getPointer(),MEDLoaderAccVisit1());
4145   MCAuto<DataArrayInt> ret2(ret->invertArrayO2N2N2OBis(nbrOfNodesInUse));
4146   MCAuto<DataArrayDouble> newCoords(coo->selectByTupleIdSafe(ret2->begin(),ret2->end()));
4147   MCAuto<DataArrayInt> newFamCoords;
4148   MCAuto<DataArrayAsciiChar> newNameCoords;
4149   if((const DataArrayInt *)_fam_coords)
4150     newFamCoords=_fam_coords->selectByTupleIdSafe(ret2->begin(),ret2->end());
4151   MCAuto<DataArrayInt> newNumCoords;
4152   if((const DataArrayInt *)_num_coords)
4153     newNumCoords=_num_coords->selectByTupleIdSafe(ret2->begin(),ret2->end());
4154   if((const DataArrayAsciiChar *)_name_coords)
4155     newNameCoords=static_cast<DataArrayAsciiChar *>(_name_coords->selectByTupleIdSafe(ret2->begin(),ret2->end()));
4156   _coords=newCoords; _fam_coords=newFamCoords; _num_coords=newNumCoords; _name_coords=newNameCoords; _rev_num_coords=0;
4157   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
4158     {
4159       if((MEDFileUMeshSplitL1*)*it)
4160         {
4161           (*it)->renumberNodesInConn(ret->begin());
4162           (*it)->setCoords(_coords);
4163         }
4164     }
4165   // updates _part_coords
4166   const PartDefinition *pc(_part_coords);
4167   if(pc)
4168     {
4169       MCAuto<PartDefinition> tmpPD(DataArrayPartDefinition::New(ret2));
4170       _part_coords=tmpPD->composeWith(pc);
4171     }
4172   return ret.retn();
4173 }
4174
4175 /*!
4176  * This method is a const method. It computes the minimal set of node ids covered by the cell extraction of \a this.
4177  * The extraction of \a this is specified by the extractDef \a input map.
4178  * This map tells for each level of cells, the cells kept in the extraction.
4179  * 
4180  * \return - a new reference of DataArrayInt that represents sorted node ids, the extraction is lying on.
4181  * \sa MEDFileField1TS::extractPart, MEDFileUMesh::extractPart
4182  */
4183 DataArrayInt *MEDFileUMesh::deduceNodeSubPartFromCellSubPart(const std::map<int, MCAuto<DataArrayInt> >& extractDef) const
4184 {
4185   std::vector<int> levs(getNonEmptyLevels());
4186   std::vector<bool> fetchedNodes(getNumberOfNodes(),false);
4187   for(std::map<int, MCAuto<DataArrayInt> >::const_iterator it=extractDef.begin();it!=extractDef.end();it++)
4188     {
4189       if((*it).first>1)
4190         throw INTERP_KERNEL::Exception("MEDFileUMesh::deduceNodeSubPartFromCellSubPart : invalid key ! Must be <=1 !");
4191       if((*it).second.isNull())
4192         throw INTERP_KERNEL::Exception("MEDFileUMesh::deduceNodeSubPartFromCellSubPart : presence of a value with null pointer !");
4193       if((*it).first==1)
4194         continue;
4195       if(std::find(levs.begin(),levs.end(),(*it).first)==levs.end())
4196         {
4197           std::ostringstream oss; oss << "MEDFileUMesh::deduceNodeSubPartFromCellSubPart : invalid level " << (*it).first << " ! Not present in this !";
4198           throw INTERP_KERNEL::Exception(oss.str());
4199         }
4200       MCAuto<MEDCouplingUMesh> m(getMeshAtLevel((*it).first));
4201       MCAuto<MEDCouplingUMesh> mPart(m->buildPartOfMySelf((*it).second->begin(),(*it).second->end(),true));
4202       mPart->computeNodeIdsAlg(fetchedNodes);
4203     }
4204   return DataArrayInt::BuildListOfSwitchedOn(fetchedNodes);
4205 }
4206
4207 /*!
4208  * This method returns a new MEDFileUMesh that is the result of the extraction of cells/nodes in \a this.
4209  * 
4210  * \return - a new reference of MEDFileUMesh
4211  * \sa MEDFileUMesh::deduceNodeSubPartFromCellSubPart, MEDFileFields::extractPart
4212  */
4213 MEDFileUMesh *MEDFileUMesh::extractPart(const std::map<int, MCAuto<DataArrayInt> >& extractDef) const
4214 {
4215   MCAuto<MEDFileUMesh> ret(MEDFileUMesh::New()); ret->setName(getName()); ret->copyFamGrpMapsFrom(*this);
4216   std::vector<int> levs(getNonEmptyLevels());
4217   for(std::map<int, MCAuto<DataArrayInt> >::const_iterator it=extractDef.begin();it!=extractDef.end();it++)
4218     {
4219       if((*it).first>1)
4220         throw INTERP_KERNEL::Exception("MEDFileUMesh::extractPart : invalid key ! Must be <=1 !");
4221       if((*it).second.isNull())
4222         throw INTERP_KERNEL::Exception("MEDFileUMesh::extractPart : presence of a value with null pointer !");
4223       if((*it).first==1)
4224         continue;
4225       if(std::find(levs.begin(),levs.end(),(*it).first)==levs.end())
4226         {
4227           std::ostringstream oss; oss << "MEDFileUMesh::extractPart : invalid level " << (*it).first << " ! Not present in this !";
4228           throw INTERP_KERNEL::Exception(oss.str());
4229         }
4230       MCAuto<MEDCouplingUMesh> m(getMeshAtLevel((*it).first));
4231       MCAuto<MEDCouplingUMesh> mPart(m->buildPartOfMySelf((*it).second->begin(),(*it).second->end(),true));
4232       ret->setMeshAtLevel((*it).first,mPart);
4233       const DataArrayInt *fam(getFamilyFieldAtLevel((*it).first)),*num(getNumberFieldAtLevel((*it).first));
4234       if(fam)
4235         {
4236           MCAuto<DataArrayInt> famPart(fam->selectByTupleIdSafe((*it).second->begin(),(*it).second->end()));
4237           ret->setFamilyFieldArr((*it).first,famPart);
4238         }
4239       if(num)
4240         {
4241           MCAuto<DataArrayInt> numPart(num->selectByTupleIdSafe((*it).second->begin(),(*it).second->end()));
4242           ret->setFamilyFieldArr((*it).first,numPart);
4243         }
4244     }
4245   std::map<int, MCAuto<DataArrayInt> >::const_iterator it2(extractDef.find(1));
4246   if(it2!=extractDef.end())
4247     {
4248       const DataArrayDouble *coo(ret->getCoords());
4249       if(!coo)
4250         throw INTERP_KERNEL::Exception("MEDFileUMesh::extractPart : trying to extract nodes whereas there is no nodes !");
4251       MCAuto<DataArrayInt> o2nNodes(((*it2).second)->invertArrayN2O2O2N(coo->getNumberOfTuples()));
4252       MCAuto<DataArrayDouble> cooPart(coo->selectByTupleIdSafe((*it2).second->begin(),(*it2).second->end()));
4253       ret->setCoords(cooPart);
4254       const DataArrayInt *fam(getFamilyFieldAtLevel(1)),*num(getNumberFieldAtLevel(1));
4255       if(fam)
4256         {
4257           MCAuto<DataArrayInt> famPart(fam->selectByTupleIdSafe((*it2).second->begin(),(*it2).second->end()));
4258           ret->setFamilyFieldArr(1,famPart);
4259         }
4260       if(num)
4261         {
4262           MCAuto<DataArrayInt> numPart(num->selectByTupleIdSafe((*it2).second->begin(),(*it2).second->end()));
4263           ret->setFamilyFieldArr(1,numPart);
4264         }
4265       for(std::map<int, MCAuto<DataArrayInt> >::const_iterator it3=extractDef.begin();it3!=extractDef.end();it3++)
4266         {
4267           if((*it3).first==1)
4268             continue;
4269           MCAuto<MEDCouplingUMesh> m(ret->getMeshAtLevel((*it3).first));
4270           m->renumberNodesInConn(o2nNodes->begin());
4271           ret->setMeshAtLevel((*it3).first,m);
4272         }
4273     }
4274   return ret.retn();
4275 }
4276
4277 /*!
4278  * This method performs an extrusion along a path defined by \a m1D.
4279  * \a this is expected to be a mesh with max mesh dimension equal to 2.
4280  * \a m1D is expected to be a mesh with space dimesion equal to 3 and mesh dimension equal to 1.
4281  * Mesh dimensions of returned mesh is incremented by one compared to thoose in \a this.
4282  * This method scans all levels in \a this
4283  * and put them in the returned mesh. All groups in \a this are also put in the returned mesh.
4284  *
4285  * \param [in] m1D - the mesh defining the extrusion path.
4286  * \param [in] policy - defines the policy of extrusion (see MEDCouplingUMesh::buildExtrudedMesh for more details)
4287  * \return - a new reference on mesh (you have to deal with using decrRef). The returned mesh will have the same name than \a this.
4288  *
4289  * \sa MEDCouplingUMesh::buildExtrudedMesh
4290  */
4291 MEDFileUMesh *MEDFileUMesh::buildExtrudedMesh(const MEDCouplingUMesh *m1D, int policy) const
4292 {
4293   checkCartesian();
4294   if(getMeshDimension()!=2)
4295     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildExtrudedMesh : this is expected to be with mesh dimension equal to 2 !");
4296   MCAuto<MEDFileUMesh> ret(MEDFileUMesh::New());
4297   m1D->checkConsistencyLight();
4298   if(m1D->getMeshDimension()!=1)
4299     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildExtrudedMesh : input mesh must have a mesh dimension equal to one !");
4300   int nbRep(m1D->getNumberOfCells());
4301   std::vector<int> levs(getNonEmptyLevels());
4302   std::vector<std::string> grps(getGroupsNames());
4303   std::vector< MCAuto<MEDCouplingUMesh> > zeList;
4304   DataArrayDouble *coords(0);
4305   std::size_t nbOfLevsOut(levs.size()+1);
4306   std::vector< MCAuto<DataArrayInt> > o2ns(nbOfLevsOut);
4307   for(std::vector<int>::const_iterator lev=levs.begin();lev!=levs.end();lev++)
4308     {
4309       MCAuto<MEDCouplingUMesh> item(getMeshAtLevel(*lev));
4310       item=item->clone(false);
4311       item->changeSpaceDimension(3+(*lev),0.);//no problem non const but change DataArrayDouble for coordinates do not alter data
4312       MCAuto<MEDCouplingUMesh> tmp(static_cast<MEDCouplingUMesh *>(m1D->deepCopy()));
4313       tmp->changeSpaceDimension(3+(*lev),0.);
4314       MCAuto<MEDCouplingUMesh> elt(item->buildExtrudedMesh(tmp,policy));
4315       zeList.push_back(elt);
4316       if(*lev==0)
4317         coords=elt->getCoords();
4318     }
4319   if(!coords)
4320     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildExtrudedMesh : internal error !");
4321   for(std::vector< MCAuto<MEDCouplingUMesh> >::iterator it=zeList.begin();it!=zeList.end();it++)
4322     {
4323       (*it)->setName(getName());
4324       (*it)->setCoords(coords);
4325     }
4326   for(std::size_t ii=0;ii!=zeList.size();ii++)
4327     {
4328       int lev(levs[ii]);
4329       MCAuto<MEDCouplingUMesh> elt(zeList[ii]);
4330       if(lev<=-1)
4331         {
4332           MCAuto<MEDCouplingUMesh> elt1(getMeshAtLevel(lev+1));
4333           MCAuto<MEDCouplingUMesh> elt2(elt1->clone(false));
4334           MCAuto<DataArrayInt> tmp(elt2->getNodalConnectivity()->deepCopy());
4335           elt2->setConnectivity(tmp,elt2->getNodalConnectivityIndex());
4336           elt2->shiftNodeNumbersInConn(nbRep*elt1->getNumberOfNodes());
4337           elt1->setCoords(elt->getCoords()); elt2->setCoords(elt->getCoords());
4338           std::vector<const MEDCouplingUMesh *> elts(3);
4339           elts[0]=elt; elts[1]=elt1; elts[2]=elt2;
4340           elt=MEDCouplingUMesh::MergeUMeshesOnSameCoords(elts);
4341           elt->setName(getName());
4342         }
4343       //
4344       o2ns[ii]=elt->sortCellsInMEDFileFrmt();
4345       ret->setMeshAtLevel(lev,elt);
4346     }
4347   MCAuto<MEDCouplingUMesh> endLev(getMeshAtLevel(levs.back())),endLev2;
4348   endLev=endLev->clone(false); endLev->setCoords(coords);
4349   MCAuto<DataArrayInt> tmp(endLev->getNodalConnectivity()->deepCopy());
4350   endLev2=endLev->clone(false); endLev2->setConnectivity(tmp,endLev->getNodalConnectivityIndex());
4351   endLev2->shiftNodeNumbersInConn(nbRep*getNumberOfNodes());
4352   endLev=MEDCouplingUMesh::MergeUMeshesOnSameCoords(endLev,endLev2);
4353   o2ns[levs.size()]=endLev->sortCellsInMEDFileFrmt();
4354   endLev->setName(getName());
4355   ret->setMeshAtLevel(levs.back()-1,endLev);
4356   //
4357   for(std::size_t ii=0;ii!=zeList.size();ii++)
4358     {
4359       int lev(levs[ii]);
4360       std::vector< MCAuto<DataArrayInt> > outGrps;
4361       std::vector< const DataArrayInt * > outGrps2;
4362       if(lev<=-1)
4363         {
4364           for(std::vector<std::string>::const_iterator grp=grps.begin();grp!=grps.end();grp++)
4365             {
4366               MCAuto<DataArrayInt> grpArr(getGroupArr(lev+1,*grp));
4367               if(!grpArr->empty())
4368                 {
4369                   MCAuto<DataArrayInt> grpArr1(grpArr->deepCopy()),grpArr2(grpArr->deepCopy());
4370                   int offset0(zeList[ii]->getNumberOfCells());
4371                   int offset1(offset0+getNumberOfCellsAtLevel(lev+1));
4372                   grpArr1->applyLin(1,offset0); grpArr2->applyLin(1,offset1);
4373                   std::ostringstream oss; oss << grpArr2->getName() << "_top";
4374                   grpArr2->setName(oss.str());
4375                   grpArr1->transformWithIndArr(o2ns[ii]->begin(),o2ns[ii]->end());
4376                   grpArr2->transformWithIndArr(o2ns[ii]->begin(),o2ns[ii]->end());
4377                   outGrps.push_back(grpArr1); outGrps.push_back(grpArr2);
4378                   outGrps2.push_back(grpArr1); outGrps2.push_back(grpArr2);
4379                 }
4380             }
4381         }
4382       //
4383       for(std::vector<std::string>::const_iterator grp=grps.begin();grp!=grps.end();grp++)
4384         {
4385           MCAuto<DataArrayInt> grpArr(getGroupArr(lev,*grp));
4386           if(!grpArr->empty())
4387             {
4388               int nbCellsB4Extrusion(getNumberOfCellsAtLevel(lev));
4389               std::vector< MCAuto<DataArrayInt> > grpArrs(nbRep);
4390               std::vector< const DataArrayInt *> grpArrs2(nbRep);
4391               for(int iii=0;iii<nbRep;iii++)
4392                 {
4393                   grpArrs[iii]=grpArr->deepCopy(); grpArrs[iii]->applyLin(1,iii*nbCellsB4Extrusion);
4394                   grpArrs2[iii]=grpArrs[iii];
4395                 }
4396               MCAuto<DataArrayInt> grpArrExt(DataArrayInt::Aggregate(grpArrs2));
4397               grpArrExt->transformWithIndArr(o2ns[ii]->begin(),o2ns[ii]->end());
4398               std::ostringstream grpName; grpName << *grp << "_extruded";
4399               grpArrExt->setName(grpName.str());
4400               outGrps.push_back(grpArrExt);
4401               outGrps2.push_back(grpArrExt);
4402             }
4403         }
4404       ret->setGroupsAtLevel(lev,outGrps2);
4405     }
4406   std::vector< MCAuto<DataArrayInt> > outGrps;
4407   std::vector< const DataArrayInt * > outGrps2;
4408   for(std::vector<std::string>::const_iterator grp=grps.begin();grp!=grps.end();grp++)
4409     {
4410       MCAuto<DataArrayInt> grpArr1(getGroupArr(levs.back(),*grp));
4411       if(grpArr1->empty())
4412         continue;
4413       MCAuto<DataArrayInt> grpArr2(grpArr1->deepCopy());
4414       std::ostringstream grpName; grpName << *grp << "_top";
4415       grpArr2->setName(grpName.str());
4416       grpArr2->applyLin(1,getNumberOfCellsAtLevel(levs.back()));
4417       outGrps.push_back(grpArr1); outGrps.push_back(grpArr2);
4418       outGrps2.push_back(grpArr1); outGrps2.push_back(grpArr2);
4419     }
4420   ret->setGroupsAtLevel(levs.back()-1,outGrps2);
4421   return ret.retn();
4422 }
4423
4424 /*!
4425  * This method converts all linear cells in \a this into quadratic cells (following the \a conversionType policy).
4426  * All the cells converted are put in the returned instance. This method applies all the groups and families in \a this to returned instance.
4427  * Groups on nodes and families on nodes are copied directly to the returned instance without transformation.
4428  *
4429  * \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
4430  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
4431  * \param [in] eps - detection threshold for coordinates.
4432  * \return A new instance that is the result of the conversion. The caller has the ownership of this returned instance.
4433  *
4434  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic , quadraticToLinear
4435  */
4436 MEDFileUMesh *MEDFileUMesh::linearToQuadratic(int conversionType, double eps) const
4437 {
4438   checkCartesian();
4439   MCAuto<MEDFileUMesh> ret(MEDFileUMesh::New());
4440   int initialNbNodes(getNumberOfNodes());
4441   MCAuto<MEDCouplingUMesh> m0Tmp(getMeshAtLevel(0));
4442   MCAuto<MEDCouplingUMesh> m0(dynamic_cast<MEDCouplingUMesh *>(m0Tmp->deepCopy()));
4443   {
4444     MCAuto<DataArrayInt> notUsed(m0->convertLinearCellsToQuadratic(conversionType));
4445   }
4446   DataArrayDouble *zeCoords(m0->getCoords());
4447   ret->setMeshAtLevel(0,m0);
4448   std::vector<int> levs(getNonEmptyLevels());
4449   const DataArrayInt *famField(getFamilyFieldAtLevel(0));
4450   if(famField)
4451     {
4452       MCAuto<DataArrayInt> famFieldCpy(famField->deepCopy());
4453       ret->setFamilyFieldArr(0,famFieldCpy);
4454     }
4455   famField=getFamilyFieldAtLevel(1);
4456   if(famField)
4457     {
4458       MCAuto<DataArrayInt> fam(DataArrayInt::New()); fam->alloc(zeCoords->getNumberOfTuples(),1);
4459       fam->fillWithZero();
4460       fam->setPartOfValues1(famField,0,initialNbNodes,1,0,1,1);
4461       ret->setFamilyFieldArr(1,fam);
4462     }
4463   ret->copyFamGrpMapsFrom(*this);
4464   MCAuto<DataArrayDouble> partZeCoords(zeCoords->selectByTupleIdSafeSlice(initialNbNodes,zeCoords->getNumberOfTuples(),1));
4465   for(std::vector<int>::const_iterator lev=levs.begin();lev!=levs.end();lev++)
4466     {
4467       if(*lev==0)
4468         continue;
4469       MCAuto<MEDCouplingUMesh> m1Tmp(getMeshAtLevel(*lev));
4470       MCAuto<MEDCouplingUMesh> m1(dynamic_cast<MEDCouplingUMesh *>(m1Tmp->deepCopy()));
4471       if(m1->getMeshDimension()!=0)
4472         {
4473           {
4474             MCAuto<DataArrayInt> notUsed(m1->convertLinearCellsToQuadratic(conversionType));
4475           }//kill unused notUsed var
4476           MCAuto<DataArrayDouble> m1Coords(m1->getCoords()->selectByTupleIdSafeSlice(initialNbNodes,m1->getNumberOfNodes(),1));
4477           DataArrayInt *b(0);
4478           bool a(partZeCoords->areIncludedInMe(m1Coords,eps,b));
4479           MCAuto<DataArrayInt> bSafe(b);
4480           if(!a)
4481             {
4482               std::ostringstream oss; oss << "MEDFileUMesh::linearCellsToQuadratic : for level " << *lev << " problem to identify nodes generated !";
4483               throw INTERP_KERNEL::Exception(oss.str().c_str());
4484             }
4485           b->applyLin(1,initialNbNodes);
4486           MCAuto<DataArrayInt> l0(DataArrayInt::New()); l0->alloc(initialNbNodes,1); l0->iota();
4487           std::vector<const DataArrayInt *> v(2); v[0]=l0; v[1]=b;
4488           MCAuto<DataArrayInt> renum(DataArrayInt::Aggregate(v));
4489           m1->renumberNodesInConn(renum->begin());
4490         }
4491       m1->setCoords(zeCoords);
4492       ret->setMeshAtLevel(*lev,m1);
4493       famField=getFamilyFieldAtLevel(*lev);
4494       if(famField)
4495         {
4496           MCAuto<DataArrayInt> famFieldCpy(famField->deepCopy());
4497           ret->setFamilyFieldArr(*lev,famFieldCpy);
4498         }
4499     }
4500   return ret.retn();
4501 }
4502
4503 /*!
4504  * This method converts all quadratic cells in \a this into linear cells.
4505  * All the cells converted are put in the returned instance. This method applies all the groups and families in \a this to returned instance.
4506  * Groups on nodes and families on nodes are copied directly to the returned instance without transformation.
4507  *
4508  * \param [in] eps - detection threshold for coordinates.
4509  * \return A new instance that is the result of the conversion. The caller has the ownership of this returned instance.
4510  *
4511  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic , linearToQuadratic
4512  */
4513 MEDFileUMesh *MEDFileUMesh::quadraticToLinear(double eps) const
4514 {
4515   checkCartesian();
4516   MCAuto<MEDFileUMesh> ret(MEDFileUMesh::New());
4517   MCAuto<MEDCouplingUMesh> m0Tmp(getMeshAtLevel(0));
4518   MCAuto<MEDCouplingUMesh> m0(dynamic_cast<MEDCouplingUMesh *>(m0Tmp->deepCopy()));
4519   m0->convertQuadraticCellsToLinear();
4520   m0->zipCoords();
4521   DataArrayDouble *zeCoords(m0->getCoords());
4522   ret->setMeshAtLevel(0,m0);
4523   std::vector<int> levs(getNonEmptyLevels());
4524   const DataArrayInt *famField(getFamilyFieldAtLevel(0));
4525   if(famField)
4526     {
4527       MCAuto<DataArrayInt> famFieldCpy(famField->deepCopy());
4528       ret->setFamilyFieldArr(0,famFieldCpy);
4529     }
4530   famField=getFamilyFieldAtLevel(1);
4531   if(famField)
4532     {
4533       MCAuto<DataArrayInt> fam(famField->selectByTupleIdSafeSlice(0,zeCoords->getNumberOfTuples(),1));
4534       ret->setFamilyFieldArr(1,fam);
4535     }
4536   ret->copyFamGrpMapsFrom(*this);
4537   for(std::vector<int>::const_iterator lev=levs.begin();lev!=levs.end();lev++)
4538     {
4539       if(*lev==0)
4540         continue;
4541       MCAuto<MEDCouplingUMesh> m1Tmp(getMeshAtLevel(*lev));
4542       MCAuto<MEDCouplingUMesh> m1(dynamic_cast<MEDCouplingUMesh *>(m1Tmp->deepCopy()));
4543       m1->convertQuadraticCellsToLinear();
4544       m1->zipCoords();
4545       DataArrayInt *b(0);
4546       bool a(zeCoords->areIncludedInMe(m1->getCoords(),eps,b));
4547       MCAuto<DataArrayInt> bSafe(b);
4548       if(!a)
4549         {
4550           std::ostringstream oss; oss << "MEDFileUMesh::quadraticToLinear : for level " << *lev << " problem to identify nodes generated !";
4551           throw INTERP_KERNEL::Exception(oss.str().c_str());
4552         }
4553       m1->renumberNodesInConn(b->begin());
4554       m1->setCoords(zeCoords);
4555       ret->setMeshAtLevel(*lev,m1);
4556       famField=getFamilyFieldAtLevel(*lev);
4557       if(famField)
4558         {
4559           MCAuto<DataArrayInt> famFieldCpy(famField->deepCopy());
4560           ret->setFamilyFieldArr(*lev,famFieldCpy);
4561         }
4562     }
4563   return ret.retn();
4564 }
4565
4566 /*!
4567  * Computes the symmetry of \a this.
4568  * \return a new object.
4569  */
4570 MCAuto<MEDFileUMesh> MEDFileUMesh::symmetry3DPlane(const double point[3], const double normalVector[3]) const
4571 {
4572   MCAuto<MEDFileUMesh> ret(deepCopy());
4573   DataArrayDouble *myCoo(getCoords());
4574   if(myCoo)
4575     {
4576       MCAuto<DataArrayDouble> newCoo(myCoo->symmetry3DPlane(point,normalVector));
4577       ret->setCoordsForced(newCoo);
4578     }
4579   return ret;
4580 }
4581
4582 MCAuto<MEDFileUMesh> MEDFileUMesh::Aggregate(const std::vector<const MEDFileUMesh *>& meshes)
4583 {
4584   if(meshes.empty())
4585     throw INTERP_KERNEL::Exception("MEDFileUMesh::Aggregate : empty input vector !");
4586   std::size_t sz(meshes.size()),i(0);
4587   std::vector<const DataArrayDouble *> coos(sz);
4588   std::vector<const DataArrayInt *> fam_coos(sz),num_coos(sz);
4589   for(std::vector<const MEDFileUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,i++)
4590     {
4591       if(!(*it))
4592         throw INTERP_KERNEL::Exception("MEDFileUMesh::Aggregate : presence of NULL pointer in input vector !");
4593       coos[i]=(*it)->getCoords();
4594       fam_coos[i]=(*it)->getFamilyFieldAtLevel(1);
4595       num_coos[i]=(*it)->getNumberFieldAtLevel(1);
4596     }
4597   const MEDFileUMesh *ref(meshes[0]);
4598   int spaceDim(ref->getSpaceDimension()),meshDim(ref->getMeshDimension());
4599   std::vector<int> levs(ref->getNonEmptyLevels());
4600   std::map<int, std::vector<const DataArrayInt *> > m_fam,m_renum;
4601   std::map<int, std::vector< MCAuto< MEDCouplingUMesh > > > m_mesh2;
4602   std::map<int, std::vector<const MEDCouplingUMesh *> > m_mesh;
4603   std::map<std::string,int> map1;
4604   std::map<std::string, std::vector<std::string> > map2;
4605   for(std::vector<const MEDFileUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,i++)
4606     {
4607       if((*it)->getSpaceDimension()!=spaceDim)
4608         throw INTERP_KERNEL::Exception("MEDFileUMesh::Aggregate : space dimension must be homogeneous !");
4609       if((*it)->getMeshDimension()!=meshDim)
4610         throw INTERP_KERNEL::Exception("MEDFileUMesh::Aggregate : mesh dimension must be homogeneous !");
4611       if((*it)->getNonEmptyLevels()!=levs)
4612         throw INTERP_KERNEL::Exception("MEDFileUMesh::Aggregate : levels must be the same for elements in input vector !");
4613       for(std::vector<int>::const_iterator it2=levs.begin();it2!=levs.end();it2++)
4614         {
4615           MCAuto<MEDCouplingUMesh> locMesh((*it)->getMeshAtLevel(*it2));
4616           m_mesh[*it2].push_back(locMesh); m_mesh2[*it2].push_back(locMesh);
4617           m_fam[*it2].push_back((*it)->getFamilyFieldAtLevel(*it2));
4618           m_renum[*it2].push_back((*it)->getNumberFieldAtLevel(*it2));
4619         }
4620       const std::map<std::string,int>& locMap1((*it)->getFamilyInfo());
4621       for(std::map<std::string,int>::const_iterator it3=locMap1.begin();it3!=locMap1.end();it3++)
4622         map1[(*it3).first]=(*it3).second;
4623       const std::map<std::string, std::vector<std::string> >& locMap2((*it)->getGroupInfo());
4624       for(std::map<std::string, std::vector<std::string> >::const_iterator it4=locMap2.begin();it4!=locMap2.end();it4++)
4625         map2[(*it4).first]=(*it4).second;
4626     }
4627   // Easy part : nodes
4628   MCAuto<MEDFileUMesh> ret(MEDFileUMesh::New());
4629   MCAuto<DataArrayDouble> coo(DataArrayDouble::Aggregate(coos));
4630   ret->setCoords(coo);
4631   if(std::find(fam_coos.begin(),fam_coos.end(),(const DataArrayInt *)0)==fam_coos.end())
4632     {
4633       MCAuto<DataArrayInt> fam_coo(DataArrayInt::Aggregate(fam_coos));
4634       ret->setFamilyFieldArr(1,fam_coo);
4635     }
4636   if(std::find(num_coos.begin(),num_coos.end(),(const DataArrayInt *)0)==num_coos.end())
4637     {
4638       MCAuto<DataArrayInt> num_coo(DataArrayInt::Aggregate(num_coos));
4639       ret->setRenumFieldArr(1,num_coo);
4640     }
4641   // cells
4642   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
4643     {
4644       std::map<int, std::vector<const MEDCouplingUMesh *> >::const_iterator it2(m_mesh.find(*it));
4645       if(it2==m_mesh.end())
4646         throw INTERP_KERNEL::Exception("MEDFileUMesh::Aggregate : internal error 1 !");
4647       MCAuto<MEDCouplingUMesh> mesh(MEDCouplingUMesh::MergeUMeshes((*it2).second));
4648       mesh->setCoords(coo); mesh->setName(ref->getName());
4649       MCAuto<DataArrayInt> renum(mesh->sortCellsInMEDFileFrmt());
4650       ret->setMeshAtLevel(*it,mesh);
4651       std::map<int, std::vector<const DataArrayInt *> >::const_iterator it3(m_fam.find(*it)),it4(m_renum.find(*it));
4652       if(it3!=m_fam.end())
4653         {
4654           const std::vector<const DataArrayInt *>& fams((*it3).second);
4655           if(std::find(fams.begin(),fams.end(),(const DataArrayInt *)0)==fams.end())
4656             {
4657               MCAuto<DataArrayInt> famm(DataArrayInt::Aggregate(fams));
4658               famm->renumberInPlace(renum->begin());
4659               ret->setFamilyFieldArr(*it,famm);
4660             }
4661         }
4662       if(it4!=m_renum.end())
4663         {
4664           const std::vector<const DataArrayInt *>& renums((*it4).second);
4665           if(std::find(renums.begin(),renums.end(),(const DataArrayInt *)0)==renums.end())
4666             {
4667               MCAuto<DataArrayInt> renumm(DataArrayInt::Aggregate(renums));
4668               renumm->renumberInPlace(renum->begin());
4669               ret->setRenumFieldArr(*it,renumm);
4670             }
4671         }
4672     }
4673   //
4674   ret->setFamilyInfo(map1);
4675   ret->setGroupInfo(map2);
4676   ret->setName(ref->getName());
4677   return ret;
4678 }
4679
4680 MEDCouplingMappedExtrudedMesh *MEDFileUMesh::convertToExtrudedMesh() const
4681 {
4682   if(getMeshDimension()!=3)
4683     throw INTERP_KERNEL::Exception("MEDFileUMesh::convertToExtrudedMesh : works only for 3D mesh !");
4684   MCAuto<MEDCouplingUMesh> m3D(getMeshAtLevel(0)),m2D(getMeshAtLevel(-1));
4685   if(m3D.isNull() || m2D.isNull())
4686     throw INTERP_KERNEL::Exception("MEDFileUMesh::convertToExtrudedMesh : this must be defined both at level 0 and level -1 !");
4687   int zeId(std::numeric_limits<int>::max()-getFamilyId(GetSpeStr4ExtMesh()));
4688   MCAuto<MEDCouplingMappedExtrudedMesh> ret(MEDCouplingMappedExtrudedMesh::New(m3D,m2D,zeId));
4689   return ret.retn();
4690 }
4691
4692 void MEDFileUMesh::serialize(std::vector<double>& tinyDouble, std::vector<int>& tinyInt, std::vector<std::string>& tinyStr, std::vector< MCAuto<DataArrayInt> >& bigArraysI, MCAuto<DataArrayDouble>& bigArrayD)
4693 {
4694   clearNonDiscrAttributes();
4695   forceComputationOfParts();
4696   tinyDouble.clear(); tinyInt.clear(); tinyStr.clear(); bigArraysI.clear(); bigArrayD=0;
4697   std::vector<int> layer0;
4698   layer0.push_back(getAxisType());//0 i
4699   layer0.push_back(_order); //1 i
4700   layer0.push_back(_iteration);//2 i
4701   layer0.push_back(getSpaceDimension());//3 i
4702   tinyDouble.push_back(_time);//0 d
4703   tinyStr.push_back(_name);//0 s
4704   tinyStr.push_back(_desc_name);//1 s
4705   for(int i=0;i<getSpaceDimension();i++)
4706     tinyStr.push_back(_coords->getInfoOnComponent(i));
4707   layer0.push_back((int)_families.size());//4 i <- key info aa layer#0
4708   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
4709     {
4710       tinyStr.push_back((*it).first);
4711       layer0.push_back((*it).second);
4712     }
4713   layer0.push_back((int)_groups.size());//4+aa i <- key info bb layer#0
4714   for(std::map<std::string, std::vector<std::string> >::const_iterator it0=_groups.begin();it0!=_groups.end();it0++)
4715     {
4716       layer0.push_back((int)(*it0).second.size());
4717       tinyStr.push_back((*it0).first);
4718       for(std::vector<std::string>::const_iterator it1=((*it0).second).begin();it1!=((*it0).second).end();it1++)
4719         tinyStr.push_back(*it1);
4720     }
4721   // sizeof(layer0)==4+aa+1+bb layer#0
4722   bigArrayD=_coords;// 0 bd
4723   bigArraysI.push_back(_fam_coords);// 0 bi
4724   bigArraysI.push_back(_num_coords);// 1 bi
4725   const PartDefinition *pd(_part_coords);
4726   if(!pd)
4727     layer0.push_back(-1);
4728   else
4729     {
4730       std::vector<int> tmp0;
4731       pd->serialize(tmp0,bigArraysI);
4732       tinyInt.push_back(tmp0.size());
4733       tinyInt.insert(tinyInt.end(),tmp0.begin(),tmp0.end());
4734     }
4735   //
4736   std::vector<int> layer1;
4737   std::vector<int> levs(getNonEmptyLevels());
4738   layer1.push_back((int)levs.size());// 0 i <- key
4739   layer1.insert(layer1.end(),levs.begin(),levs.end());
4740   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
4741     {
4742       const MEDFileUMeshSplitL1 *lev(getMeshAtLevSafe(*it));
4743       lev->serialize(layer1,bigArraysI);
4744     }
4745   // put layers all together.
4746   tinyInt.push_back(layer0.size());
4747   tinyInt.insert(tinyInt.end(),layer0.begin(),layer0.end());
4748   tinyInt.push_back(layer1.size());
4749   tinyInt.insert(tinyInt.end(),layer1.begin(),layer1.end());
4750 }
4751
4752 void MEDFileUMesh::unserialize(std::vector<double>& tinyDouble, std::vector<int>& tinyInt, std::vector<std::string>& tinyStr,
4753                                std::vector< MCAuto<DataArrayInt> >& bigArraysI, MCAuto<DataArrayDouble>& bigArrayD)
4754 {
4755   int sz0(tinyInt[0]);
4756   std::vector<int> layer0(tinyInt.begin()+1,tinyInt.begin()+1+sz0);
4757   int sz1(tinyInt[sz0+1]);
4758   std::vector<int> layer1(tinyInt.begin()+2+sz0,tinyInt.begin()+2+sz0+sz1);
4759   //
4760   std::reverse(layer0.begin(),layer0.end());
4761   std::reverse(layer1.begin(),layer1.end());
4762   std::reverse(tinyDouble.begin(),tinyDouble.end());
4763   std::reverse(tinyStr.begin(),tinyStr.end());
4764   std::reverse(bigArraysI.begin(),bigArraysI.end());
4765   //
4766   setAxisType((MEDCouplingAxisType)layer0.back()); layer0.pop_back();
4767   _order=layer0.back(); layer0.pop_back();
4768   _iteration=layer0.back(); layer0.pop_back();
4769   int spaceDim(layer0.back()); layer0.pop_back();
4770   _time=tinyDouble.back(); tinyDouble.pop_back();
4771   _name=tinyStr.back(); tinyStr.pop_back();
4772   _desc_name=tinyStr.back(); tinyStr.pop_back();
4773   _coords=bigArrayD; _coords->rearrange(spaceDim);
4774   for(int i=0;i<spaceDim;i++)
4775     {
4776       _coords->setInfoOnComponent(i,tinyStr.back());
4777       tinyStr.pop_back();
4778     }
4779   int nbOfFams(layer0.back()); layer0.pop_back();
4780   _families.clear();
4781   for(int i=0;i<nbOfFams;i++)
4782     {
4783       _families[tinyStr.back()]=layer0.back();
4784       tinyStr.pop_back(); layer0.pop_back();
4785     }
4786   int nbGroups(layer0.back()); layer0.pop_back();
4787   _groups.clear();
4788   for(int i=0;i<nbGroups;i++)
4789     {
4790       std::string grpName(tinyStr.back()); tinyStr.pop_back();
4791       int nbOfFamsOnGrp(layer0.back()); layer0.pop_back();
4792       std::vector<std::string> fams(nbOfFamsOnGrp);
4793       for(int j=0;j<nbOfFamsOnGrp;j++)
4794         {
4795           fams[j]=tinyStr.back(); tinyStr.pop_back();
4796         }
4797       _groups[grpName]=fams;
4798     }
4799   _fam_coords=bigArraysI.back(); bigArraysI.pop_back();
4800   _num_coords=bigArraysI.back(); bigArraysI.pop_back();
4801   _part_coords=0;
4802   int isPd(layer0.back()); layer0.pop_back();
4803   if(isPd!=-1)
4804     {
4805       std::vector<int> tmp0(layer0.begin(),layer0.begin()+isPd);
4806       layer0.erase(layer0.begin(),layer0.begin()+isPd);
4807       _part_coords=PartDefinition::Unserialize(tmp0,bigArraysI);
4808     }
4809   if(!layer0.empty())
4810     throw INTERP_KERNEL::Exception("MEDFileUMesh::unserialize : something wrong during unserialization #1 !");
4811   //
4812   int nbLevs(layer1.back()); layer1.pop_back();
4813   std::vector<int> levs(layer1.rbegin(),layer1.rbegin()+nbLevs); layer1.erase(layer1.end()-nbLevs,layer1.end());
4814   _ms.clear();
4815   int maxLev(-(*std::min_element(levs.begin(),levs.end())));
4816   _ms.resize(maxLev+1);
4817   for(int i=0;i<nbLevs;i++)
4818     {
4819       int lev(levs[i]);
4820       int pos(-lev);
4821       _ms[pos]=MEDFileUMeshSplitL1::Unserialize(_name,_coords,layer1,bigArraysI);
4822     }
4823 }
4824
4825 /*!
4826  * Adds a group of nodes to \a this mesh.
4827  *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
4828  *          The ids should be sorted and different each other (MED file norm).
4829  *
4830  *  \warning this method can alter default "FAMILLE_ZERO" family.
4831  *  For users sensitive to this a call to MEDFileMesh::rearrangeFamilies will be necessary after addGroup session.
4832  *
4833  *  \throw If the node coordinates array is not set.
4834  *  \throw If \a ids == \c NULL.
4835  *  \throw If \a ids->getName() == "".
4836  *  \throw If \a ids does not respect the MED file norm.
4837  *  \throw If a group with name \a ids->getName() already exists.
4838  */
4839 void MEDFileUMesh::addNodeGroup(const DataArrayInt *ids)
4840 {
4841   const DataArrayDouble *coords(_coords);
4842   if(!coords)
4843     throw INTERP_KERNEL::Exception("MEDFileUMesh::addNodeGroup : no coords set !");
4844   int nbOfNodes(coords->getNumberOfTuples());
4845   if(!((DataArrayInt *)_fam_coords))
4846     { _fam_coords=DataArrayInt::New(); _fam_coords->alloc(nbOfNodes,1); _fam_coords->fillWithZero(); }
4847   //
4848   addGroupUnderground(true,ids,_fam_coords);
4849 }
4850
4851 /*!
4852  * Adds a group of nodes/cells/faces/edges to \a this mesh.
4853  *
4854  *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
4855  *          The ids should be sorted and different each other (MED file norm).
4856  *
4857  * \warning this method can alter default "FAMILLE_ZERO" family.
4858  * For users sensitive to this a call to MEDFileMesh::rearrangeFamilies will be necessary after addGroup session.
4859  *
4860  *  \throw If the node coordinates array is not set.
4861  *  \throw If \a ids == \c NULL.
4862  *  \throw If \a ids->getName() == "".
4863  *  \throw If \a ids does not respect the MED file norm.
4864  *  \throw If a group with name \a ids->getName() already exists.
4865  */
4866 void MEDFileUMesh::addGroup(int meshDimRelToMaxExt, const DataArrayInt *ids)
4867 {
4868   std::vector<int> levs(getNonEmptyLevelsExt());
4869   if(std::find(levs.begin(),levs.end(),meshDimRelToMaxExt)==levs.end())
4870     { 
4871       std::ostringstream oss; oss << "MEDFileUMesh::addGroup : level " << meshDimRelToMaxExt << " not available ! Should be in ";
4872       std::copy(levs.begin(),levs.end(),std::ostream_iterator<int>(oss," ")); oss << " !"; throw INTERP_KERNEL::Exception(oss.str().c_str());
4873     }
4874   if(meshDimRelToMaxExt==1)
4875     { addNodeGroup(ids); return ; }
4876   MEDFileUMeshSplitL1 *lev(getMeshAtLevSafe(meshDimRelToMaxExt));
4877   DataArrayInt *fam(lev->getOrCreateAndGetFamilyField());
4878   addGroupUnderground(false,ids,fam);
4879 }
4880
4881 /*!
4882  * Changes a name of a family specified by its id.
4883  *  \param [in] id - the id of the family of interest.
4884  *  \param [in] newFamName - the new family name.
4885  *  \throw If no family with the given \a id exists.
4886  */
4887 void MEDFileUMesh::setFamilyNameAttachedOnId(int id, const std::string& newFamName)
4888 {
4889   std::string oldName=getFamilyNameGivenId(id);
4890   _families.erase(oldName);
4891   _families[newFamName]=id;
4892 }
4893
4894 /*!
4895  * Removes a mesh of a given dimension.
4896  *  \param [in] meshDimRelToMax - the relative dimension of interest.
4897  *  \throw If there is no mesh at level \a meshDimRelToMax in \a this mesh.
4898  */
4899 void MEDFileUMesh::removeMeshAtLevel(int meshDimRelToMax)
4900 {
4901   std::vector<int> levSet=getNonEmptyLevels();
4902   std::vector<int>::const_iterator it=std::find(levSet.begin(),levSet.end(),meshDimRelToMax);
4903   if(it==levSet.end())
4904     throw INTERP_KERNEL::Exception("MEDFileUMesh::removeMeshAtLevel : the requested level is not existing !");
4905   int pos=(-meshDimRelToMax);
4906   _ms[pos]=0;
4907 }
4908
4909 /*!
4910  * Sets a new MEDCoupling1GTUMesh at a given level in \a this mesh.
4911  *  \param [in] meshDimRelToMax - a relative level to set the mesh at.
4912  *  \param [in] m - the new mesh to set.
4913  *  \throw If the name or the description of \a this mesh and \a m are not empty and are
4914  *         different. 
4915  *  \throw If the node coordinates array is set \a this in mesh and \a m refers to
4916  *         another node coordinates array.
4917  *  \throw If the mesh dimension of \a m does not correspond to \a meshDimRelToMax or
4918  *         to the existing meshes of other levels of \a this mesh.
4919  */
4920 void MEDFileUMesh::setMeshAtLevel(int meshDimRelToMax, MEDCoupling1GTUMesh *m)
4921 {
4922   MCAuto<MEDFileUMeshSplitL1> elt(new MEDFileUMeshSplitL1(m));
4923   checkAndGiveEntryInSplitL1(meshDimRelToMax,m)=elt;
4924 }
4925
4926 /*!
4927  * Sets a new MEDCouplingUMesh at a given level in \a this mesh.
4928  *  \param [in] meshDimRelToMax - a relative level to set the mesh at.
4929  *  \param [in] m - the new mesh to set.
4930  *  \param [in] newOrOld - if \c true, cells in \a m are sorted by type to be ready for 
4931  *         writing \a this mesh in a MED file.
4932  *  \throw If the name or the description of \a this mesh and \a m are not empty and are
4933  *         different. 
4934  *  \throw If the node coordinates array is set \a this in mesh and \a m refers to
4935  *         another node coordinates array.
4936  *  \throw If the mesh dimension of \a m does not correspond to \a meshDimRelToMax or
4937  *         to the existing meshes of other levels of \a this mesh.
4938  */
4939 void MEDFileUMesh::setMeshAtLevel(int meshDimRelToMax, MEDCouplingUMesh *m, bool newOrOld)
4940 {
4941   MCAuto<MEDFileUMeshSplitL1> elt(new MEDFileUMeshSplitL1(m,newOrOld));
4942   checkAndGiveEntryInSplitL1(meshDimRelToMax,m)=elt;
4943 }
4944
4945 MCAuto<MEDFileUMeshSplitL1>& MEDFileUMesh::checkAndGiveEntryInSplitL1(int meshDimRelToMax, MEDCouplingPointSet *m)
4946 {
4947   dealWithTinyInfo(m);
4948   std::vector<int> levSet=getNonEmptyLevels();
4949   if(std::find(levSet.begin(),levSet.end(),meshDimRelToMax)==levSet.end())
4950     {
4951       if((DataArrayDouble *)_coords==0)
4952         {
4953           DataArrayDouble *c=m->getCoords();
4954           if(c)
4955             c->incrRef();
4956           _coords=c;
4957         }
4958       if(m->getCoords()!=_coords)
4959         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshAtLevel : Invalid Given Mesh ! The coordinates are not the same ! try to use tryToShareSameCoords !");
4960       int sz=(-meshDimRelToMax)+1;
4961       if(sz>=(int)_ms.size())
4962         _ms.resize(sz);
4963       checkMeshDimCoherency(m->getMeshDimension(),meshDimRelToMax);
4964       return _ms[sz-1];
4965     }
4966   else
4967     return _ms[-meshDimRelToMax];
4968 }
4969
4970 /*!
4971  * This method allows to set at once the content of different levels in \a this.
4972  * This method is equivalent to a series of call to MEDFileUMesh::setMeshAtLevel.
4973  *
4974  * \param [in] ms - List of unstructured meshes lying on the same coordinates and having different mesh dimesnion.
4975  * \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.
4976  *                     If false, an exception ois thrown. If true the mesh is reordered automatically. It is highly recommanded to let this parameter to false.
4977  *
4978  * \throw If \a there is a null pointer in \a ms.
4979  * \sa MEDFileUMesh::setMeshAtLevel
4980  */
4981 void MEDFileUMesh::setMeshes(const std::vector<const MEDCouplingUMesh *>& ms, bool renum)
4982 {
4983   if(ms.empty())
4984     return ;
4985   const MEDCouplingUMesh *mRef=ms[0];
4986   if(!mRef)
4987     throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : null instance in the first element of input meshes !");
4988   std::string name(mRef->getName());
4989   const DataArrayDouble *coo(mRef->getCoords());
4990   std::set<int> s;
4991   int zeDim=-1;
4992   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
4993     {
4994       const MEDCouplingUMesh *cur(*it);
4995       if(!cur)
4996         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : null instance in input vector of meshes !");
4997       if(coo!=cur->getCoords())
4998         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : The input meshes do not share the same coordinates !");
4999       int mdim=cur->getMeshDimension();
5000       zeDim=std::max(zeDim,mdim);
5001       if(s.find(mdim)!=s.end())
5002         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : The input meshes must share the same coordinates pointer, and should have different mesh dimension each other !");
5003     }
5004   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
5005     {
5006       int mdim=(*it)->getMeshDimension();
5007       setName((*it)->getName());
5008       setMeshAtLevel(mdim-zeDim,const_cast<MEDCouplingUMesh *>(*it),renum);
5009     }
5010   setName(name);
5011 }
5012
5013 /*!
5014  * Creates one MEDCouplingUMesh at a given level in \a this mesh from a sequence of
5015  * meshes each representing a group, and creates corresponding groups in \a this mesh.
5016  * The given meshes must share the same node coordinates array.
5017  *  \param [in] meshDimRelToMax - the relative dimension to create the mesh and groups at.
5018  *  \param [in] ms - the sequence of meshes. Each mesh in \a ms represents a group to
5019  *          create in \a this mesh.
5020  *  \throw If \a ms is empty.
5021  *  \throw If dimension of meshes in \a ms does not correspond to \a meshDimRelToMax or
5022  *         to the existing meshes of other levels of \a this mesh.
5023  *  \throw If the meshes in \a ms do not share the same node coordinates array.
5024  *  \throw If the node coordinates array of \a this mesh (if any) is not the same as that
5025  *         of the given meshes.
5026  *  \throw If \a ms[ i ] is not well defined (MEDCouplingUMesh::checkConsistencyLight()).
5027  *  \throw If names of some meshes in \a ms are equal.
5028  *  \throw If \a ms includes a mesh with an empty name.
5029  */
5030 void MEDFileUMesh::setGroupsFromScratch(int meshDimRelToMax, const std::vector<const MEDCouplingUMesh *>& ms, bool renum)
5031 {
5032   if(ms.empty())
5033     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsFromScratch : expecting a non empty vector !");
5034   int sz=(-meshDimRelToMax)+1;
5035   if(sz>=(int)_ms.size())
5036     _ms.resize(sz);
5037   checkMeshDimCoherency(ms[0]->getMeshDimension(),meshDimRelToMax);
5038   DataArrayDouble *coo=checkMultiMesh(ms);
5039   if((DataArrayDouble *)_coords==0)
5040     {
5041       coo->incrRef();
5042       _coords=coo;
5043     }
5044   else
5045     if((DataArrayDouble *)_coords!=coo)
5046       throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsFromScratch : coordinates mismatches !");
5047   std::vector<DataArrayInt *> corr;
5048   MCAuto<MEDCouplingUMesh> m=MEDCouplingUMesh::FuseUMeshesOnSameCoords(ms,_zipconn_pol,corr);
5049   std::vector< MCAuto<DataArrayInt> > corr3(corr.begin(),corr.end());
5050   setMeshAtLevel(meshDimRelToMax,m,renum);
5051   std::vector<const DataArrayInt *> corr2(corr.begin(),corr.end());
5052   setGroupsAtLevel(meshDimRelToMax,corr2,true);
5053 }
5054
5055 /*!
5056  * Creates groups at a given level in \a this mesh from a sequence of
5057  * meshes each representing a group.
5058  * The given meshes must share the same node coordinates array.
5059  *  \param [in] meshDimRelToMax - the relative dimension to create the groups at.
5060  *  \param [in] ms - the sequence of meshes. Each mesh in \a ms represents a group to
5061  *         create in \a this mesh.
5062  *  \param [in] renum - if \c true, then the optional numbers of entities are taken into
5063  *         account. 
5064  *  \throw If \a ms is empty.
5065  *  \throw If dimension of meshes in \a ms does not correspond to \a meshDimRelToMax or
5066  *         to the existing meshes of other levels of \a this mesh.
5067  *  \throw If the meshes in \a ms do not share the same node coordinates array.
5068  *  \throw If the node coordinates array of \a this mesh (if any) is not the same as that
5069  *         of the given meshes.
5070  *  \throw If \a ms[ i ] is not well defined (MEDCouplingUMesh::checkConsistencyLight()).
5071  *  \throw If names of some meshes in \a ms are equal.
5072  *  \throw If \a ms includes a mesh with an empty name.
5073  */
5074 void MEDFileUMesh::setGroupsOnSetMesh(int meshDimRelToMax, const std::vector<const MEDCouplingUMesh *>& ms, bool renum)
5075 {
5076   if(ms.empty())
5077     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsOnSetMesh : expecting a non empty vector !");
5078   int sz=(-meshDimRelToMax)+1;
5079   if(sz>=(int)_ms.size())
5080     _ms.resize(sz);
5081   checkMeshDimCoherency(ms[0]->getMeshDimension(),meshDimRelToMax);
5082   DataArrayDouble *coo=checkMultiMesh(ms);
5083   if((DataArrayDouble *)_coords==0)
5084     {
5085       coo->incrRef();
5086       _coords=coo;
5087     }
5088   else
5089     if((DataArrayDouble *)_coords!=coo)
5090       throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsOnSetMesh : coordinates mismatches !");
5091   MEDCouplingUMesh *m=getMeshAtLevel(meshDimRelToMax,renum);
5092   std::vector< MCAuto<DataArrayInt> > corr(ms.size());
5093   int i=0;
5094   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++,i++)
5095     {
5096       DataArrayInt *arr=0;
5097       bool test=m->areCellsIncludedIn(*it,_zipconn_pol,arr);
5098       corr[i]=arr;
5099       if(!test)
5100         {
5101           std::ostringstream oss; oss << "MEDFileUMesh::setGroupsOnSetMesh : mesh #" << i << " is not part of whole mesh !";
5102           throw INTERP_KERNEL::Exception(oss.str().c_str());
5103         }
5104     }
5105   std::vector<const DataArrayInt *> corr2(corr.begin(),corr.end());
5106   setGroupsAtLevel(meshDimRelToMax,corr2,renum);
5107 }
5108
5109 DataArrayDouble *MEDFileUMesh::checkMultiMesh(const std::vector<const MEDCouplingUMesh *>& ms) const
5110 {
5111   const DataArrayDouble *ret=ms[0]->getCoords();
5112   int mdim=ms[0]->getMeshDimension();
5113   for(unsigned int i=1;i<ms.size();i++)
5114     {
5115       ms[i]->checkConsistencyLight();
5116       if(ms[i]->getCoords()!=ret)
5117         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMultiMesh : meshes must share the same coords !");
5118       if(ms[i]->getMeshDimension()!=mdim)
5119         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMultiMesh : meshes have not same mesh dimension !");
5120     }
5121   return const_cast<DataArrayDouble *>(ret);
5122 }
5123
5124 /*!
5125  * Sets the family field of a given relative dimension.
5126  *  \param [in] meshDimRelToMaxExt - the relative dimension of entities for which
5127  *          the family field is set.
5128  *  \param [in] famArr - the array of the family field.
5129  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5130  *  \throw If \a famArr has an invalid size.
5131  */
5132 void MEDFileUMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr)
5133 {
5134   if(meshDimRelToMaxExt==1)
5135     {
5136       if(!famArr)
5137         {
5138           _fam_coords=0;
5139           return ;
5140         }
5141       DataArrayDouble *coo(_coords);
5142       if(!coo)
5143         throw INTERP_KERNEL::Exception("MEDFileUMesh::setFamilyFieldArr : the coordinates have not been set !");
5144       famArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),1,"MEDFileUMesh::setFamilyFieldArr : Problem in size of node family arr ! ");
5145       famArr->incrRef();
5146       _fam_coords=famArr;
5147       return ;
5148     }
5149   if(meshDimRelToMaxExt>1)
5150     throw INTERP_KERNEL::Exception("MEDFileUMesh::setFamilyFieldArr : Dimension request is invalid (>1) !");
5151   int traducedRk=-meshDimRelToMaxExt;
5152   if(traducedRk>=(int)_ms.size())
5153     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
5154   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
5155     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
5156   return _ms[traducedRk]->setFamilyArr(famArr);
5157 }
5158
5159 /*!
5160  * Sets the optional numbers of mesh entities of a given dimension.
5161  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5162  *  \param [in] renumArr - the array of the numbers.
5163  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5164  *  \throw If \a renumArr has an invalid size.
5165  */
5166 void MEDFileUMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr)
5167 {
5168   if(meshDimRelToMaxExt==1)
5169     {
5170       if(!renumArr)
5171         {
5172           _num_coords=0;
5173           _rev_num_coords=0;
5174           return ;
5175         }
5176       DataArrayDouble *coo(_coords);
5177       if(!coo)
5178         throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumFieldArr : the coordinates have not been set !");
5179       renumArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),1,"MEDFileUMesh::setRenumArr : Problem in size of node numbering arr ! ");
5180       renumArr->incrRef();
5181       _num_coords=renumArr;
5182       computeRevNum();
5183       return ;
5184     }
5185   if(meshDimRelToMaxExt>1)
5186     throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumArr : Dimension request is invalid (>1) !");
5187   int traducedRk=-meshDimRelToMaxExt;
5188   if(traducedRk>=(int)_ms.size())
5189     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
5190   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
5191     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
5192   return _ms[traducedRk]->setRenumArr(renumArr);
5193 }
5194
5195 /*!
5196  * Sets the optional names of mesh entities of a given dimension.
5197  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5198  *  \param [in] nameArr - the array of the names.
5199  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5200  *  \throw If \a nameArr has an invalid size.
5201  */
5202 void MEDFileUMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr)
5203 {
5204   if(meshDimRelToMaxExt==1)
5205     {
5206       if(!nameArr)
5207         {
5208           _name_coords=0;
5209           return ;
5210         }
5211       DataArrayDouble *coo(_coords);
5212       if(!coo)
5213         throw INTERP_KERNEL::Exception("MEDFileUMesh::setNameFieldAtLevel : the coordinates have not been set !");
5214       nameArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),MED_SNAME_SIZE,"MEDFileUMesh::setNameFieldAtLevel : Problem in size of node numbering arr ! ");
5215       nameArr->incrRef();
5216       _name_coords=nameArr;
5217       return ;
5218     }
5219   if(meshDimRelToMaxExt>1)
5220     throw INTERP_KERNEL::Exception("MEDFileUMesh::setNameFieldAtLevel : Dimension request is invalid (>1) !");
5221   int traducedRk=-meshDimRelToMaxExt;
5222   if(traducedRk>=(int)_ms.size())
5223     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
5224   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
5225     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
5226   return _ms[traducedRk]->setNameArr(nameArr);
5227 }
5228
5229 void MEDFileUMesh::synchronizeTinyInfoOnLeaves() const
5230 {
5231   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
5232     if((const MEDFileUMeshSplitL1 *)(*it))
5233       (*it)->synchronizeTinyInfo(*this);
5234 }
5235
5236 /*!
5237  * This method is called by MEDFileMesh::changeFamilyId. It performs only one part of the family id modification.
5238  */
5239 void MEDFileUMesh::changeFamilyIdArr(int oldId, int newId)
5240 {
5241   DataArrayInt *arr=_fam_coords;
5242   if(arr)
5243     arr->changeValue(oldId,newId);
5244   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
5245     {
5246       MEDFileUMeshSplitL1 *sp=(*it);
5247       if(sp)
5248         {
5249           sp->changeFamilyIdArr(oldId,newId);
5250         }
5251     }
5252 }
5253
5254 std::list< MCAuto<DataArrayInt> > MEDFileUMesh::getAllNonNullFamilyIds() const
5255 {
5256   std::list< MCAuto<DataArrayInt> > ret;
5257   const DataArrayInt *da(_fam_coords);
5258   if(da)
5259     { da->incrRef(); ret.push_back(MCAuto<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
5260   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
5261     {
5262       const MEDFileUMeshSplitL1 *elt(*it);
5263       if(elt)
5264         {
5265           da=elt->getFamilyField();
5266           if(da)
5267             { da->incrRef(); ret.push_back(MCAuto<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
5268         }
5269     }
5270   return ret;
5271 }
5272
5273 void MEDFileUMesh::computeRevNum() const
5274 {
5275   if((const DataArrayInt *)_num_coords)
5276     {
5277       int pos;
5278       int maxValue=_num_coords->getMaxValue(pos);
5279       _rev_num_coords=_num_coords->invertArrayN2O2O2N(maxValue+1);
5280     }
5281 }
5282
5283 std::size_t MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren() const
5284 {
5285   return MEDFileMesh::getHeapMemorySizeWithoutChildren();
5286 }
5287
5288 std::vector<const BigMemoryObject *> MEDFileStructuredMesh::getDirectChildrenWithNull() const
5289 {
5290   std::vector<const BigMemoryObject *> ret(MEDFileMesh::getDirectChildrenWithNull());
5291   ret.push_back((const DataArrayInt *)_fam_nodes);
5292   ret.push_back((const DataArrayInt *)_num_nodes);
5293   ret.push_back((const DataArrayAsciiChar *)_names_nodes);
5294   ret.push_back((const DataArrayInt *)_fam_cells);
5295   ret.push_back((const DataArrayInt *)_num_cells);
5296   ret.push_back((const DataArrayAsciiChar *)_names_cells);
5297   ret.push_back((const DataArrayInt *)_fam_faces);
5298   ret.push_back((const DataArrayInt *)_num_faces);
5299   ret.push_back((const DataArrayInt *)_rev_num_nodes);
5300   ret.push_back((const DataArrayAsciiChar *)_names_faces);
5301   ret.push_back((const DataArrayInt *)_rev_num_cells);
5302   ret.push_back((const MEDCoupling1SGTUMesh*)_faces_if_necessary);
5303   return ret;
5304 }
5305
5306 int MEDFileStructuredMesh::getMaxAbsFamilyIdInArrays() const
5307 {
5308   int ret=-std::numeric_limits<int>::max(),tmp=-1;
5309   if((const DataArrayInt *)_fam_nodes)
5310     {
5311       int val=_fam_nodes->getMaxValue(tmp);
5312       ret=std::max(ret,std::abs(val));
5313     }
5314   if((const DataArrayInt *)_fam_cells)
5315     {
5316       int val=_fam_cells->getMaxValue(tmp);
5317       ret=std::max(ret,std::abs(val));
5318     }
5319   if((const DataArrayInt *)_fam_faces)
5320     {
5321       int val=_fam_faces->getMaxValue(tmp);
5322       ret=std::max(ret,std::abs(val));
5323     }
5324   return ret;
5325 }
5326
5327 int MEDFileStructuredMesh::getMaxFamilyIdInArrays() const
5328 {
5329   int ret=-std::numeric_limits<int>::max(),tmp=-1;
5330   if((const DataArrayInt *)_fam_nodes)
5331     {
5332       int val=_fam_nodes->getMaxValue(tmp);
5333       ret=std::max(ret,val);
5334     }
5335   if((const DataArrayInt *)_fam_cells)
5336     {
5337       int val=_fam_cells->getMaxValue(tmp);
5338       ret=std::max(ret,val);
5339     }
5340   if((const DataArrayInt *)_fam_faces)
5341     {
5342       int val=_fam_faces->getMaxValue(tmp);
5343       ret=std::max(ret,val);
5344     }
5345   return ret;
5346 }
5347
5348 int MEDFileStructuredMesh::getMinFamilyIdInArrays() const
5349 {
5350   int ret=std::numeric_limits<int>::max(),tmp=-1;
5351   if((const DataArrayInt *)_fam_nodes)
5352     {
5353       int val=_fam_nodes->getMinValue(tmp);
5354       ret=std::min(ret,val);
5355     }
5356   if((const DataArrayInt *)_fam_cells)
5357     {
5358       int val=_fam_cells->getMinValue(tmp);
5359       ret=std::min(ret,val);
5360     }
5361   if((const DataArrayInt *)_fam_faces)
5362     {
5363       int val=_fam_faces->getMinValue(tmp);
5364       ret=std::min(ret,val);
5365     }
5366   return ret;
5367 }
5368
5369 bool MEDFileStructuredMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
5370 {
5371   if(!MEDFileMesh::isEqual(other,eps,what))
5372     return false;
5373   const MEDFileStructuredMesh *otherC=dynamic_cast<const  MEDFileStructuredMesh *>(other);
5374   if(!otherC)
5375     {
5376       what="Mesh types differ ! This is structured and other is NOT !";
5377       return false;
5378     }
5379   const DataArrayInt *famc1=_fam_nodes;
5380   const DataArrayInt *famc2=otherC->_fam_nodes;
5381   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
5382     {
5383       what="Mismatch of families arr on nodes ! One is defined and not other !";
5384       return false;
5385     }
5386   if(famc1)
5387     {
5388       bool ret=famc1->isEqual(*famc2);
5389       if(!ret)
5390         {
5391           what="Families arr on nodes differ !";
5392           return false;
5393         }
5394     }
5395   famc1=_fam_cells;
5396   famc2=otherC->_fam_cells;
5397   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
5398     {
5399       what="Mismatch of families arr on cells ! One is defined and not other !";
5400       return false;
5401     }
5402   if(famc1)
5403     {
5404       bool ret=famc1->isEqual(*famc2);
5405       if(!ret)
5406         {
5407           what="Families arr on cells differ !";
5408           return false;
5409         }
5410     }
5411   famc1=_fam_faces;
5412   famc2=otherC->_fam_faces;
5413   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
5414     {
5415       what="Mismatch of families arr on faces ! One is defined and not other !";
5416       return false;
5417     }
5418   if(famc1)
5419     {
5420       bool ret=famc1->isEqual(*famc2);
5421       if(!ret)
5422         {
5423           what="Families arr on faces differ !";
5424           return false;
5425         }
5426     }
5427   famc1=_num_nodes;
5428   famc2=otherC->_num_nodes;
5429   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
5430     {
5431       what="Mismatch of numbering arr on nodes ! One is defined and not other !";
5432       return false;
5433     }
5434   if(famc1)
5435     {
5436       bool ret=famc1->isEqual(*famc2);
5437       if(!ret)
5438         {
5439           what="Numbering arr on nodes differ !";
5440           return false;
5441         }
5442     }
5443   famc1=_num_cells;
5444   famc2=otherC->_num_cells;
5445   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
5446     {
5447       what="Mismatch of numbering arr on cells ! One is defined and not other !";
5448       return false;
5449     }
5450   if(famc1)
5451     {
5452       bool ret=famc1->isEqual(*famc2);
5453       if(!ret)
5454         {
5455           what="Numbering arr on cells differ !";
5456           return false;
5457         }
5458     }
5459   famc1=_num_faces;
5460   famc2=otherC->_num_faces;
5461   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
5462     {
5463       what="Mismatch of numbering arr on faces ! One is defined and not other !";
5464       return false;
5465     }
5466   if(famc1)
5467     {
5468       bool ret=famc1->isEqual(*famc2);
5469       if(!ret)
5470         {
5471           what="Numbering arr on faces differ !";
5472           return false;
5473         }
5474     }
5475   const DataArrayAsciiChar *d1=_names_cells;
5476   const DataArrayAsciiChar *d2=otherC->_names_cells;
5477   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
5478     {
5479       what="Mismatch of naming arr on cells ! One is defined and not other !";
5480       return false;
5481     }
5482   if(d1)
5483     {
5484       bool ret=d1->isEqual(*d2);
5485       if(!ret)
5486         {
5487           what="Naming arr on cells differ !";
5488           return false;
5489         }
5490     }
5491   d1=_names_faces;
5492   d2=otherC->_names_faces;
5493   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
5494     {
5495       what="Mismatch of naming arr on faces ! One is defined and not other !";
5496       return false;
5497     }
5498   if(d1)
5499     {
5500       bool ret=d1->isEqual(*d2);
5501       if(!ret)
5502         {
5503           what="Naming arr on faces differ !";
5504           return false;
5505         }
5506     }
5507   d1=_names_nodes;
5508   d2=otherC->_names_nodes;
5509   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
5510     {
5511       what="Mismatch of naming arr on nodes ! One is defined and not other !";
5512       return false;
5513     }
5514   if(d1)
5515     {
5516       bool ret=d1->isEqual(*d2);
5517       if(!ret)
5518         {
5519           what="Naming arr on nodes differ !";
5520           return false;
5521         }
5522     }
5523   return true;
5524 }
5525
5526 void MEDFileStructuredMesh::clearNonDiscrAttributes() const
5527 {
5528   MEDFileMesh::clearNonDiscrAttributes();
5529   const DataArrayInt *tmp=_fam_nodes;
5530   if(tmp)
5531     (const_cast<DataArrayInt *>(tmp))->setName("");
5532   tmp=_num_nodes;
5533   if(tmp)
5534     (const_cast<DataArrayInt *>(tmp))->setName("");
5535   tmp=_fam_cells;
5536   if(tmp)
5537     (const_cast<DataArrayInt *>(tmp))->setName("");
5538   tmp=_num_cells;
5539   if(tmp)
5540     (const_cast<DataArrayInt *>(tmp))->setName("");
5541   tmp=_fam_faces;
5542   if(tmp)
5543     (const_cast<DataArrayInt *>(tmp))->setName("");
5544   tmp=_num_faces;
5545   if(tmp)
5546     (const_cast<DataArrayInt *>(tmp))->setName("");
5547 }
5548
5549 /*!
5550  * Returns ids of mesh entities contained in given families of a given dimension.
5551  *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
5552  *          are required.
5553  *  \param [in] fams - the names of the families of interest.
5554  *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
5555  *          returned instead of ids.
5556  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
5557  *          numbers, if available and required, of mesh entities of the families. The caller
5558  *          is to delete this array using decrRef() as it is no more needed. 
5559  *  \throw If the family field is missing for \a meshDimRelToMaxExt.
5560  */
5561 DataArrayInt *MEDFileStructuredMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const
5562 {
5563   std::vector<int> famIds(getFamiliesIds(fams));
5564   switch(meshDimRelToMaxExt)
5565   {
5566     case 1:
5567       {
5568         if((const DataArrayInt *)_fam_nodes)
5569           {
5570             MCAuto<DataArrayInt> da;
5571             if(!famIds.empty())
5572               da=_fam_nodes->findIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
5573             else
5574               da=_fam_nodes->findIdsEqualList(0,0);
5575             if(renum)
5576               return MEDFileUMeshSplitL1::Renumber(_num_nodes,da);
5577             else
5578               return da.retn();
5579           }
5580         else
5581           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on nodes !");
5582         break;
5583       }
5584     case 0:
5585       {
5586         if((const DataArrayInt *)_fam_cells)
5587           {
5588             MCAuto<DataArrayInt> da;
5589             if(!famIds.empty())
5590               da=_fam_cells->findIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
5591             else
5592               da=_fam_cells->findIdsEqualList(0,0);
5593             if(renum)
5594               return MEDFileUMeshSplitL1::Renumber(_num_cells,da);
5595             else
5596               return da.retn();
5597           }
5598         else
5599           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on cells !");
5600         break;
5601       }
5602     case -1:
5603       {
5604         if((const DataArrayInt *)_fam_faces)
5605           {
5606             MCAuto<DataArrayInt> da;
5607             if(!famIds.empty())
5608               da=_fam_faces->findIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
5609             else
5610               da=_fam_faces->findIdsEqualList(0,0);
5611             if(renum)
5612               return MEDFileUMeshSplitL1::Renumber(_num_faces,da);
5613             else
5614               return da.retn();
5615           }
5616         else
5617           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on faces !");
5618         break;
5619       }
5620     default:
5621       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : input meshDimRelative must be in [0,1,-1] !");
5622   }
5623   throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : unmanaged case !");
5624 }
5625
5626 /*!
5627  * Sets the family field of a given relative dimension.
5628  *  \param [in] meshDimRelToMaxExt - the relative dimension of entities for which
5629  *          the family field is set.
5630  *  \param [in] famArr - the array of the family field.
5631  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5632  *  \throw If \a famArr has an invalid size.
5633  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1 and \a meshDimRelToMaxExt != -1.
5634  */
5635 void MEDFileStructuredMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr)
5636 {
5637   const MEDCouplingStructuredMesh *mesh(getStructuredMesh());
5638   if(!mesh)
5639     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setFamilyFieldArr : no structured mesh specified ! Impossible to set family array !");
5640   switch(meshDimRelToMaxExt)
5641   {
5642     case 0:
5643       {
5644         int nbCells(mesh->getNumberOfCells());
5645         if(famArr)
5646           famArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of cells of mesh !");
5647         _fam_cells=famArr;
5648         break;
5649       }
5650     case 1:
5651       {
5652         int nbNodes(mesh->getNumberOfNodes());
5653         if(famArr)
5654           famArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !");
5655         _fam_nodes=famArr;
5656         break;
5657       }
5658     case -1:
5659       {
5660         int nbCells(mesh->getNumberOfCellsOfSubLevelMesh());
5661         if(famArr)
5662           famArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of faces of mesh !");
5663         _fam_faces=famArr;
5664         break;
5665       }
5666     default:
5667       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setFamilyFieldArr : Only available for levels 0 or 1 or -1 !");
5668   }
5669   if(famArr)
5670     famArr->incrRef();
5671 }
5672
5673 /*!
5674  * Sets the optional numbers of mesh entities of a given dimension.
5675  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5676  *  \param [in] renumArr - the array of the numbers.
5677  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5678  *  \throw If \a renumArr has an invalid size.
5679  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
5680  */
5681 void MEDFileStructuredMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr)
5682 {
5683   const MEDCouplingStructuredMesh *mesh=getStructuredMesh();
5684   if(!mesh)
5685     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : no structured mesh specified ! Impossible to set number array !");
5686   switch(meshDimRelToMaxExt)
5687   {
5688     case 0:
5689       {
5690         int nbCells=mesh->getNumberOfCells();
5691         renumArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Renum arr ! Mismatch with number of cells of mesh !");
5692         _num_cells=renumArr;
5693         break;
5694       }
5695     case 1:
5696       {
5697         int nbNodes=mesh->getNumberOfNodes();
5698         renumArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !");
5699         _num_nodes=renumArr;
5700         break;
5701       }
5702     case -1:
5703       {
5704         int nbCells=mesh->getNumberOfCellsOfSubLevelMesh();
5705         renumArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Renum arr ! Mismatch with number of faces of mesh !");
5706         _num_faces=renumArr;
5707         break;
5708       }
5709     default:
5710       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : Only available for levels 0 or 1 or -1 !");
5711   }
5712   if(renumArr)
5713     renumArr->incrRef();
5714 }
5715
5716 /*!
5717  * Sets the optional names of mesh entities of a given dimension.
5718  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5719  *  \param [in] nameArr - the array of the names.
5720  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5721  *  \throw If \a nameArr has an invalid size.
5722  */
5723 void MEDFileStructuredMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr)
5724 {
5725   const MEDCouplingStructuredMesh *mesh(getStructuredMesh());
5726   if(!mesh)
5727     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : no structured mesh specified ! Impossible to set names array !");
5728   switch(meshDimRelToMaxExt)
5729   {
5730     case 0:
5731       {
5732         int nbCells=mesh->getNumberOfCells();
5733         nameArr->checkNbOfTuplesAndComp(nbCells,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of cells of mesh !");
5734         _names_cells=nameArr;
5735         break;
5736       }
5737     case 1:
5738       {
5739         int nbNodes=mesh->getNumberOfNodes();
5740         nameArr->checkNbOfTuplesAndComp(nbNodes,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of nodes of mesh !");
5741         _names_nodes=nameArr;
5742         break;
5743       }
5744     case -1:
5745       {
5746         int nbCells=mesh->getNumberOfCellsOfSubLevelMesh();
5747         nameArr->checkNbOfTuplesAndComp(nbCells,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of faces of mesh !");
5748         _names_cells=nameArr;
5749       }
5750     default:
5751       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : Only available for levels 0 or 1 or -1 !");
5752   }
5753   if(nameArr)
5754     nameArr->incrRef();
5755 }
5756
5757 /*!
5758  * Adds a group of nodes to \a this mesh.
5759  *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
5760  *          The ids should be sorted and different each other (MED file norm).
5761  *
5762  *  \warning this method can alter default "FAMILLE_ZERO" family.
5763  *  For users sensitive to this a call to MEDFileMesh::rearrangeFamilies will be necessary after addGroup session.
5764  *
5765  *  \throw If the node coordinates array is not set.
5766  *  \throw If \a ids == \c NULL.
5767  *  \throw If \a ids->getName() == "".
5768  *  \throw If \a ids does not respect the MED file norm.
5769  *  \throw If a group with name \a ids->getName() already exists.
5770  */
5771 void MEDFileStructuredMesh::addNodeGroup(const DataArrayInt *ids)
5772 {
5773   addGroup(1,ids);
5774 }
5775
5776 /*!
5777  * Adds a group of nodes/cells/faces/edges to \a this mesh.
5778  *
5779  *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
5780  *          The ids should be sorted and different each other (MED file norm).
5781  *
5782  * \warning this method can alter default "FAMILLE_ZERO" family.
5783  * For users sensitive to this a call to MEDFileMesh::rearrangeFamilies will be necessary after addGroup session.
5784  *
5785  *  \throw If the node coordinates array is not set.
5786  *  \throw If \a ids == \c NULL.
5787  *  \throw If \a ids->getName() == "".
5788  *  \throw If \a ids does not respect the MED file norm.
5789  *  \throw If a group with name \a ids->getName() already exists.
5790  */
5791 void MEDFileStructuredMesh::addGroup(int meshDimRelToMaxExt, const DataArrayInt *ids)
5792 {
5793   DataArrayInt *fam(getOrCreateAndGetFamilyFieldAtLevel(meshDimRelToMaxExt));
5794   addGroupUnderground(false,ids,fam);
5795   return ;
5796 }
5797
5798 /*!
5799  * Returns the family field for mesh entities of a given dimension.
5800  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5801  *  \return const DataArrayInt * - the family field. It is an array of ids of families
5802  *          each mesh entity belongs to. It can be \c NULL.
5803  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
5804  */
5805 const DataArrayInt *MEDFileStructuredMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) const
5806 {
5807   switch(meshDimRelToMaxExt)
5808   {
5809     case 0:
5810       return _fam_cells;
5811     case 1:
5812       return _fam_nodes;
5813     case -1:
5814       return _fam_faces;
5815     default:
5816       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamilyFieldAtLevel : Only available for levels 0 or 1 or -1 !");
5817   }
5818 }
5819
5820 /*!
5821  * Returns the family field for mesh entities of a given dimension.
5822  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5823  *  \return const DataArrayInt * - the family field. It is an array of ids of families
5824  *          each mesh entity belongs to. It can be \c NULL.
5825  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
5826  */
5827 DataArrayInt *MEDFileStructuredMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt)
5828 {
5829   switch(meshDimRelToMaxExt)
5830   {
5831     case 0:
5832       return _fam_cells;
5833     case 1:
5834       return _fam_nodes;
5835     case -1:
5836       return _fam_faces;
5837     default:
5838       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamilyFieldAtLevel : Only available for levels 0 or 1 or -1 !");
5839   }
5840 }
5841
5842 /*!
5843  * Returns the optional numbers of mesh entities of a given dimension.
5844  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5845  *  \return const DataArrayInt * - the array of the entity numbers.
5846  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5847  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
5848  */
5849 const DataArrayInt *MEDFileStructuredMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) const
5850 {
5851   switch(meshDimRelToMaxExt)
5852   {
5853     case 0:
5854       return _num_cells;
5855     case 1:
5856       return _num_nodes;
5857     case -1:
5858       return _num_faces;
5859     default:
5860       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberFieldAtLevel : Only available for levels 0 or 1 or -1 !");
5861   }
5862 }
5863
5864 /*!
5865  * Returns the optional numbers of mesh entities of a given dimension transformed using
5866  * DataArrayInt::invertArrayN2O2O2N().
5867  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5868  *  \return const DataArrayInt * - the array of the entity numbers transformed using
5869  *          DataArrayInt::invertArrayN2O2O2N().
5870  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
5871  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5872  */
5873 const DataArrayInt *MEDFileStructuredMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxExt) const
5874 {
5875   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
5876     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getRevNumberFieldAtLevel : Only available for levels 0 or 1 !");
5877   if(meshDimRelToMaxExt==0)
5878     {
5879       if((const DataArrayInt *)_num_cells)
5880         {
5881           int pos;
5882           int maxValue=_num_cells->getMaxValue(pos);
5883           _rev_num_cells=_num_cells->invertArrayN2O2O2N(maxValue+1);
5884           return _rev_num_cells;
5885         }
5886       else
5887         throw INTERP_KERNEL::Exception("MEDFileCMesh::getRevNumberFieldAtLevel : no cell renumbering for a request on reverse numbering !");
5888     }
5889   else
5890     {
5891       if((const DataArrayInt *)_num_nodes)
5892         {
5893           int pos;
5894           int maxValue=_num_nodes->getMaxValue(pos);
5895           _rev_num_nodes=_num_nodes->invertArrayN2O2O2N(maxValue+1);
5896           return _rev_num_nodes;
5897         }
5898       else
5899         throw INTERP_KERNEL::Exception("MEDFileCMesh::getRevNumberFieldAtLevel : no node renumbering for a request on reverse numbering !");
5900     }
5901 }
5902
5903 const DataArrayAsciiChar *MEDFileStructuredMesh::getNameFieldAtLevel(int meshDimRelToMaxExt) const
5904 {
5905   switch(meshDimRelToMaxExt)
5906   {
5907     case 0:
5908       return _names_cells;
5909     case 1:
5910       return _names_nodes;
5911     case -1:
5912       return _names_faces;
5913     default:
5914       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNameFieldAtLevel : Only available for levels 0 or 1 or -1 !");
5915   }
5916 }
5917
5918 /*!
5919  * Returns relative dimensions of mesh entities (excluding nodes) present in \a this mesh.
5920  *  \return std::vector<int> - a sequence of the relative dimensions: [0].
5921  */
5922 std::vector<int> MEDFileStructuredMesh::getNonEmptyLevels() const
5923 {
5924   std::vector<int> ret(1);
5925   return ret;
5926 }
5927
5928 /*!
5929  * Returns relative dimensions of mesh entities (including nodes) present in \a this mesh.
5930  *  \return std::vector<int> - a sequence of the relative dimensions: [1,0].
5931  */
5932 std::vector<int> MEDFileStructuredMesh::getNonEmptyLevelsExt() const
5933 {
5934   std::vector<int> ret(2);
5935   ret[0]=1;
5936   return ret;
5937 }
5938
5939 /*!
5940  * Returns the set of extensive levels (nodes included) where not NULL family arr are defined.
5941  */
5942 std::vector<int> MEDFileStructuredMesh::getFamArrNonEmptyLevelsExt() const
5943 {
5944   std::vector<int> ret;
5945   const DataArrayInt *famNodes(_fam_nodes),*famCells(_fam_cells),*famFaces(_fam_faces);
5946   if(famNodes)
5947     ret.push_back(1);
5948   if(famCells)
5949     ret.push_back(0);
5950   if(famFaces)
5951     ret.push_back(-1);
5952   return ret;
5953 }
5954
5955 /*!
5956  * Returns the set of extensive levels (nodes included) where not NULL numbering arr are defined.
5957  */
5958 std::vector<int> MEDFileStructuredMesh::getNumArrNonEmptyLevelsExt() const
5959 {
5960   std::vector<int> ret;
5961   const DataArrayInt *numNodes(_num_nodes),*numCells(_num_cells),*numFaces(_num_faces);
5962   if(numNodes)
5963     ret.push_back(1);
5964   if(numCells)
5965     ret.push_back(0);
5966   if(numFaces)
5967     ret.push_back(-1);
5968   return ret;
5969 }
5970
5971 /*!
5972  * Returns the set of extensive levels (nodes included) where not NULL naming arr are defined.
5973  */
5974 std::vector<int> MEDFileStructuredMesh::getNameArrNonEmptyLevelsExt() const
5975 {
5976   std::vector<int> ret;
5977   const DataArrayAsciiChar *namesNodes(_names_nodes),*namesCells(_names_cells),*namesFaces(_names_faces);
5978   if(namesNodes)
5979     ret.push_back(1);
5980   if(namesCells)
5981     ret.push_back(0);
5982   if(namesFaces)
5983     ret.push_back(-1);
5984   return ret;
5985 }
5986
5987 /*!
5988  * no implementation here, it is not a bug, but intresically no polyhedra in \a this.
5989  */
5990 bool MEDFileStructuredMesh::unPolyze(std::vector<int>& oldCode, std::vector<int>& newCode, DataArrayInt *& o2nRenumCell)
5991 {
5992   oldCode.clear(); newCode.clear(); o2nRenumCell=0;
5993   return false;
5994 }
5995
5996 void MEDFileStructuredMesh::changeFamilyIdArr(int oldId, int newId)
5997 {
5998   DataArrayInt *arr=_fam_nodes;
5999   if(arr)
6000     arr->changeValue(oldId,newId);
6001   arr=_fam_cells;
6002   if(arr)
6003     arr->changeValue(oldId,newId);
6004   arr=_fam_faces;
6005   if(arr)
6006     arr->changeValue(oldId,newId);
6007 }
6008
6009 std::list< MCAuto<DataArrayInt> > MEDFileStructuredMesh::getAllNonNullFamilyIds() const
6010 {
6011   std::list< MCAuto<DataArrayInt> > ret;
6012   const DataArrayInt *da(_fam_nodes);
6013   if(da)
6014     { da->incrRef(); ret.push_back(MCAuto<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
6015   da=_fam_cells;
6016   if(da)
6017     { da->incrRef(); ret.push_back(MCAuto<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
6018   da=_fam_faces;
6019   if(da)
6020     { da->incrRef(); ret.push_back(MCAuto<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
6021   return ret;
6022 }
6023
6024 void MEDFileStructuredMesh::deepCpyAttributes()
6025 {
6026   if((const DataArrayInt*)_fam_nodes)
6027     _fam_nodes=_fam_nodes->deepCopy();
6028   if((const DataArrayInt*)_num_nodes)
6029     _num_nodes=_num_nodes->deepCopy();
6030   if((const DataArrayAsciiChar*)_names_nodes)
6031     _names_nodes=_names_nodes->deepCopy();
6032   if((const DataArrayInt*)_fam_cells)
6033     _fam_cells=_fam_cells->deepCopy();
6034   if((const DataArrayInt*)_num_cells)
6035     _num_cells=_num_cells->deepCopy();
6036   if((const DataArrayAsciiChar*)_names_cells)
6037     _names_cells=_names_cells->deepCopy();
6038   if((const DataArrayInt*)_fam_faces)
6039     _fam_faces=_fam_faces->deepCopy();
6040   if((const DataArrayInt*)_num_faces)
6041     _num_faces=_num_faces->deepCopy();
6042   if((const DataArrayAsciiChar*)_names_faces)
6043     _names_faces=_names_faces->deepCopy();
6044   if((const DataArrayInt*)_rev_num_nodes)
6045     _rev_num_nodes=_rev_num_nodes->deepCopy();
6046   if((const DataArrayInt*)_rev_num_cells)
6047     _rev_num_cells=_rev_num_cells->deepCopy();
6048 }
6049
6050 /*!
6051  * Returns a pointer to mesh at the specified level (here 0 is compulsary for cartesian mesh).
6052  * 
6053  * \return a pointer to cartesian mesh that need to be managed by the caller.
6054  * \warning the returned pointer has to be managed by the caller.
6055  */
6056
6057 /*!
6058  * Returns a pointer to MEDCouplingStructuredMesh held by \a this. 
6059  *  \param [in] meshDimRelToMax - it must be \c 0 or \c -1.
6060  *  \param [in] renum - it must be \c false.
6061  *  \return MEDCouplingMesh * - a pointer to MEDCouplingMesh that the caller is to
6062  *          delete using decrRef() as it is no more needed. 
6063  */
6064 MEDCouplingMesh *MEDFileStructuredMesh::getMeshAtLevel(int meshDimRelToMax, bool renum) const
6065 {
6066   checkCartesian();
6067   if(renum)
6068     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support renumbering ! To do it perform request of renum array directly !");
6069   const MEDCouplingStructuredMesh *m(getStructuredMesh());
6070   switch(meshDimRelToMax)
6071   {
6072     case 0:
6073       {
6074         if(m)
6075           m->incrRef();
6076         return const_cast<MEDCouplingStructuredMesh *>(m);
6077       }
6078     case -1:
6079       {
6080         if(!m)
6081           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getMeshAtLevel : level -1 requested must be non empty to be able to compute unstructured sub mesh !");
6082         buildMinusOneImplicitPartIfNeeded();
6083         MEDCoupling1SGTUMesh *ret(_faces_if_necessary);
6084         if(ret)
6085           ret->incrRef();
6086         return ret;
6087       }
6088     default:
6089       throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support multi level for mesh 0 expected as input !");
6090   }
6091 }
6092
6093 std::vector<int> MEDFileStructuredMesh::getFamsNonEmptyLevels(const std::vector<std::string>& fams) const
6094 {
6095   std::vector<int> ret;
6096   const DataArrayInt *famCells(_fam_cells),*famFaces(_fam_faces);
6097   if(famCells && famCells->presenceOfValue(ret))
6098     ret.push_back(0);
6099   if(famFaces && famFaces->presenceOfValue(ret))
6100     ret.push_back(-1);
6101   return ret;  
6102 }
6103
6104 std::vector<int> MEDFileStructuredMesh::getFamsNonEmptyLevelsExt(const std::vector<std::string>& fams) const
6105 {
6106   std::vector<int> ret(getFamsNonEmptyLevels(fams));
6107   const DataArrayInt *famNodes(_fam_nodes);
6108   if(famNodes && famNodes->presenceOfValue(ret))
6109     ret.push_back(1);
6110   return ret;  
6111 }
6112
6113 /*!
6114  * Returns number of mesh entities of a given relative dimension in \a this mesh.
6115  *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
6116  *  \return int - the number of entities.
6117  *  \throw If no mesh entities of dimension \a meshDimRelToMaxExt are available in \a this mesh.
6118  */
6119 int MEDFileStructuredMesh::getSizeAtLevel(int meshDimRelToMaxExt) const
6120 {
6121   const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
6122   if(!cmesh)
6123     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : No structured mesh set !");
6124   switch(meshDimRelToMaxExt)
6125   {
6126     case 0:
6127       return cmesh->getNumberOfCells();
6128     case 1:
6129       return cmesh->getNumberOfNodes();
6130     case -1:
6131       return cmesh->getNumberOfCellsOfSubLevelMesh();
6132     default:
6133       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : Only available for levels 0 or 1 or -1 !");
6134   }
6135 }
6136
6137 int MEDFileStructuredMesh::getNumberOfNodes() const
6138 {
6139   const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
6140   if(!cmesh)
6141     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberOfNodes : no cartesian mesh set !");
6142   return cmesh->getNumberOfNodes();
6143 }
6144
6145 int MEDFileStructuredMesh::getNumberOfCellsAtLevel(int meshDimRelToMaxExt) const
6146 {
6147   const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
6148   if(!cmesh)
6149     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberOfNodes : no cartesian mesh set !");
6150   switch(meshDimRelToMaxExt)
6151   {
6152     case 0:
6153       return cmesh->getNumberOfCells();
6154     case -1:
6155       return cmesh->getNumberOfCellsOfSubLevelMesh();
6156     default:
6157       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberOfNodes : only meshDimRelToMax=0 and meshDimRelToMax=-1 supported !");
6158     }
6159 }
6160
6161 bool MEDFileStructuredMesh::hasImplicitPart() const
6162 {
6163   return true;
6164 }
6165
6166 /*!
6167  * \sa MEDFileStructuredMesh::getImplicitFaceMesh
6168  */
6169 int MEDFileStructuredMesh::buildImplicitPartIfAny(INTERP_KERNEL::NormalizedCellType gt) const
6170 {
6171   static const char MSG[]="MEDFileStructuredMesh::buildImplicitPartIfAny : the given geo type is not manageable by a structured mesh !";
6172   const MEDCoupling1SGTUMesh *zeFaceMesh(_faces_if_necessary);
6173   if(!zeFaceMesh)
6174     {
6175       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(getMeshDimension())));
6176       if(cm.getReverseExtrudedType()!=gt)
6177         throw INTERP_KERNEL::Exception(MSG);
6178       buildImplicitPart();
6179       return getStructuredMesh()->getNumberOfCellsOfSubLevelMesh();
6180     }
6181   else
6182     {
6183       if(gt!=zeFaceMesh->getCellModelEnum())
6184         throw INTERP_KERNEL::Exception(MSG);
6185       return zeFaceMesh->getNumberOfCells();
6186     }
6187 }
6188
6189 void MEDFileStructuredMesh::buildMinusOneImplicitPartIfNeeded() const
6190 {
6191   const MEDCoupling1SGTUMesh *zeFaceMesh(_faces_if_necessary);
6192   if(!zeFaceMesh)
6193     buildImplicitPart();
6194 }
6195
6196 void MEDFileStructuredMesh::buildImplicitPart() const
6197 {
6198   const MEDCouplingStructuredMesh *mcmesh(getStructuredMesh());
6199   if(!mcmesh)
6200     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::buildImplicitPart : Unable to build the implicit part of structured mesh because no structured mesh at level 0 defined !");
6201   _faces_if_necessary=mcmesh->build1SGTSubLevelMesh();
6202 }
6203
6204 void MEDFileStructuredMesh::releaseImplicitPartIfAny() const
6205 {
6206   _faces_if_necessary=0;
6207 }
6208
6209 /*!
6210  * Retrieves the internal pointer (no decrRef requested) of the implicit face mesh if any.
6211  * To force to build it you can invoke MEDFileStructuredMesh::buildImplicitPartIfAny method.
6212  * 
6213  * \sa MEDFileStructuredMesh::buildImplicitPartIfAny
6214  */
6215 MEDCoupling1SGTUMesh *MEDFileStructuredMesh::getImplicitFaceMesh() const
6216 {
6217   checkCartesian();
6218   return _faces_if_necessary;
6219 }
6220
6221 std::vector<INTERP_KERNEL::NormalizedCellType> MEDFileStructuredMesh::getGeoTypesAtLevel(int meshDimRelToMax) const
6222 {
6223   const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
6224   if(!cmesh)
6225     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGeoTypesAtLevel : No structured mesh set !");
6226   switch(meshDimRelToMax)
6227   {
6228     case 0:
6229       {
6230         std::vector<INTERP_KERNEL::NormalizedCellType> ret(1,cmesh->getTypeOfCell(0));
6231         return ret;
6232       }
6233     case -1:
6234       {
6235         int mdim(cmesh->getMeshDimension());
6236         if(mdim<1)
6237           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGeoTypesAtLevel : only one level available for structured meshes ! Input 0 is mandatory or 0D mesh !");
6238         std::vector<INTERP_KERNEL::NormalizedCellType> ret(1,MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(mdim-1));
6239         return ret;
6240       }
6241     default:
6242       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGeoTypesAtLevel : only 2 levels available at most : 0 and -1 !");
6243   }
6244 }
6245
6246 int MEDFileStructuredMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType ct) const
6247 {
6248   if(ct!=MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(getMeshDimension()))
6249     return 0;
6250   else
6251     return getNumberOfCellsAtLevel(0);
6252 }
6253
6254 void MEDFileStructuredMesh::whichAreNodesFetched(const MEDFileField1TSStructItem& st, const MEDFileFieldGlobsReal *globs, std::vector<bool>& nodesFetched) const
6255 {
6256   if(st.getNumberOfItems()!=1)
6257     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 !");
6258   if(st[0].getGeo()!=MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(getMeshDimension()))
6259     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : The sturture of field is not lying on expected geo type !");
6260   if(getNumberOfNodes()!=(int)nodesFetched.size())
6261     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : invalid size of array !");
6262   if(st[0].getPflName().empty())
6263     {
6264       std::fill(nodesFetched.begin(),nodesFetched.end(),true);
6265       return ;
6266     }
6267   const DataArrayInt *arr(globs->getProfile(st[0].getPflName()));
6268   const MEDCouplingStructuredMesh *cmesh=getStructuredMesh();//cmesh not null because getNumberOfNodes called before
6269   int sz(nodesFetched.size());
6270   for(const int *work=arr->begin();work!=arr->end();work++)
6271     {
6272       std::vector<int> conn;
6273       cmesh->getNodeIdsOfCell(*work,conn);
6274       for(std::vector<int>::const_iterator it=conn.begin();it!=conn.end();it++)
6275         if(*it>=0 && *it<sz)
6276           nodesFetched[*it]=true;
6277         else
6278           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : internal error !");
6279     }
6280 }
6281
6282 med_geometry_type MEDFileStructuredMesh::GetGeoTypeFromMeshDim(int meshDim)
6283 {
6284   INTERP_KERNEL::NormalizedCellType ct(MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(meshDim));
6285   return typmai3[ct];
6286 }
6287
6288 void MEDFileStructuredMesh::LoadStrMeshDAFromFile(med_idt fid, int meshDim, int dt, int it, const std::string& mName, MEDFileMeshReadSelector *mrs,
6289                                                   MCAuto<DataArrayInt>& famCells, MCAuto<DataArrayInt>& numCells, MCAuto<DataArrayAsciiChar>& namesCells)
6290 {
6291   med_bool chgt=MED_FALSE,trsf=MED_FALSE;
6292   med_geometry_type geoTypeReq=MEDFileStructuredMesh::GetGeoTypeFromMeshDim(meshDim);
6293   int nbOfElt(0);
6294   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf);
6295   if(nbOfElt>0)
6296     {
6297       if(!mrs || mrs->isCellFamilyFieldReading())
6298         {
6299           famCells=DataArrayInt::New();
6300           famCells->alloc(nbOfElt,1);
6301           MEDFILESAFECALLERRD0(MEDmeshEntityFamilyNumberRd,(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,famCells->getPointer()));
6302         }
6303     }
6304   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,MED_NUMBER,MED_NODAL,&chgt,&trsf);
6305   if(nbOfElt>0)
6306     {
6307       if(!mrs || mrs->isCellNumFieldReading())
6308         {
6309           numCells=DataArrayInt::New();
6310           numCells->alloc(nbOfElt,1);
6311           MEDFILESAFECALLERRD0(MEDmeshEntityNumberRd,(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,numCells->getPointer()));
6312         }
6313     }
6314   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,MED_NAME,MED_NODAL,&chgt,&trsf);
6315   if(nbOfElt>0)
6316     {
6317       if(!mrs || mrs->isCellNameFieldReading())
6318         {
6319           namesCells=DataArrayAsciiChar::New();
6320           namesCells->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end
6321           MEDFILESAFECALLERRD0(MEDmeshEntityNameRd,(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,namesCells->getPointer()));
6322           namesCells->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end
6323         }
6324     }
6325 }
6326
6327 void MEDFileStructuredMesh::loadStrMeshFromFile(MEDFileStrMeshL2 *strm, med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6328 {
6329   setName(strm->getName());
6330   setDescription(strm->getDescription());
6331   setUnivName(strm->getUnivName());
6332   setIteration(strm->getIteration());
6333   setOrder(strm->getOrder());
6334   setTimeValue(strm->getTime());
6335   setTimeUnit(strm->getTimeUnit());
6336   MEDFileMeshL2::ReadFamiliesAndGrps(fid,mName,_families,_groups,mrs);
6337   med_bool chgt=MED_FALSE,trsf=MED_FALSE;
6338   int nbOfElt(MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf));
6339   if(nbOfElt>0)
6340     {
6341       if(!mrs || mrs->isNodeFamilyFieldReading())
6342         {
6343           int nbNodes(getNumberOfNodes());
6344           if(nbOfElt>nbNodes)
6345             throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::loadStrMeshFromFile : invalid size of family node array regarding number of nodes in this ! File seems to be corrupted !");
6346           _fam_nodes=DataArrayInt::New();
6347           _fam_nodes->alloc(nbNodes,1);//yes nbNodes and not nbOfElt see next line.
6348           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...
6349             _fam_nodes->fillWithZero();
6350           MEDFILESAFECALLERRD0(MEDmeshEntityFamilyNumberRd,(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,_fam_nodes->getPointer()));
6351         }
6352     }
6353   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_NUMBER,MED_NODAL,&chgt,&trsf);
6354   if(nbOfElt>0)
6355     {
6356       if(!mrs || mrs->isNodeNumFieldReading())
6357         {
6358           _num_nodes=DataArrayInt::New();
6359           _num_nodes->alloc(nbOfElt,1);
6360           MEDFILESAFECALLERRD0(MEDmeshEntityNumberRd,(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,_num_nodes->getPointer()));
6361         }
6362     }
6363   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_NAME,MED_NODAL,&chgt,&trsf);
6364   if(nbOfElt>0)
6365     {
6366       if(!mrs || mrs->isNodeNameFieldReading())
6367         {
6368           _names_nodes=DataArrayAsciiChar::New();
6369           _names_nodes->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end
6370           MEDFILESAFECALLERRD0(MEDmeshEntityNameRd,(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,_names_nodes->getPointer()));
6371           _names_nodes->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end
6372         }
6373     }
6374   int meshDim(getStructuredMesh()->getMeshDimension());
6375   LoadStrMeshDAFromFile(fid,meshDim,dt,it,mName,mrs,_fam_cells,_num_cells,_names_cells);
6376   if(meshDim>=1)
6377     LoadStrMeshDAFromFile(fid,meshDim-1,dt,it,mName,mrs,_fam_faces,_num_faces,_names_faces);
6378 }
6379
6380 void MEDFileStructuredMesh::writeStructuredLL(med_idt fid, const std::string& maa) const
6381 {
6382   int meshDim(getStructuredMesh()->getMeshDimension());
6383   med_geometry_type geoTypeReq(GetGeoTypeFromMeshDim(meshDim)),geoTypeReq2(GetGeoTypeFromMeshDim(meshDim-1));
6384   //
6385   if((const DataArrayInt *)_fam_cells)
6386     MEDFILESAFECALLERWR0(MEDmeshEntityFamilyNumberWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq,_fam_cells->getNumberOfTuples(),_fam_cells->getConstPointer()));
6387   if((const DataArrayInt *)_fam_faces)
6388     MEDFILESAFECALLERWR0(MEDmeshEntityFamilyNumberWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq2,_fam_faces->getNumberOfTuples(),_fam_faces->getConstPointer()));
6389   if((const DataArrayInt *)_fam_nodes)
6390     MEDFILESAFECALLERWR0(MEDmeshEntityFamilyNumberWr,(fid,maa.c_str(),_iteration,_order,MED_NODE,MED_NONE,_fam_nodes->getNumberOfTuples(),_fam_nodes->getConstPointer()));
6391   if((const DataArrayInt *)_num_cells)
6392     MEDFILESAFECALLERWR0(MEDmeshEntityNumberWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq,_num_cells->getNumberOfTuples(),_num_cells->getConstPointer()));
6393   if((const DataArrayInt *)_num_faces)
6394     MEDFILESAFECALLERWR0(MEDmeshEntityNumberWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq2,_num_faces->getNumberOfTuples(),_num_faces->getConstPointer()));
6395   if((const DataArrayInt *)_num_nodes)
6396     MEDFILESAFECALLERWR0(MEDmeshEntityNumberWr,(fid,maa.c_str(),_iteration,_order,MED_NODE,MED_NONE,_num_nodes->getNumberOfTuples(),_num_nodes->getConstPointer()));
6397   if((const DataArrayAsciiChar *)_names_cells)
6398     {
6399       if(_names_cells->getNumberOfComponents()!=MED_SNAME_SIZE)
6400         {
6401           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on cells with number of components set to " << MED_SNAME_SIZE;
6402           oss << " ! The array has " << _names_cells->getNumberOfComponents() << " components !";
6403           throw INTERP_KERNEL::Exception(oss.str().c_str());
6404         }
6405       MEDFILESAFECALLERWR0(MEDmeshEntityNameWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq,_names_cells->getNumberOfTuples(),_names_cells->getConstPointer()));
6406     }
6407   if((const DataArrayAsciiChar *)_names_faces)
6408     {
6409       if(_names_faces->getNumberOfComponents()!=MED_SNAME_SIZE)
6410         {
6411           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on faces with number of components set to " << MED_SNAME_SIZE;
6412           oss << " ! The array has " << _names_faces->getNumberOfComponents() << " components !";
6413           throw INTERP_KERNEL::Exception(oss.str().c_str());
6414         }
6415       MEDFILESAFECALLERWR0(MEDmeshEntityNameWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq2,_names_faces->getNumberOfTuples(),_names_faces->getConstPointer()));
6416     }
6417   if((const DataArrayAsciiChar *)_names_nodes)
6418     {
6419       if(_names_nodes->getNumberOfComponents()!=MED_SNAME_SIZE)
6420         {
6421           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on nodes with number of components set to " << MED_SNAME_SIZE;
6422           oss << " ! The array has " << _names_cells->getNumberOfComponents() << " components !";
6423           throw INTERP_KERNEL::Exception(oss.str().c_str());
6424         }
6425       MEDFILESAFECALLERWR0(MEDmeshEntityNameWr,(fid,maa.c_str(),_iteration,_order,MED_NODE,MED_NONE,_names_nodes->getNumberOfTuples(),_names_nodes->getConstPointer()));
6426     }
6427   //
6428   MEDFileUMeshL2::WriteFamiliesAndGrps(fid,maa.c_str(),_families,_groups,_too_long_str);
6429 }
6430
6431 /*!
6432  * Returns an empty instance of MEDFileCMesh.
6433  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
6434  *          mesh using decrRef() as it is no more needed. 
6435  */
6436 MEDFileCMesh *MEDFileCMesh::New()
6437 {
6438   return new MEDFileCMesh;
6439 }
6440
6441 /*!
6442  * Returns a new MEDFileCMesh holding the mesh data that has been read from a given MED
6443  * file. The first mesh in the file is loaded.
6444  *  \param [in] fileName - the name of MED file to read.
6445  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
6446  *          mesh using decrRef() as it is no more needed. 
6447  *  \throw If the file is not readable.
6448  *  \throw If there is no meshes in the file.
6449  *  \throw If the mesh in the file is not a Cartesian one.
6450  */
6451 MEDFileCMesh *MEDFileCMesh::New(const std::string& fileName, MEDFileMeshReadSelector *mrs)
6452 {
6453   MEDFileUtilities::AutoFid fid(OpenMEDFileForRead(fileName));
6454   return New(fid,mrs);
6455 }
6456
6457 MEDFileCMesh *MEDFileCMesh::New(med_idt fid, MEDFileMeshReadSelector *mrs)
6458 {
6459   return NewForTheFirstMeshInFile<MEDFileCMesh>(fid,mrs);
6460 }
6461
6462 /*!
6463  * Returns a new MEDFileCMesh holding the mesh data that has been read from a given MED
6464  * file. The mesh to load is specified by its name and numbers of a time step and an
6465  * iteration.
6466  *  \param [in] fileName - the name of MED file to read.
6467  *  \param [in] mName - the name of the mesh to read.
6468  *  \param [in] dt - the number of a time step.
6469  *  \param [in] it - the number of an iteration.
6470  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
6471  *          mesh using decrRef() as it is no more needed. 
6472  *  \throw If the file is not readable.
6473  *  \throw If there is no mesh with given attributes in the file.
6474  *  \throw If the mesh in the file is not a Cartesian one.
6475  */
6476 MEDFileCMesh *MEDFileCMesh::New(const std::string& fileName, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6477 {
6478   MEDFileUtilities::AutoFid fid(OpenMEDFileForRead(fileName));
6479   return New(fid,mName,dt,it,mrs);
6480 }
6481
6482 MEDFileCMesh *MEDFileCMesh::New(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6483 {
6484   return new MEDFileCMesh(fid,mName,dt,it,mrs);
6485 }
6486
6487 std::size_t MEDFileCMesh::getHeapMemorySizeWithoutChildren() const
6488 {
6489   return MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren();
6490 }
6491
6492 std::vector<const BigMemoryObject *> MEDFileCMesh::getDirectChildrenWithNull() const
6493 {
6494   std::vector<const BigMemoryObject *> ret(MEDFileStructuredMesh::getDirectChildrenWithNull());
6495   ret.push_back((const MEDCouplingCMesh *)_cmesh);
6496   return ret;
6497 }
6498
6499 /*!
6500  * Returns the dimension on cells in \a this mesh.
6501  *  \return int - the mesh dimension.
6502  *  \throw If there are no cells in this mesh.
6503  */
6504 int MEDFileCMesh::getMeshDimension() const
6505 {
6506   if(!((const MEDCouplingCMesh*)_cmesh))
6507     throw INTERP_KERNEL::Exception("MEDFileCMesh::getMeshDimension : unable to get meshdimension because no mesh set !");
6508   return _cmesh->getMeshDimension();
6509 }
6510
6511 /*!
6512  * Returns the dimension on nodes in \a this mesh.
6513  *  \return int - the space dimension.
6514  *  \throw If there are no cells in this mesh.
6515  */
6516 int MEDFileCMesh::getSpaceDimension() const
6517 {
6518   if(!((const MEDCouplingCMesh*)_cmesh))
6519     throw INTERP_KERNEL::Exception("MEDFileCMesh::getSpaceDimension : unable to get spacedimension because no mesh set !");
6520   return _cmesh->getSpaceDimension();
6521 }
6522
6523 /*!
6524  * Returns a string describing \a this mesh.
6525  *  \return std::string - the mesh information string.
6526  */
6527 std::string MEDFileCMesh::simpleRepr() const
6528 {
6529   return MEDFileStructuredMesh::simpleRepr();
6530 }
6531
6532 /*!
6533  * Returns a full textual description of \a this mesh.
6534  *  \return std::string - the string holding the mesh description.
6535  */
6536 std::string MEDFileCMesh::advancedRepr() const
6537 {
6538   return simpleRepr();
6539 }
6540
6541 MEDFileCMesh *MEDFileCMesh::shallowCpy() const
6542 {
6543   MCAuto<MEDFileCMesh> ret(new MEDFileCMesh(*this));
6544   return ret.retn();
6545 }
6546
6547 MEDFileMesh *MEDFileCMesh::createNewEmpty() const
6548 {
6549   return new MEDFileCMesh;
6550 }
6551
6552 MEDFileCMesh *MEDFileCMesh::deepCopy() const
6553 {
6554   MCAuto<MEDFileCMesh> ret(new MEDFileCMesh(*this));
6555   ret->deepCpyEquivalences(*this);
6556   if((const MEDCouplingCMesh*)_cmesh)
6557     ret->_cmesh=static_cast<MEDCouplingCMesh*>(_cmesh->deepCopy());
6558   ret->deepCpyAttributes();
6559   return ret.retn();
6560 }
6561
6562 /*!
6563  * Checks if \a this and another mesh are equal.
6564  *  \param [in] other - the mesh to compare with.
6565  *  \param [in] eps - a precision used to compare real values.
6566  *  \param [in,out] what - the string returning description of unequal data.
6567  *  \return bool - \c true if the meshes are equal, \c false, else.
6568  */
6569 bool MEDFileCMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
6570 {
6571   if(!MEDFileStructuredMesh::isEqual(other,eps,what))
6572     return false;
6573   const MEDFileCMesh *otherC=dynamic_cast<const MEDFileCMesh *>(other);
6574   if(!otherC)
6575     {
6576       what="Mesh types differ ! This is cartesian and other is NOT !";
6577       return false;
6578     }
6579   clearNonDiscrAttributes();
6580   otherC->clearNonDiscrAttributes();
6581   const MEDCouplingCMesh *coo1=_cmesh;
6582   const MEDCouplingCMesh *coo2=otherC->_cmesh;
6583   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
6584     {
6585       what="Mismatch of cartesian meshes ! One is defined and not other !";
6586       return false;
6587     }
6588   if(coo1)
6589     {
6590       bool ret=coo1->isEqual(coo2,eps);
6591       if(!ret)
6592         {
6593           what="cartesian meshes differ !";
6594           return false;
6595         }
6596     }
6597   return true;
6598 }
6599
6600 /*!
6601  * Clears redundant attributes of incorporated data arrays.
6602  */
6603 void MEDFileCMesh::clearNonDiscrAttributes() const
6604 {
6605   MEDFileStructuredMesh::clearNonDiscrAttributes();
6606   MEDFileUMeshSplitL1::ClearNonDiscrAttributes(_cmesh);//to it is not a bug umeshsplit have already the method implemented
6607 }
6608
6609 MEDFileCMesh::MEDFileCMesh()
6610 {
6611 }
6612
6613 MEDFileCMesh::MEDFileCMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6614 try
6615 {
6616     loadLLWithAdditionalItems(fid,mName,dt,it,mrs);
6617 }
6618 catch(INTERP_KERNEL::Exception& e)
6619 {
6620     throw e;
6621 }
6622
6623 void MEDFileCMesh::loadLL(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6624 {
6625   MEDCoupling::MEDCouplingMeshType meshType;
6626   int dummy0,dummy1;
6627   std::string dtunit;
6628   MEDCoupling::MEDCouplingAxisType axType;
6629   INTERP_KERNEL::AutoCppPtr<MeshOrStructMeshCls> mid(MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,axType,dummy0,dummy1,dtunit));
6630   if(meshType!=CARTESIAN)
6631     {
6632       std::ostringstream oss; oss << "Trying to load as cartesian an existing mesh with name '" << mName << "' that is NOT cartesian !";
6633       throw INTERP_KERNEL::Exception(oss.str().c_str());
6634     }
6635   MEDFileCMeshL2 loaderl2;
6636   loaderl2.loadAll(fid,mid,mName,dt,it);
6637   setAxisType(axType);
6638   MEDCouplingCMesh *mesh=loaderl2.getMesh();
6639   mesh->incrRef();
6640   _cmesh=mesh;
6641   loadStrMeshFromFile(&loaderl2,fid,mName,dt,it,mrs);
6642 }
6643
6644 /*!
6645  * Returns a const pointer to MEDCouplingCMesh held by \a this mesh.
6646  *  \return const MEDCouplingCMesh * - a pointer to the held MEDCouplingCMesh.
6647  */
6648 const MEDCouplingCMesh *MEDFileCMesh::getMesh() const
6649 {
6650   synchronizeTinyInfoOnLeaves();
6651   return _cmesh;
6652 }
6653
6654 const MEDCouplingStructuredMesh *MEDFileCMesh::getStructuredMesh() const
6655 {
6656   synchronizeTinyInfoOnLeaves();
6657   return _cmesh;
6658 }
6659
6660 /*!
6661  * Sets the MEDCouplingCMesh holding the data of \a this mesh.
6662  *  \param [in] m - the new MEDCouplingCMesh to refer to.
6663  *  \throw If the name or the description of \a this mesh and \a m are not empty and are
6664  *         different. 
6665  */
6666 void MEDFileCMesh::setMesh(MEDCouplingCMesh *m)
6667 {
6668   dealWithTinyInfo(m);
6669   if(m)
6670     m->incrRef();
6671   _cmesh=m;
6672 }
6673
6674 MEDFileMesh *MEDFileCMesh::cartesianize() const
6675 {
6676   if(getAxisType()==AX_CART)
6677     {
6678       incrRef();
6679       return const_cast<MEDFileCMesh *>(this);
6680     }
6681   else
6682     {
6683       const MEDCouplingCMesh *cmesh(getMesh());
6684       if(!cmesh)
6685         throw INTERP_KERNEL::Exception("MEDFileCMesh::cartesianize : impossible to turn into cartesian because the mesh is null !");
6686       MCAuto<MEDCouplingCurveLinearMesh> clmesh(cmesh->buildCurveLinear());
6687       MCAuto<DataArrayDouble> coords(clmesh->getCoords()->cartesianize(getAxisType()));
6688       clmesh->setCoords(coords);
6689       MCAuto<MEDFileCurveLinearMesh> ret(MEDFileCurveLinearMesh::New());
6690       ret->MEDFileStructuredMesh::operator=(*this);
6691       ret->setMesh(clmesh);
6692       ret->setAxisType(AX_CART);
6693       return ret.retn();
6694     }
6695 }
6696
6697 void MEDFileCMesh::writeMeshLL(med_idt fid) const
6698 {
6699   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
6700   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
6701   INTERP_KERNEL::AutoPtr<char> dtunit=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE);
6702   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
6703   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
6704   MEDLoaderBase::safeStrCpy(_dt_unit.c_str(),MED_LNAME_SIZE,dtunit,_too_long_str);
6705   int spaceDim(_cmesh->getSpaceDimension());
6706   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
6707   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
6708   for(int i=0;i<spaceDim;i++)
6709     {
6710       std::string info(_cmesh->getCoordsAt(i)->getInfoOnComponent(0));
6711       std::string c,u;
6712       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
6713       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
6714       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
6715     }
6716   MEDFILESAFECALLERWR0(MEDmeshCr,(fid,maa,spaceDim,spaceDim,MED_STRUCTURED_MESH,desc,dtunit,MED_SORT_DTIT,MEDFileMeshL2::TraduceAxisTypeRev(getAxisType()),comp,unit));
6717   if(_univ_wr_status)
6718     MEDFILESAFECALLERWR0(MEDmeshUniversalNameWr,(fid,maa));
6719   MEDFILESAFECALLERWR0(MEDmeshGridTypeWr,(fid,maa,MEDFileMeshL2::TraduceAxisTypeRevStruct(getAxisType())));
6720   for(int i=0;i<spaceDim;i++)
6721     {
6722       const DataArrayDouble *da=_cmesh->getCoordsAt(i);
6723       MEDFILESAFECALLERWR0(MEDmeshGridIndexCoordinateWr,(fid,maa,_iteration,_order,_time,i+1,da->getNumberOfTuples(),da->getConstPointer()));
6724     }
6725   //
6726   std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE));
6727   MEDFileStructuredMesh::writeStructuredLL(fid,meshName);
6728 }
6729
6730 void MEDFileCMesh::synchronizeTinyInfoOnLeaves() const
6731 {
6732   const MEDCouplingCMesh *cmesh=_cmesh;
6733   if(!cmesh)
6734     return;
6735   (const_cast<MEDCouplingCMesh *>(cmesh))->setName(_name);
6736   (const_cast<MEDCouplingCMesh *>(cmesh))->setDescription(_desc_name);
6737   (const_cast<MEDCouplingCMesh *>(cmesh))->setTime(_time,_iteration,_order);
6738   (const_cast<MEDCouplingCMesh *>(cmesh))->setTimeUnit(_dt_unit);
6739 }
6740
6741 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New()
6742 {
6743   return new MEDFileCurveLinearMesh;
6744 }
6745
6746 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(med_idt fid, MEDFileMeshReadSelector *mrs)
6747 {
6748   return NewForTheFirstMeshInFile<MEDFileCurveLinearMesh>(fid,mrs);
6749 }
6750
6751 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const std::string& fileName, MEDFileMeshReadSelector *mrs)
6752 {
6753   MEDFileUtilities::AutoFid fid(OpenMEDFileForRead(fileName));
6754   return New(fid,mrs);
6755 }
6756
6757 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const std::string& fileName, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6758 {
6759   MEDFileUtilities::AutoFid fid(OpenMEDFileForRead(fileName));
6760   return New(fid,mName,dt,it,mrs);
6761 }
6762
6763 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6764 {
6765   return new MEDFileCurveLinearMesh(fid,mName,dt,it,mrs);
6766 }
6767
6768 std::size_t MEDFileCurveLinearMesh::getHeapMemorySizeWithoutChildren() const
6769 {
6770   return MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren();
6771 }
6772
6773 std::vector<const BigMemoryObject *> MEDFileCurveLinearMesh::getDirectChildrenWithNull() const
6774 {
6775   std::vector<const BigMemoryObject *> ret(MEDFileStructuredMesh::getDirectChildrenWithNull());
6776   ret.push_back((const MEDCouplingCurveLinearMesh *)_clmesh);
6777   return ret;
6778 }
6779
6780 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::shallowCpy() const
6781 {
6782   MCAuto<MEDFileCurveLinearMesh> ret(new MEDFileCurveLinearMesh(*this));
6783   return ret.retn();
6784 }
6785
6786 MEDFileMesh *MEDFileCurveLinearMesh::createNewEmpty() const
6787 {
6788   return new MEDFileCurveLinearMesh;
6789 }
6790
6791 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::deepCopy() const
6792 {
6793   MCAuto<MEDFileCurveLinearMesh> ret(new MEDFileCurveLinearMesh(*this));
6794   ret->deepCpyEquivalences(*this);
6795   if((const MEDCouplingCurveLinearMesh*)_clmesh)
6796     ret->_clmesh=static_cast<MEDCouplingCurveLinearMesh*>(_clmesh->deepCopy());
6797   ret->deepCpyAttributes();
6798   return ret.retn();
6799 }
6800
6801 int MEDFileCurveLinearMesh::getMeshDimension() const
6802 {
6803   if(!((const MEDCouplingCurveLinearMesh*)_clmesh))
6804     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::getMeshDimension : unable to get meshdimension because no mesh set !");
6805   return _clmesh->getMeshDimension();
6806 }
6807
6808 std::string MEDFileCurveLinearMesh::simpleRepr() const
6809 {
6810   return MEDFileStructuredMesh::simpleRepr();
6811 }
6812
6813 std::string MEDFileCurveLinearMesh::advancedRepr() const
6814 {
6815   return simpleRepr();
6816 }
6817
6818 bool MEDFileCurveLinearMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
6819 {
6820   if(!MEDFileStructuredMesh::isEqual(other,eps,what))
6821     return false;
6822   const MEDFileCurveLinearMesh *otherC=dynamic_cast<const MEDFileCurveLinearMesh *>(other);
6823   if(!otherC)
6824     {
6825       what="Mesh types differ ! This is curve linear and other is NOT !";
6826       return false;
6827     }
6828   clearNonDiscrAttributes();
6829   otherC->clearNonDiscrAttributes();
6830   const MEDCouplingCurveLinearMesh *coo1=_clmesh;
6831   const MEDCouplingCurveLinearMesh *coo2=otherC->_clmesh;
6832   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
6833     {
6834       what="Mismatch of curve linear meshes ! One is defined and not other !";
6835       return false;
6836     }
6837   if(coo1)
6838     {
6839       bool ret=coo1->isEqual(coo2,eps);
6840       if(!ret)
6841         {
6842           what="curve linear meshes differ !";
6843           return false;
6844         }
6845     }
6846   return true;
6847 }
6848
6849 void MEDFileCurveLinearMesh::clearNonDiscrAttributes() const
6850 {
6851   MEDFileStructuredMesh::clearNonDiscrAttributes();
6852   MEDFileUMeshSplitL1::ClearNonDiscrAttributes(_clmesh);//to it is not a bug umeshsplit have already the method implemented
6853 }
6854
6855 void MEDFileCurveLinearMesh::synchronizeTinyInfoOnLeaves() const
6856 {
6857   const MEDCouplingCurveLinearMesh *clmesh=_clmesh;
6858   if(!clmesh)
6859     return;
6860   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setName(_name);
6861   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setDescription(_desc_name);
6862   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setTime(_time,_iteration,_order);
6863   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setTimeUnit(_dt_unit);
6864 }
6865
6866 const MEDCouplingCurveLinearMesh *MEDFileCurveLinearMesh::getMesh() const
6867 {
6868   synchronizeTinyInfoOnLeaves();
6869   return _clmesh;
6870 }
6871
6872 void MEDFileCurveLinearMesh::setMesh(MEDCouplingCurveLinearMesh *m)
6873 {
6874   dealWithTinyInfo(m);
6875   if(m)
6876     m->incrRef();
6877   _clmesh=m;
6878 }
6879
6880 MEDFileMesh *MEDFileCurveLinearMesh::cartesianize() const
6881 {
6882   if(getAxisType()==AX_CART)
6883     {
6884       incrRef();
6885       return const_cast<MEDFileCurveLinearMesh *>(this);
6886     }
6887   else
6888     {
6889       const MEDCouplingCurveLinearMesh *mesh(getMesh());
6890       if(!mesh)
6891         throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::cartesianize : impossible to turn into cartesian because the mesh is null !");
6892       const DataArrayDouble *coords(mesh->getCoords());
6893       if(!coords)
6894         throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::cartesianize : coordinate pointer in mesh is null !");
6895       MCAuto<MEDFileCurveLinearMesh> ret(new MEDFileCurveLinearMesh(*this));
6896       MCAuto<MEDCouplingCurveLinearMesh> mesh2(mesh->clone(false));
6897       MCAuto<DataArrayDouble> coordsCart(coords->cartesianize(getAxisType()));
6898       mesh2->setCoords(coordsCart);
6899       ret->setMesh(mesh2);
6900       ret->setAxisType(AX_CART);
6901       return ret.retn();
6902     }
6903 }
6904
6905 const MEDCouplingStructuredMesh *MEDFileCurveLinearMesh::getStructuredMesh() const
6906 {
6907   synchronizeTinyInfoOnLeaves();
6908   return _clmesh;
6909 }
6910
6911 MEDFileCurveLinearMesh::MEDFileCurveLinearMesh()
6912 {
6913 }
6914
6915 MEDFileCurveLinearMesh::MEDFileCurveLinearMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6916 try
6917 {
6918     loadLLWithAdditionalItems(fid,mName,dt,it,mrs);
6919 }
6920 catch(INTERP_KERNEL::Exception& e)
6921 {
6922     throw e;
6923 }
6924
6925 void MEDFileCurveLinearMesh::writeMeshLL(med_idt fid) const
6926 {
6927   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
6928   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
6929   INTERP_KERNEL::AutoPtr<char> dtunit=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE);
6930   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
6931   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
6932   MEDLoaderBase::safeStrCpy(_dt_unit.c_str(),MED_LNAME_SIZE,dtunit,_too_long_str);
6933   int spaceDim=_clmesh->getSpaceDimension();
6934   int meshDim=_clmesh->getMeshDimension();
6935   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
6936   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
6937   const DataArrayDouble *coords=_clmesh->getCoords();
6938   if(!coords)
6939     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::writeMeshLL : no coordinates set !");
6940   for(int i=0;i<spaceDim;i++)
6941     {
6942       std::string info(_clmesh->getCoords()->getInfoOnComponent(i));
6943       std::string c,u;
6944       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
6945       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
6946       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
6947     }
6948   MEDFILESAFECALLERWR0(MEDmeshCr,(fid,maa,spaceDim,meshDim,MED_STRUCTURED_MESH,desc,dtunit,MED_SORT_DTIT,MEDFileMeshL2::TraduceAxisTypeRev(getAxisType()),comp,unit));
6949   if(_univ_wr_status)
6950     MEDFILESAFECALLERWR0(MEDmeshUniversalNameWr,(fid,maa));
6951   MEDFILESAFECALLERWR0(MEDmeshGridTypeWr,(fid,maa,MED_CURVILINEAR_GRID));
6952   std::vector<int> nodeGridSt=_clmesh->getNodeGridStructure();
6953   MEDFILESAFECALLERWR0(MEDmeshGridStructWr,(fid,maa,_iteration,_order,_time,&nodeGridSt[0]));
6954
6955   MEDFILESAFECALLERWR0(MEDmeshNodeCoordinateWr,(fid,maa,_iteration,_order,_time,MED_FULL_INTERLACE,coords->getNumberOfTuples(),coords->begin()));
6956   //
6957   std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE));
6958   MEDFileStructuredMesh::writeStructuredLL(fid,meshName);
6959 }
6960
6961 void MEDFileCurveLinearMesh::loadLL(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6962 {
6963   MEDCoupling::MEDCouplingMeshType meshType;
6964   int dummy0,dummy1;
6965   std::string dtunit;
6966   MEDCoupling::MEDCouplingAxisType axType;
6967   INTERP_KERNEL::AutoCppPtr<MeshOrStructMeshCls> mid(MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,axType,dummy0,dummy1,dtunit));
6968   setAxisType(axType);
6969   if(meshType!=CURVE_LINEAR)
6970     {
6971       std::ostringstream oss; oss << "Trying to load as curve linear an existing mesh with name '" << mName << "' that is NOT curve linear !";
6972       throw INTERP_KERNEL::Exception(oss.str().c_str());
6973     }
6974   MEDFileCLMeshL2 loaderl2;
6975   loaderl2.loadAll(fid,mid,mName,dt,it);
6976   MEDCouplingCurveLinearMesh *mesh=loaderl2.getMesh();
6977   mesh->incrRef();
6978   _clmesh=mesh;
6979   loadStrMeshFromFile(&loaderl2,fid,mName,dt,it,mrs);
6980 }
6981
6982 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New()
6983 {
6984   return new MEDFileMeshMultiTS;
6985 }
6986
6987 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(med_idt fid)
6988 {
6989   return new MEDFileMeshMultiTS(fid);
6990 }
6991
6992 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(const std::string& fileName)
6993 {
6994   MEDFileUtilities::AutoFid fid(OpenMEDFileForRead(fileName));
6995   return New(fid);
6996 }
6997
6998 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(med_idt fid, const std::string& mName)
6999 {
7000   return new MEDFileMeshMultiTS(fid,mName);
7001 }
7002
7003 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(const std::string& fileName, const std::string& mName)
7004 {
7005   MEDFileUtilities::AutoFid fid(OpenMEDFileForRead(fileName));
7006   return New(fid,mName);
7007 }
7008
7009 MEDFileMeshMultiTS *MEDFileMeshMultiTS::deepCopy() const
7010 {
7011   MCAuto<MEDFileMeshMultiTS> ret(MEDFileMeshMultiTS::New());
7012   std::vector< MCAuto<MEDFileMesh> > meshOneTs(_mesh_one_ts.size());
7013   std::size_t i(0);
7014   for(std::vector< MCAuto<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++,i++)
7015     if((const MEDFileMesh *)*it)
7016       meshOneTs[i]=(*it)->deepCopy();
7017   ret->_mesh_one_ts=meshOneTs;
7018   return ret.retn();
7019 }
7020
7021 std::size_t MEDFileMeshMultiTS::getHeapMemorySizeWithoutChildren() const
7022 {
7023   return _mesh_one_ts.capacity()*sizeof(MCAuto<MEDFileMesh>);
7024 }
7025
7026 std::vector<const BigMemoryObject *> MEDFileMeshMultiTS::getDirectChildrenWithNull() const
7027 {
7028   std::vector<const BigMemoryObject *> ret;
7029   for(std::vector< MCAuto<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
7030     ret.push_back((const MEDFileMesh *)*it);
7031   return ret;
7032 }
7033
7034 std::string MEDFileMeshMultiTS::getName() const
7035 {
7036   if(_mesh_one_ts.empty())
7037     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::getName : no time steps set !");
7038   return _mesh_one_ts[0]->getName();
7039 }
7040
7041 void MEDFileMeshMultiTS::setName(const std::string& newMeshName)
7042 {
7043   std::string oldName(getName());
7044   std::vector< std::pair<std::string,std::string> > v(1);
7045   v[0].first=oldName; v[0].second=newMeshName;
7046   changeNames(v);
7047 }
7048
7049 bool MEDFileMeshMultiTS::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab)
7050 {
7051   bool ret=false;
7052   for(std::vector< MCAuto<MEDFileMesh> >::iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
7053     {
7054       MEDFileMesh *cur(*it);
7055       if(cur)
7056         ret=cur->changeNames(modifTab) || ret;
7057     }
7058   return ret;
7059 }
7060
7061 void MEDFileMeshMultiTS::cartesianizeMe()
7062 {
7063   for(std::vector< MCAuto<MEDFileMesh> >::iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
7064     {
7065       MEDFileMesh *cur(*it);
7066       if(cur)
7067         {
7068           MCAuto<MEDFileMesh> ccur(cur->cartesianize());// Attention ! Do not wrap these two lines because memory leak !
7069           *it=ccur;
7070         }
7071     }
7072 }
7073
7074 MEDFileMesh *MEDFileMeshMultiTS::getOneTimeStep() const
7075 {
7076   if(_mesh_one_ts.empty())
7077     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::getOneTimeStep : empty time step set !");
7078   return const_cast<MEDFileMesh *>(static_cast<const MEDFileMesh *>(_mesh_one_ts[0]));
7079 }
7080
7081 void MEDFileMeshMultiTS::setOneTimeStep(MEDFileMesh *mesh1TimeStep)
7082 {
7083   if(!mesh1TimeStep)
7084     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::setOneTimeStep : input pointer should be different from 0 !");
7085   _mesh_one_ts.resize(1);
7086   mesh1TimeStep->incrRef();
7087   //MCAuto<MEDFileMesh> toto=mesh1TimeStep;
7088   _mesh_one_ts[0]=mesh1TimeStep;
7089 }
7090
7091 MEDFileJoints * MEDFileMeshMultiTS::getJoints() const
7092 {
7093   if ( MEDFileMesh* m = getOneTimeStep() )
7094     return m->getJoints();
7095   return 0;
7096 }
7097
7098 /*!
7099  * \brief Set Joints that are common to all time-stamps
7100  */
7101 void MEDFileMeshMultiTS::setJoints( MEDFileJoints* joints )
7102 {
7103   for(std::vector< MCAuto<MEDFileMesh> >::iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
7104     {
7105       (*it)->setJoints( joints );
7106     }
7107 }
7108
7109 bool MEDFileMeshMultiTS::presenceOfStructureElements() const
7110 {
7111   for(std::vector< MCAuto<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
7112     if((*it).isNotNull())
7113       if((*it)->presenceOfStructureElements())
7114         return true;
7115   return false;
7116 }
7117
7118 void MEDFileMeshMultiTS::killStructureElements()
7119 {
7120   for(std::vector< MCAuto<MEDFileMesh> >::iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
7121     if((*it).isNotNull())
7122       (*it)->killStructureElements();
7123 }
7124
7125 void MEDFileMeshMultiTS::writeLL(med_idt fid) const
7126 {
7127   MEDFileJoints *joints(getJoints());
7128   bool jointsWritten(false);
7129
7130   for(std::vector< MCAuto<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
7131     {
7132       if ( jointsWritten )
7133         const_cast<MEDFileMesh&>(**it).setJoints( 0 );
7134       else
7135         jointsWritten = true;
7136
7137       (*it)->copyOptionsFrom(*this);
7138       (*it)->writeLL(fid);
7139     }
7140
7141   (const_cast<MEDFileMeshMultiTS*>(this))->setJoints( joints ); // restore joints
7142 }
7143
7144 void MEDFileMeshMultiTS::loadFromFile(med_idt fid, const std::string& mName)
7145 {
7146   MEDFileJoints *joints(0);
7147   if ( !_mesh_one_ts.empty() && getOneTimeStep() )
7148     {
7149       // joints of mName already read, pass them to MEDFileMesh::New() to prevent repeated reading
7150       joints = getOneTimeStep()->getJoints();
7151     }
7152   _mesh_one_ts.clear();  //for the moment to be improved
7153   _mesh_one_ts.push_back( MEDFileMesh::New(fid,mName,-1,-1,0, joints ));
7154 }
7155
7156 MEDFileMeshMultiTS::MEDFileMeshMultiTS()
7157 {
7158 }
7159
7160 MEDFileMeshMultiTS::MEDFileMeshMultiTS(med_idt fid)
7161 try
7162 {
7163   std::vector<std::string> ms(MEDLoaderNS::getMeshNamesFid(fid));
7164     if(ms.empty())
7165       {
7166         std::ostringstream oss; oss << "MEDFileMeshMultiTS : no meshes in file \"" << FileNameFromFID(fid) << "\" !";
7167         throw INTERP_KERNEL::Exception(oss.str().c_str());
7168       }
7169     int dt,it;
7170     MEDCoupling::MEDCouplingMeshType meshType;
7171     std::string dummy2;
7172     MEDCoupling::MEDCouplingAxisType dummy3;
7173     MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dummy3,dt,it,dummy2);
7174     loadFromFile(fid,ms.front());
7175 }
7176 catch(INTERP_KERNEL::Exception& e)
7177 {
7178     throw e;
7179 }
7180
7181 MEDFileMeshMultiTS::MEDFileMeshMultiTS(med_idt fid, const std::string& mName)
7182 try
7183 {
7184     loadFromFile(fid,mName);
7185 }
7186 catch(INTERP_KERNEL::Exception& e)
7187 {
7188     throw e;
7189 }
7190
7191 MEDFileMeshes *MEDFileMeshes::New()
7192 {
7193   return new MEDFileMeshes;
7194 }
7195
7196 MEDFileMeshes *MEDFileMeshes::New(med_idt fid)
7197 {
7198   return new MEDFileMeshes(fid);
7199 }
7200
7201 MEDFileMeshes *MEDFileMeshes::New(const std::string& fileName)
7202 {
7203   MEDFileUtilities::AutoFid fid(OpenMEDFileForRead(fileName));
7204   return New(fid);
7205 }
7206
7207 void MEDFileMeshes::writeLL(med_idt fid) const
7208 {
7209   checkConsistencyLight();
7210   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++)
7211     {
7212       (*it)->copyOptionsFrom(*this);
7213       (*it)->writeLL(fid);
7214     }
7215 }
7216
7217 //  MEDFileMeshes::writ checkConsistencyLight();
7218
7219 int MEDFileMeshes::getNumberOfMeshes() const
7220 {
7221   return _meshes.size();
7222 }
7223
7224 MEDFileMeshesIterator *MEDFileMeshes::iterator()
7225 {
7226   return new MEDFileMeshesIterator(this);
7227 }
7228
7229 /** Return a borrowed reference (caller is not responsible) */
7230 MEDFileMesh *MEDFileMeshes::getMeshAtPos(int i) const
7231 {
7232   if(i<0 || i>=(int)_meshes.size())
7233     {
7234       std::ostringstream oss; oss << "MEDFileMeshes::getMeshAtPos : invalid mesh id given in parameter ! Should be in [0;" << _meshes.size() << ") !";
7235       throw INTERP_KERNEL::Exception(oss.str().c_str());
7236     }
7237   return _meshes[i]->getOneTimeStep();
7238 }
7239
7240 /** Return a borrowed reference (caller is not responsible) */
7241 MEDFileMesh *MEDFileMeshes::getMeshWithName(const std::string& mname) const
7242 {
7243   std::vector<std::string> ms=getMeshesNames();
7244   std::vector<std::string>::iterator it=std::find(ms.begin(),ms.end(),mname);
7245   if(it==ms.end())
7246     {
7247       std::ostringstream oss; oss << "MEDFileMeshes::getMeshWithName : Mesh  \"" << mname << "\" does not exist in this ! Existing are : ";
7248       std::copy(ms.begin(),ms.end(),std::ostream_iterator<std::string>(oss," "));
7249       throw INTERP_KERNEL::Exception(oss.str().c_str());
7250     }
7251   return getMeshAtPos((int)std::distance(ms.begin(),it));
7252 }
7253
7254 std::vector<std::string> MEDFileMeshes::getMeshesNames() const
7255 {
7256   std::vector<std::string> ret(_meshes.size());
7257   int i=0;
7258   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
7259     {
7260       const MEDFileMeshMultiTS *f=(*it);
7261       if(f)
7262         {
7263           ret[i]=f->getName();
7264         }
7265       else
7266         {
7267           std::ostringstream oss; oss << "MEDFileMeshes::getMeshesNames : At rank #" << i << " mesh is not defined !";
7268           throw INTERP_KERNEL::Exception(oss.str().c_str());
7269         }
7270     }
7271   return ret;
7272 }
7273
7274 bool MEDFileMeshes::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab)
7275 {
7276   bool ret=false;
7277   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::iterator it=_meshes.begin();it!=_meshes.end();it++)
7278     {
7279       MEDFileMeshMultiTS *cur(*it);
7280       if(cur)
7281         ret=cur->changeNames(modifTab) || ret;
7282     }
7283   return ret;
7284 }
7285
7286 void MEDFileMeshes::cartesianizeMe()
7287 {
7288   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::iterator it=_meshes.begin();it!=_meshes.end();it++)
7289     {
7290       MEDFileMeshMultiTS *cur(*it);
7291       if(cur)
7292         cur->cartesianizeMe();
7293     }
7294 }
7295
7296 void MEDFileMeshes::resize(int newSize)
7297 {
7298   _meshes.resize(newSize);
7299 }
7300
7301 void MEDFileMeshes::pushMesh(MEDFileMesh *mesh)
7302 {
7303   if(!mesh)
7304     throw INTERP_KERNEL::Exception("MEDFileMeshes::pushMesh : invalid input pointer ! should be different from 0 !");
7305   MEDFileMeshMultiTS *elt=MEDFileMeshMultiTS::New();
7306   elt->setOneTimeStep(mesh);
7307   _meshes.push_back(elt);
7308 }
7309
7310 void MEDFileMeshes::setMeshAtPos(int i, MEDFileMesh *mesh)
7311 {
7312   if(!mesh)
7313     throw INTERP_KERNEL::Exception("MEDFileMeshes::setMeshAtPos : invalid input pointer ! should be different from 0 !");
7314   if(i>=(int)_meshes.size())
7315     _meshes.resize(i+1);
7316   MEDFileMeshMultiTS *elt=MEDFileMeshMultiTS::New();
7317   elt->setOneTimeStep(mesh);
7318   _meshes[i]=elt;
7319 }
7320
7321 void MEDFileMeshes::destroyMeshAtPos(int i)
7322 {
7323   if(i<0 || i>=(int)_meshes.size())
7324     {
7325       std::ostringstream oss; oss << "MEDFileMeshes::destroyMeshAtPos : Invalid given id in input (" << i << ") should be in [0," << _meshes.size() << ") !";
7326       throw INTERP_KERNEL::Exception(oss.str().c_str());
7327     }
7328   _meshes.erase(_meshes.begin()+i);
7329 }
7330
7331 void MEDFileMeshes::loadFromFile(med_idt fid)
7332 {
7333   std::vector<std::string> ms(MEDLoaderNS::getMeshNamesFid(fid));
7334   int i=0;
7335   _meshes.resize(ms.size());
7336   for(std::vector<std::string>::const_iterator it=ms.begin();it!=ms.end();it++,i++)
7337     _meshes[i]=MEDFileMeshMultiTS::New(fid,(*it));
7338 }
7339
7340 MEDFileMeshes::MEDFileMeshes()
7341 {
7342 }
7343
7344 MEDFileMeshes::MEDFileMeshes(med_idt fid)
7345 try
7346 {
7347     loadFromFile(fid);
7348 }
7349 catch(INTERP_KERNEL::Exception& /*e*/)
7350 {
7351 }
7352
7353 MEDFileMeshes *MEDFileMeshes::deepCopy() const
7354 {
7355   std::vector< MCAuto<MEDFileMeshMultiTS> > meshes(_meshes.size());
7356   std::size_t i=0;
7357   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
7358     if((const MEDFileMeshMultiTS *)*it)
7359       meshes[i]=(*it)->deepCopy();
7360   MCAuto<MEDFileMeshes> ret(MEDFileMeshes::New());
7361   ret->_meshes=meshes;
7362   return ret.retn();
7363 }
7364
7365 std::size_t MEDFileMeshes::getHeapMemorySizeWithoutChildren() const
7366 {
7367   return _meshes.capacity()*(sizeof(MCAuto<MEDFileMeshMultiTS>));
7368 }
7369
7370 std::vector<const BigMemoryObject *> MEDFileMeshes::getDirectChildrenWithNull() const
7371 {
7372   std::vector<const BigMemoryObject *> ret;
7373   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++)
7374     ret.push_back((const MEDFileMeshMultiTS *)*it);
7375   return ret;
7376 }
7377
7378 std::string MEDFileMeshes::simpleRepr() const
7379 {
7380   std::ostringstream oss;
7381   oss << "(*****************)\n(* MEDFileMeshes *)\n(*****************)\n\n";
7382   simpleReprWithoutHeader(oss);
7383   return oss.str();
7384 }
7385
7386 void MEDFileMeshes::simpleReprWithoutHeader(std::ostream& oss) const
7387 {
7388   int nbOfMeshes=getNumberOfMeshes();
7389   oss << "There are " << nbOfMeshes << " meshes with the following names : \n";
7390   std::vector<std::string> mns=getMeshesNames();
7391   for(int i=0;i<nbOfMeshes;i++)
7392     oss << "  - #" << i << " \"" << mns[i] << "\"\n";
7393 }
7394
7395 void MEDFileMeshes::checkConsistencyLight() const
7396 {
7397   static const char MSG[]="MEDFileMeshes::checkConsistencyLight : mesh at rank ";
7398   int i=0;
7399   std::set<std::string> s;
7400   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
7401     {
7402       const MEDFileMeshMultiTS *elt=(*it);
7403       if(!elt)
7404         {
7405           std::ostringstream oss; oss << MSG << i << "/" << _meshes.size() << " is empty !";
7406           throw INTERP_KERNEL::Exception(oss.str().c_str());
7407         }
7408       std::size_t sz=s.size();
7409       s.insert(std::string((*it)->getName()));
7410       if(s.size()==sz)
7411         {
7412           std::ostringstream oss; oss << MSG << i << " has a name (\"" << (*it)->getName() << "\") already used by an another mesh in list !";
7413           throw INTERP_KERNEL::Exception(oss.str().c_str());
7414         }
7415     }
7416 }
7417
7418 bool MEDFileMeshes::presenceOfStructureElements() const
7419 {
7420   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++)
7421     if((*it).isNotNull())
7422       if((*it)->presenceOfStructureElements())
7423         return true;
7424   return false;
7425 }
7426
7427 void MEDFileMeshes::killStructureElements()
7428 {
7429   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::iterator it=_meshes.begin();it!=_meshes.end();it++)
7430     if((*it).isNotNull())
7431       (*it)->killStructureElements();
7432 }
7433
7434 MEDFileMeshesIterator::MEDFileMeshesIterator(MEDFileMeshes *ms):_ms(ms),_iter_id(0),_nb_iter(0)
7435 {
7436   if(ms)
7437     {
7438       ms->incrRef();
7439       _nb_iter=ms->getNumberOfMeshes();
7440     }
7441 }
7442
7443 MEDFileMeshesIterator::~MEDFileMeshesIterator()
7444 {
7445 }
7446
7447 MEDFileMesh *MEDFileMeshesIterator::nextt()
7448 {
7449   if(_iter_id<_nb_iter)
7450     {
7451       MEDFileMeshes *ms(_ms);
7452       if(ms)
7453         return ms->getMeshAtPos(_iter_id++);
7454       else
7455         return 0;
7456     }
7457   else
7458     return 0;
7459 }
7460
7461 INTERP_KERNEL::NormalizedCellType MEDFileMesh::ConvertFromMEDFileGeoType(med_geometry_type geoType)
7462 {
7463   med_geometry_type *pos(std::find(typmai,typmai+MED_N_CELL_FIXED_GEO,geoType));
7464   if(pos==typmai+MED_N_CELL_FIXED_GEO)
7465     {
7466       if(geoType==MED_NO_GEOTYPE)
7467         return INTERP_KERNEL::NORM_ERROR;
7468       std::ostringstream oss; oss << "MEDFileMesh::ConvertFromMEDFileGeoType : no entry with " << geoType << " !"; 
7469       throw INTERP_KERNEL::Exception(oss.str());
7470     }
7471   return typmai2[std::distance(typmai,pos)];
7472 }
7473
7474 TypeOfField MEDFileMesh::ConvertFromMEDFileEntity(med_entity_type etype)
7475 {
7476   switch(etype)
7477     {
7478     case MED_NODE:
7479       return ON_NODES;
7480     case MED_CELL:
7481       return ON_CELLS;
7482     default:
7483       {
7484         std::ostringstream oss; oss << "EDFileMesh::ConvertFromMEDFileEntity : not recognized entity " << etype << " !";
7485         throw INTERP_KERNEL::Exception(oss.str());
7486       }
7487     }
7488 }
7489
7490