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