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