Salome HOME
Merge branch 'abn/tests_from_build'
[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       ret->setAxType(AX_CART);
3168       return ret.retn();
3169     }
3170 }
3171
3172 /*!
3173  * Returns the optional numbers of mesh entities of a given dimension transformed using
3174  * DataArrayInt::invertArrayN2O2O2N().
3175  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
3176  *  \return const DataArrayInt * - the array of the entity numbers transformed using
3177  *          DataArrayInt::invertArrayN2O2O2N().
3178  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3179  */
3180 const DataArrayInt *MEDFileUMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxExt) const
3181 {
3182   if(meshDimRelToMaxExt==1)
3183     {
3184       if(!((const DataArrayInt *)_num_coords))
3185         throw INTERP_KERNEL::Exception("MEDFileUMesh::getRevNumberFieldAtLevel : no coordinates renum specified !");
3186       return _rev_num_coords;
3187     }
3188   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3189   return l1->getRevNumberField();
3190 }
3191
3192 /*!
3193  * Returns a pointer to the node coordinates array of \a this mesh \b without
3194  * incrementing its reference counter, thus there is no need to decrRef() it by the caller.
3195  */
3196 DataArrayDouble *MEDFileUMesh::getCoords() const
3197 {
3198   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp(_coords);
3199   if((DataArrayDouble *)tmp)
3200     {
3201       return tmp;
3202     }
3203   return 0;
3204 }
3205
3206 /*!
3207  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in a given
3208  * group of \a this mesh. Only mesh entities of a given dimension are included in the
3209  * new mesh.
3210  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
3211  *  \param [in] grp - the name of the group whose mesh entities are included in the
3212  *          new mesh.
3213  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
3214  *          according to the optional numbers of entities, if available.
3215  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
3216  *          delete this mesh using decrRef() as it is no more needed.
3217  *  \throw If the name of a nonexistent group is specified.
3218  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3219  */
3220 MEDCouplingUMesh *MEDFileUMesh::getGroup(int meshDimRelToMaxExt, const std::string& grp, bool renum) const
3221 {
3222   synchronizeTinyInfoOnLeaves();
3223   std::vector<std::string> tmp(1);
3224   tmp[0]=grp;
3225   return getGroups(meshDimRelToMaxExt,tmp,renum);
3226 }
3227
3228 /*!
3229  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in given
3230  * groups of \a this mesh. Only mesh entities of a given dimension are included in the
3231  * new mesh.
3232  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
3233  *  \param [in] grps - a sequence of group names whose mesh entities are included in the
3234  *          new mesh.
3235  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
3236  *          according to the optional numbers of entities, if available.
3237  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
3238  *          delete this mesh using decrRef() as it is no more needed.
3239  *  \throw If a name of a nonexistent group is present in \a grps.
3240  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3241  */
3242 MEDCouplingUMesh *MEDFileUMesh::getGroups(int meshDimRelToMaxExt, const std::vector<std::string>& grps, bool renum) const
3243 {
3244   synchronizeTinyInfoOnLeaves();
3245   std::vector<std::string> fams2=getFamiliesOnGroups(grps);
3246   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> zeRet=getFamilies(meshDimRelToMaxExt,fams2,renum);
3247   if(grps.size()==1 && ((MEDCouplingUMesh *)zeRet))
3248     zeRet->setName(grps[0]);
3249   return zeRet.retn();
3250 }
3251
3252 /*!
3253  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in a given
3254  * family of \a this mesh. Only mesh entities of a given dimension are included in the
3255  * new mesh.
3256  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
3257  *  \param [in] fam - the name of the family whose mesh entities are included in the
3258  *          new mesh.
3259  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
3260  *          according to the optional numbers of entities, if available.
3261  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
3262  *          delete this mesh using decrRef() as it is no more needed.
3263  *  \throw If a name of a nonexistent family is present in \a grps.
3264  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3265  */
3266 MEDCouplingUMesh *MEDFileUMesh::getFamily(int meshDimRelToMaxExt, const std::string& fam, bool renum) const
3267 {
3268   synchronizeTinyInfoOnLeaves();
3269   std::vector<std::string> tmp(1);
3270   tmp[0]=fam;
3271   return getFamilies(meshDimRelToMaxExt,tmp,renum);
3272 }
3273
3274 /*!
3275  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in given
3276  * families of \a this mesh. Only mesh entities of a given dimension are included in the
3277  * new mesh.
3278  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
3279  *  \param [in] fams - a sequence of family names whose mesh entities are included in the
3280  *          new mesh.
3281  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
3282  *          according to the optional numbers of entities, if available.
3283  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
3284  *          delete this mesh using decrRef() as it is no more needed.
3285  *  \throw If a name of a nonexistent family is present in \a fams.
3286  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3287  */
3288 MEDCouplingUMesh *MEDFileUMesh::getFamilies(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const
3289 {
3290   synchronizeTinyInfoOnLeaves();
3291   if(meshDimRelToMaxExt==1)
3292     {
3293       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr=getFamiliesArr(1,fams,renum);
3294       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3295       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> c=_coords->selectByTupleId(arr->getConstPointer(),arr->getConstPointer()+arr->getNbOfElems());
3296       ret->setCoords(c);
3297       return ret.retn();
3298     }
3299   std::vector<int> famIds=getFamiliesIds(fams);
3300   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3301   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> zeRet;
3302   if(!famIds.empty())
3303     zeRet=l1->getFamilyPart(&famIds[0],&famIds[0]+famIds.size(),renum);
3304   else
3305     zeRet=l1->getFamilyPart(0,0,renum);
3306   if(fams.size()==1 && ((MEDCouplingUMesh *)zeRet))
3307     zeRet->setName(fams[0]);
3308   return zeRet.retn();
3309 }
3310
3311 /*!
3312  * Returns ids of mesh entities contained in given families of a given dimension.
3313  *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
3314  *          are required.
3315  *  \param [in] fams - the names of the families of interest.
3316  *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
3317  *          returned instead of ids.
3318  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
3319  *          numbers, if available and required, of mesh entities of the families. The caller
3320  *          is to delete this array using decrRef() as it is no more needed. 
3321  *  \throw If the family field is missing for \a meshDimRelToMaxExt.
3322  */
3323 DataArrayInt *MEDFileUMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const
3324 {
3325   std::vector<int> famIds=getFamiliesIds(fams);
3326   if(meshDimRelToMaxExt==1)
3327     {
3328       if((const DataArrayInt *)_fam_coords)
3329         {
3330           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
3331           if(!famIds.empty())
3332             da=_fam_coords->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
3333           else
3334             da=_fam_coords->getIdsEqualList(0,0);
3335           if(renum)
3336             return MEDFileUMeshSplitL1::Renumber(_num_coords,da);
3337           else
3338             return da.retn();
3339         }
3340       else
3341         throw INTERP_KERNEL::Exception("MEDFileUMesh::getFamiliesArr : no family array specified on nodes !");
3342     }
3343   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3344   if(!famIds.empty())
3345     return l1->getFamilyPartArr(&famIds[0],&famIds[0]+famIds.size(),renum);
3346   else
3347     return l1->getFamilyPartArr(0,0,renum);
3348 }
3349
3350 /*!
3351  * Returns a MEDCouplingUMesh of a given relative dimension.
3352  * \warning If \a meshDimRelToMaxExt == 1 (which means nodes), the returned mesh **is not
3353  * valid**. This is a feature, because MEDLoader does not create cells that do not exist! 
3354  * To build a valid MEDCouplingUMesh from the returned one in this case,
3355  * call MEDCouplingUMesh::Build0DMeshFromCoords().
3356  *  \param [in] meshDimRelToMax - the relative dimension of interest.
3357  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3358  *          optional numbers of mesh entities.
3359  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
3360  *          delete using decrRef() as it is no more needed. 
3361  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3362  * \sa getGenMeshAtLevel()
3363  */
3364 MEDCouplingUMesh *MEDFileUMesh::getMeshAtLevel(int meshDimRelToMaxExt, bool renum) const
3365 {
3366   synchronizeTinyInfoOnLeaves();
3367   if(meshDimRelToMaxExt==1)
3368     {
3369       if(!renum)
3370         {
3371           MEDCouplingUMesh *umesh=MEDCouplingUMesh::New();
3372           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> cc=_coords->deepCpy();
3373           umesh->setCoords(cc);
3374           MEDFileUMeshSplitL1::ClearNonDiscrAttributes(umesh);
3375           umesh->setName(getName());
3376           return umesh;
3377         }
3378     }
3379   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3380   return l1->getWholeMesh(renum);
3381 }
3382
3383 /*!
3384  * Returns a MEDCouplingUMesh of a given relative dimension.
3385  * \warning If \a meshDimRelToMaxExt == 1 (which means nodes), the returned mesh **is not
3386  * valid**. This is a feature, because MEDLoader does not create cells that do not exist! 
3387  * To build a valid MEDCouplingUMesh from the returned one in this case,
3388  * call MEDCouplingUMesh::Build0DMeshFromCoords().
3389  *  \param [in] meshDimRelToMax - the relative dimension of interest.
3390  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3391  *          optional numbers of mesh entities.
3392  *  \return MEDCouplingMesh * - a pointer to MEDCouplingUMesh that the caller is to
3393  *          delete using decrRef() as it is no more needed. 
3394  *  \throw If there are no mesh entities of \a meshDimRelToMax dimension in \a this mesh.
3395  * \sa getMeshAtLevel()
3396  */
3397 MEDCouplingMesh *MEDFileUMesh::getGenMeshAtLevel(int meshDimRelToMax, bool renum) const
3398 {
3399   return getMeshAtLevel(meshDimRelToMax,renum);
3400 }
3401
3402 std::vector<int> MEDFileUMesh::getDistributionOfTypes(int meshDimRelToMax) const
3403 {
3404   const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMax));
3405   return l1->getDistributionOfTypes();
3406 }
3407
3408 /*!
3409  * Returns a MEDCouplingUMesh of a relative dimension == 0.
3410  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3411  *          optional numbers of mesh entities.
3412  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
3413  *          delete using decrRef() as it is no more needed. 
3414  *  \throw If there are no mesh entities of the relative dimension == 0 in \a this mesh.
3415  */
3416 MEDCouplingUMesh *MEDFileUMesh::getLevel0Mesh(bool renum) const
3417 {
3418   return getMeshAtLevel(0,renum);
3419 }
3420
3421 /*!
3422  * Returns a MEDCouplingUMesh of a relative dimension == -1.
3423  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3424  *          optional numbers of mesh entities.
3425  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
3426  *          delete using decrRef() as it is no more needed. 
3427  *  \throw If there are no mesh entities of the relative dimension == -1 in \a this mesh.
3428  */
3429 MEDCouplingUMesh *MEDFileUMesh::getLevelM1Mesh(bool renum) const
3430 {
3431   return getMeshAtLevel(-1,renum);
3432 }
3433
3434 /*!
3435  * Returns a MEDCouplingUMesh of a relative dimension == -2.
3436  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3437  *          optional numbers of mesh entities.
3438  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
3439  *          delete using decrRef() as it is no more needed. 
3440  *  \throw If there are no mesh entities of the relative dimension == -2 in \a this mesh.
3441  */
3442 MEDCouplingUMesh *MEDFileUMesh::getLevelM2Mesh(bool renum) const
3443 {
3444   return getMeshAtLevel(-2,renum);
3445 }
3446
3447 /*!
3448  * Returns a MEDCouplingUMesh of a relative dimension == -3.
3449  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3450  *          optional numbers of mesh entities.
3451  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
3452  *          delete using decrRef() as it is no more needed. 
3453  *  \throw If there are no mesh entities of the relative dimension == -3 in \a this mesh.
3454  */
3455 MEDCouplingUMesh *MEDFileUMesh::getLevelM3Mesh(bool renum) const
3456 {
3457   return getMeshAtLevel(-3,renum);
3458 }
3459
3460 /*!
3461  * This method is for advanced users. There is two storing strategy of mesh in \a this.
3462  * Either MEDCouplingUMesh, or vector of MEDCoupling1GTUMesh instances.
3463  * When assignement is done the first one is done, which is not optimal in write mode for MED file.
3464  * This method allows to switch from MEDCouplingUMesh mode to MEDCoupling1GTUMesh mode.
3465  */
3466 void MEDFileUMesh::forceComputationOfParts() const
3467 {
3468   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
3469     {
3470       const MEDFileUMeshSplitL1 *elt(*it);
3471       if(elt)
3472         elt->forceComputationOfParts();
3473     }
3474 }
3475
3476 /*!
3477  * This method returns a vector of mesh parts containing each exactly one geometric type.
3478  * This method will never launch an automatic computation of split by type (an INTERP_KERNEL::Exception will be then thrown).
3479  * This method is only for memory aware users.
3480  * The returned pointers are **NOT** new object pointer. No need to mange them.
3481  */
3482 std::vector<MEDCoupling1GTUMesh *> MEDFileUMesh::getDirectUndergroundSingleGeoTypeMeshes(int meshDimRelToMax) const
3483 {
3484   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(meshDimRelToMax));
3485   return sp->getDirectUndergroundSingleGeoTypeMeshes();
3486 }
3487
3488 /*!
3489  * This method returns the part of \a this having the geometric type \a gt.
3490  * If such part is not existing an exception will be thrown.
3491  * The returned pointer is **NOT** new object pointer. No need to mange it.
3492  */
3493 MEDCoupling1GTUMesh *MEDFileUMesh::getDirectUndergroundSingleGeoTypeMesh(INTERP_KERNEL::NormalizedCellType gt) const
3494 {
3495   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
3496   int lev=(int)cm.getDimension()-getMeshDimension();
3497   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(lev));
3498   return sp->getDirectUndergroundSingleGeoTypeMesh(gt);
3499 }
3500
3501 /*!
3502  * Given a relative level \a meshDimRelToMax it returns the sorted vector of geometric types present in \a this.
3503  * \throw if the reqsuested \a meshDimRelToMax does not exist.
3504  */
3505 std::vector<INTERP_KERNEL::NormalizedCellType> MEDFileUMesh::getGeoTypesAtLevel(int meshDimRelToMax) const
3506 {
3507   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(meshDimRelToMax));
3508   return sp->getGeoTypes();
3509 }
3510
3511 int MEDFileUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType ct) const
3512 {
3513   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(ct);
3514   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe( ((int)cm.getDimension())-getMeshDimension() ));
3515   return sp->getNumberOfCellsWithType(ct);
3516 }
3517
3518 /*!
3519  * This method extracts from whole family field ids the part relative to the input parameter \a gt.
3520  * \param [in] gt - the geometric type for which the family field is asked.
3521  * \return DataArrayInt * - a pointer to DataArrayInt that the caller is to
3522  *          delete using decrRef() as it is no more needed.
3523  * \sa MEDFileUMesh::extractNumberFieldOnGeoType
3524  */
3525 DataArrayInt *MEDFileUMesh::extractFamilyFieldOnGeoType(INTERP_KERNEL::NormalizedCellType gt) const
3526 {
3527   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
3528   int lev=(int)cm.getDimension()-getMeshDimension();
3529   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(lev));
3530   return sp->extractFamilyFieldOnGeoType(gt);
3531 }
3532
3533 /*!
3534  * This method extracts from whole number field ids the part relative to the input parameter \a gt.
3535  * \param [in] gt - the geometric type for which the number field is asked.
3536  * \return DataArrayInt * - a pointer to DataArrayInt that the caller is to
3537  *          delete using decrRef() as it is no more needed.
3538  * \sa MEDFileUMesh::extractFamilyFieldOnGeoType
3539  */
3540 DataArrayInt *MEDFileUMesh::extractNumberFieldOnGeoType(INTERP_KERNEL::NormalizedCellType gt) const
3541 {
3542   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
3543   int lev=(int)cm.getDimension()-getMeshDimension();
3544   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(lev));
3545   return sp->extractNumberFieldOnGeoType(gt);
3546 }
3547
3548 /*!
3549  * This method returns for specified geometric type \a gt the relative level to \a this.
3550  * If the relative level is empty an exception will be thrown.
3551  */
3552 int MEDFileUMesh::getRelativeLevOnGeoType(INTERP_KERNEL::NormalizedCellType gt) const
3553 {
3554   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
3555   int ret((int)cm.getDimension()-getMeshDimension());
3556   getMeshAtLevSafe(ret);//To test that returned value corresponds to a valid level.
3557   return ret;
3558 }
3559
3560 const MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt) const
3561 {
3562   if(meshDimRelToMaxExt==1)
3563     throw INTERP_KERNEL::Exception("Dimension request is invalid : asking for node level (1) !");
3564   if(meshDimRelToMaxExt>1)
3565     throw INTERP_KERNEL::Exception("Dimension request is invalid (>1) !");
3566   int tracucedRk=-meshDimRelToMaxExt;
3567   if(tracucedRk>=(int)_ms.size())
3568     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
3569   if((const MEDFileUMeshSplitL1 *)_ms[tracucedRk]==0)
3570     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3571   return _ms[tracucedRk];
3572 }
3573
3574 MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt)
3575 {
3576   if(meshDimRelToMaxExt==1)
3577     throw INTERP_KERNEL::Exception("Dimension request is invalid : asking for node level (1) !");
3578   if(meshDimRelToMaxExt>1)
3579     throw INTERP_KERNEL::Exception("Dimension request is invalid (>1) !");
3580   int tracucedRk=-meshDimRelToMaxExt;
3581   if(tracucedRk>=(int)_ms.size())
3582     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
3583   if((const MEDFileUMeshSplitL1 *)_ms[tracucedRk]==0)
3584     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3585   return _ms[tracucedRk];
3586 }
3587
3588 void MEDFileUMesh::checkMeshDimCoherency(int meshDim, int meshDimRelToMax) const
3589 {
3590   if(-meshDimRelToMax>=(int)_ms.size())
3591     throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMeshDimCoherency : The meshdim of mesh is not managed by 'this' !");
3592   int i=0;
3593   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,i++)
3594     {
3595       if(((const MEDFileUMeshSplitL1*) (*it))!=0)
3596         {
3597           int ref=(*it)->getMeshDimension();
3598           if(ref+i!=meshDim-meshDimRelToMax)
3599             throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMeshDimCoherency : no coherency between levels !");
3600         }
3601     }
3602 }
3603
3604 /*!
3605  * Sets the node coordinates array of \a this mesh.
3606  *  \param [in] coords - the new node coordinates array.
3607  *  \throw If \a coords == \c NULL.
3608  */
3609 void MEDFileUMesh::setCoords(DataArrayDouble *coords)
3610 {
3611   if(!coords)
3612     throw INTERP_KERNEL::Exception("MEDFileUMesh::setCoords : null pointer in input !");
3613   if(coords==(DataArrayDouble *)_coords)
3614     return ;
3615   coords->checkAllocated();
3616   int nbOfTuples=coords->getNumberOfTuples();
3617   _coords=coords;
3618   coords->incrRef();
3619   _fam_coords=DataArrayInt::New();
3620   _fam_coords->alloc(nbOfTuples,1);
3621   _fam_coords->fillWithZero();
3622   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
3623     if((MEDFileUMeshSplitL1 *)(*it))
3624       (*it)->setCoords(coords);
3625 }
3626
3627 /*!
3628  * Removes all groups of a given dimension in \a this mesh.
3629  *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
3630  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3631  */
3632 void MEDFileUMesh::eraseGroupsAtLevel(int meshDimRelToMaxExt)
3633 {
3634   if(meshDimRelToMaxExt==1)
3635     {
3636       if((DataArrayInt *)_fam_coords)
3637         _fam_coords->fillWithZero();
3638       return ;
3639     }
3640   MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3641   l1->eraseFamilyField();
3642   optimizeFamilies();
3643 }
3644
3645 /*!
3646  * Removes all families with ids not present in the family fields of \a this mesh.
3647  */
3648 void MEDFileUMesh::optimizeFamilies()
3649 {
3650   std::vector<int> levs=getNonEmptyLevelsExt();
3651   std::set<int> allFamsIds;
3652   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
3653     {
3654       const DataArrayInt *ffield=getFamilyFieldAtLevel(*it);
3655       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=ffield->getDifferentValues();
3656       std::set<int> res;
3657       std::set_union(ids->begin(),ids->end(),allFamsIds.begin(),allFamsIds.end(),std::inserter(res,res.begin()));
3658       allFamsIds=res;
3659     }
3660   std::set<std::string> famNamesToKill;
3661   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
3662     {
3663       if(allFamsIds.find((*it).second)!=allFamsIds.end())
3664         famNamesToKill.insert((*it).first);
3665     }
3666   for(std::set<std::string>::const_iterator it=famNamesToKill.begin();it!=famNamesToKill.end();it++)
3667     _families.erase(*it);
3668   std::vector<std::string> grpNamesToKill;
3669   for(std::map<std::string, std::vector<std::string> >::iterator it=_groups.begin();it!=_groups.end();it++)
3670     {
3671       std::vector<std::string> tmp;
3672       for(std::vector<std::string>::const_iterator it2=(*it).second.begin();it2!=(*it).second.end();it2++)
3673         {
3674           if(famNamesToKill.find(*it2)==famNamesToKill.end())
3675             tmp.push_back(*it2);
3676         }
3677       if(!tmp.empty())
3678         (*it).second=tmp;
3679       else
3680         tmp.push_back((*it).first);
3681     }
3682   for(std::vector<std::string>::const_iterator it=grpNamesToKill.begin();it!=grpNamesToKill.end();it++)
3683     _groups.erase(*it);
3684 }
3685
3686 /**
3687  * \b this must be filled at level 0 and -1, typically the -1 level being (part of) the descending connectivity
3688  * of the top level. This method build a "crack", or an inner boundary, in \b this along the group of level -1 named grpNameM1.
3689  * The boundary is built according to the following method:
3690  *  - all nodes along the boundary which are not lying on an internal extremity of the (-1)-level group are duplicated (so the
3691  * coordinates array is extended).
3692  *  - new (-1)-level cells are built lying on those new nodes. So the edges/faces along the group are duplicated.
3693  *  After this operation a top-level cell bordering the group will loose some neighbors (typically the cell which is  on the
3694  *  other side of the group is no more a neighbor)
3695  *   - finally, the connectivity of (part of) the top level-cells bordering the group is also modified so that some cells
3696  *  bordering the newly created boundary use the newly computed nodes.
3697  *
3698  *  \param[in] grpNameM1 name of the (-1)-level group defining the boundary
3699  *  \param[out] nodesDuplicated ids of the initial nodes which have been duplicated (and whose copy is put at the end of
3700  *  the coord array)
3701  *  \param[out] cellsModified ids of the cells whose connectivity has been modified (to use the newly created nodes)
3702  *  \param[out] cellsNotModified ids of the rest of cells bordering the new boundary whose connectivity remains unchanged.
3703  */
3704 void MEDFileUMesh::buildInnerBoundaryAlongM1Group(const std::string& grpNameM1, DataArrayInt *&nodesDuplicated,
3705                                            DataArrayInt *&cellsModified, DataArrayInt *&cellsNotModified)
3706 {
3707   std::vector<int> levs=getNonEmptyLevels();
3708   if(std::find(levs.begin(),levs.end(),0)==levs.end() || std::find(levs.begin(),levs.end(),-1)==levs.end())
3709     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildInnerBoundaryAlongM1Group : This method works only for mesh definied on level 0 and -1 !");
3710   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0=getMeshAtLevel(0);
3711   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1=getMeshAtLevel(-1);
3712   int nbNodes=m0->getNumberOfNodes();
3713   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m11=getGroup(-1,grpNameM1);
3714   DataArrayInt *tmp00=0,*tmp11=0,*tmp22=0;
3715   m0->findNodesToDuplicate(*m11,tmp00,tmp11,tmp22);
3716   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodeIdsToDuplicate(tmp00);
3717   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0(tmp11);
3718   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1(tmp22);
3719   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp0=static_cast<MEDCouplingUMesh *>(m0->buildPartOfMySelf(cellsToModifyConn0->begin(),cellsToModifyConn0->end(),true));
3720   // node renumbering of cells in m1 impacted by duplication of node but not in group 'grpNameM1' on level -1
3721   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descTmp0=DataArrayInt::New(),descITmp0=DataArrayInt::New(),revDescTmp0=DataArrayInt::New(),revDescITmp0=DataArrayInt::New();
3722   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp0Desc=tmp0->buildDescendingConnectivity(descTmp0,descITmp0,revDescTmp0,revDescITmp0);
3723   descTmp0=0; descITmp0=0; revDescTmp0=0; revDescITmp0=0;
3724   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsInM1ToRenumW2=tmp0Desc->getCellIdsLyingOnNodes(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),false);
3725   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cellsInM1ToRenumW3=static_cast<MEDCouplingUMesh *>(tmp0Desc->buildPartOfMySelf(cellsInM1ToRenumW2->begin(),cellsInM1ToRenumW2->end(),true));
3726   DataArrayInt *cellsInM1ToRenumW4Tmp=0;
3727   m1->areCellsIncludedIn(cellsInM1ToRenumW3,2,cellsInM1ToRenumW4Tmp);
3728   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsInM1ToRenumW4(cellsInM1ToRenumW4Tmp);
3729   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsInM1ToRenumW5=cellsInM1ToRenumW4->getIdsInRange(0,m1->getNumberOfCells());
3730   cellsInM1ToRenumW5->transformWithIndArr(cellsInM1ToRenumW4->begin(),cellsInM1ToRenumW4->end());
3731   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> grpIds=getGroupArr(-1,grpNameM1);
3732   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsInM1ToRenum=cellsInM1ToRenumW5->buildSubstraction(grpIds);
3733   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Part=static_cast<MEDCouplingUMesh *>(m1->buildPartOfMySelf(cellsInM1ToRenum->begin(),cellsInM1ToRenum->end(),true));
3734   m1Part->duplicateNodesInConn(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),nbNodes);
3735   m1->setPartOfMySelf(cellsInM1ToRenum->begin(),cellsInM1ToRenum->end(),*m1Part);
3736   // end of node renumbering of cells in m1 impacted by duplication of node but not in group of level -1 'grpNameM1'
3737   tmp0->duplicateNodes(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end());
3738   m0->setCoords(tmp0->getCoords());
3739   m0->setPartOfMySelf(cellsToModifyConn0->begin(),cellsToModifyConn0->end(),*tmp0);
3740   m1->setCoords(m0->getCoords());
3741   _coords=m0->getCoords(); _coords->incrRef();
3742   // duplication of cells in group 'grpNameM1' on level -1
3743   m11->duplicateNodesInConn(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),nbNodes); m11->setCoords(m0->getCoords());
3744   std::vector<const MEDCouplingUMesh *> v(2); v[0]=m1; v[1]=m11;
3745   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> newm1=MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(v,tmp00,tmp11);
3746   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> szOfCellGrpOfSameType(tmp00);
3747   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idInMsOfCellGrpOfSameType(tmp11);
3748   //
3749   newm1->setName(getName());
3750   const DataArrayInt *fam=getFamilyFieldAtLevel(-1);
3751   if(!fam)
3752     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildInnerBoundaryAlongM1Group : internal problem !");
3753   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newFam=DataArrayInt::New();
3754   newFam->alloc(newm1->getNumberOfCells(),1);
3755   // Get a new family ID: care must be taken if we need a positive ID or a negative one:
3756   // Positive ID for family of nodes, negative for all the rest.
3757   int idd;
3758   if (m1->getMeshDimension() == 0)
3759     idd=getMaxFamilyId()+1;
3760   else
3761     idd=getMinFamilyId()-1;
3762   int globStart=0,start=0,end,globEnd;
3763   int nbOfChunks=szOfCellGrpOfSameType->getNumberOfTuples();
3764   for(int i=0;i<nbOfChunks;i++)
3765     {
3766       globEnd=globStart+szOfCellGrpOfSameType->getIJ(i,0);
3767       if(idInMsOfCellGrpOfSameType->getIJ(i,0)==0)
3768         {
3769           end=start+szOfCellGrpOfSameType->getIJ(i,0);
3770           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=fam->selectByTupleId2(start,end,1);
3771           newFam->setPartOfValues1(part,globStart,globEnd,1,0,1,1,true);
3772           start=end;
3773         }
3774       else
3775         {
3776           newFam->setPartOfValuesSimple1(idd,globStart,globEnd,1,0,1,1);
3777         }
3778       globStart=globEnd;
3779     }
3780   newm1->setCoords(getCoords());
3781   setMeshAtLevel(-1,newm1);
3782   setFamilyFieldArr(-1,newFam);
3783   std::string grpName2(grpNameM1); grpName2+="_dup";
3784   addFamily(grpName2,idd);
3785   addFamilyOnGrp(grpName2,grpName2);
3786   //
3787   fam=_fam_coords;
3788   if(fam)
3789     {
3790       int newNbOfNodes=getCoords()->getNumberOfTuples();
3791       newFam=DataArrayInt::New(); newFam->alloc(newNbOfNodes,1);
3792       newFam->setPartOfValues1(fam,0,nbNodes,1,0,1,1,true);
3793       newFam->setPartOfValuesSimple1(0,nbNodes,newNbOfNodes,1,0,1,1);
3794       _fam_coords=newFam;
3795     }
3796   nodesDuplicated=nodeIdsToDuplicate.retn();
3797   cellsModified=cellsToModifyConn0.retn();
3798   cellsNotModified=cellsToModifyConn1.retn();
3799 }
3800
3801 /*!
3802  * \param [out] oldCode retrieves the distribution of types before the call if true is returned
3803  * \param [out] newCode etrieves the distribution of types after the call if true is returned
3804  * \param [out] o2nRenumCell tells for **all levels** the old 2 new renumbering of cells.
3805  * 
3806  * \return false if no modification has been performed linked to the unpolyzation. Neither cell type, not cell numbers. When false is returned no need of field on cells or on gauss renumbering.
3807  * Inversely, if true is returned, it means that distribution of cell by geometric type has changed and field on cell and field on gauss point must be renumbered.
3808  */
3809 bool MEDFileUMesh::unPolyze(std::vector<int>& oldCode, std::vector<int>& newCode, DataArrayInt *& o2nRenumCell)
3810 {
3811   o2nRenumCell=0; oldCode.clear(); newCode.clear();
3812   std::vector<int> levs=getNonEmptyLevels();
3813   bool ret=false;
3814   std::vector< const DataArrayInt* > renumCellsSplited;//same than memorySaverIfThrow
3815   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > memorySaverIfThrow;//same than renumCellsSplited only in case of throw
3816   int start=0;
3817   int end=0;
3818   for(std::vector<int>::reverse_iterator it=levs.rbegin();it!=levs.rend();it++)
3819     {
3820       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=getMeshAtLevel(*it);
3821       std::vector<int> code1=m->getDistributionOfTypes();
3822       end=PutInThirdComponentOfCodeOffset(code1,start);
3823       oldCode.insert(oldCode.end(),code1.begin(),code1.end());
3824       bool hasChanged=m->unPolyze();
3825       DataArrayInt *fake=0;
3826       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nCellsPart=m->getLevArrPerCellTypes(MEDCouplingUMesh::MEDMEM_ORDER,
3827           MEDCouplingUMesh::MEDMEM_ORDER+MEDCouplingUMesh::N_MEDMEM_ORDER,fake);
3828       fake->decrRef();
3829       renumCellsSplited.push_back(o2nCellsPart); memorySaverIfThrow.push_back(o2nCellsPart);
3830       if(hasChanged)
3831         {
3832           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nCellsPart2=o2nCellsPart->buildPermArrPerLevel();
3833           m->renumberCells(o2nCellsPart2->getConstPointer(),false);
3834           ret=true;
3835           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famField2,numField2;
3836           const DataArrayInt *famField=getFamilyFieldAtLevel(*it); if(famField) { famField->incrRef(); famField2=const_cast<DataArrayInt *>(famField); }
3837           const DataArrayInt *numField=getNumberFieldAtLevel(*it); if(numField) { numField->incrRef(); numField2=const_cast<DataArrayInt *>(numField); }
3838           setMeshAtLevel(*it,m);
3839           std::vector<int> code2=m->getDistributionOfTypes();
3840           end=PutInThirdComponentOfCodeOffset(code2,start);
3841           newCode.insert(newCode.end(),code2.begin(),code2.end());
3842           //
3843           if(o2nCellsPart2->isIdentity())
3844             continue;
3845           if(famField)
3846             {
3847               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newFamField=famField->renumber(o2nCellsPart2->getConstPointer());
3848               setFamilyFieldArr(*it,newFamField);
3849             }
3850           if(numField)
3851             {
3852               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newNumField=numField->renumber(o2nCellsPart2->getConstPointer());
3853               setRenumFieldArr(*it,newNumField);
3854             }
3855         }
3856       else
3857         {
3858           newCode.insert(newCode.end(),code1.begin(),code1.end());
3859         }
3860       start=end;
3861     }
3862   if(ret)
3863     {
3864       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renumCells=DataArrayInt::Aggregate(renumCellsSplited);
3865       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRenumCellRet=renumCells->buildPermArrPerLevel();
3866       o2nRenumCell=o2nRenumCellRet.retn();
3867     }
3868   return ret;
3869 }
3870
3871 /*! \cond HIDDEN_ITEMS */
3872 struct MEDLoaderAccVisit1
3873 {
3874   MEDLoaderAccVisit1():_new_nb_of_nodes(0) { }
3875   int operator()(bool val) { return val?_new_nb_of_nodes++:-1; }
3876   int _new_nb_of_nodes;
3877 };
3878 /*! \endcond */
3879
3880 /*!
3881  * Array returned is the correspondance in \b old \b to \b new format. The returned array is newly created and should be dealt by the caller.
3882  * The maximum value stored in returned array is the number of nodes of \a this minus 1 after call of this method.
3883  * The size of returned array is the number of nodes of the old (previous to the call of this method) number of nodes.
3884  * -1 values in returned array means that the corresponding old node is no more used.
3885  *
3886  * \return newly allocated array containing correspondance in \b old \b to \b new format. If all nodes in \a this are fetched \c NULL pointer is returned and nothing
3887  *         is modified in \a this.
3888  * \throw If no coordinates are set in \a this or if there is in any available mesh in \a this a cell having a nodal connectivity containing a node id not in the range of
3889  *  set coordinates.
3890  */
3891 DataArrayInt *MEDFileUMesh::zipCoords()
3892 {
3893   const DataArrayDouble *coo(getCoords());
3894   if(!coo)
3895     throw INTERP_KERNEL::Exception("MEDFileUMesh::zipCoords : no coordinates set in this !");
3896   int nbOfNodes(coo->getNumberOfTuples());
3897   std::vector<bool> nodeIdsInUse(nbOfNodes,false);
3898   std::vector<int> neLevs(getNonEmptyLevels());
3899   for(std::vector<int>::const_iterator lev=neLevs.begin();lev!=neLevs.end();lev++)
3900     {
3901       const MEDFileUMeshSplitL1 *zeLev(getMeshAtLevSafe(*lev));
3902       if(zeLev->isMeshStoredSplitByType())
3903         {
3904           std::vector<MEDCoupling1GTUMesh *> ms(zeLev->getDirectUndergroundSingleGeoTypeMeshes());
3905           for(std::vector<MEDCoupling1GTUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
3906             if(*it)
3907               (*it)->computeNodeIdsAlg(nodeIdsInUse);
3908         }
3909       else
3910         {
3911           MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh(zeLev->getWholeMesh(false));
3912           mesh->computeNodeIdsAlg(nodeIdsInUse);
3913         }
3914     }
3915   int nbrOfNodesInUse((int)std::count(nodeIdsInUse.begin(),nodeIdsInUse.end(),true));
3916   if(nbrOfNodesInUse==nbOfNodes)
3917     return 0;//no need to update _part_coords
3918   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodes,1);
3919   std::transform(nodeIdsInUse.begin(),nodeIdsInUse.end(),ret->getPointer(),MEDLoaderAccVisit1());
3920   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(ret->invertArrayO2N2N2OBis(nbrOfNodesInUse));
3921   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(coo->selectByTupleIdSafe(ret2->begin(),ret2->end()));
3922   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newFamCoords;
3923   MEDCouplingAutoRefCountObjectPtr<DataArrayAsciiChar> newNameCoords;
3924   if((const DataArrayInt *)_fam_coords)
3925     newFamCoords=_fam_coords->selectByTupleIdSafe(ret2->begin(),ret2->end());
3926   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newNumCoords;
3927   if((const DataArrayInt *)_num_coords)
3928     newNumCoords=_num_coords->selectByTupleIdSafe(ret2->begin(),ret2->end());
3929   if((const DataArrayAsciiChar *)_name_coords)
3930     newNameCoords=static_cast<DataArrayAsciiChar *>(_name_coords->selectByTupleIdSafe(ret2->begin(),ret2->end()));
3931   _coords=newCoords; _fam_coords=newFamCoords; _num_coords=newNumCoords; _name_coords=newNameCoords; _rev_num_coords=0;
3932   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
3933     {
3934       if((MEDFileUMeshSplitL1*)*it)
3935         {
3936           (*it)->renumberNodesInConn(ret->begin());
3937           (*it)->setCoords(_coords);
3938         }
3939     }
3940   // updates _part_coords
3941   const PartDefinition *pc(_part_coords);
3942   if(pc)
3943     {
3944       MEDCouplingAutoRefCountObjectPtr<PartDefinition> tmpPD(DataArrayPartDefinition::New(ret2));
3945       _part_coords=tmpPD->composeWith(pc);
3946     }
3947   return ret.retn();
3948 }
3949
3950 /*!
3951  * This method performs an extrusion along a path defined by \a m1D.
3952  * \a this is expected to be a mesh with max mesh dimension equal to 2.
3953  * \a m1D is expected to be a mesh with space dimesion equal to 3 and mesh dimension equal to 1.
3954  * Mesh dimensions of returned mesh is incremented by one compared to thoose in \a this.
3955  * This method scans all levels in \a this
3956  * and put them in the returned mesh. All groups in \a this are also put in the returned mesh.
3957  *
3958  * \param [in] m1D - the mesh defining the extrusion path.
3959  * \param [in] policy - defines the policy of extrusion (see MEDCouplingUMesh::buildExtrudedMesh for more details)
3960  * \return - a new reference on mesh (you have to deal with using decrRef). The returned mesh will have the same name than \a this.
3961  *
3962  * \sa MEDCouplingUMesh::buildExtrudedMesh
3963  */
3964 MEDFileUMesh *MEDFileUMesh::buildExtrudedMesh(const MEDCouplingUMesh *m1D, int policy) const
3965 {
3966   if(getMeshDimension()!=2)
3967     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildExtrudedMesh : this is expected to be with mesh dimension equal to 2 !");
3968   MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret(MEDFileUMesh::New());
3969   m1D->checkCoherency();
3970   if(m1D->getMeshDimension()!=1)
3971     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildExtrudedMesh : input mesh must have a mesh dimension equal to one !");
3972   int nbRep(m1D->getNumberOfCells());
3973   std::vector<int> levs(getNonEmptyLevels());
3974   std::vector<std::string> grps(getGroupsNames());
3975   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > zeList;
3976   DataArrayDouble *coords(0);
3977   std::size_t nbOfLevsOut(levs.size()+1);
3978   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > o2ns(nbOfLevsOut);
3979   for(std::vector<int>::const_iterator lev=levs.begin();lev!=levs.end();lev++)
3980     {
3981       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> item(getMeshAtLevel(*lev));
3982       item=item->clone(false);
3983       item->changeSpaceDimension(3+(*lev),0.);//no problem non const but change DataArrayDouble for coordinates do not alter data
3984       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp(static_cast<MEDCouplingUMesh *>(m1D->deepCpy()));
3985       tmp->changeSpaceDimension(3+(*lev),0.);
3986       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(item->buildExtrudedMesh(tmp,policy));
3987       zeList.push_back(elt);
3988       if(*lev==0)
3989         coords=elt->getCoords();
3990     }
3991   if(!coords)
3992     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildExtrudedMesh : internal error !");
3993   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> >::iterator it=zeList.begin();it!=zeList.end();it++)
3994     {
3995       (*it)->setName(getName());
3996       (*it)->setCoords(coords);
3997     }
3998   for(std::size_t ii=0;ii!=zeList.size();ii++)
3999     {
4000       int lev(levs[ii]);
4001       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(zeList[ii]);
4002       if(lev<=-1)
4003         {
4004           MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt1(getMeshAtLevel(lev+1));
4005           MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt2(elt1->clone(false));
4006           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(elt2->getNodalConnectivity()->deepCpy());
4007           elt2->setConnectivity(tmp,elt2->getNodalConnectivityIndex());
4008           elt2->shiftNodeNumbersInConn(nbRep*elt1->getNumberOfNodes());
4009           elt1->setCoords(elt->getCoords()); elt2->setCoords(elt->getCoords());
4010           std::vector<const MEDCouplingUMesh *> elts(3);
4011           elts[0]=elt; elts[1]=elt1; elts[2]=elt2;
4012           elt=MEDCouplingUMesh::MergeUMeshesOnSameCoords(elts);
4013           elt->setName(getName());
4014         }
4015       //
4016       o2ns[ii]=elt->sortCellsInMEDFileFrmt();
4017       ret->setMeshAtLevel(lev,elt);
4018     }
4019   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> endLev(getMeshAtLevel(levs.back())),endLev2;
4020   endLev=endLev->clone(false); endLev->setCoords(coords);
4021   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(endLev->getNodalConnectivity()->deepCpy());
4022   endLev2=endLev->clone(false); endLev2->setConnectivity(tmp,endLev->getNodalConnectivityIndex());
4023   endLev2->shiftNodeNumbersInConn(nbRep*getNumberOfNodes());
4024   endLev=MEDCouplingUMesh::MergeUMeshesOnSameCoords(endLev,endLev2);
4025   o2ns[levs.size()]=endLev->sortCellsInMEDFileFrmt();
4026   endLev->setName(getName());
4027   ret->setMeshAtLevel(levs.back()-1,endLev);
4028   //
4029   for(std::size_t ii=0;ii!=zeList.size();ii++)
4030     {
4031       int lev(levs[ii]);
4032       std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > outGrps;
4033       std::vector< const DataArrayInt * > outGrps2;
4034       if(lev<=-1)
4035         {
4036           for(std::vector<std::string>::const_iterator grp=grps.begin();grp!=grps.end();grp++)
4037             {
4038               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> grpArr(getGroupArr(lev+1,*grp));
4039               if(!grpArr->empty())
4040                 {
4041                   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> grpArr1(grpArr->deepCpy()),grpArr2(grpArr->deepCpy());
4042                   int offset0(zeList[ii]->getNumberOfCells());
4043                   int offset1(offset0+getNumberOfCellsAtLevel(lev+1));
4044                   grpArr1->applyLin(1,offset0); grpArr2->applyLin(1,offset1);
4045                   std::ostringstream oss; oss << grpArr2->getName() << "_top";
4046                   grpArr2->setName(oss.str());
4047                   grpArr1->transformWithIndArr(o2ns[ii]->begin(),o2ns[ii]->end());
4048                   grpArr2->transformWithIndArr(o2ns[ii]->begin(),o2ns[ii]->end());
4049                   outGrps.push_back(grpArr1); outGrps.push_back(grpArr2);
4050                   outGrps2.push_back(grpArr1); outGrps2.push_back(grpArr2);
4051                 }
4052             }
4053         }
4054       //
4055       for(std::vector<std::string>::const_iterator grp=grps.begin();grp!=grps.end();grp++)
4056         {
4057           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> grpArr(getGroupArr(lev,*grp));
4058           if(!grpArr->empty())
4059             {
4060               int nbCellsB4Extrusion(getNumberOfCellsAtLevel(lev));
4061               std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > grpArrs(nbRep);
4062               std::vector< const DataArrayInt *> grpArrs2(nbRep);
4063               for(int iii=0;iii<nbRep;iii++)
4064                 {
4065                   grpArrs[iii]=grpArr->deepCpy(); grpArrs[iii]->applyLin(1,iii*nbCellsB4Extrusion);
4066                   grpArrs2[iii]=grpArrs[iii];
4067                 }
4068               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> grpArrExt(DataArrayInt::Aggregate(grpArrs2));
4069               grpArrExt->transformWithIndArr(o2ns[ii]->begin(),o2ns[ii]->end());
4070               std::ostringstream grpName; grpName << *grp << "_extruded";
4071               grpArrExt->setName(grpName.str());
4072               outGrps.push_back(grpArrExt);
4073               outGrps2.push_back(grpArrExt);
4074             }
4075         }
4076       ret->setGroupsAtLevel(lev,outGrps2);
4077     }
4078   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > outGrps;
4079   std::vector< const DataArrayInt * > outGrps2;
4080   for(std::vector<std::string>::const_iterator grp=grps.begin();grp!=grps.end();grp++)
4081     {
4082       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> grpArr1(getGroupArr(levs.back(),*grp));
4083       if(grpArr1->empty())
4084         continue;
4085       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> grpArr2(grpArr1->deepCpy());
4086       std::ostringstream grpName; grpName << *grp << "_top";
4087       grpArr2->setName(grpName.str());
4088       grpArr2->applyLin(1,getNumberOfCellsAtLevel(levs.back()));
4089       outGrps.push_back(grpArr1); outGrps.push_back(grpArr2);
4090       outGrps2.push_back(grpArr1); outGrps2.push_back(grpArr2);
4091     }
4092   ret->setGroupsAtLevel(levs.back()-1,outGrps2);
4093   return ret.retn();
4094 }
4095
4096 /*!
4097  * This method converts all linear cells in \a this into quadratic cells (following the \a conversionType policy).
4098  * All the cells converted are put in the returned instance. This method applies all the groups and families in \a this to returned instance.
4099  * Groups on nodes and families on nodes are copied directly to the returned instance without transformation.
4100  *
4101  * \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
4102  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
4103  * \param [in] eps - detection threshold for coordinates.
4104  * \return A new instance that is the result of the conversion. The caller has the ownership of this returned instance.
4105  *
4106  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic , quadraticToLinear
4107  */
4108 MEDFileUMesh *MEDFileUMesh::linearToQuadratic(int conversionType, double eps) const
4109 {
4110   MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret(MEDFileUMesh::New());
4111   int initialNbNodes(getNumberOfNodes());
4112   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Tmp(getMeshAtLevel(0));
4113   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0(dynamic_cast<MEDCouplingUMesh *>(m0Tmp->deepCpy()));
4114   {
4115     MEDCouplingAutoRefCountObjectPtr<DataArrayInt> notUsed(m0->convertLinearCellsToQuadratic(conversionType));
4116   }
4117   DataArrayDouble *zeCoords(m0->getCoords());
4118   ret->setMeshAtLevel(0,m0);
4119   std::vector<int> levs(getNonEmptyLevels());
4120   const DataArrayInt *famField(getFamilyFieldAtLevel(0));
4121   if(famField)
4122     {
4123       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famFieldCpy(famField->deepCpy());
4124       ret->setFamilyFieldArr(0,famFieldCpy);
4125     }
4126   famField=getFamilyFieldAtLevel(1);
4127   if(famField)
4128     {
4129       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fam(DataArrayInt::New()); fam->alloc(zeCoords->getNumberOfTuples(),1);
4130       fam->fillWithZero();
4131       fam->setPartOfValues1(famField,0,initialNbNodes,1,0,1,1);
4132       ret->setFamilyFieldArr(1,fam);
4133     }
4134   ret->copyFamGrpMapsFrom(*this);
4135   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> partZeCoords(zeCoords->selectByTupleId2(initialNbNodes,zeCoords->getNumberOfTuples(),1));
4136   for(std::vector<int>::const_iterator lev=levs.begin();lev!=levs.end();lev++)
4137     {
4138       if(*lev==0)
4139         continue;
4140       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Tmp(getMeshAtLevel(*lev));
4141       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1(dynamic_cast<MEDCouplingUMesh *>(m1Tmp->deepCpy()));
4142       if(m1->getMeshDimension()!=0)
4143         {
4144           {
4145             MEDCouplingAutoRefCountObjectPtr<DataArrayInt> notUsed(m1->convertLinearCellsToQuadratic(conversionType));
4146           }//kill unused notUsed var
4147           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> m1Coords(m1->getCoords()->selectByTupleId2(initialNbNodes,m1->getNumberOfNodes(),1));
4148           DataArrayInt *b(0);
4149           bool a(partZeCoords->areIncludedInMe(m1Coords,eps,b));
4150           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> bSafe(b);
4151           if(!a)
4152             {
4153               std::ostringstream oss; oss << "MEDFileUMesh::linearCellsToQuadratic : for level " << *lev << " problem to identify nodes generated !";
4154               throw INTERP_KERNEL::Exception(oss.str().c_str());
4155             }
4156           b->applyLin(1,initialNbNodes);
4157           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> l0(DataArrayInt::New()); l0->alloc(initialNbNodes,1); l0->iota();
4158           std::vector<const DataArrayInt *> v(2); v[0]=l0; v[1]=b;
4159           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum(DataArrayInt::Aggregate(v));
4160           m1->renumberNodesInConn(renum->begin());
4161         }
4162       m1->setCoords(zeCoords);
4163       ret->setMeshAtLevel(*lev,m1);
4164       famField=getFamilyFieldAtLevel(*lev);
4165       if(famField)
4166         {
4167           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famFieldCpy(famField->deepCpy());
4168           ret->setFamilyFieldArr(*lev,famFieldCpy);
4169         }
4170     }
4171   return ret.retn();
4172 }
4173
4174 /*!
4175  * This method converts all quadratic cells in \a this into linear cells.
4176  * All the cells converted are put in the returned instance. This method applies all the groups and families in \a this to returned instance.
4177  * Groups on nodes and families on nodes are copied directly to the returned instance without transformation.
4178  *
4179  * \param [in] eps - detection threshold for coordinates.
4180  * \return A new instance that is the result of the conversion. The caller has the ownership of this returned instance.
4181  *
4182  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic , linearToQuadratic
4183  */
4184 MEDFileUMesh *MEDFileUMesh::quadraticToLinear(double eps) const
4185 {
4186   MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret(MEDFileUMesh::New());
4187   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Tmp(getMeshAtLevel(0));
4188   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0(dynamic_cast<MEDCouplingUMesh *>(m0Tmp->deepCpy()));
4189   m0->convertQuadraticCellsToLinear();
4190   m0->zipCoords();
4191   DataArrayDouble *zeCoords(m0->getCoords());
4192   ret->setMeshAtLevel(0,m0);
4193   std::vector<int> levs(getNonEmptyLevels());
4194   const DataArrayInt *famField(getFamilyFieldAtLevel(0));
4195   if(famField)
4196     {
4197       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famFieldCpy(famField->deepCpy());
4198       ret->setFamilyFieldArr(0,famFieldCpy);
4199     }
4200   famField=getFamilyFieldAtLevel(1);
4201   if(famField)
4202     {
4203       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fam(famField->selectByTupleId2(0,zeCoords->getNumberOfTuples(),1));
4204       ret->setFamilyFieldArr(1,fam);
4205     }
4206   ret->copyFamGrpMapsFrom(*this);
4207   for(std::vector<int>::const_iterator lev=levs.begin();lev!=levs.end();lev++)
4208     {
4209       if(*lev==0)
4210         continue;
4211       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Tmp(getMeshAtLevel(*lev));
4212       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1(dynamic_cast<MEDCouplingUMesh *>(m1Tmp->deepCpy()));
4213       m1->convertQuadraticCellsToLinear();
4214       m1->zipCoords();
4215       DataArrayInt *b(0);
4216       bool a(zeCoords->areIncludedInMe(m1->getCoords(),eps,b));
4217       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> bSafe(b);
4218       if(!a)
4219         {
4220           std::ostringstream oss; oss << "MEDFileUMesh::quadraticToLinear : for level " << *lev << " problem to identify nodes generated !";
4221           throw INTERP_KERNEL::Exception(oss.str().c_str());
4222         }
4223       m1->renumberNodesInConn(b->begin());
4224       m1->setCoords(zeCoords);
4225       ret->setMeshAtLevel(*lev,m1);
4226       famField=getFamilyFieldAtLevel(*lev);
4227       if(famField)
4228         {
4229           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famFieldCpy(famField->deepCpy());
4230           ret->setFamilyFieldArr(*lev,famFieldCpy);
4231         }
4232     }
4233   return ret.retn();
4234 }
4235
4236 void MEDFileUMesh::serialize(std::vector<double>& tinyDouble, std::vector<int>& tinyInt, std::vector<std::string>& tinyStr, std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >& bigArraysI, MEDCouplingAutoRefCountObjectPtr<DataArrayDouble>& bigArrayD)
4237 {
4238   clearNonDiscrAttributes();
4239   forceComputationOfParts();
4240   tinyDouble.clear(); tinyInt.clear(); tinyStr.clear(); bigArraysI.clear(); bigArrayD=0;
4241   std::vector<int> layer0;
4242   layer0.push_back(getAxType());//0 i
4243   layer0.push_back(_order); //1 i
4244   layer0.push_back(_iteration);//2 i
4245   layer0.push_back(getSpaceDimension());//3 i
4246   tinyDouble.push_back(_time);//0 d
4247   tinyStr.push_back(_name);//0 s
4248   tinyStr.push_back(_desc_name);//1 s
4249   for(int i=0;i<getSpaceDimension();i++)
4250     tinyStr.push_back(_coords->getInfoOnComponent(i));
4251   layer0.push_back((int)_families.size());//4 i <- key info aa layer#0
4252   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
4253     {
4254       tinyStr.push_back((*it).first);
4255       layer0.push_back((*it).second);
4256     }
4257   layer0.push_back((int)_groups.size());//4+aa i <- key info bb layer#0
4258   for(std::map<std::string, std::vector<std::string> >::const_iterator it0=_groups.begin();it0!=_groups.end();it0++)
4259     {
4260       layer0.push_back((int)(*it0).second.size());
4261       tinyStr.push_back((*it0).first);
4262       for(std::vector<std::string>::const_iterator it1=((*it0).second).begin();it1!=((*it0).second).end();it1++)
4263         tinyStr.push_back(*it1);
4264     }
4265   // sizeof(layer0)==4+aa+1+bb layer#0
4266   bigArrayD=_coords;// 0 bd
4267   bigArraysI.push_back(_fam_coords);// 0 bi
4268   bigArraysI.push_back(_num_coords);// 1 bi
4269   const PartDefinition *pd(_part_coords);
4270   if(!pd)
4271     layer0.push_back(-1);
4272   else
4273     {
4274       std::vector<int> tmp0;
4275       pd->serialize(tmp0,bigArraysI);
4276       tinyInt.push_back(tmp0.size());
4277       tinyInt.insert(tinyInt.end(),tmp0.begin(),tmp0.end());
4278     }
4279   //
4280   std::vector<int> layer1;
4281   std::vector<int> levs(getNonEmptyLevels());
4282   layer1.push_back((int)levs.size());// 0 i <- key
4283   layer1.insert(layer1.end(),levs.begin(),levs.end());
4284   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
4285     {
4286       const MEDFileUMeshSplitL1 *lev(getMeshAtLevSafe(*it));
4287       lev->serialize(layer1,bigArraysI);
4288     }
4289   // put layers all together.
4290   tinyInt.push_back(layer0.size());
4291   tinyInt.insert(tinyInt.end(),layer0.begin(),layer0.end());
4292   tinyInt.push_back(layer1.size());
4293   tinyInt.insert(tinyInt.end(),layer1.begin(),layer1.end());
4294 }
4295
4296 void MEDFileUMesh::unserialize(std::vector<double>& tinyDouble, std::vector<int>& tinyInt, std::vector<std::string>& tinyStr,
4297                                std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >& bigArraysI, MEDCouplingAutoRefCountObjectPtr<DataArrayDouble>& bigArrayD)
4298 {
4299   int sz0(tinyInt[0]);
4300   std::vector<int> layer0(tinyInt.begin()+1,tinyInt.begin()+1+sz0);
4301   int sz1(tinyInt[sz0+1]);
4302   std::vector<int> layer1(tinyInt.begin()+2+sz0,tinyInt.begin()+2+sz0+sz1);
4303   //
4304   std::reverse(layer0.begin(),layer0.end());
4305   std::reverse(layer1.begin(),layer1.end());
4306   std::reverse(tinyDouble.begin(),tinyDouble.end());
4307   std::reverse(tinyStr.begin(),tinyStr.end());
4308   std::reverse(bigArraysI.begin(),bigArraysI.end());
4309   //
4310   setAxType((MEDCouplingAxisType)layer0.back()); layer0.pop_back();
4311   _order=layer0.back(); layer0.pop_back();
4312   _iteration=layer0.back(); layer0.pop_back();
4313   int spaceDim(layer0.back()); layer0.pop_back();
4314   _time=tinyDouble.back(); tinyDouble.pop_back();
4315   _name=tinyStr.back(); tinyStr.pop_back();
4316   _desc_name=tinyStr.back(); tinyStr.pop_back();
4317   _coords=bigArrayD; _coords->rearrange(spaceDim);
4318   for(int i=0;i<spaceDim;i++)
4319     {
4320       _coords->setInfoOnComponent(i,tinyStr.back());
4321       tinyStr.pop_back();
4322     }
4323   int nbOfFams(layer0.back()); layer0.pop_back();
4324   _families.clear();
4325   for(int i=0;i<nbOfFams;i++)
4326     {
4327       _families[tinyStr.back()]=layer0.back();
4328       tinyStr.pop_back(); layer0.pop_back();
4329     }
4330   int nbGroups(layer0.back()); layer0.pop_back();
4331   _groups.clear();
4332   for(int i=0;i<nbGroups;i++)
4333     {
4334       std::string grpName(tinyStr.back()); tinyStr.pop_back();
4335       int nbOfFamsOnGrp(layer0.back()); layer0.pop_back();
4336       std::vector<std::string> fams(nbOfFamsOnGrp);
4337       for(int j=0;j<nbOfFamsOnGrp;j++)
4338         {
4339           fams[j]=tinyStr.back(); tinyStr.pop_back();
4340         }
4341       _groups[grpName]=fams;
4342     }
4343   _fam_coords=bigArraysI.back(); bigArraysI.pop_back();
4344   _num_coords=bigArraysI.back(); bigArraysI.pop_back();
4345   _part_coords=0;
4346   int isPd(layer0.back()); layer0.pop_back();
4347   if(isPd!=-1)
4348     {
4349       std::vector<int> tmp0(layer0.begin(),layer0.begin()+isPd);
4350       layer0.erase(layer0.begin(),layer0.begin()+isPd);
4351       _part_coords=PartDefinition::Unserialize(tmp0,bigArraysI);
4352     }
4353   if(!layer0.empty())
4354     throw INTERP_KERNEL::Exception("MEDFileUMesh::unserialize : something wrong during unserialization #1 !");
4355   //
4356   int nbLevs(layer1.back()); layer1.pop_back();
4357   std::vector<int> levs(layer1.rbegin(),layer1.rbegin()+nbLevs); layer1.erase(layer1.end()-nbLevs,layer1.end());
4358   _ms.clear();
4359   int maxLev(-(*std::min_element(levs.begin(),levs.end())));
4360   _ms.resize(maxLev+1);
4361   for(int i=0;i<nbLevs;i++)
4362     {
4363       int lev(levs[i]);
4364       int pos(-lev);
4365       _ms[pos]=MEDFileUMeshSplitL1::Unserialize(_name,_coords,layer1,bigArraysI);
4366     }
4367 }
4368
4369 /*!
4370  * Adds a group of nodes to \a this mesh.
4371  *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
4372  *          The ids should be sorted and different each other (MED file norm).
4373  *
4374  *  \warning this method can alter default "FAMILLE_ZERO" family.
4375  *  For users sensitive to this a call to MEDFileMesh::rearrangeFamilies will be necessary after addGroup session.
4376  *
4377  *  \throw If the node coordinates array is not set.
4378  *  \throw If \a ids == \c NULL.
4379  *  \throw If \a ids->getName() == "".
4380  *  \throw If \a ids does not respect the MED file norm.
4381  *  \throw If a group with name \a ids->getName() already exists.
4382  */
4383 void MEDFileUMesh::addNodeGroup(const DataArrayInt *ids)
4384 {
4385   const DataArrayDouble *coords(_coords);
4386   if(!coords)
4387     throw INTERP_KERNEL::Exception("MEDFileUMesh::addNodeGroup : no coords set !");
4388   int nbOfNodes(coords->getNumberOfTuples());
4389   if(!((DataArrayInt *)_fam_coords))
4390     { _fam_coords=DataArrayInt::New(); _fam_coords->alloc(nbOfNodes,1); _fam_coords->fillWithZero(); }
4391   //
4392   addGroupUnderground(true,ids,_fam_coords);
4393 }
4394
4395 /*!
4396  * Adds a group of nodes/cells/faces/edges to \a this mesh.
4397  *
4398  *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
4399  *          The ids should be sorted and different each other (MED file norm).
4400  *
4401  * \warning this method can alter default "FAMILLE_ZERO" family.
4402  * For users sensitive to this a call to MEDFileMesh::rearrangeFamilies will be necessary after addGroup session.
4403  *
4404  *  \throw If the node coordinates array is not set.
4405  *  \throw If \a ids == \c NULL.
4406  *  \throw If \a ids->getName() == "".
4407  *  \throw If \a ids does not respect the MED file norm.
4408  *  \throw If a group with name \a ids->getName() already exists.
4409  */
4410 void MEDFileUMesh::addGroup(int meshDimRelToMaxExt, const DataArrayInt *ids)
4411 {
4412   std::vector<int> levs(getNonEmptyLevelsExt());
4413   if(std::find(levs.begin(),levs.end(),meshDimRelToMaxExt)==levs.end())
4414     { 
4415       std::ostringstream oss; oss << "MEDFileUMesh::addGroup : level " << meshDimRelToMaxExt << " not available ! Should be in ";
4416       std::copy(levs.begin(),levs.end(),std::ostream_iterator<int>(oss," ")); oss << " !"; throw INTERP_KERNEL::Exception(oss.str().c_str());
4417     }
4418   if(meshDimRelToMaxExt==1)
4419     { addNodeGroup(ids); return ; }
4420   MEDFileUMeshSplitL1 *lev(getMeshAtLevSafe(meshDimRelToMaxExt));
4421   DataArrayInt *fam(lev->getOrCreateAndGetFamilyField());
4422   addGroupUnderground(false,ids,fam);
4423 }
4424
4425 /*!
4426  * Changes a name of a family specified by its id.
4427  *  \param [in] id - the id of the family of interest.
4428  *  \param [in] newFamName - the new family name.
4429  *  \throw If no family with the given \a id exists.
4430  */
4431 void MEDFileUMesh::setFamilyNameAttachedOnId(int id, const std::string& newFamName)
4432 {
4433   std::string oldName=getFamilyNameGivenId(id);
4434   _families.erase(oldName);
4435   _families[newFamName]=id;
4436 }
4437
4438 /*!
4439  * Removes a mesh of a given dimension.
4440  *  \param [in] meshDimRelToMax - the relative dimension of interest.
4441  *  \throw If there is no mesh at level \a meshDimRelToMax in \a this mesh.
4442  */
4443 void MEDFileUMesh::removeMeshAtLevel(int meshDimRelToMax)
4444 {
4445   std::vector<int> levSet=getNonEmptyLevels();
4446   std::vector<int>::const_iterator it=std::find(levSet.begin(),levSet.end(),meshDimRelToMax);
4447   if(it==levSet.end())
4448     throw INTERP_KERNEL::Exception("MEDFileUMesh::removeMeshAtLevel : the requested level is not existing !");
4449   int pos=(-meshDimRelToMax);
4450   _ms[pos]=0;
4451 }
4452
4453 /*!
4454  * Sets a new MEDCoupling1GTUMesh at a given level in \a this mesh.
4455  *  \param [in] meshDimRelToMax - a relative level to set the mesh at.
4456  *  \param [in] m - the new mesh to set.
4457  *  \throw If the name or the description of \a this mesh and \a m are not empty and are
4458  *         different. 
4459  *  \throw If the node coordinates array is set \a this in mesh and \a m refers to
4460  *         another node coordinates array.
4461  *  \throw If the mesh dimension of \a m does not correspond to \a meshDimRelToMax or
4462  *         to the existing meshes of other levels of \a this mesh.
4463  */
4464 void MEDFileUMesh::setMeshAtLevel(int meshDimRelToMax, MEDCoupling1GTUMesh *m)
4465 {
4466   MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> elt(new MEDFileUMeshSplitL1(m));
4467   checkAndGiveEntryInSplitL1(meshDimRelToMax,m)=elt;
4468 }
4469
4470 /*!
4471  * Sets a new MEDCouplingUMesh at a given level in \a this mesh.
4472  *  \param [in] meshDimRelToMax - a relative level to set the mesh at.
4473  *  \param [in] m - the new mesh to set.
4474  *  \param [in] newOrOld - if \c true, cells in \a m are sorted by type to be ready for 
4475  *         writing \a this mesh in a MED file.
4476  *  \throw If the name or the description of \a this mesh and \a m are not empty and are
4477  *         different. 
4478  *  \throw If the node coordinates array is set \a this in mesh and \a m refers to
4479  *         another node coordinates array.
4480  *  \throw If the mesh dimension of \a m does not correspond to \a meshDimRelToMax or
4481  *         to the existing meshes of other levels of \a this mesh.
4482  */
4483 void MEDFileUMesh::setMeshAtLevel(int meshDimRelToMax, MEDCouplingUMesh *m, bool newOrOld)
4484 {
4485   MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> elt(new MEDFileUMeshSplitL1(m,newOrOld));
4486   checkAndGiveEntryInSplitL1(meshDimRelToMax,m)=elt;
4487 }
4488
4489 MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1>& MEDFileUMesh::checkAndGiveEntryInSplitL1(int meshDimRelToMax, MEDCouplingPointSet *m)
4490 {
4491   dealWithTinyInfo(m);
4492   std::vector<int> levSet=getNonEmptyLevels();
4493   if(std::find(levSet.begin(),levSet.end(),meshDimRelToMax)==levSet.end())
4494     {
4495       if((DataArrayDouble *)_coords==0)
4496         {
4497           DataArrayDouble *c=m->getCoords();
4498           if(c)
4499             c->incrRef();
4500           _coords=c;
4501         }
4502       if(m->getCoords()!=_coords)
4503         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshAtLevel : Invalid Given Mesh ! The coordinates are not the same ! try to use tryToShareSameCoords !");
4504       int sz=(-meshDimRelToMax)+1;
4505       if(sz>=(int)_ms.size())
4506         _ms.resize(sz);
4507       checkMeshDimCoherency(m->getMeshDimension(),meshDimRelToMax);
4508       return _ms[sz-1];
4509     }
4510   else
4511     return _ms[-meshDimRelToMax];
4512 }
4513
4514 /*!
4515  * This method allows to set at once the content of different levels in \a this.
4516  * This method is equivalent to a series of call to MEDFileUMesh::setMeshAtLevel.
4517  *
4518  * \param [in] ms - List of unstructured meshes lying on the same coordinates and having different mesh dimesnion.
4519  * \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.
4520  *                     If false, an exception ois thrown. If true the mesh is reordered automatically. It is highly recommanded to let this parameter to false.
4521  *
4522  * \throw If \a there is a null pointer in \a ms.
4523  * \sa MEDFileUMesh::setMeshAtLevel
4524  */
4525 void MEDFileUMesh::setMeshes(const std::vector<const MEDCouplingUMesh *>& ms, bool renum)
4526 {
4527   if(ms.empty())
4528     return ;
4529   const MEDCouplingUMesh *mRef=ms[0];
4530   if(!mRef)
4531     throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : null instance in the first element of input meshes !");
4532   std::string name(mRef->getName());
4533   const DataArrayDouble *coo(mRef->getCoords());
4534   std::set<int> s;
4535   int zeDim=-1;
4536   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
4537     {
4538       const MEDCouplingUMesh *cur(*it);
4539       if(!cur)
4540         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : null instance in input vector of meshes !");
4541       if(coo!=cur->getCoords())
4542         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : The input meshes do not share the same coordinates !");
4543       int mdim=cur->getMeshDimension();
4544       zeDim=std::max(zeDim,mdim);
4545       if(s.find(mdim)!=s.end())
4546         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : The input meshes must share the same coordinates pointer, and should have different mesh dimension each other !");
4547     }
4548   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
4549     {
4550       int mdim=(*it)->getMeshDimension();
4551       setName((*it)->getName());
4552       setMeshAtLevel(mdim-zeDim,const_cast<MEDCouplingUMesh *>(*it),renum);
4553     }
4554   setName(name);
4555 }
4556
4557 /*!
4558  * Creates one MEDCouplingUMesh at a given level in \a this mesh from a sequence of
4559  * meshes each representing a group, and creates corresponding groups in \a this mesh.
4560  * The given meshes must share the same node coordinates array.
4561  *  \param [in] meshDimRelToMax - the relative dimension to create the mesh and groups at.
4562  *  \param [in] ms - the sequence of meshes. Each mesh in \a ms represents a group to
4563  *          create in \a this mesh.
4564  *  \throw If \a ms is empty.
4565  *  \throw If dimension of meshes in \a ms does not correspond to \a meshDimRelToMax or
4566  *         to the existing meshes of other levels of \a this mesh.
4567  *  \throw If the meshes in \a ms do not share the same node coordinates array.
4568  *  \throw If the node coordinates array of \a this mesh (if any) is not the same as that
4569  *         of the given meshes.
4570  *  \throw If \a ms[ i ] is not well defined (MEDCouplingUMesh::checkCoherency()).
4571  *  \throw If names of some meshes in \a ms are equal.
4572  *  \throw If \a ms includes a mesh with an empty name.
4573  */
4574 void MEDFileUMesh::setGroupsFromScratch(int meshDimRelToMax, const std::vector<const MEDCouplingUMesh *>& ms, bool renum)
4575 {
4576   if(ms.empty())
4577     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsFromScratch : expecting a non empty vector !");
4578   int sz=(-meshDimRelToMax)+1;
4579   if(sz>=(int)_ms.size())
4580     _ms.resize(sz);
4581   checkMeshDimCoherency(ms[0]->getMeshDimension(),meshDimRelToMax);
4582   DataArrayDouble *coo=checkMultiMesh(ms);
4583   if((DataArrayDouble *)_coords==0)
4584     {
4585       coo->incrRef();
4586       _coords=coo;
4587     }
4588   else
4589     if((DataArrayDouble *)_coords!=coo)
4590       throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsFromScratch : coordinates mismatches !");
4591   std::vector<DataArrayInt *> corr;
4592   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MEDCouplingUMesh::FuseUMeshesOnSameCoords(ms,_zipconn_pol,corr);
4593   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > corr3(corr.begin(),corr.end());
4594   setMeshAtLevel(meshDimRelToMax,m,renum);
4595   std::vector<const DataArrayInt *> corr2(corr.begin(),corr.end());
4596   setGroupsAtLevel(meshDimRelToMax,corr2,true);
4597 }
4598
4599 /*!
4600  * Creates groups at a given level in \a this mesh from a sequence of
4601  * meshes each representing a group.
4602  * The given meshes must share the same node coordinates array.
4603  *  \param [in] meshDimRelToMax - the relative dimension to create the groups at.
4604  *  \param [in] ms - the sequence of meshes. Each mesh in \a ms represents a group to
4605  *         create in \a this mesh.
4606  *  \param [in] renum - if \c true, then the optional numbers of entities are taken into
4607  *         account. 
4608  *  \throw If \a ms is empty.
4609  *  \throw If dimension of meshes in \a ms does not correspond to \a meshDimRelToMax or
4610  *         to the existing meshes of other levels of \a this mesh.
4611  *  \throw If the meshes in \a ms do not share the same node coordinates array.
4612  *  \throw If the node coordinates array of \a this mesh (if any) is not the same as that
4613  *         of the given meshes.
4614  *  \throw If \a ms[ i ] is not well defined (MEDCouplingUMesh::checkCoherency()).
4615  *  \throw If names of some meshes in \a ms are equal.
4616  *  \throw If \a ms includes a mesh with an empty name.
4617  */
4618 void MEDFileUMesh::setGroupsOnSetMesh(int meshDimRelToMax, const std::vector<const MEDCouplingUMesh *>& ms, bool renum)
4619 {
4620   if(ms.empty())
4621     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsOnSetMesh : expecting a non empty vector !");
4622   int sz=(-meshDimRelToMax)+1;
4623   if(sz>=(int)_ms.size())
4624     _ms.resize(sz);
4625   checkMeshDimCoherency(ms[0]->getMeshDimension(),meshDimRelToMax);
4626   DataArrayDouble *coo=checkMultiMesh(ms);
4627   if((DataArrayDouble *)_coords==0)
4628     {
4629       coo->incrRef();
4630       _coords=coo;
4631     }
4632   else
4633     if((DataArrayDouble *)_coords!=coo)
4634       throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsOnSetMesh : coordinates mismatches !");
4635   MEDCouplingUMesh *m=getMeshAtLevel(meshDimRelToMax,renum);
4636   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > corr(ms.size());
4637   int i=0;
4638   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++,i++)
4639     {
4640       DataArrayInt *arr=0;
4641       bool test=m->areCellsIncludedIn(*it,_zipconn_pol,arr);
4642       corr[i]=arr;
4643       if(!test)
4644         {
4645           std::ostringstream oss; oss << "MEDFileUMesh::setGroupsOnSetMesh : mesh #" << i << " is not part of whole mesh !";
4646           throw INTERP_KERNEL::Exception(oss.str().c_str());
4647         }
4648     }
4649   std::vector<const DataArrayInt *> corr2(corr.begin(),corr.end());
4650   setGroupsAtLevel(meshDimRelToMax,corr2,renum);
4651 }
4652
4653 DataArrayDouble *MEDFileUMesh::checkMultiMesh(const std::vector<const MEDCouplingUMesh *>& ms) const
4654 {
4655   const DataArrayDouble *ret=ms[0]->getCoords();
4656   int mdim=ms[0]->getMeshDimension();
4657   for(unsigned int i=1;i<ms.size();i++)
4658     {
4659       ms[i]->checkCoherency();
4660       if(ms[i]->getCoords()!=ret)
4661         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMultiMesh : meshes must share the same coords !");
4662       if(ms[i]->getMeshDimension()!=mdim)
4663         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMultiMesh : meshes have not same mesh dimension !");
4664     }
4665   return const_cast<DataArrayDouble *>(ret);
4666 }
4667
4668 /*!
4669  * Sets the family field of a given relative dimension.
4670  *  \param [in] meshDimRelToMaxExt - the relative dimension of entities for which
4671  *          the family field is set.
4672  *  \param [in] famArr - the array of the family field.
4673  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4674  *  \throw If \a famArr has an invalid size.
4675  */
4676 void MEDFileUMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr)
4677 {
4678   if(meshDimRelToMaxExt==1)
4679     {
4680       if(!famArr)
4681         {
4682           _fam_coords=0;
4683           return ;
4684         }
4685       DataArrayDouble *coo(_coords);
4686       if(!coo)
4687         throw INTERP_KERNEL::Exception("MEDFileUMesh::setFamilyFieldArr : the coordinates have not been set !");
4688       famArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),1,"MEDFileUMesh::setFamilyFieldArr : Problem in size of node family arr ! ");
4689       famArr->incrRef();
4690       _fam_coords=famArr;
4691       return ;
4692     }
4693   if(meshDimRelToMaxExt>1)
4694     throw INTERP_KERNEL::Exception("MEDFileUMesh::setFamilyFieldArr : Dimension request is invalid (>1) !");
4695   int traducedRk=-meshDimRelToMaxExt;
4696   if(traducedRk>=(int)_ms.size())
4697     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
4698   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
4699     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
4700   return _ms[traducedRk]->setFamilyArr(famArr);
4701 }
4702
4703 /*!
4704  * Sets the optional numbers of mesh entities of a given dimension.
4705  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4706  *  \param [in] renumArr - the array of the numbers.
4707  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4708  *  \throw If \a renumArr has an invalid size.
4709  */
4710 void MEDFileUMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr)
4711 {
4712   if(meshDimRelToMaxExt==1)
4713     {
4714       if(!renumArr)
4715         {
4716           _num_coords=0;
4717           _rev_num_coords=0;
4718           return ;
4719         }
4720       DataArrayDouble *coo(_coords);
4721       if(!coo)
4722         throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumFieldArr : the coordinates have not been set !");
4723       renumArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),1,"MEDFileUMesh::setRenumArr : Problem in size of node numbering arr ! ");
4724       renumArr->incrRef();
4725       _num_coords=renumArr;
4726       computeRevNum();
4727       return ;
4728     }
4729   if(meshDimRelToMaxExt>1)
4730     throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumArr : Dimension request is invalid (>1) !");
4731   int traducedRk=-meshDimRelToMaxExt;
4732   if(traducedRk>=(int)_ms.size())
4733     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
4734   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
4735     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
4736   return _ms[traducedRk]->setRenumArr(renumArr);
4737 }
4738
4739 /*!
4740  * Sets the optional names of mesh entities of a given dimension.
4741  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4742  *  \param [in] nameArr - the array of the names.
4743  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4744  *  \throw If \a nameArr has an invalid size.
4745  */
4746 void MEDFileUMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr)
4747 {
4748   if(meshDimRelToMaxExt==1)
4749     {
4750       if(!nameArr)
4751         {
4752           _name_coords=0;
4753           return ;
4754         }
4755       DataArrayDouble *coo(_coords);
4756       if(!coo)
4757         throw INTERP_KERNEL::Exception("MEDFileUMesh::setNameFieldAtLevel : the coordinates have not been set !");
4758       nameArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),MED_SNAME_SIZE,"MEDFileUMesh::setNameFieldAtLevel : Problem in size of node numbering arr ! ");
4759       nameArr->incrRef();
4760       _name_coords=nameArr;
4761       return ;
4762     }
4763   if(meshDimRelToMaxExt>1)
4764     throw INTERP_KERNEL::Exception("MEDFileUMesh::setNameFieldAtLevel : Dimension request is invalid (>1) !");
4765   int traducedRk=-meshDimRelToMaxExt;
4766   if(traducedRk>=(int)_ms.size())
4767     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
4768   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
4769     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
4770   return _ms[traducedRk]->setNameArr(nameArr);
4771 }
4772
4773 void MEDFileUMesh::synchronizeTinyInfoOnLeaves() const
4774 {
4775   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
4776     if((const MEDFileUMeshSplitL1 *)(*it))
4777       (*it)->synchronizeTinyInfo(*this);
4778 }
4779
4780 /*!
4781  * This method is called by MEDFileMesh::changeFamilyId. It performs only one part of the family id modification.
4782  */
4783 void MEDFileUMesh::changeFamilyIdArr(int oldId, int newId)
4784 {
4785   DataArrayInt *arr=_fam_coords;
4786   if(arr)
4787     arr->changeValue(oldId,newId);
4788   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
4789     {
4790       MEDFileUMeshSplitL1 *sp=(*it);
4791       if(sp)
4792         {
4793           sp->changeFamilyIdArr(oldId,newId);
4794         }
4795     }
4796 }
4797
4798 std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > MEDFileUMesh::getAllNonNullFamilyIds() const
4799 {
4800   std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret;
4801   const DataArrayInt *da(_fam_coords);
4802   if(da)
4803     { da->incrRef(); ret.push_back(MEDCouplingAutoRefCountObjectPtr<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
4804   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
4805     {
4806       const MEDFileUMeshSplitL1 *elt(*it);
4807       if(elt)
4808         {
4809           da=elt->getFamilyField();
4810           if(da)
4811             { da->incrRef(); ret.push_back(MEDCouplingAutoRefCountObjectPtr<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
4812         }
4813     }
4814   return ret;
4815 }
4816
4817 void MEDFileUMesh::computeRevNum() const
4818 {
4819   if((const DataArrayInt *)_num_coords)
4820     {
4821       int pos;
4822       int maxValue=_num_coords->getMaxValue(pos);
4823       _rev_num_coords=_num_coords->invertArrayN2O2O2N(maxValue+1);
4824     }
4825 }
4826
4827 std::size_t MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren() const
4828 {
4829   return MEDFileMesh::getHeapMemorySizeWithoutChildren();
4830 }
4831
4832 std::vector<const BigMemoryObject *> MEDFileStructuredMesh::getDirectChildrenWithNull() const
4833 {
4834   std::vector<const BigMemoryObject *> ret(MEDFileMesh::getDirectChildrenWithNull());
4835   ret.push_back((const DataArrayInt *)_fam_nodes);
4836   ret.push_back((const DataArrayInt *)_num_nodes);
4837   ret.push_back((const DataArrayAsciiChar *)_names_nodes);
4838   ret.push_back((const DataArrayInt *)_fam_cells);
4839   ret.push_back((const DataArrayInt *)_num_cells);
4840   ret.push_back((const DataArrayAsciiChar *)_names_cells);
4841   ret.push_back((const DataArrayInt *)_fam_faces);
4842   ret.push_back((const DataArrayInt *)_num_faces);
4843   ret.push_back((const DataArrayInt *)_rev_num_nodes);
4844   ret.push_back((const DataArrayAsciiChar *)_names_faces);
4845   ret.push_back((const DataArrayInt *)_rev_num_cells);
4846   ret.push_back((const MEDCoupling1SGTUMesh*)_faces_if_necessary);
4847   return ret;
4848 }
4849
4850 int MEDFileStructuredMesh::getMaxAbsFamilyIdInArrays() const
4851 {
4852   int ret=-std::numeric_limits<int>::max(),tmp=-1;
4853   if((const DataArrayInt *)_fam_nodes)
4854     {
4855       int val=_fam_nodes->getMaxValue(tmp);
4856       ret=std::max(ret,std::abs(val));
4857     }
4858   if((const DataArrayInt *)_fam_cells)
4859     {
4860       int val=_fam_cells->getMaxValue(tmp);
4861       ret=std::max(ret,std::abs(val));
4862     }
4863   if((const DataArrayInt *)_fam_faces)
4864     {
4865       int val=_fam_faces->getMaxValue(tmp);
4866       ret=std::max(ret,std::abs(val));
4867     }
4868   return ret;
4869 }
4870
4871 int MEDFileStructuredMesh::getMaxFamilyIdInArrays() const
4872 {
4873   int ret=-std::numeric_limits<int>::max(),tmp=-1;
4874   if((const DataArrayInt *)_fam_nodes)
4875     {
4876       int val=_fam_nodes->getMaxValue(tmp);
4877       ret=std::max(ret,val);
4878     }
4879   if((const DataArrayInt *)_fam_cells)
4880     {
4881       int val=_fam_cells->getMaxValue(tmp);
4882       ret=std::max(ret,val);
4883     }
4884   if((const DataArrayInt *)_fam_faces)
4885     {
4886       int val=_fam_faces->getMaxValue(tmp);
4887       ret=std::max(ret,val);
4888     }
4889   return ret;
4890 }
4891
4892 int MEDFileStructuredMesh::getMinFamilyIdInArrays() const
4893 {
4894   int ret=std::numeric_limits<int>::max(),tmp=-1;
4895   if((const DataArrayInt *)_fam_nodes)
4896     {
4897       int val=_fam_nodes->getMinValue(tmp);
4898       ret=std::min(ret,val);
4899     }
4900   if((const DataArrayInt *)_fam_cells)
4901     {
4902       int val=_fam_cells->getMinValue(tmp);
4903       ret=std::min(ret,val);
4904     }
4905   if((const DataArrayInt *)_fam_faces)
4906     {
4907       int val=_fam_faces->getMinValue(tmp);
4908       ret=std::min(ret,val);
4909     }
4910   return ret;
4911 }
4912
4913 bool MEDFileStructuredMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
4914 {
4915   if(!MEDFileMesh::isEqual(other,eps,what))
4916     return false;
4917   const MEDFileStructuredMesh *otherC=dynamic_cast<const  MEDFileStructuredMesh *>(other);
4918   if(!otherC)
4919     {
4920       what="Mesh types differ ! This is structured and other is NOT !";
4921       return false;
4922     }
4923   const DataArrayInt *famc1=_fam_nodes;
4924   const DataArrayInt *famc2=otherC->_fam_nodes;
4925   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
4926     {
4927       what="Mismatch of families arr on nodes ! One is defined and not other !";
4928       return false;
4929     }
4930   if(famc1)
4931     {
4932       bool ret=famc1->isEqual(*famc2);
4933       if(!ret)
4934         {
4935           what="Families arr on nodes differ !";
4936           return false;
4937         }
4938     }
4939   famc1=_fam_cells;
4940   famc2=otherC->_fam_cells;
4941   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
4942     {
4943       what="Mismatch of families arr on cells ! One is defined and not other !";
4944       return false;
4945     }
4946   if(famc1)
4947     {
4948       bool ret=famc1->isEqual(*famc2);
4949       if(!ret)
4950         {
4951           what="Families arr on cells differ !";
4952           return false;
4953         }
4954     }
4955   famc1=_fam_faces;
4956   famc2=otherC->_fam_faces;
4957   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
4958     {
4959       what="Mismatch of families arr on faces ! One is defined and not other !";
4960       return false;
4961     }
4962   if(famc1)
4963     {
4964       bool ret=famc1->isEqual(*famc2);
4965       if(!ret)
4966         {
4967           what="Families arr on faces differ !";
4968           return false;
4969         }
4970     }
4971   famc1=_num_nodes;
4972   famc2=otherC->_num_nodes;
4973   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
4974     {
4975       what="Mismatch of numbering arr on nodes ! One is defined and not other !";
4976       return false;
4977     }
4978   if(famc1)
4979     {
4980       bool ret=famc1->isEqual(*famc2);
4981       if(!ret)
4982         {
4983           what="Numbering arr on nodes differ !";
4984           return false;
4985         }
4986     }
4987   famc1=_num_cells;
4988   famc2=otherC->_num_cells;
4989   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
4990     {
4991       what="Mismatch of numbering arr on cells ! One is defined and not other !";
4992       return false;
4993     }
4994   if(famc1)
4995     {
4996       bool ret=famc1->isEqual(*famc2);
4997       if(!ret)
4998         {
4999           what="Numbering arr on cells differ !";
5000           return false;
5001         }
5002     }
5003   famc1=_num_faces;
5004   famc2=otherC->_num_faces;
5005   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
5006     {
5007       what="Mismatch of numbering arr on faces ! One is defined and not other !";
5008       return false;
5009     }
5010   if(famc1)
5011     {
5012       bool ret=famc1->isEqual(*famc2);
5013       if(!ret)
5014         {
5015           what="Numbering arr on faces differ !";
5016           return false;
5017         }
5018     }
5019   const DataArrayAsciiChar *d1=_names_cells;
5020   const DataArrayAsciiChar *d2=otherC->_names_cells;
5021   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
5022     {
5023       what="Mismatch of naming arr on cells ! One is defined and not other !";
5024       return false;
5025     }
5026   if(d1)
5027     {
5028       bool ret=d1->isEqual(*d2);
5029       if(!ret)
5030         {
5031           what="Naming arr on cells differ !";
5032           return false;
5033         }
5034     }
5035   d1=_names_faces;
5036   d2=otherC->_names_faces;
5037   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
5038     {
5039       what="Mismatch of naming arr on faces ! One is defined and not other !";
5040       return false;
5041     }
5042   if(d1)
5043     {
5044       bool ret=d1->isEqual(*d2);
5045       if(!ret)
5046         {
5047           what="Naming arr on faces differ !";
5048           return false;
5049         }
5050     }
5051   d1=_names_nodes;
5052   d2=otherC->_names_nodes;
5053   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
5054     {
5055       what="Mismatch of naming arr on nodes ! One is defined and not other !";
5056       return false;
5057     }
5058   if(d1)
5059     {
5060       bool ret=d1->isEqual(*d2);
5061       if(!ret)
5062         {
5063           what="Naming arr on nodes differ !";
5064           return false;
5065         }
5066     }
5067   return true;
5068 }
5069
5070 void MEDFileStructuredMesh::clearNonDiscrAttributes() const
5071 {
5072   MEDFileMesh::clearNonDiscrAttributes();
5073   const DataArrayInt *tmp=_fam_nodes;
5074   if(tmp)
5075     (const_cast<DataArrayInt *>(tmp))->setName("");
5076   tmp=_num_nodes;
5077   if(tmp)
5078     (const_cast<DataArrayInt *>(tmp))->setName("");
5079   tmp=_fam_cells;
5080   if(tmp)
5081     (const_cast<DataArrayInt *>(tmp))->setName("");
5082   tmp=_num_cells;
5083   if(tmp)
5084     (const_cast<DataArrayInt *>(tmp))->setName("");
5085   tmp=_fam_faces;
5086   if(tmp)
5087     (const_cast<DataArrayInt *>(tmp))->setName("");
5088   tmp=_num_faces;
5089   if(tmp)
5090     (const_cast<DataArrayInt *>(tmp))->setName("");
5091 }
5092
5093 /*!
5094  * Returns ids of mesh entities contained in given families of a given dimension.
5095  *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
5096  *          are required.
5097  *  \param [in] fams - the names of the families of interest.
5098  *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
5099  *          returned instead of ids.
5100  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
5101  *          numbers, if available and required, of mesh entities of the families. The caller
5102  *          is to delete this array using decrRef() as it is no more needed. 
5103  *  \throw If the family field is missing for \a meshDimRelToMaxExt.
5104  */
5105 DataArrayInt *MEDFileStructuredMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const
5106 {
5107   std::vector<int> famIds(getFamiliesIds(fams));
5108   switch(meshDimRelToMaxExt)
5109   {
5110     case 1:
5111       {
5112         if((const DataArrayInt *)_fam_nodes)
5113           {
5114             MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
5115             if(!famIds.empty())
5116               da=_fam_nodes->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
5117             else
5118               da=_fam_nodes->getIdsEqualList(0,0);
5119             if(renum)
5120               return MEDFileUMeshSplitL1::Renumber(_num_nodes,da);
5121             else
5122               return da.retn();
5123           }
5124         else
5125           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on nodes !");
5126         break;
5127       }
5128     case 0:
5129       {
5130         if((const DataArrayInt *)_fam_cells)
5131           {
5132             MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
5133             if(!famIds.empty())
5134               da=_fam_cells->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
5135             else
5136               da=_fam_cells->getIdsEqualList(0,0);
5137             if(renum)
5138               return MEDFileUMeshSplitL1::Renumber(_num_cells,da);
5139             else
5140               return da.retn();
5141           }
5142         else
5143           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on cells !");
5144         break;
5145       }
5146     case -1:
5147       {
5148         if((const DataArrayInt *)_fam_faces)
5149           {
5150             MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
5151             if(!famIds.empty())
5152               da=_fam_faces->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
5153             else
5154               da=_fam_faces->getIdsEqualList(0,0);
5155             if(renum)
5156               return MEDFileUMeshSplitL1::Renumber(_num_faces,da);
5157             else
5158               return da.retn();
5159           }
5160         else
5161           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on faces !");
5162         break;
5163       }
5164     default:
5165       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : input meshDimRelative must be in [0,1,-1] !");
5166   }
5167   throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : unmanaged case !");
5168 }
5169
5170 /*!
5171  * Sets the family field of a given relative dimension.
5172  *  \param [in] meshDimRelToMaxExt - the relative dimension of entities for which
5173  *          the family field is set.
5174  *  \param [in] famArr - the array of the family field.
5175  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5176  *  \throw If \a famArr has an invalid size.
5177  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1 and \a meshDimRelToMaxExt != -1.
5178  */
5179 void MEDFileStructuredMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr)
5180 {
5181   const MEDCouplingStructuredMesh *mesh(getStructuredMesh());
5182   if(!mesh)
5183     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setFamilyFieldArr : no structured mesh specified ! Impossible to set family array !");
5184   switch(meshDimRelToMaxExt)
5185   {
5186     case 0:
5187       {
5188         int nbCells=mesh->getNumberOfCells();
5189         famArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of cells of mesh !");
5190         _fam_cells=famArr;
5191         break;
5192       }
5193     case 1:
5194       {
5195         int nbNodes=mesh->getNumberOfNodes();
5196         famArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !");
5197         _fam_nodes=famArr;
5198         break;
5199       }
5200     case -1:
5201       {
5202         int nbCells=mesh->getNumberOfCellsOfSubLevelMesh();
5203         famArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of faces of mesh !");
5204         _fam_faces=famArr;
5205         break;
5206       }
5207     default:
5208       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setFamilyFieldArr : Only available for levels 0 or 1 or -1 !");
5209   }
5210   if(famArr)
5211     famArr->incrRef();
5212 }
5213
5214 /*!
5215  * Sets the optional numbers of mesh entities of a given dimension.
5216  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5217  *  \param [in] renumArr - the array of the numbers.
5218  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5219  *  \throw If \a renumArr has an invalid size.
5220  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
5221  */
5222 void MEDFileStructuredMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr)
5223 {
5224   const MEDCouplingStructuredMesh *mesh=getStructuredMesh();
5225   if(!mesh)
5226     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : no structured mesh specified ! Impossible to set number array !");
5227   switch(meshDimRelToMaxExt)
5228   {
5229     case 0:
5230       {
5231         int nbCells=mesh->getNumberOfCells();
5232         renumArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Renum arr ! Mismatch with number of cells of mesh !");
5233         _num_cells=renumArr;
5234         break;
5235       }
5236     case 1:
5237       {
5238         int nbNodes=mesh->getNumberOfNodes();
5239         renumArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !");
5240         _num_nodes=renumArr;
5241         break;
5242       }
5243     case -1:
5244       {
5245         int nbCells=mesh->getNumberOfCellsOfSubLevelMesh();
5246         renumArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Renum arr ! Mismatch with number of faces of mesh !");
5247         _num_faces=renumArr;
5248         break;
5249       }
5250     default:
5251       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : Only available for levels 0 or 1 or -1 !");
5252   }
5253   if(renumArr)
5254     renumArr->incrRef();
5255 }
5256
5257 /*!
5258  * Sets the optional names of mesh entities of a given dimension.
5259  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5260  *  \param [in] nameArr - the array of the names.
5261  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5262  *  \throw If \a nameArr has an invalid size.
5263  */
5264 void MEDFileStructuredMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr)
5265 {
5266   const MEDCouplingStructuredMesh *mesh(getStructuredMesh());
5267   if(!mesh)
5268     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : no structured mesh specified ! Impossible to set names array !");
5269   switch(meshDimRelToMaxExt)
5270   {
5271     case 0:
5272       {
5273         int nbCells=mesh->getNumberOfCells();
5274         nameArr->checkNbOfTuplesAndComp(nbCells,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of cells of mesh !");
5275         _names_cells=nameArr;
5276         break;
5277       }
5278     case 1:
5279       {
5280         int nbNodes=mesh->getNumberOfNodes();
5281         nameArr->checkNbOfTuplesAndComp(nbNodes,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of nodes of mesh !");
5282         _names_nodes=nameArr;
5283         break;
5284       }
5285     case -1:
5286       {
5287         int nbCells=mesh->getNumberOfCellsOfSubLevelMesh();
5288         nameArr->checkNbOfTuplesAndComp(nbCells,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of faces of mesh !");
5289         _names_cells=nameArr;
5290       }
5291     default:
5292       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : Only available for levels 0 or 1 or -1 !");
5293   }
5294   if(nameArr)
5295     nameArr->incrRef();
5296 }
5297
5298 /*!
5299  * Adds a group of nodes to \a this mesh.
5300  *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
5301  *          The ids should be sorted and different each other (MED file norm).
5302  *
5303  *  \warning this method can alter default "FAMILLE_ZERO" family.
5304  *  For users sensitive to this a call to MEDFileMesh::rearrangeFamilies will be necessary after addGroup session.
5305  *
5306  *  \throw If the node coordinates array is not set.
5307  *  \throw If \a ids == \c NULL.
5308  *  \throw If \a ids->getName() == "".
5309  *  \throw If \a ids does not respect the MED file norm.
5310  *  \throw If a group with name \a ids->getName() already exists.
5311  */
5312 void MEDFileStructuredMesh::addNodeGroup(const DataArrayInt *ids)
5313 {
5314   addGroup(1,ids);
5315 }
5316
5317 /*!
5318  * Adds a group of nodes/cells/faces/edges to \a this mesh.
5319  *
5320  *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
5321  *          The ids should be sorted and different each other (MED file norm).
5322  *
5323  * \warning this method can alter default "FAMILLE_ZERO" family.
5324  * For users sensitive to this a call to MEDFileMesh::rearrangeFamilies will be necessary after addGroup session.
5325  *
5326  *  \throw If the node coordinates array is not set.
5327  *  \throw If \a ids == \c NULL.
5328  *  \throw If \a ids->getName() == "".
5329  *  \throw If \a ids does not respect the MED file norm.
5330  *  \throw If a group with name \a ids->getName() already exists.
5331  */
5332 void MEDFileStructuredMesh::addGroup(int meshDimRelToMaxExt, const DataArrayInt *ids)
5333 {
5334   DataArrayInt *fam(getOrCreateAndGetFamilyFieldAtLevel(meshDimRelToMaxExt));
5335   addGroupUnderground(false,ids,fam);
5336   return ;
5337 }
5338
5339 /*!
5340  * Returns the family field for mesh entities of a given dimension.
5341  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5342  *  \return const DataArrayInt * - the family field. It is an array of ids of families
5343  *          each mesh entity belongs to. It can be \c NULL.
5344  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
5345  */
5346 const DataArrayInt *MEDFileStructuredMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) const
5347 {
5348   switch(meshDimRelToMaxExt)
5349   {
5350     case 0:
5351       return _fam_cells;
5352     case 1:
5353       return _fam_nodes;
5354     case -1:
5355       return _fam_faces;
5356     default:
5357       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamilyFieldAtLevel : Only available for levels 0 or 1 or -1 !");
5358   }
5359 }
5360
5361 /*!
5362  * Returns the family field for mesh entities of a given dimension.
5363  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5364  *  \return const DataArrayInt * - the family field. It is an array of ids of families
5365  *          each mesh entity belongs to. It can be \c NULL.
5366  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
5367  */
5368 DataArrayInt *MEDFileStructuredMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt)
5369 {
5370   switch(meshDimRelToMaxExt)
5371   {
5372     case 0:
5373       return _fam_cells;
5374     case 1:
5375       return _fam_nodes;
5376     case -1:
5377       return _fam_faces;
5378     default:
5379       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamilyFieldAtLevel : Only available for levels 0 or 1 or -1 !");
5380   }
5381 }
5382
5383 /*!
5384  * Returns the optional numbers of mesh entities of a given dimension.
5385  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5386  *  \return const DataArrayInt * - the array of the entity numbers.
5387  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5388  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
5389  */
5390 const DataArrayInt *MEDFileStructuredMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) const
5391 {
5392   switch(meshDimRelToMaxExt)
5393   {
5394     case 0:
5395       return _num_cells;
5396     case 1:
5397       return _num_nodes;
5398     case -1:
5399       return _num_faces;
5400     default:
5401       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberFieldAtLevel : Only available for levels 0 or 1 or -1 !");
5402   }
5403 }
5404
5405 /*!
5406  * Returns the optional numbers of mesh entities of a given dimension transformed using
5407  * DataArrayInt::invertArrayN2O2O2N().
5408  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5409  *  \return const DataArrayInt * - the array of the entity numbers transformed using
5410  *          DataArrayInt::invertArrayN2O2O2N().
5411  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
5412  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5413  */
5414 const DataArrayInt *MEDFileStructuredMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxExt) const
5415 {
5416   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
5417     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getRevNumberFieldAtLevel : Only available for levels 0 or 1 !");
5418   if(meshDimRelToMaxExt==0)
5419     {
5420       if((const DataArrayInt *)_num_cells)
5421         {
5422           int pos;
5423           int maxValue=_num_cells->getMaxValue(pos);
5424           _rev_num_cells=_num_cells->invertArrayN2O2O2N(maxValue+1);
5425           return _rev_num_cells;
5426         }
5427       else
5428         throw INTERP_KERNEL::Exception("MEDFileCMesh::getRevNumberFieldAtLevel : no cell renumbering for a request on reverse numbering !");
5429     }
5430   else
5431     {
5432       if((const DataArrayInt *)_num_nodes)
5433         {
5434           int pos;
5435           int maxValue=_num_nodes->getMaxValue(pos);
5436           _rev_num_nodes=_num_nodes->invertArrayN2O2O2N(maxValue+1);
5437           return _rev_num_nodes;
5438         }
5439       else
5440         throw INTERP_KERNEL::Exception("MEDFileCMesh::getRevNumberFieldAtLevel : no node renumbering for a request on reverse numbering !");
5441     }
5442 }
5443
5444 const DataArrayAsciiChar *MEDFileStructuredMesh::getNameFieldAtLevel(int meshDimRelToMaxExt) const
5445 {
5446   switch(meshDimRelToMaxExt)
5447   {
5448     case 0:
5449       return _names_cells;
5450     case 1:
5451       return _names_nodes;
5452     case -1:
5453       return _names_faces;
5454     default:
5455       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNameFieldAtLevel : Only available for levels 0 or 1 or -1 !");
5456   }
5457 }
5458
5459 /*!
5460  * Returns relative dimensions of mesh entities (excluding nodes) present in \a this mesh.
5461  *  \return std::vector<int> - a sequence of the relative dimensions: [0].
5462  */
5463 std::vector<int> MEDFileStructuredMesh::getNonEmptyLevels() const
5464 {
5465   std::vector<int> ret(1);
5466   return ret;
5467 }
5468
5469 /*!
5470  * Returns relative dimensions of mesh entities (including nodes) present in \a this mesh.
5471  *  \return std::vector<int> - a sequence of the relative dimensions: [1,0].
5472  */
5473 std::vector<int> MEDFileStructuredMesh::getNonEmptyLevelsExt() const
5474 {
5475   std::vector<int> ret(2);
5476   ret[0]=1;
5477   return ret;
5478 }
5479
5480 /*!
5481  * Returns the set of extensive levels (nodes included) where not NULL family arr are defined.
5482  */
5483 std::vector<int> MEDFileStructuredMesh::getFamArrNonEmptyLevelsExt() const
5484 {
5485   std::vector<int> ret;
5486   const DataArrayInt *famNodes(_fam_nodes),*famCells(_fam_cells),*famFaces(_fam_faces);
5487   if(famNodes)
5488     ret.push_back(1);
5489   if(famCells)
5490     ret.push_back(0);
5491   if(famFaces)
5492     ret.push_back(-1);
5493   return ret;
5494 }
5495
5496 /*!
5497  * Returns the set of extensive levels (nodes included) where not NULL numbering arr are defined.
5498  */
5499 std::vector<int> MEDFileStructuredMesh::getNumArrNonEmptyLevelsExt() const
5500 {
5501   std::vector<int> ret;
5502   const DataArrayInt *numNodes(_num_nodes),*numCells(_num_cells),*numFaces(_num_faces);
5503   if(numNodes)
5504     ret.push_back(1);
5505   if(numCells)
5506     ret.push_back(0);
5507   if(numFaces)
5508     ret.push_back(-1);
5509   return ret;
5510 }
5511
5512 /*!
5513  * Returns the set of extensive levels (nodes included) where not NULL naming arr are defined.
5514  */
5515 std::vector<int> MEDFileStructuredMesh::getNameArrNonEmptyLevelsExt() const
5516 {
5517   std::vector<int> ret;
5518   const DataArrayAsciiChar *namesNodes(_names_nodes),*namesCells(_names_cells),*namesFaces(_names_faces);
5519   if(namesNodes)
5520     ret.push_back(1);
5521   if(namesCells)
5522     ret.push_back(0);
5523   if(namesFaces)
5524     ret.push_back(-1);
5525   return ret;
5526 }
5527
5528 /*!
5529  * no implementation here, it is not a bug, but intresically no polyhedra in \a this.
5530  */
5531 bool MEDFileStructuredMesh::unPolyze(std::vector<int>& oldCode, std::vector<int>& newCode, DataArrayInt *& o2nRenumCell)
5532 {
5533   oldCode.clear(); newCode.clear(); o2nRenumCell=0;
5534   return false;
5535 }
5536
5537 void MEDFileStructuredMesh::changeFamilyIdArr(int oldId, int newId)
5538 {
5539   DataArrayInt *arr=_fam_nodes;
5540   if(arr)
5541     arr->changeValue(oldId,newId);
5542   arr=_fam_cells;
5543   if(arr)
5544     arr->changeValue(oldId,newId);
5545   arr=_fam_faces;
5546   if(arr)
5547     arr->changeValue(oldId,newId);
5548 }
5549
5550 std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > MEDFileStructuredMesh::getAllNonNullFamilyIds() const
5551 {
5552   std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret;
5553   const DataArrayInt *da(_fam_nodes);
5554   if(da)
5555     { da->incrRef(); ret.push_back(MEDCouplingAutoRefCountObjectPtr<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
5556   da=_fam_cells;
5557   if(da)
5558     { da->incrRef(); ret.push_back(MEDCouplingAutoRefCountObjectPtr<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
5559   da=_fam_faces;
5560   if(da)
5561     { da->incrRef(); ret.push_back(MEDCouplingAutoRefCountObjectPtr<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
5562   return ret;
5563 }
5564
5565 void MEDFileStructuredMesh::deepCpyAttributes()
5566 {
5567   if((const DataArrayInt*)_fam_nodes)
5568     _fam_nodes=_fam_nodes->deepCpy();
5569   if((const DataArrayInt*)_num_nodes)
5570     _num_nodes=_num_nodes->deepCpy();
5571   if((const DataArrayAsciiChar*)_names_nodes)
5572     _names_nodes=_names_nodes->deepCpy();
5573   if((const DataArrayInt*)_fam_cells)
5574     _fam_cells=_fam_cells->deepCpy();
5575   if((const DataArrayInt*)_num_cells)
5576     _num_cells=_num_cells->deepCpy();
5577   if((const DataArrayAsciiChar*)_names_cells)
5578     _names_cells=_names_cells->deepCpy();
5579   if((const DataArrayInt*)_fam_faces)
5580     _fam_faces=_fam_faces->deepCpy();
5581   if((const DataArrayInt*)_num_faces)
5582     _num_faces=_num_faces->deepCpy();
5583   if((const DataArrayAsciiChar*)_names_faces)
5584     _names_faces=_names_faces->deepCpy();
5585   if((const DataArrayInt*)_rev_num_nodes)
5586     _rev_num_nodes=_rev_num_nodes->deepCpy();
5587   if((const DataArrayInt*)_rev_num_cells)
5588     _rev_num_cells=_rev_num_cells->deepCpy();
5589 }
5590
5591 /*!
5592  * Returns a pointer to mesh at the specified level (here 0 is compulsary for cartesian mesh).
5593  * 
5594  * \return a pointer to cartesian mesh that need to be managed by the caller.
5595  * \warning the returned pointer has to be managed by the caller.
5596  */
5597
5598 /*!
5599  * Returns a pointer to MEDCouplingStructuredMesh held by \a this. 
5600  *  \param [in] meshDimRelToMax - it must be \c 0 or \c -1.
5601  *  \param [in] renum - it must be \c false.
5602  *  \return MEDCouplingMesh * - a pointer to MEDCouplingMesh that the caller is to
5603  *          delete using decrRef() as it is no more needed. 
5604  */
5605 MEDCouplingMesh *MEDFileStructuredMesh::getGenMeshAtLevel(int meshDimRelToMax, bool renum) const
5606 {
5607   if(renum)
5608     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support renumbering ! To do it perform request of renum array directly !");
5609   const MEDCouplingStructuredMesh *m(getStructuredMesh());
5610   switch(meshDimRelToMax)
5611   {
5612     case 0:
5613       {
5614         if(m)
5615           m->incrRef();
5616         return const_cast<MEDCouplingStructuredMesh *>(m);
5617       }
5618     case -1:
5619       {
5620         if(!m)
5621           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGenMeshAtLevel : level -1 requested must be non empty to be able to compute unstructured sub mesh !");
5622         buildMinusOneImplicitPartIfNeeded();
5623         MEDCouplingMesh *ret(_faces_if_necessary);
5624         if(ret)
5625           ret->incrRef();
5626         return ret;
5627       }
5628     default:
5629       throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support multi level for mesh 0 expected as input !");
5630   }
5631 }
5632
5633 /*!
5634  * Returns number of mesh entities of a given relative dimension in \a this mesh.
5635  *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
5636  *  \return int - the number of entities.
5637  *  \throw If no mesh entities of dimension \a meshDimRelToMaxExt are available in \a this mesh.
5638  */
5639 int MEDFileStructuredMesh::getSizeAtLevel(int meshDimRelToMaxExt) const
5640 {
5641   const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
5642   if(!cmesh)
5643     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : No structured mesh set !");
5644   switch(meshDimRelToMaxExt)
5645   {
5646     case 0:
5647       return cmesh->getNumberOfCells();
5648     case 1:
5649       return cmesh->getNumberOfNodes();
5650     case -1:
5651       return cmesh->getNumberOfCellsOfSubLevelMesh();
5652     default:
5653       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : Only available for levels 0 or 1 or -1 !");
5654   }
5655 }
5656
5657 int MEDFileStructuredMesh::getNumberOfNodes() const
5658 {
5659   const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
5660   if(!cmesh)
5661     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberOfNodes : no cartesian mesh set !");
5662   return cmesh->getNumberOfNodes();
5663 }
5664
5665 int MEDFileStructuredMesh::getNumberOfCellsAtLevel(int meshDimRelToMaxExt) const
5666 {
5667   const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
5668   if(!cmesh)
5669     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberOfNodes : no cartesian mesh set !");
5670   switch(meshDimRelToMaxExt)
5671   {
5672     case 0:
5673       return cmesh->getNumberOfCells();
5674     case -1:
5675       return cmesh->getNumberOfCellsOfSubLevelMesh();
5676     default:
5677       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberOfNodes : only meshDimRelToMax=0 and meshDimRelToMax=-1 supported !");
5678     }
5679 }
5680
5681 bool MEDFileStructuredMesh::hasImplicitPart() const
5682 {
5683   return true;
5684 }
5685
5686 /*!
5687  * \sa MEDFileStructuredMesh::getImplicitFaceMesh
5688  */
5689 int MEDFileStructuredMesh::buildImplicitPartIfAny(INTERP_KERNEL::NormalizedCellType gt) const
5690 {
5691   static const char MSG[]="MEDFileStructuredMesh::buildImplicitPartIfAny : the given geo type is not manageable by a structured mesh !";
5692   const MEDCoupling1SGTUMesh *zeFaceMesh(_faces_if_necessary);
5693   if(!zeFaceMesh)
5694     {
5695       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(getMeshDimension())));
5696       if(cm.getReverseExtrudedType()!=gt)
5697         throw INTERP_KERNEL::Exception(MSG);
5698       buildImplicitPart();
5699       return getStructuredMesh()->getNumberOfCellsOfSubLevelMesh();
5700     }
5701   else
5702     {
5703       if(gt!=zeFaceMesh->getCellModelEnum())
5704         throw INTERP_KERNEL::Exception(MSG);
5705       return zeFaceMesh->getNumberOfCells();
5706     }
5707 }
5708
5709 void MEDFileStructuredMesh::buildMinusOneImplicitPartIfNeeded() const
5710 {
5711   const MEDCoupling1SGTUMesh *zeFaceMesh(_faces_if_necessary);
5712   if(!zeFaceMesh)
5713     buildImplicitPart();
5714 }
5715
5716 void MEDFileStructuredMesh::buildImplicitPart() const
5717 {
5718   const MEDCouplingStructuredMesh *mcmesh(getStructuredMesh());
5719   if(!mcmesh)
5720     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::buildImplicitPart : Unable to build the implicit part of structured mesh because no structured mesh at level 0 defined !");
5721   _faces_if_necessary=mcmesh->build1SGTSubLevelMesh();
5722 }
5723
5724 void MEDFileStructuredMesh::releaseImplicitPartIfAny() const
5725 {
5726   _faces_if_necessary=0;
5727 }
5728
5729 /*!
5730  * Retrieves the internal pointer (no decrRef requested) of the implicit face mesh if any.
5731  * To force to build it you can invoke MEDFileStructuredMesh::buildImplicitPartIfAny method.
5732  * 
5733  * \sa MEDFileStructuredMesh::buildImplicitPartIfAny
5734  */
5735 MEDCoupling1SGTUMesh *MEDFileStructuredMesh::getImplicitFaceMesh() const
5736 {
5737   return _faces_if_necessary;
5738 }
5739
5740 std::vector<INTERP_KERNEL::NormalizedCellType> MEDFileStructuredMesh::getGeoTypesAtLevel(int meshDimRelToMax) const
5741 {
5742   const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
5743   if(!cmesh)
5744     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGeoTypesAtLevel : No structured mesh set !");
5745   switch(meshDimRelToMax)
5746   {
5747     case 0:
5748       {
5749         std::vector<INTERP_KERNEL::NormalizedCellType> ret(1,cmesh->getTypeOfCell(0));
5750         return ret;
5751       }
5752     case -1:
5753       {
5754         int mdim(cmesh->getMeshDimension());
5755         if(mdim<1)
5756           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGeoTypesAtLevel : only one level available for structured meshes ! Input 0 is mandatory or 0D mesh !");
5757         std::vector<INTERP_KERNEL::NormalizedCellType> ret(1,MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(mdim-1));
5758         return ret;
5759       }
5760     default:
5761       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGeoTypesAtLevel : only 2 levels available at most : 0 and -1 !");
5762   }
5763 }
5764
5765 int MEDFileStructuredMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType ct) const
5766 {
5767   if(ct!=MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(getMeshDimension()))
5768     return 0;
5769   else
5770     return getNumberOfCellsAtLevel(0);
5771 }
5772
5773 void MEDFileStructuredMesh::whichAreNodesFetched(const MEDFileField1TSStructItem& st, const MEDFileFieldGlobsReal *globs, std::vector<bool>& nodesFetched) const
5774 {
5775   if(st.getNumberOfItems()!=1)
5776     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 !");
5777   if(st[0].getGeo()!=MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(getMeshDimension()))
5778     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : The sturture of field is not lying on expected geo type !");
5779   if(getNumberOfNodes()!=(int)nodesFetched.size())
5780     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : invalid size of array !");
5781   if(st[0].getPflName().empty())
5782     {
5783       std::fill(nodesFetched.begin(),nodesFetched.end(),true);
5784       return ;
5785     }
5786   const DataArrayInt *arr(globs->getProfile(st[0].getPflName()));
5787   const MEDCouplingStructuredMesh *cmesh=getStructuredMesh();//cmesh not null because getNumberOfNodes called before
5788   int sz(nodesFetched.size());
5789   for(const int *work=arr->begin();work!=arr->end();work++)
5790     {
5791       std::vector<int> conn;
5792       cmesh->getNodeIdsOfCell(*work,conn);
5793       for(std::vector<int>::const_iterator it=conn.begin();it!=conn.end();it++)
5794         if(*it>=0 && *it<sz)
5795           nodesFetched[*it]=true;
5796         else
5797           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : internal error !");
5798     }
5799 }
5800
5801 med_geometry_type MEDFileStructuredMesh::GetGeoTypeFromMeshDim(int meshDim)
5802 {
5803   INTERP_KERNEL::NormalizedCellType ct(MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(meshDim));
5804   return typmai3[ct];
5805 }
5806
5807 void MEDFileStructuredMesh::LoadStrMeshDAFromFile(med_idt fid, int meshDim, int dt, int it, const std::string& mName, MEDFileMeshReadSelector *mrs,
5808                                                   MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& famCells, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& numCells, MEDCouplingAutoRefCountObjectPtr<DataArrayAsciiChar>& namesCells)
5809 {
5810   med_bool chgt=MED_FALSE,trsf=MED_FALSE;
5811   med_geometry_type geoTypeReq=MEDFileStructuredMesh::GetGeoTypeFromMeshDim(meshDim);
5812   int nbOfElt(0);
5813   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf);
5814   if(nbOfElt>0)
5815     {
5816       if(!mrs || mrs->isCellFamilyFieldReading())
5817         {
5818           famCells=DataArrayInt::New();
5819           famCells->alloc(nbOfElt,1);
5820           MEDFILESAFECALLERRD0(MEDmeshEntityFamilyNumberRd,(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,famCells->getPointer()));
5821         }
5822     }
5823   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,MED_NUMBER,MED_NODAL,&chgt,&trsf);
5824   if(nbOfElt>0)
5825     {
5826       if(!mrs || mrs->isCellNumFieldReading())
5827         {
5828           numCells=DataArrayInt::New();
5829           numCells->alloc(nbOfElt,1);
5830           MEDFILESAFECALLERRD0(MEDmeshEntityNumberRd,(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,numCells->getPointer()));
5831         }
5832     }
5833   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,MED_NAME,MED_NODAL,&chgt,&trsf);
5834   if(nbOfElt>0)
5835     {
5836       if(!mrs || mrs->isCellNameFieldReading())
5837         {
5838           namesCells=DataArrayAsciiChar::New();
5839           namesCells->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end
5840           MEDFILESAFECALLERRD0(MEDmeshEntityNameRd,(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,namesCells->getPointer()));
5841           namesCells->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end
5842         }
5843     }
5844 }
5845
5846 void MEDFileStructuredMesh::loadStrMeshFromFile(MEDFileStrMeshL2 *strm, med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
5847 {
5848   setName(strm->getName());
5849   setDescription(strm->getDescription());
5850   setUnivName(strm->getUnivName());
5851   setIteration(strm->getIteration());
5852   setOrder(strm->getOrder());
5853   setTimeValue(strm->getTime());
5854   setTimeUnit(strm->getTimeUnit());
5855   MEDFileMeshL2::ReadFamiliesAndGrps(fid,mName,_families,_groups,mrs);
5856   med_bool chgt=MED_FALSE,trsf=MED_FALSE;
5857   int nbOfElt(MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf));
5858   if(nbOfElt>0)
5859     {
5860       if(!mrs || mrs->isNodeFamilyFieldReading())
5861         {
5862           int nbNodes(getNumberOfNodes());
5863           if(nbOfElt>nbNodes)
5864             throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::loadStrMeshFromFile : invalid size of family node array regarding number of nodes in this ! File seems to be corrupted !");
5865           _fam_nodes=DataArrayInt::New();
5866           _fam_nodes->alloc(nbNodes,1);//yes nbNodes and not nbOfElt see next line.
5867           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...
5868             _fam_nodes->fillWithZero();
5869           MEDFILESAFECALLERRD0(MEDmeshEntityFamilyNumberRd,(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,_fam_nodes->getPointer()));
5870         }
5871     }
5872   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_NUMBER,MED_NODAL,&chgt,&trsf);
5873   if(nbOfElt>0)
5874     {
5875       if(!mrs || mrs->isNodeNumFieldReading())
5876         {
5877           _num_nodes=DataArrayInt::New();
5878           _num_nodes->alloc(nbOfElt,1);
5879           MEDFILESAFECALLERRD0(MEDmeshEntityNumberRd,(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,_num_nodes->getPointer()));
5880         }
5881     }
5882   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_NAME,MED_NODAL,&chgt,&trsf);
5883   if(nbOfElt>0)
5884     {
5885       if(!mrs || mrs->isNodeNameFieldReading())
5886         {
5887           _names_nodes=DataArrayAsciiChar::New();
5888           _names_nodes->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end
5889           MEDFILESAFECALLERRD0(MEDmeshEntityNameRd,(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,_names_nodes->getPointer()));
5890           _names_nodes->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end
5891         }
5892     }
5893   int meshDim(getStructuredMesh()->getMeshDimension());
5894   LoadStrMeshDAFromFile(fid,meshDim,dt,it,mName,mrs,_fam_cells,_num_cells,_names_cells);
5895   if(meshDim>=1)
5896     LoadStrMeshDAFromFile(fid,meshDim-1,dt,it,mName,mrs,_fam_faces,_num_faces,_names_faces);
5897 }
5898
5899 void MEDFileStructuredMesh::writeStructuredLL(med_idt fid, const std::string& maa) const
5900 {
5901   int meshDim(getStructuredMesh()->getMeshDimension());
5902   med_geometry_type geoTypeReq(GetGeoTypeFromMeshDim(meshDim)),geoTypeReq2(GetGeoTypeFromMeshDim(meshDim-1));
5903   //
5904   if((const DataArrayInt *)_fam_cells)
5905     MEDFILESAFECALLERWR0(MEDmeshEntityFamilyNumberWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq,_fam_cells->getNumberOfTuples(),_fam_cells->getConstPointer()));
5906   if((const DataArrayInt *)_fam_faces)
5907     MEDFILESAFECALLERWR0(MEDmeshEntityFamilyNumberWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq2,_fam_faces->getNumberOfTuples(),_fam_faces->getConstPointer()));
5908   if((const DataArrayInt *)_fam_nodes)
5909     MEDFILESAFECALLERWR0(MEDmeshEntityFamilyNumberWr,(fid,maa.c_str(),_iteration,_order,MED_NODE,MED_NONE,_fam_nodes->getNumberOfTuples(),_fam_nodes->getConstPointer()));
5910   if((const DataArrayInt *)_num_cells)
5911     MEDFILESAFECALLERWR0(MEDmeshEntityNumberWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq,_num_cells->getNumberOfTuples(),_num_cells->getConstPointer()));
5912   if((const DataArrayInt *)_num_faces)
5913     MEDFILESAFECALLERWR0(MEDmeshEntityNumberWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq2,_num_faces->getNumberOfTuples(),_num_faces->getConstPointer()));
5914   if((const DataArrayInt *)_num_nodes)
5915     MEDFILESAFECALLERWR0(MEDmeshEntityNumberWr,(fid,maa.c_str(),_iteration,_order,MED_NODE,MED_NONE,_num_nodes->getNumberOfTuples(),_num_nodes->getConstPointer()));
5916   if((const DataArrayAsciiChar *)_names_cells)
5917     {
5918       if(_names_cells->getNumberOfComponents()!=MED_SNAME_SIZE)
5919         {
5920           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on cells with number of components set to " << MED_SNAME_SIZE;
5921           oss << " ! The array has " << _names_cells->getNumberOfComponents() << " components !";
5922           throw INTERP_KERNEL::Exception(oss.str().c_str());
5923         }
5924       MEDFILESAFECALLERWR0(MEDmeshEntityNameWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq,_names_cells->getNumberOfTuples(),_names_cells->getConstPointer()));
5925     }
5926   if((const DataArrayAsciiChar *)_names_faces)
5927     {
5928       if(_names_faces->getNumberOfComponents()!=MED_SNAME_SIZE)
5929         {
5930           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on faces with number of components set to " << MED_SNAME_SIZE;
5931           oss << " ! The array has " << _names_faces->getNumberOfComponents() << " components !";
5932           throw INTERP_KERNEL::Exception(oss.str().c_str());
5933         }
5934       MEDFILESAFECALLERWR0(MEDmeshEntityNameWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq2,_names_faces->getNumberOfTuples(),_names_faces->getConstPointer()));
5935     }
5936   if((const DataArrayAsciiChar *)_names_nodes)
5937     {
5938       if(_names_nodes->getNumberOfComponents()!=MED_SNAME_SIZE)
5939         {
5940           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on nodes with number of components set to " << MED_SNAME_SIZE;
5941           oss << " ! The array has " << _names_cells->getNumberOfComponents() << " components !";
5942           throw INTERP_KERNEL::Exception(oss.str().c_str());
5943         }
5944       MEDFILESAFECALLERWR0(MEDmeshEntityNameWr,(fid,maa.c_str(),_iteration,_order,MED_NODE,MED_NONE,_names_nodes->getNumberOfTuples(),_names_nodes->getConstPointer()));
5945     }
5946   //
5947   MEDFileUMeshL2::WriteFamiliesAndGrps(fid,maa.c_str(),_families,_groups,_too_long_str);
5948 }
5949
5950 /*!
5951  * Returns an empty instance of MEDFileCMesh.
5952  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
5953  *          mesh using decrRef() as it is no more needed. 
5954  */
5955 MEDFileCMesh *MEDFileCMesh::New()
5956 {
5957   return new MEDFileCMesh;
5958 }
5959
5960 /*!
5961  * Returns a new MEDFileCMesh holding the mesh data that has been read from a given MED
5962  * file. The first mesh in the file is loaded.
5963  *  \param [in] fileName - the name of MED file to read.
5964  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
5965  *          mesh using decrRef() as it is no more needed. 
5966  *  \throw If the file is not readable.
5967  *  \throw If there is no meshes in the file.
5968  *  \throw If the mesh in the file is not a Cartesian one.
5969  */
5970 MEDFileCMesh *MEDFileCMesh::New(const std::string& fileName, MEDFileMeshReadSelector *mrs)
5971 {
5972   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
5973   if(ms.empty())
5974     {
5975       std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
5976       throw INTERP_KERNEL::Exception(oss.str().c_str());
5977     }
5978   MEDFileUtilities::CheckFileForRead(fileName);
5979   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
5980   int dt,it;
5981   ParaMEDMEM::MEDCouplingMeshType meshType;
5982   std::string dummy2;
5983   ParaMEDMEM::MEDCouplingAxisType dummy3;
5984   MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dummy3,dt,it,dummy2);
5985   return new MEDFileCMesh(fid,ms.front(),dt,it,mrs);
5986 }
5987
5988 /*!
5989  * Returns a new MEDFileCMesh holding the mesh data that has been read from a given MED
5990  * file. The mesh to load is specified by its name and numbers of a time step and an
5991  * iteration.
5992  *  \param [in] fileName - the name of MED file to read.
5993  *  \param [in] mName - the name of the mesh to read.
5994  *  \param [in] dt - the number of a time step.
5995  *  \param [in] it - the number of an iteration.
5996  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
5997  *          mesh using decrRef() as it is no more needed. 
5998  *  \throw If the file is not readable.
5999  *  \throw If there is no mesh with given attributes in the file.
6000  *  \throw If the mesh in the file is not a Cartesian one.
6001  */
6002 MEDFileCMesh *MEDFileCMesh::New(const std::string& fileName, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6003 {
6004   MEDFileUtilities::CheckFileForRead(fileName);
6005   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
6006   return new MEDFileCMesh(fid,mName,dt,it,mrs);
6007 }
6008
6009 std::size_t MEDFileCMesh::getHeapMemorySizeWithoutChildren() const
6010 {
6011   return MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren();
6012 }
6013
6014 std::vector<const BigMemoryObject *> MEDFileCMesh::getDirectChildrenWithNull() const
6015 {
6016   std::vector<const BigMemoryObject *> ret(MEDFileStructuredMesh::getDirectChildrenWithNull());
6017   ret.push_back((const MEDCouplingCMesh *)_cmesh);
6018   return ret;
6019 }
6020
6021 /*!
6022  * Returns the dimension on cells in \a this mesh.
6023  *  \return int - the mesh dimension.
6024  *  \throw If there are no cells in this mesh.
6025  */
6026 int MEDFileCMesh::getMeshDimension() const
6027 {
6028   if(!((const MEDCouplingCMesh*)_cmesh))
6029     throw INTERP_KERNEL::Exception("MEDFileCMesh::getMeshDimension : unable to get meshdimension because no mesh set !");
6030   return _cmesh->getMeshDimension();
6031 }
6032
6033 /*!
6034  * Returns the dimension on nodes in \a this mesh.
6035  *  \return int - the space dimension.
6036  *  \throw If there are no cells in this mesh.
6037  */
6038 int MEDFileCMesh::getSpaceDimension() const
6039 {
6040   if(!((const MEDCouplingCMesh*)_cmesh))
6041     throw INTERP_KERNEL::Exception("MEDFileCMesh::getSpaceDimension : unable to get spacedimension because no mesh set !");
6042   return _cmesh->getSpaceDimension();
6043 }
6044
6045 /*!
6046  * Returns a string describing \a this mesh.
6047  *  \return std::string - the mesh information string.
6048  */
6049 std::string MEDFileCMesh::simpleRepr() const
6050 {
6051   return MEDFileStructuredMesh::simpleRepr();
6052 }
6053
6054 /*!
6055  * Returns a full textual description of \a this mesh.
6056  *  \return std::string - the string holding the mesh description.
6057  */
6058 std::string MEDFileCMesh::advancedRepr() const
6059 {
6060   return simpleRepr();
6061 }
6062
6063 MEDFileMesh *MEDFileCMesh::shallowCpy() const
6064 {
6065   MEDCouplingAutoRefCountObjectPtr<MEDFileCMesh> ret(new MEDFileCMesh(*this));
6066   return ret.retn();
6067 }
6068
6069 MEDFileMesh *MEDFileCMesh::createNewEmpty() const
6070 {
6071   return new MEDFileCMesh;
6072 }
6073
6074 MEDFileMesh *MEDFileCMesh::deepCpy() const
6075 {
6076   MEDCouplingAutoRefCountObjectPtr<MEDFileCMesh> ret(new MEDFileCMesh(*this));
6077   ret->deepCpyEquivalences(*this);
6078   if((const MEDCouplingCMesh*)_cmesh)
6079     ret->_cmesh=static_cast<MEDCouplingCMesh*>(_cmesh->deepCpy());
6080   ret->deepCpyAttributes();
6081   return ret.retn();
6082 }
6083
6084 /*!
6085  * Checks if \a this and another mesh are equal.
6086  *  \param [in] other - the mesh to compare with.
6087  *  \param [in] eps - a precision used to compare real values.
6088  *  \param [in,out] what - the string returning description of unequal data.
6089  *  \return bool - \c true if the meshes are equal, \c false, else.
6090  */
6091 bool MEDFileCMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
6092 {
6093   if(!MEDFileStructuredMesh::isEqual(other,eps,what))
6094     return false;
6095   const MEDFileCMesh *otherC=dynamic_cast<const MEDFileCMesh *>(other);
6096   if(!otherC)
6097     {
6098       what="Mesh types differ ! This is cartesian and other is NOT !";
6099       return false;
6100     }
6101   clearNonDiscrAttributes();
6102   otherC->clearNonDiscrAttributes();
6103   const MEDCouplingCMesh *coo1=_cmesh;
6104   const MEDCouplingCMesh *coo2=otherC->_cmesh;
6105   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
6106     {
6107       what="Mismatch of cartesian meshes ! One is defined and not other !";
6108       return false;
6109     }
6110   if(coo1)
6111     {
6112       bool ret=coo1->isEqual(coo2,eps);
6113       if(!ret)
6114         {
6115           what="cartesian meshes differ !";
6116           return false;
6117         }
6118     }
6119   return true;
6120 }
6121
6122 /*!
6123  * Clears redundant attributes of incorporated data arrays.
6124  */
6125 void MEDFileCMesh::clearNonDiscrAttributes() const
6126 {
6127   MEDFileStructuredMesh::clearNonDiscrAttributes();
6128   MEDFileUMeshSplitL1::ClearNonDiscrAttributes(_cmesh);//to it is not a bug umeshsplit have already the method implemented
6129 }
6130
6131 MEDFileCMesh::MEDFileCMesh()
6132 {
6133 }
6134
6135 MEDFileCMesh::MEDFileCMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6136 try
6137 {
6138     loadLLWithAdditionalItems(fid,mName,dt,it,mrs);
6139 }
6140 catch(INTERP_KERNEL::Exception& e)
6141 {
6142     throw e;
6143 }
6144
6145 void MEDFileCMesh::loadLL(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6146 {
6147   ParaMEDMEM::MEDCouplingMeshType meshType;
6148   int dummy0,dummy1;
6149   std::string dtunit;
6150   ParaMEDMEM::MEDCouplingAxisType axType;
6151   int mid=MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,axType,dummy0,dummy1,dtunit);
6152   if(meshType!=CARTESIAN)
6153     {
6154       std::ostringstream oss; oss << "Trying to load as cartesian an existing mesh with name '" << mName << "' that is NOT cartesian !";
6155       throw INTERP_KERNEL::Exception(oss.str().c_str());
6156     }
6157   MEDFileCMeshL2 loaderl2;
6158   loaderl2.loadAll(fid,mid,mName,dt,it);
6159   setAxType(loaderl2.getAxType());
6160   MEDCouplingCMesh *mesh=loaderl2.getMesh();
6161   mesh->incrRef();
6162   _cmesh=mesh;
6163   loadStrMeshFromFile(&loaderl2,fid,mName,dt,it,mrs);
6164 }
6165
6166 /*!
6167  * Returns a const pointer to MEDCouplingCMesh held by \a this mesh.
6168  *  \return const MEDCouplingCMesh * - a pointer to the held MEDCouplingCMesh.
6169  */
6170 const MEDCouplingCMesh *MEDFileCMesh::getMesh() const
6171 {
6172   synchronizeTinyInfoOnLeaves();
6173   return _cmesh;
6174 }
6175
6176 const MEDCouplingStructuredMesh *MEDFileCMesh::getStructuredMesh() const
6177 {
6178   synchronizeTinyInfoOnLeaves();
6179   return _cmesh;
6180 }
6181
6182 /*!
6183  * Sets the MEDCouplingCMesh holding the data of \a this mesh.
6184  *  \param [in] m - the new MEDCouplingCMesh to refer to.
6185  *  \throw If the name or the description of \a this mesh and \a m are not empty and are
6186  *         different. 
6187  */
6188 void MEDFileCMesh::setMesh(MEDCouplingCMesh *m)
6189 {
6190   dealWithTinyInfo(m);
6191   if(m)
6192     m->incrRef();
6193   _cmesh=m;
6194 }
6195
6196 MEDFileMesh *MEDFileCMesh::cartesianize() const
6197 {
6198   if(getAxType()==AX_CART)
6199     {
6200       incrRef();
6201       return const_cast<MEDFileCMesh *>(this);
6202     }
6203   else
6204     {
6205       const MEDCouplingCMesh *cmesh(getMesh());
6206       if(!cmesh)
6207         throw INTERP_KERNEL::Exception("MEDFileCMesh::cartesianize : impossible to turn into cartesian because the mesh is null !");
6208       MEDCouplingAutoRefCountObjectPtr<MEDCouplingCurveLinearMesh> clmesh(cmesh->buildCurveLinear());
6209       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords(clmesh->getCoords()->cartesianize(getAxType()));
6210       clmesh->setCoords(coords);
6211       MEDCouplingAutoRefCountObjectPtr<MEDFileCurveLinearMesh> ret(MEDFileCurveLinearMesh::New());
6212       ret->MEDFileStructuredMesh::operator=(*this);
6213       ret->setMesh(clmesh);
6214       ret->setAxType(AX_CART);
6215       return ret.retn();
6216     }
6217 }
6218
6219 void MEDFileCMesh::writeLL(med_idt fid) const
6220 {
6221   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
6222   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
6223   INTERP_KERNEL::AutoPtr<char> dtunit=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE);
6224   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
6225   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
6226   MEDLoaderBase::safeStrCpy(_dt_unit.c_str(),MED_LNAME_SIZE,dtunit,_too_long_str);
6227   int spaceDim(_cmesh->getSpaceDimension());
6228   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
6229   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
6230   for(int i=0;i<spaceDim;i++)
6231     {
6232       std::string info(_cmesh->getCoordsAt(i)->getInfoOnComponent(0));
6233       std::string c,u;
6234       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
6235       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
6236       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
6237     }
6238   // MED_CARTESIAN and not MEDFileMeshL2::TraduceAxisTypeRev(getAxType()) ! Yes it is not a bug. The discrimination is done in MEDmeshGridTypeWr.
6239   MEDFILESAFECALLERWR0(MEDmeshCr,(fid,maa,spaceDim,spaceDim,MED_STRUCTURED_MESH,desc,dtunit,MED_SORT_DTIT,MED_CARTESIAN,comp,unit));
6240   if(_univ_wr_status)
6241     MEDFILESAFECALLERWR0(MEDmeshUniversalNameWr,(fid,maa));
6242   MEDFILESAFECALLERWR0(MEDmeshGridTypeWr,(fid,maa,MEDFileMeshL2::TraduceAxisTypeRevStruct(getAxType())));
6243   for(int i=0;i<spaceDim;i++)
6244     {
6245       const DataArrayDouble *da=_cmesh->getCoordsAt(i);
6246       MEDFILESAFECALLERWR0(MEDmeshGridIndexCoordinateWr,(fid,maa,_iteration,_order,_time,i+1,da->getNumberOfTuples(),da->getConstPointer()));
6247     }
6248   //
6249   std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE));
6250   MEDFileStructuredMesh::writeStructuredLL(fid,meshName);
6251 }
6252
6253 void MEDFileCMesh::synchronizeTinyInfoOnLeaves() const
6254 {
6255   const MEDCouplingCMesh *cmesh=_cmesh;
6256   if(!cmesh)
6257     return;
6258   (const_cast<MEDCouplingCMesh *>(cmesh))->setName(_name);
6259   (const_cast<MEDCouplingCMesh *>(cmesh))->setDescription(_desc_name);
6260   (const_cast<MEDCouplingCMesh *>(cmesh))->setTime(_time,_iteration,_order);
6261   (const_cast<MEDCouplingCMesh *>(cmesh))->setTimeUnit(_dt_unit);
6262 }
6263
6264 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New()
6265 {
6266   return new MEDFileCurveLinearMesh;
6267 }
6268
6269 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const std::string& fileName, MEDFileMeshReadSelector *mrs)
6270 {
6271   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
6272   if(ms.empty())
6273     {
6274       std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
6275       throw INTERP_KERNEL::Exception(oss.str().c_str());
6276     }
6277   MEDFileUtilities::CheckFileForRead(fileName);
6278   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
6279   int dt,it;
6280   ParaMEDMEM::MEDCouplingMeshType meshType;
6281   ParaMEDMEM::MEDCouplingAxisType dummy3;
6282   std::string dummy2;
6283   MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dummy3,dt,it,dummy2);
6284   return new MEDFileCurveLinearMesh(fid,ms.front(),dt,it,mrs);
6285 }
6286
6287 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const std::string& fileName, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6288 {
6289   MEDFileUtilities::CheckFileForRead(fileName);
6290   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
6291   return new MEDFileCurveLinearMesh(fid,mName,dt,it,mrs);
6292 }
6293
6294 std::size_t MEDFileCurveLinearMesh::getHeapMemorySizeWithoutChildren() const
6295 {
6296   return MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren();
6297 }
6298
6299 std::vector<const BigMemoryObject *> MEDFileCurveLinearMesh::getDirectChildrenWithNull() const
6300 {
6301   std::vector<const BigMemoryObject *> ret(MEDFileStructuredMesh::getDirectChildrenWithNull());
6302   ret.push_back((const MEDCouplingCurveLinearMesh *)_clmesh);
6303   return ret;
6304 }
6305
6306 MEDFileMesh *MEDFileCurveLinearMesh::shallowCpy() const
6307 {
6308   MEDCouplingAutoRefCountObjectPtr<MEDFileCurveLinearMesh> ret(new MEDFileCurveLinearMesh(*this));
6309   return ret.retn();
6310 }
6311
6312 MEDFileMesh *MEDFileCurveLinearMesh::createNewEmpty() const
6313 {
6314   return new MEDFileCurveLinearMesh;
6315 }
6316
6317 MEDFileMesh *MEDFileCurveLinearMesh::deepCpy() const
6318 {
6319   MEDCouplingAutoRefCountObjectPtr<MEDFileCurveLinearMesh> ret(new MEDFileCurveLinearMesh(*this));
6320   ret->deepCpyEquivalences(*this);
6321   if((const MEDCouplingCurveLinearMesh*)_clmesh)
6322     ret->_clmesh=static_cast<MEDCouplingCurveLinearMesh*>(_clmesh->deepCpy());
6323   ret->deepCpyAttributes();
6324   return ret.retn();
6325 }
6326
6327 int MEDFileCurveLinearMesh::getMeshDimension() const
6328 {
6329   if(!((const MEDCouplingCurveLinearMesh*)_clmesh))
6330     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::getMeshDimension : unable to get meshdimension because no mesh set !");
6331   return _clmesh->getMeshDimension();
6332 }
6333
6334 std::string MEDFileCurveLinearMesh::simpleRepr() const
6335 {
6336   return MEDFileStructuredMesh::simpleRepr();
6337 }
6338
6339 std::string MEDFileCurveLinearMesh::advancedRepr() const
6340 {
6341   return simpleRepr();
6342 }
6343
6344 bool MEDFileCurveLinearMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
6345 {
6346   if(!MEDFileStructuredMesh::isEqual(other,eps,what))
6347     return false;
6348   const MEDFileCurveLinearMesh *otherC=dynamic_cast<const MEDFileCurveLinearMesh *>(other);
6349   if(!otherC)
6350     {
6351       what="Mesh types differ ! This is curve linear and other is NOT !";
6352       return false;
6353     }
6354   clearNonDiscrAttributes();
6355   otherC->clearNonDiscrAttributes();
6356   const MEDCouplingCurveLinearMesh *coo1=_clmesh;
6357   const MEDCouplingCurveLinearMesh *coo2=otherC->_clmesh;
6358   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
6359     {
6360       what="Mismatch of curve linear meshes ! One is defined and not other !";
6361       return false;
6362     }
6363   if(coo1)
6364     {
6365       bool ret=coo1->isEqual(coo2,eps);
6366       if(!ret)
6367         {
6368           what="curve linear meshes differ !";
6369           return false;
6370         }
6371     }
6372   return true;
6373 }
6374
6375 void MEDFileCurveLinearMesh::clearNonDiscrAttributes() const
6376 {
6377   MEDFileStructuredMesh::clearNonDiscrAttributes();
6378   MEDFileUMeshSplitL1::ClearNonDiscrAttributes(_clmesh);//to it is not a bug umeshsplit have already the method implemented
6379 }
6380
6381 void MEDFileCurveLinearMesh::synchronizeTinyInfoOnLeaves() const
6382 {
6383   const MEDCouplingCurveLinearMesh *clmesh=_clmesh;
6384   if(!clmesh)
6385     return;
6386   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setName(_name);
6387   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setDescription(_desc_name);
6388   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setTime(_time,_iteration,_order);
6389   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setTimeUnit(_dt_unit);
6390 }
6391
6392 const MEDCouplingCurveLinearMesh *MEDFileCurveLinearMesh::getMesh() const
6393 {
6394   synchronizeTinyInfoOnLeaves();
6395   return _clmesh;
6396 }
6397
6398 void MEDFileCurveLinearMesh::setMesh(MEDCouplingCurveLinearMesh *m)
6399 {
6400   dealWithTinyInfo(m);
6401   if(m)
6402     m->incrRef();
6403   _clmesh=m;
6404 }
6405
6406 MEDFileMesh *MEDFileCurveLinearMesh::cartesianize() const
6407 {
6408   if(getAxType()==AX_CART)
6409     {
6410       incrRef();
6411       return const_cast<MEDFileCurveLinearMesh *>(this);
6412     }
6413   else
6414     {
6415       const MEDCouplingCurveLinearMesh *mesh(getMesh());
6416       if(!mesh)
6417         throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::cartesianize : impossible to turn into cartesian because the mesh is null !");
6418       const DataArrayDouble *coords(mesh->getCoords());
6419       if(!coords)
6420         throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::cartesianize : coordinate pointer in mesh is null !");
6421       MEDCouplingAutoRefCountObjectPtr<MEDFileCurveLinearMesh> ret(new MEDFileCurveLinearMesh(*this));
6422       MEDCouplingAutoRefCountObjectPtr<MEDCouplingCurveLinearMesh> mesh2(mesh->clone(false));
6423       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsCart(coords->cartesianize(getAxType()));
6424       mesh2->setCoords(coordsCart);
6425       ret->setMesh(mesh2);
6426       ret->setAxType(AX_CART);
6427       return ret.retn();
6428     }
6429 }
6430
6431 const MEDCouplingStructuredMesh *MEDFileCurveLinearMesh::getStructuredMesh() const
6432 {
6433   synchronizeTinyInfoOnLeaves();
6434   return _clmesh;
6435 }
6436
6437 MEDFileCurveLinearMesh::MEDFileCurveLinearMesh()
6438 {
6439 }
6440
6441 MEDFileCurveLinearMesh::MEDFileCurveLinearMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6442 try
6443 {
6444     loadLLWithAdditionalItems(fid,mName,dt,it,mrs);
6445 }
6446 catch(INTERP_KERNEL::Exception& e)
6447 {
6448     throw e;
6449 }
6450
6451 void MEDFileCurveLinearMesh::writeLL(med_idt fid) const
6452 {
6453   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
6454   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
6455   INTERP_KERNEL::AutoPtr<char> dtunit=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE);
6456   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
6457   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
6458   MEDLoaderBase::safeStrCpy(_dt_unit.c_str(),MED_LNAME_SIZE,dtunit,_too_long_str);
6459   int spaceDim=_clmesh->getSpaceDimension();
6460   int meshDim=_clmesh->getMeshDimension();
6461   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
6462   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
6463   const DataArrayDouble *coords=_clmesh->getCoords();
6464   if(!coords)
6465     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::writeLL : no coordinates set !");
6466   for(int i=0;i<spaceDim;i++)
6467     {
6468       std::string info(_clmesh->getCoords()->getInfoOnComponent(i));
6469       std::string c,u;
6470       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
6471       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
6472       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
6473     }
6474   MEDFILESAFECALLERWR0(MEDmeshCr,(fid,maa,spaceDim,meshDim,MED_STRUCTURED_MESH,desc,dtunit,MED_SORT_DTIT,MEDFileMeshL2::TraduceAxisTypeRev(getAxType()),comp,unit));
6475   if(_univ_wr_status)
6476     MEDFILESAFECALLERWR0(MEDmeshUniversalNameWr,(fid,maa));
6477   MEDFILESAFECALLERWR0(MEDmeshGridTypeWr,(fid,maa,MED_CURVILINEAR_GRID));
6478   std::vector<int> nodeGridSt=_clmesh->getNodeGridStructure();
6479   MEDFILESAFECALLERWR0(MEDmeshGridStructWr,(fid,maa,_iteration,_order,_time,&nodeGridSt[0]));
6480
6481   MEDFILESAFECALLERWR0(MEDmeshNodeCoordinateWr,(fid,maa,_iteration,_order,_time,MED_FULL_INTERLACE,coords->getNumberOfTuples(),coords->begin()));
6482   //
6483   std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE));
6484   MEDFileStructuredMesh::writeStructuredLL(fid,meshName);
6485 }
6486
6487 void MEDFileCurveLinearMesh::loadLL(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6488 {
6489   ParaMEDMEM::MEDCouplingMeshType meshType;
6490   int dummy0,dummy1;
6491   std::string dtunit;
6492   ParaMEDMEM::MEDCouplingAxisType axType;
6493   int mid=MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,axType,dummy0,dummy1,dtunit);
6494   setAxType(axType);
6495   if(meshType!=CURVE_LINEAR)
6496     {
6497       std::ostringstream oss; oss << "Trying to load as curve linear an existing mesh with name '" << mName << "' that is NOT curve linear !";
6498       throw INTERP_KERNEL::Exception(oss.str().c_str());
6499     }
6500   MEDFileCLMeshL2 loaderl2;
6501   loaderl2.loadAll(fid,mid,mName,dt,it);
6502   MEDCouplingCurveLinearMesh *mesh=loaderl2.getMesh();
6503   mesh->incrRef();
6504   _clmesh=mesh;
6505   loadStrMeshFromFile(&loaderl2,fid,mName,dt,it,mrs);
6506 }
6507
6508 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New()
6509 {
6510   return new MEDFileMeshMultiTS;
6511 }
6512
6513 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(const std::string& fileName)
6514 {
6515   return new MEDFileMeshMultiTS(fileName);
6516 }
6517
6518 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(const std::string& fileName, const std::string& mName)
6519 {
6520   return new MEDFileMeshMultiTS(fileName,mName);
6521 }
6522
6523 MEDFileMeshMultiTS *MEDFileMeshMultiTS::deepCpy() const
6524 {
6525   MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> ret=MEDFileMeshMultiTS::New();
6526   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> > meshOneTs(_mesh_one_ts.size());
6527   std::size_t i=0;
6528   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++,i++)
6529     if((const MEDFileMesh *)*it)
6530       meshOneTs[i]=(*it)->deepCpy();
6531   ret->_mesh_one_ts=meshOneTs;
6532   return ret.retn();
6533 }
6534
6535 std::size_t MEDFileMeshMultiTS::getHeapMemorySizeWithoutChildren() const
6536 {
6537   return _mesh_one_ts.capacity()*sizeof(MEDCouplingAutoRefCountObjectPtr<MEDFileMesh>);
6538 }
6539
6540 std::vector<const BigMemoryObject *> MEDFileMeshMultiTS::getDirectChildrenWithNull() const
6541 {
6542   std::vector<const BigMemoryObject *> ret;
6543   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
6544     ret.push_back((const MEDFileMesh *)*it);
6545   return ret;
6546 }
6547
6548 std::string MEDFileMeshMultiTS::getName() const
6549 {
6550   if(_mesh_one_ts.empty())
6551     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::getName : no time steps set !");
6552   return _mesh_one_ts[0]->getName();
6553 }
6554
6555 void MEDFileMeshMultiTS::setName(const std::string& newMeshName)
6556 {
6557   std::string oldName(getName());
6558   std::vector< std::pair<std::string,std::string> > v(1);
6559   v[0].first=oldName; v[0].second=newMeshName;
6560   changeNames(v);
6561 }
6562
6563 bool MEDFileMeshMultiTS::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab)
6564 {
6565   bool ret=false;
6566   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
6567     {
6568       MEDFileMesh *cur(*it);
6569       if(cur)
6570         ret=cur->changeNames(modifTab) || ret;
6571     }
6572   return ret;
6573 }
6574
6575 void MEDFileMeshMultiTS::cartesianizeMe()
6576 {
6577   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
6578     {
6579       MEDFileMesh *cur(*it);
6580       if(cur)
6581         {
6582           MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> ccur(cur->cartesianize());// Attention ! Do not wrap these two lines because memory leak !
6583           *it=ccur;
6584         }
6585     }
6586 }
6587
6588 MEDFileMesh *MEDFileMeshMultiTS::getOneTimeStep() const
6589 {
6590   if(_mesh_one_ts.empty())
6591     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::getOneTimeStep : empty time step set !");
6592   return const_cast<MEDFileMesh *>(static_cast<const MEDFileMesh *>(_mesh_one_ts[0]));
6593 }
6594
6595 void MEDFileMeshMultiTS::setOneTimeStep(MEDFileMesh *mesh1TimeStep)
6596 {
6597   if(!mesh1TimeStep)
6598     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::setOneTimeStep : input pointer should be different from 0 !");
6599   _mesh_one_ts.resize(1);
6600   mesh1TimeStep->incrRef();
6601   //MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> toto=mesh1TimeStep;
6602   _mesh_one_ts[0]=mesh1TimeStep;
6603 }
6604
6605 MEDFileJoints * MEDFileMeshMultiTS::getJoints() const
6606 {
6607   if ( MEDFileMesh* m = getOneTimeStep() )
6608     return m->getJoints();
6609   return 0;
6610 }
6611
6612 /*!
6613  * \brief Set Joints that are common to all time-stamps
6614  */
6615 void MEDFileMeshMultiTS::setJoints( MEDFileJoints* joints )
6616 {
6617   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
6618     {
6619       (*it)->setJoints( joints );
6620     }
6621 }
6622
6623 void MEDFileMeshMultiTS::write(med_idt fid) const
6624 {
6625   MEDFileJoints *joints(getJoints());
6626   bool jointsWritten(false);
6627
6628   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
6629     {
6630       if ( jointsWritten )
6631         const_cast<MEDFileMesh&>(**it).setJoints( 0 );
6632       else
6633         jointsWritten = true;
6634
6635       (*it)->copyOptionsFrom(*this);
6636       (*it)->write(fid);
6637     }
6638
6639   (const_cast<MEDFileMeshMultiTS*>(this))->setJoints( joints ); // restore joints
6640 }
6641
6642 void MEDFileMeshMultiTS::write(const std::string& fileName, int mode) const
6643 {
6644   med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode);
6645   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),medmod);
6646   std::ostringstream oss; oss << "MEDFileMesh : error on attempt to write in file : \"" << fileName << "\""; 
6647   MEDFileUtilities::CheckMEDCode(fid,fid,oss.str());
6648   write(fid);
6649 }
6650
6651 void MEDFileMeshMultiTS::loadFromFile(const std::string& fileName, const std::string& mName)
6652 {
6653   MEDFileJoints* joints = 0;
6654   if ( !_mesh_one_ts.empty() && getOneTimeStep() )
6655     {
6656       // joints of mName already read, pass them to MEDFileMesh::New() to prevent repeated reading
6657       joints = getOneTimeStep()->getJoints();
6658     }
6659
6660   _mesh_one_ts.clear();  //for the moment to be improved
6661   _mesh_one_ts.push_back( MEDFileMesh::New(fileName,mName,-1,-1,0, joints ));
6662 }
6663
6664 MEDFileMeshMultiTS::MEDFileMeshMultiTS()
6665 {
6666 }
6667
6668 MEDFileMeshMultiTS::MEDFileMeshMultiTS(const std::string& fileName)
6669 try
6670 {
6671     std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
6672     if(ms.empty())
6673       {
6674         std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
6675         throw INTERP_KERNEL::Exception(oss.str().c_str());
6676       }
6677     MEDFileUtilities::CheckFileForRead(fileName);
6678     MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
6679     int dt,it;
6680     ParaMEDMEM::MEDCouplingMeshType meshType;
6681     std::string dummy2;
6682     ParaMEDMEM::MEDCouplingAxisType dummy3;
6683     MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dummy3,dt,it,dummy2);
6684     loadFromFile(fileName,ms.front());
6685 }
6686 catch(INTERP_KERNEL::Exception& e)
6687 {
6688     throw e;
6689 }
6690
6691 MEDFileMeshMultiTS::MEDFileMeshMultiTS(const std::string& fileName, const std::string& mName)
6692 try
6693 {
6694     loadFromFile(fileName,mName);
6695 }
6696 catch(INTERP_KERNEL::Exception& e)
6697 {
6698     throw e;
6699 }
6700
6701 MEDFileMeshes *MEDFileMeshes::New()
6702 {
6703   return new MEDFileMeshes;
6704 }
6705
6706 MEDFileMeshes *MEDFileMeshes::New(const std::string& fileName)
6707 {
6708   return new MEDFileMeshes(fileName);
6709 }
6710
6711 void MEDFileMeshes::write(med_idt fid) const
6712 {
6713   checkCoherency();
6714   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++)
6715     {
6716       (*it)->copyOptionsFrom(*this);
6717       (*it)->write(fid);
6718     }
6719 }
6720
6721 void MEDFileMeshes::write(const std::string& fileName, int mode) const
6722 {
6723   med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode);
6724   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),medmod);
6725   std::ostringstream oss; oss << "MEDFileMesh : error on attempt to write in file : \"" << fileName << "\""; 
6726   MEDFileUtilities::CheckMEDCode(fid,fid,oss.str());
6727   checkCoherency();
6728   write(fid);
6729 }
6730
6731 int MEDFileMeshes::getNumberOfMeshes() const
6732 {
6733   return _meshes.size();
6734 }
6735
6736 MEDFileMeshesIterator *MEDFileMeshes::iterator()
6737 {
6738   return new MEDFileMeshesIterator(this);
6739 }
6740
6741 /** Return a borrowed reference (caller is not responsible) */
6742 MEDFileMesh *MEDFileMeshes::getMeshAtPos(int i) const
6743 {
6744   if(i<0 || i>=(int)_meshes.size())
6745     {
6746       std::ostringstream oss; oss << "MEDFileMeshes::getMeshAtPos : invalid mesh id given in parameter ! Should be in [0;" << _meshes.size() << ") !";
6747       throw INTERP_KERNEL::Exception(oss.str().c_str());
6748     }
6749   return _meshes[i]->getOneTimeStep();
6750 }
6751
6752 /** Return a borrowed reference (caller is not responsible) */
6753 MEDFileMesh *MEDFileMeshes::getMeshWithName(const std::string& mname) const
6754 {
6755   std::vector<std::string> ms=getMeshesNames();
6756   std::vector<std::string>::iterator it=std::find(ms.begin(),ms.end(),mname);
6757   if(it==ms.end())
6758     {
6759       std::ostringstream oss; oss << "MEDFileMeshes::getMeshWithName : Mesh  \"" << mname << "\" does not exist in this ! Existing are : ";
6760       std::copy(ms.begin(),ms.end(),std::ostream_iterator<std::string>(oss," "));
6761       throw INTERP_KERNEL::Exception(oss.str().c_str());
6762     }
6763   return getMeshAtPos((int)std::distance(ms.begin(),it));
6764 }
6765
6766 std::vector<std::string> MEDFileMeshes::getMeshesNames() const
6767 {
6768   std::vector<std::string> ret(_meshes.size());
6769   int i=0;
6770   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
6771     {
6772       const MEDFileMeshMultiTS *f=(*it);
6773       if(f)
6774         {
6775           ret[i]=f->getName();
6776         }
6777       else
6778         {
6779           std::ostringstream oss; oss << "MEDFileMeshes::getMeshesNames : At rank #" << i << " mesh is not defined !";
6780           throw INTERP_KERNEL::Exception(oss.str().c_str());
6781         }
6782     }
6783   return ret;
6784 }
6785
6786 bool MEDFileMeshes::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab)
6787 {
6788   bool ret=false;
6789   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::iterator it=_meshes.begin();it!=_meshes.end();it++)
6790     {
6791       MEDFileMeshMultiTS *cur(*it);
6792       if(cur)
6793         ret=cur->changeNames(modifTab) || ret;
6794     }
6795   return ret;
6796 }
6797
6798 void MEDFileMeshes::cartesianizeMe()
6799 {
6800   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::iterator it=_meshes.begin();it!=_meshes.end();it++)
6801     {
6802       MEDFileMeshMultiTS *cur(*it);
6803       if(cur)
6804         cur->cartesianizeMe();
6805     }
6806 }
6807
6808 void MEDFileMeshes::resize(int newSize)
6809 {
6810   _meshes.resize(newSize);
6811 }
6812
6813 void MEDFileMeshes::pushMesh(MEDFileMesh *mesh)
6814 {
6815   if(!mesh)
6816     throw INTERP_KERNEL::Exception("MEDFileMeshes::pushMesh : invalid input pointer ! should be different from 0 !");
6817   MEDFileMeshMultiTS *elt=MEDFileMeshMultiTS::New();
6818   elt->setOneTimeStep(mesh);
6819   _meshes.push_back(elt);
6820 }
6821
6822 void MEDFileMeshes::setMeshAtPos(int i, MEDFileMesh *mesh)
6823 {
6824   if(!mesh)
6825     throw INTERP_KERNEL::Exception("MEDFileMeshes::setMeshAtPos : invalid input pointer ! should be different from 0 !");
6826   if(i>=(int)_meshes.size())
6827     _meshes.resize(i+1);
6828   MEDFileMeshMultiTS *elt=MEDFileMeshMultiTS::New();
6829   elt->setOneTimeStep(mesh);
6830   _meshes[i]=elt;
6831 }
6832
6833 void MEDFileMeshes::destroyMeshAtPos(int i)
6834 {
6835   if(i<0 || i>=(int)_meshes.size())
6836     {
6837       std::ostringstream oss; oss << "MEDFileMeshes::destroyMeshAtPos : Invalid given id in input (" << i << ") should be in [0," << _meshes.size() << ") !";
6838       throw INTERP_KERNEL::Exception(oss.str().c_str());
6839     }
6840   _meshes.erase(_meshes.begin()+i);
6841 }
6842
6843 void MEDFileMeshes::loadFromFile(const std::string& fileName)
6844 {
6845   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
6846   int i=0;
6847   _meshes.resize(ms.size());
6848   for(std::vector<std::string>::const_iterator it=ms.begin();it!=ms.end();it++,i++)
6849     _meshes[i]=MEDFileMeshMultiTS::New(fileName,(*it));
6850 }
6851
6852 MEDFileMeshes::MEDFileMeshes()
6853 {
6854 }
6855
6856 MEDFileMeshes::MEDFileMeshes(const std::string& fileName)
6857 try
6858 {
6859     loadFromFile(fileName);
6860 }
6861 catch(INTERP_KERNEL::Exception& /*e*/)
6862 {
6863 }
6864
6865 MEDFileMeshes *MEDFileMeshes::deepCpy() const
6866 {
6867   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> > meshes(_meshes.size());
6868   std::size_t i=0;
6869   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
6870     if((const MEDFileMeshMultiTS *)*it)
6871       meshes[i]=(*it)->deepCpy();
6872   MEDCouplingAutoRefCountObjectPtr<MEDFileMeshes> ret=MEDFileMeshes::New();
6873   ret->_meshes=meshes;
6874   return ret.retn();
6875 }
6876
6877 std::size_t MEDFileMeshes::getHeapMemorySizeWithoutChildren() const
6878 {
6879   return _meshes.capacity()*(sizeof(MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS>));
6880 }
6881
6882 std::vector<const BigMemoryObject *> MEDFileMeshes::getDirectChildrenWithNull() const
6883 {
6884   std::vector<const BigMemoryObject *> ret;
6885   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++)
6886     ret.push_back((const MEDFileMeshMultiTS *)*it);
6887   return ret;
6888 }
6889
6890 std::string MEDFileMeshes::simpleRepr() const
6891 {
6892   std::ostringstream oss;
6893   oss << "(*****************)\n(* MEDFileMeshes *)\n(*****************)\n\n";
6894   simpleReprWithoutHeader(oss);
6895   return oss.str();
6896 }
6897
6898 void MEDFileMeshes::simpleReprWithoutHeader(std::ostream& oss) const
6899 {
6900   int nbOfMeshes=getNumberOfMeshes();
6901   oss << "There are " << nbOfMeshes << " meshes with the following names : \n";
6902   std::vector<std::string> mns=getMeshesNames();
6903   for(int i=0;i<nbOfMeshes;i++)
6904     oss << "  - #" << i << " \"" << mns[i] << "\"\n";
6905 }
6906
6907 void MEDFileMeshes::checkCoherency() const
6908 {
6909   static const char MSG[]="MEDFileMeshes::checkCoherency : mesh at rank ";
6910   int i=0;
6911   std::set<std::string> s;
6912   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
6913     {
6914       const MEDFileMeshMultiTS *elt=(*it);
6915       if(!elt)
6916         {
6917           std::ostringstream oss; oss << MSG << i << "/" << _meshes.size() << " is empty !";
6918           throw INTERP_KERNEL::Exception(oss.str().c_str());
6919         }
6920       std::size_t sz=s.size();
6921       s.insert(std::string((*it)->getName()));
6922       if(s.size()==sz)
6923         {
6924           std::ostringstream oss; oss << MSG << i << " has a name (\"" << (*it)->getName() << "\") already used by an another mesh in list !";
6925           throw INTERP_KERNEL::Exception(oss.str().c_str());
6926         }
6927     }
6928 }
6929
6930 MEDFileMeshesIterator::MEDFileMeshesIterator(MEDFileMeshes *ms):_ms(ms),_iter_id(0),_nb_iter(0)
6931 {
6932   if(ms)
6933     {
6934       ms->incrRef();
6935       _nb_iter=ms->getNumberOfMeshes();
6936     }
6937 }
6938
6939 MEDFileMeshesIterator::~MEDFileMeshesIterator()
6940 {
6941 }
6942
6943 MEDFileMesh *MEDFileMeshesIterator::nextt()
6944 {
6945   if(_iter_id<_nb_iter)
6946     {
6947       MEDFileMeshes *ms(_ms);
6948       if(ms)
6949         return ms->getMeshAtPos(_iter_id++);
6950       else
6951         return 0;
6952     }
6953   else
6954     return 0;
6955 }