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