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