Salome HOME
Addition of new reference coords including degenerated cells.
[tools/medcoupling.git] / src / MEDLoader / MEDFileMesh.cxx
1 // Copyright (C) 2007-2013  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.
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 "MEDLoaderBase.hxx"
27
28 #include "MEDCouplingUMesh.hxx"
29
30 #include "InterpKernelAutoPtr.hxx"
31
32 #include <limits>
33 #include <cmath>
34
35 using namespace ParaMEDMEM;
36
37 const char MEDFileMesh::DFT_FAM_NAME[]="FAMILLE_ZERO";
38
39 MEDFileMesh::MEDFileMesh():_order(-1),_iteration(-1),_time(0.),_univ_wr_status(true)
40 {
41 }
42
43 std::size_t MEDFileMesh::getHeapMemorySizeWithoutChildren() const
44 {
45   std::size_t ret(_dt_unit.capacity()+_name.capacity()+_univ_name.capacity()+_desc_name.capacity());
46   for(std::map<std::string, std::vector<std::string> >::const_iterator it=_groups.begin();it!=_groups.end();it++)
47     {
48       ret+=(*it).first.capacity()+(*it).second.capacity()*sizeof(std::string);
49       for(std::vector<std::string>::const_iterator it2=(*it).second.begin();it2!=(*it).second.end();it2++)
50         ret+=(*it2).capacity();
51     }
52   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
53     ret+=(*it).first.capacity()+sizeof(int);
54   return ret;
55 }
56
57 std::vector<const BigMemoryObject *> MEDFileMesh::getDirectChildren() const
58 {
59   return std::vector<const BigMemoryObject *>();
60 }
61
62 /*!
63  * Returns a new MEDFileMesh holding the mesh data that has been read from a given MED
64  * file. The first mesh in the file is loaded.
65  *  \param [in] fileName - the name of MED file to read.
66  *  \return MEDFileMesh * - a new instance of MEDFileMesh. The caller is to delete this
67  *          mesh using decrRef() as it is no more needed. 
68  *  \throw If the file is not readable.
69  *  \throw If there is no meshes in the file.
70  *  \throw If the mesh in the file is of a not supported type.
71  */
72 MEDFileMesh *MEDFileMesh::New(const std::string& fileName, MEDFileMeshReadSelector *mrs)
73 {
74   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
75   if(ms.empty())
76     {
77       std::ostringstream oss; oss << "MEDFileMesh::New : no meshes in file \"" << fileName << "\" !";
78       throw INTERP_KERNEL::Exception(oss.str().c_str());
79     }
80   MEDFileUtilities::CheckFileForRead(fileName);
81   ParaMEDMEM::MEDCouplingMeshType meshType;
82   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
83   int dt,it;
84   std::string dummy2;
85   MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dt,it,dummy2);
86   switch(meshType)
87     {
88     case UNSTRUCTURED:
89       {
90         MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret=MEDFileUMesh::New();
91         ret->loadUMeshFromFile(fid,ms.front(),dt,it,mrs);
92         return (MEDFileUMesh *)ret.retn();
93       }
94     case CARTESIAN:
95       {
96         MEDCouplingAutoRefCountObjectPtr<MEDFileCMesh> ret=MEDFileCMesh::New();
97         ret->loadCMeshFromFile(fid,ms.front(),dt,it,mrs);
98         return (MEDFileCMesh *)ret.retn();
99       }
100     case CURVE_LINEAR:
101       {
102         MEDCouplingAutoRefCountObjectPtr<MEDFileCurveLinearMesh> ret=MEDFileCurveLinearMesh::New();
103         ret->loadCLMeshFromFile(fid,ms.front(),dt,it,mrs);
104         return (MEDFileCurveLinearMesh *)ret.retn();
105       }
106     default:
107       {
108         std::ostringstream oss; oss << "MEDFileMesh::New : MED file exists and has mesh '" << ms.front() << "' exists but unsupported type yet !";
109         throw INTERP_KERNEL::Exception(oss.str().c_str());
110       }
111     }
112 }
113
114 /*!
115  * Returns a new MEDFileMesh holding the mesh data that has been read from a given MED
116  * file. The mesh to load is specified by its name and numbers of a time step and an
117  * iteration.
118  *  \param [in] fileName - the name of MED file to read.
119  *  \param [in] mName - the name of the mesh to read.
120  *  \param [in] dt - the number of a time step.
121  *  \param [in] it - the number of an iteration.
122  *  \return MEDFileMesh * - a new instance of MEDFileMesh. The caller is to delete this
123  *          mesh using decrRef() as it is no more needed. 
124  *  \throw If the file is not readable.
125  *  \throw If there is no mesh with given attributes in the file.
126  *  \throw If the mesh in the file is of a not supported type.
127  */
128 MEDFileMesh *MEDFileMesh::New(const std::string& fileName, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
129 {
130   MEDFileUtilities::CheckFileForRead(fileName);
131   ParaMEDMEM::MEDCouplingMeshType meshType;
132   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
133   int dummy0,dummy1;
134   std::string dummy2;
135   MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dummy2);
136   switch(meshType)
137     {
138     case UNSTRUCTURED:
139       {
140         MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret=MEDFileUMesh::New();
141         ret->loadUMeshFromFile(fid,mName,dt,it,mrs);
142         return (MEDFileUMesh *)ret.retn();
143       }
144     case CARTESIAN:
145       {
146         MEDCouplingAutoRefCountObjectPtr<MEDFileCMesh> ret=MEDFileCMesh::New();
147         ret->loadCMeshFromFile(fid,mName,dt,it,mrs);
148         return (MEDFileCMesh *)ret.retn();
149       }
150     case CURVE_LINEAR:
151       {
152         MEDCouplingAutoRefCountObjectPtr<MEDFileCurveLinearMesh> ret=MEDFileCurveLinearMesh::New();
153         ret->loadCLMeshFromFile(fid,mName,dt,it,mrs);
154         return (MEDFileCurveLinearMesh *)ret.retn();
155       }
156     default:
157       {
158         std::ostringstream oss; oss << "MEDFileMesh::New : MED file exists and has mesh '" << mName << "' exists but unsupported type yet !";
159         throw INTERP_KERNEL::Exception(oss.str().c_str());
160       }
161     }
162 }
163
164 /*!
165  * Writes \a this mesh into an open MED file specified by its descriptor.
166  *  \param [in] fid - the MED file descriptor.
167  *  \throw If the mesh name is not set.
168  *  \throw If the file is open for reading only.
169  *  \throw If the writing mode == 1 and the same data is present in an existing file.
170  */
171 void MEDFileMesh::write(med_idt fid) const
172 {
173   if(!existsFamily(0))
174     const_cast<MEDFileMesh *>(this)->addFamily(DFT_FAM_NAME,0);
175   if(_name.empty())
176     throw INTERP_KERNEL::Exception("MEDFileMesh : name is empty. MED file ask for a NON EMPTY name !");
177   writeLL(fid);
178 }
179
180 /*!
181  * Writes \a this mesh into a MED file specified by its name.
182  *  \param [in] fileName - the MED file name.
183  *  \param [in] mode - the writing mode. For more on \a mode, see \ref AdvMEDLoaderBasics.
184  * - 2 - erase; an existing file is removed.
185  * - 1 - append; same data should not be present in an existing file.
186  * - 0 - overwrite; same data present in an existing file is overwritten.
187  *  \throw If the mesh name is not set.
188  *  \throw If \a mode == 1 and the same data is present in an existing file.
189  */
190 void MEDFileMesh::write(const std::string& fileName, int mode) const
191 {
192   med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode);
193   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),medmod);
194   std::ostringstream oss; oss << "MEDFileMesh : error on attempt to write in file : \"" << fileName << "\""; 
195   MEDFileUtilities::CheckMEDCode(fid,fid,oss.str());
196   write(fid);
197 }
198
199 /*!
200  * Checks if \a this and another mesh are equal.
201  *  \param [in] other - the mesh to compare with.
202  *  \param [in] eps - a precision used to compare real values.
203  *  \param [in,out] what - the string returning description of unequal data.
204  *  \return bool - \c true if the meshes are equal, \c false, else.
205  */
206 bool MEDFileMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
207 {
208   if(_order!=other->_order)
209     {
210       what="Orders differ !";
211       return false;
212     }
213   if(_iteration!=other->_iteration)
214     {
215       what="Iterations differ !";
216       return false;
217     }
218   if(fabs(_time-other->_time)>eps)
219     {
220       what="Time values differ !";
221       return false;
222     }
223   if(_dt_unit!=other->_dt_unit)
224     {
225       what="Time units differ !";
226       return false;
227     }
228   if(_name!=other->_name)
229     {
230       what="Names differ !";
231       return false;
232     }
233   //univ_name has been ignored -> not a bug because it is a mutable attribute
234   if(_desc_name!=other->_desc_name)
235     {
236       what="Description names differ !";
237       return false;
238     }
239   if(!areGrpsEqual(other,what))
240     return false;
241   if(!areFamsEqual(other,what))
242     return false;
243   return true;
244 }
245
246 void MEDFileMesh::setName(const std::string& name)
247 {
248   _name=name;
249 }
250
251 /*!
252  * Clears redundant attributes of incorporated data arrays.
253  */
254 void MEDFileMesh::clearNonDiscrAttributes() const
255 {
256   
257 }
258
259 bool MEDFileMesh::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab)
260 {
261   for(std::vector< std::pair<std::string,std::string> >::const_iterator it=modifTab.begin();it!=modifTab.end();it++)
262     {
263       if((*it).first==_name)
264         {
265           _name=(*it).second;
266           return true;
267         }
268     }
269   return false;
270 }
271
272 /*!
273  * Copies data on groups and families from another mesh.
274  *  \param [in] other - the mesh to copy the data from.
275  */
276 void MEDFileMesh::copyFamGrpMapsFrom(const MEDFileMesh& other)
277 {
278   _groups=other._groups;
279   _families=other._families;
280 }
281
282
283 /*!
284  * This method clear all the groups in the map.
285  * So this method does not operate at all on arrays.
286  * So this method can lead to orphan families.
287  * 
288  * \sa MEDFileMesh::clearFamMap, MEDFileMesh::clearFamGrpMaps
289  */
290 void MEDFileMesh::clearGrpMap()
291 {
292   _groups.clear();
293 }
294
295 /*!
296  * This method clear all the families in the map.
297  * So this method does not operate at all on arrays.
298  * WARNING ! if there are some groups lying on cleared families, those groups will be impacted !
299  *
300  * \sa MEDFileMesh::clearFamMap, MEDFileMesh::clearFamGrpMaps
301  */
302 void MEDFileMesh::clearFamMap()
303 {
304   _families.clear();
305 }
306
307 /*!
308  * This method clear all the families and groups in the map.
309  * So this method does not operate at all on arrays.
310  * As all groups and families entry will be removed after 
311  * 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.
312  *
313  * \sa MEDFileMesh::clearFamMap, MEDFileMesh::clearFamMap
314  */
315 void MEDFileMesh::clearFamGrpMaps()
316 {
317   clearGrpMap();
318   clearFamMap();
319 }
320
321 /*!
322  * Returns names of families constituting a group.
323  *  \param [in] name - the name of the group of interest.
324  *  \return std::vector<std::string> - a sequence of names of the families.
325  *  \throw If the name of a nonexistent group is specified.
326  */
327 std::vector<std::string> MEDFileMesh::getFamiliesOnGroup(const std::string& name) const
328 {
329   std::string oname(name);
330   std::map<std::string, std::vector<std::string> >::const_iterator it=_groups.find(oname);
331   if(it==_groups.end())
332     {
333       std::vector<std::string> grps=getGroupsNames();
334       std::ostringstream oss; oss << "No such groupname \"" << name << "\" !\nAvailable groups are :";
335       std::copy(grps.begin(),grps.end(),std::ostream_iterator<std::string>(oss," "));
336       throw INTERP_KERNEL::Exception(oss.str().c_str());
337     }
338   return (*it).second;
339 }
340
341 /*!
342  * Returns names of families constituting some groups.
343  *  \param [in] grps - a sequence of names of groups of interest.
344  *  \return std::vector<std::string> - a sequence of names of the families.
345  *  \throw If a name of a nonexistent group is present in \a grps.
346  */
347 std::vector<std::string> MEDFileMesh::getFamiliesOnGroups(const std::vector<std::string>& grps) const
348 {
349   std::set<std::string> fams;
350   for(std::vector<std::string>::const_iterator it=grps.begin();it!=grps.end();it++)
351     {
352       std::map<std::string, std::vector<std::string> >::const_iterator it2=_groups.find(*it);
353       if(it2==_groups.end())
354         {
355           std::ostringstream oss; oss << "No such group in mesh \"" << _name << "\" : " << *it; 
356           std::vector<std::string> grps2=getGroupsNames(); oss << "\" !\nAvailable groups are :";
357           std::copy(grps2.begin(),grps2.end(),std::ostream_iterator<std::string>(oss," "));
358           throw INTERP_KERNEL::Exception(oss.str().c_str());
359         }
360       fams.insert((*it2).second.begin(),(*it2).second.end());
361     }
362   std::vector<std::string> fams2(fams.begin(),fams.end());
363   return fams2;
364 }
365
366 /*!
367  * Returns ids of families constituting a group.
368  *  \param [in] name - the name of the group of interest.
369  *  \return std::vector<int> - sequence of ids of the families.
370  *  \throw If the name of a nonexistent group is specified.
371  */
372 std::vector<int> MEDFileMesh::getFamiliesIdsOnGroup(const std::string& name) const
373 {
374   std::string oname(name);
375   std::map<std::string, std::vector<std::string> >::const_iterator it=_groups.find(oname);
376   std::vector<std::string> grps=getGroupsNames();
377   if(it==_groups.end())
378     {
379       std::ostringstream oss; oss << "No such groupname \"" << name << "\" !\nAvailable groups are :";
380       std::copy(grps.begin(),grps.end(),std::ostream_iterator<std::string>(oss," "));
381       throw INTERP_KERNEL::Exception(oss.str().c_str());
382     }
383   return getFamiliesIds((*it).second);
384 }
385
386 /*!
387  * Sets names of families constituting a group. If data on families of this group is
388  * already present, it is overwritten. Every family in \a fams is checked, and if a
389  family is not yet in \a this mesh, the default group id \c 0 is assigned to it.
390  *  \param [in] name - the name of the group of interest.
391  *  \param [in] fams - a sequence of names of families constituting the group.
392  */
393 void MEDFileMesh::setFamiliesOnGroup(const std::string& name, const std::vector<std::string>& fams)
394 {
395   std::string oname(name);
396   _groups[oname]=fams;
397   for(std::vector<std::string>::const_iterator it1=fams.begin();it1!=fams.end();it1++)
398     {
399       std::map<std::string,int>::iterator it2=_families.find(*it1);
400       if(it2==_families.end())
401         _families[*it1]=0;
402     }
403 }
404
405 /*!
406  * Sets families constituting a group. The families are specified by their ids.
407  * If a family name is not found by its id, an exception is thrown.
408  * If several families have same id, the first one in lexical order is taken.
409  *  \param [in] name - the name of the group of interest.
410  *  \param [in] famIds - a sequence of ids of families constituting the group.
411  *  \throw If a family name is not found by its id.
412  */
413 void MEDFileMesh::setFamiliesIdsOnGroup(const std::string& name, const std::vector<int>& famIds)
414 {
415   std::string oname(name);
416   std::vector<std::string> fams(famIds.size());
417   int i=0;
418   for(std::vector<int>::const_iterator it1=famIds.begin();it1!=famIds.end();it1++,i++)
419     {
420       std::string name2=getFamilyNameGivenId(*it1);
421       fams[i]=name2;
422     }
423   _groups[oname]=fams;
424 }
425
426 /*!
427  * Returns names of groups including a given family.
428  *  \param [in] name - the name of the family of interest.
429  *  \return std::vector<std::string> - a sequence of names of groups including the family.
430  */
431 std::vector<std::string> MEDFileMesh::getGroupsOnFamily(const std::string& name) const
432 {
433   std::vector<std::string> ret;
434   for(std::map<std::string, std::vector<std::string> >::const_iterator it1=_groups.begin();it1!=_groups.end();it1++)
435     {
436       for(std::vector<std::string>::const_iterator it2=(*it1).second.begin();it2!=(*it1).second.end();it2++)
437         if((*it2)==name)
438           {
439             ret.push_back((*it1).first);
440             break;
441           }
442     }
443   return ret;
444 }
445
446 /*!
447  * Adds an existing family to groups.
448  *  \param [in] famName - a name of family to add to \a grps.
449  *  \param [in] grps - a sequence of group names to add the family in.
450  *  \throw If a family named \a famName not yet exists.
451  */
452 void MEDFileMesh::setGroupsOnFamily(const std::string& famName, const std::vector<std::string>& grps)
453 {
454   std::string fName(famName);
455   const std::map<std::string,int>::const_iterator it=_families.find(fName);
456   if(it==_families.end())
457     {
458       std::vector<std::string> fams=getFamiliesNames();
459       std::ostringstream oss; oss << "No such familyname \"" << fName << "\" !\nAvailable families are :";
460       std::copy(fams.begin(),fams.end(),std::ostream_iterator<std::string>(oss," "));
461       throw INTERP_KERNEL::Exception(oss.str().c_str());
462     }
463   for(std::vector<std::string>::const_iterator it3=grps.begin();it3!=grps.end();it3++)
464     {
465       std::map< std::string, std::vector<std::string> >::iterator it2=_groups.find(*it3);
466       if(it2!=_groups.end())
467         (*it2).second.push_back(fName);
468       else
469         {
470           std::vector<std::string> grps2(1,fName);
471           _groups[*it3]=grps2;
472         }
473     }
474 }
475
476 /*!
477  * Returns names of all groups of \a this mesh.
478  *  \return std::vector<std::string> - a sequence of group names.
479  */
480 std::vector<std::string> MEDFileMesh::getGroupsNames() const
481 {
482   std::vector<std::string> ret(_groups.size());
483   int i=0;
484   for(std::map<std::string, std::vector<std::string> >::const_iterator it=_groups.begin();it!=_groups.end();it++,i++)
485     ret[i]=(*it).first;
486   return ret;
487 }
488
489 /*!
490  * Returns names of all families of \a this mesh.
491  *  \return std::vector<std::string> - a sequence of family names.
492  */
493 std::vector<std::string> MEDFileMesh::getFamiliesNames() const
494 {
495   std::vector<std::string> ret(_families.size());
496   int i=0;
497   for(std::map<std::string, int >::const_iterator it=_families.begin();it!=_families.end();it++,i++)
498     ret[i]=(*it).first;
499   return ret;
500 }
501
502 /*!
503  * Changes a name of every family, included in one group only, to be same as the group name.
504  *  \throw If there are families with equal names in \a this mesh.
505  */
506 void MEDFileMesh::assignFamilyNameWithGroupName()
507 {
508   std::map<std::string, std::vector<std::string> > groups(_groups);
509   std::map<std::string,int> newFams;
510   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
511     {
512       std::vector<std::string> grps=getGroupsOnFamily((*it).first);
513       if(grps.size()==1 && groups[grps[0]].size()==1)
514         {
515           if(newFams.find(grps[0])!=newFams.end())
516             {
517               std::ostringstream oss; oss << "MEDFileMesh::assignFamilyNameWithGroupName : Family \"" << grps[0] << "\" already exists !";
518               throw INTERP_KERNEL::Exception(oss.str().c_str());
519             }
520           newFams[grps[0]]=(*it).second;
521           std::vector<std::string>& grps2=groups[grps[0]];
522           std::size_t pos=std::distance(grps2.begin(),std::find(grps2.begin(),grps2.end(),(*it).first));
523           grps2[pos]=grps[0];
524         }
525       else
526         {
527           if(newFams.find((*it).first)!=newFams.end())
528             {
529               std::ostringstream oss; oss << "MEDFileMesh::assignFamilyNameWithGroupName : Family \"" << (*it).first << "\" already exists !";
530               throw INTERP_KERNEL::Exception(oss.str().c_str());
531             }
532           newFams[(*it).first]=(*it).second;
533         }
534     }
535   _families=newFams;
536   _groups=groups;
537 }
538
539 /*!
540  * Removes all groups lying on no family. If there is no empty groups, \a this is let untouched.
541  * 
542  * \return the removed groups.
543  */
544 std::vector<std::string> MEDFileMesh::removeEmptyGroups()
545 {
546   std::vector<std::string> ret;
547   std::map<std::string, std::vector<std::string> > newGrps;
548   for(std::map<std::string, std::vector<std::string> >::const_iterator it=_groups.begin();it!=_groups.end();it++)
549     {
550       if((*it).second.empty())
551         ret.push_back((*it).first);
552       else
553         newGrps[(*it).first]=(*it).second;
554     }
555   if(!ret.empty())
556     _groups=newGrps;
557   return ret;
558 }
559
560 /*!
561  * Removes a group from \a this mesh.
562  *  \param [in] name - the name of the group to remove.
563  *  \throw If no group with such a \a name exists.
564  */
565 void MEDFileMesh::removeGroup(const std::string& name)
566 {
567   std::string oname(name);
568   std::map<std::string, std::vector<std::string> >::iterator it=_groups.find(oname);
569   std::vector<std::string> grps=getGroupsNames();
570   if(it==_groups.end())
571     {
572       std::ostringstream oss; oss << "No such groupname \"" << name << "\" !\nAvailable groups are :";
573       std::copy(grps.begin(),grps.end(),std::ostream_iterator<std::string>(oss," "));
574       throw INTERP_KERNEL::Exception(oss.str().c_str());
575     }
576   _groups.erase(it);
577 }
578
579 /*!
580  * Removes a family from \a this mesh.
581  *  \param [in] name - the name of the family to remove.
582  *  \throw If no family with such a \a name exists.
583  */
584 void MEDFileMesh::removeFamily(const std::string& name)
585 {
586   std::string oname(name);
587   std::map<std::string, int >::iterator it=_families.find(oname);
588   std::vector<std::string> fams=getFamiliesNames();
589   if(it==_families.end())
590     {
591       std::ostringstream oss; oss << "No such familyname \"" << name << "\" !\nAvailable families are :";
592       std::copy(fams.begin(),fams.end(),std::ostream_iterator<std::string>(oss," "));
593       throw INTERP_KERNEL::Exception(oss.str().c_str());
594     }
595   _families.erase(it);
596   for(std::map<std::string, std::vector<std::string> >::iterator it3=_groups.begin();it3!=_groups.end();it3++)
597     {
598       std::vector<std::string>& v=(*it3).second;
599       std::vector<std::string>::iterator it4=std::find(v.begin(),v.end(),oname);
600       if(it4!=v.end())
601         v.erase(it4);
602     }
603 }
604
605 /*!
606  * Removes all groups in \a this that are orphan. A group is orphan if this group lies on
607  * a set of families, themselves orphan. A family is said orphan if its id appears nowhere in
608  * family field whatever its level. This method also suppresses the orphan families.
609  * 
610  * \return - The list of removed groups names. 
611  *
612  * \sa MEDFileMesh::removeOrphanFamilies.
613  */
614 std::vector<std::string> MEDFileMesh::removeOrphanGroups()
615 {
616   removeOrphanFamilies();
617   return removeEmptyGroups();
618 }
619
620 /*!
621  * Removes all families in \a this that are orphan. A family is said orphan if its id appears nowhere in
622  * 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.
623  * 
624  * \return - The list of removed families names.
625  * \sa MEDFileMesh::removeOrphanGroups.
626  */
627 std::vector<std::string> MEDFileMesh::removeOrphanFamilies()
628 {
629   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> allFamIdsInUse=computeAllFamilyIdsInUse();
630   std::vector<std::string> ret;
631   if(!((DataArrayInt*)allFamIdsInUse))
632     {
633       ret=getFamiliesNames();
634       _families.clear(); _groups.clear();
635       return ret;
636     }
637   std::map<std::string,int> famMap;
638   std::map<std::string, std::vector<std::string> > grps(_groups);
639   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
640     {
641       if(allFamIdsInUse->presenceOfValue((*it).second))
642         famMap[(*it).first]=(*it).second;
643       else
644         {
645           ret.push_back((*it).first);
646           std::vector<std::string> grpsOnEraseFam=getGroupsOnFamily((*it).first);
647           for(std::vector<std::string>::const_iterator it2=grpsOnEraseFam.begin();it2!=grpsOnEraseFam.end();it2++)
648             {
649               std::map<std::string, std::vector<std::string> >::iterator it3=grps.find(*it2);//it3!=grps.empty() thanks to copy
650               std::vector<std::string>& famv=(*it3).second;
651               std::vector<std::string>::iterator it4=std::find(famv.begin(),famv.end(),(*it).first);//it4!=famv.end() thanks to copy
652               famv.erase(it4);
653             }
654         }
655     }
656   if(!ret.empty())
657     { _families=famMap; _groups=grps; }
658   return ret;
659 }
660
661 /*!
662  * Renames a group in \a this mesh.
663  *  \param [in] oldName - a current name of the group to rename.
664  *  \param [in] newName - a new group name.
665  *  \throw If no group named \a oldName exists in \a this mesh.
666  *  \throw If a group named \a newName already exists.
667  */
668 void MEDFileMesh::changeGroupName(const std::string& oldName, const std::string& newName)
669 {
670   std::string oname(oldName);
671   std::map<std::string, std::vector<std::string> >::iterator it=_groups.find(oname);
672   std::vector<std::string> grps=getGroupsNames();
673   if(it==_groups.end())
674     {
675       std::ostringstream oss; oss << "No such groupname \"" << oldName << "\" !\nAvailable groups are :";
676       std::copy(grps.begin(),grps.end(),std::ostream_iterator<std::string>(oss," "));
677       throw INTERP_KERNEL::Exception(oss.str().c_str());
678     }
679   std::string nname(newName);
680   std::map<std::string, std::vector<std::string> >::iterator it2=_groups.find(nname);
681   if(it2!=_groups.end())
682     {
683       std::ostringstream oss; oss << "Such groupname \"" << newName << "\" already exists ! Kill it before !";
684       throw INTERP_KERNEL::Exception(oss.str().c_str());
685     }
686   std::vector<std::string> cpy=(*it).second;
687   _groups.erase(it);
688   _groups[newName]=cpy;
689 }
690
691 /*!
692  * Changes an id of a family in \a this mesh. 
693  * This method calls changeFamilyIdArr().
694  *  \param [in] oldId - a current id of the family.
695  *  \param [in] newId - a new family id.
696  */
697 void MEDFileMesh::changeFamilyId(int oldId, int newId)
698 {
699   changeFamilyIdArr(oldId,newId);
700   std::map<std::string,int> fam2;
701   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
702     {
703       if((*it).second==oldId)
704         fam2[(*it).first]=newId;
705       else
706         fam2[(*it).first]=(*it).second;
707     }
708   _families=fam2;
709 }
710
711 /*!
712  * Renames a family in \a this mesh.
713  *  \param [in] oldName - a current name of the family to rename.
714  *  \param [in] newName - a new family name.
715  *  \throw If no family named \a oldName exists in \a this mesh.
716  *  \throw If a family named \a newName already exists.
717  */
718 void MEDFileMesh::changeFamilyName(const std::string& oldName, const std::string& newName)
719 {
720   std::string oname(oldName);
721   std::map<std::string, int >::iterator it=_families.find(oname);
722   std::vector<std::string> fams=getFamiliesNames();
723   if(it==_families.end())
724     {
725       std::ostringstream oss; oss << "No such familyname \"" << oldName << "\" !\nAvailable families are :";
726       std::copy(fams.begin(),fams.end(),std::ostream_iterator<std::string>(oss," "));
727       throw INTERP_KERNEL::Exception(oss.str().c_str());
728     }
729   std::string nname(newName);
730   std::map<std::string, int >::iterator it2=_families.find(nname);
731   if(it2!=_families.end())
732     {
733       std::ostringstream oss; oss << "Such familyname \"" << newName << " already exists ! Kill it before !";
734       throw INTERP_KERNEL::Exception(oss.str().c_str());
735     }
736   int cpy=(*it).second;
737   _families.erase(it);
738   _families[newName]=cpy;
739   for(std::map<std::string, std::vector<std::string> >::iterator it3=_groups.begin();it3!=_groups.end();it3++)
740     {
741       std::vector<std::string>& v=(*it3).second;
742       std::vector<std::string>::iterator it4=std::find(v.begin(),v.end(),oname);
743       if(it4!=v.end())
744         (*it4)=nname;
745     }
746 }
747
748 /*!
749  * Checks if \a this and another mesh contains the same families.
750  *  \param [in] other - the mesh to compare with \a this one.
751  *  \param [in,out] what - an unused parameter.
752  *  \return bool - \c true if number of families and their ids are the same in the two
753  *          meshes. Families with the id == \c 0 are not considered.
754  */
755 bool MEDFileMesh::areFamsEqual(const MEDFileMesh *other, std::string& what) const
756 {
757   if(_families==other->_families)
758     return true;
759   std::map<std::string,int> fam0;
760   std::map<std::string,int> fam1;
761   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
762     if((*it).second!=0)
763       fam0[(*it).first]=(*it).second;
764   for(std::map<std::string,int>::const_iterator it=other->_families.begin();it!=other->_families.end();it++)
765     if((*it).second!=0)
766       fam1[(*it).first]=(*it).second;
767   return fam0==fam1;
768 }
769
770 /*!
771  * Checks if \a this and another mesh contains the same groups.
772  *  \param [in] other - the mesh to compare with \a this one.
773  *  \param [in,out] what - a string describing a difference of groups of the two meshes
774  *          in case if this method returns \c false.
775  *  \return bool - \c true if number of groups and families constituting them are the
776  *          same in the two meshes.
777  */
778 bool MEDFileMesh::areGrpsEqual(const MEDFileMesh *other, std::string& what) const
779 {
780   if(_groups==other->_groups)
781     return true;
782   bool ret=true;
783   std::size_t sz=_groups.size();
784   if(sz!=other->_groups.size())
785     {
786       what="Groups differ because not same number !\n";
787       ret=false;
788     }
789   if(ret)
790     {
791       std::map<std::string, std::vector<std::string> >::const_iterator it1=_groups.begin();
792       for(std::size_t i=0;i<sz && ret;i++,it1++)
793         {
794           std::map<std::string, std::vector<std::string> >::const_iterator it2=other->_groups.find((*it1).first);
795           if(it2!=other->_groups.end())
796             {
797               std::set<std::string> s1((*it1).second.begin(),(*it1).second.end());
798               std::set<std::string> s2((*it2).second.begin(),(*it2).second.end());
799               ret=(s1==s2);
800             }
801           else
802             {
803               ret=false;
804               what="A group in first mesh exists not in other !\n";
805             }
806         }
807     }
808   if(!ret)
809     {
810       std::ostringstream oss; oss << "Groups description differs :\n";
811       oss << "First group description :\n";
812       for(std::map<std::string, std::vector<std::string> >::const_iterator it=_groups.begin();it!=_groups.end();it++)
813         {
814           oss << " Group \"" << (*it).first << "\" on following families :\n";
815           for(std::vector<std::string>::const_iterator it2=(*it).second.begin();it2!=(*it).second.end();it2++)
816         oss << "    \"" << *it2 << "\n";
817         }
818       oss << "Second group description :\n";
819       for(std::map<std::string, std::vector<std::string> >::const_iterator it=other->_groups.begin();it!=other->_groups.end();it++)
820         {
821           oss << " Group \"" << (*it).first << "\" on following families :\n";
822           for(std::vector<std::string>::const_iterator it2=(*it).second.begin();it2!=(*it).second.end();it2++)
823             oss << "    \"" << *it2 << "\n";
824         }
825       what+=oss.str();
826     }
827   return ret;
828 }
829
830 /*!
831  * Checks if a group with a given name exists in \a this mesh.
832  *  \param [in] groupName - the group name.
833  *  \return bool - \c true the group \a groupName exists in \a this mesh.
834  */
835 bool MEDFileMesh::existsGroup(const std::string& groupName) const
836 {
837   std::string grpName(groupName);
838   return _groups.find(grpName)!=_groups.end();
839 }
840
841 /*!
842  * Checks if a family with a given id exists in \a this mesh.
843  *  \param [in] famId - the family id.
844  *  \return bool - \c true the family with the id \a famId exists in \a this mesh.
845  */
846 bool MEDFileMesh::existsFamily(int famId) const
847 {
848   for(std::map<std::string,int>::const_iterator it2=_families.begin();it2!=_families.end();it2++)
849     if((*it2).second==famId)
850       return true;
851   return false;
852 }
853
854 /*!
855  * Checks if a family with a given name exists in \a this mesh.
856  *  \param [in] familyName - the family name.
857  *  \return bool - \c true the family \a familyName exists in \a this mesh.
858  */
859 bool MEDFileMesh::existsFamily(const std::string& familyName) const
860 {
861   std::string fname(familyName);
862   return _families.find(fname)!=_families.end();
863 }
864
865 /*!
866  * Sets an id of a family.
867  *  \param [in] familyName - the family name.
868  *  \param [in] id - a new id of the family.
869  */
870 void MEDFileMesh::setFamilyId(const std::string& familyName, int id)
871 {
872   std::string fname(familyName);
873   _families[fname]=id;
874 }
875
876 void MEDFileMesh::setFamilyIdUnique(const std::string& familyName, int id)
877 {
878   std::string fname(familyName);
879   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
880     if((*it).second==id)
881       {
882         if((*it).first!=familyName)
883           {
884             std::ostringstream oss; oss << "MEDFileMesh::setFamilyIdUnique : Family id #" << id << " is already belonging to family with name \"" << (*it).first << "\" !";
885             throw INTERP_KERNEL::Exception(oss.str().c_str());
886           }
887       }
888   _families[fname]=id;
889 }
890
891 /*!
892  * Adds a family to \a this mesh.
893  *  \param [in] familyName - a name of the family.
894  *  \param [in] famId - an id of the family.
895  *  \throw If a family with the same name or id already exists in \a this mesh.
896  */
897 void MEDFileMesh::addFamily(const std::string& familyName, int famId)
898 {
899   std::string fname(familyName);
900   std::map<std::string,int>::const_iterator it=_families.find(fname);
901   if(it==_families.end())
902     {
903        for(std::map<std::string,int>::const_iterator it2=_families.begin();it2!=_families.end();it2++)
904          if((*it2).second==famId)
905            {
906              std::ostringstream oss;
907              oss << "MEDFileMesh::addFamily : Family \"" << (*it2).first << "\" already exists with specified id : " << famId << " !";
908              throw INTERP_KERNEL::Exception(oss.str().c_str());
909            }
910        _families[fname]=famId;
911     }
912   else
913     {
914       if((*it).second!=famId)
915         {
916           std::ostringstream oss;
917           oss << "MEDFileMesh::addFamily : Family \"" << fname << "\" already exists but has id set to " << (*it).second << " different from asked famId " << famId << " !";
918           throw INTERP_KERNEL::Exception(oss.str().c_str());
919         }
920     }
921 }
922
923 /*!
924  * Creates a group including all mesh entities of given dimension.
925  * \warning This method does \b not guarantee that the created group includes mesh
926  * entities of only \a meshDimRelToMaxExt dimension in the case if some family id is
927  * present in family fields of different dimensions. To assure this, call
928  * ensureDifferentFamIdsPerLevel() \b before calling this method.
929  *  \param [in] meshDimRelToMaxExt - a relative dimension of mesh entities to include to
930  *          the group.
931  *  \param [in] groupName - a name of the new group.
932  *  \throw If a group named \a groupName already exists.
933  *  \throw If no mesh entities of dimension \a meshDimRelToMaxExt exist in \a this mesh.
934  *  \throw If no family field of dimension \a meshDimRelToMaxExt is present in \a this mesh.
935  */
936 void MEDFileMesh::createGroupOnAll(int meshDimRelToMaxExt, const std::string& groupName)
937 {
938   std::string grpName(groupName);
939   std::vector<int> levs=getNonEmptyLevelsExt();
940   if(std::find(levs.begin(),levs.end(),meshDimRelToMaxExt)==levs.end())
941     {
942       std::ostringstream oss; oss << "MEDFileMesh::createGroupOnAll : The relative ext dimension " << meshDimRelToMaxExt << " is not available !" << std::endl;
943       oss << "Available relative ext levels are : ";
944       std::copy(levs.begin(),levs.end(),std::ostream_iterator<int>(oss," "));
945       throw INTERP_KERNEL::Exception(oss.str().c_str());
946     }
947   if(existsGroup(groupName))
948     {
949       std::ostringstream oss; oss << "MEDFileMesh::createGroupOnAll : The groups \"" << grpName << "\" already exists in this !" << std::endl;
950       oss << "Already existing groups are : ";
951       std::copy(levs.begin(),levs.end(),std::ostream_iterator<int>(oss," "));
952       oss << std::endl << "Please choose an another group name or call removeGroup(\"" << grpName << "\") method !";
953       throw INTERP_KERNEL::Exception(oss.str().c_str());
954     }
955   const DataArrayInt *fieldFamIds=getFamilyFieldAtLevel(meshDimRelToMaxExt);
956   if(fieldFamIds==0)
957     throw INTERP_KERNEL::Exception("MEDFileMesh::createGroupOnAll : Family field arr ids is not defined for this level !");
958   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famIds=fieldFamIds->getDifferentValues();
959   std::vector<std::string> familiesOnWholeGroup;
960   for(const int *it=famIds->begin();it!=famIds->end();it++)
961     {
962       bool tmp;
963       familiesOnWholeGroup.push_back(findOrCreateAndGiveFamilyWithId(*it,tmp));
964     }
965   _groups[grpName]=familiesOnWholeGroup;
966 }
967
968 /*!
969  * Ensures that given family ids do not present in family fields of dimensions different
970  * than given ones. If a family id is present in the family fields of dimensions different
971  * than the given ones, a new family is created and the whole data is updated accordingly.
972  *  \param [in] famIds - a sequence of family ids to check.
973  *  \param [in] vMeshDimRelToMaxExt - a sequence of relative dimensions to which the \a
974  *          famIds should exclusively belong.
975  *  \return bool - \c true if no modification is done in \a this mesh by this method.
976  */
977 bool MEDFileMesh::keepFamIdsOnlyOnLevs(const std::vector<int>& famIds, const std::vector<int>& vMeshDimRelToMaxExt)
978 {
979   std::set<int> levsInput(vMeshDimRelToMaxExt.begin(),vMeshDimRelToMaxExt.end());
980   std::vector<int> levs=getNonEmptyLevelsExt();
981   std::set<int> levs2(levs.begin(),levs.end());
982   std::vector<int> levsToTest;
983   std::set_difference(levs2.begin(),levs2.end(),levsInput.begin(),levsInput.end(),std::back_insert_iterator< std::vector<int> >(levsToTest));
984   std::set<int> famIds2(famIds.begin(),famIds.end());
985   bool ret=true;
986   int maxFamId=1;
987   if(!_families.empty())
988     maxFamId=getMaxFamilyId()+1;
989   std::vector<std::string> allFams=getFamiliesNames();
990   for(std::vector<int>::const_iterator it=levsToTest.begin();it!=levsToTest.end();it++)
991     {
992       const DataArrayInt *fieldFamIds=getFamilyFieldAtLevel(*it);
993       if(fieldFamIds)
994         {
995           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famIds3=fieldFamIds->getDifferentValues();
996           std::vector<int> tmp;
997           std::set_intersection(famIds3->begin(),famIds3->end(),famIds2.begin(),famIds2.end(),std::back_insert_iterator< std::vector<int> >(tmp));
998           for(std::vector<int>::const_iterator it2=tmp.begin();it2!=tmp.end();it2++)
999             {
1000               ret=false;
1001               std::string famName=getFamilyNameGivenId(*it2);
1002               std::ostringstream oss; oss << "Family_" << maxFamId;
1003               std::string zeName=CreateNameNotIn(oss.str(),allFams);
1004               addFamilyOnAllGroupsHaving(famName,zeName);
1005               _families[zeName]=maxFamId;
1006               (const_cast<DataArrayInt *>(fieldFamIds))->changeValue(*it2,maxFamId);
1007               maxFamId++;
1008             }
1009         }
1010     }
1011   return ret;
1012 }
1013
1014 /*!
1015  * Adds a family to a given group in \a this mesh. If the group with a given name does
1016  * not exist, it is created.
1017  *  \param [in] grpName - the name of the group to add the family in.
1018  *  \param [in] famName - the name of the family to add to the group named \a grpName.
1019  *  \throw If \a grpName or \a famName is an empty string.
1020  *  \throw If no family named \a famName is present in \a this mesh.
1021  */
1022 void MEDFileMesh::addFamilyOnGrp(const std::string& grpName, const std::string& famName)
1023 {
1024   std::string grpn(grpName);
1025   std::string famn(famName);
1026   if(grpn.empty() || famn.empty())
1027     throw INTERP_KERNEL::Exception("MEDFileMesh::addFamilyOnGrp : input strings must be non null !");
1028   std::vector<std::string> fams=getFamiliesNames();
1029   if(std::find(fams.begin(),fams.end(),famn)==fams.end())
1030     {
1031       std::ostringstream oss; oss << "MEDFileMesh::addFamilyOnGrp : Family \"" << famn << "\" does not exist !" << std::endl;
1032       oss << "Create this family or choose an existing one ! Existing fams are : ";
1033       std::copy(fams.begin(),fams.end(),std::ostream_iterator<std::string>(oss," ")); oss << ".";
1034       throw INTERP_KERNEL::Exception(oss.str().c_str());
1035     }
1036   std::map<std::string, std::vector<std::string> >::iterator it=_groups.find(grpn);
1037   if(it==_groups.end())
1038     {
1039       _groups[grpn].push_back(famn);
1040     }
1041   else
1042     {
1043       std::vector<std::string>::iterator it2=std::find((*it).second.begin(),(*it).second.end(),famn);
1044       if(it2==(*it).second.end())
1045         (*it).second.push_back(famn);
1046     }
1047 }
1048
1049 /*!
1050  * This method adds to all groups lying on family with name 'famName' the other family name 'otherFamName'.
1051  * This method is quite underground because it can lead to unconsistency because family 'otherFamName' is \b not added into _families.
1052  * This method is used by MEDFileMesh::keepFamIdsOnlyOnLevs method.
1053  */
1054 void MEDFileMesh::addFamilyOnAllGroupsHaving(const std::string& famName, const std::string& otherFamName)
1055 {
1056   std::string famNameCpp(famName);
1057   std::string otherCpp(otherFamName);
1058   for(std::map<std::string, std::vector<std::string> >::iterator it=_groups.begin();it!=_groups.end();it++)
1059     {
1060       std::vector<std::string>& v=(*it).second;
1061       if(std::find(v.begin(),v.end(),famNameCpp)!=v.end())
1062         {
1063           v.push_back(otherCpp);
1064         }
1065     }
1066 }
1067
1068 void MEDFileMesh::changeAllGroupsContainingFamily(const std::string& familyNameToChange, const std::vector<std::string>& newFamiliesNames)
1069 {
1070   ChangeAllGroupsContainingFamily(_groups,familyNameToChange,newFamiliesNames);
1071 }
1072
1073 void MEDFileMesh::ChangeAllGroupsContainingFamily(std::map<std::string, std::vector<std::string> >& groups, const std::string& familyNameToChange, const std::vector<std::string>& newFamiliesNames)
1074 {
1075   std::string fam(familyNameToChange);
1076   for(std::map<std::string, std::vector<std::string> >::iterator it=groups.begin();it!=groups.end();it++)
1077     {
1078       std::vector<std::string>& fams((*it).second);
1079       std::vector<std::string>::iterator it2=std::find(fams.begin(),fams.end(),fam);
1080       if(it2!=fams.end())
1081         {
1082           fams.erase(it2);
1083           fams.insert(fams.end(),newFamiliesNames.begin(),newFamiliesNames.end());
1084         }
1085     }
1086 }
1087
1088 /*!
1089  * Returns a name of the family having a given id or, if no such a family exists, creates
1090  * a new uniquely named family and returns its name.
1091  *  \param [in] id - the id of the family whose name is required.
1092  *  \param [out] created - returns \c true if the new family has been created, \c false, else.
1093  *  \return std::string - the name of the existing or the created family.
1094  *  \throw If it is not possible to create a unique family name.
1095  */
1096 std::string MEDFileMesh::findOrCreateAndGiveFamilyWithId(int id, bool& created)
1097 {
1098   return FindOrCreateAndGiveFamilyWithId(_families,id,created);
1099 }
1100
1101 /*!
1102  * If it exists a family whose family id is equal to 'id' this method behaves as MEDFileMesh::getFamilyNameGivenId.
1103  * In this case, 'this' internal states remains unchanged and 'created' out parameter will be set to false.
1104  * If there is no family whose family id is equal to 'id' a family is created with a name different from those
1105  * already existing. In this case 'created' will be returned with a value set to true, and internal state
1106  * will be modified.
1107  * This method will throws an exception if it is not possible to create a unique family name.
1108  */
1109 std::string MEDFileMesh::FindOrCreateAndGiveFamilyWithId(std::map<std::string,int>& families, int id, bool& created)
1110 {
1111   std::vector<std::string> famAlreadyExisting(families.size());
1112   int ii=0;
1113   for(std::map<std::string,int>::const_iterator it=families.begin();it!=families.end();it++,ii++)
1114     {
1115       if((*it).second!=id)
1116         {
1117           famAlreadyExisting[ii]=(*it).first;
1118         }
1119       else
1120         {
1121           created=false;
1122           return (*it).first;
1123         }
1124     }
1125   created=true;
1126   std::ostringstream oss; oss << "Family_" << id;
1127   std::string ret=CreateNameNotIn(oss.str(),famAlreadyExisting);
1128   families[ret]=id;
1129   return ret;
1130 }
1131
1132 /*!
1133  * Sets names and ids of all families in \a this mesh.
1134  *  \param [in] info - a map of a family name to a family id.
1135  */
1136 void MEDFileMesh::setFamilyInfo(const std::map<std::string,int>& info)
1137 {
1138   _families=info;
1139 }
1140
1141 /*!
1142  * Sets names of all groups and families constituting them in \a this mesh.
1143  *  \param [in] info - a map of a group name to a vector of names of families
1144  *          constituting the group.
1145  */
1146 void MEDFileMesh::setGroupInfo(const std::map<std::string, std::vector<std::string> >&info)
1147 {
1148   _groups=info;
1149 }
1150
1151 /*!
1152  * Returns an id of the family having a given name.
1153  *  \param [in] name - the name of the family of interest.
1154  *  \return int - the id of the family of interest.
1155  *  \throw If no family with such a \a name exists.
1156  */
1157 int MEDFileMesh::getFamilyId(const std::string& name) const
1158 {
1159   std::string oname(name);
1160   std::map<std::string, int>::const_iterator it=_families.find(oname);
1161   std::vector<std::string> fams=getFamiliesNames();
1162   if(it==_families.end())
1163     {
1164       std::ostringstream oss; oss << "No such familyname \"" << name << "\" !\nAvailable families are :";
1165       std::copy(fams.begin(),fams.end(),std::ostream_iterator<std::string>(oss," "));
1166       throw INTERP_KERNEL::Exception(oss.str().c_str());
1167     }
1168   return (*it).second;
1169 }
1170
1171 /*!
1172  * Returns ids of the families having given names.
1173  *  \param [in] fams - a sequence of the names of families of interest.
1174  *  \return std::vector<int> - a sequence of the ids of families of interest.
1175  *  \throw If \a fams contains a name of an inexistent family.
1176  */
1177 std::vector<int> MEDFileMesh::getFamiliesIds(const std::vector<std::string>& fams) const
1178 {
1179   std::vector<int> ret(fams.size());
1180   int i=0;
1181   for(std::vector<std::string>::const_iterator it=fams.begin();it!=fams.end();it++,i++)
1182     {
1183       std::map<std::string, int>::const_iterator it2=_families.find(*it);
1184       if(it2==_families.end())
1185         {
1186           std::vector<std::string> fams2=getFamiliesNames();
1187           std::ostringstream oss; oss << "No such familyname \"" << *it << "\" in input list !\nAvailable families are :";
1188           std::copy(fams2.begin(),fams2.end(),std::ostream_iterator<std::string>(oss," "));
1189           throw INTERP_KERNEL::Exception(oss.str().c_str());
1190         }
1191       ret[i]=(*it2).second;
1192     }
1193   return ret;
1194 }
1195
1196 /*!
1197  * Returns a maximal abs(id) of families in \a this mesh.
1198  *  \return int - the maximal norm of family id.
1199  *  \throw If there are no families in \a this mesh.
1200  */
1201 int MEDFileMesh::getMaxAbsFamilyId() const
1202 {
1203   if(_families.empty())
1204     throw INTERP_KERNEL::Exception("MEDFileMesh::getMaxFamilyId : no families set !");
1205   int ret=-std::numeric_limits<int>::max();
1206   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
1207     {
1208       ret=std::max(std::abs((*it).second),ret);
1209     }
1210   return ret;
1211 }
1212
1213 /*!
1214  * Returns a maximal id of families in \a this mesh.
1215  *  \return int - the maximal family id.
1216  *  \throw If there are no families in \a this mesh.
1217  */
1218 int MEDFileMesh::getMaxFamilyId() const
1219 {
1220   if(_families.empty())
1221     throw INTERP_KERNEL::Exception("MEDFileMesh::getMaxFamilyId : no families set !");
1222   int ret=-std::numeric_limits<int>::max();
1223   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
1224     {
1225       ret=std::max((*it).second,ret);
1226     }
1227   return ret;
1228 }
1229
1230 /*!
1231  * Returns a minimal id of families in \a this mesh.
1232  *  \return int - the minimal family id.
1233  *  \throw If there are no families in \a this mesh.
1234  */
1235 int MEDFileMesh::getMinFamilyId() const
1236 {
1237   if(_families.empty())
1238     throw INTERP_KERNEL::Exception("MEDFileMesh::getMinFamilyId : no families set !");
1239   int ret=std::numeric_limits<int>::max();
1240   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
1241     {
1242       ret=std::min((*it).second,ret);
1243     }
1244   return ret;
1245 }
1246
1247 /*!
1248  * Returns a maximal id of families in \a this mesh. Not only named families are
1249  * considered but all family fields as well.
1250  *  \return int - the maximal family id.
1251  */
1252 int MEDFileMesh::getTheMaxAbsFamilyId() const
1253 {
1254   int m1=-std::numeric_limits<int>::max();
1255   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
1256     m1=std::max(std::abs((*it).second),m1);
1257   int m2=getMaxAbsFamilyIdInArrays();
1258   return std::max(m1,m2);
1259 }
1260
1261 /*!
1262  * Returns a maximal id of families in \a this mesh. Not only named families are
1263  * considered but all family fields as well.
1264  *  \return int - the maximal family id.
1265  */
1266 int MEDFileMesh::getTheMaxFamilyId() const
1267 {
1268   int m1=-std::numeric_limits<int>::max();
1269   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
1270     m1=std::max((*it).second,m1);
1271   int m2=getMaxFamilyIdInArrays();
1272   return std::max(m1,m2);
1273 }
1274
1275 /*!
1276  * Returns a minimal id of families in \a this mesh. Not only named families are
1277  * considered but all family fields as well.
1278  *  \return int - the minimal family id.
1279  */
1280 int MEDFileMesh::getTheMinFamilyId() const
1281 {
1282   int m1=std::numeric_limits<int>::max();
1283   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
1284     m1=std::min((*it).second,m1);
1285   int m2=getMinFamilyIdInArrays();
1286   return std::min(m1,m2);
1287 }
1288
1289 /*!
1290  * This method only considers the maps. The contain of family array is ignored here.
1291  * 
1292  * \sa MEDFileMesh::computeAllFamilyIdsInUse
1293  */
1294 DataArrayInt *MEDFileMesh::getAllFamiliesIdsReferenced() const
1295 {
1296   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1297   std::set<int> v;
1298   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
1299     v.insert((*it).second);
1300   ret->alloc((int)v.size(),1);
1301   std::copy(v.begin(),v.end(),ret->getPointer());
1302   return ret.retn();
1303 }
1304
1305 /*!
1306  * This method does not consider map of family name, family id. Only family field array on different levels is considered.
1307  * 
1308  * \sa MEDFileMesh::getAllFamiliesIdsReferenced
1309  */
1310 DataArrayInt *MEDFileMesh::computeAllFamilyIdsInUse() const
1311 {
1312   std::vector<int> famLevs=getFamArrNonEmptyLevelsExt();
1313   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret;
1314   for(std::vector<int>::const_iterator it=famLevs.begin();it!=famLevs.end();it++)
1315     {
1316       const DataArrayInt *arr=getFamilyFieldAtLevel(*it);//arr not null due to spec of getFamArrNonEmptyLevelsExt
1317       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dv=arr->getDifferentValues();
1318       if((DataArrayInt *) ret)
1319         ret=dv->buildUnion(ret);
1320       else
1321         ret=dv;
1322     }
1323   return ret.retn();
1324 }
1325
1326 /*!
1327  * true is returned if no modification has been needed. false if family
1328  * renumbering has been needed.       
1329  */
1330 bool MEDFileMesh::ensureDifferentFamIdsPerLevel()
1331 {
1332   std::vector<int> levs=getNonEmptyLevelsExt();
1333   std::set<int> allFamIds;
1334   int maxId=getMaxFamilyId()+1;
1335   std::map<int,std::vector<int> > famIdsToRenum;
1336   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
1337     {
1338       const DataArrayInt *fam=getFamilyFieldAtLevel(*it);
1339       if(fam)
1340         {
1341           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=fam->getDifferentValues();
1342           std::set<int> r2;
1343           std::set_intersection(tmp->begin(),tmp->end(),allFamIds.begin(),allFamIds.end(),std::inserter(r2,r2.end()));
1344           if(!r2.empty())
1345             famIdsToRenum[*it].insert(famIdsToRenum[*it].end(),r2.begin(),r2.end());
1346           std::set<int> r3;
1347           std::set_union(tmp->begin(),tmp->end(),allFamIds.begin(),allFamIds.end(),std::inserter(r3,r3.end()));
1348         }
1349     }
1350   if(famIdsToRenum.empty())
1351     return true;
1352   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> allIds=getAllFamiliesIdsReferenced();
1353   for(std::map<int,std::vector<int> >::const_iterator it2=famIdsToRenum.begin();it2!=famIdsToRenum.end();it2++)
1354     {
1355       DataArrayInt *fam=const_cast<DataArrayInt *>(getFamilyFieldAtLevel((*it2).first));
1356       int *famIdsToChange=fam->getPointer();
1357       std::map<int,int> ren;
1358       for(std::vector<int>::const_iterator it3=(*it2).second.begin();it3!=(*it2).second.end();it3++,maxId++)
1359         {
1360           if(allIds->presenceOfValue(*it3))
1361             {
1362               std::string famName=getFamilyNameGivenId(*it3);
1363               std::vector<std::string> grps=getGroupsOnFamily(famName);
1364               ren[*it3]=maxId;
1365               bool dummy;
1366               std::string newFam=findOrCreateAndGiveFamilyWithId(maxId,dummy);
1367               for(std::vector<std::string>::const_iterator it4=grps.begin();it4!=grps.end();it4++)
1368                 addFamilyOnGrp((*it4),newFam);
1369             }
1370         }
1371       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=fam->getIdsEqualList(&(*it2).second[0],&(*it2).second[0]+(*it2).second.size());
1372       for(const int *id=ids->begin();id!=ids->end();id++)
1373         famIdsToChange[*id]=ren[famIdsToChange[*id]];
1374     }
1375   return false;
1376 }
1377
1378 /*!
1379  * This method normalizes fam id with the policy explained underneath. This policy is close to those implemented in SMESH.
1380  * Level #0 famids > 0, Level #-1 famids < 0, Level #-2 famids=0, Level #1 famids=0
1381  * This policy is those used by SMESH and Trio and that is the opposite of those in MED file.
1382  * This method will throw an exception if a same family id is detected in different level.
1383  * \warning This policy is the opposite of those in MED file documentation ...
1384  */
1385 void MEDFileMesh::normalizeFamIdsTrio()
1386 {
1387   ensureDifferentFamIdsPerLevel();
1388   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> allIds=getAllFamiliesIdsReferenced();
1389   std::vector<int> levs=getNonEmptyLevelsExt();
1390   std::set<int> levsS(levs.begin(),levs.end());
1391   std::set<std::string> famsFetched;
1392   std::map<std::string,int> families;
1393   if(std::find(levs.begin(),levs.end(),0)!=levs.end())
1394     {
1395       levsS.erase(0);
1396       const DataArrayInt *fam=getFamilyFieldAtLevel(0);
1397       if(fam)
1398         {
1399           int refId=1;
1400           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=fam->getDifferentValues();
1401           std::map<int,int> ren;
1402           for(const int *it=tmp->begin();it!=tmp->end();it++,refId++)
1403             ren[*it]=refId;
1404           int nbOfTuples=fam->getNumberOfTuples();
1405           int *start=const_cast<DataArrayInt *>(fam)->getPointer();
1406           for(int *w=start;w!=start+nbOfTuples;w++)
1407             *w=ren[*w];
1408           for(const int *it=tmp->begin();it!=tmp->end();it++)
1409             {
1410               if(allIds->presenceOfValue(*it))
1411                 {
1412                   std::string famName=getFamilyNameGivenId(*it);
1413                   families[famName]=ren[*it];
1414                   famsFetched.insert(famName);
1415                 }
1416             }
1417         }
1418     }
1419   if(std::find(levs.begin(),levs.end(),-1)!=levs.end())
1420     {
1421       levsS.erase(-1);
1422       const DataArrayInt *fam=getFamilyFieldAtLevel(-1);
1423       if(fam)
1424         {
1425           int refId=-1;
1426           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=fam->getDifferentValues();
1427           std::map<int,int> ren;
1428           for(const int *it=tmp->begin();it!=tmp->end();it++,refId--)
1429             ren[*it]=refId;
1430           int nbOfTuples=fam->getNumberOfTuples();
1431           int *start=const_cast<DataArrayInt *>(fam)->getPointer();
1432           for(int *w=start;w!=start+nbOfTuples;w++)
1433             *w=ren[*w];
1434           for(const int *it=tmp->begin();it!=tmp->end();it++)
1435             {
1436               if(allIds->presenceOfValue(*it))
1437                 {
1438                   std::string famName=getFamilyNameGivenId(*it);
1439                   families[famName]=ren[*it];
1440                   famsFetched.insert(famName);
1441                 }
1442             }
1443         }
1444     }
1445   for(std::set<int>::const_iterator it2=levsS.begin();it2!=levsS.end();it2++)
1446     {
1447       DataArrayInt *fam=const_cast<DataArrayInt*>(getFamilyFieldAtLevel(*it2));
1448       if(fam)
1449         {
1450           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=fam->getDifferentValues();
1451           fam->fillWithZero();
1452           for(const int *it3=tmp->begin();it3!=tmp->end();it3++)
1453             if(allIds->presenceOfValue(*it3))
1454               {
1455                 std::string famName=getFamilyNameGivenId(*it3);
1456                 families[famName]=0;
1457                 famsFetched.insert(famName);
1458               }
1459         }
1460     }
1461   //
1462   std::vector<std::string> allFams=getFamiliesNames();
1463   std::set<std::string> allFamsS(allFams.begin(),allFams.end());
1464   std::set<std::string> unFetchedIds;
1465   std::set_difference(allFamsS.begin(),allFamsS.end(),famsFetched.begin(),famsFetched.end(),std::inserter(unFetchedIds,unFetchedIds.end()));
1466   for(std::set<std::string>::const_iterator it4=unFetchedIds.begin();it4!=unFetchedIds.end();it4++)
1467     families[*it4]=_families[*it4];
1468   _families=families;
1469 }
1470
1471 /*!
1472  * This method normalizes fam id with the following policy.
1473  * Level #0 famids < 0, Level #-1 famids < 0 and for Level #1 famids >= 0
1474  * This policy is those defined in the MED file format but is the opposite of those implemented in SMESH and Trio.
1475  * This method will throw an exception if a same family id is detected in different level.
1476  */
1477 void MEDFileMesh::normalizeFamIdsMEDFile()
1478 {
1479   ensureDifferentFamIdsPerLevel();
1480   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> allIds=getAllFamiliesIdsReferenced();
1481   std::vector<int> levs=getNonEmptyLevelsExt();
1482   std::set<int> levsS(levs.begin(),levs.end());
1483   std::set<std::string> famsFetched;
1484   std::map<std::string,int> families;
1485   int refId=1;
1486   if(std::find(levs.begin(),levs.end(),1)!=levs.end())
1487     {
1488       levsS.erase(1);
1489       const DataArrayInt *fam=getFamilyFieldAtLevel(1);
1490       if(fam)
1491         {
1492           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=fam->getDifferentValues();
1493           std::map<int,int> ren;
1494           for(const int *it=tmp->begin();it!=tmp->end();it++,refId++)
1495             ren[*it]=refId;
1496           int nbOfTuples=fam->getNumberOfTuples();
1497           int *start=const_cast<DataArrayInt *>(fam)->getPointer();
1498           for(int *w=start;w!=start+nbOfTuples;w++)
1499             *w=ren[*w];
1500           for(const int *it=tmp->begin();it!=tmp->end();it++)
1501             {
1502               if(allIds->presenceOfValue(*it))
1503                 {
1504                   std::string famName=getFamilyNameGivenId(*it);
1505                   families[famName]=ren[*it];
1506                   famsFetched.insert(famName);
1507                 }
1508             }
1509         }
1510     }
1511   refId=-1;
1512   for(std::set<int>::const_reverse_iterator it2=levsS.rbegin();it2!=levsS.rend();it2++)
1513     {
1514       const DataArrayInt *fam=getFamilyFieldAtLevel(*it2);
1515       if(fam)
1516         {
1517           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=fam->getDifferentValues();
1518           std::map<int,int> ren;
1519           for(const int *it=tmp->begin();it!=tmp->end();it++,refId--)
1520             ren[*it]=refId;
1521           int nbOfTuples=fam->getNumberOfTuples();
1522           int *start=const_cast<DataArrayInt *>(fam)->getPointer();
1523           for(int *w=start;w!=start+nbOfTuples;w++)
1524             *w=ren[*w];
1525           for(const int *it=tmp->begin();it!=tmp->end();it++)
1526             {
1527               if(allIds->presenceOfValue(*it))
1528                 {
1529                   std::string famName=getFamilyNameGivenId(*it);
1530                   families[famName]=ren[*it];
1531                   famsFetched.insert(famName);
1532                 }
1533             }
1534         }
1535     }
1536   //
1537   std::vector<std::string> allFams=getFamiliesNames();
1538   std::set<std::string> allFamsS(allFams.begin(),allFams.end());
1539   std::set<std::string> unFetchedIds;
1540   std::set_difference(allFamsS.begin(),allFamsS.end(),famsFetched.begin(),famsFetched.end(),std::inserter(unFetchedIds,unFetchedIds.end()));
1541   for(std::set<std::string>::const_iterator it4=unFetchedIds.begin();it4!=unFetchedIds.end();it4++)
1542     families[*it4]=_families[*it4];
1543   _families=families;
1544 }
1545
1546 /*!
1547  * Returns a name of the family by its id. If there are several families having the given
1548  * id, the name first in lexical order is returned.
1549  *  \param [in] id - the id of the family whose name is required.
1550  *  \return std::string - the name of the found family.
1551  *  \throw If no family with the given \a id exists.
1552  */
1553 std::string MEDFileMesh::getFamilyNameGivenId(int id) const
1554 {
1555   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
1556     if((*it).second==id)
1557       return (*it).first;
1558   std::ostringstream oss; oss << "MEDFileUMesh::getFamilyNameGivenId : no such family id : " << id;
1559   throw INTERP_KERNEL::Exception(oss.str().c_str());
1560 }
1561
1562 /*!
1563  * Returns a string describing \a this mesh. This description includes the mesh name and
1564  * the mesh description string.
1565  *  \return std::string - the mesh information string.
1566  */
1567 std::string MEDFileMesh::simpleRepr() const
1568 {
1569   std::ostringstream oss;
1570   oss << "(*************************************)\n(* GENERAL INFORMATION ON THE MESH : *)\n(*************************************)\n";
1571   oss << "- Name of the mesh : <<" << getName() << ">>\n";
1572   oss << "- Description associated to the mesh : " << getDescription() << std::endl;
1573   return oss.str();
1574 }
1575
1576 /*!
1577  * Returns ids of mesh entities contained in a given group of a given dimension.
1578  *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
1579  *          are required.
1580  *  \param [in] grp - the name of the group of interest.
1581  *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
1582  *          returned instead of ids. 
1583  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
1584  *          numbers, if available and required, of mesh entities of the group. The caller
1585  *          is to delete this array using decrRef() as it is no more needed. 
1586  *  \throw If the name of a nonexistent group is specified.
1587  *  \throw If the family field is missing for \a meshDimRelToMaxExt.
1588  */
1589 DataArrayInt *MEDFileMesh::getGroupArr(int meshDimRelToMaxExt, const std::string& grp, bool renum) const
1590 {
1591   std::vector<std::string> tmp(1);
1592   tmp[0]=grp;
1593   DataArrayInt *ret=getGroupsArr(meshDimRelToMaxExt,tmp,renum);
1594   ret->setName(grp);
1595   return ret;
1596 }
1597
1598 /*!
1599  * Returns ids of mesh entities contained in given groups of a given dimension.
1600  *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
1601  *          are required.
1602  *  \param [in] grps - the names of the groups of interest.
1603  *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
1604  *          returned instead of ids.
1605  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
1606  *          numbers, if available and required, of mesh entities of the groups. The caller
1607  *          is to delete this array using decrRef() as it is no more needed. 
1608  *  \throw If the name of a nonexistent group is present in \a grps.
1609  *  \throw If the family field is missing for \a meshDimRelToMaxExt.
1610  */
1611 DataArrayInt *MEDFileMesh::getGroupsArr(int meshDimRelToMaxExt, const std::vector<std::string>& grps, bool renum) const
1612 {
1613   std::vector<std::string> fams2=getFamiliesOnGroups(grps);
1614   return getFamiliesArr(meshDimRelToMaxExt,fams2,renum);
1615 }
1616
1617 /*!
1618  * Returns ids of mesh entities contained in a given family of a given dimension.
1619  *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
1620  *          are required.
1621  *  \param [in] fam - the name of the family of interest.
1622  *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
1623  *          returned instead of ids. 
1624  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
1625  *          numbers, if available and required, of mesh entities of the family. The caller
1626  *          is to delete this array using decrRef() as it is no more needed. 
1627  *  \throw If the family field is missing for \a meshDimRelToMaxExt.
1628  */
1629 DataArrayInt *MEDFileMesh::getFamilyArr(int meshDimRelToMaxExt, const std::string& fam, bool renum) const
1630 {
1631   std::vector<std::string> tmp(1);
1632   tmp[0]=fam;
1633   DataArrayInt *ret=getFamiliesArr(meshDimRelToMaxExt,tmp,renum);
1634   ret->setName(fam);
1635   return ret;
1636 }
1637
1638 /*!
1639  * Returns ids of nodes contained in a given group.
1640  *  \param [in] grp - the name of the group of interest.
1641  *  \param [in] renum - if \c true, the optional numbers of nodes, if available, are
1642  *          returned instead of ids. 
1643  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
1644  *          numbers, if available and required, of nodes of the group. The caller
1645  *          is to delete this array using decrRef() as it is no more needed. 
1646  *  \throw If the name of a nonexistent group is specified.
1647  *  \throw If the family field is missing for nodes.
1648  */
1649 DataArrayInt *MEDFileMesh::getNodeGroupArr(const std::string& grp, bool renum) const
1650 {
1651   std::vector<std::string> tmp(1);
1652   tmp[0]=grp;
1653   DataArrayInt *ret=getNodeGroupsArr(tmp,renum);
1654   ret->setName(grp);
1655   return ret;
1656 }
1657
1658 /*!
1659  * Returns ids of nodes contained in given groups.
1660  *  \param [in] grps - the names of the groups of interest.
1661  *  \param [in] renum - if \c true, the optional numbers of nodes, if available, are
1662  *          returned instead of ids. 
1663  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
1664  *          numbers, if available and required, of nodes of the groups. The caller
1665  *          is to delete this array using decrRef() as it is no more needed. 
1666  *  \throw If the name of a nonexistent group is present in \a grps.
1667  *  \throw If the family field is missing for nodes.
1668  */
1669 DataArrayInt *MEDFileMesh::getNodeGroupsArr(const std::vector<std::string>& grps, bool renum) const
1670 {
1671   return getGroupsArr(1,grps,renum);
1672 }
1673
1674 /*!
1675  * Returns ids of nodes contained in a given group.
1676  *  \param [in] grp - the name of the group of interest.
1677  *  \param [in] renum - if \c true, the optional numbers of nodes, if available, are
1678  *          returned instead of ids. 
1679  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
1680  *          numbers, if available and required, of nodes of the group. The caller
1681  *          is to delete this array using decrRef() as it is no more needed. 
1682  *  \throw If the name of a nonexistent group is specified.
1683  *  \throw If the family field is missing for nodes.
1684  */
1685 DataArrayInt *MEDFileMesh::getNodeFamilyArr(const std::string& fam, bool renum) const
1686 {
1687   std::vector<std::string> tmp(1);
1688   tmp[0]=fam;
1689   DataArrayInt *ret=getNodeFamiliesArr(tmp,renum);
1690   ret->setName(fam);
1691   return ret;
1692 }
1693
1694 /*!
1695  * Returns ids of nodes contained in given families.
1696  *  \param [in] fams - the names of the families of interest.
1697  *  \param [in] renum - if \c true, the optional numbers of nodes, if available, are
1698  *          returned instead of ids. 
1699  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
1700  *          numbers, if available and required, of nodes of the families. The caller
1701  *          is to delete this array using decrRef() as it is no more needed. 
1702  *  \throw If the family field is missing for nodes.
1703  */
1704 DataArrayInt *MEDFileMesh::getNodeFamiliesArr(const std::vector<std::string>& fams, bool renum) const
1705 {
1706   return getFamiliesArr(1,fams,renum);
1707 }
1708
1709 /*!
1710  * Adds groups of given dimension and creates corresponding families and family fields
1711  * given ids of mesh entities of each group.
1712  *  \param [in] meshDimRelToMaxExt - the relative mesh dimension of given mesh entities.
1713  *  \param [in] grps - a sequence of arrays of ids each describing a group.
1714  *  \param [in] renum - \c true means that \a grps contains not ids but optional numbers
1715  *          of mesh entities.
1716  *  \throw If names of some groups in \a grps are equal.
1717  *  \throw If \a grps includes a group with an empty name.
1718  *  \throw If \a grps includes invalid ids (or numbers if \a renum == \c true ).
1719  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
1720  */
1721 void MEDFileMesh::setGroupsAtLevel(int meshDimRelToMaxExt, const std::vector<const DataArrayInt *>& grps, bool renum)
1722 {
1723   if(grps.empty())
1724     return ;
1725   std::set<std::string> grpsName;
1726   std::vector<std::string> grpsName2(grps.size());
1727   int i=0;
1728
1729   for(std::vector<const DataArrayInt *>::const_iterator it=grps.begin();it!=grps.end();it++,i++)
1730     {
1731       grpsName.insert((*it)->getName());
1732       grpsName2[i]=(*it)->getName();
1733     }
1734   if(grpsName.size()!=grps.size())
1735     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsAtLevel : groups name must be different each other !");
1736   if(grpsName.find(std::string(""))!=grpsName.end())
1737     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsAtLevel : groups name must be different empty string !");
1738   int sz=getSizeAtLevel(meshDimRelToMaxExt);
1739   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fam;
1740   std::vector< std::vector<int> > fidsOfGroups;
1741   if(!renum)
1742     {
1743       fam=DataArrayInt::MakePartition(grps,sz,fidsOfGroups);
1744     }
1745   else
1746     {
1747       std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > grps2(grps.size());
1748       for(unsigned int ii=0;ii<grps.size();ii++)
1749         {
1750           grps2[ii]=MEDFileUMeshSplitL1::Renumber(getRevNumberFieldAtLevel(meshDimRelToMaxExt),grps[ii]);
1751           grps2[ii]->setName(grps[ii]->getName());
1752         }
1753       std::vector<const DataArrayInt *> grps3(grps2.begin(),grps2.end());
1754       fam=DataArrayInt::MakePartition(grps3,sz,fidsOfGroups);
1755     }
1756   int offset=1;
1757   if(!_families.empty())
1758     offset=getMaxAbsFamilyId()+1;
1759   TranslateFamilyIds(meshDimRelToMaxExt==1?offset:-offset,fam,fidsOfGroups);
1760   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=fam->getDifferentValues();
1761   appendFamilyEntries(ids,fidsOfGroups,grpsName2);
1762   setFamilyFieldArr(meshDimRelToMaxExt,fam);
1763 }
1764
1765 /*!
1766  * This method append into '_families' attribute the families whose ids are in 'famIds'. Warning 'famIds' are expected to be ids
1767  * not in '_families'. Groups information are given in parameters in order to give to families representative names.
1768  * For the moment, the two last input parameters are not taken into account.
1769  */
1770 void MEDFileMesh::appendFamilyEntries(const DataArrayInt *famIds, const std::vector< std::vector<int> >& fidsOfGrps, const std::vector<std::string>& grpNames)
1771 {
1772   std::map<int,std::string> famInv;
1773   for(const int *it=famIds->begin();it!=famIds->end();it++)
1774     {
1775       std::ostringstream oss;
1776       oss << "Family_" << (*it);
1777       _families[oss.str()]=(*it);
1778       famInv[*it]=oss.str();
1779     }
1780   int i=0;
1781   for(std::vector< std::vector<int> >::const_iterator it1=fidsOfGrps.begin();it1!=fidsOfGrps.end();it1++,i++)
1782     {
1783       for(std::vector<int>::const_iterator it2=(*it1).begin();it2!=(*it1).end();it2++)
1784         {
1785           _groups[grpNames[i]].push_back(famInv[*it2]);
1786         }
1787     }
1788 }
1789
1790 std::vector<int> MEDFileMesh::getDistributionOfTypes(int meshDimRelToMax) const
1791 {
1792   MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> mLev(getGenMeshAtLevel(meshDimRelToMax));
1793   return mLev->getDistributionOfTypes();
1794 }
1795
1796 void MEDFileMesh::TranslateFamilyIds(int offset, DataArrayInt *famArr, std::vector< std::vector<int> >& famIdsPerGrp)
1797 {
1798   famArr->applyLin(offset>0?1:-1,offset,0);
1799   for(std::vector< std::vector<int> >::iterator it1=famIdsPerGrp.begin();it1!=famIdsPerGrp.end();it1++)
1800     {
1801       if(offset<0)
1802         std::transform((*it1).begin(),(*it1).end(),(*it1).begin(),std::negate<int>());
1803       std::transform((*it1).begin(),(*it1).end(),(*it1).begin(),std::bind2nd(std::plus<int>(),offset));
1804     }
1805 }
1806
1807 /*!
1808  * Warning no check is done on 'nameTry' in parameter. It should be non empty.
1809  * This method returns a name close to 'nameTry' so that it is not already into 'namesToAvoid'.
1810  * If this method fails to find such a name it will throw an exception.
1811  */
1812 std::string MEDFileMesh::CreateNameNotIn(const std::string& nameTry, const std::vector<std::string>& namesToAvoid)
1813 {
1814   //attempt #0
1815   if(std::find(namesToAvoid.begin(),namesToAvoid.end(),nameTry)==namesToAvoid.end())
1816     return nameTry;
1817   //attempt #1
1818   std::size_t len=nameTry.length();
1819   for(std::size_t ii=1;ii<len;ii++)
1820     {
1821       std::string tmp=nameTry.substr(ii,len-ii);
1822       if(std::find(namesToAvoid.begin(),namesToAvoid.end(),tmp)==namesToAvoid.end())
1823         return tmp;
1824     }
1825   //attempt #2
1826   if(len>=1)
1827     {
1828       for(std::size_t i=1;i<30;i++)
1829         {
1830           std::string tmp1(nameTry.at(0),i);
1831           tmp1+=nameTry;
1832           if(std::find(namesToAvoid.begin(),namesToAvoid.end(),tmp1)==namesToAvoid.end())
1833             return tmp1;
1834         }
1835     }
1836   //attempt #3
1837   std::string tmp2;
1838   for(std::vector<std::string>::const_iterator it2=namesToAvoid.begin();it2!=namesToAvoid.end();it2++)
1839     tmp2+=(*it2);
1840   if(std::find(namesToAvoid.begin(),namesToAvoid.end(),tmp2)==namesToAvoid.end())
1841     return tmp2;
1842   throw INTERP_KERNEL::Exception("MEDFileMesh::CreateNameNotIn : impossible to find a not already used name !");
1843 }
1844
1845 int MEDFileMesh::PutInThirdComponentOfCodeOffset(std::vector<int>& code, int strt)
1846 {
1847   std::size_t nbOfChunks=code.size()/3;
1848   if(code.size()%3!=0)
1849     throw INTERP_KERNEL::Exception("MEDFileMesh::PutInThirdComponentOfCodeOffset : code has invalid size : should be of size 3*x !");
1850   int ret=strt;
1851   for(std::size_t i=0;i<nbOfChunks;i++)
1852     {
1853       code[3*i+2]=ret;
1854       ret+=code[3*i+1];
1855     }
1856   return ret;
1857 }
1858
1859 /*!
1860  * This method should be called by any set* method of subclasses to deal automatically with _name attribute.
1861  * If _name attribute is empty the name of 'm' if taken as _name attribute.
1862  * If _name is not empty and that 'm' has the same name nothing is done.
1863  * If _name is not emplt and that 'm' has \b NOT the same name an exception is thrown.
1864  */
1865 void MEDFileMesh::dealWithTinyInfo(const MEDCouplingMesh *m)
1866 {
1867   if(!m)
1868     throw INTERP_KERNEL::Exception("MEDFileMesh::dealWithTinyInfo : input mesh in NULL !");
1869   if(_name.empty())
1870     _name=m->getName();
1871   else
1872     {
1873       std::string name(m->getName());
1874       if(!name.empty())
1875         {
1876           if(_name!=name)
1877             {
1878               std::ostringstream oss; oss << "MEDFileMesh::dealWithTinyInfo : name of current MEDfile mesh is '" << _name << "' whereas name of input mesh is : '";
1879               oss << name << "' ! Names must match !";
1880               throw INTERP_KERNEL::Exception(oss.str().c_str());
1881             }
1882         }
1883     }
1884   if(_desc_name.empty())
1885     _desc_name=m->getDescription();
1886   else
1887     {
1888       std::string name(m->getDescription());
1889       if(!name.empty())
1890         {
1891           if(_desc_name!=name)
1892             {
1893               std::ostringstream oss; oss << "MEDFileMesh::dealWithTinyInfo : description of current MEDfile mesh is '" << _desc_name << "' whereas name of input mesh is : '";
1894               oss << name << "' ! Names must match !";
1895               throw INTERP_KERNEL::Exception(oss.str().c_str());
1896             }
1897         }
1898     }
1899 }
1900
1901 void MEDFileMesh::getFamilyRepr(std::ostream& oss) const
1902 {
1903   oss << "(**************************)\n(* FAMILIES OF THE MESH : *)\n(**************************)\n";
1904   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
1905     {
1906       oss << "- Family with name \"" << (*it).first << "\" with number " << (*it).second << std::endl;
1907       oss << "  - Groups lying on this family : ";
1908       std::vector<std::string> grps=getGroupsOnFamily((*it).first);
1909       std::copy(grps.begin(),grps.end(),std::ostream_iterator<std::string>(oss," "));
1910       oss << std::endl << std::endl;
1911     }
1912 }
1913
1914 /*!
1915  * Returns a new MEDFileUMesh holding the mesh data that has been read from a given MED
1916  * file. The mesh to load is specified by its name and numbers of a time step and an
1917  * iteration.
1918  *  \param [in] fileName - the name of MED file to read.
1919  *  \param [in] mName - the name of the mesh to read.
1920  *  \param [in] dt - the number of a time step.
1921  *  \param [in] it - the number of an iteration.
1922  *  \return MEDFileUMesh * - a new instance of MEDFileUMesh. The caller is to delete this
1923  *          mesh using decrRef() as it is no more needed. 
1924  *  \throw If the file is not readable.
1925  *  \throw If there is no mesh with given attributes in the file.
1926  *  \throw If the mesh in the file is not an unstructured one.
1927  */
1928 MEDFileUMesh *MEDFileUMesh::New(const std::string& fileName, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
1929 {
1930   MEDFileUtilities::CheckFileForRead(fileName);
1931   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
1932   return new MEDFileUMesh(fid,mName,dt,it,mrs);
1933 }
1934
1935 /*!
1936  * Returns a new MEDFileUMesh holding the mesh data that has been read from a given MED
1937  * file. The first mesh in the file is loaded.
1938  *  \param [in] fileName - the name of MED file to read.
1939  *  \return MEDFileUMesh * - a new instance of MEDFileUMesh. The caller is to delete this
1940  *          mesh using decrRef() as it is no more needed. 
1941  *  \throw If the file is not readable.
1942  *  \throw If there is no meshes in the file.
1943  *  \throw If the mesh in the file is not an unstructured one.
1944  */
1945 MEDFileUMesh *MEDFileUMesh::New(const std::string& fileName, MEDFileMeshReadSelector *mrs)
1946 {
1947   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
1948   if(ms.empty())
1949     {
1950       std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
1951       throw INTERP_KERNEL::Exception(oss.str().c_str());
1952     }
1953   MEDFileUtilities::CheckFileForRead(fileName);
1954   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
1955   int dt,it;
1956   ParaMEDMEM::MEDCouplingMeshType meshType;
1957   std::string dummy2;
1958   MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dt,it,dummy2);
1959   return new MEDFileUMesh(fid,ms.front(),dt,it,mrs);
1960 }
1961
1962 /*!
1963  * Returns an empty instance of MEDFileUMesh.
1964  *  \return MEDFileUMesh * - a new instance of MEDFileUMesh. The caller is to delete this
1965  *          mesh using decrRef() as it is no more needed. 
1966  */
1967 MEDFileUMesh *MEDFileUMesh::New()
1968 {
1969   return new MEDFileUMesh;
1970 }
1971
1972 std::size_t MEDFileUMesh::getHeapMemorySizeWithoutChildren() const
1973 {
1974   std::size_t ret(MEDFileMesh::getHeapMemorySizeWithoutChildren());
1975   ret+=_ms.capacity()*(sizeof(MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1>));
1976   return ret;
1977 }
1978
1979 std::vector<const BigMemoryObject *> MEDFileUMesh::getDirectChildren() const
1980 {
1981   std::vector<const BigMemoryObject *> ret(MEDFileMesh::getDirectChildren());
1982   if((const DataArrayDouble*)_coords)
1983     ret.push_back((const DataArrayDouble*)_coords);
1984   if((const DataArrayInt *)_fam_coords)
1985     ret.push_back((const DataArrayInt *)_fam_coords);
1986   if((const DataArrayInt *)_num_coords)
1987     ret.push_back((const DataArrayInt *)_num_coords);
1988   if((const DataArrayInt *)_rev_num_coords)
1989     ret.push_back((const DataArrayInt *)_rev_num_coords);
1990   if((const DataArrayAsciiChar *)_name_coords)
1991     ret.push_back((const DataArrayAsciiChar *)_name_coords);
1992   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
1993     if((const MEDFileUMeshSplitL1*) *it)
1994       ret.push_back((const MEDFileUMeshSplitL1*) *it);
1995   return ret;
1996 }
1997
1998 MEDFileMesh *MEDFileUMesh::shallowCpy() const
1999 {
2000   MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret=new MEDFileUMesh(*this);
2001   return ret.retn();
2002 }
2003
2004 MEDFileMesh *MEDFileUMesh::createNewEmpty() const
2005 {
2006   return new MEDFileUMesh;
2007 }
2008
2009 MEDFileMesh *MEDFileUMesh::deepCpy() const
2010 {
2011   MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret=new MEDFileUMesh(*this);
2012   if((const DataArrayDouble*)_coords)
2013     ret->_coords=_coords->deepCpy();
2014   if((const DataArrayInt*)_fam_coords)
2015     ret->_fam_coords=_fam_coords->deepCpy();
2016   if((const DataArrayInt*)_num_coords)
2017     ret->_num_coords=_num_coords->deepCpy();
2018   if((const DataArrayInt*)_rev_num_coords)
2019     ret->_rev_num_coords=_rev_num_coords->deepCpy();
2020   if((const DataArrayAsciiChar*)_name_coords)
2021     ret->_name_coords=_name_coords->deepCpy();
2022   std::size_t i=0;
2023   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,i++)
2024     {
2025       if((const MEDFileUMeshSplitL1 *)(*it))
2026         ret->_ms[i]=(*it)->deepCpy(ret->_coords);
2027     }
2028   return ret.retn();
2029 }
2030
2031 /*!
2032  * Checks if \a this and another mesh are equal.
2033  *  \param [in] other - the mesh to compare with.
2034  *  \param [in] eps - a precision used to compare real values.
2035  *  \param [in,out] what - the string returning description of unequal data.
2036  *  \return bool - \c true if the meshes are equal, \c false, else.
2037  */
2038 bool MEDFileUMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
2039 {
2040   if(!MEDFileMesh::isEqual(other,eps,what))
2041     return false;
2042   const MEDFileUMesh *otherC=dynamic_cast<const MEDFileUMesh *>(other);
2043   if(!otherC)
2044     {
2045       what="Mesh types differ ! This is unstructured and other is NOT !";
2046       return false;
2047     }
2048   clearNonDiscrAttributes();
2049   otherC->clearNonDiscrAttributes();
2050   const DataArrayDouble *coo1=_coords;
2051   const DataArrayDouble *coo2=otherC->_coords;
2052   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
2053     {
2054       what="Mismatch of coordinates ! One is defined and not other !";
2055       return false;
2056     }
2057   if(coo1)
2058     {
2059       bool ret=coo1->isEqual(*coo2,eps);
2060       if(!ret)
2061         {
2062           what="Coords differ !";
2063           return false;
2064         }
2065     }
2066   const DataArrayInt *famc1=_fam_coords;
2067   const DataArrayInt *famc2=otherC->_fam_coords;
2068   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
2069     {
2070       what="Mismatch of families arr on nodes ! One is defined and not other !";
2071       return false;
2072     }
2073   if(famc1)
2074     {
2075       bool ret=famc1->isEqual(*famc2);
2076       if(!ret)
2077         {
2078           what="Families arr on node differ !";
2079           return false;
2080         }
2081     }
2082   const DataArrayInt *numc1=_num_coords;
2083   const DataArrayInt *numc2=otherC->_num_coords;
2084   if((numc1==0 && numc2!=0) || (numc1!=0 && numc2==0))
2085     {
2086       what="Mismatch of numbering arr on nodes ! One is defined and not other !";
2087       return false;
2088     }
2089   if(numc1)
2090     {
2091       bool ret=numc1->isEqual(*numc2);
2092       if(!ret)
2093         {
2094           what="Numbering arr on node differ !";
2095           return false;
2096         }
2097     }
2098   const DataArrayAsciiChar *namec1=_name_coords;
2099   const DataArrayAsciiChar *namec2=otherC->_name_coords;
2100   if((namec1==0 && namec2!=0) || (namec1!=0 && namec2==0))
2101     {
2102       what="Mismatch of naming arr on nodes ! One is defined and not other !";
2103       return false;
2104     }
2105   if(namec1)
2106     {
2107       bool ret=namec1->isEqual(*namec2);
2108       if(!ret)
2109         {
2110           what="Names arr on node differ !";
2111           return false;
2112         }
2113     }
2114   if(_ms.size()!=otherC->_ms.size())
2115     {
2116       what="Number of levels differs !";
2117       return false;
2118     }
2119   std::size_t sz=_ms.size();
2120   for(std::size_t i=0;i<sz;i++)
2121     {
2122       const MEDFileUMeshSplitL1 *s1=_ms[i];
2123       const MEDFileUMeshSplitL1 *s2=otherC->_ms[i];
2124       if((s1==0 && s2!=0) || (s1!=0 && s2==0))
2125         {
2126           what="Mismatch of presence of sub levels !";
2127           return false;
2128         }
2129       if(s1)
2130         {
2131           bool ret=s1->isEqual(s2,eps,what);
2132           if(!ret)
2133             return false;
2134         }
2135     }
2136   return true;
2137 }
2138
2139 /*!
2140  * Clears redundant attributes of incorporated data arrays.
2141  */
2142 void MEDFileUMesh::clearNonDiscrAttributes() const
2143 {
2144   MEDFileMesh::clearNonDiscrAttributes();
2145   const DataArrayDouble *coo1=_coords;
2146   if(coo1)
2147     (const_cast<DataArrayDouble *>(coo1))->setName("");//This parameter is not discriminant for comparison
2148   const DataArrayInt *famc1=_fam_coords;
2149   if(famc1)
2150     (const_cast<DataArrayInt *>(famc1))->setName("");//This parameter is not discriminant for comparison
2151   const DataArrayInt *numc1=_num_coords;
2152   if(numc1)
2153     (const_cast<DataArrayInt *>(numc1))->setName("");//This parameter is not discriminant for comparison
2154   const DataArrayAsciiChar *namc1=_name_coords;
2155   if(namc1)
2156     (const_cast<DataArrayAsciiChar *>(namc1))->setName("");//This parameter is not discriminant for comparison
2157   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2158     {
2159       const MEDFileUMeshSplitL1 *tmp=(*it);
2160       if(tmp)
2161         tmp->clearNonDiscrAttributes();
2162     }
2163 }
2164
2165 void MEDFileUMesh::setName(const std::string& name)
2166 {
2167   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
2168     if((MEDFileUMeshSplitL1 *)(*it)!=0)
2169       (*it)->setName(name);
2170   MEDFileMesh::setName(name);
2171 }
2172
2173 MEDFileUMesh::MEDFileUMesh()
2174 {
2175 }
2176
2177 MEDFileUMesh::MEDFileUMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
2178 try
2179   {
2180     loadUMeshFromFile(fid,mName,dt,it,mrs);
2181   }
2182 catch(INTERP_KERNEL::Exception& e)
2183   {
2184     throw e;
2185   }
2186
2187 void MEDFileUMesh::loadUMeshFromFile(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
2188 {
2189   MEDFileUMeshL2 loaderl2;
2190   ParaMEDMEM::MEDCouplingMeshType meshType;
2191   int dummy0,dummy1;
2192   std::string dummy2;
2193   int mid=MEDFileUMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dummy2);
2194   if(meshType!=UNSTRUCTURED)
2195     {
2196       std::ostringstream oss; oss << "Trying to load as unstructured an existing mesh with name '" << mName << "' !";
2197       throw INTERP_KERNEL::Exception(oss.str().c_str());
2198     }
2199   loaderl2.loadAll(fid,mid,mName,dt,it,mrs);
2200   int lev=loaderl2.getNumberOfLevels();
2201   _ms.resize(lev);
2202   for(int i=0;i<lev;i++)
2203     {
2204       if(!loaderl2.emptyLev(i))
2205         _ms[i]=new MEDFileUMeshSplitL1(loaderl2,mName,i);
2206       else
2207         _ms[i]=0;
2208     }
2209   MEDFileMeshL2::ReadFamiliesAndGrps(fid,mName,_families,_groups,mrs);
2210   //
2211   setName(loaderl2.getName());
2212   setDescription(loaderl2.getDescription());
2213   setUnivName(loaderl2.getUnivName());
2214   setIteration(loaderl2.getIteration());
2215   setOrder(loaderl2.getOrder());
2216   setTimeValue(loaderl2.getTime());
2217   setTimeUnit(loaderl2.getTimeUnit());
2218   _coords=loaderl2.getCoords();
2219   if(!mrs || mrs->isNodeFamilyFieldReading())
2220     _fam_coords=loaderl2.getCoordsFamily();
2221   if(!mrs || mrs->isNodeNumFieldReading())
2222     _num_coords=loaderl2.getCoordsNum();
2223   if(!mrs || mrs->isNodeNameFieldReading())
2224     _name_coords=loaderl2.getCoordsName();
2225   computeRevNum();
2226 }
2227
2228 MEDFileUMesh::~MEDFileUMesh()
2229 {
2230 }
2231
2232 void MEDFileUMesh::writeLL(med_idt fid) const
2233 {
2234   const DataArrayDouble *coo=_coords;
2235   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
2236   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
2237   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
2238   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
2239   int spaceDim=coo?coo->getNumberOfComponents():0;
2240   int mdim=getMeshDimension();
2241   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
2242   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
2243   for(int i=0;i<spaceDim;i++)
2244     {
2245       std::string info=coo->getInfoOnComponent(i);
2246       std::string c,u;
2247       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
2248       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
2249       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
2250     }
2251   MEDmeshCr(fid,maa,spaceDim,mdim,MED_UNSTRUCTURED_MESH,desc,"",MED_SORT_DTIT,MED_CARTESIAN,comp,unit);
2252   MEDmeshUniversalNameWr(fid,maa);
2253   std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE));
2254   MEDFileUMeshL2::WriteCoords(fid,meshName,_iteration,_order,_time,_coords,_fam_coords,_num_coords,_name_coords);
2255   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2256     if((const MEDFileUMeshSplitL1 *)(*it)!=0)
2257       (*it)->write(fid,meshName,mdim);
2258   MEDFileUMeshL2::WriteFamiliesAndGrps(fid,meshName,_families,_groups,_too_long_str);
2259 }
2260
2261 /*!
2262  * Returns relative dimensions of mesh entities (excluding nodes) present in \a this mesh.
2263  *  \return std::vector<int> - a sequence of the relative dimensions.
2264  */
2265 std::vector<int> MEDFileUMesh::getNonEmptyLevels() const
2266 {
2267   std::vector<int> ret;
2268   int lev=0;
2269   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
2270     if((const MEDFileUMeshSplitL1 *)(*it)!=0)
2271       if(!(*it)->empty())
2272         ret.push_back(lev);
2273   return ret;
2274 }
2275
2276 /*!
2277  * Returns relative dimensions of mesh entities (including nodes) present in \a this mesh.
2278  *  \return std::vector<int> - a sequence of the relative dimensions.
2279  */
2280 std::vector<int> MEDFileUMesh::getNonEmptyLevelsExt() const
2281 {
2282   std::vector<int> ret0=getNonEmptyLevels();
2283   if((const DataArrayDouble *) _coords)
2284     {
2285       std::vector<int> ret(ret0.size()+1);
2286       ret[0]=1;
2287       std::copy(ret0.begin(),ret0.end(),ret.begin()+1);
2288       return ret;
2289     }
2290   return ret0;
2291 }
2292
2293 std::vector<int> MEDFileUMesh::getFamArrNonEmptyLevelsExt() const
2294 {
2295   std::vector<int> ret;
2296   const DataArrayInt *famCoo(_fam_coords);
2297   if(famCoo)
2298     ret.push_back(1);
2299   int lev=0;
2300   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
2301     {
2302       const MEDFileUMeshSplitL1 *cur(*it);
2303       if(cur)
2304         if(cur->getFamilyField())
2305           ret.push_back(lev);
2306     }
2307   return ret;
2308 }
2309
2310 std::vector<int> MEDFileUMesh::getNumArrNonEmptyLevelsExt() const
2311 {
2312   std::vector<int> ret;
2313   const DataArrayInt *numCoo(_num_coords);
2314   if(numCoo)
2315     ret.push_back(1);
2316   int lev=0;
2317   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
2318     {
2319       const MEDFileUMeshSplitL1 *cur(*it);
2320       if(cur)
2321         if(cur->getNumberField())
2322           ret.push_back(lev);
2323     }
2324   return ret;
2325 }
2326
2327 std::vector<int> MEDFileUMesh::getNameArrNonEmptyLevelsExt() const
2328 {
2329   std::vector<int> ret;
2330   const DataArrayAsciiChar *nameCoo(_name_coords);
2331   if(nameCoo)
2332     ret.push_back(1);
2333   int lev=0;
2334   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
2335     {
2336       const MEDFileUMeshSplitL1 *cur(*it);
2337       if(cur)
2338         if(cur->getNameField())
2339           ret.push_back(lev);
2340     }
2341   return ret;
2342 }
2343
2344 /*!
2345  * Returns all relative mesh levels (**excluding nodes**) where a given group is defined.
2346  * To include nodes, call getGrpNonEmptyLevelsExt() method.
2347  *  \param [in] grp - the name of the group of interest.
2348  *  \return std::vector<int> - a sequence of the relative dimensions.
2349  */
2350 std::vector<int> MEDFileUMesh::getGrpNonEmptyLevels(const std::string& grp) const
2351 {
2352   std::vector<std::string> fams=getFamiliesOnGroup(grp);
2353   return getFamsNonEmptyLevels(fams);
2354 }
2355
2356 /*!
2357  * Returns all relative mesh levels (including nodes) where a given group is defined.
2358  *  \param [in] grp - the name of the group of interest.
2359  *  \return std::vector<int> - a sequence of the relative dimensions.
2360  */
2361 std::vector<int> MEDFileUMesh::getGrpNonEmptyLevelsExt(const std::string& grp) const
2362 {
2363   std::vector<std::string> fams=getFamiliesOnGroup(grp);
2364   return getFamsNonEmptyLevelsExt(fams);
2365 }
2366
2367 /*!
2368  * Returns all relative mesh levels (**excluding nodes**) where a given family is defined.
2369  * To include nodes, call getFamNonEmptyLevelsExt() method.
2370  *  \param [in] fam - the name of the family of interest.
2371  *  \return std::vector<int> - a sequence of the relative dimensions.
2372  */
2373 std::vector<int> MEDFileUMesh::getFamNonEmptyLevels(const std::string& fam) const
2374 {
2375   std::vector<std::string> fams(1,std::string(fam));
2376   return getFamsNonEmptyLevels(fams);
2377 }
2378
2379 /*!
2380  * Returns all relative mesh levels (including nodes) where a given family is defined.
2381  *  \param [in] fam - the name of the family of interest.
2382  *  \return std::vector<int> - a sequence of the relative dimensions.
2383  */
2384 std::vector<int> MEDFileUMesh::getFamNonEmptyLevelsExt(const std::string& fam) const
2385 {
2386   std::vector<std::string> fams(1,std::string(fam));
2387   return getFamsNonEmptyLevelsExt(fams);
2388 }
2389
2390 /*!
2391  * Returns all relative mesh levels (**excluding nodes**) where given groups are defined.
2392  * To include nodes, call getGrpsNonEmptyLevelsExt() method.
2393  *  \param [in] grps - a sequence of names of the groups of interest.
2394  *  \return std::vector<int> - a sequence of the relative dimensions.
2395  */
2396 std::vector<int> MEDFileUMesh::getGrpsNonEmptyLevels(const std::vector<std::string>& grps) const
2397 {
2398   std::vector<std::string> fams=getFamiliesOnGroups(grps);
2399   return getFamsNonEmptyLevels(fams);
2400 }
2401
2402 /*!
2403  * Returns all relative mesh levels (including nodes) where given groups are defined.
2404  *  \param [in] grps - a sequence of names of the groups of interest.
2405  *  \return std::vector<int> - a sequence of the relative dimensions.
2406  */
2407 std::vector<int> MEDFileUMesh::getGrpsNonEmptyLevelsExt(const std::vector<std::string>& grps) const
2408 {
2409   std::vector<std::string> fams=getFamiliesOnGroups(grps);
2410   return getFamsNonEmptyLevelsExt(fams);
2411 }
2412
2413 /*!
2414  * Returns all relative mesh levels (**excluding nodes**) where given families are defined.
2415  * To include nodes, call getFamsNonEmptyLevelsExt() method.
2416  *  \param [in] fams - the name of the family of interest.
2417  *  \return std::vector<int> - a sequence of the relative dimensions.
2418  */
2419 std::vector<int> MEDFileUMesh::getFamsNonEmptyLevels(const std::vector<std::string>& fams) const
2420 {
2421   std::vector<int> ret;
2422   std::vector<int> levs=getNonEmptyLevels();
2423   std::vector<int> famIds=getFamiliesIds(fams);
2424   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
2425     if(_ms[-(*it)]->presenceOfOneFams(famIds))
2426       ret.push_back(*it);
2427   return ret;
2428 }
2429
2430 /*!
2431  * Returns all relative mesh levels (including nodes) where given families are defined.
2432  *  \param [in] fams - the names of the families of interest.
2433  *  \return std::vector<int> - a sequence of the relative dimensions.
2434  */
2435 std::vector<int> MEDFileUMesh::getFamsNonEmptyLevelsExt(const std::vector<std::string>& fams) const
2436 {
2437   std::vector<int> ret0=getFamsNonEmptyLevels(fams);
2438   const DataArrayInt *famCoords=_fam_coords;
2439   if(!famCoords)
2440     return ret0;
2441   std::vector<int> famIds=getFamiliesIds(fams);
2442   if(famCoords->presenceOfValue(famIds))
2443     {
2444       std::vector<int> ret(ret0.size()+1);
2445       ret[0]=1;
2446       std::copy(ret0.begin(),ret0.end(),ret.begin()+1);
2447       return ret;
2448     }
2449   else
2450     return ret0;
2451 }
2452
2453 /*!
2454  * Returns names of groups that partly or fully appear on the level \a meshDimRelToMaxExt.
2455  *  \param [in] meshDimRelToMaxExt - a relative dimension of interest.
2456  *  \return std::vector<std::string> - a sequence of group names at \a meshDimRelToMaxExt
2457  *          level. 
2458  */
2459 std::vector<std::string> MEDFileUMesh::getGroupsOnSpecifiedLev(int meshDimRelToMaxExt) const
2460 {
2461   std::vector<std::string> ret;
2462   std::vector<std::string> allGrps=getGroupsNames();
2463   for(std::vector<std::string>::const_iterator it=allGrps.begin();it!=allGrps.end();it++)
2464     {
2465       std::vector<int> levs=getGrpNonEmptyLevelsExt((*it));
2466       if(std::find(levs.begin(),levs.end(),meshDimRelToMaxExt)!=levs.end())
2467         ret.push_back(*it);
2468     }
2469   return ret;
2470 }
2471
2472 int MEDFileUMesh::getMaxAbsFamilyIdInArrays() const
2473 {
2474   int ret=-std::numeric_limits<int>::max(),tmp=-1;
2475   if((const DataArrayInt *)_fam_coords)
2476     {
2477       int val=_fam_coords->getMaxValue(tmp);
2478       ret=std::max(ret,std::abs(val));
2479     }
2480   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2481     {
2482       if((const MEDFileUMeshSplitL1 *)(*it))
2483         {
2484           const DataArrayInt *da=(*it)->getFamilyField();
2485           if(da)
2486             {
2487               int val=da->getMaxValue(tmp);
2488               ret=std::max(ret,std::abs(val));
2489             }
2490         }
2491     }
2492   return ret;
2493 }
2494
2495 int MEDFileUMesh::getMaxFamilyIdInArrays() const
2496 {
2497   int ret=-std::numeric_limits<int>::max(),tmp=-1;
2498   if((const DataArrayInt *)_fam_coords)
2499     {
2500       int val=_fam_coords->getMaxValue(tmp);
2501       ret=std::max(ret,val);
2502     }
2503   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2504     {
2505       if((const MEDFileUMeshSplitL1 *)(*it))
2506         {
2507           const DataArrayInt *da=(*it)->getFamilyField();
2508           if(da)
2509             {
2510               int val=da->getMaxValue(tmp);
2511               ret=std::max(ret,val);
2512             }
2513         }
2514     }
2515   return ret;
2516 }
2517
2518 int MEDFileUMesh::getMinFamilyIdInArrays() const
2519 {
2520   int ret=std::numeric_limits<int>::max(),tmp=-1;
2521   if((const DataArrayInt *)_fam_coords)
2522     {
2523       int val=_fam_coords->getMinValue(tmp);
2524       ret=std::min(ret,val);
2525     }
2526   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2527     {
2528       if((const MEDFileUMeshSplitL1 *)(*it))
2529         {
2530           const DataArrayInt *da=(*it)->getFamilyField();
2531           if(da)
2532             {
2533               int val=da->getMinValue(tmp);
2534               ret=std::min(ret,val);
2535             }
2536         }
2537     }
2538   return ret;
2539 }
2540
2541 /*!
2542  * Returns the dimension on cells in \a this mesh.
2543  *  \return int - the mesh dimension.
2544  *  \throw If there are no cells in this mesh.
2545  */
2546 int MEDFileUMesh::getMeshDimension() const
2547 {
2548   int lev=0;
2549   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev++)
2550     if((const MEDFileUMeshSplitL1 *)(*it)!=0)
2551       return (*it)->getMeshDimension()+lev;
2552   throw INTERP_KERNEL::Exception("MEDFileUMesh::getMeshDimension : impossible to find a mesh dimension !");
2553 }
2554
2555 /*!
2556  * Returns the space dimension of \a this mesh that is equal to number of components in
2557  * the node coordinates array.
2558  *  \return int - the space dimension of \a this mesh.
2559  *  \throw If the node coordinates array is not available.
2560  */
2561 int MEDFileUMesh::getSpaceDimension() const
2562 {
2563   const DataArrayDouble *coo=_coords;
2564   if(!coo)
2565     throw INTERP_KERNEL::Exception(" MEDFileUMesh::getSpaceDimension : no coords set !");
2566   return coo->getNumberOfComponents();
2567 }
2568
2569 /*!
2570  * Returns a string describing \a this mesh.
2571  *  \return std::string - the mesh information string.
2572  */
2573 std::string MEDFileUMesh::simpleRepr() const
2574 {
2575   std::ostringstream oss;
2576   oss << MEDFileMesh::simpleRepr();
2577   const DataArrayDouble *coo=_coords;
2578   oss << "- The dimension of the space is ";
2579   static const char MSG1[]= "*** NO COORDS SET ***";
2580   static const char MSG2[]= "*** NO CONNECTIVITY SET FOR THIS LEVEL***";
2581   if(coo)
2582     oss << _coords->getNumberOfComponents() << std::endl;
2583   else
2584     oss << MSG1 << std::endl;
2585   oss << "- Type of the mesh : UNSTRUCTURED\n";
2586   oss << "- Number of nodes : ";
2587   if(coo)
2588     oss << _coords->getNumberOfTuples() << std::endl;
2589   else
2590     oss << MSG1 << std::endl;
2591   std::size_t nbOfLev=_ms.size();
2592   oss << "- Number of levels allocated : " << nbOfLev << std::endl;
2593   for(std::size_t i=0;i<nbOfLev;i++)
2594     {
2595       const MEDFileUMeshSplitL1 *lev=_ms[i];
2596       oss << "  - Level #" << -((int) i) << " has dimension : ";
2597       if(lev)
2598         {
2599           oss << lev->getMeshDimension() << std::endl;
2600           lev->simpleRepr(oss);
2601         }
2602       else
2603         oss << MSG2 << std::endl;
2604     }
2605   oss << "- Number of families : " << _families.size() << std::endl << std::endl;
2606   if(coo)
2607     {
2608       oss << "(***********************)\n(* NODES OF THE MESH : *)\n(***********************)\n";
2609       oss << "- Names of coordinates :" << std::endl;
2610       std::vector<std::string> vars=coo->getVarsOnComponent();
2611       std::copy(vars.begin(),vars.end(),std::ostream_iterator<std::string>(oss," "));
2612       oss << std::endl << "- Units of coordinates : " << std::endl;
2613       std::vector<std::string> units=coo->getUnitsOnComponent();
2614       std::copy(units.begin(),units.end(),std::ostream_iterator<std::string>(oss," "));
2615     }
2616   oss << std::endl << std::endl;
2617   getFamilyRepr(oss);
2618   return oss.str();
2619 }
2620
2621 /*!
2622  * Returns a full textual description of \a this mesh.
2623  *  \return std::string - the string holding the mesh description.
2624  */
2625 std::string MEDFileUMesh::advancedRepr() const
2626 {
2627   return simpleRepr();
2628 }
2629
2630 /*!
2631  * Returns number of mesh entities of a given relative dimension in \a this mesh.
2632  *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
2633  *  \return int - the number of entities.
2634  *  \throw If no mesh entities of dimension \a meshDimRelToMaxExt are available in \a this mesh.
2635  */
2636 int MEDFileUMesh::getSizeAtLevel(int meshDimRelToMaxExt) const
2637 {
2638   if(meshDimRelToMaxExt==1)
2639     {
2640       if(!((const DataArrayDouble *)_coords))
2641         throw INTERP_KERNEL::Exception("MEDFileUMesh::getSizeAtLevel : no coordinates specified !");
2642       return _coords->getNumberOfTuples();
2643     }
2644   return getMeshAtLevSafe(meshDimRelToMaxExt)->getSize();
2645 }
2646
2647 /*!
2648  * Returns the family field for mesh entities of a given dimension.
2649  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
2650  *  \return const DataArrayInt * - the family field. It is an array of ids of families
2651  *          each mesh entity belongs to. It can be \c NULL.
2652  */
2653 const DataArrayInt *MEDFileUMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) const
2654 {
2655   if(meshDimRelToMaxExt==1)
2656     return _fam_coords;
2657   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2658   return l1->getFamilyField();
2659 }
2660
2661 /*!
2662  * Returns the optional numbers of mesh entities of a given dimension.
2663  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
2664  *  \return const DataArrayInt * - the array of the entity numbers.
2665  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2666  */
2667 const DataArrayInt *MEDFileUMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) const
2668 {
2669   if(meshDimRelToMaxExt==1)
2670     return _num_coords;
2671   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2672   return l1->getNumberField();
2673 }
2674
2675 const DataArrayAsciiChar *MEDFileUMesh::getNameFieldAtLevel(int meshDimRelToMaxExt) const
2676 {
2677   if(meshDimRelToMaxExt==1)
2678     return _name_coords;
2679   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2680   return l1->getNameField();
2681 }
2682
2683 int MEDFileUMesh::getNumberOfNodes() const
2684 {
2685   const DataArrayDouble *coo=_coords;
2686   if(!coo)
2687     throw INTERP_KERNEL::Exception(" MEDFileUMesh::getNumberOfNodes : no coords set !");
2688   return coo->getNumberOfTuples();
2689 }
2690
2691 void MEDFileUMesh::whichAreNodesFetched(const MEDFileField1TSStructItem& st, const MEDFileFieldGlobsReal *globs, std::vector<bool>& nodesFetched) const
2692 {
2693   std::size_t sz(st.getNumberOfItems());
2694   for(std::size_t i=0;i<sz;i++)
2695     {
2696       INTERP_KERNEL::NormalizedCellType curGt(st[i].getGeo());
2697       const MEDCoupling1GTUMesh *m(getDirectUndergroundSingleGeoTypeMesh(curGt));
2698       if(st[i].getPflName().empty())
2699         m->computeNodeIdsAlg(nodesFetched);
2700       else
2701         {
2702           const DataArrayInt *arr(globs->getProfile(st[i].getPflName()));
2703           MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> m2(dynamic_cast<MEDCoupling1GTUMesh *>(m->buildPartOfMySelf(arr->begin(),arr->end(),true)));
2704           m2->computeNodeIdsAlg(nodesFetched);
2705         }
2706     }
2707 }
2708
2709 /*!
2710  * Returns the optional numbers of mesh entities of a given dimension transformed using
2711  * DataArrayInt::invertArrayN2O2O2N().
2712  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
2713  *  \return const DataArrayInt * - the array of the entity numbers transformed using
2714  *          DataArrayInt::invertArrayN2O2O2N().
2715  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2716  */
2717 const DataArrayInt *MEDFileUMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxExt) const
2718 {
2719   if(meshDimRelToMaxExt==1)
2720     {
2721       if(!((const DataArrayInt *)_num_coords))
2722         throw INTERP_KERNEL::Exception("MEDFileUMesh::getRevNumberFieldAtLevel : no coordinates renum specified !");
2723       return _rev_num_coords;
2724     }
2725   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2726   return l1->getRevNumberField();
2727 }
2728
2729 /*!
2730  * Returns a pointer to the node coordinates array of \a this mesh \b without
2731  * incrementing its reference counter, thus there is no need to decrRef() it by the caller.
2732  */
2733 DataArrayDouble *MEDFileUMesh::getCoords() const
2734 {
2735   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp(_coords);
2736   if((DataArrayDouble *)tmp)
2737     {
2738       return tmp;
2739     }
2740   return 0;
2741 }
2742
2743 /*!
2744  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in a given
2745  * group of \a this mesh. Only mesh entities of a given dimension are included in the
2746  * new mesh.
2747  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
2748  *  \param [in] grp - the name of the group whose mesh entities are included in the
2749  *          new mesh.
2750  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
2751  *          according to the optional numbers of entities, if available.
2752  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
2753  *          delete this mesh using decrRef() as it is no more needed.
2754  *  \throw If the name of a nonexistent group is specified.
2755  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2756  */
2757 MEDCouplingUMesh *MEDFileUMesh::getGroup(int meshDimRelToMaxExt, const std::string& grp, bool renum) const
2758 {
2759   synchronizeTinyInfoOnLeaves();
2760   std::vector<std::string> tmp(1);
2761   tmp[0]=grp;
2762   return getGroups(meshDimRelToMaxExt,tmp,renum);
2763 }
2764
2765 /*!
2766  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in given
2767  * groups of \a this mesh. Only mesh entities of a given dimension are included in the
2768  * new mesh.
2769  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
2770  *  \param [in] grps - a sequence of group names whose mesh entities are included in the
2771  *          new mesh.
2772  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
2773  *          according to the optional numbers of entities, if available.
2774  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
2775  *          delete this mesh using decrRef() as it is no more needed.
2776  *  \throw If a name of a nonexistent group is present in \a grps.
2777  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2778  */
2779 MEDCouplingUMesh *MEDFileUMesh::getGroups(int meshDimRelToMaxExt, const std::vector<std::string>& grps, bool renum) const
2780 {
2781   synchronizeTinyInfoOnLeaves();
2782   std::vector<std::string> fams2=getFamiliesOnGroups(grps);
2783   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> zeRet=getFamilies(meshDimRelToMaxExt,fams2,renum);
2784   if(grps.size()==1 && ((MEDCouplingUMesh *)zeRet))
2785     zeRet->setName(grps[0]);
2786   return zeRet.retn();
2787 }
2788
2789 /*!
2790  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in a given
2791  * family of \a this mesh. Only mesh entities of a given dimension are included in the
2792  * new mesh.
2793  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
2794  *  \param [in] fam - the name of the family whose mesh entities are included in the
2795  *          new mesh.
2796  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
2797  *          according to the optional numbers of entities, if available.
2798  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
2799  *          delete this mesh using decrRef() as it is no more needed.
2800  *  \throw If a name of a nonexistent family is present in \a grps.
2801  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2802  */
2803 MEDCouplingUMesh *MEDFileUMesh::getFamily(int meshDimRelToMaxExt, const std::string& fam, bool renum) const
2804 {
2805   synchronizeTinyInfoOnLeaves();
2806   std::vector<std::string> tmp(1);
2807   tmp[0]=fam;
2808   return getFamilies(meshDimRelToMaxExt,tmp,renum);
2809 }
2810
2811 /*!
2812  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in given
2813  * families of \a this mesh. Only mesh entities of a given dimension are included in the
2814  * new mesh.
2815  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
2816  *  \param [in] fams - a sequence of family names whose mesh entities are included in the
2817  *          new mesh.
2818  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
2819  *          according to the optional numbers of entities, if available.
2820  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
2821  *          delete this mesh using decrRef() as it is no more needed.
2822  *  \throw If a name of a nonexistent family is present in \a fams.
2823  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2824  */
2825 MEDCouplingUMesh *MEDFileUMesh::getFamilies(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const
2826 {
2827   synchronizeTinyInfoOnLeaves();
2828   if(meshDimRelToMaxExt==1)
2829     {
2830       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr=getFamiliesArr(1,fams,renum);
2831       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
2832       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> c=_coords->selectByTupleId(arr->getConstPointer(),arr->getConstPointer()+arr->getNbOfElems());
2833       ret->setCoords(c);
2834       return ret.retn();
2835     }
2836   std::vector<int> famIds=getFamiliesIds(fams);
2837   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2838   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> zeRet;
2839   if(!famIds.empty())
2840     zeRet=l1->getFamilyPart(&famIds[0],&famIds[0]+famIds.size(),renum);
2841   else
2842     zeRet=l1->getFamilyPart(0,0,renum);
2843   if(fams.size()==1 && ((MEDCouplingUMesh *)zeRet))
2844     zeRet->setName(fams[0]);
2845   return zeRet.retn();
2846 }
2847
2848 /*!
2849  * Returns ids of mesh entities contained in given families of a given dimension.
2850  *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
2851  *          are required.
2852  *  \param [in] fams - the names of the families of interest.
2853  *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
2854  *          returned instead of ids.
2855  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
2856  *          numbers, if available and required, of mesh entities of the families. The caller
2857  *          is to delete this array using decrRef() as it is no more needed. 
2858  *  \throw If the family field is missing for \a meshDimRelToMaxExt.
2859  */
2860 DataArrayInt *MEDFileUMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const
2861 {
2862   std::vector<int> famIds=getFamiliesIds(fams);
2863   if(meshDimRelToMaxExt==1)
2864     {
2865       if((const DataArrayInt *)_fam_coords)
2866         {
2867           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
2868           if(!famIds.empty())
2869             da=_fam_coords->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
2870           else
2871             da=_fam_coords->getIdsEqualList(0,0);
2872           if(renum)
2873             return MEDFileUMeshSplitL1::Renumber(_num_coords,da);
2874           else
2875             return da.retn();
2876         }
2877       else
2878         throw INTERP_KERNEL::Exception("MEDFileUMesh::getFamiliesArr : no family array specified on nodes !");
2879     }
2880   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2881   if(!famIds.empty())
2882     return l1->getFamilyPartArr(&famIds[0],&famIds[0]+famIds.size(),renum);
2883   else
2884     return l1->getFamilyPartArr(0,0,renum);
2885 }
2886
2887 /*!
2888  * Returns a MEDCouplingUMesh of a given relative dimension.
2889  * \warning If \a meshDimRelToMaxExt == 1 (which means nodes), the returned mesh **is not
2890  * valid**. This is a feature, because MEDLoader does not create cells that do not exist! 
2891  * To build a valid MEDCouplingUMesh from the returned one in this case,
2892  * call MEDCouplingUMesh::Build0DMeshFromCoords().
2893  *  \param [in] meshDimRelToMax - the relative dimension of interest.
2894  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
2895  *          optional numbers of mesh entities.
2896  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
2897  *          delete using decrRef() as it is no more needed. 
2898  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2899  * \sa getGenMeshAtLevel()
2900  */
2901 MEDCouplingUMesh *MEDFileUMesh::getMeshAtLevel(int meshDimRelToMaxExt, bool renum) const
2902 {
2903   synchronizeTinyInfoOnLeaves();
2904   if(meshDimRelToMaxExt==1)
2905     {
2906       if(!renum)
2907         {
2908           MEDCouplingUMesh *umesh=MEDCouplingUMesh::New();
2909           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> cc=_coords->deepCpy();
2910           umesh->setCoords(cc);
2911           MEDFileUMeshSplitL1::ClearNonDiscrAttributes(umesh);
2912           umesh->setName(getName());
2913           return umesh;
2914         }
2915     }
2916   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2917   return l1->getWholeMesh(renum);
2918 }
2919
2920 /*!
2921  * Returns a MEDCouplingUMesh of a given relative dimension.
2922  * \warning If \a meshDimRelToMaxExt == 1 (which means nodes), the returned mesh **is not
2923  * valid**. This is a feature, because MEDLoader does not create cells that do not exist! 
2924  * To build a valid MEDCouplingUMesh from the returned one in this case,
2925  * call MEDCouplingUMesh::Build0DMeshFromCoords().
2926  *  \param [in] meshDimRelToMax - the relative dimension of interest.
2927  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
2928  *          optional numbers of mesh entities.
2929  *  \return MEDCouplingMesh * - a pointer to MEDCouplingUMesh that the caller is to
2930  *          delete using decrRef() as it is no more needed. 
2931  *  \throw If there are no mesh entities of \a meshDimRelToMax dimension in \a this mesh.
2932  * \sa getMeshAtLevel()
2933  */
2934 MEDCouplingMesh *MEDFileUMesh::getGenMeshAtLevel(int meshDimRelToMax, bool renum) const
2935 {
2936   return getMeshAtLevel(meshDimRelToMax,renum);
2937 }
2938
2939 std::vector<int> MEDFileUMesh::getDistributionOfTypes(int meshDimRelToMax) const
2940 {
2941   const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMax));
2942   return l1->getDistributionOfTypes();
2943 }
2944
2945 /*!
2946  * Returns a MEDCouplingUMesh of a relative dimension == 0.
2947  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
2948  *          optional numbers of mesh entities.
2949  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
2950  *          delete using decrRef() as it is no more needed. 
2951  *  \throw If there are no mesh entities of the relative dimension == 0 in \a this mesh.
2952  */
2953 MEDCouplingUMesh *MEDFileUMesh::getLevel0Mesh(bool renum) const
2954 {
2955   return getMeshAtLevel(0,renum);
2956 }
2957
2958 /*!
2959  * Returns a MEDCouplingUMesh of a relative dimension == -1.
2960  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
2961  *          optional numbers of mesh entities.
2962  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
2963  *          delete using decrRef() as it is no more needed. 
2964  *  \throw If there are no mesh entities of the relative dimension == -1 in \a this mesh.
2965  */
2966 MEDCouplingUMesh *MEDFileUMesh::getLevelM1Mesh(bool renum) const
2967 {
2968   return getMeshAtLevel(-1,renum);
2969 }
2970
2971 /*!
2972  * Returns a MEDCouplingUMesh of a relative dimension == -2.
2973  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
2974  *          optional numbers of mesh entities.
2975  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
2976  *          delete using decrRef() as it is no more needed. 
2977  *  \throw If there are no mesh entities of the relative dimension == -2 in \a this mesh.
2978  */
2979 MEDCouplingUMesh *MEDFileUMesh::getLevelM2Mesh(bool renum) const
2980 {
2981   return getMeshAtLevel(-2,renum);
2982 }
2983
2984 /*!
2985  * Returns a MEDCouplingUMesh of a relative dimension == -3.
2986  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
2987  *          optional numbers of mesh entities.
2988  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
2989  *          delete using decrRef() as it is no more needed. 
2990  *  \throw If there are no mesh entities of the relative dimension == -3 in \a this mesh.
2991  */
2992 MEDCouplingUMesh *MEDFileUMesh::getLevelM3Mesh(bool renum) const
2993 {
2994   return getMeshAtLevel(-3,renum);
2995 }
2996
2997 /*!
2998  * This method is for advanced users. There is two storing strategy of mesh in \a this.
2999  * Either MEDCouplingUMesh, or vector of MEDCoupling1GTUMesh instances.
3000  * When assignement is done the first one is done, which is not optimal in write mode for MED file.
3001  * This method allows to switch from MEDCouplingUMesh mode to MEDCoupling1GTUMesh mode.
3002  */
3003 void MEDFileUMesh::forceComputationOfParts() const
3004 {
3005   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
3006     {
3007       const MEDFileUMeshSplitL1 *elt(*it);
3008       if(elt)
3009         elt->forceComputationOfParts();
3010     }
3011 }
3012
3013 /*!
3014  * This method returns a vector of mesh parts containing each exactly one geometric type.
3015  * This method will never launch an automatic computation of split by type (an INTERP_KERNEL::Exception will be then thrown).
3016  * This method is only for memory aware users.
3017  * The returned pointers are **NOT** new object pointer. No need to mange them.
3018  */
3019 std::vector<MEDCoupling1GTUMesh *> MEDFileUMesh::getDirectUndergroundSingleGeoTypeMeshes(int meshDimRelToMax) const
3020 {
3021   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(meshDimRelToMax));
3022   return sp->getDirectUndergroundSingleGeoTypeMeshes();
3023 }
3024
3025 /*!
3026  * This method returns the part of \a this having the geometric type \a gt.
3027  * If such part is not existing an exception will be thrown.
3028  * The returned pointer is **NOT** new object pointer. No need to mange it.
3029  */
3030 MEDCoupling1GTUMesh *MEDFileUMesh::getDirectUndergroundSingleGeoTypeMesh(INTERP_KERNEL::NormalizedCellType gt) const
3031 {
3032   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
3033   int lev=(int)cm.getDimension()-getMeshDimension();
3034   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(lev));
3035   return sp->getDirectUndergroundSingleGeoTypeMesh(gt);
3036 }
3037
3038 /*!
3039  * Given a relative level \a meshDimRelToMax it returns the sorted vector of geometric types present in \a this.
3040  * \throw if the reqsuested \a meshDimRelToMax does not exist.
3041  */
3042 std::vector<INTERP_KERNEL::NormalizedCellType> MEDFileUMesh::getGeoTypesAtLevel(int meshDimRelToMax) const
3043 {
3044   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(meshDimRelToMax));
3045   return sp->getGeoTypes();
3046 }
3047
3048 /*!
3049  * This method extracts from whole family field ids the part relative to the input parameter \a gt.
3050  * \param [in] gt - the geometric type for which the family field is asked.
3051  * \return DataArrayInt * - a pointer to DataArrayInt that the caller is to
3052  *          delete using decrRef() as it is no more needed.
3053  * \sa MEDFileUMesh::extractNumberFieldOnGeoType
3054  */
3055 DataArrayInt *MEDFileUMesh::extractFamilyFieldOnGeoType(INTERP_KERNEL::NormalizedCellType gt) const
3056 {
3057   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
3058   int lev=(int)cm.getDimension()-getMeshDimension();
3059   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(lev));
3060   return sp->extractFamilyFieldOnGeoType(gt);
3061 }
3062
3063 /*!
3064  * This method extracts from whole number field ids the part relative to the input parameter \a gt.
3065  * \param [in] gt - the geometric type for which the number field is asked.
3066  * \return DataArrayInt * - a pointer to DataArrayInt that the caller is to
3067  *          delete using decrRef() as it is no more needed.
3068  * \sa MEDFileUMesh::extractFamilyFieldOnGeoType
3069  */
3070 DataArrayInt *MEDFileUMesh::extractNumberFieldOnGeoType(INTERP_KERNEL::NormalizedCellType gt) const
3071 {
3072   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
3073   int lev=(int)cm.getDimension()-getMeshDimension();
3074   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(lev));
3075   return sp->extractNumberFieldOnGeoType(gt);
3076 }
3077
3078 const MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt) const
3079 {
3080   if(meshDimRelToMaxExt==1)
3081     throw INTERP_KERNEL::Exception("Dimension request is invalid : asking for node level (1) !");
3082   if(meshDimRelToMaxExt>1)
3083     throw INTERP_KERNEL::Exception("Dimension request is invalid (>1) !");
3084   int tracucedRk=-meshDimRelToMaxExt;
3085   if(tracucedRk>=(int)_ms.size())
3086     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
3087   if((const MEDFileUMeshSplitL1 *)_ms[tracucedRk]==0)
3088     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3089   return _ms[tracucedRk];
3090 }
3091
3092 MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt)
3093 {
3094    if(meshDimRelToMaxExt==1)
3095     throw INTERP_KERNEL::Exception("Dimension request is invalid : asking for node level (1) !");
3096   if(meshDimRelToMaxExt>1)
3097     throw INTERP_KERNEL::Exception("Dimension request is invalid (>1) !");
3098   int tracucedRk=-meshDimRelToMaxExt;
3099   if(tracucedRk>=(int)_ms.size())
3100     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
3101   if((const MEDFileUMeshSplitL1 *)_ms[tracucedRk]==0)
3102     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3103   return _ms[tracucedRk];
3104 }
3105
3106 void MEDFileUMesh::checkMeshDimCoherency(int meshDim, int meshDimRelToMax) const
3107 {
3108   if(-meshDimRelToMax>=(int)_ms.size())
3109     throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMeshDimCoherency : The meshdim of mesh is not managed by 'this' !");
3110   int i=0;
3111   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,i++)
3112     {
3113       if(((const MEDFileUMeshSplitL1*) (*it))!=0)
3114         {
3115           int ref=(*it)->getMeshDimension();
3116           if(ref+i!=meshDim-meshDimRelToMax)
3117             throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMeshDimCoherency : no coherency between levels !");
3118         }
3119     }
3120 }
3121
3122 /*!
3123  * Sets the node coordinates array of \a this mesh.
3124  *  \param [in] coords - the new node coordinates array.
3125  *  \throw If \a coords == \c NULL.
3126  */
3127 void MEDFileUMesh::setCoords(DataArrayDouble *coords)
3128 {
3129   if(!coords)
3130     throw INTERP_KERNEL::Exception("MEDFileUMesh::setCoords : null pointer in input !");
3131   coords->checkAllocated();
3132   int nbOfTuples=coords->getNumberOfTuples();
3133   _coords=coords;
3134   coords->incrRef();
3135   _fam_coords=DataArrayInt::New();
3136   _fam_coords->alloc(nbOfTuples,1);
3137   _fam_coords->fillWithZero();
3138   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
3139     if((MEDFileUMeshSplitL1 *)(*it))
3140       (*it)->setCoords(coords);
3141 }
3142
3143 /*!
3144  * Removes all groups of a given dimension in \a this mesh.
3145  *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
3146  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3147  */
3148 void MEDFileUMesh::eraseGroupsAtLevel(int meshDimRelToMaxExt)
3149 {
3150   if(meshDimRelToMaxExt==1)
3151     {
3152       if((DataArrayInt *)_fam_coords)
3153         _fam_coords->fillWithZero();
3154       return ;
3155     }
3156   MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3157   l1->eraseFamilyField();
3158   optimizeFamilies();
3159 }
3160
3161 /*!
3162  * Removes all families with ids not present in the family fields of \a this mesh.
3163  */
3164 void MEDFileUMesh::optimizeFamilies()
3165 {
3166   std::vector<int> levs=getNonEmptyLevelsExt();
3167   std::set<int> allFamsIds;
3168   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
3169     {
3170       const DataArrayInt *ffield=getFamilyFieldAtLevel(*it);
3171       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=ffield->getDifferentValues();
3172       std::set<int> res;
3173       std::set_union(ids->begin(),ids->end(),allFamsIds.begin(),allFamsIds.end(),std::inserter(res,res.begin()));
3174       allFamsIds=res;
3175     }
3176   std::set<std::string> famNamesToKill;
3177   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
3178     {
3179       if(allFamsIds.find((*it).second)!=allFamsIds.end())
3180         famNamesToKill.insert((*it).first);
3181     }
3182   for(std::set<std::string>::const_iterator it=famNamesToKill.begin();it!=famNamesToKill.end();it++)
3183     _families.erase(*it);
3184   std::vector<std::string> grpNamesToKill;
3185   for(std::map<std::string, std::vector<std::string> >::iterator it=_groups.begin();it!=_groups.end();it++)
3186     {
3187       std::vector<std::string> tmp;
3188       for(std::vector<std::string>::const_iterator it2=(*it).second.begin();it2!=(*it).second.end();it2++)
3189         {
3190           if(famNamesToKill.find(*it2)==famNamesToKill.end())
3191             tmp.push_back(*it2);
3192         }
3193       if(!tmp.empty())
3194         (*it).second=tmp;
3195       else
3196         tmp.push_back((*it).first);
3197     }
3198   for(std::vector<std::string>::const_iterator it=grpNamesToKill.begin();it!=grpNamesToKill.end();it++)
3199     _groups.erase(*it);
3200 }
3201
3202 void MEDFileUMesh::duplicateNodesOnM1Group(const std::string& grpNameM1, DataArrayInt *&nodesDuplicated, DataArrayInt *&cellsModified, DataArrayInt *&cellsNotModified)
3203 {
3204   std::vector<int> levs=getNonEmptyLevels();
3205   if(std::find(levs.begin(),levs.end(),0)==levs.end() || std::find(levs.begin(),levs.end(),-1)==levs.end())
3206     throw INTERP_KERNEL::Exception("MEDFileUMesh::duplicateNodesOnM1Group : This method works only for mesh definied on level 0 and -1 !");
3207   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0=getMeshAtLevel(0);
3208   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1=getMeshAtLevel(-1);
3209   int nbNodes=m0->getNumberOfNodes();
3210   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m11=getGroup(-1,grpNameM1);
3211   DataArrayInt *tmp00=0,*tmp11=0,*tmp22=0;
3212   m0->findNodesToDuplicate(*m11,tmp00,tmp11,tmp22);
3213   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodeIdsToDuplicate(tmp00);
3214   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0(tmp11);
3215   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1(tmp22);
3216   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp0=static_cast<MEDCouplingUMesh *>(m0->buildPartOfMySelf(cellsToModifyConn0->begin(),cellsToModifyConn0->end(),true));
3217   // node renumbering of cells in m1 impacted by duplication of node but not in group 'grpNameM1' on level -1
3218   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descTmp0=DataArrayInt::New(),descITmp0=DataArrayInt::New(),revDescTmp0=DataArrayInt::New(),revDescITmp0=DataArrayInt::New();
3219   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp0Desc=tmp0->buildDescendingConnectivity(descTmp0,descITmp0,revDescTmp0,revDescITmp0);
3220   descTmp0=0; descITmp0=0; revDescTmp0=0; revDescITmp0=0;
3221   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsInM1ToRenumW2=tmp0Desc->getCellIdsLyingOnNodes(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),false);
3222   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cellsInM1ToRenumW3=static_cast<MEDCouplingUMesh *>(tmp0Desc->buildPartOfMySelf(cellsInM1ToRenumW2->begin(),cellsInM1ToRenumW2->end(),true));
3223   DataArrayInt *cellsInM1ToRenumW4Tmp=0;
3224   m1->areCellsIncludedIn(cellsInM1ToRenumW3,2,cellsInM1ToRenumW4Tmp);
3225   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsInM1ToRenumW4(cellsInM1ToRenumW4Tmp);
3226   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsInM1ToRenumW5=cellsInM1ToRenumW4->getIdsInRange(0,m1->getNumberOfCells());
3227   cellsInM1ToRenumW5->transformWithIndArr(cellsInM1ToRenumW4->begin(),cellsInM1ToRenumW4->end());
3228   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> grpIds=getGroupArr(-1,grpNameM1);
3229   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsInM1ToRenum=cellsInM1ToRenumW5->buildSubstraction(grpIds);
3230   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Part=static_cast<MEDCouplingUMesh *>(m1->buildPartOfMySelf(cellsInM1ToRenum->begin(),cellsInM1ToRenum->end(),true));
3231   m1Part->duplicateNodesInConn(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),nbNodes);
3232   m1->setPartOfMySelf(cellsInM1ToRenum->begin(),cellsInM1ToRenum->end(),*m1Part);
3233   // end of node renumbering of cells in m1 impacted by duplication of node but not in group of level -1 'grpNameM1'
3234   tmp0->duplicateNodes(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end());
3235   m0->setCoords(tmp0->getCoords());
3236   m0->setPartOfMySelf(cellsToModifyConn0->begin(),cellsToModifyConn0->end(),*tmp0);
3237   m1->setCoords(m0->getCoords());
3238   _coords=m0->getCoords(); _coords->incrRef();
3239   // duplication of cells in group 'grpNameM1' on level -1
3240   m11->duplicateNodesInConn(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),nbNodes); m11->setCoords(m0->getCoords());
3241   std::vector<const MEDCouplingUMesh *> v(2); v[0]=m1; v[1]=m11;
3242   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> newm1=MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(v,tmp00,tmp11);
3243   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> szOfCellGrpOfSameType(tmp00);
3244   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idInMsOfCellGrpOfSameType(tmp11);
3245   //
3246   newm1->setName(getName());
3247   const DataArrayInt *fam=getFamilyFieldAtLevel(-1);
3248   if(!fam)
3249     throw INTERP_KERNEL::Exception("MEDFileUMesh::duplicateNodesOnM1Group : internal problem !");
3250   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newFam=DataArrayInt::New();
3251   newFam->alloc(newm1->getNumberOfCells(),1);
3252   int idd=getMaxFamilyId()+1;
3253   int globStart=0,start=0,end,globEnd;
3254   int nbOfChunks=szOfCellGrpOfSameType->getNumberOfTuples();
3255   for(int i=0;i<nbOfChunks;i++)
3256     {
3257       globEnd=globStart+szOfCellGrpOfSameType->getIJ(i,0);
3258       if(idInMsOfCellGrpOfSameType->getIJ(i,0)==0)
3259         {
3260           end=start+szOfCellGrpOfSameType->getIJ(i,0);
3261           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=fam->selectByTupleId2(start,end,1);
3262           newFam->setPartOfValues1(part,globStart,globEnd,1,0,1,1,true);
3263           start=end;
3264         }
3265       else
3266         {
3267           newFam->setPartOfValuesSimple1(idd,globStart,globEnd,1,0,1,1);
3268         }
3269       globStart=globEnd;
3270     }
3271   newm1->setCoords(getCoords());
3272   setMeshAtLevel(-1,newm1);
3273   setFamilyFieldArr(-1,newFam);
3274   std::string grpName2(grpNameM1); grpName2+="_dup";
3275   addFamily(grpName2,idd);
3276   addFamilyOnGrp(grpName2,grpName2);
3277   //
3278   fam=_fam_coords;
3279   if(fam)
3280     {
3281       int newNbOfNodes=getCoords()->getNumberOfTuples();
3282       newFam=DataArrayInt::New(); newFam->alloc(newNbOfNodes,1);
3283       newFam->setPartOfValues1(fam,0,nbNodes,1,0,1,1,true);
3284       newFam->setPartOfValuesSimple1(0,nbNodes,newNbOfNodes,1,0,1,1);
3285       _fam_coords=newFam;
3286     }
3287   nodesDuplicated=nodeIdsToDuplicate.retn();
3288   cellsModified=cellsToModifyConn0.retn();
3289   cellsNotModified=cellsToModifyConn1.retn();
3290 }
3291
3292 /*!
3293  * \param [out] oldCode retrieves the distribution of types before the call if true is returned
3294  * \param [out] newCode etrieves the distribution of types after the call if true is returned
3295  * \param [out] o2nRenumCell tells for **all levels** the old 2 new renumbering of cells.
3296  * 
3297  * \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.
3298  * 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.
3299  */
3300 bool MEDFileUMesh::unPolyze(std::vector<int>& oldCode, std::vector<int>& newCode, DataArrayInt *& o2nRenumCell)
3301 {
3302   o2nRenumCell=0; oldCode.clear(); newCode.clear();
3303   std::vector<int> levs=getNonEmptyLevels();
3304   bool ret=false;
3305   std::vector< const DataArrayInt* > renumCellsSplited;//same than memorySaverIfThrow
3306   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > memorySaverIfThrow;//same than renumCellsSplited only in case of throw
3307   int start=0;
3308   int end=0;
3309   for(std::vector<int>::reverse_iterator it=levs.rbegin();it!=levs.rend();it++)
3310     {
3311       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=getMeshAtLevel(*it);
3312       std::vector<int> code1=m->getDistributionOfTypes();
3313       end=PutInThirdComponentOfCodeOffset(code1,start);
3314       oldCode.insert(oldCode.end(),code1.begin(),code1.end());
3315       bool hasChanged=m->unPolyze();
3316       DataArrayInt *fake=0;
3317       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nCellsPart=m->getLevArrPerCellTypes(MEDCouplingUMesh::MEDMEM_ORDER,
3318                                                                                            MEDCouplingUMesh::MEDMEM_ORDER+MEDCouplingUMesh::N_MEDMEM_ORDER,fake);
3319       fake->decrRef();
3320       renumCellsSplited.push_back(o2nCellsPart); memorySaverIfThrow.push_back(o2nCellsPart);
3321       if(hasChanged)
3322         {
3323           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nCellsPart2=o2nCellsPart->buildPermArrPerLevel();
3324           m->renumberCells(o2nCellsPart2->getConstPointer(),false);
3325           ret=true;
3326           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famField2,numField2;
3327           const DataArrayInt *famField=getFamilyFieldAtLevel(*it); if(famField) { famField->incrRef(); famField2=const_cast<DataArrayInt *>(famField); }
3328           const DataArrayInt *numField=getNumberFieldAtLevel(*it); if(numField) { numField->incrRef(); numField2=const_cast<DataArrayInt *>(numField); }
3329           setMeshAtLevel(*it,m);
3330           std::vector<int> code2=m->getDistributionOfTypes();
3331           end=PutInThirdComponentOfCodeOffset(code2,start);
3332           newCode.insert(newCode.end(),code2.begin(),code2.end());
3333           //
3334           if(o2nCellsPart2->isIdentity())
3335             continue;
3336           if(famField)
3337             {
3338               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newFamField=famField->renumber(o2nCellsPart2->getConstPointer());
3339               setFamilyFieldArr(*it,newFamField);
3340             }
3341           if(numField)
3342             {
3343               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newNumField=numField->renumber(o2nCellsPart2->getConstPointer());
3344               setRenumFieldArr(*it,newNumField);
3345             }
3346         }
3347       else
3348         {
3349           newCode.insert(newCode.end(),code1.begin(),code1.end());
3350         }
3351       start=end;
3352     }
3353   if(ret)
3354     {
3355       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renumCells=DataArrayInt::Aggregate(renumCellsSplited);
3356       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRenumCellRet=renumCells->buildPermArrPerLevel();
3357       o2nRenumCell=o2nRenumCellRet.retn();
3358     }
3359   return ret;
3360 }
3361
3362 struct MEDLoaderAccVisit1
3363 {
3364   MEDLoaderAccVisit1():_new_nb_of_nodes(0) { }
3365   int operator()(bool val) { return val?_new_nb_of_nodes++:-1; }
3366   int _new_nb_of_nodes;
3367 };
3368
3369 /*!
3370  * 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.
3371  * The maximum value stored in returned array is the number of nodes of \a this minus 1 after call of this method.
3372  * The size of returned array is the number of nodes of the old (previous to the call of this method) number of nodes.
3373  * -1 values in returned array means that the corresponding old node is no more used.
3374  *
3375  * \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
3376  *         is modified in \a this.
3377  * \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
3378  *  set coordinates.
3379  */
3380 DataArrayInt *MEDFileUMesh::zipCoords()
3381 {
3382   const DataArrayDouble *coo=getCoords();
3383   if(!coo)
3384     throw INTERP_KERNEL::Exception("MEDFileUMesh::zipCoords : no coordinates set in this !");
3385   int nbOfNodes=coo->getNumberOfTuples();
3386   std::vector<bool> nodeIdsInUse(nbOfNodes,false);
3387   std::vector<int> neLevs=getNonEmptyLevels();
3388   for(std::vector<int>::const_iterator lev=neLevs.begin();lev!=neLevs.end();lev++)
3389     {
3390       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=getMeshAtLevel(*lev);
3391       m->computeNodeIdsAlg(nodeIdsInUse);
3392     }
3393   int nbrOfNodesInUse=(int)std::count(nodeIdsInUse.begin(),nodeIdsInUse.end(),true);
3394   if(nbrOfNodesInUse==nbOfNodes)
3395     return 0;
3396   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodes,1);
3397   std::transform(nodeIdsInUse.begin(),nodeIdsInUse.end(),ret->getPointer(),MEDLoaderAccVisit1());
3398   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2=ret->invertArrayO2N2N2OBis(nbrOfNodesInUse);
3399   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->selectByTupleIdSafe(ret2->begin(),ret2->end());
3400   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newFamCoords;
3401   MEDCouplingAutoRefCountObjectPtr<DataArrayAsciiChar> newNameCoords;
3402   if((const DataArrayInt *)_fam_coords)
3403     newFamCoords=_fam_coords->selectByTupleIdSafe(ret2->begin(),ret2->end());
3404   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newNumCoords;
3405   if((const DataArrayInt *)_num_coords)
3406     newNumCoords=_num_coords->selectByTupleIdSafe(ret2->begin(),ret2->end());
3407   if((const DataArrayAsciiChar *)_name_coords)
3408     newNameCoords=static_cast<DataArrayAsciiChar *>(_name_coords->selectByTupleIdSafe(ret2->begin(),ret2->end()));
3409   _coords=newCoords; _fam_coords=newFamCoords; _num_coords=newNumCoords; _name_coords=newNameCoords; _rev_num_coords=0;
3410   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
3411     {
3412       if((MEDFileUMeshSplitL1*)*it)
3413         (*it)->renumberNodesInConn(ret->begin());
3414     }
3415   return ret.retn();
3416 }
3417
3418 /*!
3419  * Adds a group of nodes to \a this mesh.
3420  *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
3421  *          The ids should be sorted and different each other (MED file norm).
3422  *  \throw If the node coordinates array is not set.
3423  *  \throw If \a ids == \c NULL.
3424  *  \throw If \a ids->getName() == "".
3425  *  \throw If \a ids does not respect the MED file norm.
3426  *  \throw If a group with name \a ids->getName() already exists.
3427  */
3428 void MEDFileUMesh::addNodeGroup(const DataArrayInt *ids)
3429 {
3430   const DataArrayDouble *coords=_coords;
3431   if(!coords)
3432     throw INTERP_KERNEL::Exception("MEDFileUMesh::addNodeGroup : no coords set !");
3433   int nbOfNodes=coords->getNumberOfTuples();
3434   if(!((DataArrayInt *)_fam_coords))
3435     { _fam_coords=DataArrayInt::New(); _fam_coords->alloc(nbOfNodes,1); _fam_coords->fillWithZero(); }
3436   //
3437   addGroupUnderground(true,ids,_fam_coords);
3438 }
3439
3440 /*!
3441  * Adds a group of nodes/cells/faces/edges to \a this mesh.
3442  *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
3443  *          The ids should be sorted and different each other (MED file norm).
3444  *  \throw If the node coordinates array is not set.
3445  *  \throw If \a ids == \c NULL.
3446  *  \throw If \a ids->getName() == "".
3447  *  \throw If \a ids does not respect the MED file norm.
3448  *  \throw If a group with name \a ids->getName() already exists.
3449  */
3450 void MEDFileUMesh::addGroup(int meshDimRelToMaxExt, const DataArrayInt *ids)
3451 {
3452   std::vector<int> levs=getNonEmptyLevelsExt();
3453   if(std::find(levs.begin(),levs.end(),meshDimRelToMaxExt)==levs.end())
3454     { 
3455       std::ostringstream oss; oss << "MEDFileUMesh::addGroup : level " << meshDimRelToMaxExt << " not available ! Should be in ";
3456       std::copy(levs.begin(),levs.end(),std::ostream_iterator<int>(oss," ")); oss << " !"; throw INTERP_KERNEL::Exception(oss.str().c_str());
3457     }
3458   if(meshDimRelToMaxExt==1)
3459     { addNodeGroup(ids); return ; }
3460   MEDFileUMeshSplitL1 *lev=getMeshAtLevSafe(meshDimRelToMaxExt);
3461   DataArrayInt *fam=lev->getOrCreateAndGetFamilyField();
3462   addGroupUnderground(false,ids,fam);
3463 }
3464
3465 /*!
3466  * \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).
3467  * \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)
3468  */
3469 void MEDFileUMesh::addGroupUnderground(bool isNodeGroup, const DataArrayInt *ids, DataArrayInt *famArr)
3470 {
3471   if(!ids)
3472     throw INTERP_KERNEL::Exception("MEDFileUMesh::addGroup : NULL pointer in input !");
3473   std::string grpName(ids->getName());
3474   if(grpName.empty())
3475     throw INTERP_KERNEL::Exception("MEDFileUMesh::addGroup : empty group name ! MED file format do not accept empty group name !");
3476   ids->checkStrictlyMonotonic(true);
3477   famArr->incrRef(); MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famArrTmp(famArr);
3478   std::vector<std::string> grpsNames=getGroupsNames();
3479   if(std::find(grpsNames.begin(),grpsNames.end(),grpName)!=grpsNames.end())
3480     {
3481       std::ostringstream oss; oss << "MEDFileUMesh::addGroup : Group with name \"" << grpName << "\" already exists ! Destroy it before calling this method !";
3482       throw INTERP_KERNEL::Exception(oss.str().c_str());
3483     }
3484   std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > allFamIds=getAllNonNullFamilyIds();
3485   allFamIds.erase(std::find(allFamIds.begin(),allFamIds.end(),famArrTmp));
3486   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famIds=famArr->selectByTupleIdSafe(ids->begin(),ids->end());
3487   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffFamIds=famIds->getDifferentValues();
3488   std::vector<int> familyIds;
3489   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerfamiliyIds;
3490   int maxVal=getTheMaxAbsFamilyId()+1;
3491   std::map<std::string,int> families(_families);
3492   std::map<std::string, std::vector<std::string> > groups(_groups);
3493   std::vector<std::string> fams;
3494   bool created(false);
3495   for(const int *famId=diffFamIds->begin();famId!=diffFamIds->end();famId++)
3496     {
3497       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2Tmp=famIds->getIdsEqual(*famId);
3498       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=ids->selectByTupleId(ids2Tmp->begin(),ids2Tmp->end());
3499       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids1=famArr->getIdsEqual(*famId);
3500       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(ids1->buildSubstractionOptimized(ids2));
3501       if(ret0->empty())
3502         {
3503           bool isFamPresent=false;
3504           for(std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::const_iterator itl=allFamIds.begin();itl!=allFamIds.end() && !isFamPresent;itl++)
3505             isFamPresent=(*itl)->presenceOfValue(*famId);
3506           if(!isFamPresent)
3507             { familyIds.push_back(*famId); idsPerfamiliyIds.push_back(ret0); fams.push_back(FindOrCreateAndGiveFamilyWithId(families,*famId,created)); } // adding *famId in grp
3508           else
3509             {
3510               familyIds.push_back(isNodeGroup?maxVal:-maxVal); idsPerfamiliyIds.push_back(ids2);
3511               std::string locFamName=FindOrCreateAndGiveFamilyWithId(families,isNodeGroup?maxVal:-maxVal,created);
3512               fams.push_back(locFamName);
3513               if(existsFamily(*famId))
3514                 {
3515                   std::string locFamName2=getFamilyNameGivenId(*famId); std::vector<std::string> v(2); v[0]=locFamName2; v[1]=locFamName;
3516                   ChangeAllGroupsContainingFamily(groups,getFamilyNameGivenId(*famId),v);
3517                 }
3518               maxVal++;
3519             } // modifying all other groups on *famId to lie on maxVal and lie the grp on maxVal
3520         }
3521       else
3522         {
3523           familyIds.push_back(isNodeGroup?maxVal:-maxVal); idsPerfamiliyIds.push_back(ret0); // modifying all other groups on *famId to lie on maxVal and on maxVal+1
3524           familyIds.push_back(isNodeGroup?maxVal+1:-maxVal-1); idsPerfamiliyIds.push_back(ids2);//grp lie only on maxVal+1
3525           std::string n2(FindOrCreateAndGiveFamilyWithId(families,isNodeGroup?maxVal+1:-maxVal-1,created)); fams.push_back(n2);
3526           if(existsFamily(*famId))
3527             {
3528               std::string n1(FindOrCreateAndGiveFamilyWithId(families,isNodeGroup?maxVal:-maxVal,created)); std::vector<std::string> v(2); v[0]=n1; v[1]=n2;
3529               ChangeAllGroupsContainingFamily(groups,getFamilyNameGivenId(*famId),v);
3530             }
3531           maxVal+=2;
3532         }
3533     }
3534   for(std::size_t i=0;i<familyIds.size();i++)
3535     {
3536       DataArrayInt *da=idsPerfamiliyIds[i];
3537       famArr->setPartOfValuesSimple3(familyIds[i],da->begin(),da->end(),0,1,1);
3538     }
3539   _families=families;
3540   _groups=groups;
3541   _groups[grpName]=fams;
3542 }
3543
3544 /*!
3545  * Changes a name of a family specified by its id.
3546  *  \param [in] id - the id of the family of interest.
3547  *  \param [in] newFamName - the new family name.
3548  *  \throw If no family with the given \a id exists.
3549  */
3550 void MEDFileUMesh::setFamilyNameAttachedOnId(int id, const std::string& newFamName)
3551 {
3552   std::string oldName=getFamilyNameGivenId(id);
3553   _families.erase(oldName);
3554   _families[newFamName]=id;
3555 }
3556
3557 /*!
3558  * Removes a mesh of a given dimension.
3559  *  \param [in] meshDimRelToMax - the relative dimension of interest.
3560  *  \throw If there is no mesh at level \a meshDimRelToMax in \a this mesh.
3561  */
3562 void MEDFileUMesh::removeMeshAtLevel(int meshDimRelToMax)
3563 {
3564   std::vector<int> levSet=getNonEmptyLevels();
3565   std::vector<int>::const_iterator it=std::find(levSet.begin(),levSet.end(),meshDimRelToMax);
3566   if(it==levSet.end())
3567     throw INTERP_KERNEL::Exception("MEDFileUMesh::removeMeshAtLevel : the requested level is not existing !");
3568   int pos=(-meshDimRelToMax);
3569   _ms[pos]=0;
3570 }
3571
3572 /*!
3573  * Sets a new MEDCoupling1GTUMesh at a given level in \a this mesh.
3574  *  \param [in] meshDimRelToMax - a relative level to set the mesh at.
3575  *  \param [in] m - the new mesh to set.
3576  *  \throw If the name or the description of \a this mesh and \a m are not empty and are
3577  *         different. 
3578  *  \throw If the node coordinates array is set \a this in mesh and \a m refers to
3579  *         another node coordinates array.
3580  *  \throw If the mesh dimension of \a m does not correspond to \a meshDimRelToMax or
3581  *         to the existing meshes of other levels of \a this mesh.
3582  */
3583 void MEDFileUMesh::setMeshAtLevel(int meshDimRelToMax, MEDCoupling1GTUMesh *m)
3584 {
3585   MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> elt(new MEDFileUMeshSplitL1(m));
3586   checkAndGiveEntryInSplitL1(meshDimRelToMax,m)=elt;
3587 }
3588
3589 /*!
3590  * Sets a new MEDCouplingUMesh at a given level in \a this mesh.
3591  *  \param [in] meshDimRelToMax - a relative level to set the mesh at.
3592  *  \param [in] m - the new mesh to set.
3593  *  \param [in] newOrOld - if \c true, cells in \a m are sorted by type to be ready for 
3594  *         writing \a this mesh in a MED file.
3595  *  \throw If the name or the description of \a this mesh and \a m are not empty and are
3596  *         different. 
3597  *  \throw If the node coordinates array is set \a this in mesh and \a m refers to
3598  *         another node coordinates array.
3599  *  \throw If the mesh dimension of \a m does not correspond to \a meshDimRelToMax or
3600  *         to the existing meshes of other levels of \a this mesh.
3601  */
3602 void MEDFileUMesh::setMeshAtLevel(int meshDimRelToMax, MEDCouplingUMesh *m, bool newOrOld)
3603 {
3604   MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> elt(new MEDFileUMeshSplitL1(m,newOrOld));
3605   checkAndGiveEntryInSplitL1(meshDimRelToMax,m)=elt;
3606 }
3607
3608 MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1>& MEDFileUMesh::checkAndGiveEntryInSplitL1(int meshDimRelToMax, MEDCouplingPointSet *m)
3609 {
3610   dealWithTinyInfo(m);
3611   std::vector<int> levSet=getNonEmptyLevels();
3612   if(std::find(levSet.begin(),levSet.end(),meshDimRelToMax)==levSet.end())
3613     {
3614       if((DataArrayDouble *)_coords==0)
3615         {
3616           DataArrayDouble *c=m->getCoords();
3617           if(c)
3618             c->incrRef();
3619           _coords=c;
3620         }
3621       if(m->getCoords()!=_coords)
3622         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshAtLevel : Invalid Given Mesh ! The coordinates are not the same ! try to use tryToShareSameCoords !");
3623       int sz=(-meshDimRelToMax)+1;
3624       if(sz>=(int)_ms.size())
3625         _ms.resize(sz);
3626       checkMeshDimCoherency(m->getMeshDimension(),meshDimRelToMax);
3627       return _ms[sz-1];
3628     }
3629   else
3630     return _ms[-meshDimRelToMax];
3631 }
3632
3633 /*!
3634  * This method allows to set at once the content of different levels in \a this.
3635  * This method is equivalent to a series of call to MEDFileUMesh::setMeshAtLevel.
3636  *
3637  * \param [in] ms - List of unstructured meshes lying on the same coordinates and having different mesh dimesnion.
3638  * \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.
3639  *                     If false, an exception ois thrown. If true the mesh is reordered automatically. It is highly recommanded to let this parameter to false.
3640  *
3641  * \throw If \a there is a null pointer in \a ms.
3642  * \sa MEDFileUMesh::setMeshAtLevel
3643  */
3644 void MEDFileUMesh::setMeshes(const std::vector<const MEDCouplingUMesh *>& ms, bool renum)
3645 {
3646   if(ms.empty())
3647     return ;
3648   const MEDCouplingUMesh *mRef=ms[0];
3649   if(!mRef)
3650     throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : null instance in the first element of input meshes !");
3651   std::string name(mRef->getName());
3652   const DataArrayDouble *coo(mRef->getCoords());
3653   std::set<int> s;
3654   int zeDim=-1;
3655   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
3656     {
3657       const MEDCouplingUMesh *cur(*it);
3658       if(!cur)
3659         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : null instance in input vector of meshes !");
3660       if(coo!=cur->getCoords())
3661         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : The input meshes do not share the same coordinates !");
3662       int mdim=cur->getMeshDimension();
3663       zeDim=std::max(zeDim,mdim);
3664       if(s.find(mdim)!=s.end())
3665         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : The input meshes must share the same coordinates pointer, and should have different mesh dimension each other !");
3666     }
3667   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
3668     {
3669       int mdim=(*it)->getMeshDimension();
3670       setName((*it)->getName());
3671       setMeshAtLevel(mdim-zeDim,const_cast<MEDCouplingUMesh *>(*it),renum);
3672     }
3673   setName(name);
3674 }
3675
3676 /*!
3677  * Creates one MEDCouplingUMesh at a given level in \a this mesh from a sequence of
3678  * meshes each representing a group, and creates corresponding groups in \a this mesh.
3679  * The given meshes must share the same node coordinates array.
3680  *  \param [in] meshDimRelToMax - the relative dimension to create the mesh and groups at.
3681  *  \param [in] ms - the sequence of meshes. Each mesh in \a ms represents a group to
3682  *          create in \a this mesh.
3683  *  \throw If \a ms is empty.
3684  *  \throw If dimension of meshes in \a ms does not correspond to \a meshDimRelToMax or
3685  *         to the existing meshes of other levels of \a this mesh.
3686  *  \throw If the meshes in \a ms do not share the same node coordinates array.
3687  *  \throw If the node coordinates array of \a this mesh (if any) is not the same as that
3688  *         of the given meshes.
3689  *  \throw If \a ms[ i ] is not well defined (MEDCouplingUMesh::checkCoherency()).
3690  *  \throw If names of some meshes in \a ms are equal.
3691  *  \throw If \a ms includes a mesh with an empty name.
3692  */
3693 void MEDFileUMesh::setGroupsFromScratch(int meshDimRelToMax, const std::vector<const MEDCouplingUMesh *>& ms, bool renum)
3694 {
3695   if(ms.empty())
3696     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsFromScratch : expecting a non empty vector !");
3697   int sz=(-meshDimRelToMax)+1;
3698   if(sz>=(int)_ms.size())
3699     _ms.resize(sz);
3700   checkMeshDimCoherency(ms[0]->getMeshDimension(),meshDimRelToMax);
3701   DataArrayDouble *coo=checkMultiMesh(ms);
3702   if((DataArrayDouble *)_coords==0)
3703     {
3704       coo->incrRef();
3705       _coords=coo;
3706     }
3707   else
3708     if((DataArrayDouble *)_coords!=coo)
3709       throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsFromScratch : coordinates mismatches !");
3710   std::vector<DataArrayInt *> corr;
3711   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MEDCouplingUMesh::FuseUMeshesOnSameCoords(ms,_zipconn_pol,corr);
3712   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > corr3(corr.begin(),corr.end());
3713   setMeshAtLevel(meshDimRelToMax,m,renum);
3714   std::vector<const DataArrayInt *> corr2(corr.begin(),corr.end());
3715   setGroupsAtLevel(meshDimRelToMax,corr2,true);
3716 }
3717
3718 /*!
3719  * Creates groups at a given level in \a this mesh from a sequence of
3720  * meshes each representing a group.
3721  * The given meshes must share the same node coordinates array.
3722  *  \param [in] meshDimRelToMax - the relative dimension to create the groups at.
3723  *  \param [in] ms - the sequence of meshes. Each mesh in \a ms represents a group to
3724  *         create in \a this mesh.
3725  *  \param [in] renum - if \c true, then the optional numbers of entities are taken into
3726  *         account. 
3727  *  \throw If \a ms is empty.
3728  *  \throw If dimension of meshes in \a ms does not correspond to \a meshDimRelToMax or
3729  *         to the existing meshes of other levels of \a this mesh.
3730  *  \throw If the meshes in \a ms do not share the same node coordinates array.
3731  *  \throw If the node coordinates array of \a this mesh (if any) is not the same as that
3732  *         of the given meshes.
3733  *  \throw If \a ms[ i ] is not well defined (MEDCouplingUMesh::checkCoherency()).
3734  *  \throw If names of some meshes in \a ms are equal.
3735  *  \throw If \a ms includes a mesh with an empty name.
3736  */
3737 void MEDFileUMesh::setGroupsOnSetMesh(int meshDimRelToMax, const std::vector<const MEDCouplingUMesh *>& ms, bool renum)
3738 {
3739   if(ms.empty())
3740     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsOnSetMesh : expecting a non empty vector !");
3741   int sz=(-meshDimRelToMax)+1;
3742   if(sz>=(int)_ms.size())
3743     _ms.resize(sz);
3744   checkMeshDimCoherency(ms[0]->getMeshDimension(),meshDimRelToMax);
3745   DataArrayDouble *coo=checkMultiMesh(ms);
3746   if((DataArrayDouble *)_coords==0)
3747     {
3748       coo->incrRef();
3749       _coords=coo;
3750     }
3751   else
3752     if((DataArrayDouble *)_coords!=coo)
3753       throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsOnSetMesh : coordinates mismatches !");
3754   MEDCouplingUMesh *m=getMeshAtLevel(meshDimRelToMax,renum);
3755   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > corr(ms.size());
3756   int i=0;
3757   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++,i++)
3758     {
3759       DataArrayInt *arr=0;
3760       bool test=m->areCellsIncludedIn(*it,_zipconn_pol,arr);
3761       corr[i]=arr;
3762       if(!test)
3763         {
3764           std::ostringstream oss; oss << "MEDFileUMesh::setGroupsOnSetMesh : mesh #" << i << " is not part of whole mesh !";
3765           throw INTERP_KERNEL::Exception(oss.str().c_str());
3766         }
3767     }
3768   std::vector<const DataArrayInt *> corr2(corr.begin(),corr.end());
3769   setGroupsAtLevel(meshDimRelToMax,corr2,renum);
3770 }
3771
3772 DataArrayDouble *MEDFileUMesh::checkMultiMesh(const std::vector<const MEDCouplingUMesh *>& ms) const
3773 {
3774   const DataArrayDouble *ret=ms[0]->getCoords();
3775   int mdim=ms[0]->getMeshDimension();
3776   for(unsigned int i=1;i<ms.size();i++)
3777     {
3778       ms[i]->checkCoherency();
3779       if(ms[i]->getCoords()!=ret)
3780         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMultiMesh : meshes must share the same coords !");
3781       if(ms[i]->getMeshDimension()!=mdim)
3782         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMultiMesh : meshes have not same mesh dimension !");
3783     }
3784   return const_cast<DataArrayDouble *>(ret);
3785 }
3786
3787 /*!
3788  * Sets the family field of a given relative dimension.
3789  *  \param [in] meshDimRelToMaxExt - the relative dimension of entities for which
3790  *          the family field is set.
3791  *  \param [in] famArr - the array of the family field.
3792  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3793  *  \throw If \a famArr has an invalid size.
3794  */
3795 void MEDFileUMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr)
3796 {
3797   if(meshDimRelToMaxExt==1)
3798     {
3799       if(!famArr)
3800         {
3801           _fam_coords=0;
3802           return ;
3803         }
3804       DataArrayDouble *coo(_coords);
3805       if(!coo)
3806         throw INTERP_KERNEL::Exception("MEDFileUMesh::setFamilyFieldArr : the coordinates have not been set !");
3807       famArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),1,"MEDFileUMesh::setFamilyFieldArr : Problem in size of node family arr ! ");
3808       famArr->incrRef();
3809       _fam_coords=famArr;
3810       return ;
3811     }
3812   if(meshDimRelToMaxExt>1)
3813     throw INTERP_KERNEL::Exception("MEDFileUMesh::setFamilyFieldArr : Dimension request is invalid (>1) !");
3814   int traducedRk=-meshDimRelToMaxExt;
3815   if(traducedRk>=(int)_ms.size())
3816     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
3817   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
3818     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3819   return _ms[traducedRk]->setFamilyArr(famArr);
3820 }
3821
3822 /*!
3823  * Sets the optional numbers of mesh entities of a given dimension.
3824  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
3825  *  \param [in] renumArr - the array of the numbers.
3826  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3827  *  \throw If \a renumArr has an invalid size.
3828  */
3829 void MEDFileUMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr)
3830 {
3831   if(meshDimRelToMaxExt==1)
3832     {
3833       if(!renumArr)
3834         {
3835           _num_coords=0;
3836           _rev_num_coords=0;
3837           return ;
3838         }
3839       DataArrayDouble *coo(_coords);
3840       if(!coo)
3841         throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumFieldArr : the coordinates have not been set !");
3842       renumArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),1,"MEDFileUMesh::setRenumArr : Problem in size of node numbering arr ! ");
3843       renumArr->incrRef();
3844       _num_coords=renumArr;
3845       computeRevNum();
3846       return ;
3847     }
3848   if(meshDimRelToMaxExt>1)
3849     throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumArr : Dimension request is invalid (>1) !");
3850   int traducedRk=-meshDimRelToMaxExt;
3851   if(traducedRk>=(int)_ms.size())
3852     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
3853   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
3854     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3855   return _ms[traducedRk]->setRenumArr(renumArr);
3856 }
3857
3858 /*!
3859  * Sets the optional names of mesh entities of a given dimension.
3860  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
3861  *  \param [in] nameArr - the array of the names.
3862  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3863  *  \throw If \a nameArr has an invalid size.
3864  */
3865 void MEDFileUMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr)
3866 {
3867   if(meshDimRelToMaxExt==1)
3868     {
3869       if(!nameArr)
3870         {
3871           _name_coords=0;
3872           return ;
3873         }
3874       DataArrayDouble *coo(_coords);
3875       if(!coo)
3876         throw INTERP_KERNEL::Exception("MEDFileUMesh::setNameFieldAtLevel : the coordinates have not been set !");
3877       nameArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),MED_SNAME_SIZE,"MEDFileUMesh::setNameFieldAtLevel : Problem in size of node numbering arr ! ");
3878       nameArr->incrRef();
3879       _name_coords=nameArr;
3880       return ;
3881     }
3882   if(meshDimRelToMaxExt>1)
3883     throw INTERP_KERNEL::Exception("MEDFileUMesh::setNameFieldAtLevel : Dimension request is invalid (>1) !");
3884   int traducedRk=-meshDimRelToMaxExt;
3885   if(traducedRk>=(int)_ms.size())
3886     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
3887   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
3888     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3889   return _ms[traducedRk]->setNameArr(nameArr);
3890 }
3891
3892 void MEDFileUMesh::synchronizeTinyInfoOnLeaves() const
3893 {
3894   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
3895     if((const MEDFileUMeshSplitL1 *)(*it))
3896       (*it)->synchronizeTinyInfo(*this);
3897 }
3898
3899 /*!
3900  * This method is called by MEDFileMesh::changeFamilyId. It performs only one part of the family id modification.
3901  */
3902 void MEDFileUMesh::changeFamilyIdArr(int oldId, int newId)
3903 {
3904   DataArrayInt *arr=_fam_coords;
3905   if(arr)
3906     arr->changeValue(oldId,newId);
3907   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
3908     {
3909       MEDFileUMeshSplitL1 *sp=(*it);
3910       if(sp)
3911         {
3912           sp->changeFamilyIdArr(oldId,newId);
3913         }
3914     }
3915 }
3916
3917 std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > MEDFileUMesh::getAllNonNullFamilyIds() const
3918 {
3919   std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret;
3920   const DataArrayInt *da(_fam_coords);
3921   if(da)
3922     { da->incrRef(); ret.push_back(MEDCouplingAutoRefCountObjectPtr<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
3923   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
3924     {
3925       const MEDFileUMeshSplitL1 *elt(*it);
3926       if(elt)
3927         {
3928           da=elt->getFamilyField();
3929           if(da)
3930             { da->incrRef(); ret.push_back(MEDCouplingAutoRefCountObjectPtr<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
3931         }
3932     }
3933   return ret;
3934 }
3935
3936 void MEDFileUMesh::computeRevNum() const
3937 {
3938   if((const DataArrayInt *)_num_coords)
3939     {
3940       int pos;
3941       int maxValue=_num_coords->getMaxValue(pos);
3942       _rev_num_coords=_num_coords->invertArrayN2O2O2N(maxValue+1);
3943     }
3944 }
3945
3946 std::size_t MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren() const
3947 {
3948   return MEDFileMesh::getHeapMemorySizeWithoutChildren();
3949 }
3950
3951 std::vector<const BigMemoryObject *> MEDFileStructuredMesh::getDirectChildren() const
3952 {
3953   std::vector<const BigMemoryObject *> ret(MEDFileMesh::getDirectChildren());
3954   if((const DataArrayInt *)_fam_nodes)
3955     ret.push_back((const DataArrayInt *)_fam_nodes);
3956   if((const DataArrayInt *)_num_nodes)
3957     ret.push_back((const DataArrayInt *)_num_nodes);
3958   if((const DataArrayInt *)_fam_cells)
3959     ret.push_back((const DataArrayInt *)_fam_cells);
3960   if((const DataArrayInt *)_num_cells)
3961     ret.push_back((const DataArrayInt *)_num_nodes);
3962   if((const DataArrayInt *)_rev_num_nodes)
3963     ret.push_back((const DataArrayInt *)_rev_num_nodes);
3964   if((const DataArrayInt *)_rev_num_cells)
3965     ret.push_back((const DataArrayInt *)_rev_num_cells);
3966   return ret;
3967 }
3968
3969 int MEDFileStructuredMesh::getMaxAbsFamilyIdInArrays() const
3970 {
3971   int ret=-std::numeric_limits<int>::max(),tmp=-1;
3972   if((const DataArrayInt *)_fam_nodes)
3973     {
3974       int val=_fam_nodes->getMaxValue(tmp);
3975       ret=std::max(ret,std::abs(val));
3976     }
3977   if((const DataArrayInt *)_fam_cells)
3978     {
3979       int val=_fam_cells->getMaxValue(tmp);
3980       ret=std::max(ret,std::abs(val));
3981     }
3982   return ret;
3983 }
3984
3985 int MEDFileStructuredMesh::getMaxFamilyIdInArrays() const
3986 {
3987   int ret=-std::numeric_limits<int>::max(),tmp=-1;
3988   if((const DataArrayInt *)_fam_nodes)
3989     {
3990       int val=_fam_nodes->getMaxValue(tmp);
3991       ret=std::max(ret,val);
3992     }
3993   if((const DataArrayInt *)_fam_cells)
3994     {
3995       int val=_fam_cells->getMaxValue(tmp);
3996       ret=std::max(ret,val);
3997     }
3998   return ret;
3999 }
4000
4001 int MEDFileStructuredMesh::getMinFamilyIdInArrays() const
4002 {
4003   int ret=std::numeric_limits<int>::max(),tmp=-1;
4004   if((const DataArrayInt *)_fam_nodes)
4005     {
4006       int val=_fam_nodes->getMinValue(tmp);
4007       ret=std::min(ret,val);
4008     }
4009   if((const DataArrayInt *)_fam_cells)
4010     {
4011       int val=_fam_cells->getMinValue(tmp);
4012       ret=std::min(ret,val);
4013     }
4014   return ret;
4015 }
4016
4017 bool MEDFileStructuredMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
4018 {
4019   if(!MEDFileMesh::isEqual(other,eps,what))
4020     return false;
4021   const MEDFileStructuredMesh *otherC=dynamic_cast<const  MEDFileStructuredMesh *>(other);
4022   if(!otherC)
4023     {
4024       what="Mesh types differ ! This is structured and other is NOT !";
4025       return false;
4026     }
4027   const DataArrayInt *famc1=_fam_nodes;
4028   const DataArrayInt *famc2=otherC->_fam_nodes;
4029   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
4030     {
4031       what="Mismatch of families arr on nodes ! One is defined and not other !";
4032       return false;
4033     }
4034   if(famc1)
4035     {
4036       bool ret=famc1->isEqual(*famc2);
4037       if(!ret)
4038         {
4039           what="Families arr on nodes differ !";
4040           return false;
4041         }
4042     }
4043   famc1=_fam_cells;
4044   famc2=otherC->_fam_cells;
4045   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
4046     {
4047       what="Mismatch of families arr on cells ! One is defined and not other !";
4048       return false;
4049     }
4050   if(famc1)
4051     {
4052       bool ret=famc1->isEqual(*famc2);
4053       if(!ret)
4054         {
4055           what="Families arr on cells differ !";
4056           return false;
4057         }
4058     }
4059   famc1=_num_nodes;
4060   famc2=otherC->_num_nodes;
4061   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
4062     {
4063       what="Mismatch of numbering arr on nodes ! One is defined and not other !";
4064       return false;
4065     }
4066   if(famc1)
4067     {
4068       bool ret=famc1->isEqual(*famc2);
4069       if(!ret)
4070         {
4071           what="Numbering arr on nodes differ !";
4072           return false;
4073         }
4074     }
4075   famc1=_num_cells;
4076   famc2=otherC->_num_cells;
4077   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
4078     {
4079       what="Mismatch of numbering arr on cells ! One is defined and not other !";
4080       return false;
4081     }
4082   if(famc1)
4083     {
4084       bool ret=famc1->isEqual(*famc2);
4085       if(!ret)
4086         {
4087           what="Numbering arr on cells differ !";
4088           return false;
4089         }
4090     }
4091   const DataArrayAsciiChar *d1=_names_cells;
4092   const DataArrayAsciiChar *d2=otherC->_names_cells;
4093   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
4094     {
4095       what="Mismatch of naming arr on cells ! One is defined and not other !";
4096       return false;
4097     }
4098   if(d1)
4099     {
4100       bool ret=d1->isEqual(*d2);
4101       if(!ret)
4102         {
4103           what="Naming arr on cells differ !";
4104           return false;
4105         }
4106     }
4107   d1=_names_nodes;
4108   d2=otherC->_names_nodes;
4109   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
4110     {
4111       what="Mismatch of naming arr on nodes ! One is defined and not other !";
4112       return false;
4113     }
4114   if(d1)
4115     {
4116       bool ret=d1->isEqual(*d2);
4117       if(!ret)
4118         {
4119           what="Naming arr on nodes differ !";
4120           return false;
4121         }
4122     }
4123   return true;
4124 }
4125
4126 void MEDFileStructuredMesh::clearNonDiscrAttributes() const
4127 {
4128   MEDFileMesh::clearNonDiscrAttributes();
4129   const DataArrayInt *tmp=_fam_nodes;
4130   if(tmp)
4131     (const_cast<DataArrayInt *>(tmp))->setName("");
4132   tmp=_num_nodes;
4133   if(tmp)
4134     (const_cast<DataArrayInt *>(tmp))->setName("");
4135   tmp=_fam_cells;
4136   if(tmp)
4137     (const_cast<DataArrayInt *>(tmp))->setName("");
4138   tmp=_num_cells;
4139   if(tmp)
4140     (const_cast<DataArrayInt *>(tmp))->setName("");
4141 }
4142
4143 /*!
4144  * Returns ids of mesh entities contained in given families of a given dimension.
4145  *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
4146  *          are required.
4147  *  \param [in] fams - the names of the families of interest.
4148  *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
4149  *          returned instead of ids.
4150  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
4151  *          numbers, if available and required, of mesh entities of the families. The caller
4152  *          is to delete this array using decrRef() as it is no more needed. 
4153  *  \throw If the family field is missing for \a meshDimRelToMaxExt.
4154  */
4155 DataArrayInt *MEDFileStructuredMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const
4156 {
4157   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4158     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : Only available for levels 0 or 1 !");
4159   std::vector<int> famIds=getFamiliesIds(fams);
4160   if(meshDimRelToMaxExt==1)
4161     {
4162       if((const DataArrayInt *)_fam_nodes)
4163         {
4164           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
4165           if(!famIds.empty())
4166             da=_fam_nodes->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
4167           else
4168             da=_fam_nodes->getIdsEqualList(0,0);
4169           if(renum)
4170             return MEDFileUMeshSplitL1::Renumber(_num_nodes,da);
4171           else
4172             return da.retn();
4173         }
4174       else
4175         throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on nodes !");
4176     }
4177   else
4178     {
4179       if((const DataArrayInt *)_fam_cells)
4180         {
4181           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
4182           if(!famIds.empty())
4183             da=_fam_cells->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
4184           else
4185             da=_fam_cells->getIdsEqualList(0,0);
4186           if(renum)
4187             return MEDFileUMeshSplitL1::Renumber(_num_cells,da);
4188           else
4189             return da.retn();
4190         }
4191       else
4192         throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on cells !");
4193     }
4194 }
4195
4196 /*!
4197  * Sets the family field of a given relative dimension.
4198  *  \param [in] meshDimRelToMaxExt - the relative dimension of entities for which
4199  *          the family field is set.
4200  *  \param [in] famArr - the array of the family field.
4201  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4202  *  \throw If \a famArr has an invalid size.
4203  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
4204  */
4205 void MEDFileStructuredMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr)
4206 {
4207   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4208     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : Only available for levels 0 or 1 !");
4209   const MEDCouplingStructuredMesh *mesh=getStructuredMesh();
4210   if(!mesh)
4211     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setFamilyFieldArr : no structured mesh specified ! Impossible to set family array !");
4212   if(meshDimRelToMaxExt==0)
4213     {
4214       int nbCells=mesh->getNumberOfCells();
4215       famArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of cells of mesh !");
4216       _fam_cells=famArr;
4217     }
4218   else
4219     {
4220       int nbNodes=mesh->getNumberOfNodes();
4221       famArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !");
4222       _fam_nodes=famArr;
4223     }
4224   if(famArr)
4225     famArr->incrRef();
4226 }
4227
4228 /*!
4229  * Sets the optional numbers of mesh entities of a given dimension.
4230  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4231  *  \param [in] renumArr - the array of the numbers.
4232  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4233  *  \throw If \a renumArr has an invalid size.
4234  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
4235  */
4236 void MEDFileStructuredMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr)
4237 {
4238   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4239     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : Only available for levels 0 or 1 !");
4240   const MEDCouplingStructuredMesh *mesh=getStructuredMesh();
4241   if(!mesh)
4242     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : no structured mesh specified ! Impossible to set number array !");
4243   if(meshDimRelToMaxExt==0)
4244     {
4245       int nbCells=mesh->getNumberOfCells();
4246       renumArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Renum arr ! Mismatch with number of cells of mesh !");
4247       _num_cells=renumArr;
4248     }
4249   else
4250     {
4251       int nbNodes=mesh->getNumberOfNodes();
4252       renumArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !");
4253       _num_nodes=renumArr;
4254     }
4255   if(renumArr)
4256     renumArr->incrRef();
4257 }
4258
4259 /*!
4260  * Sets the optional names of mesh entities of a given dimension.
4261  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4262  *  \param [in] nameArr - the array of the names.
4263  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4264  *  \throw If \a nameArr has an invalid size.
4265  */
4266 void MEDFileStructuredMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr)
4267 {
4268   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4269     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : Only available for levels 0 or 1 !");
4270   const MEDCouplingStructuredMesh *mesh=getStructuredMesh();
4271   if(!mesh)
4272     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : no structured mesh specified ! Impossible to set names array !");
4273   if(meshDimRelToMaxExt==0)
4274     {
4275       int nbCells=mesh->getNumberOfCells();
4276       nameArr->checkNbOfTuplesAndComp(nbCells,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of cells of mesh !");
4277       _names_cells=nameArr;
4278     }
4279   else
4280     {
4281       int nbNodes=mesh->getNumberOfNodes();
4282       nameArr->checkNbOfTuplesAndComp(nbNodes,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of nodes of mesh !");
4283       _names_nodes=nameArr;
4284     }
4285   if(nameArr)
4286     nameArr->incrRef();
4287 }
4288
4289 /*!
4290  * Returns the family field for mesh entities of a given dimension.
4291  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4292  *  \return const DataArrayInt * - the family field. It is an array of ids of families
4293  *          each mesh entity belongs to. It can be \c NULL.
4294  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
4295  */
4296 const DataArrayInt *MEDFileStructuredMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) const
4297 {
4298   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4299     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamilyFieldAtLevel : Only available for levels 0 or 1 !");
4300   if(meshDimRelToMaxExt==0)
4301     return _fam_cells;
4302   else
4303     return _fam_nodes;
4304 }
4305
4306 /*!
4307  * Returns the optional numbers of mesh entities of a given dimension.
4308  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4309  *  \return const DataArrayInt * - the array of the entity numbers.
4310  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4311  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
4312  */
4313 const DataArrayInt *MEDFileStructuredMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) const
4314 {
4315   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4316     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberFieldAtLevel : Only available for levels 0 or 1 !");
4317   if(meshDimRelToMaxExt==0)
4318     return _num_cells;
4319   else
4320     return _num_nodes;
4321 }
4322
4323 /*!
4324  * Returns the optional numbers of mesh entities of a given dimension transformed using
4325  * DataArrayInt::invertArrayN2O2O2N().
4326  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4327  *  \return const DataArrayInt * - the array of the entity numbers transformed using
4328  *          DataArrayInt::invertArrayN2O2O2N().
4329  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
4330  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4331  */
4332 const DataArrayInt *MEDFileStructuredMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxExt) const
4333 {
4334   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4335     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getRevNumberFieldAtLevel : Only available for levels 0 or 1 !");
4336   if(meshDimRelToMaxExt==0)
4337     {
4338       if((const DataArrayInt *)_num_cells)
4339         {
4340           int pos;
4341           int maxValue=_num_cells->getMaxValue(pos);
4342           _rev_num_cells=_num_cells->invertArrayN2O2O2N(maxValue+1);
4343           return _rev_num_cells;
4344         }
4345       else
4346         throw INTERP_KERNEL::Exception("MEDFileCMesh::getRevNumberFieldAtLevel : no cell renumbering for a request on reverse numbering !");
4347     }
4348   else
4349     {
4350       if((const DataArrayInt *)_num_nodes)
4351         {
4352           int pos;
4353           int maxValue=_num_nodes->getMaxValue(pos);
4354           _rev_num_nodes=_num_nodes->invertArrayN2O2O2N(maxValue+1);
4355           return _rev_num_nodes;
4356         }
4357       else
4358         throw INTERP_KERNEL::Exception("MEDFileCMesh::getRevNumberFieldAtLevel : no node renumbering for a request on reverse numbering !");
4359     }
4360 }
4361
4362 const DataArrayAsciiChar *MEDFileStructuredMesh::getNameFieldAtLevel(int meshDimRelToMaxExt) const
4363 {
4364   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4365     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNameFieldAtLevel : Only available for levels 0 or 1 !");
4366   if(meshDimRelToMaxExt==0)
4367     return _names_cells;
4368   else
4369     return _names_nodes;
4370 }
4371
4372 /*!
4373  * Returns relative dimensions of mesh entities (excluding nodes) present in \a this mesh.
4374  *  \return std::vector<int> - a sequence of the relative dimensions: [0].
4375  */
4376 std::vector<int> MEDFileStructuredMesh::getNonEmptyLevels() const
4377 {
4378   std::vector<int> ret(1);
4379   return ret;
4380 }
4381
4382 /*!
4383  * Returns relative dimensions of mesh entities (including nodes) present in \a this mesh.
4384  *  \return std::vector<int> - a sequence of the relative dimensions: [1,0].
4385  */
4386 std::vector<int> MEDFileStructuredMesh::getNonEmptyLevelsExt() const
4387 {
4388   std::vector<int> ret(2);
4389   ret[0]=1;
4390   return ret;
4391 }
4392
4393 /*!
4394  * Returns the set of extensive levels (nodes included) where not NULL family arr are defined.
4395  */
4396 std::vector<int> MEDFileStructuredMesh::getFamArrNonEmptyLevelsExt() const
4397 {
4398   std::vector<int> ret;
4399   const DataArrayInt *famNodes(_fam_nodes),*famCells(_fam_cells);
4400   if(famNodes)
4401     ret.push_back(1);
4402   if(famCells)
4403     ret.push_back(0);
4404   return ret;
4405 }
4406
4407 /*!
4408  * Returns the set of extensive levels (nodes included) where not NULL numbering arr are defined.
4409  */
4410 std::vector<int> MEDFileStructuredMesh::getNumArrNonEmptyLevelsExt() const
4411 {
4412   std::vector<int> ret;
4413   const DataArrayInt *numNodes(_num_nodes),*numCells(_num_cells);
4414   if(numNodes)
4415     ret.push_back(1);
4416   if(numCells)
4417     ret.push_back(0);
4418   return ret;
4419 }
4420
4421 /*!
4422  * Returns the set of extensive levels (nodes included) where not NULL naming arr are defined.
4423  */
4424 std::vector<int> MEDFileStructuredMesh::getNameArrNonEmptyLevelsExt() const
4425 {
4426   std::vector<int> ret;
4427   const DataArrayAsciiChar *namesCells(_names_cells);
4428   if(namesCells)
4429     ret.push_back(0);
4430   return ret;
4431 }
4432
4433 /*!
4434  * no implementation here, it is not a bug, but intresically no polyhedra in \a this.
4435  */
4436 bool MEDFileStructuredMesh::unPolyze(std::vector<int>& oldCode, std::vector<int>& newCode, DataArrayInt *& o2nRenumCell)
4437 {
4438   oldCode.clear(); newCode.clear(); o2nRenumCell=0;
4439   return false;
4440 }
4441
4442 void MEDFileStructuredMesh::changeFamilyIdArr(int oldId, int newId)
4443 {
4444   DataArrayInt *arr=_fam_nodes;
4445   if(arr)
4446     arr->changeValue(oldId,newId);
4447   arr=_fam_cells;
4448   if(arr)
4449     arr->changeValue(oldId,newId);
4450 }
4451
4452 void MEDFileStructuredMesh::deepCpyAttributes()
4453 {
4454   if((const DataArrayInt*)_fam_nodes)
4455     _fam_nodes=_fam_nodes->deepCpy();
4456   if((const DataArrayInt*)_num_nodes)
4457     _num_nodes=_num_nodes->deepCpy();
4458   if((const DataArrayInt*)_fam_cells)
4459     _fam_cells=_fam_cells->deepCpy();
4460   if((const DataArrayInt*)_num_cells)
4461     _num_cells=_num_cells->deepCpy();
4462   if((const DataArrayInt*)_rev_num_nodes)
4463     _rev_num_nodes=_rev_num_nodes->deepCpy();
4464   if((const DataArrayInt*)_rev_num_cells)
4465     _rev_num_cells=_rev_num_cells->deepCpy();
4466 }
4467
4468 /*!
4469  * Returns a pointer to mesh at the specified level (here 0 is compulsary for cartesian mesh).
4470  * 
4471  * \return a pointer to cartesian mesh that need to be managed by the caller.
4472  * \warning the returned pointer has to be managed by the caller.
4473  */
4474
4475 /*!
4476  * Returns a pointer to MEDCouplingStructuredMesh held by \a this. 
4477  *  \param [in] meshDimRelToMax - it must be \c 0.
4478  *  \param [in] renum - it must be \c false.
4479  *  \return MEDCouplingMesh * - a pointer to MEDCouplingMesh that the caller is to
4480  *          delete using decrRef() as it is no more needed. 
4481  */
4482 MEDCouplingMesh *MEDFileStructuredMesh::getGenMeshAtLevel(int meshDimRelToMax, bool renum) const
4483 {
4484   if(renum)
4485     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support renumbering ! To do it perform request of renum array directly !");
4486   if(meshDimRelToMax!=0)
4487     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support multi level for mesh 0 expected as input !");
4488   const MEDCouplingStructuredMesh *m=getStructuredMesh();
4489   if(m)
4490     m->incrRef();
4491   return const_cast<MEDCouplingStructuredMesh *>(m);
4492 }
4493
4494 /*!
4495  * Returns number of mesh entities of a given relative dimension in \a this mesh.
4496  *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
4497  *  \return int - the number of entities.
4498  *  \throw If no mesh entities of dimension \a meshDimRelToMaxExt are available in \a this mesh.
4499  */
4500 int MEDFileStructuredMesh::getSizeAtLevel(int meshDimRelToMaxExt) const
4501 {
4502   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4503     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : Only available for levels 0 or 1 !");
4504   const MEDCouplingStructuredMesh *cmesh=getStructuredMesh();
4505   if(!cmesh)
4506     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : No structured mesh set !");
4507   if(meshDimRelToMaxExt==0)
4508     return cmesh->getNumberOfCells();
4509   else
4510     return cmesh->getNumberOfNodes();
4511 }
4512
4513 int MEDFileStructuredMesh::getNumberOfNodes() const
4514 {
4515   const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
4516   if(!cmesh)
4517     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberOfNodes : no cartesian mesh set !");
4518   return cmesh->getNumberOfNodes();
4519 }
4520
4521 std::vector<INTERP_KERNEL::NormalizedCellType> MEDFileStructuredMesh::getGeoTypesAtLevel(int meshDimRelToMax) const
4522 {
4523   if(meshDimRelToMax!=0)
4524     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGeoTypesAtLevel : only one level available for structured meshes ! Input 0 is mandatory !");
4525   const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
4526   std::vector<INTERP_KERNEL::NormalizedCellType> ret(1,cmesh->getTypeOfCell(0));
4527   return ret;
4528 }
4529
4530 void MEDFileStructuredMesh::whichAreNodesFetched(const MEDFileField1TSStructItem& st, const MEDFileFieldGlobsReal *globs, std::vector<bool>& nodesFetched) const
4531 {
4532   if(st.getNumberOfItems()!=1)
4533     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 !");
4534   if(st[0].getGeo()!=MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(getMeshDimension()))
4535     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : The sturture of field is not lying on expected geo type !");
4536   if(getNumberOfNodes()!=(int)nodesFetched.size())
4537     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : invalid size of array !");
4538   if(st[0].getPflName().empty())
4539     {
4540       std::fill(nodesFetched.begin(),nodesFetched.end(),true);
4541       return ;
4542     }
4543   const DataArrayInt *arr(globs->getProfile(st[0].getPflName()));
4544   const MEDCouplingStructuredMesh *cmesh=getStructuredMesh();//cmesh not null because getNumberOfNodes called before
4545   int sz(nodesFetched.size());
4546   for(const int *work=arr->begin();work!=arr->end();work++)
4547     {
4548       std::vector<int> conn;
4549       cmesh->getNodeIdsOfCell(*work,conn);
4550       for(std::vector<int>::const_iterator it=conn.begin();it!=conn.end();it++)
4551         if(*it>=0 && *it<sz)
4552           nodesFetched[*it]=true;
4553         else
4554           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : internal error !");
4555     }
4556 }
4557
4558 med_geometry_type MEDFileStructuredMesh::GetGeoTypeFromMeshDim(int meshDim)
4559 {
4560   med_geometry_type geoTypeReq=MED_NONE;
4561   switch(meshDim)
4562     {
4563     case 3:
4564       geoTypeReq=MED_HEXA8;
4565       break;
4566     case 2:
4567       geoTypeReq=MED_QUAD4;
4568       break;
4569     case 1:
4570       geoTypeReq=MED_SEG2;
4571       break;
4572     case 0:
4573       geoTypeReq=MED_POINT1;
4574       break;
4575     default:
4576       throw INTERP_KERNEL::Exception("Invalid meshdim detected for structured mesh ! Must be in (1,2,3) !");
4577     }
4578   return geoTypeReq;
4579 }
4580
4581 void MEDFileStructuredMesh::loadStrMeshFromFile(MEDFileStrMeshL2 *strm, med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
4582 {
4583   setName(strm->getName());
4584   setDescription(strm->getDescription());
4585   setUnivName(strm->getUnivName());
4586   setIteration(strm->getIteration());
4587   setOrder(strm->getOrder());
4588   setTimeValue(strm->getTime());
4589   setTimeUnit(strm->getTimeUnit());
4590   MEDFileMeshL2::ReadFamiliesAndGrps(fid,mName,_families,_groups,mrs);
4591   med_bool chgt=MED_FALSE,trsf=MED_FALSE;
4592   int nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf);
4593   if(nbOfElt>0)
4594     {
4595       if(!mrs || mrs->isNodeFamilyFieldReading())
4596         {
4597           _fam_nodes=DataArrayInt::New();
4598           _fam_nodes->alloc(nbOfElt,1);
4599           MEDmeshEntityFamilyNumberRd(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,_fam_nodes->getPointer());
4600         }
4601     }
4602   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_NUMBER,MED_NODAL,&chgt,&trsf);
4603   if(nbOfElt>0)
4604     {
4605       if(!mrs || mrs->isNodeNumFieldReading())
4606         {
4607           _num_nodes=DataArrayInt::New();
4608           _num_nodes->alloc(nbOfElt,1);
4609           MEDmeshEntityNumberRd(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,_num_nodes->getPointer());
4610         }
4611     }
4612   int meshDim=getStructuredMesh()->getMeshDimension();
4613   med_geometry_type geoTypeReq=GetGeoTypeFromMeshDim(meshDim);
4614   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf);
4615   if(nbOfElt>0)
4616     {
4617       if(!mrs || mrs->isCellFamilyFieldReading())
4618         {
4619           _fam_cells=DataArrayInt::New();
4620           _fam_cells->alloc(nbOfElt,1);
4621           MEDmeshEntityFamilyNumberRd(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,_fam_cells->getPointer());
4622         }
4623     }
4624   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,MED_NUMBER,MED_NODAL,&chgt,&trsf);
4625   if(nbOfElt>0)
4626     {
4627       if(!mrs || mrs->isCellNumFieldReading())
4628         {
4629           _num_cells=DataArrayInt::New();
4630           _num_cells->alloc(nbOfElt,1);
4631           MEDmeshEntityNumberRd(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,_num_cells->getPointer());
4632         }
4633     }
4634   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,MED_NAME,MED_NODAL,&chgt,&trsf);
4635   if(nbOfElt>0)
4636     {
4637       if(!mrs || mrs->isCellNameFieldReading())
4638         {
4639           _names_cells=DataArrayAsciiChar::New();
4640           _names_cells->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end
4641           MEDmeshEntityNameRd(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,_names_cells->getPointer());
4642           _names_cells->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end
4643         }
4644     }
4645   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_NAME,MED_NODAL,&chgt,&trsf);
4646   if(nbOfElt>0)
4647     {
4648       if(!mrs || mrs->isNodeNameFieldReading())
4649         {
4650           _names_nodes=DataArrayAsciiChar::New();
4651           _names_nodes->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end
4652           MEDmeshEntityNameRd(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,_names_nodes->getPointer());
4653           _names_nodes->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end
4654         }
4655     }
4656 }
4657
4658 void MEDFileStructuredMesh::writeStructuredLL(med_idt fid, const std::string& maa) const
4659 {
4660   int meshDim=getStructuredMesh()->getMeshDimension();
4661   med_geometry_type geoTypeReq=GetGeoTypeFromMeshDim(meshDim);
4662   //
4663   if((const DataArrayInt *)_fam_cells)
4664     MEDmeshEntityFamilyNumberWr(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq,_fam_cells->getNumberOfTuples(),_fam_cells->getConstPointer());
4665   if((const DataArrayInt *)_fam_nodes)
4666     MEDmeshEntityFamilyNumberWr(fid,maa.c_str(),_iteration,_order,MED_NODE,MED_NONE,_fam_nodes->getNumberOfTuples(),_fam_nodes->getConstPointer());
4667   if((const DataArrayInt *)_num_cells)
4668     MEDmeshEntityNumberWr(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq,_num_cells->getNumberOfTuples(),_num_cells->getConstPointer());
4669   if((const DataArrayInt *)_num_nodes)
4670     MEDmeshEntityNumberWr(fid,maa.c_str(),_iteration,_order,MED_NODE,MED_NONE,_num_nodes->getNumberOfTuples(),_num_nodes->getConstPointer());
4671   if((const DataArrayAsciiChar *)_names_cells)
4672     {
4673       if(_names_cells->getNumberOfComponents()!=MED_SNAME_SIZE)
4674         {
4675           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on cells with number of components set to " << MED_SNAME_SIZE;
4676           oss << " ! The array has " << _names_cells->getNumberOfComponents() << " components !";
4677           throw INTERP_KERNEL::Exception(oss.str().c_str());
4678         }
4679       MEDmeshEntityNameWr(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq,_names_cells->getNumberOfTuples(),_names_cells->getConstPointer());
4680     }
4681   if((const DataArrayAsciiChar *)_names_nodes)
4682     {
4683       if(_names_nodes->getNumberOfComponents()!=MED_SNAME_SIZE)
4684         {
4685           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on nodes with number of components set to " << MED_SNAME_SIZE;
4686           oss << " ! The array has " << _names_cells->getNumberOfComponents() << " components !";
4687           throw INTERP_KERNEL::Exception(oss.str().c_str());
4688         }
4689       MEDmeshEntityNameWr(fid,maa.c_str(),_iteration,_order,MED_NODE,MED_NONE,_names_nodes->getNumberOfTuples(),_names_nodes->getConstPointer());
4690     }
4691   //
4692   MEDFileUMeshL2::WriteFamiliesAndGrps(fid,maa.c_str(),_families,_groups,_too_long_str);
4693 }
4694
4695 /*!
4696  * Returns an empty instance of MEDFileCMesh.
4697  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
4698  *          mesh using decrRef() as it is no more needed. 
4699  */
4700 MEDFileCMesh *MEDFileCMesh::New()
4701 {
4702   return new MEDFileCMesh;
4703 }
4704
4705 /*!
4706  * Returns a new MEDFileCMesh holding the mesh data that has been read from a given MED
4707  * file. The first mesh in the file is loaded.
4708  *  \param [in] fileName - the name of MED file to read.
4709  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
4710  *          mesh using decrRef() as it is no more needed. 
4711  *  \throw If the file is not readable.
4712  *  \throw If there is no meshes in the file.
4713  *  \throw If the mesh in the file is not a Cartesian one.
4714  */
4715 MEDFileCMesh *MEDFileCMesh::New(const std::string& fileName, MEDFileMeshReadSelector *mrs)
4716 {
4717   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
4718   if(ms.empty())
4719     {
4720       std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
4721       throw INTERP_KERNEL::Exception(oss.str().c_str());
4722     }
4723   MEDFileUtilities::CheckFileForRead(fileName);
4724   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
4725   int dt,it;
4726   ParaMEDMEM::MEDCouplingMeshType meshType;
4727   std::string dummy2;
4728   MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dt,it,dummy2);
4729   return new MEDFileCMesh(fid,ms.front(),dt,it,mrs);
4730 }
4731
4732 /*!
4733  * Returns a new MEDFileCMesh holding the mesh data that has been read from a given MED
4734  * file. The mesh to load is specified by its name and numbers of a time step and an
4735  * iteration.
4736  *  \param [in] fileName - the name of MED file to read.
4737  *  \param [in] mName - the name of the mesh to read.
4738  *  \param [in] dt - the number of a time step.
4739  *  \param [in] it - the number of an iteration.
4740  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
4741  *          mesh using decrRef() as it is no more needed. 
4742  *  \throw If the file is not readable.
4743  *  \throw If there is no mesh with given attributes in the file.
4744  *  \throw If the mesh in the file is not a Cartesian one.
4745  */
4746 MEDFileCMesh *MEDFileCMesh::New(const std::string& fileName, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
4747 {
4748   MEDFileUtilities::CheckFileForRead(fileName);
4749   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
4750   return new MEDFileCMesh(fid,mName,dt,it,mrs);
4751 }
4752
4753 std::size_t MEDFileCMesh::getHeapMemorySizeWithoutChildren() const
4754 {
4755   return MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren();
4756 }
4757
4758 std::vector<const BigMemoryObject *> MEDFileCMesh::getDirectChildren() const
4759 {
4760   std::vector<const BigMemoryObject *> ret(MEDFileStructuredMesh::getDirectChildren());
4761   if((const MEDCouplingCMesh *)_cmesh)
4762     ret.push_back((const MEDCouplingCMesh *)_cmesh);
4763   return ret;
4764 }
4765
4766 /*!
4767  * Returns the dimension on cells in \a this mesh.
4768  *  \return int - the mesh dimension.
4769  *  \throw If there are no cells in this mesh.
4770  */
4771 int MEDFileCMesh::getMeshDimension() const
4772 {
4773   if(!((const MEDCouplingCMesh*)_cmesh))
4774     throw INTERP_KERNEL::Exception("MEDFileCMesh::getMeshDimension : unable to get meshdimension because no mesh set !");
4775   return _cmesh->getMeshDimension();
4776 }
4777
4778 /*!
4779  * Returns the dimension on nodes in \a this mesh.
4780  *  \return int - the space dimension.
4781  *  \throw If there are no cells in this mesh.
4782  */
4783 int MEDFileCMesh::getSpaceDimension() const
4784 {
4785   if(!((const MEDCouplingCMesh*)_cmesh))
4786     throw INTERP_KERNEL::Exception("MEDFileCMesh::getSpaceDimension : unable to get spacedimension because no mesh set !");
4787   return _cmesh->getSpaceDimension();
4788 }
4789
4790 /*!
4791  * Returns a string describing \a this mesh.
4792  *  \return std::string - the mesh information string.
4793  */
4794 std::string MEDFileCMesh::simpleRepr() const
4795 {
4796   return MEDFileStructuredMesh::simpleRepr();
4797 }
4798
4799 /*!
4800  * Returns a full textual description of \a this mesh.
4801  *  \return std::string - the string holding the mesh description.
4802  */
4803 std::string MEDFileCMesh::advancedRepr() const
4804 {
4805   return simpleRepr();
4806 }
4807
4808 MEDFileMesh *MEDFileCMesh::shallowCpy() const
4809 {
4810   MEDCouplingAutoRefCountObjectPtr<MEDFileCMesh> ret=new MEDFileCMesh(*this);
4811   return ret.retn();
4812 }
4813
4814 MEDFileMesh *MEDFileCMesh::createNewEmpty() const
4815 {
4816   return new MEDFileCMesh;
4817 }
4818
4819 MEDFileMesh *MEDFileCMesh::deepCpy() const
4820 {
4821   MEDCouplingAutoRefCountObjectPtr<MEDFileCMesh> ret=new MEDFileCMesh(*this);
4822   if((const MEDCouplingCMesh*)_cmesh)
4823     ret->_cmesh=static_cast<MEDCouplingCMesh*>(_cmesh->deepCpy());
4824   ret->deepCpyAttributes();
4825   return ret.retn();
4826 }
4827
4828 /*!
4829  * Checks if \a this and another mesh are equal.
4830  *  \param [in] other - the mesh to compare with.
4831  *  \param [in] eps - a precision used to compare real values.
4832  *  \param [in,out] what - the string returning description of unequal data.
4833  *  \return bool - \c true if the meshes are equal, \c false, else.
4834  */
4835 bool MEDFileCMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
4836 {
4837   if(!MEDFileStructuredMesh::isEqual(other,eps,what))
4838     return false;
4839   const MEDFileCMesh *otherC=dynamic_cast<const MEDFileCMesh *>(other);
4840   if(!otherC)
4841     {
4842       what="Mesh types differ ! This is cartesian and other is NOT !";
4843       return false;
4844     }
4845   clearNonDiscrAttributes();
4846   otherC->clearNonDiscrAttributes();
4847   const MEDCouplingCMesh *coo1=_cmesh;
4848   const MEDCouplingCMesh *coo2=otherC->_cmesh;
4849   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
4850     {
4851       what="Mismatch of cartesian meshes ! One is defined and not other !";
4852       return false;
4853     }
4854   if(coo1)
4855     {
4856       bool ret=coo1->isEqual(coo2,eps);
4857       if(!ret)
4858         {
4859           what="cartesian meshes differ !";
4860           return false;
4861         }
4862     }
4863   return true;
4864 }
4865
4866 /*!
4867  * Clears redundant attributes of incorporated data arrays.
4868  */
4869 void MEDFileCMesh::clearNonDiscrAttributes() const
4870 {
4871   MEDFileStructuredMesh::clearNonDiscrAttributes();
4872   MEDFileUMeshSplitL1::ClearNonDiscrAttributes(_cmesh);//to it is not a bug umeshsplit have already the method implemented
4873 }
4874
4875 MEDFileCMesh::MEDFileCMesh()
4876 {
4877 }
4878
4879 MEDFileCMesh::MEDFileCMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
4880 try
4881   {
4882     loadCMeshFromFile(fid,mName,dt,it,mrs);
4883   }
4884 catch(INTERP_KERNEL::Exception& e)
4885   {
4886     throw e;
4887   }
4888
4889 void MEDFileCMesh::loadCMeshFromFile(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
4890 {
4891   ParaMEDMEM::MEDCouplingMeshType meshType;
4892   int dummy0,dummy1;
4893   std::string dtunit;
4894   int mid=MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dtunit);
4895   if(meshType!=CARTESIAN)
4896     {
4897       std::ostringstream oss; oss << "Trying to load as cartesian an existing mesh with name '" << mName << "' that is NOT cartesian !";
4898       throw INTERP_KERNEL::Exception(oss.str().c_str());
4899     }
4900   MEDFileCMeshL2 loaderl2;
4901   loaderl2.loadAll(fid,mid,mName,dt,it);
4902   MEDCouplingCMesh *mesh=loaderl2.getMesh();
4903   mesh->incrRef();
4904   _cmesh=mesh;
4905   loadStrMeshFromFile(&loaderl2,fid,mName,dt,it,mrs);
4906 }
4907
4908 /*!
4909  * Returns a const pointer to MEDCouplingCMesh held by \a this mesh.
4910  *  \return const MEDCouplingCMesh * - a pointer to the held MEDCouplingCMesh.
4911  */
4912 const MEDCouplingCMesh *MEDFileCMesh::getMesh() const
4913 {
4914   synchronizeTinyInfoOnLeaves();
4915   return _cmesh;
4916 }
4917
4918 const MEDCouplingStructuredMesh *MEDFileCMesh::getStructuredMesh() const
4919 {
4920   synchronizeTinyInfoOnLeaves();
4921   return _cmesh;
4922 }
4923
4924 /*!
4925  * Sets the MEDCouplingCMesh holding the data of \a this mesh.
4926  *  \param [in] m - the new MEDCouplingCMesh to refer to.
4927  *  \throw If the name or the description of \a this mesh and \a m are not empty and are
4928  *         different. 
4929  */
4930 void MEDFileCMesh::setMesh(MEDCouplingCMesh *m)
4931 {
4932   dealWithTinyInfo(m);
4933   if(m)
4934     m->incrRef();
4935   _cmesh=m;
4936 }
4937
4938 void MEDFileCMesh::writeLL(med_idt fid) const
4939 {
4940   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
4941   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
4942   INTERP_KERNEL::AutoPtr<char> dtunit=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE);
4943   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
4944   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
4945   MEDLoaderBase::safeStrCpy(_dt_unit.c_str(),MED_LNAME_SIZE,dtunit,_too_long_str);
4946   int spaceDim(_cmesh->getSpaceDimension());
4947   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
4948   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
4949   for(int i=0;i<spaceDim;i++)
4950     {
4951       std::string info(_cmesh->getCoordsAt(i)->getInfoOnComponent(0));
4952       std::string c,u;
4953       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
4954       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
4955       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
4956     }
4957   MEDmeshCr(fid,maa,spaceDim,spaceDim,MED_STRUCTURED_MESH,desc,dtunit,MED_SORT_DTIT,MED_CARTESIAN,comp,unit);
4958   MEDmeshUniversalNameWr(fid,maa);
4959   MEDmeshGridTypeWr(fid,maa,MED_CARTESIAN_GRID);
4960   for(int i=0;i<spaceDim;i++)
4961     {
4962       const DataArrayDouble *da=_cmesh->getCoordsAt(i);
4963       MEDmeshGridIndexCoordinateWr(fid,maa,_iteration,_order,_time,i+1,da->getNumberOfTuples(),da->getConstPointer());
4964     }
4965   //
4966   std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE));
4967   MEDFileStructuredMesh::writeStructuredLL(fid,meshName);
4968 }
4969
4970 void MEDFileCMesh::synchronizeTinyInfoOnLeaves() const
4971 {
4972   const MEDCouplingCMesh *cmesh=_cmesh;
4973   if(!cmesh)
4974     return;
4975   (const_cast<MEDCouplingCMesh *>(cmesh))->setName(_name);
4976   (const_cast<MEDCouplingCMesh *>(cmesh))->setDescription(_desc_name);
4977   (const_cast<MEDCouplingCMesh *>(cmesh))->setTime(_time,_iteration,_order);
4978   (const_cast<MEDCouplingCMesh *>(cmesh))->setTimeUnit(_dt_unit);
4979 }
4980
4981 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New()
4982 {
4983   return new MEDFileCurveLinearMesh;
4984 }
4985
4986 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const std::string& fileName, MEDFileMeshReadSelector *mrs)
4987 {
4988   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
4989   if(ms.empty())
4990     {
4991       std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
4992       throw INTERP_KERNEL::Exception(oss.str().c_str());
4993     }
4994   MEDFileUtilities::CheckFileForRead(fileName);
4995   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
4996   int dt,it;
4997   ParaMEDMEM::MEDCouplingMeshType meshType;
4998   std::string dummy2;
4999   MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dt,it,dummy2);
5000   return new MEDFileCurveLinearMesh(fid,ms.front(),dt,it,mrs);
5001 }
5002
5003 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const std::string& fileName, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
5004 {
5005   MEDFileUtilities::CheckFileForRead(fileName);
5006   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
5007   return new MEDFileCurveLinearMesh(fid,mName,dt,it,mrs);
5008 }
5009
5010 std::size_t MEDFileCurveLinearMesh::getHeapMemorySizeWithoutChildren() const
5011 {
5012   return MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren();
5013 }
5014
5015 std::vector<const BigMemoryObject *> MEDFileCurveLinearMesh::getDirectChildren() const
5016 {
5017   std::vector<const BigMemoryObject *> ret(MEDFileStructuredMesh::getDirectChildren());
5018   if((const MEDCouplingCurveLinearMesh *)_clmesh)
5019     ret.push_back((const MEDCouplingCurveLinearMesh *)_clmesh);
5020   return ret;
5021 }
5022
5023 MEDFileMesh *MEDFileCurveLinearMesh::shallowCpy() const
5024 {
5025   MEDCouplingAutoRefCountObjectPtr<MEDFileCurveLinearMesh> ret=new MEDFileCurveLinearMesh(*this);
5026   return ret.retn();
5027 }
5028
5029 MEDFileMesh *MEDFileCurveLinearMesh::createNewEmpty() const
5030 {
5031   return new MEDFileCurveLinearMesh;
5032 }
5033
5034 MEDFileMesh *MEDFileCurveLinearMesh::deepCpy() const
5035 {
5036   MEDCouplingAutoRefCountObjectPtr<MEDFileCurveLinearMesh> ret=new MEDFileCurveLinearMesh(*this);
5037   if((const MEDCouplingCurveLinearMesh*)_clmesh)
5038     ret->_clmesh=static_cast<MEDCouplingCurveLinearMesh*>(_clmesh->deepCpy());
5039   ret->deepCpyAttributes();
5040   return ret.retn();
5041 }
5042
5043 int MEDFileCurveLinearMesh::getMeshDimension() const
5044 {
5045   if(!((const MEDCouplingCurveLinearMesh*)_clmesh))
5046     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::getMeshDimension : unable to get meshdimension because no mesh set !");
5047   return _clmesh->getMeshDimension();
5048 }
5049
5050 std::string MEDFileCurveLinearMesh::simpleRepr() const
5051 {
5052   return MEDFileStructuredMesh::simpleRepr();
5053 }
5054
5055 std::string MEDFileCurveLinearMesh::advancedRepr() const
5056 {
5057   return simpleRepr();
5058 }
5059
5060 bool MEDFileCurveLinearMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
5061 {
5062   if(!MEDFileStructuredMesh::isEqual(other,eps,what))
5063     return false;
5064   const MEDFileCurveLinearMesh *otherC=dynamic_cast<const MEDFileCurveLinearMesh *>(other);
5065   if(!otherC)
5066     {
5067       what="Mesh types differ ! This is curve linear and other is NOT !";
5068       return false;
5069     }
5070   clearNonDiscrAttributes();
5071   otherC->clearNonDiscrAttributes();
5072   const MEDCouplingCurveLinearMesh *coo1=_clmesh;
5073   const MEDCouplingCurveLinearMesh *coo2=otherC->_clmesh;
5074   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
5075     {
5076       what="Mismatch of curve linear meshes ! One is defined and not other !";
5077       return false;
5078     }
5079   if(coo1)
5080     {
5081       bool ret=coo1->isEqual(coo2,eps);
5082       if(!ret)
5083         {
5084           what="curve linear meshes differ !";
5085           return false;
5086         }
5087     }
5088   return true;
5089 }
5090
5091 void MEDFileCurveLinearMesh::clearNonDiscrAttributes() const
5092 {
5093   MEDFileStructuredMesh::clearNonDiscrAttributes();
5094   MEDFileUMeshSplitL1::ClearNonDiscrAttributes(_clmesh);//to it is not a bug umeshsplit have already the method implemented
5095 }
5096
5097 void MEDFileCurveLinearMesh::synchronizeTinyInfoOnLeaves() const
5098 {
5099   const MEDCouplingCurveLinearMesh *clmesh=_clmesh;
5100   if(!clmesh)
5101     return;
5102   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setName(_name);
5103   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setDescription(_desc_name);
5104   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setTime(_time,_iteration,_order);
5105   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setTimeUnit(_dt_unit);
5106 }
5107
5108 const MEDCouplingCurveLinearMesh *MEDFileCurveLinearMesh::getMesh() const
5109 {
5110   synchronizeTinyInfoOnLeaves();
5111   return _clmesh;
5112 }
5113
5114 void MEDFileCurveLinearMesh::setMesh(MEDCouplingCurveLinearMesh *m)
5115 {
5116   dealWithTinyInfo(m);
5117   if(m)
5118     m->incrRef();
5119   _clmesh=m;
5120 }
5121
5122 const MEDCouplingStructuredMesh *MEDFileCurveLinearMesh::getStructuredMesh() const
5123 {
5124   synchronizeTinyInfoOnLeaves();
5125   return _clmesh;
5126 }
5127
5128 MEDFileCurveLinearMesh::MEDFileCurveLinearMesh()
5129 {
5130 }
5131
5132 MEDFileCurveLinearMesh::MEDFileCurveLinearMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
5133 try
5134   {
5135     loadCLMeshFromFile(fid,mName,dt,it,mrs);
5136   }
5137 catch(INTERP_KERNEL::Exception& e)
5138   {
5139     throw e;
5140   }
5141
5142 void MEDFileCurveLinearMesh::writeLL(med_idt fid) const
5143 {
5144   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
5145   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
5146   INTERP_KERNEL::AutoPtr<char> dtunit=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE);
5147   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
5148   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
5149   MEDLoaderBase::safeStrCpy(_dt_unit.c_str(),MED_LNAME_SIZE,dtunit,_too_long_str);
5150   int spaceDim=_clmesh->getSpaceDimension();
5151   int meshDim=_clmesh->getMeshDimension();
5152   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
5153   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
5154   const DataArrayDouble *coords=_clmesh->getCoords();
5155   if(!coords)
5156     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::writeLL : no coordinates set !");
5157   for(int i=0;i<spaceDim;i++)
5158     {
5159       std::string info(_clmesh->getCoords()->getInfoOnComponent(i));
5160       std::string c,u;
5161       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
5162       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
5163       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
5164     }
5165   MEDmeshCr(fid,maa,spaceDim,meshDim,MED_STRUCTURED_MESH,desc,dtunit,MED_SORT_DTIT,MED_CARTESIAN,comp,unit);
5166   MEDmeshUniversalNameWr(fid,maa);
5167   MEDmeshGridTypeWr(fid,maa,MED_CURVILINEAR_GRID);
5168   std::vector<int> nodeGridSt=_clmesh->getNodeGridStructure();
5169   MEDmeshGridStructWr(fid,maa,_iteration,_order,_time,&nodeGridSt[0]);
5170   
5171   MEDmeshNodeCoordinateWr(fid,maa,_iteration,_order,_time,MED_FULL_INTERLACE,coords->getNumberOfTuples(),coords->begin());
5172   //
5173   std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE));
5174   MEDFileStructuredMesh::writeStructuredLL(fid,meshName);
5175 }
5176
5177 void MEDFileCurveLinearMesh::loadCLMeshFromFile(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
5178 {
5179   ParaMEDMEM::MEDCouplingMeshType meshType;
5180   int dummy0,dummy1;
5181   std::string dtunit;
5182   int mid=MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dtunit);
5183   if(meshType!=CURVE_LINEAR)
5184     {
5185       std::ostringstream oss; oss << "Trying to load as curve linear an existing mesh with name '" << mName << "' that is NOT curve linear !";
5186       throw INTERP_KERNEL::Exception(oss.str().c_str());
5187     }
5188   MEDFileCLMeshL2 loaderl2;
5189   loaderl2.loadAll(fid,mid,mName,dt,it);
5190   MEDCouplingCurveLinearMesh *mesh=loaderl2.getMesh();
5191   mesh->incrRef();
5192   _clmesh=mesh;
5193   loadStrMeshFromFile(&loaderl2,fid,mName,dt,it,mrs);
5194 }
5195
5196 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New()
5197 {
5198   return new MEDFileMeshMultiTS;
5199 }
5200
5201 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(const std::string& fileName)
5202 {
5203   return new MEDFileMeshMultiTS(fileName);
5204 }
5205
5206 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(const std::string& fileName, const std::string& mName)
5207 {
5208   return new MEDFileMeshMultiTS(fileName,mName);
5209 }
5210
5211 MEDFileMeshMultiTS *MEDFileMeshMultiTS::deepCpy() const
5212 {
5213   MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> ret=MEDFileMeshMultiTS::New();
5214   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> > meshOneTs(_mesh_one_ts.size());
5215   std::size_t i=0;
5216   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++,i++)
5217     if((const MEDFileMesh *)*it)
5218       meshOneTs[i]=(*it)->deepCpy();
5219   ret->_mesh_one_ts=meshOneTs;
5220   return ret.retn();
5221 }
5222
5223 std::size_t MEDFileMeshMultiTS::getHeapMemorySizeWithoutChildren() const
5224 {
5225   return _mesh_one_ts.capacity()*sizeof(MEDCouplingAutoRefCountObjectPtr<MEDFileMesh>);
5226 }
5227
5228 std::vector<const BigMemoryObject *> MEDFileMeshMultiTS::getDirectChildren() const
5229 {
5230   std::vector<const BigMemoryObject *> ret;
5231   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
5232     {
5233       const MEDFileMesh *cur(*it);
5234       if(cur)
5235         ret.push_back(cur);
5236     }
5237   return ret;
5238 }
5239
5240 std::string MEDFileMeshMultiTS::getName() const
5241 {
5242   if(_mesh_one_ts.empty())
5243     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::getName : no time steps set !");
5244   return _mesh_one_ts[0]->getName();
5245 }
5246
5247 void MEDFileMeshMultiTS::setName(const std::string& newMeshName)
5248 {
5249   std::string oldName(getName());
5250   std::vector< std::pair<std::string,std::string> > v(1);
5251   v[0].first=oldName; v[0].second=newMeshName;
5252   changeNames(v);
5253 }
5254
5255 bool MEDFileMeshMultiTS::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab)
5256 {
5257   bool ret=false;
5258   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
5259     {
5260       MEDFileMesh *cur(*it);
5261       if(cur)
5262         ret=cur->changeNames(modifTab) || ret;
5263     }
5264   return ret;
5265 }
5266
5267 MEDFileMesh *MEDFileMeshMultiTS::getOneTimeStep() const
5268 {
5269   if(_mesh_one_ts.empty())
5270     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::getOneTimeStep : empty time step set !");
5271   return const_cast<MEDFileMesh *>(static_cast<const MEDFileMesh *>(_mesh_one_ts[0]));
5272 }
5273
5274 void MEDFileMeshMultiTS::setOneTimeStep(MEDFileMesh *mesh1TimeStep)
5275 {
5276   if(!mesh1TimeStep)
5277     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::setOneTimeStep : input pointer should be different from 0 !");
5278   _mesh_one_ts.resize(1);
5279   mesh1TimeStep->incrRef();
5280   //MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> toto=mesh1TimeStep;
5281   _mesh_one_ts[0]=mesh1TimeStep;
5282 }
5283
5284 void MEDFileMeshMultiTS::write(med_idt fid) const
5285 {
5286   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
5287     {
5288       (*it)->copyOptionsFrom(*this);
5289       (*it)->write(fid);
5290     }
5291 }
5292
5293 void MEDFileMeshMultiTS::write(const std::string& fileName, int mode) const
5294 {
5295   med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode);
5296   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),medmod);
5297   std::ostringstream oss; oss << "MEDFileMesh : error on attempt to write in file : \"" << fileName << "\""; 
5298   MEDFileUtilities::CheckMEDCode(fid,fid,oss.str());
5299   write(fid);
5300 }
5301
5302 void MEDFileMeshMultiTS::loadFromFile(const std::string& fileName, const std::string& mName)
5303 {//for the moment to be improved
5304   _mesh_one_ts.resize(1);
5305   _mesh_one_ts[0]=MEDFileMesh::New(fileName,mName,-1,-1);
5306 }
5307
5308 MEDFileMeshMultiTS::MEDFileMeshMultiTS()
5309 {
5310 }
5311
5312 MEDFileMeshMultiTS::MEDFileMeshMultiTS(const std::string& fileName)
5313 try
5314   {
5315     std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
5316     if(ms.empty())
5317     {
5318       std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
5319       throw INTERP_KERNEL::Exception(oss.str().c_str());
5320     }
5321     MEDFileUtilities::CheckFileForRead(fileName);
5322     MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
5323     int dt,it;
5324     ParaMEDMEM::MEDCouplingMeshType meshType;
5325     std::string dummy2;
5326     MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dt,it,dummy2);
5327     loadFromFile(fileName,ms.front());
5328   }
5329 catch(INTERP_KERNEL::Exception& e)
5330   {
5331     throw e;
5332   }
5333
5334 MEDFileMeshMultiTS::MEDFileMeshMultiTS(const std::string& fileName, const std::string& mName)
5335 try
5336   {
5337     loadFromFile(fileName,mName);
5338   }
5339 catch(INTERP_KERNEL::Exception& e)
5340   {
5341     throw e;
5342   }
5343
5344 MEDFileMeshes *MEDFileMeshes::New()
5345 {
5346   return new MEDFileMeshes;
5347 }
5348
5349 MEDFileMeshes *MEDFileMeshes::New(const std::string& fileName)
5350 {
5351   return new MEDFileMeshes(fileName);
5352 }
5353
5354 void MEDFileMeshes::write(med_idt fid) const
5355 {
5356   checkCoherency();
5357   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++)
5358     {
5359       (*it)->copyOptionsFrom(*this);
5360       (*it)->write(fid);
5361     }
5362 }
5363
5364 void MEDFileMeshes::write(const std::string& fileName, int mode) const
5365 {
5366   med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode);
5367   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),medmod);
5368   std::ostringstream oss; oss << "MEDFileMesh : error on attempt to write in file : \"" << fileName << "\""; 
5369   MEDFileUtilities::CheckMEDCode(fid,fid,oss.str());
5370   checkCoherency();
5371   write(fid);
5372 }
5373
5374 int MEDFileMeshes::getNumberOfMeshes() const
5375 {
5376   return _meshes.size();
5377 }
5378
5379 MEDFileMeshesIterator *MEDFileMeshes::iterator()
5380 {
5381   return new MEDFileMeshesIterator(this);
5382 }
5383
5384 MEDFileMesh *MEDFileMeshes::getMeshAtPos(int i) const
5385 {
5386   if(i<0 || i>=(int)_meshes.size())
5387     {
5388       std::ostringstream oss; oss << "MEDFileMeshes::getMeshAtPos : invalid mesh id given in parameter ! Should be in [0;" << _meshes.size() << ") !";
5389       throw INTERP_KERNEL::Exception(oss.str().c_str());
5390     }
5391   return _meshes[i]->getOneTimeStep();
5392 }
5393
5394 MEDFileMesh *MEDFileMeshes::getMeshWithName(const std::string& mname) const
5395 {
5396   std::vector<std::string> ms=getMeshesNames();
5397   std::vector<std::string>::iterator it=std::find(ms.begin(),ms.end(),mname);
5398   if(it==ms.end())
5399     {
5400       std::ostringstream oss; oss << "MEDFileMeshes::getMeshWithName : Mesh  \"" << mname << "\" does not exist in this ! Existing are : ";
5401       std::copy(ms.begin(),ms.end(),std::ostream_iterator<std::string>(oss," "));
5402       throw INTERP_KERNEL::Exception(oss.str().c_str());
5403     }
5404   return getMeshAtPos((int)std::distance(ms.begin(),it));
5405 }
5406
5407 std::vector<std::string> MEDFileMeshes::getMeshesNames() const
5408 {
5409   std::vector<std::string> ret(_meshes.size());
5410   int i=0;
5411   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
5412     {
5413       const MEDFileMeshMultiTS *f=(*it);
5414       if(f)
5415         {
5416           ret[i]=f->getName();
5417         }
5418       else
5419         {
5420           std::ostringstream oss; oss << "MEDFileMeshes::getMeshesNames : At rank #" << i << " mesh is not defined !";
5421           throw INTERP_KERNEL::Exception(oss.str().c_str());
5422         }
5423     }
5424   return ret;
5425 }
5426
5427 bool MEDFileMeshes::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab)
5428 {
5429   bool ret=false;
5430   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::iterator it=_meshes.begin();it!=_meshes.end();it++)
5431     {
5432       MEDFileMeshMultiTS *cur(*it);
5433       if(cur)
5434         ret=cur->changeNames(modifTab) || ret;
5435     }
5436   return ret;
5437 }
5438
5439 void MEDFileMeshes::resize(int newSize)
5440 {
5441   _meshes.resize(newSize);
5442 }
5443
5444 void MEDFileMeshes::pushMesh(MEDFileMesh *mesh)
5445 {
5446   if(!mesh)
5447     throw INTERP_KERNEL::Exception("MEDFileMeshes::pushMesh : invalid input pointer ! should be different from 0 !");
5448   MEDFileMeshMultiTS *elt=MEDFileMeshMultiTS::New();
5449   elt->setOneTimeStep(mesh);
5450   _meshes.push_back(elt);
5451 }
5452
5453 void MEDFileMeshes::setMeshAtPos(int i, MEDFileMesh *mesh)
5454 {
5455   if(!mesh)
5456     throw INTERP_KERNEL::Exception("MEDFileMeshes::setMeshAtPos : invalid input pointer ! should be different from 0 !");
5457   if(i>=(int)_meshes.size())
5458     _meshes.resize(i+1);
5459   MEDFileMeshMultiTS *elt=MEDFileMeshMultiTS::New();
5460   elt->setOneTimeStep(mesh);
5461   _meshes[i]=elt;
5462 }
5463
5464 void MEDFileMeshes::destroyMeshAtPos(int i)
5465 {
5466   if(i<0 || i>=(int)_meshes.size())
5467     {
5468       std::ostringstream oss; oss << "MEDFileMeshes::destroyMeshAtPos : Invalid given id in input (" << i << ") should be in [0," << _meshes.size() << ") !";
5469       throw INTERP_KERNEL::Exception(oss.str().c_str());
5470     }
5471   _meshes.erase(_meshes.begin()+i);
5472 }
5473
5474 void MEDFileMeshes::loadFromFile(const std::string& fileName)
5475 {
5476   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
5477   int i=0;
5478   _meshes.resize(ms.size());
5479   for(std::vector<std::string>::const_iterator it=ms.begin();it!=ms.end();it++,i++)
5480     _meshes[i]=MEDFileMeshMultiTS::New(fileName,(*it));
5481 }
5482
5483 MEDFileMeshes::MEDFileMeshes()
5484 {
5485 }
5486
5487 MEDFileMeshes::MEDFileMeshes(const std::string& fileName)
5488 try
5489   {
5490     loadFromFile(fileName);
5491   }
5492 catch(INTERP_KERNEL::Exception& /*e*/)
5493   {
5494   }
5495
5496 MEDFileMeshes *MEDFileMeshes::deepCpy() const
5497 {
5498   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> > meshes(_meshes.size());
5499   std::size_t i=0;
5500   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
5501     if((const MEDFileMeshMultiTS *)*it)
5502       meshes[i]=(*it)->deepCpy();
5503   MEDCouplingAutoRefCountObjectPtr<MEDFileMeshes> ret=MEDFileMeshes::New();
5504   ret->_meshes=meshes;
5505   return ret.retn();
5506 }
5507
5508 std::size_t MEDFileMeshes::getHeapMemorySizeWithoutChildren() const
5509 {
5510   return _meshes.capacity()*(sizeof(MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS>));
5511 }
5512
5513 std::vector<const BigMemoryObject *> MEDFileMeshes::getDirectChildren() const
5514 {
5515   std::vector<const BigMemoryObject *> ret;
5516   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++)
5517     {
5518       const MEDFileMeshMultiTS *cur(*it);
5519       if(cur)
5520         ret.push_back(cur);
5521     }
5522   return ret;
5523 }
5524
5525 std::string MEDFileMeshes::simpleRepr() const
5526 {
5527   std::ostringstream oss;
5528   oss << "(*****************)\n(* MEDFileMeshes *)\n(*****************)\n\n";
5529   simpleReprWithoutHeader(oss);
5530   return oss.str();
5531 }
5532
5533 void MEDFileMeshes::simpleReprWithoutHeader(std::ostream& oss) const
5534 {
5535   int nbOfMeshes=getNumberOfMeshes();
5536   oss << "There are " << nbOfMeshes << " meshes with the following names : \n";
5537   std::vector<std::string> mns=getMeshesNames();
5538   for(int i=0;i<nbOfMeshes;i++)
5539     oss << "  - #" << i << " \"" << mns[i] << "\"\n";
5540 }
5541
5542 void MEDFileMeshes::checkCoherency() const
5543 {
5544   static const char MSG[]="MEDFileMeshes::checkCoherency : mesh at rank ";
5545   int i=0;
5546   std::set<std::string> s;
5547   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
5548     {
5549       const MEDFileMeshMultiTS *elt=(*it);
5550       if(!elt)
5551         {
5552           std::ostringstream oss; oss << MSG << i << "/" << _meshes.size() << " is empty !";
5553           throw INTERP_KERNEL::Exception(oss.str().c_str());
5554         }
5555       std::size_t sz=s.size();
5556       s.insert(std::string((*it)->getName()));
5557       if(s.size()==sz)
5558         {
5559           std::ostringstream oss; oss << MSG << i << " has a name (\"" << (*it)->getName() << "\") already used by an another mesh in list !";
5560           throw INTERP_KERNEL::Exception(oss.str().c_str());
5561         }
5562     }
5563 }
5564
5565 MEDFileMeshesIterator::MEDFileMeshesIterator(MEDFileMeshes *ms):_ms(ms),_iter_id(0),_nb_iter(0)
5566 {
5567   if(ms)
5568     {
5569       ms->incrRef();
5570       _nb_iter=ms->getNumberOfMeshes();
5571     }
5572 }
5573
5574 MEDFileMeshesIterator::~MEDFileMeshesIterator()
5575 {
5576 }
5577
5578 MEDFileMesh *MEDFileMeshesIterator::nextt()
5579 {
5580   if(_iter_id<_nb_iter)
5581     {
5582       MEDFileMeshes *ms(_ms);
5583       if(ms)
5584         return ms->getMeshAtPos(_iter_id++);
5585       else
5586         return 0;
5587     }
5588   else
5589     return 0;
5590 }