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