Salome HOME
On the road of ParaMEDReader for fields.
[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   ret.push_back((const PartDefinition *)_part_coords);
2036   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2037     ret.push_back((const MEDFileUMeshSplitL1*) *it);
2038   return ret;
2039 }
2040
2041 MEDFileMesh *MEDFileUMesh::shallowCpy() const
2042 {
2043   MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret=new MEDFileUMesh(*this);
2044   return ret.retn();
2045 }
2046
2047 MEDFileMesh *MEDFileUMesh::createNewEmpty() const
2048 {
2049   return new MEDFileUMesh;
2050 }
2051
2052 MEDFileMesh *MEDFileUMesh::deepCpy() const
2053 {
2054   MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret=new MEDFileUMesh(*this);
2055   if((const DataArrayDouble*)_coords)
2056     ret->_coords=_coords->deepCpy();
2057   if((const DataArrayInt*)_fam_coords)
2058     ret->_fam_coords=_fam_coords->deepCpy();
2059   if((const DataArrayInt*)_num_coords)
2060     ret->_num_coords=_num_coords->deepCpy();
2061   if((const DataArrayInt*)_rev_num_coords)
2062     ret->_rev_num_coords=_rev_num_coords->deepCpy();
2063   if((const DataArrayAsciiChar*)_name_coords)
2064     ret->_name_coords=_name_coords->deepCpy();
2065   std::size_t i=0;
2066   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,i++)
2067     {
2068       if((const MEDFileUMeshSplitL1 *)(*it))
2069         ret->_ms[i]=(*it)->deepCpy(ret->_coords);
2070     }
2071   return ret.retn();
2072 }
2073
2074 /*!
2075  * Checks if \a this and another mesh are equal.
2076  *  \param [in] other - the mesh to compare with.
2077  *  \param [in] eps - a precision used to compare real values.
2078  *  \param [in,out] what - the string returning description of unequal data.
2079  *  \return bool - \c true if the meshes are equal, \c false, else.
2080  */
2081 bool MEDFileUMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
2082 {
2083   if(!MEDFileMesh::isEqual(other,eps,what))
2084     return false;
2085   const MEDFileUMesh *otherC=dynamic_cast<const MEDFileUMesh *>(other);
2086   if(!otherC)
2087     {
2088       what="Mesh types differ ! This is unstructured and other is NOT !";
2089       return false;
2090     }
2091   clearNonDiscrAttributes();
2092   otherC->clearNonDiscrAttributes();
2093   const DataArrayDouble *coo1=_coords;
2094   const DataArrayDouble *coo2=otherC->_coords;
2095   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
2096     {
2097       what="Mismatch of coordinates ! One is defined and not other !";
2098       return false;
2099     }
2100   if(coo1)
2101     {
2102       bool ret=coo1->isEqual(*coo2,eps);
2103       if(!ret)
2104         {
2105           what="Coords differ !";
2106           return false;
2107         }
2108     }
2109   const DataArrayInt *famc1=_fam_coords;
2110   const DataArrayInt *famc2=otherC->_fam_coords;
2111   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
2112     {
2113       what="Mismatch of families arr on nodes ! One is defined and not other !";
2114       return false;
2115     }
2116   if(famc1)
2117     {
2118       bool ret=famc1->isEqual(*famc2);
2119       if(!ret)
2120         {
2121           what="Families arr on node differ !";
2122           return false;
2123         }
2124     }
2125   const DataArrayInt *numc1=_num_coords;
2126   const DataArrayInt *numc2=otherC->_num_coords;
2127   if((numc1==0 && numc2!=0) || (numc1!=0 && numc2==0))
2128     {
2129       what="Mismatch of numbering arr on nodes ! One is defined and not other !";
2130       return false;
2131     }
2132   if(numc1)
2133     {
2134       bool ret=numc1->isEqual(*numc2);
2135       if(!ret)
2136         {
2137           what="Numbering arr on node differ !";
2138           return false;
2139         }
2140     }
2141   const DataArrayAsciiChar *namec1=_name_coords;
2142   const DataArrayAsciiChar *namec2=otherC->_name_coords;
2143   if((namec1==0 && namec2!=0) || (namec1!=0 && namec2==0))
2144     {
2145       what="Mismatch of naming arr on nodes ! One is defined and not other !";
2146       return false;
2147     }
2148   if(namec1)
2149     {
2150       bool ret=namec1->isEqual(*namec2);
2151       if(!ret)
2152         {
2153           what="Names arr on node differ !";
2154           return false;
2155         }
2156     }
2157   if(_ms.size()!=otherC->_ms.size())
2158     {
2159       what="Number of levels differs !";
2160       return false;
2161     }
2162   std::size_t sz=_ms.size();
2163   for(std::size_t i=0;i<sz;i++)
2164     {
2165       const MEDFileUMeshSplitL1 *s1=_ms[i];
2166       const MEDFileUMeshSplitL1 *s2=otherC->_ms[i];
2167       if((s1==0 && s2!=0) || (s1!=0 && s2==0))
2168         {
2169           what="Mismatch of presence of sub levels !";
2170           return false;
2171         }
2172       if(s1)
2173         {
2174           bool ret=s1->isEqual(s2,eps,what);
2175           if(!ret)
2176             return false;
2177         }
2178     }
2179   return true;
2180 }
2181
2182 /*!
2183  * Clears redundant attributes of incorporated data arrays.
2184  */
2185 void MEDFileUMesh::clearNonDiscrAttributes() const
2186 {
2187   MEDFileMesh::clearNonDiscrAttributes();
2188   const DataArrayDouble *coo1=_coords;
2189   if(coo1)
2190     (const_cast<DataArrayDouble *>(coo1))->setName("");//This parameter is not discriminant for comparison
2191   const DataArrayInt *famc1=_fam_coords;
2192   if(famc1)
2193     (const_cast<DataArrayInt *>(famc1))->setName("");//This parameter is not discriminant for comparison
2194   const DataArrayInt *numc1=_num_coords;
2195   if(numc1)
2196     (const_cast<DataArrayInt *>(numc1))->setName("");//This parameter is not discriminant for comparison
2197   const DataArrayAsciiChar *namc1=_name_coords;
2198   if(namc1)
2199     (const_cast<DataArrayAsciiChar *>(namc1))->setName("");//This parameter is not discriminant for comparison
2200   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2201     {
2202       const MEDFileUMeshSplitL1 *tmp=(*it);
2203       if(tmp)
2204         tmp->clearNonDiscrAttributes();
2205     }
2206 }
2207
2208 void MEDFileUMesh::setName(const std::string& name)
2209 {
2210   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
2211     if((MEDFileUMeshSplitL1 *)(*it)!=0)
2212       (*it)->setName(name);
2213   MEDFileMesh::setName(name);
2214 }
2215
2216 MEDFileUMesh::MEDFileUMesh()
2217 {
2218 }
2219
2220 MEDFileUMesh::MEDFileUMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
2221 try
2222 {
2223     loadUMeshFromFile(fid,mName,dt,it,mrs);
2224 }
2225 catch(INTERP_KERNEL::Exception& e)
2226 {
2227     throw e;
2228 }
2229
2230 /*!
2231  * This method loads only a part of specified cells (given by range of cell ID per geometric type)
2232  * See MEDFileUMesh::LoadPartOf for detailed description.
2233  *
2234  * \sa loadUMeshFromFile
2235  */
2236 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)
2237 {
2238   MEDFileUMeshL2 loaderl2;
2239   ParaMEDMEM::MEDCouplingMeshType meshType;
2240   int dummy0,dummy1;
2241   std::string dummy2;
2242   int mid(MEDFileUMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dummy2));
2243   if(meshType!=UNSTRUCTURED)
2244     {
2245       std::ostringstream oss; oss << "loadPartUMeshFromFile : Trying to load as unstructured an existing mesh with name '" << mName << "' !";
2246       throw INTERP_KERNEL::Exception(oss.str().c_str());
2247     }
2248   loaderl2.loadPart(fid,mid,mName,types,slicPerTyp,dt,it,mrs);
2249   dispatchLoadedPart(fid,loaderl2,mName,mrs);
2250 }
2251
2252 /*!
2253  * This method loads \b all \b the \b mesh \a mName in the file with \a fid descriptor.
2254  *
2255  * \sa loadPartUMeshFromFile
2256  */
2257 void MEDFileUMesh::loadUMeshFromFile(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
2258 {
2259   MEDFileUMeshL2 loaderl2;
2260   ParaMEDMEM::MEDCouplingMeshType meshType;
2261   int dummy0,dummy1;
2262   std::string dummy2;
2263   int mid(MEDFileUMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dummy2));
2264   if(meshType!=UNSTRUCTURED)
2265     {
2266       std::ostringstream oss; oss << "Trying to load as unstructured an existing mesh with name '" << mName << "' !";
2267       throw INTERP_KERNEL::Exception(oss.str().c_str());
2268     }
2269   loaderl2.loadAll(fid,mid,mName,dt,it,mrs);
2270   dispatchLoadedPart(fid,loaderl2,mName,mrs);
2271
2272 }
2273
2274 void MEDFileUMesh::dispatchLoadedPart(med_idt fid, const MEDFileUMeshL2& loaderl2, const std::string& mName, MEDFileMeshReadSelector *mrs)
2275 {
2276   int lev=loaderl2.getNumberOfLevels();
2277   _ms.resize(lev);
2278   for(int i=0;i<lev;i++)
2279     {
2280       if(!loaderl2.emptyLev(i))
2281         _ms[i]=new MEDFileUMeshSplitL1(loaderl2,mName,i);
2282       else
2283         _ms[i]=0;
2284     }
2285   MEDFileMeshL2::ReadFamiliesAndGrps(fid,mName,_families,_groups,mrs);
2286   //
2287   setName(loaderl2.getName());
2288   setDescription(loaderl2.getDescription());
2289   setUnivName(loaderl2.getUnivName());
2290   setIteration(loaderl2.getIteration());
2291   setOrder(loaderl2.getOrder());
2292   setTimeValue(loaderl2.getTime());
2293   setTimeUnit(loaderl2.getTimeUnit());
2294   _coords=loaderl2.getCoords();
2295   if(!mrs || mrs->isNodeFamilyFieldReading())
2296     _fam_coords=loaderl2.getCoordsFamily();
2297   if(!mrs || mrs->isNodeNumFieldReading())
2298     _num_coords=loaderl2.getCoordsNum();
2299   if(!mrs || mrs->isNodeNameFieldReading())
2300     _name_coords=loaderl2.getCoordsName();
2301   _part_coords=loaderl2.getPartDefOfCoo();
2302   computeRevNum();
2303 }
2304
2305 MEDFileUMesh::~MEDFileUMesh()
2306 {
2307 }
2308
2309 void MEDFileUMesh::writeLL(med_idt fid) const
2310 {
2311   const DataArrayDouble *coo=_coords;
2312   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
2313   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
2314   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
2315   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
2316   int spaceDim=coo?coo->getNumberOfComponents():0;
2317   int mdim=getMeshDimension();
2318   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
2319   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
2320   for(int i=0;i<spaceDim;i++)
2321     {
2322       std::string info=coo->getInfoOnComponent(i);
2323       std::string c,u;
2324       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
2325       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
2326       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
2327     }
2328   MEDmeshCr(fid,maa,spaceDim,mdim,MED_UNSTRUCTURED_MESH,desc,"",MED_SORT_DTIT,MED_CARTESIAN,comp,unit);
2329   MEDmeshUniversalNameWr(fid,maa);
2330   std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE));
2331   MEDFileUMeshL2::WriteCoords(fid,meshName,_iteration,_order,_time,_coords,_fam_coords,_num_coords,_name_coords);
2332   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2333     if((const MEDFileUMeshSplitL1 *)(*it)!=0)
2334       (*it)->write(fid,meshName,mdim);
2335   MEDFileUMeshL2::WriteFamiliesAndGrps(fid,meshName,_families,_groups,_too_long_str);
2336 }
2337
2338 /*!
2339  * Returns relative dimensions of mesh entities (excluding nodes) present in \a this mesh.
2340  *  \return std::vector<int> - a sequence of the relative dimensions.
2341  */
2342 std::vector<int> MEDFileUMesh::getNonEmptyLevels() const
2343 {
2344   std::vector<int> ret;
2345   int lev=0;
2346   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
2347     if((const MEDFileUMeshSplitL1 *)(*it)!=0)
2348       if(!(*it)->empty())
2349         ret.push_back(lev);
2350   return ret;
2351 }
2352
2353 /*!
2354  * Returns relative dimensions of mesh entities (including nodes) present in \a this mesh.
2355  *  \return std::vector<int> - a sequence of the relative dimensions.
2356  */
2357 std::vector<int> MEDFileUMesh::getNonEmptyLevelsExt() const
2358 {
2359   std::vector<int> ret0=getNonEmptyLevels();
2360   if((const DataArrayDouble *) _coords)
2361     {
2362       std::vector<int> ret(ret0.size()+1);
2363       ret[0]=1;
2364       std::copy(ret0.begin(),ret0.end(),ret.begin()+1);
2365       return ret;
2366     }
2367   return ret0;
2368 }
2369
2370 std::vector<int> MEDFileUMesh::getFamArrNonEmptyLevelsExt() const
2371 {
2372   std::vector<int> ret;
2373   const DataArrayInt *famCoo(_fam_coords);
2374   if(famCoo)
2375     ret.push_back(1);
2376   int lev=0;
2377   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
2378     {
2379       const MEDFileUMeshSplitL1 *cur(*it);
2380       if(cur)
2381         if(cur->getFamilyField())
2382           ret.push_back(lev);
2383     }
2384   return ret;
2385 }
2386
2387 std::vector<int> MEDFileUMesh::getNumArrNonEmptyLevelsExt() const
2388 {
2389   std::vector<int> ret;
2390   const DataArrayInt *numCoo(_num_coords);
2391   if(numCoo)
2392     ret.push_back(1);
2393   int lev=0;
2394   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
2395     {
2396       const MEDFileUMeshSplitL1 *cur(*it);
2397       if(cur)
2398         if(cur->getNumberField())
2399           ret.push_back(lev);
2400     }
2401   return ret;
2402 }
2403
2404 std::vector<int> MEDFileUMesh::getNameArrNonEmptyLevelsExt() const
2405 {
2406   std::vector<int> ret;
2407   const DataArrayAsciiChar *nameCoo(_name_coords);
2408   if(nameCoo)
2409     ret.push_back(1);
2410   int lev=0;
2411   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
2412     {
2413       const MEDFileUMeshSplitL1 *cur(*it);
2414       if(cur)
2415         if(cur->getNameField())
2416           ret.push_back(lev);
2417     }
2418   return ret;
2419 }
2420
2421 /*!
2422  * Returns all relative mesh levels (**excluding nodes**) where a given group is defined.
2423  * To include nodes, call getGrpNonEmptyLevelsExt() method.
2424  *  \param [in] grp - the name of the group of interest.
2425  *  \return std::vector<int> - a sequence of the relative dimensions.
2426  */
2427 std::vector<int> MEDFileUMesh::getGrpNonEmptyLevels(const std::string& grp) const
2428 {
2429   std::vector<std::string> fams=getFamiliesOnGroup(grp);
2430   return getFamsNonEmptyLevels(fams);
2431 }
2432
2433 /*!
2434  * Returns all relative mesh levels (including nodes) where a given group is defined.
2435  *  \param [in] grp - the name of the group of interest.
2436  *  \return std::vector<int> - a sequence of the relative dimensions.
2437  */
2438 std::vector<int> MEDFileUMesh::getGrpNonEmptyLevelsExt(const std::string& grp) const
2439 {
2440   std::vector<std::string> fams=getFamiliesOnGroup(grp);
2441   return getFamsNonEmptyLevelsExt(fams);
2442 }
2443
2444 /*!
2445  * Returns all relative mesh levels (**excluding nodes**) where a given family is defined.
2446  * To include nodes, call getFamNonEmptyLevelsExt() method.
2447  *  \param [in] fam - the name of the family of interest.
2448  *  \return std::vector<int> - a sequence of the relative dimensions.
2449  */
2450 std::vector<int> MEDFileUMesh::getFamNonEmptyLevels(const std::string& fam) const
2451 {
2452   std::vector<std::string> fams(1,std::string(fam));
2453   return getFamsNonEmptyLevels(fams);
2454 }
2455
2456 /*!
2457  * Returns all relative mesh levels (including nodes) where a given family is defined.
2458  *  \param [in] fam - the name of the family of interest.
2459  *  \return std::vector<int> - a sequence of the relative dimensions.
2460  */
2461 std::vector<int> MEDFileUMesh::getFamNonEmptyLevelsExt(const std::string& fam) const
2462 {
2463   std::vector<std::string> fams(1,std::string(fam));
2464   return getFamsNonEmptyLevelsExt(fams);
2465 }
2466
2467 /*!
2468  * Returns all relative mesh levels (**excluding nodes**) where given groups are defined.
2469  * To include nodes, call getGrpsNonEmptyLevelsExt() method.
2470  *  \param [in] grps - a sequence of names of the groups of interest.
2471  *  \return std::vector<int> - a sequence of the relative dimensions.
2472  */
2473 std::vector<int> MEDFileUMesh::getGrpsNonEmptyLevels(const std::vector<std::string>& grps) const
2474 {
2475   std::vector<std::string> fams=getFamiliesOnGroups(grps);
2476   return getFamsNonEmptyLevels(fams);
2477 }
2478
2479 /*!
2480  * Returns all relative mesh levels (including nodes) where given groups are defined.
2481  *  \param [in] grps - a sequence of names of the groups of interest.
2482  *  \return std::vector<int> - a sequence of the relative dimensions.
2483  */
2484 std::vector<int> MEDFileUMesh::getGrpsNonEmptyLevelsExt(const std::vector<std::string>& grps) const
2485 {
2486   std::vector<std::string> fams=getFamiliesOnGroups(grps);
2487   return getFamsNonEmptyLevelsExt(fams);
2488 }
2489
2490 /*!
2491  * Returns all relative mesh levels (**excluding nodes**) where given families are defined.
2492  * To include nodes, call getFamsNonEmptyLevelsExt() method.
2493  *  \param [in] fams - the name of the family of interest.
2494  *  \return std::vector<int> - a sequence of the relative dimensions.
2495  */
2496 std::vector<int> MEDFileUMesh::getFamsNonEmptyLevels(const std::vector<std::string>& fams) const
2497 {
2498   std::vector<int> ret;
2499   std::vector<int> levs=getNonEmptyLevels();
2500   std::vector<int> famIds=getFamiliesIds(fams);
2501   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
2502     if(_ms[-(*it)]->presenceOfOneFams(famIds))
2503       ret.push_back(*it);
2504   return ret;
2505 }
2506
2507 /*!
2508  * Returns all relative mesh levels (including nodes) where given families are defined.
2509  *  \param [in] fams - the names of the families of interest.
2510  *  \return std::vector<int> - a sequence of the relative dimensions.
2511  */
2512 std::vector<int> MEDFileUMesh::getFamsNonEmptyLevelsExt(const std::vector<std::string>& fams) const
2513 {
2514   std::vector<int> ret0=getFamsNonEmptyLevels(fams);
2515   const DataArrayInt *famCoords=_fam_coords;
2516   if(!famCoords)
2517     return ret0;
2518   std::vector<int> famIds=getFamiliesIds(fams);
2519   if(famCoords->presenceOfValue(famIds))
2520     {
2521       std::vector<int> ret(ret0.size()+1);
2522       ret[0]=1;
2523       std::copy(ret0.begin(),ret0.end(),ret.begin()+1);
2524       return ret;
2525     }
2526   else
2527     return ret0;
2528 }
2529
2530 /*!
2531  * Returns names of groups that partly or fully appear on the level \a meshDimRelToMaxExt.
2532  *  \param [in] meshDimRelToMaxExt - a relative dimension of interest.
2533  *  \return std::vector<std::string> - a sequence of group names at \a meshDimRelToMaxExt
2534  *          level. 
2535  */
2536 std::vector<std::string> MEDFileUMesh::getGroupsOnSpecifiedLev(int meshDimRelToMaxExt) const
2537 {
2538   std::vector<std::string> ret;
2539   std::vector<std::string> allGrps=getGroupsNames();
2540   for(std::vector<std::string>::const_iterator it=allGrps.begin();it!=allGrps.end();it++)
2541     {
2542       std::vector<int> levs=getGrpNonEmptyLevelsExt((*it));
2543       if(std::find(levs.begin(),levs.end(),meshDimRelToMaxExt)!=levs.end())
2544         ret.push_back(*it);
2545     }
2546   return ret;
2547 }
2548
2549 int MEDFileUMesh::getMaxAbsFamilyIdInArrays() const
2550 {
2551   int ret=-std::numeric_limits<int>::max(),tmp=-1;
2552   if((const DataArrayInt *)_fam_coords)
2553     {
2554       int val=_fam_coords->getMaxValue(tmp);
2555       ret=std::max(ret,std::abs(val));
2556     }
2557   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2558     {
2559       if((const MEDFileUMeshSplitL1 *)(*it))
2560         {
2561           const DataArrayInt *da=(*it)->getFamilyField();
2562           if(da)
2563             {
2564               int val=da->getMaxValue(tmp);
2565               ret=std::max(ret,std::abs(val));
2566             }
2567         }
2568     }
2569   return ret;
2570 }
2571
2572 int MEDFileUMesh::getMaxFamilyIdInArrays() const
2573 {
2574   int ret=-std::numeric_limits<int>::max(),tmp=-1;
2575   if((const DataArrayInt *)_fam_coords)
2576     {
2577       int val=_fam_coords->getMaxValue(tmp);
2578       ret=std::max(ret,val);
2579     }
2580   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2581     {
2582       if((const MEDFileUMeshSplitL1 *)(*it))
2583         {
2584           const DataArrayInt *da=(*it)->getFamilyField();
2585           if(da)
2586             {
2587               int val=da->getMaxValue(tmp);
2588               ret=std::max(ret,val);
2589             }
2590         }
2591     }
2592   return ret;
2593 }
2594
2595 int MEDFileUMesh::getMinFamilyIdInArrays() const
2596 {
2597   int ret=std::numeric_limits<int>::max(),tmp=-1;
2598   if((const DataArrayInt *)_fam_coords)
2599     {
2600       int val=_fam_coords->getMinValue(tmp);
2601       ret=std::min(ret,val);
2602     }
2603   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2604     {
2605       if((const MEDFileUMeshSplitL1 *)(*it))
2606         {
2607           const DataArrayInt *da=(*it)->getFamilyField();
2608           if(da)
2609             {
2610               int val=da->getMinValue(tmp);
2611               ret=std::min(ret,val);
2612             }
2613         }
2614     }
2615   return ret;
2616 }
2617
2618 /*!
2619  * Returns the dimension on cells in \a this mesh.
2620  *  \return int - the mesh dimension.
2621  *  \throw If there are no cells in this mesh.
2622  */
2623 int MEDFileUMesh::getMeshDimension() const
2624 {
2625   int lev=0;
2626   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev++)
2627     if((const MEDFileUMeshSplitL1 *)(*it)!=0)
2628       return (*it)->getMeshDimension()+lev;
2629   throw INTERP_KERNEL::Exception("MEDFileUMesh::getMeshDimension : impossible to find a mesh dimension !");
2630 }
2631
2632 /*!
2633  * Returns the space dimension of \a this mesh that is equal to number of components in
2634  * the node coordinates array.
2635  *  \return int - the space dimension of \a this mesh.
2636  *  \throw If the node coordinates array is not available.
2637  */
2638 int MEDFileUMesh::getSpaceDimension() const
2639 {
2640   const DataArrayDouble *coo=_coords;
2641   if(!coo)
2642     throw INTERP_KERNEL::Exception(" MEDFileUMesh::getSpaceDimension : no coords set !");
2643   return coo->getNumberOfComponents();
2644 }
2645
2646 /*!
2647  * Returns a string describing \a this mesh.
2648  *  \return std::string - the mesh information string.
2649  */
2650 std::string MEDFileUMesh::simpleRepr() const
2651 {
2652   std::ostringstream oss;
2653   oss << MEDFileMesh::simpleRepr();
2654   const DataArrayDouble *coo=_coords;
2655   oss << "- The dimension of the space is ";
2656   static const char MSG1[]= "*** NO COORDS SET ***";
2657   static const char MSG2[]= "*** NO CONNECTIVITY SET FOR THIS LEVEL***";
2658   if(coo)
2659     oss << _coords->getNumberOfComponents() << std::endl;
2660   else
2661     oss << MSG1 << std::endl;
2662   oss << "- Type of the mesh : UNSTRUCTURED\n";
2663   oss << "- Number of nodes : ";
2664   if(coo)
2665     oss << _coords->getNumberOfTuples() << std::endl;
2666   else
2667     oss << MSG1 << std::endl;
2668   std::size_t nbOfLev=_ms.size();
2669   oss << "- Number of levels allocated : " << nbOfLev << std::endl;
2670   for(std::size_t i=0;i<nbOfLev;i++)
2671     {
2672       const MEDFileUMeshSplitL1 *lev=_ms[i];
2673       oss << "  - Level #" << -((int) i) << " has dimension : ";
2674       if(lev)
2675         {
2676           oss << lev->getMeshDimension() << std::endl;
2677           lev->simpleRepr(oss);
2678         }
2679       else
2680         oss << MSG2 << std::endl;
2681     }
2682   oss << "- Number of families : " << _families.size() << std::endl << std::endl;
2683   if(coo)
2684     {
2685       oss << "(***********************)\n(* NODES OF THE MESH : *)\n(***********************)\n";
2686       oss << "- Names of coordinates :" << std::endl;
2687       std::vector<std::string> vars=coo->getVarsOnComponent();
2688       std::copy(vars.begin(),vars.end(),std::ostream_iterator<std::string>(oss," "));
2689       oss << std::endl << "- Units of coordinates : " << std::endl;
2690       std::vector<std::string> units=coo->getUnitsOnComponent();
2691       std::copy(units.begin(),units.end(),std::ostream_iterator<std::string>(oss," "));
2692     }
2693   oss << std::endl << std::endl;
2694   getFamilyRepr(oss);
2695   return oss.str();
2696 }
2697
2698 /*!
2699  * Returns a full textual description of \a this mesh.
2700  *  \return std::string - the string holding the mesh description.
2701  */
2702 std::string MEDFileUMesh::advancedRepr() const
2703 {
2704   return simpleRepr();
2705 }
2706
2707 /*!
2708  * Returns number of mesh entities of a given relative dimension in \a this mesh.
2709  *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
2710  *  \return int - the number of entities.
2711  *  \throw If no mesh entities of dimension \a meshDimRelToMaxExt are available in \a this mesh.
2712  */
2713 int MEDFileUMesh::getSizeAtLevel(int meshDimRelToMaxExt) const
2714 {
2715   if(meshDimRelToMaxExt==1)
2716     {
2717       if(!((const DataArrayDouble *)_coords))
2718         throw INTERP_KERNEL::Exception("MEDFileUMesh::getSizeAtLevel : no coordinates specified !");
2719       return _coords->getNumberOfTuples();
2720     }
2721   return getMeshAtLevSafe(meshDimRelToMaxExt)->getSize();
2722 }
2723
2724 /*!
2725  * Returns the family field for mesh entities of a given dimension.
2726  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
2727  *  \return const DataArrayInt * - the family field. It is an array of ids of families
2728  *          each mesh entity belongs to. It can be \c NULL.
2729  */
2730 const DataArrayInt *MEDFileUMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) const
2731 {
2732   if(meshDimRelToMaxExt==1)
2733     return _fam_coords;
2734   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2735   return l1->getFamilyField();
2736 }
2737
2738 /*!
2739  * Returns the optional numbers of mesh entities of a given dimension.
2740  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
2741  *  \return const DataArrayInt * - the array of the entity numbers.
2742  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2743  */
2744 const DataArrayInt *MEDFileUMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) const
2745 {
2746   if(meshDimRelToMaxExt==1)
2747     return _num_coords;
2748   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2749   return l1->getNumberField();
2750 }
2751
2752 const DataArrayAsciiChar *MEDFileUMesh::getNameFieldAtLevel(int meshDimRelToMaxExt) const
2753 {
2754   if(meshDimRelToMaxExt==1)
2755     return _name_coords;
2756   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2757   return l1->getNameField();
2758 }
2759
2760 /*!
2761  * This method returns for a specified relative level \a meshDimRelToMaxExt the part effectively read (if the instance is the result of the read of a file).
2762  *
2763  * \param [in] meshDimRelToMaxExt - the extended relative level for which the part definition is requested.
2764  * \param [in] gt - The input geometric type for which the part definition is requested.
2765  * \return the part definition owned by \a this. So no need to deallocate the returned instance.
2766  */
2767 const PartDefinition *MEDFileUMesh::getPartDefAtLevel(int meshDimRelToMaxExt, INTERP_KERNEL::NormalizedCellType gt) const
2768 {
2769   if(meshDimRelToMaxExt==1)
2770     return _part_coords;
2771   const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMaxExt));
2772   return l1->getPartDef(gt);
2773 }
2774
2775 int MEDFileUMesh::getNumberOfNodes() const
2776 {
2777   const DataArrayDouble *coo=_coords;
2778   if(!coo)
2779     throw INTERP_KERNEL::Exception(" MEDFileUMesh::getNumberOfNodes : no coords set !");
2780   return coo->getNumberOfTuples();
2781 }
2782
2783 bool MEDFileUMesh::hasImplicitPart() const
2784 {
2785   return false;
2786 }
2787
2788 int MEDFileUMesh::buildImplicitPartIfAny(INTERP_KERNEL::NormalizedCellType gt) const
2789 {
2790   throw INTERP_KERNEL::Exception("MEDFileUMesh::buildImplicitPartIfAny : unstructured meshes do not have implicit part !");
2791 }
2792
2793 void MEDFileUMesh::releaseImplicitPartIfAny() const
2794 {
2795 }
2796
2797 void MEDFileUMesh::whichAreNodesFetched(const MEDFileField1TSStructItem& st, const MEDFileFieldGlobsReal *globs, std::vector<bool>& nodesFetched) const
2798 {
2799   std::size_t sz(st.getNumberOfItems());
2800   for(std::size_t i=0;i<sz;i++)
2801     {
2802       INTERP_KERNEL::NormalizedCellType curGt(st[i].getGeo());
2803       const MEDCoupling1GTUMesh *m(getDirectUndergroundSingleGeoTypeMesh(curGt));
2804       if(st[i].getPflName().empty())
2805         m->computeNodeIdsAlg(nodesFetched);
2806       else
2807         {
2808           const DataArrayInt *arr(globs->getProfile(st[i].getPflName()));
2809           MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> m2(dynamic_cast<MEDCoupling1GTUMesh *>(m->buildPartOfMySelf(arr->begin(),arr->end(),true)));
2810           m2->computeNodeIdsAlg(nodesFetched);
2811         }
2812     }
2813 }
2814
2815 /*!
2816  * Returns the optional numbers of mesh entities of a given dimension transformed using
2817  * DataArrayInt::invertArrayN2O2O2N().
2818  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
2819  *  \return const DataArrayInt * - the array of the entity numbers transformed using
2820  *          DataArrayInt::invertArrayN2O2O2N().
2821  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2822  */
2823 const DataArrayInt *MEDFileUMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxExt) const
2824 {
2825   if(meshDimRelToMaxExt==1)
2826     {
2827       if(!((const DataArrayInt *)_num_coords))
2828         throw INTERP_KERNEL::Exception("MEDFileUMesh::getRevNumberFieldAtLevel : no coordinates renum specified !");
2829       return _rev_num_coords;
2830     }
2831   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2832   return l1->getRevNumberField();
2833 }
2834
2835 /*!
2836  * Returns a pointer to the node coordinates array of \a this mesh \b without
2837  * incrementing its reference counter, thus there is no need to decrRef() it by the caller.
2838  */
2839 DataArrayDouble *MEDFileUMesh::getCoords() const
2840 {
2841   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp(_coords);
2842   if((DataArrayDouble *)tmp)
2843     {
2844       return tmp;
2845     }
2846   return 0;
2847 }
2848
2849 /*!
2850  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in a given
2851  * group of \a this mesh. Only mesh entities of a given dimension are included in the
2852  * new mesh.
2853  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
2854  *  \param [in] grp - the name of the group whose mesh entities are included in the
2855  *          new mesh.
2856  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
2857  *          according to the optional numbers of entities, if available.
2858  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
2859  *          delete this mesh using decrRef() as it is no more needed.
2860  *  \throw If the name of a nonexistent group is specified.
2861  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2862  */
2863 MEDCouplingUMesh *MEDFileUMesh::getGroup(int meshDimRelToMaxExt, const std::string& grp, bool renum) const
2864 {
2865   synchronizeTinyInfoOnLeaves();
2866   std::vector<std::string> tmp(1);
2867   tmp[0]=grp;
2868   return getGroups(meshDimRelToMaxExt,tmp,renum);
2869 }
2870
2871 /*!
2872  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in given
2873  * groups of \a this mesh. Only mesh entities of a given dimension are included in the
2874  * new mesh.
2875  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
2876  *  \param [in] grps - a sequence of group names whose mesh entities are included in the
2877  *          new mesh.
2878  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
2879  *          according to the optional numbers of entities, if available.
2880  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
2881  *          delete this mesh using decrRef() as it is no more needed.
2882  *  \throw If a name of a nonexistent group is present in \a grps.
2883  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2884  */
2885 MEDCouplingUMesh *MEDFileUMesh::getGroups(int meshDimRelToMaxExt, const std::vector<std::string>& grps, bool renum) const
2886 {
2887   synchronizeTinyInfoOnLeaves();
2888   std::vector<std::string> fams2=getFamiliesOnGroups(grps);
2889   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> zeRet=getFamilies(meshDimRelToMaxExt,fams2,renum);
2890   if(grps.size()==1 && ((MEDCouplingUMesh *)zeRet))
2891     zeRet->setName(grps[0]);
2892   return zeRet.retn();
2893 }
2894
2895 /*!
2896  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in a given
2897  * family of \a this mesh. Only mesh entities of a given dimension are included in the
2898  * new mesh.
2899  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
2900  *  \param [in] fam - the name of the family whose mesh entities are included in the
2901  *          new mesh.
2902  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
2903  *          according to the optional numbers of entities, if available.
2904  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
2905  *          delete this mesh using decrRef() as it is no more needed.
2906  *  \throw If a name of a nonexistent family is present in \a grps.
2907  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2908  */
2909 MEDCouplingUMesh *MEDFileUMesh::getFamily(int meshDimRelToMaxExt, const std::string& fam, bool renum) const
2910 {
2911   synchronizeTinyInfoOnLeaves();
2912   std::vector<std::string> tmp(1);
2913   tmp[0]=fam;
2914   return getFamilies(meshDimRelToMaxExt,tmp,renum);
2915 }
2916
2917 /*!
2918  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in given
2919  * families of \a this mesh. Only mesh entities of a given dimension are included in the
2920  * new mesh.
2921  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
2922  *  \param [in] fams - a sequence of family names whose mesh entities are included in the
2923  *          new mesh.
2924  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
2925  *          according to the optional numbers of entities, if available.
2926  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
2927  *          delete this mesh using decrRef() as it is no more needed.
2928  *  \throw If a name of a nonexistent family is present in \a fams.
2929  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2930  */
2931 MEDCouplingUMesh *MEDFileUMesh::getFamilies(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const
2932 {
2933   synchronizeTinyInfoOnLeaves();
2934   if(meshDimRelToMaxExt==1)
2935     {
2936       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr=getFamiliesArr(1,fams,renum);
2937       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
2938       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> c=_coords->selectByTupleId(arr->getConstPointer(),arr->getConstPointer()+arr->getNbOfElems());
2939       ret->setCoords(c);
2940       return ret.retn();
2941     }
2942   std::vector<int> famIds=getFamiliesIds(fams);
2943   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2944   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> zeRet;
2945   if(!famIds.empty())
2946     zeRet=l1->getFamilyPart(&famIds[0],&famIds[0]+famIds.size(),renum);
2947   else
2948     zeRet=l1->getFamilyPart(0,0,renum);
2949   if(fams.size()==1 && ((MEDCouplingUMesh *)zeRet))
2950     zeRet->setName(fams[0]);
2951   return zeRet.retn();
2952 }
2953
2954 /*!
2955  * Returns ids of mesh entities contained in given families of a given dimension.
2956  *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
2957  *          are required.
2958  *  \param [in] fams - the names of the families of interest.
2959  *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
2960  *          returned instead of ids.
2961  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
2962  *          numbers, if available and required, of mesh entities of the families. The caller
2963  *          is to delete this array using decrRef() as it is no more needed. 
2964  *  \throw If the family field is missing for \a meshDimRelToMaxExt.
2965  */
2966 DataArrayInt *MEDFileUMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const
2967 {
2968   std::vector<int> famIds=getFamiliesIds(fams);
2969   if(meshDimRelToMaxExt==1)
2970     {
2971       if((const DataArrayInt *)_fam_coords)
2972         {
2973           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
2974           if(!famIds.empty())
2975             da=_fam_coords->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
2976           else
2977             da=_fam_coords->getIdsEqualList(0,0);
2978           if(renum)
2979             return MEDFileUMeshSplitL1::Renumber(_num_coords,da);
2980           else
2981             return da.retn();
2982         }
2983       else
2984         throw INTERP_KERNEL::Exception("MEDFileUMesh::getFamiliesArr : no family array specified on nodes !");
2985     }
2986   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2987   if(!famIds.empty())
2988     return l1->getFamilyPartArr(&famIds[0],&famIds[0]+famIds.size(),renum);
2989   else
2990     return l1->getFamilyPartArr(0,0,renum);
2991 }
2992
2993 /*!
2994  * Returns a MEDCouplingUMesh of a given relative dimension.
2995  * \warning If \a meshDimRelToMaxExt == 1 (which means nodes), the returned mesh **is not
2996  * valid**. This is a feature, because MEDLoader does not create cells that do not exist! 
2997  * To build a valid MEDCouplingUMesh from the returned one in this case,
2998  * call MEDCouplingUMesh::Build0DMeshFromCoords().
2999  *  \param [in] meshDimRelToMax - the relative dimension of interest.
3000  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3001  *          optional numbers of mesh entities.
3002  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
3003  *          delete using decrRef() as it is no more needed. 
3004  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3005  * \sa getGenMeshAtLevel()
3006  */
3007 MEDCouplingUMesh *MEDFileUMesh::getMeshAtLevel(int meshDimRelToMaxExt, bool renum) const
3008 {
3009   synchronizeTinyInfoOnLeaves();
3010   if(meshDimRelToMaxExt==1)
3011     {
3012       if(!renum)
3013         {
3014           MEDCouplingUMesh *umesh=MEDCouplingUMesh::New();
3015           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> cc=_coords->deepCpy();
3016           umesh->setCoords(cc);
3017           MEDFileUMeshSplitL1::ClearNonDiscrAttributes(umesh);
3018           umesh->setName(getName());
3019           return umesh;
3020         }
3021     }
3022   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3023   return l1->getWholeMesh(renum);
3024 }
3025
3026 /*!
3027  * Returns a MEDCouplingUMesh of a given relative dimension.
3028  * \warning If \a meshDimRelToMaxExt == 1 (which means nodes), the returned mesh **is not
3029  * valid**. This is a feature, because MEDLoader does not create cells that do not exist! 
3030  * To build a valid MEDCouplingUMesh from the returned one in this case,
3031  * call MEDCouplingUMesh::Build0DMeshFromCoords().
3032  *  \param [in] meshDimRelToMax - the relative dimension of interest.
3033  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3034  *          optional numbers of mesh entities.
3035  *  \return MEDCouplingMesh * - a pointer to MEDCouplingUMesh that the caller is to
3036  *          delete using decrRef() as it is no more needed. 
3037  *  \throw If there are no mesh entities of \a meshDimRelToMax dimension in \a this mesh.
3038  * \sa getMeshAtLevel()
3039  */
3040 MEDCouplingMesh *MEDFileUMesh::getGenMeshAtLevel(int meshDimRelToMax, bool renum) const
3041 {
3042   return getMeshAtLevel(meshDimRelToMax,renum);
3043 }
3044
3045 std::vector<int> MEDFileUMesh::getDistributionOfTypes(int meshDimRelToMax) const
3046 {
3047   const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMax));
3048   return l1->getDistributionOfTypes();
3049 }
3050
3051 /*!
3052  * Returns a MEDCouplingUMesh of a relative dimension == 0.
3053  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3054  *          optional numbers of mesh entities.
3055  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
3056  *          delete using decrRef() as it is no more needed. 
3057  *  \throw If there are no mesh entities of the relative dimension == 0 in \a this mesh.
3058  */
3059 MEDCouplingUMesh *MEDFileUMesh::getLevel0Mesh(bool renum) const
3060 {
3061   return getMeshAtLevel(0,renum);
3062 }
3063
3064 /*!
3065  * Returns a MEDCouplingUMesh of a relative dimension == -1.
3066  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3067  *          optional numbers of mesh entities.
3068  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
3069  *          delete using decrRef() as it is no more needed. 
3070  *  \throw If there are no mesh entities of the relative dimension == -1 in \a this mesh.
3071  */
3072 MEDCouplingUMesh *MEDFileUMesh::getLevelM1Mesh(bool renum) const
3073 {
3074   return getMeshAtLevel(-1,renum);
3075 }
3076
3077 /*!
3078  * Returns a MEDCouplingUMesh of a relative dimension == -2.
3079  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3080  *          optional numbers of mesh entities.
3081  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
3082  *          delete using decrRef() as it is no more needed. 
3083  *  \throw If there are no mesh entities of the relative dimension == -2 in \a this mesh.
3084  */
3085 MEDCouplingUMesh *MEDFileUMesh::getLevelM2Mesh(bool renum) const
3086 {
3087   return getMeshAtLevel(-2,renum);
3088 }
3089
3090 /*!
3091  * Returns a MEDCouplingUMesh of a relative dimension == -3.
3092  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3093  *          optional numbers of mesh entities.
3094  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
3095  *          delete using decrRef() as it is no more needed. 
3096  *  \throw If there are no mesh entities of the relative dimension == -3 in \a this mesh.
3097  */
3098 MEDCouplingUMesh *MEDFileUMesh::getLevelM3Mesh(bool renum) const
3099 {
3100   return getMeshAtLevel(-3,renum);
3101 }
3102
3103 /*!
3104  * This method is for advanced users. There is two storing strategy of mesh in \a this.
3105  * Either MEDCouplingUMesh, or vector of MEDCoupling1GTUMesh instances.
3106  * When assignement is done the first one is done, which is not optimal in write mode for MED file.
3107  * This method allows to switch from MEDCouplingUMesh mode to MEDCoupling1GTUMesh mode.
3108  */
3109 void MEDFileUMesh::forceComputationOfParts() const
3110 {
3111   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
3112     {
3113       const MEDFileUMeshSplitL1 *elt(*it);
3114       if(elt)
3115         elt->forceComputationOfParts();
3116     }
3117 }
3118
3119 /*!
3120  * This method returns a vector of mesh parts containing each exactly one geometric type.
3121  * This method will never launch an automatic computation of split by type (an INTERP_KERNEL::Exception will be then thrown).
3122  * This method is only for memory aware users.
3123  * The returned pointers are **NOT** new object pointer. No need to mange them.
3124  */
3125 std::vector<MEDCoupling1GTUMesh *> MEDFileUMesh::getDirectUndergroundSingleGeoTypeMeshes(int meshDimRelToMax) const
3126 {
3127   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(meshDimRelToMax));
3128   return sp->getDirectUndergroundSingleGeoTypeMeshes();
3129 }
3130
3131 /*!
3132  * This method returns the part of \a this having the geometric type \a gt.
3133  * If such part is not existing an exception will be thrown.
3134  * The returned pointer is **NOT** new object pointer. No need to mange it.
3135  */
3136 MEDCoupling1GTUMesh *MEDFileUMesh::getDirectUndergroundSingleGeoTypeMesh(INTERP_KERNEL::NormalizedCellType gt) const
3137 {
3138   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
3139   int lev=(int)cm.getDimension()-getMeshDimension();
3140   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(lev));
3141   return sp->getDirectUndergroundSingleGeoTypeMesh(gt);
3142 }
3143
3144 /*!
3145  * Given a relative level \a meshDimRelToMax it returns the sorted vector of geometric types present in \a this.
3146  * \throw if the reqsuested \a meshDimRelToMax does not exist.
3147  */
3148 std::vector<INTERP_KERNEL::NormalizedCellType> MEDFileUMesh::getGeoTypesAtLevel(int meshDimRelToMax) const
3149 {
3150   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(meshDimRelToMax));
3151   return sp->getGeoTypes();
3152 }
3153
3154 /*!
3155  * This method extracts from whole family field ids the part relative to the input parameter \a gt.
3156  * \param [in] gt - the geometric type for which the family field is asked.
3157  * \return DataArrayInt * - a pointer to DataArrayInt that the caller is to
3158  *          delete using decrRef() as it is no more needed.
3159  * \sa MEDFileUMesh::extractNumberFieldOnGeoType
3160  */
3161 DataArrayInt *MEDFileUMesh::extractFamilyFieldOnGeoType(INTERP_KERNEL::NormalizedCellType gt) const
3162 {
3163   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
3164   int lev=(int)cm.getDimension()-getMeshDimension();
3165   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(lev));
3166   return sp->extractFamilyFieldOnGeoType(gt);
3167 }
3168
3169 /*!
3170  * This method extracts from whole number field ids the part relative to the input parameter \a gt.
3171  * \param [in] gt - the geometric type for which the number field is asked.
3172  * \return DataArrayInt * - a pointer to DataArrayInt that the caller is to
3173  *          delete using decrRef() as it is no more needed.
3174  * \sa MEDFileUMesh::extractFamilyFieldOnGeoType
3175  */
3176 DataArrayInt *MEDFileUMesh::extractNumberFieldOnGeoType(INTERP_KERNEL::NormalizedCellType gt) const
3177 {
3178   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
3179   int lev=(int)cm.getDimension()-getMeshDimension();
3180   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(lev));
3181   return sp->extractNumberFieldOnGeoType(gt);
3182 }
3183
3184 /*!
3185  * This method returns for specified geometric type \a gt the relative level to \a this.
3186  * If the relative level is empty an exception will be thrown.
3187  */
3188 int MEDFileUMesh::getRelativeLevOnGeoType(INTERP_KERNEL::NormalizedCellType gt) const
3189 {
3190   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
3191   int ret((int)cm.getDimension()-getMeshDimension());
3192   getMeshAtLevSafe(ret);//To test that returned value corresponds to a valid level.
3193   return ret;
3194 }
3195
3196 const MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt) const
3197 {
3198   if(meshDimRelToMaxExt==1)
3199     throw INTERP_KERNEL::Exception("Dimension request is invalid : asking for node level (1) !");
3200   if(meshDimRelToMaxExt>1)
3201     throw INTERP_KERNEL::Exception("Dimension request is invalid (>1) !");
3202   int tracucedRk=-meshDimRelToMaxExt;
3203   if(tracucedRk>=(int)_ms.size())
3204     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
3205   if((const MEDFileUMeshSplitL1 *)_ms[tracucedRk]==0)
3206     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3207   return _ms[tracucedRk];
3208 }
3209
3210 MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt)
3211 {
3212   if(meshDimRelToMaxExt==1)
3213     throw INTERP_KERNEL::Exception("Dimension request is invalid : asking for node level (1) !");
3214   if(meshDimRelToMaxExt>1)
3215     throw INTERP_KERNEL::Exception("Dimension request is invalid (>1) !");
3216   int tracucedRk=-meshDimRelToMaxExt;
3217   if(tracucedRk>=(int)_ms.size())
3218     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
3219   if((const MEDFileUMeshSplitL1 *)_ms[tracucedRk]==0)
3220     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3221   return _ms[tracucedRk];
3222 }
3223
3224 void MEDFileUMesh::checkMeshDimCoherency(int meshDim, int meshDimRelToMax) const
3225 {
3226   if(-meshDimRelToMax>=(int)_ms.size())
3227     throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMeshDimCoherency : The meshdim of mesh is not managed by 'this' !");
3228   int i=0;
3229   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,i++)
3230     {
3231       if(((const MEDFileUMeshSplitL1*) (*it))!=0)
3232         {
3233           int ref=(*it)->getMeshDimension();
3234           if(ref+i!=meshDim-meshDimRelToMax)
3235             throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMeshDimCoherency : no coherency between levels !");
3236         }
3237     }
3238 }
3239
3240 /*!
3241  * Sets the node coordinates array of \a this mesh.
3242  *  \param [in] coords - the new node coordinates array.
3243  *  \throw If \a coords == \c NULL.
3244  */
3245 void MEDFileUMesh::setCoords(DataArrayDouble *coords)
3246 {
3247   if(!coords)
3248     throw INTERP_KERNEL::Exception("MEDFileUMesh::setCoords : null pointer in input !");
3249   coords->checkAllocated();
3250   int nbOfTuples=coords->getNumberOfTuples();
3251   _coords=coords;
3252   coords->incrRef();
3253   _fam_coords=DataArrayInt::New();
3254   _fam_coords->alloc(nbOfTuples,1);
3255   _fam_coords->fillWithZero();
3256   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
3257     if((MEDFileUMeshSplitL1 *)(*it))
3258       (*it)->setCoords(coords);
3259 }
3260
3261 /*!
3262  * Removes all groups of a given dimension in \a this mesh.
3263  *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
3264  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3265  */
3266 void MEDFileUMesh::eraseGroupsAtLevel(int meshDimRelToMaxExt)
3267 {
3268   if(meshDimRelToMaxExt==1)
3269     {
3270       if((DataArrayInt *)_fam_coords)
3271         _fam_coords->fillWithZero();
3272       return ;
3273     }
3274   MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3275   l1->eraseFamilyField();
3276   optimizeFamilies();
3277 }
3278
3279 /*!
3280  * Removes all families with ids not present in the family fields of \a this mesh.
3281  */
3282 void MEDFileUMesh::optimizeFamilies()
3283 {
3284   std::vector<int> levs=getNonEmptyLevelsExt();
3285   std::set<int> allFamsIds;
3286   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
3287     {
3288       const DataArrayInt *ffield=getFamilyFieldAtLevel(*it);
3289       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=ffield->getDifferentValues();
3290       std::set<int> res;
3291       std::set_union(ids->begin(),ids->end(),allFamsIds.begin(),allFamsIds.end(),std::inserter(res,res.begin()));
3292       allFamsIds=res;
3293     }
3294   std::set<std::string> famNamesToKill;
3295   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
3296     {
3297       if(allFamsIds.find((*it).second)!=allFamsIds.end())
3298         famNamesToKill.insert((*it).first);
3299     }
3300   for(std::set<std::string>::const_iterator it=famNamesToKill.begin();it!=famNamesToKill.end();it++)
3301     _families.erase(*it);
3302   std::vector<std::string> grpNamesToKill;
3303   for(std::map<std::string, std::vector<std::string> >::iterator it=_groups.begin();it!=_groups.end();it++)
3304     {
3305       std::vector<std::string> tmp;
3306       for(std::vector<std::string>::const_iterator it2=(*it).second.begin();it2!=(*it).second.end();it2++)
3307         {
3308           if(famNamesToKill.find(*it2)==famNamesToKill.end())
3309             tmp.push_back(*it2);
3310         }
3311       if(!tmp.empty())
3312         (*it).second=tmp;
3313       else
3314         tmp.push_back((*it).first);
3315     }
3316   for(std::vector<std::string>::const_iterator it=grpNamesToKill.begin();it!=grpNamesToKill.end();it++)
3317     _groups.erase(*it);
3318 }
3319
3320 void MEDFileUMesh::duplicateNodesOnM1Group(const std::string& grpNameM1, DataArrayInt *&nodesDuplicated, DataArrayInt *&cellsModified, DataArrayInt *&cellsNotModified)
3321 {
3322   std::vector<int> levs=getNonEmptyLevels();
3323   if(std::find(levs.begin(),levs.end(),0)==levs.end() || std::find(levs.begin(),levs.end(),-1)==levs.end())
3324     throw INTERP_KERNEL::Exception("MEDFileUMesh::duplicateNodesOnM1Group : This method works only for mesh definied on level 0 and -1 !");
3325   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0=getMeshAtLevel(0);
3326   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1=getMeshAtLevel(-1);
3327   int nbNodes=m0->getNumberOfNodes();
3328   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m11=getGroup(-1,grpNameM1);
3329   DataArrayInt *tmp00=0,*tmp11=0,*tmp22=0;
3330   m0->findNodesToDuplicate(*m11,tmp00,tmp11,tmp22);
3331   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodeIdsToDuplicate(tmp00);
3332   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0(tmp11);
3333   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1(tmp22);
3334   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp0=static_cast<MEDCouplingUMesh *>(m0->buildPartOfMySelf(cellsToModifyConn0->begin(),cellsToModifyConn0->end(),true));
3335   // node renumbering of cells in m1 impacted by duplication of node but not in group 'grpNameM1' on level -1
3336   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descTmp0=DataArrayInt::New(),descITmp0=DataArrayInt::New(),revDescTmp0=DataArrayInt::New(),revDescITmp0=DataArrayInt::New();
3337   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp0Desc=tmp0->buildDescendingConnectivity(descTmp0,descITmp0,revDescTmp0,revDescITmp0);
3338   descTmp0=0; descITmp0=0; revDescTmp0=0; revDescITmp0=0;
3339   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsInM1ToRenumW2=tmp0Desc->getCellIdsLyingOnNodes(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),false);
3340   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cellsInM1ToRenumW3=static_cast<MEDCouplingUMesh *>(tmp0Desc->buildPartOfMySelf(cellsInM1ToRenumW2->begin(),cellsInM1ToRenumW2->end(),true));
3341   DataArrayInt *cellsInM1ToRenumW4Tmp=0;
3342   m1->areCellsIncludedIn(cellsInM1ToRenumW3,2,cellsInM1ToRenumW4Tmp);
3343   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsInM1ToRenumW4(cellsInM1ToRenumW4Tmp);
3344   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsInM1ToRenumW5=cellsInM1ToRenumW4->getIdsInRange(0,m1->getNumberOfCells());
3345   cellsInM1ToRenumW5->transformWithIndArr(cellsInM1ToRenumW4->begin(),cellsInM1ToRenumW4->end());
3346   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> grpIds=getGroupArr(-1,grpNameM1);
3347   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsInM1ToRenum=cellsInM1ToRenumW5->buildSubstraction(grpIds);
3348   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Part=static_cast<MEDCouplingUMesh *>(m1->buildPartOfMySelf(cellsInM1ToRenum->begin(),cellsInM1ToRenum->end(),true));
3349   m1Part->duplicateNodesInConn(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),nbNodes);
3350   m1->setPartOfMySelf(cellsInM1ToRenum->begin(),cellsInM1ToRenum->end(),*m1Part);
3351   // end of node renumbering of cells in m1 impacted by duplication of node but not in group of level -1 'grpNameM1'
3352   tmp0->duplicateNodes(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end());
3353   m0->setCoords(tmp0->getCoords());
3354   m0->setPartOfMySelf(cellsToModifyConn0->begin(),cellsToModifyConn0->end(),*tmp0);
3355   m1->setCoords(m0->getCoords());
3356   _coords=m0->getCoords(); _coords->incrRef();
3357   // duplication of cells in group 'grpNameM1' on level -1
3358   m11->duplicateNodesInConn(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),nbNodes); m11->setCoords(m0->getCoords());
3359   std::vector<const MEDCouplingUMesh *> v(2); v[0]=m1; v[1]=m11;
3360   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> newm1=MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(v,tmp00,tmp11);
3361   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> szOfCellGrpOfSameType(tmp00);
3362   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idInMsOfCellGrpOfSameType(tmp11);
3363   //
3364   newm1->setName(getName());
3365   const DataArrayInt *fam=getFamilyFieldAtLevel(-1);
3366   if(!fam)
3367     throw INTERP_KERNEL::Exception("MEDFileUMesh::duplicateNodesOnM1Group : internal problem !");
3368   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newFam=DataArrayInt::New();
3369   newFam->alloc(newm1->getNumberOfCells(),1);
3370   int idd=getMaxFamilyId()+1;
3371   int globStart=0,start=0,end,globEnd;
3372   int nbOfChunks=szOfCellGrpOfSameType->getNumberOfTuples();
3373   for(int i=0;i<nbOfChunks;i++)
3374     {
3375       globEnd=globStart+szOfCellGrpOfSameType->getIJ(i,0);
3376       if(idInMsOfCellGrpOfSameType->getIJ(i,0)==0)
3377         {
3378           end=start+szOfCellGrpOfSameType->getIJ(i,0);
3379           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=fam->selectByTupleId2(start,end,1);
3380           newFam->setPartOfValues1(part,globStart,globEnd,1,0,1,1,true);
3381           start=end;
3382         }
3383       else
3384         {
3385           newFam->setPartOfValuesSimple1(idd,globStart,globEnd,1,0,1,1);
3386         }
3387       globStart=globEnd;
3388     }
3389   newm1->setCoords(getCoords());
3390   setMeshAtLevel(-1,newm1);
3391   setFamilyFieldArr(-1,newFam);
3392   std::string grpName2(grpNameM1); grpName2+="_dup";
3393   addFamily(grpName2,idd);
3394   addFamilyOnGrp(grpName2,grpName2);
3395   //
3396   fam=_fam_coords;
3397   if(fam)
3398     {
3399       int newNbOfNodes=getCoords()->getNumberOfTuples();
3400       newFam=DataArrayInt::New(); newFam->alloc(newNbOfNodes,1);
3401       newFam->setPartOfValues1(fam,0,nbNodes,1,0,1,1,true);
3402       newFam->setPartOfValuesSimple1(0,nbNodes,newNbOfNodes,1,0,1,1);
3403       _fam_coords=newFam;
3404     }
3405   nodesDuplicated=nodeIdsToDuplicate.retn();
3406   cellsModified=cellsToModifyConn0.retn();
3407   cellsNotModified=cellsToModifyConn1.retn();
3408 }
3409
3410 /*!
3411  * \param [out] oldCode retrieves the distribution of types before the call if true is returned
3412  * \param [out] newCode etrieves the distribution of types after the call if true is returned
3413  * \param [out] o2nRenumCell tells for **all levels** the old 2 new renumbering of cells.
3414  * 
3415  * \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.
3416  * 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.
3417  */
3418 bool MEDFileUMesh::unPolyze(std::vector<int>& oldCode, std::vector<int>& newCode, DataArrayInt *& o2nRenumCell)
3419 {
3420   o2nRenumCell=0; oldCode.clear(); newCode.clear();
3421   std::vector<int> levs=getNonEmptyLevels();
3422   bool ret=false;
3423   std::vector< const DataArrayInt* > renumCellsSplited;//same than memorySaverIfThrow
3424   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > memorySaverIfThrow;//same than renumCellsSplited only in case of throw
3425   int start=0;
3426   int end=0;
3427   for(std::vector<int>::reverse_iterator it=levs.rbegin();it!=levs.rend();it++)
3428     {
3429       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=getMeshAtLevel(*it);
3430       std::vector<int> code1=m->getDistributionOfTypes();
3431       end=PutInThirdComponentOfCodeOffset(code1,start);
3432       oldCode.insert(oldCode.end(),code1.begin(),code1.end());
3433       bool hasChanged=m->unPolyze();
3434       DataArrayInt *fake=0;
3435       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nCellsPart=m->getLevArrPerCellTypes(MEDCouplingUMesh::MEDMEM_ORDER,
3436           MEDCouplingUMesh::MEDMEM_ORDER+MEDCouplingUMesh::N_MEDMEM_ORDER,fake);
3437       fake->decrRef();
3438       renumCellsSplited.push_back(o2nCellsPart); memorySaverIfThrow.push_back(o2nCellsPart);
3439       if(hasChanged)
3440         {
3441           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nCellsPart2=o2nCellsPart->buildPermArrPerLevel();
3442           m->renumberCells(o2nCellsPart2->getConstPointer(),false);
3443           ret=true;
3444           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famField2,numField2;
3445           const DataArrayInt *famField=getFamilyFieldAtLevel(*it); if(famField) { famField->incrRef(); famField2=const_cast<DataArrayInt *>(famField); }
3446           const DataArrayInt *numField=getNumberFieldAtLevel(*it); if(numField) { numField->incrRef(); numField2=const_cast<DataArrayInt *>(numField); }
3447           setMeshAtLevel(*it,m);
3448           std::vector<int> code2=m->getDistributionOfTypes();
3449           end=PutInThirdComponentOfCodeOffset(code2,start);
3450           newCode.insert(newCode.end(),code2.begin(),code2.end());
3451           //
3452           if(o2nCellsPart2->isIdentity())
3453             continue;
3454           if(famField)
3455             {
3456               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newFamField=famField->renumber(o2nCellsPart2->getConstPointer());
3457               setFamilyFieldArr(*it,newFamField);
3458             }
3459           if(numField)
3460             {
3461               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newNumField=numField->renumber(o2nCellsPart2->getConstPointer());
3462               setRenumFieldArr(*it,newNumField);
3463             }
3464         }
3465       else
3466         {
3467           newCode.insert(newCode.end(),code1.begin(),code1.end());
3468         }
3469       start=end;
3470     }
3471   if(ret)
3472     {
3473       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renumCells=DataArrayInt::Aggregate(renumCellsSplited);
3474       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRenumCellRet=renumCells->buildPermArrPerLevel();
3475       o2nRenumCell=o2nRenumCellRet.retn();
3476     }
3477   return ret;
3478 }
3479
3480 struct MEDLoaderAccVisit1
3481 {
3482   MEDLoaderAccVisit1():_new_nb_of_nodes(0) { }
3483   int operator()(bool val) { return val?_new_nb_of_nodes++:-1; }
3484   int _new_nb_of_nodes;
3485 };
3486
3487 /*!
3488  * 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.
3489  * The maximum value stored in returned array is the number of nodes of \a this minus 1 after call of this method.
3490  * The size of returned array is the number of nodes of the old (previous to the call of this method) number of nodes.
3491  * -1 values in returned array means that the corresponding old node is no more used.
3492  *
3493  * \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
3494  *         is modified in \a this.
3495  * \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
3496  *  set coordinates.
3497  */
3498 DataArrayInt *MEDFileUMesh::zipCoords()
3499 {
3500   const DataArrayDouble *coo=getCoords();
3501   if(!coo)
3502     throw INTERP_KERNEL::Exception("MEDFileUMesh::zipCoords : no coordinates set in this !");
3503   int nbOfNodes=coo->getNumberOfTuples();
3504   std::vector<bool> nodeIdsInUse(nbOfNodes,false);
3505   std::vector<int> neLevs=getNonEmptyLevels();
3506   for(std::vector<int>::const_iterator lev=neLevs.begin();lev!=neLevs.end();lev++)
3507     {
3508       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=getMeshAtLevel(*lev);
3509       m->computeNodeIdsAlg(nodeIdsInUse);
3510     }
3511   int nbrOfNodesInUse=(int)std::count(nodeIdsInUse.begin(),nodeIdsInUse.end(),true);
3512   if(nbrOfNodesInUse==nbOfNodes)
3513     return 0;
3514   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodes,1);
3515   std::transform(nodeIdsInUse.begin(),nodeIdsInUse.end(),ret->getPointer(),MEDLoaderAccVisit1());
3516   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2=ret->invertArrayO2N2N2OBis(nbrOfNodesInUse);
3517   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->selectByTupleIdSafe(ret2->begin(),ret2->end());
3518   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newFamCoords;
3519   MEDCouplingAutoRefCountObjectPtr<DataArrayAsciiChar> newNameCoords;
3520   if((const DataArrayInt *)_fam_coords)
3521     newFamCoords=_fam_coords->selectByTupleIdSafe(ret2->begin(),ret2->end());
3522   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newNumCoords;
3523   if((const DataArrayInt *)_num_coords)
3524     newNumCoords=_num_coords->selectByTupleIdSafe(ret2->begin(),ret2->end());
3525   if((const DataArrayAsciiChar *)_name_coords)
3526     newNameCoords=static_cast<DataArrayAsciiChar *>(_name_coords->selectByTupleIdSafe(ret2->begin(),ret2->end()));
3527   _coords=newCoords; _fam_coords=newFamCoords; _num_coords=newNumCoords; _name_coords=newNameCoords; _rev_num_coords=0;
3528   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
3529     {
3530       if((MEDFileUMeshSplitL1*)*it)
3531         (*it)->renumberNodesInConn(ret->begin());
3532     }
3533   return ret.retn();
3534 }
3535
3536 /*!
3537  * Adds a group of nodes to \a this mesh.
3538  *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
3539  *          The ids should be sorted and different each other (MED file norm).
3540  *  \throw If the node coordinates array is not set.
3541  *  \throw If \a ids == \c NULL.
3542  *  \throw If \a ids->getName() == "".
3543  *  \throw If \a ids does not respect the MED file norm.
3544  *  \throw If a group with name \a ids->getName() already exists.
3545  */
3546 void MEDFileUMesh::addNodeGroup(const DataArrayInt *ids)
3547 {
3548   const DataArrayDouble *coords=_coords;
3549   if(!coords)
3550     throw INTERP_KERNEL::Exception("MEDFileUMesh::addNodeGroup : no coords set !");
3551   int nbOfNodes=coords->getNumberOfTuples();
3552   if(!((DataArrayInt *)_fam_coords))
3553     { _fam_coords=DataArrayInt::New(); _fam_coords->alloc(nbOfNodes,1); _fam_coords->fillWithZero(); }
3554   //
3555   addGroupUnderground(true,ids,_fam_coords);
3556 }
3557
3558 /*!
3559  * Adds a group of nodes/cells/faces/edges to \a this mesh.
3560  *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
3561  *          The ids should be sorted and different each other (MED file norm).
3562  *  \throw If the node coordinates array is not set.
3563  *  \throw If \a ids == \c NULL.
3564  *  \throw If \a ids->getName() == "".
3565  *  \throw If \a ids does not respect the MED file norm.
3566  *  \throw If a group with name \a ids->getName() already exists.
3567  */
3568 void MEDFileUMesh::addGroup(int meshDimRelToMaxExt, const DataArrayInt *ids)
3569 {
3570   std::vector<int> levs=getNonEmptyLevelsExt();
3571   if(std::find(levs.begin(),levs.end(),meshDimRelToMaxExt)==levs.end())
3572     { 
3573       std::ostringstream oss; oss << "MEDFileUMesh::addGroup : level " << meshDimRelToMaxExt << " not available ! Should be in ";
3574       std::copy(levs.begin(),levs.end(),std::ostream_iterator<int>(oss," ")); oss << " !"; throw INTERP_KERNEL::Exception(oss.str().c_str());
3575     }
3576   if(meshDimRelToMaxExt==1)
3577     { addNodeGroup(ids); return ; }
3578   MEDFileUMeshSplitL1 *lev=getMeshAtLevSafe(meshDimRelToMaxExt);
3579   DataArrayInt *fam=lev->getOrCreateAndGetFamilyField();
3580   addGroupUnderground(false,ids,fam);
3581 }
3582
3583 /*!
3584  * \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).
3585  * \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)
3586  */
3587 void MEDFileUMesh::addGroupUnderground(bool isNodeGroup, const DataArrayInt *ids, DataArrayInt *famArr)
3588 {
3589   if(!ids)
3590     throw INTERP_KERNEL::Exception("MEDFileUMesh::addGroup : NULL pointer in input !");
3591   std::string grpName(ids->getName());
3592   if(grpName.empty())
3593     throw INTERP_KERNEL::Exception("MEDFileUMesh::addGroup : empty group name ! MED file format do not accept empty group name !");
3594   ids->checkStrictlyMonotonic(true);
3595   famArr->incrRef(); MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famArrTmp(famArr);
3596   std::vector<std::string> grpsNames=getGroupsNames();
3597   if(std::find(grpsNames.begin(),grpsNames.end(),grpName)!=grpsNames.end())
3598     {
3599       std::ostringstream oss; oss << "MEDFileUMesh::addGroup : Group with name \"" << grpName << "\" already exists ! Destroy it before calling this method !";
3600       throw INTERP_KERNEL::Exception(oss.str().c_str());
3601     }
3602   std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > allFamIds=getAllNonNullFamilyIds();
3603   allFamIds.erase(std::find(allFamIds.begin(),allFamIds.end(),famArrTmp));
3604   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famIds=famArr->selectByTupleIdSafe(ids->begin(),ids->end());
3605   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffFamIds=famIds->getDifferentValues();
3606   std::vector<int> familyIds;
3607   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerfamiliyIds;
3608   int maxVal=getTheMaxAbsFamilyId()+1;
3609   std::map<std::string,int> families(_families);
3610   std::map<std::string, std::vector<std::string> > groups(_groups);
3611   std::vector<std::string> fams;
3612   bool created(false);
3613   for(const int *famId=diffFamIds->begin();famId!=diffFamIds->end();famId++)
3614     {
3615       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2Tmp=famIds->getIdsEqual(*famId);
3616       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=ids->selectByTupleId(ids2Tmp->begin(),ids2Tmp->end());
3617       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids1=famArr->getIdsEqual(*famId);
3618       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(ids1->buildSubstractionOptimized(ids2));
3619       if(ret0->empty())
3620         {
3621           bool isFamPresent=false;
3622           for(std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::const_iterator itl=allFamIds.begin();itl!=allFamIds.end() && !isFamPresent;itl++)
3623             isFamPresent=(*itl)->presenceOfValue(*famId);
3624           if(!isFamPresent)
3625             { familyIds.push_back(*famId); idsPerfamiliyIds.push_back(ret0); fams.push_back(FindOrCreateAndGiveFamilyWithId(families,*famId,created)); } // adding *famId in grp
3626           else
3627             {
3628               familyIds.push_back(isNodeGroup?maxVal:-maxVal); idsPerfamiliyIds.push_back(ids2);
3629               std::string locFamName=FindOrCreateAndGiveFamilyWithId(families,isNodeGroup?maxVal:-maxVal,created);
3630               fams.push_back(locFamName);
3631               if(existsFamily(*famId))
3632                 {
3633                   std::string locFamName2=getFamilyNameGivenId(*famId); std::vector<std::string> v(2); v[0]=locFamName2; v[1]=locFamName;
3634                   ChangeAllGroupsContainingFamily(groups,getFamilyNameGivenId(*famId),v);
3635                 }
3636               maxVal++;
3637             } // modifying all other groups on *famId to lie on maxVal and lie the grp on maxVal
3638         }
3639       else
3640         {
3641           familyIds.push_back(isNodeGroup?maxVal:-maxVal); idsPerfamiliyIds.push_back(ret0); // modifying all other groups on *famId to lie on maxVal and on maxVal+1
3642           familyIds.push_back(isNodeGroup?maxVal+1:-maxVal-1); idsPerfamiliyIds.push_back(ids2);//grp lie only on maxVal+1
3643           std::string n2(FindOrCreateAndGiveFamilyWithId(families,isNodeGroup?maxVal+1:-maxVal-1,created)); fams.push_back(n2);
3644           if(existsFamily(*famId))
3645             {
3646               std::string n1(FindOrCreateAndGiveFamilyWithId(families,isNodeGroup?maxVal:-maxVal,created)); std::vector<std::string> v(2); v[0]=n1; v[1]=n2;
3647               ChangeAllGroupsContainingFamily(groups,getFamilyNameGivenId(*famId),v);
3648             }
3649           maxVal+=2;
3650         }
3651     }
3652   for(std::size_t i=0;i<familyIds.size();i++)
3653     {
3654       DataArrayInt *da=idsPerfamiliyIds[i];
3655       famArr->setPartOfValuesSimple3(familyIds[i],da->begin(),da->end(),0,1,1);
3656     }
3657   _families=families;
3658   _groups=groups;
3659   _groups[grpName]=fams;
3660 }
3661
3662 /*!
3663  * Changes a name of a family specified by its id.
3664  *  \param [in] id - the id of the family of interest.
3665  *  \param [in] newFamName - the new family name.
3666  *  \throw If no family with the given \a id exists.
3667  */
3668 void MEDFileUMesh::setFamilyNameAttachedOnId(int id, const std::string& newFamName)
3669 {
3670   std::string oldName=getFamilyNameGivenId(id);
3671   _families.erase(oldName);
3672   _families[newFamName]=id;
3673 }
3674
3675 /*!
3676  * Removes a mesh of a given dimension.
3677  *  \param [in] meshDimRelToMax - the relative dimension of interest.
3678  *  \throw If there is no mesh at level \a meshDimRelToMax in \a this mesh.
3679  */
3680 void MEDFileUMesh::removeMeshAtLevel(int meshDimRelToMax)
3681 {
3682   std::vector<int> levSet=getNonEmptyLevels();
3683   std::vector<int>::const_iterator it=std::find(levSet.begin(),levSet.end(),meshDimRelToMax);
3684   if(it==levSet.end())
3685     throw INTERP_KERNEL::Exception("MEDFileUMesh::removeMeshAtLevel : the requested level is not existing !");
3686   int pos=(-meshDimRelToMax);
3687   _ms[pos]=0;
3688 }
3689
3690 /*!
3691  * Sets a new MEDCoupling1GTUMesh at a given level in \a this mesh.
3692  *  \param [in] meshDimRelToMax - a relative level to set the mesh at.
3693  *  \param [in] m - the new mesh to set.
3694  *  \throw If the name or the description of \a this mesh and \a m are not empty and are
3695  *         different. 
3696  *  \throw If the node coordinates array is set \a this in mesh and \a m refers to
3697  *         another node coordinates array.
3698  *  \throw If the mesh dimension of \a m does not correspond to \a meshDimRelToMax or
3699  *         to the existing meshes of other levels of \a this mesh.
3700  */
3701 void MEDFileUMesh::setMeshAtLevel(int meshDimRelToMax, MEDCoupling1GTUMesh *m)
3702 {
3703   MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> elt(new MEDFileUMeshSplitL1(m));
3704   checkAndGiveEntryInSplitL1(meshDimRelToMax,m)=elt;
3705 }
3706
3707 /*!
3708  * Sets a new MEDCouplingUMesh at a given level in \a this mesh.
3709  *  \param [in] meshDimRelToMax - a relative level to set the mesh at.
3710  *  \param [in] m - the new mesh to set.
3711  *  \param [in] newOrOld - if \c true, cells in \a m are sorted by type to be ready for 
3712  *         writing \a this mesh in a MED file.
3713  *  \throw If the name or the description of \a this mesh and \a m are not empty and are
3714  *         different. 
3715  *  \throw If the node coordinates array is set \a this in mesh and \a m refers to
3716  *         another node coordinates array.
3717  *  \throw If the mesh dimension of \a m does not correspond to \a meshDimRelToMax or
3718  *         to the existing meshes of other levels of \a this mesh.
3719  */
3720 void MEDFileUMesh::setMeshAtLevel(int meshDimRelToMax, MEDCouplingUMesh *m, bool newOrOld)
3721 {
3722   MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> elt(new MEDFileUMeshSplitL1(m,newOrOld));
3723   checkAndGiveEntryInSplitL1(meshDimRelToMax,m)=elt;
3724 }
3725
3726 MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1>& MEDFileUMesh::checkAndGiveEntryInSplitL1(int meshDimRelToMax, MEDCouplingPointSet *m)
3727 {
3728   dealWithTinyInfo(m);
3729   std::vector<int> levSet=getNonEmptyLevels();
3730   if(std::find(levSet.begin(),levSet.end(),meshDimRelToMax)==levSet.end())
3731     {
3732       if((DataArrayDouble *)_coords==0)
3733         {
3734           DataArrayDouble *c=m->getCoords();
3735           if(c)
3736             c->incrRef();
3737           _coords=c;
3738         }
3739       if(m->getCoords()!=_coords)
3740         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshAtLevel : Invalid Given Mesh ! The coordinates are not the same ! try to use tryToShareSameCoords !");
3741       int sz=(-meshDimRelToMax)+1;
3742       if(sz>=(int)_ms.size())
3743         _ms.resize(sz);
3744       checkMeshDimCoherency(m->getMeshDimension(),meshDimRelToMax);
3745       return _ms[sz-1];
3746     }
3747   else
3748     return _ms[-meshDimRelToMax];
3749 }
3750
3751 /*!
3752  * This method allows to set at once the content of different levels in \a this.
3753  * This method is equivalent to a series of call to MEDFileUMesh::setMeshAtLevel.
3754  *
3755  * \param [in] ms - List of unstructured meshes lying on the same coordinates and having different mesh dimesnion.
3756  * \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.
3757  *                     If false, an exception ois thrown. If true the mesh is reordered automatically. It is highly recommanded to let this parameter to false.
3758  *
3759  * \throw If \a there is a null pointer in \a ms.
3760  * \sa MEDFileUMesh::setMeshAtLevel
3761  */
3762 void MEDFileUMesh::setMeshes(const std::vector<const MEDCouplingUMesh *>& ms, bool renum)
3763 {
3764   if(ms.empty())
3765     return ;
3766   const MEDCouplingUMesh *mRef=ms[0];
3767   if(!mRef)
3768     throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : null instance in the first element of input meshes !");
3769   std::string name(mRef->getName());
3770   const DataArrayDouble *coo(mRef->getCoords());
3771   std::set<int> s;
3772   int zeDim=-1;
3773   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
3774     {
3775       const MEDCouplingUMesh *cur(*it);
3776       if(!cur)
3777         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : null instance in input vector of meshes !");
3778       if(coo!=cur->getCoords())
3779         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : The input meshes do not share the same coordinates !");
3780       int mdim=cur->getMeshDimension();
3781       zeDim=std::max(zeDim,mdim);
3782       if(s.find(mdim)!=s.end())
3783         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : The input meshes must share the same coordinates pointer, and should have different mesh dimension each other !");
3784     }
3785   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
3786     {
3787       int mdim=(*it)->getMeshDimension();
3788       setName((*it)->getName());
3789       setMeshAtLevel(mdim-zeDim,const_cast<MEDCouplingUMesh *>(*it),renum);
3790     }
3791   setName(name);
3792 }
3793
3794 /*!
3795  * Creates one MEDCouplingUMesh at a given level in \a this mesh from a sequence of
3796  * meshes each representing a group, and creates corresponding groups in \a this mesh.
3797  * The given meshes must share the same node coordinates array.
3798  *  \param [in] meshDimRelToMax - the relative dimension to create the mesh and groups at.
3799  *  \param [in] ms - the sequence of meshes. Each mesh in \a ms represents a group to
3800  *          create in \a this mesh.
3801  *  \throw If \a ms is empty.
3802  *  \throw If dimension of meshes in \a ms does not correspond to \a meshDimRelToMax or
3803  *         to the existing meshes of other levels of \a this mesh.
3804  *  \throw If the meshes in \a ms do not share the same node coordinates array.
3805  *  \throw If the node coordinates array of \a this mesh (if any) is not the same as that
3806  *         of the given meshes.
3807  *  \throw If \a ms[ i ] is not well defined (MEDCouplingUMesh::checkCoherency()).
3808  *  \throw If names of some meshes in \a ms are equal.
3809  *  \throw If \a ms includes a mesh with an empty name.
3810  */
3811 void MEDFileUMesh::setGroupsFromScratch(int meshDimRelToMax, const std::vector<const MEDCouplingUMesh *>& ms, bool renum)
3812 {
3813   if(ms.empty())
3814     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsFromScratch : expecting a non empty vector !");
3815   int sz=(-meshDimRelToMax)+1;
3816   if(sz>=(int)_ms.size())
3817     _ms.resize(sz);
3818   checkMeshDimCoherency(ms[0]->getMeshDimension(),meshDimRelToMax);
3819   DataArrayDouble *coo=checkMultiMesh(ms);
3820   if((DataArrayDouble *)_coords==0)
3821     {
3822       coo->incrRef();
3823       _coords=coo;
3824     }
3825   else
3826     if((DataArrayDouble *)_coords!=coo)
3827       throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsFromScratch : coordinates mismatches !");
3828   std::vector<DataArrayInt *> corr;
3829   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MEDCouplingUMesh::FuseUMeshesOnSameCoords(ms,_zipconn_pol,corr);
3830   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > corr3(corr.begin(),corr.end());
3831   setMeshAtLevel(meshDimRelToMax,m,renum);
3832   std::vector<const DataArrayInt *> corr2(corr.begin(),corr.end());
3833   setGroupsAtLevel(meshDimRelToMax,corr2,true);
3834 }
3835
3836 /*!
3837  * Creates groups at a given level in \a this mesh from a sequence of
3838  * meshes each representing a group.
3839  * The given meshes must share the same node coordinates array.
3840  *  \param [in] meshDimRelToMax - the relative dimension to create the groups at.
3841  *  \param [in] ms - the sequence of meshes. Each mesh in \a ms represents a group to
3842  *         create in \a this mesh.
3843  *  \param [in] renum - if \c true, then the optional numbers of entities are taken into
3844  *         account. 
3845  *  \throw If \a ms is empty.
3846  *  \throw If dimension of meshes in \a ms does not correspond to \a meshDimRelToMax or
3847  *         to the existing meshes of other levels of \a this mesh.
3848  *  \throw If the meshes in \a ms do not share the same node coordinates array.
3849  *  \throw If the node coordinates array of \a this mesh (if any) is not the same as that
3850  *         of the given meshes.
3851  *  \throw If \a ms[ i ] is not well defined (MEDCouplingUMesh::checkCoherency()).
3852  *  \throw If names of some meshes in \a ms are equal.
3853  *  \throw If \a ms includes a mesh with an empty name.
3854  */
3855 void MEDFileUMesh::setGroupsOnSetMesh(int meshDimRelToMax, const std::vector<const MEDCouplingUMesh *>& ms, bool renum)
3856 {
3857   if(ms.empty())
3858     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsOnSetMesh : expecting a non empty vector !");
3859   int sz=(-meshDimRelToMax)+1;
3860   if(sz>=(int)_ms.size())
3861     _ms.resize(sz);
3862   checkMeshDimCoherency(ms[0]->getMeshDimension(),meshDimRelToMax);
3863   DataArrayDouble *coo=checkMultiMesh(ms);
3864   if((DataArrayDouble *)_coords==0)
3865     {
3866       coo->incrRef();
3867       _coords=coo;
3868     }
3869   else
3870     if((DataArrayDouble *)_coords!=coo)
3871       throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsOnSetMesh : coordinates mismatches !");
3872   MEDCouplingUMesh *m=getMeshAtLevel(meshDimRelToMax,renum);
3873   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > corr(ms.size());
3874   int i=0;
3875   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++,i++)
3876     {
3877       DataArrayInt *arr=0;
3878       bool test=m->areCellsIncludedIn(*it,_zipconn_pol,arr);
3879       corr[i]=arr;
3880       if(!test)
3881         {
3882           std::ostringstream oss; oss << "MEDFileUMesh::setGroupsOnSetMesh : mesh #" << i << " is not part of whole mesh !";
3883           throw INTERP_KERNEL::Exception(oss.str().c_str());
3884         }
3885     }
3886   std::vector<const DataArrayInt *> corr2(corr.begin(),corr.end());
3887   setGroupsAtLevel(meshDimRelToMax,corr2,renum);
3888 }
3889
3890 DataArrayDouble *MEDFileUMesh::checkMultiMesh(const std::vector<const MEDCouplingUMesh *>& ms) const
3891 {
3892   const DataArrayDouble *ret=ms[0]->getCoords();
3893   int mdim=ms[0]->getMeshDimension();
3894   for(unsigned int i=1;i<ms.size();i++)
3895     {
3896       ms[i]->checkCoherency();
3897       if(ms[i]->getCoords()!=ret)
3898         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMultiMesh : meshes must share the same coords !");
3899       if(ms[i]->getMeshDimension()!=mdim)
3900         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMultiMesh : meshes have not same mesh dimension !");
3901     }
3902   return const_cast<DataArrayDouble *>(ret);
3903 }
3904
3905 /*!
3906  * Sets the family field of a given relative dimension.
3907  *  \param [in] meshDimRelToMaxExt - the relative dimension of entities for which
3908  *          the family field is set.
3909  *  \param [in] famArr - the array of the family field.
3910  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3911  *  \throw If \a famArr has an invalid size.
3912  */
3913 void MEDFileUMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr)
3914 {
3915   if(meshDimRelToMaxExt==1)
3916     {
3917       if(!famArr)
3918         {
3919           _fam_coords=0;
3920           return ;
3921         }
3922       DataArrayDouble *coo(_coords);
3923       if(!coo)
3924         throw INTERP_KERNEL::Exception("MEDFileUMesh::setFamilyFieldArr : the coordinates have not been set !");
3925       famArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),1,"MEDFileUMesh::setFamilyFieldArr : Problem in size of node family arr ! ");
3926       famArr->incrRef();
3927       _fam_coords=famArr;
3928       return ;
3929     }
3930   if(meshDimRelToMaxExt>1)
3931     throw INTERP_KERNEL::Exception("MEDFileUMesh::setFamilyFieldArr : Dimension request is invalid (>1) !");
3932   int traducedRk=-meshDimRelToMaxExt;
3933   if(traducedRk>=(int)_ms.size())
3934     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
3935   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
3936     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3937   return _ms[traducedRk]->setFamilyArr(famArr);
3938 }
3939
3940 /*!
3941  * Sets the optional numbers of mesh entities of a given dimension.
3942  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
3943  *  \param [in] renumArr - the array of the numbers.
3944  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3945  *  \throw If \a renumArr has an invalid size.
3946  */
3947 void MEDFileUMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr)
3948 {
3949   if(meshDimRelToMaxExt==1)
3950     {
3951       if(!renumArr)
3952         {
3953           _num_coords=0;
3954           _rev_num_coords=0;
3955           return ;
3956         }
3957       DataArrayDouble *coo(_coords);
3958       if(!coo)
3959         throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumFieldArr : the coordinates have not been set !");
3960       renumArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),1,"MEDFileUMesh::setRenumArr : Problem in size of node numbering arr ! ");
3961       renumArr->incrRef();
3962       _num_coords=renumArr;
3963       computeRevNum();
3964       return ;
3965     }
3966   if(meshDimRelToMaxExt>1)
3967     throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumArr : Dimension request is invalid (>1) !");
3968   int traducedRk=-meshDimRelToMaxExt;
3969   if(traducedRk>=(int)_ms.size())
3970     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
3971   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
3972     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3973   return _ms[traducedRk]->setRenumArr(renumArr);
3974 }
3975
3976 /*!
3977  * Sets the optional names of mesh entities of a given dimension.
3978  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
3979  *  \param [in] nameArr - the array of the names.
3980  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3981  *  \throw If \a nameArr has an invalid size.
3982  */
3983 void MEDFileUMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr)
3984 {
3985   if(meshDimRelToMaxExt==1)
3986     {
3987       if(!nameArr)
3988         {
3989           _name_coords=0;
3990           return ;
3991         }
3992       DataArrayDouble *coo(_coords);
3993       if(!coo)
3994         throw INTERP_KERNEL::Exception("MEDFileUMesh::setNameFieldAtLevel : the coordinates have not been set !");
3995       nameArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),MED_SNAME_SIZE,"MEDFileUMesh::setNameFieldAtLevel : Problem in size of node numbering arr ! ");
3996       nameArr->incrRef();
3997       _name_coords=nameArr;
3998       return ;
3999     }
4000   if(meshDimRelToMaxExt>1)
4001     throw INTERP_KERNEL::Exception("MEDFileUMesh::setNameFieldAtLevel : Dimension request is invalid (>1) !");
4002   int traducedRk=-meshDimRelToMaxExt;
4003   if(traducedRk>=(int)_ms.size())
4004     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
4005   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
4006     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
4007   return _ms[traducedRk]->setNameArr(nameArr);
4008 }
4009
4010 void MEDFileUMesh::synchronizeTinyInfoOnLeaves() const
4011 {
4012   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
4013     if((const MEDFileUMeshSplitL1 *)(*it))
4014       (*it)->synchronizeTinyInfo(*this);
4015 }
4016
4017 /*!
4018  * This method is called by MEDFileMesh::changeFamilyId. It performs only one part of the family id modification.
4019  */
4020 void MEDFileUMesh::changeFamilyIdArr(int oldId, int newId)
4021 {
4022   DataArrayInt *arr=_fam_coords;
4023   if(arr)
4024     arr->changeValue(oldId,newId);
4025   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
4026     {
4027       MEDFileUMeshSplitL1 *sp=(*it);
4028       if(sp)
4029         {
4030           sp->changeFamilyIdArr(oldId,newId);
4031         }
4032     }
4033 }
4034
4035 std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > MEDFileUMesh::getAllNonNullFamilyIds() const
4036 {
4037   std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret;
4038   const DataArrayInt *da(_fam_coords);
4039   if(da)
4040     { da->incrRef(); ret.push_back(MEDCouplingAutoRefCountObjectPtr<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
4041   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
4042     {
4043       const MEDFileUMeshSplitL1 *elt(*it);
4044       if(elt)
4045         {
4046           da=elt->getFamilyField();
4047           if(da)
4048             { da->incrRef(); ret.push_back(MEDCouplingAutoRefCountObjectPtr<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
4049         }
4050     }
4051   return ret;
4052 }
4053
4054 void MEDFileUMesh::computeRevNum() const
4055 {
4056   if((const DataArrayInt *)_num_coords)
4057     {
4058       int pos;
4059       int maxValue=_num_coords->getMaxValue(pos);
4060       _rev_num_coords=_num_coords->invertArrayN2O2O2N(maxValue+1);
4061     }
4062 }
4063
4064 std::size_t MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren() const
4065 {
4066   return MEDFileMesh::getHeapMemorySizeWithoutChildren();
4067 }
4068
4069 std::vector<const BigMemoryObject *> MEDFileStructuredMesh::getDirectChildrenWithNull() const
4070 {
4071   std::vector<const BigMemoryObject *> ret(MEDFileMesh::getDirectChildrenWithNull());
4072   ret.push_back((const DataArrayInt *)_fam_nodes);
4073   ret.push_back((const DataArrayInt *)_num_nodes);
4074   ret.push_back((const DataArrayAsciiChar *)_names_nodes);
4075   ret.push_back((const DataArrayInt *)_fam_cells);
4076   ret.push_back((const DataArrayInt *)_num_cells);
4077   ret.push_back((const DataArrayAsciiChar *)_names_cells);
4078   ret.push_back((const DataArrayInt *)_fam_faces);
4079   ret.push_back((const DataArrayInt *)_num_faces);
4080   ret.push_back((const DataArrayInt *)_rev_num_nodes);
4081   ret.push_back((const DataArrayAsciiChar *)_names_faces);
4082   ret.push_back((const DataArrayInt *)_rev_num_cells);
4083   ret.push_back((const MEDCoupling1SGTUMesh*)_faces_if_necessary);
4084   return ret;
4085 }
4086
4087 int MEDFileStructuredMesh::getMaxAbsFamilyIdInArrays() const
4088 {
4089   int ret=-std::numeric_limits<int>::max(),tmp=-1;
4090   if((const DataArrayInt *)_fam_nodes)
4091     {
4092       int val=_fam_nodes->getMaxValue(tmp);
4093       ret=std::max(ret,std::abs(val));
4094     }
4095   if((const DataArrayInt *)_fam_cells)
4096     {
4097       int val=_fam_cells->getMaxValue(tmp);
4098       ret=std::max(ret,std::abs(val));
4099     }
4100   if((const DataArrayInt *)_fam_faces)
4101     {
4102       int val=_fam_faces->getMaxValue(tmp);
4103       ret=std::max(ret,std::abs(val));
4104     }
4105   return ret;
4106 }
4107
4108 int MEDFileStructuredMesh::getMaxFamilyIdInArrays() const
4109 {
4110   int ret=-std::numeric_limits<int>::max(),tmp=-1;
4111   if((const DataArrayInt *)_fam_nodes)
4112     {
4113       int val=_fam_nodes->getMaxValue(tmp);
4114       ret=std::max(ret,val);
4115     }
4116   if((const DataArrayInt *)_fam_cells)
4117     {
4118       int val=_fam_cells->getMaxValue(tmp);
4119       ret=std::max(ret,val);
4120     }
4121   if((const DataArrayInt *)_fam_faces)
4122     {
4123       int val=_fam_faces->getMaxValue(tmp);
4124       ret=std::max(ret,val);
4125     }
4126   return ret;
4127 }
4128
4129 int MEDFileStructuredMesh::getMinFamilyIdInArrays() const
4130 {
4131   int ret=std::numeric_limits<int>::max(),tmp=-1;
4132   if((const DataArrayInt *)_fam_nodes)
4133     {
4134       int val=_fam_nodes->getMinValue(tmp);
4135       ret=std::min(ret,val);
4136     }
4137   if((const DataArrayInt *)_fam_cells)
4138     {
4139       int val=_fam_cells->getMinValue(tmp);
4140       ret=std::min(ret,val);
4141     }
4142   if((const DataArrayInt *)_fam_faces)
4143     {
4144       int val=_fam_faces->getMinValue(tmp);
4145       ret=std::min(ret,val);
4146     }
4147   return ret;
4148 }
4149
4150 bool MEDFileStructuredMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
4151 {
4152   if(!MEDFileMesh::isEqual(other,eps,what))
4153     return false;
4154   const MEDFileStructuredMesh *otherC=dynamic_cast<const  MEDFileStructuredMesh *>(other);
4155   if(!otherC)
4156     {
4157       what="Mesh types differ ! This is structured and other is NOT !";
4158       return false;
4159     }
4160   const DataArrayInt *famc1=_fam_nodes;
4161   const DataArrayInt *famc2=otherC->_fam_nodes;
4162   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
4163     {
4164       what="Mismatch of families arr on nodes ! One is defined and not other !";
4165       return false;
4166     }
4167   if(famc1)
4168     {
4169       bool ret=famc1->isEqual(*famc2);
4170       if(!ret)
4171         {
4172           what="Families arr on nodes differ !";
4173           return false;
4174         }
4175     }
4176   famc1=_fam_cells;
4177   famc2=otherC->_fam_cells;
4178   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
4179     {
4180       what="Mismatch of families arr on cells ! One is defined and not other !";
4181       return false;
4182     }
4183   if(famc1)
4184     {
4185       bool ret=famc1->isEqual(*famc2);
4186       if(!ret)
4187         {
4188           what="Families arr on cells differ !";
4189           return false;
4190         }
4191     }
4192   famc1=_fam_faces;
4193   famc2=otherC->_fam_faces;
4194   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
4195     {
4196       what="Mismatch of families arr on faces ! One is defined and not other !";
4197       return false;
4198     }
4199   if(famc1)
4200     {
4201       bool ret=famc1->isEqual(*famc2);
4202       if(!ret)
4203         {
4204           what="Families arr on faces differ !";
4205           return false;
4206         }
4207     }
4208   famc1=_num_nodes;
4209   famc2=otherC->_num_nodes;
4210   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
4211     {
4212       what="Mismatch of numbering arr on nodes ! One is defined and not other !";
4213       return false;
4214     }
4215   if(famc1)
4216     {
4217       bool ret=famc1->isEqual(*famc2);
4218       if(!ret)
4219         {
4220           what="Numbering arr on nodes differ !";
4221           return false;
4222         }
4223     }
4224   famc1=_num_cells;
4225   famc2=otherC->_num_cells;
4226   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
4227     {
4228       what="Mismatch of numbering arr on cells ! One is defined and not other !";
4229       return false;
4230     }
4231   if(famc1)
4232     {
4233       bool ret=famc1->isEqual(*famc2);
4234       if(!ret)
4235         {
4236           what="Numbering arr on cells differ !";
4237           return false;
4238         }
4239     }
4240   famc1=_num_faces;
4241   famc2=otherC->_num_faces;
4242   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
4243     {
4244       what="Mismatch of numbering arr on faces ! One is defined and not other !";
4245       return false;
4246     }
4247   if(famc1)
4248     {
4249       bool ret=famc1->isEqual(*famc2);
4250       if(!ret)
4251         {
4252           what="Numbering arr on faces differ !";
4253           return false;
4254         }
4255     }
4256   const DataArrayAsciiChar *d1=_names_cells;
4257   const DataArrayAsciiChar *d2=otherC->_names_cells;
4258   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
4259     {
4260       what="Mismatch of naming arr on cells ! One is defined and not other !";
4261       return false;
4262     }
4263   if(d1)
4264     {
4265       bool ret=d1->isEqual(*d2);
4266       if(!ret)
4267         {
4268           what="Naming arr on cells differ !";
4269           return false;
4270         }
4271     }
4272   d1=_names_faces;
4273   d2=otherC->_names_faces;
4274   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
4275     {
4276       what="Mismatch of naming arr on faces ! One is defined and not other !";
4277       return false;
4278     }
4279   if(d1)
4280     {
4281       bool ret=d1->isEqual(*d2);
4282       if(!ret)
4283         {
4284           what="Naming arr on faces differ !";
4285           return false;
4286         }
4287     }
4288   d1=_names_nodes;
4289   d2=otherC->_names_nodes;
4290   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
4291     {
4292       what="Mismatch of naming arr on nodes ! One is defined and not other !";
4293       return false;
4294     }
4295   if(d1)
4296     {
4297       bool ret=d1->isEqual(*d2);
4298       if(!ret)
4299         {
4300           what="Naming arr on nodes differ !";
4301           return false;
4302         }
4303     }
4304   return true;
4305 }
4306
4307 void MEDFileStructuredMesh::clearNonDiscrAttributes() const
4308 {
4309   MEDFileMesh::clearNonDiscrAttributes();
4310   const DataArrayInt *tmp=_fam_nodes;
4311   if(tmp)
4312     (const_cast<DataArrayInt *>(tmp))->setName("");
4313   tmp=_num_nodes;
4314   if(tmp)
4315     (const_cast<DataArrayInt *>(tmp))->setName("");
4316   tmp=_fam_cells;
4317   if(tmp)
4318     (const_cast<DataArrayInt *>(tmp))->setName("");
4319   tmp=_num_cells;
4320   if(tmp)
4321     (const_cast<DataArrayInt *>(tmp))->setName("");
4322   tmp=_fam_faces;
4323   if(tmp)
4324     (const_cast<DataArrayInt *>(tmp))->setName("");
4325   tmp=_num_faces;
4326   if(tmp)
4327     (const_cast<DataArrayInt *>(tmp))->setName("");
4328 }
4329
4330 /*!
4331  * Returns ids of mesh entities contained in given families of a given dimension.
4332  *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
4333  *          are required.
4334  *  \param [in] fams - the names of the families of interest.
4335  *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
4336  *          returned instead of ids.
4337  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
4338  *          numbers, if available and required, of mesh entities of the families. The caller
4339  *          is to delete this array using decrRef() as it is no more needed. 
4340  *  \throw If the family field is missing for \a meshDimRelToMaxExt.
4341  */
4342 DataArrayInt *MEDFileStructuredMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const
4343 {
4344   std::vector<int> famIds(getFamiliesIds(fams));
4345   switch(meshDimRelToMaxExt)
4346   {
4347     case 1:
4348       {
4349         if((const DataArrayInt *)_fam_nodes)
4350           {
4351             MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
4352             if(!famIds.empty())
4353               da=_fam_nodes->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
4354             else
4355               da=_fam_nodes->getIdsEqualList(0,0);
4356             if(renum)
4357               return MEDFileUMeshSplitL1::Renumber(_num_nodes,da);
4358             else
4359               return da.retn();
4360           }
4361         else
4362           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on nodes !");
4363         break;
4364       }
4365     case 0:
4366       {
4367         if((const DataArrayInt *)_fam_cells)
4368           {
4369             MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
4370             if(!famIds.empty())
4371               da=_fam_cells->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
4372             else
4373               da=_fam_cells->getIdsEqualList(0,0);
4374             if(renum)
4375               return MEDFileUMeshSplitL1::Renumber(_num_cells,da);
4376             else
4377               return da.retn();
4378           }
4379         else
4380           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on cells !");
4381         break;
4382       }
4383     case -1:
4384       {
4385         if((const DataArrayInt *)_fam_faces)
4386           {
4387             MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
4388             if(!famIds.empty())
4389               da=_fam_faces->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
4390             else
4391               da=_fam_faces->getIdsEqualList(0,0);
4392             if(renum)
4393               return MEDFileUMeshSplitL1::Renumber(_num_faces,da);
4394             else
4395               return da.retn();
4396           }
4397         else
4398           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on faces !");
4399         break;
4400       }
4401     default:
4402       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : input meshDimRelative must be in [0,1,-1] !");
4403   }
4404   throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : unmanaged case !");
4405 }
4406
4407 /*!
4408  * Sets the family field of a given relative dimension.
4409  *  \param [in] meshDimRelToMaxExt - the relative dimension of entities for which
4410  *          the family field is set.
4411  *  \param [in] famArr - the array of the family field.
4412  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4413  *  \throw If \a famArr has an invalid size.
4414  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1 and \a meshDimRelToMaxExt != -1.
4415  */
4416 void MEDFileStructuredMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr)
4417 {
4418   const MEDCouplingStructuredMesh *mesh(getStructuredMesh());
4419   if(!mesh)
4420     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setFamilyFieldArr : no structured mesh specified ! Impossible to set family array !");
4421   switch(meshDimRelToMaxExt)
4422   {
4423     case 0:
4424       {
4425         int nbCells=mesh->getNumberOfCells();
4426         famArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of cells of mesh !");
4427         _fam_cells=famArr;
4428         break;
4429       }
4430     case 1:
4431       {
4432         int nbNodes=mesh->getNumberOfNodes();
4433         famArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !");
4434         _fam_nodes=famArr;
4435         break;
4436       }
4437     case -1:
4438       {
4439         int nbCells=mesh->getNumberOfCellsOfSubLevelMesh();
4440         famArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of faces of mesh !");
4441         _fam_faces=famArr;
4442         break;
4443       }
4444     default:
4445       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setFamilyFieldArr : Only available for levels 0 or 1 or -1 !");
4446   }
4447   if(famArr)
4448     famArr->incrRef();
4449 }
4450
4451 /*!
4452  * Sets the optional numbers of mesh entities of a given dimension.
4453  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4454  *  \param [in] renumArr - the array of the numbers.
4455  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4456  *  \throw If \a renumArr has an invalid size.
4457  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
4458  */
4459 void MEDFileStructuredMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr)
4460 {
4461   const MEDCouplingStructuredMesh *mesh=getStructuredMesh();
4462   if(!mesh)
4463     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : no structured mesh specified ! Impossible to set number array !");
4464   switch(meshDimRelToMaxExt)
4465   {
4466     case 0:
4467       {
4468         int nbCells=mesh->getNumberOfCells();
4469         renumArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Renum arr ! Mismatch with number of cells of mesh !");
4470         _num_cells=renumArr;
4471         break;
4472       }
4473     case 1:
4474       {
4475         int nbNodes=mesh->getNumberOfNodes();
4476         renumArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !");
4477         _num_nodes=renumArr;
4478         break;
4479       }
4480     case -1:
4481       {
4482         int nbCells=mesh->getNumberOfCellsOfSubLevelMesh();
4483         renumArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Renum arr ! Mismatch with number of faces of mesh !");
4484         _num_faces=renumArr;
4485         break;
4486       }
4487     default:
4488       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : Only available for levels 0 or 1 or -1 !");
4489   }
4490   if(renumArr)
4491     renumArr->incrRef();
4492 }
4493
4494 /*!
4495  * Sets the optional names of mesh entities of a given dimension.
4496  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4497  *  \param [in] nameArr - the array of the names.
4498  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4499  *  \throw If \a nameArr has an invalid size.
4500  */
4501 void MEDFileStructuredMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr)
4502 {
4503   const MEDCouplingStructuredMesh *mesh(getStructuredMesh());
4504   if(!mesh)
4505     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : no structured mesh specified ! Impossible to set names array !");
4506   switch(meshDimRelToMaxExt)
4507   {
4508     case 0:
4509       {
4510         int nbCells=mesh->getNumberOfCells();
4511         nameArr->checkNbOfTuplesAndComp(nbCells,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of cells of mesh !");
4512         _names_cells=nameArr;
4513         break;
4514       }
4515     case 1:
4516       {
4517         int nbNodes=mesh->getNumberOfNodes();
4518         nameArr->checkNbOfTuplesAndComp(nbNodes,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of nodes of mesh !");
4519         _names_nodes=nameArr;
4520         break;
4521       }
4522     case -1:
4523       {
4524         int nbCells=mesh->getNumberOfCellsOfSubLevelMesh();
4525         nameArr->checkNbOfTuplesAndComp(nbCells,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of faces of mesh !");
4526         _names_cells=nameArr;
4527       }
4528     default:
4529       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : Only available for levels 0 or 1 or -1 !");
4530   }
4531   if(nameArr)
4532     nameArr->incrRef();
4533 }
4534
4535 /*!
4536  * Returns the family field for mesh entities of a given dimension.
4537  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4538  *  \return const DataArrayInt * - the family field. It is an array of ids of families
4539  *          each mesh entity belongs to. It can be \c NULL.
4540  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
4541  */
4542 const DataArrayInt *MEDFileStructuredMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) const
4543 {
4544   switch(meshDimRelToMaxExt)
4545   {
4546     case 0:
4547       return _fam_cells;
4548     case 1:
4549       return _fam_nodes;
4550     case -1:
4551       return _fam_faces;
4552     default:
4553       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamilyFieldAtLevel : Only available for levels 0 or 1 or -1 !");
4554   }
4555 }
4556
4557 /*!
4558  * Returns the optional numbers of mesh entities of a given dimension.
4559  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4560  *  \return const DataArrayInt * - the array of the entity numbers.
4561  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4562  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
4563  */
4564 const DataArrayInt *MEDFileStructuredMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) const
4565 {
4566   switch(meshDimRelToMaxExt)
4567   {
4568     case 0:
4569       return _num_cells;
4570     case 1:
4571       return _num_nodes;
4572     case -1:
4573       return _num_faces;
4574     default:
4575       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberFieldAtLevel : Only available for levels 0 or 1 or -1 !");
4576   }
4577 }
4578
4579 /*!
4580  * Returns the optional numbers of mesh entities of a given dimension transformed using
4581  * DataArrayInt::invertArrayN2O2O2N().
4582  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4583  *  \return const DataArrayInt * - the array of the entity numbers transformed using
4584  *          DataArrayInt::invertArrayN2O2O2N().
4585  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
4586  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4587  */
4588 const DataArrayInt *MEDFileStructuredMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxExt) const
4589 {
4590   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4591     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getRevNumberFieldAtLevel : Only available for levels 0 or 1 !");
4592   if(meshDimRelToMaxExt==0)
4593     {
4594       if((const DataArrayInt *)_num_cells)
4595         {
4596           int pos;
4597           int maxValue=_num_cells->getMaxValue(pos);
4598           _rev_num_cells=_num_cells->invertArrayN2O2O2N(maxValue+1);
4599           return _rev_num_cells;
4600         }
4601       else
4602         throw INTERP_KERNEL::Exception("MEDFileCMesh::getRevNumberFieldAtLevel : no cell renumbering for a request on reverse numbering !");
4603     }
4604   else
4605     {
4606       if((const DataArrayInt *)_num_nodes)
4607         {
4608           int pos;
4609           int maxValue=_num_nodes->getMaxValue(pos);
4610           _rev_num_nodes=_num_nodes->invertArrayN2O2O2N(maxValue+1);
4611           return _rev_num_nodes;
4612         }
4613       else
4614         throw INTERP_KERNEL::Exception("MEDFileCMesh::getRevNumberFieldAtLevel : no node renumbering for a request on reverse numbering !");
4615     }
4616 }
4617
4618 const DataArrayAsciiChar *MEDFileStructuredMesh::getNameFieldAtLevel(int meshDimRelToMaxExt) const
4619 {
4620   switch(meshDimRelToMaxExt)
4621   {
4622     case 0:
4623       return _names_cells;
4624     case 1:
4625       return _names_nodes;
4626     case -1:
4627       return _names_faces;
4628     default:
4629       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNameFieldAtLevel : Only available for levels 0 or 1 or -1 !");
4630   }
4631 }
4632
4633 /*!
4634  * Returns relative dimensions of mesh entities (excluding nodes) present in \a this mesh.
4635  *  \return std::vector<int> - a sequence of the relative dimensions: [0].
4636  */
4637 std::vector<int> MEDFileStructuredMesh::getNonEmptyLevels() const
4638 {
4639   std::vector<int> ret(1);
4640   return ret;
4641 }
4642
4643 /*!
4644  * Returns relative dimensions of mesh entities (including nodes) present in \a this mesh.
4645  *  \return std::vector<int> - a sequence of the relative dimensions: [1,0].
4646  */
4647 std::vector<int> MEDFileStructuredMesh::getNonEmptyLevelsExt() const
4648 {
4649   std::vector<int> ret(2);
4650   ret[0]=1;
4651   return ret;
4652 }
4653
4654 /*!
4655  * Returns the set of extensive levels (nodes included) where not NULL family arr are defined.
4656  */
4657 std::vector<int> MEDFileStructuredMesh::getFamArrNonEmptyLevelsExt() const
4658 {
4659   std::vector<int> ret;
4660   const DataArrayInt *famNodes(_fam_nodes),*famCells(_fam_cells),*famFaces(_fam_faces);
4661   if(famNodes)
4662     ret.push_back(1);
4663   if(famCells)
4664     ret.push_back(0);
4665   if(famFaces)
4666     ret.push_back(-1);
4667   return ret;
4668 }
4669
4670 /*!
4671  * Returns the set of extensive levels (nodes included) where not NULL numbering arr are defined.
4672  */
4673 std::vector<int> MEDFileStructuredMesh::getNumArrNonEmptyLevelsExt() const
4674 {
4675   std::vector<int> ret;
4676   const DataArrayInt *numNodes(_num_nodes),*numCells(_num_cells),*numFaces(_num_faces);
4677   if(numNodes)
4678     ret.push_back(1);
4679   if(numCells)
4680     ret.push_back(0);
4681   if(numFaces)
4682     ret.push_back(-1);
4683   return ret;
4684 }
4685
4686 /*!
4687  * Returns the set of extensive levels (nodes included) where not NULL naming arr are defined.
4688  */
4689 std::vector<int> MEDFileStructuredMesh::getNameArrNonEmptyLevelsExt() const
4690 {
4691   std::vector<int> ret;
4692   const DataArrayAsciiChar *namesNodes(_names_nodes),*namesCells(_names_cells),*namesFaces(_names_faces);
4693   if(namesNodes)
4694     ret.push_back(1);
4695   if(namesCells)
4696     ret.push_back(0);
4697   if(namesFaces)
4698     ret.push_back(-1);
4699   return ret;
4700 }
4701
4702 /*!
4703  * no implementation here, it is not a bug, but intresically no polyhedra in \a this.
4704  */
4705 bool MEDFileStructuredMesh::unPolyze(std::vector<int>& oldCode, std::vector<int>& newCode, DataArrayInt *& o2nRenumCell)
4706 {
4707   oldCode.clear(); newCode.clear(); o2nRenumCell=0;
4708   return false;
4709 }
4710
4711 void MEDFileStructuredMesh::changeFamilyIdArr(int oldId, int newId)
4712 {
4713   DataArrayInt *arr=_fam_nodes;
4714   if(arr)
4715     arr->changeValue(oldId,newId);
4716   arr=_fam_cells;
4717   if(arr)
4718     arr->changeValue(oldId,newId);
4719   arr=_fam_faces;
4720   if(arr)
4721     arr->changeValue(oldId,newId);
4722 }
4723
4724 void MEDFileStructuredMesh::deepCpyAttributes()
4725 {
4726   if((const DataArrayInt*)_fam_nodes)
4727     _fam_nodes=_fam_nodes->deepCpy();
4728   if((const DataArrayInt*)_num_nodes)
4729     _num_nodes=_num_nodes->deepCpy();
4730   if((const DataArrayAsciiChar*)_names_nodes)
4731     _names_nodes=_names_nodes->deepCpy();
4732   if((const DataArrayInt*)_fam_cells)
4733     _fam_cells=_fam_cells->deepCpy();
4734   if((const DataArrayInt*)_num_cells)
4735     _num_cells=_num_cells->deepCpy();
4736   if((const DataArrayAsciiChar*)_names_cells)
4737     _names_cells=_names_cells->deepCpy();
4738   if((const DataArrayInt*)_fam_faces)
4739     _fam_faces=_fam_faces->deepCpy();
4740   if((const DataArrayInt*)_num_faces)
4741     _num_faces=_num_faces->deepCpy();
4742   if((const DataArrayAsciiChar*)_names_faces)
4743     _names_faces=_names_faces->deepCpy();
4744   if((const DataArrayInt*)_rev_num_nodes)
4745     _rev_num_nodes=_rev_num_nodes->deepCpy();
4746   if((const DataArrayInt*)_rev_num_cells)
4747     _rev_num_cells=_rev_num_cells->deepCpy();
4748 }
4749
4750 /*!
4751  * Returns a pointer to mesh at the specified level (here 0 is compulsary for cartesian mesh).
4752  * 
4753  * \return a pointer to cartesian mesh that need to be managed by the caller.
4754  * \warning the returned pointer has to be managed by the caller.
4755  */
4756
4757 /*!
4758  * Returns a pointer to MEDCouplingStructuredMesh held by \a this. 
4759  *  \param [in] meshDimRelToMax - it must be \c 0 or \c -1.
4760  *  \param [in] renum - it must be \c false.
4761  *  \return MEDCouplingMesh * - a pointer to MEDCouplingMesh that the caller is to
4762  *          delete using decrRef() as it is no more needed. 
4763  */
4764 MEDCouplingMesh *MEDFileStructuredMesh::getGenMeshAtLevel(int meshDimRelToMax, bool renum) const
4765 {
4766   if(renum)
4767     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support renumbering ! To do it perform request of renum array directly !");
4768   const MEDCouplingStructuredMesh *m(getStructuredMesh());
4769   switch(meshDimRelToMax)
4770   {
4771     case 0:
4772       {
4773         if(m)
4774           m->incrRef();
4775         return const_cast<MEDCouplingStructuredMesh *>(m);
4776       }
4777     case -1:
4778       {
4779         if(!m)
4780           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGenMeshAtLevel : level -1 requested must be non empty to be able to compute unstructured sub mesh !");
4781         buildMinusOneImplicitPartIfNeeded();
4782         MEDCouplingMesh *ret(_faces_if_necessary);
4783         if(ret)
4784           ret->incrRef();
4785         return ret;
4786       }
4787     default:
4788       throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support multi level for mesh 0 expected as input !");
4789   }
4790 }
4791
4792 /*!
4793  * Returns number of mesh entities of a given relative dimension in \a this mesh.
4794  *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
4795  *  \return int - the number of entities.
4796  *  \throw If no mesh entities of dimension \a meshDimRelToMaxExt are available in \a this mesh.
4797  */
4798 int MEDFileStructuredMesh::getSizeAtLevel(int meshDimRelToMaxExt) const
4799 {
4800   const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
4801   if(!cmesh)
4802     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : No structured mesh set !");
4803   switch(meshDimRelToMaxExt)
4804   {
4805     case 0:
4806       return cmesh->getNumberOfCells();
4807     case 1:
4808       return cmesh->getNumberOfNodes();
4809     case -1:
4810       return cmesh->getNumberOfCellsOfSubLevelMesh();
4811     default:
4812       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : Only available for levels 0 or 1 or -1 !");
4813   }
4814 }
4815
4816 int MEDFileStructuredMesh::getNumberOfNodes() const
4817 {
4818   const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
4819   if(!cmesh)
4820     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberOfNodes : no cartesian mesh set !");
4821   return cmesh->getNumberOfNodes();
4822 }
4823
4824 bool MEDFileStructuredMesh::hasImplicitPart() const
4825 {
4826   return true;
4827 }
4828
4829 /*!
4830  * \sa MEDFileStructuredMesh::getImplicitFaceMesh
4831  */
4832 int MEDFileStructuredMesh::buildImplicitPartIfAny(INTERP_KERNEL::NormalizedCellType gt) const
4833 {
4834   static const char MSG[]="MEDFileStructuredMesh::buildImplicitPartIfAny : the given geo type is not manageable by a structured mesh !";
4835   const MEDCoupling1SGTUMesh *zeFaceMesh(_faces_if_necessary);
4836   if(!zeFaceMesh)
4837     {
4838       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(getMeshDimension())));
4839       if(cm.getReverseExtrudedType()!=gt)
4840         throw INTERP_KERNEL::Exception(MSG);
4841       buildImplicitPart();
4842       return getStructuredMesh()->getNumberOfCellsOfSubLevelMesh();
4843     }
4844   else
4845     {
4846       if(gt!=zeFaceMesh->getCellModelEnum())
4847         throw INTERP_KERNEL::Exception(MSG);
4848       return zeFaceMesh->getNumberOfCells();
4849     }
4850 }
4851
4852 void MEDFileStructuredMesh::buildMinusOneImplicitPartIfNeeded() const
4853 {
4854   const MEDCoupling1SGTUMesh *zeFaceMesh(_faces_if_necessary);
4855   if(!zeFaceMesh)
4856     buildImplicitPart();
4857 }
4858
4859 void MEDFileStructuredMesh::buildImplicitPart() const
4860 {
4861   const MEDCouplingStructuredMesh *mcmesh(getStructuredMesh());
4862   if(!mcmesh)
4863     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::buildImplicitPart : Unable to build the implicit part of structured mesh because no structured mesh at level 0 defined !");
4864   _faces_if_necessary=mcmesh->build1SGTSubLevelMesh();
4865 }
4866
4867 void MEDFileStructuredMesh::releaseImplicitPartIfAny() const
4868 {
4869   _faces_if_necessary=0;
4870 }
4871
4872 /*!
4873  * Retrieves the internal pointer (no decrRef requested) of the implicit face mesh if any.
4874  * To force to build it you can invoke MEDFileStructuredMesh::buildImplicitPartIfAny method.
4875  * 
4876  * \sa MEDFileStructuredMesh::buildImplicitPartIfAny
4877  */
4878 MEDCoupling1SGTUMesh *MEDFileStructuredMesh::getImplicitFaceMesh() const
4879 {
4880   return _faces_if_necessary;
4881 }
4882
4883 std::vector<INTERP_KERNEL::NormalizedCellType> MEDFileStructuredMesh::getGeoTypesAtLevel(int meshDimRelToMax) const
4884 {
4885   const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
4886   if(!cmesh)
4887     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGeoTypesAtLevel : No structured mesh set !");
4888   switch(meshDimRelToMax)
4889   {
4890     case 0:
4891       {
4892         std::vector<INTERP_KERNEL::NormalizedCellType> ret(1,cmesh->getTypeOfCell(0));
4893         return ret;
4894       }
4895     case -1:
4896       {
4897         int mdim(cmesh->getMeshDimension());
4898         if(mdim<1)
4899           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGeoTypesAtLevel : only one level available for structured meshes ! Input 0 is mandatory or 0D mesh !");
4900         std::vector<INTERP_KERNEL::NormalizedCellType> ret(1,MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(mdim-1));
4901         return ret;
4902       }
4903     default:
4904       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGeoTypesAtLevel : only 2 levels available at most : 0 and -1 !");
4905   }
4906 }
4907
4908 void MEDFileStructuredMesh::whichAreNodesFetched(const MEDFileField1TSStructItem& st, const MEDFileFieldGlobsReal *globs, std::vector<bool>& nodesFetched) const
4909 {
4910   if(st.getNumberOfItems()!=1)
4911     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 !");
4912   if(st[0].getGeo()!=MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(getMeshDimension()))
4913     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : The sturture of field is not lying on expected geo type !");
4914   if(getNumberOfNodes()!=(int)nodesFetched.size())
4915     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : invalid size of array !");
4916   if(st[0].getPflName().empty())
4917     {
4918       std::fill(nodesFetched.begin(),nodesFetched.end(),true);
4919       return ;
4920     }
4921   const DataArrayInt *arr(globs->getProfile(st[0].getPflName()));
4922   const MEDCouplingStructuredMesh *cmesh=getStructuredMesh();//cmesh not null because getNumberOfNodes called before
4923   int sz(nodesFetched.size());
4924   for(const int *work=arr->begin();work!=arr->end();work++)
4925     {
4926       std::vector<int> conn;
4927       cmesh->getNodeIdsOfCell(*work,conn);
4928       for(std::vector<int>::const_iterator it=conn.begin();it!=conn.end();it++)
4929         if(*it>=0 && *it<sz)
4930           nodesFetched[*it]=true;
4931         else
4932           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : internal error !");
4933     }
4934 }
4935
4936 med_geometry_type MEDFileStructuredMesh::GetGeoTypeFromMeshDim(int meshDim)
4937 {
4938   INTERP_KERNEL::NormalizedCellType ct(MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(meshDim));
4939   return typmai3[ct];
4940 }
4941
4942 void MEDFileStructuredMesh::LoadStrMeshDAFromFile(med_idt fid, int meshDim, int dt, int it, const std::string& mName, MEDFileMeshReadSelector *mrs,
4943                                                   MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& famCells, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& numCells, MEDCouplingAutoRefCountObjectPtr<DataArrayAsciiChar>& namesCells)
4944 {
4945   med_bool chgt=MED_FALSE,trsf=MED_FALSE;
4946   med_geometry_type geoTypeReq=MEDFileStructuredMesh::GetGeoTypeFromMeshDim(meshDim);
4947   int nbOfElt(0);
4948   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf);
4949   if(nbOfElt>0)
4950     {
4951       if(!mrs || mrs->isCellFamilyFieldReading())
4952         {
4953           famCells=DataArrayInt::New();
4954           famCells->alloc(nbOfElt,1);
4955           MEDmeshEntityFamilyNumberRd(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,famCells->getPointer());
4956         }
4957     }
4958   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,MED_NUMBER,MED_NODAL,&chgt,&trsf);
4959   if(nbOfElt>0)
4960     {
4961       if(!mrs || mrs->isCellNumFieldReading())
4962         {
4963           numCells=DataArrayInt::New();
4964           numCells->alloc(nbOfElt,1);
4965           MEDmeshEntityNumberRd(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,numCells->getPointer());
4966         }
4967     }
4968   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,MED_NAME,MED_NODAL,&chgt,&trsf);
4969   if(nbOfElt>0)
4970     {
4971       if(!mrs || mrs->isCellNameFieldReading())
4972         {
4973           namesCells=DataArrayAsciiChar::New();
4974           namesCells->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end
4975           MEDmeshEntityNameRd(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,namesCells->getPointer());
4976           namesCells->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end
4977         }
4978     }
4979 }
4980
4981 void MEDFileStructuredMesh::loadStrMeshFromFile(MEDFileStrMeshL2 *strm, med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
4982 {
4983   setName(strm->getName());
4984   setDescription(strm->getDescription());
4985   setUnivName(strm->getUnivName());
4986   setIteration(strm->getIteration());
4987   setOrder(strm->getOrder());
4988   setTimeValue(strm->getTime());
4989   setTimeUnit(strm->getTimeUnit());
4990   MEDFileMeshL2::ReadFamiliesAndGrps(fid,mName,_families,_groups,mrs);
4991   med_bool chgt=MED_FALSE,trsf=MED_FALSE;
4992   int nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf);
4993   if(nbOfElt>0)
4994     {
4995       if(!mrs || mrs->isNodeFamilyFieldReading())
4996         {
4997           int nbNodes(getNumberOfNodes());
4998           if(nbOfElt>nbNodes)
4999             throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::loadStrMeshFromFile : invalid size of family node array regarding number of nodes in this ! File seems to be corrupted !");
5000           _fam_nodes=DataArrayInt::New();
5001           _fam_nodes->alloc(nbNodes,1);//yes nbNodes and not nbOfElt see next line.
5002           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...
5003             _fam_nodes->fillWithZero();
5004           MEDmeshEntityFamilyNumberRd(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,_fam_nodes->getPointer());
5005         }
5006     }
5007   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_NUMBER,MED_NODAL,&chgt,&trsf);
5008   if(nbOfElt>0)
5009     {
5010       if(!mrs || mrs->isNodeNumFieldReading())
5011         {
5012           _num_nodes=DataArrayInt::New();
5013           _num_nodes->alloc(nbOfElt,1);
5014           MEDmeshEntityNumberRd(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,_num_nodes->getPointer());
5015         }
5016     }
5017   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_NAME,MED_NODAL,&chgt,&trsf);
5018   if(nbOfElt>0)
5019     {
5020       if(!mrs || mrs->isNodeNameFieldReading())
5021         {
5022           _names_nodes=DataArrayAsciiChar::New();
5023           _names_nodes->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end
5024           MEDmeshEntityNameRd(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,_names_nodes->getPointer());
5025           _names_nodes->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end
5026         }
5027     }
5028   int meshDim(getStructuredMesh()->getMeshDimension());
5029   LoadStrMeshDAFromFile(fid,meshDim,dt,it,mName,mrs,_fam_cells,_num_cells,_names_cells);
5030   if(meshDim>=1)
5031     LoadStrMeshDAFromFile(fid,meshDim-1,dt,it,mName,mrs,_fam_faces,_num_faces,_names_faces);
5032 }
5033
5034 void MEDFileStructuredMesh::writeStructuredLL(med_idt fid, const std::string& maa) const
5035 {
5036   int meshDim(getStructuredMesh()->getMeshDimension());
5037   med_geometry_type geoTypeReq(GetGeoTypeFromMeshDim(meshDim)),geoTypeReq2(GetGeoTypeFromMeshDim(meshDim-1));
5038   //
5039   if((const DataArrayInt *)_fam_cells)
5040     MEDmeshEntityFamilyNumberWr(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq,_fam_cells->getNumberOfTuples(),_fam_cells->getConstPointer());
5041   if((const DataArrayInt *)_fam_faces)
5042     MEDmeshEntityFamilyNumberWr(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq2,_fam_faces->getNumberOfTuples(),_fam_faces->getConstPointer());
5043   if((const DataArrayInt *)_fam_nodes)
5044     MEDmeshEntityFamilyNumberWr(fid,maa.c_str(),_iteration,_order,MED_NODE,MED_NONE,_fam_nodes->getNumberOfTuples(),_fam_nodes->getConstPointer());
5045   if((const DataArrayInt *)_num_cells)
5046     MEDmeshEntityNumberWr(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq,_num_cells->getNumberOfTuples(),_num_cells->getConstPointer());
5047   if((const DataArrayInt *)_num_faces)
5048     MEDmeshEntityNumberWr(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq2,_num_faces->getNumberOfTuples(),_num_faces->getConstPointer());
5049   if((const DataArrayInt *)_num_nodes)
5050     MEDmeshEntityNumberWr(fid,maa.c_str(),_iteration,_order,MED_NODE,MED_NONE,_num_nodes->getNumberOfTuples(),_num_nodes->getConstPointer());
5051   if((const DataArrayAsciiChar *)_names_cells)
5052     {
5053       if(_names_cells->getNumberOfComponents()!=MED_SNAME_SIZE)
5054         {
5055           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on cells with number of components set to " << MED_SNAME_SIZE;
5056           oss << " ! The array has " << _names_cells->getNumberOfComponents() << " components !";
5057           throw INTERP_KERNEL::Exception(oss.str().c_str());
5058         }
5059       MEDmeshEntityNameWr(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq,_names_cells->getNumberOfTuples(),_names_cells->getConstPointer());
5060     }
5061   if((const DataArrayAsciiChar *)_names_faces)
5062     {
5063       if(_names_faces->getNumberOfComponents()!=MED_SNAME_SIZE)
5064         {
5065           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on faces with number of components set to " << MED_SNAME_SIZE;
5066           oss << " ! The array has " << _names_faces->getNumberOfComponents() << " components !";
5067           throw INTERP_KERNEL::Exception(oss.str().c_str());
5068         }
5069       MEDmeshEntityNameWr(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq2,_names_faces->getNumberOfTuples(),_names_faces->getConstPointer());
5070     }
5071   if((const DataArrayAsciiChar *)_names_nodes)
5072     {
5073       if(_names_nodes->getNumberOfComponents()!=MED_SNAME_SIZE)
5074         {
5075           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on nodes with number of components set to " << MED_SNAME_SIZE;
5076           oss << " ! The array has " << _names_cells->getNumberOfComponents() << " components !";
5077           throw INTERP_KERNEL::Exception(oss.str().c_str());
5078         }
5079       MEDmeshEntityNameWr(fid,maa.c_str(),_iteration,_order,MED_NODE,MED_NONE,_names_nodes->getNumberOfTuples(),_names_nodes->getConstPointer());
5080     }
5081   //
5082   MEDFileUMeshL2::WriteFamiliesAndGrps(fid,maa.c_str(),_families,_groups,_too_long_str);
5083 }
5084
5085 /*!
5086  * Returns an empty instance of MEDFileCMesh.
5087  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
5088  *          mesh using decrRef() as it is no more needed. 
5089  */
5090 MEDFileCMesh *MEDFileCMesh::New()
5091 {
5092   return new MEDFileCMesh;
5093 }
5094
5095 /*!
5096  * Returns a new MEDFileCMesh holding the mesh data that has been read from a given MED
5097  * file. The first mesh in the file is loaded.
5098  *  \param [in] fileName - the name of MED file to read.
5099  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
5100  *          mesh using decrRef() as it is no more needed. 
5101  *  \throw If the file is not readable.
5102  *  \throw If there is no meshes in the file.
5103  *  \throw If the mesh in the file is not a Cartesian one.
5104  */
5105 MEDFileCMesh *MEDFileCMesh::New(const std::string& fileName, MEDFileMeshReadSelector *mrs)
5106 {
5107   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
5108   if(ms.empty())
5109     {
5110       std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
5111       throw INTERP_KERNEL::Exception(oss.str().c_str());
5112     }
5113   MEDFileUtilities::CheckFileForRead(fileName);
5114   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
5115   int dt,it;
5116   ParaMEDMEM::MEDCouplingMeshType meshType;
5117   std::string dummy2;
5118   MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dt,it,dummy2);
5119   return new MEDFileCMesh(fid,ms.front(),dt,it,mrs);
5120 }
5121
5122 /*!
5123  * Returns a new MEDFileCMesh holding the mesh data that has been read from a given MED
5124  * file. The mesh to load is specified by its name and numbers of a time step and an
5125  * iteration.
5126  *  \param [in] fileName - the name of MED file to read.
5127  *  \param [in] mName - the name of the mesh to read.
5128  *  \param [in] dt - the number of a time step.
5129  *  \param [in] it - the number of an iteration.
5130  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
5131  *          mesh using decrRef() as it is no more needed. 
5132  *  \throw If the file is not readable.
5133  *  \throw If there is no mesh with given attributes in the file.
5134  *  \throw If the mesh in the file is not a Cartesian one.
5135  */
5136 MEDFileCMesh *MEDFileCMesh::New(const std::string& fileName, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
5137 {
5138   MEDFileUtilities::CheckFileForRead(fileName);
5139   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
5140   return new MEDFileCMesh(fid,mName,dt,it,mrs);
5141 }
5142
5143 std::size_t MEDFileCMesh::getHeapMemorySizeWithoutChildren() const
5144 {
5145   return MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren();
5146 }
5147
5148 std::vector<const BigMemoryObject *> MEDFileCMesh::getDirectChildrenWithNull() const
5149 {
5150   std::vector<const BigMemoryObject *> ret(MEDFileStructuredMesh::getDirectChildrenWithNull());
5151   ret.push_back((const MEDCouplingCMesh *)_cmesh);
5152   return ret;
5153 }
5154
5155 /*!
5156  * Returns the dimension on cells in \a this mesh.
5157  *  \return int - the mesh dimension.
5158  *  \throw If there are no cells in this mesh.
5159  */
5160 int MEDFileCMesh::getMeshDimension() const
5161 {
5162   if(!((const MEDCouplingCMesh*)_cmesh))
5163     throw INTERP_KERNEL::Exception("MEDFileCMesh::getMeshDimension : unable to get meshdimension because no mesh set !");
5164   return _cmesh->getMeshDimension();
5165 }
5166
5167 /*!
5168  * Returns the dimension on nodes in \a this mesh.
5169  *  \return int - the space dimension.
5170  *  \throw If there are no cells in this mesh.
5171  */
5172 int MEDFileCMesh::getSpaceDimension() const
5173 {
5174   if(!((const MEDCouplingCMesh*)_cmesh))
5175     throw INTERP_KERNEL::Exception("MEDFileCMesh::getSpaceDimension : unable to get spacedimension because no mesh set !");
5176   return _cmesh->getSpaceDimension();
5177 }
5178
5179 /*!
5180  * Returns a string describing \a this mesh.
5181  *  \return std::string - the mesh information string.
5182  */
5183 std::string MEDFileCMesh::simpleRepr() const
5184 {
5185   return MEDFileStructuredMesh::simpleRepr();
5186 }
5187
5188 /*!
5189  * Returns a full textual description of \a this mesh.
5190  *  \return std::string - the string holding the mesh description.
5191  */
5192 std::string MEDFileCMesh::advancedRepr() const
5193 {
5194   return simpleRepr();
5195 }
5196
5197 MEDFileMesh *MEDFileCMesh::shallowCpy() const
5198 {
5199   MEDCouplingAutoRefCountObjectPtr<MEDFileCMesh> ret=new MEDFileCMesh(*this);
5200   return ret.retn();
5201 }
5202
5203 MEDFileMesh *MEDFileCMesh::createNewEmpty() const
5204 {
5205   return new MEDFileCMesh;
5206 }
5207
5208 MEDFileMesh *MEDFileCMesh::deepCpy() const
5209 {
5210   MEDCouplingAutoRefCountObjectPtr<MEDFileCMesh> ret=new MEDFileCMesh(*this);
5211   if((const MEDCouplingCMesh*)_cmesh)
5212     ret->_cmesh=static_cast<MEDCouplingCMesh*>(_cmesh->deepCpy());
5213   ret->deepCpyAttributes();
5214   return ret.retn();
5215 }
5216
5217 /*!
5218  * Checks if \a this and another mesh are equal.
5219  *  \param [in] other - the mesh to compare with.
5220  *  \param [in] eps - a precision used to compare real values.
5221  *  \param [in,out] what - the string returning description of unequal data.
5222  *  \return bool - \c true if the meshes are equal, \c false, else.
5223  */
5224 bool MEDFileCMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
5225 {
5226   if(!MEDFileStructuredMesh::isEqual(other,eps,what))
5227     return false;
5228   const MEDFileCMesh *otherC=dynamic_cast<const MEDFileCMesh *>(other);
5229   if(!otherC)
5230     {
5231       what="Mesh types differ ! This is cartesian and other is NOT !";
5232       return false;
5233     }
5234   clearNonDiscrAttributes();
5235   otherC->clearNonDiscrAttributes();
5236   const MEDCouplingCMesh *coo1=_cmesh;
5237   const MEDCouplingCMesh *coo2=otherC->_cmesh;
5238   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
5239     {
5240       what="Mismatch of cartesian meshes ! One is defined and not other !";
5241       return false;
5242     }
5243   if(coo1)
5244     {
5245       bool ret=coo1->isEqual(coo2,eps);
5246       if(!ret)
5247         {
5248           what="cartesian meshes differ !";
5249           return false;
5250         }
5251     }
5252   return true;
5253 }
5254
5255 /*!
5256  * Clears redundant attributes of incorporated data arrays.
5257  */
5258 void MEDFileCMesh::clearNonDiscrAttributes() const
5259 {
5260   MEDFileStructuredMesh::clearNonDiscrAttributes();
5261   MEDFileUMeshSplitL1::ClearNonDiscrAttributes(_cmesh);//to it is not a bug umeshsplit have already the method implemented
5262 }
5263
5264 MEDFileCMesh::MEDFileCMesh()
5265 {
5266 }
5267
5268 MEDFileCMesh::MEDFileCMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
5269 try
5270 {
5271     loadCMeshFromFile(fid,mName,dt,it,mrs);
5272 }
5273 catch(INTERP_KERNEL::Exception& e)
5274 {
5275     throw e;
5276 }
5277
5278 void MEDFileCMesh::loadCMeshFromFile(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
5279 {
5280   ParaMEDMEM::MEDCouplingMeshType meshType;
5281   int dummy0,dummy1;
5282   std::string dtunit;
5283   int mid=MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dtunit);
5284   if(meshType!=CARTESIAN)
5285     {
5286       std::ostringstream oss; oss << "Trying to load as cartesian an existing mesh with name '" << mName << "' that is NOT cartesian !";
5287       throw INTERP_KERNEL::Exception(oss.str().c_str());
5288     }
5289   MEDFileCMeshL2 loaderl2;
5290   loaderl2.loadAll(fid,mid,mName,dt,it);
5291   MEDCouplingCMesh *mesh=loaderl2.getMesh();
5292   mesh->incrRef();
5293   _cmesh=mesh;
5294   loadStrMeshFromFile(&loaderl2,fid,mName,dt,it,mrs);
5295 }
5296
5297 /*!
5298  * Returns a const pointer to MEDCouplingCMesh held by \a this mesh.
5299  *  \return const MEDCouplingCMesh * - a pointer to the held MEDCouplingCMesh.
5300  */
5301 const MEDCouplingCMesh *MEDFileCMesh::getMesh() const
5302 {
5303   synchronizeTinyInfoOnLeaves();
5304   return _cmesh;
5305 }
5306
5307 const MEDCouplingStructuredMesh *MEDFileCMesh::getStructuredMesh() const
5308 {
5309   synchronizeTinyInfoOnLeaves();
5310   return _cmesh;
5311 }
5312
5313 /*!
5314  * Sets the MEDCouplingCMesh holding the data of \a this mesh.
5315  *  \param [in] m - the new MEDCouplingCMesh to refer to.
5316  *  \throw If the name or the description of \a this mesh and \a m are not empty and are
5317  *         different. 
5318  */
5319 void MEDFileCMesh::setMesh(MEDCouplingCMesh *m)
5320 {
5321   dealWithTinyInfo(m);
5322   if(m)
5323     m->incrRef();
5324   _cmesh=m;
5325 }
5326
5327 void MEDFileCMesh::writeLL(med_idt fid) const
5328 {
5329   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
5330   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
5331   INTERP_KERNEL::AutoPtr<char> dtunit=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE);
5332   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
5333   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
5334   MEDLoaderBase::safeStrCpy(_dt_unit.c_str(),MED_LNAME_SIZE,dtunit,_too_long_str);
5335   int spaceDim(_cmesh->getSpaceDimension());
5336   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
5337   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
5338   for(int i=0;i<spaceDim;i++)
5339     {
5340       std::string info(_cmesh->getCoordsAt(i)->getInfoOnComponent(0));
5341       std::string c,u;
5342       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
5343       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
5344       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
5345     }
5346   MEDmeshCr(fid,maa,spaceDim,spaceDim,MED_STRUCTURED_MESH,desc,dtunit,MED_SORT_DTIT,MED_CARTESIAN,comp,unit);
5347   MEDmeshUniversalNameWr(fid,maa);
5348   MEDmeshGridTypeWr(fid,maa,MED_CARTESIAN_GRID);
5349   for(int i=0;i<spaceDim;i++)
5350     {
5351       const DataArrayDouble *da=_cmesh->getCoordsAt(i);
5352       MEDmeshGridIndexCoordinateWr(fid,maa,_iteration,_order,_time,i+1,da->getNumberOfTuples(),da->getConstPointer());
5353     }
5354   //
5355   std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE));
5356   MEDFileStructuredMesh::writeStructuredLL(fid,meshName);
5357 }
5358
5359 void MEDFileCMesh::synchronizeTinyInfoOnLeaves() const
5360 {
5361   const MEDCouplingCMesh *cmesh=_cmesh;
5362   if(!cmesh)
5363     return;
5364   (const_cast<MEDCouplingCMesh *>(cmesh))->setName(_name);
5365   (const_cast<MEDCouplingCMesh *>(cmesh))->setDescription(_desc_name);
5366   (const_cast<MEDCouplingCMesh *>(cmesh))->setTime(_time,_iteration,_order);
5367   (const_cast<MEDCouplingCMesh *>(cmesh))->setTimeUnit(_dt_unit);
5368 }
5369
5370 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New()
5371 {
5372   return new MEDFileCurveLinearMesh;
5373 }
5374
5375 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const std::string& fileName, MEDFileMeshReadSelector *mrs)
5376 {
5377   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
5378   if(ms.empty())
5379     {
5380       std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
5381       throw INTERP_KERNEL::Exception(oss.str().c_str());
5382     }
5383   MEDFileUtilities::CheckFileForRead(fileName);
5384   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
5385   int dt,it;
5386   ParaMEDMEM::MEDCouplingMeshType meshType;
5387   std::string dummy2;
5388   MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dt,it,dummy2);
5389   return new MEDFileCurveLinearMesh(fid,ms.front(),dt,it,mrs);
5390 }
5391
5392 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const std::string& fileName, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
5393 {
5394   MEDFileUtilities::CheckFileForRead(fileName);
5395   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
5396   return new MEDFileCurveLinearMesh(fid,mName,dt,it,mrs);
5397 }
5398
5399 std::size_t MEDFileCurveLinearMesh::getHeapMemorySizeWithoutChildren() const
5400 {
5401   return MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren();
5402 }
5403
5404 std::vector<const BigMemoryObject *> MEDFileCurveLinearMesh::getDirectChildrenWithNull() const
5405 {
5406   std::vector<const BigMemoryObject *> ret(MEDFileStructuredMesh::getDirectChildrenWithNull());
5407   ret.push_back((const MEDCouplingCurveLinearMesh *)_clmesh);
5408   return ret;
5409 }
5410
5411 MEDFileMesh *MEDFileCurveLinearMesh::shallowCpy() const
5412 {
5413   MEDCouplingAutoRefCountObjectPtr<MEDFileCurveLinearMesh> ret=new MEDFileCurveLinearMesh(*this);
5414   return ret.retn();
5415 }
5416
5417 MEDFileMesh *MEDFileCurveLinearMesh::createNewEmpty() const
5418 {
5419   return new MEDFileCurveLinearMesh;
5420 }
5421
5422 MEDFileMesh *MEDFileCurveLinearMesh::deepCpy() const
5423 {
5424   MEDCouplingAutoRefCountObjectPtr<MEDFileCurveLinearMesh> ret=new MEDFileCurveLinearMesh(*this);
5425   if((const MEDCouplingCurveLinearMesh*)_clmesh)
5426     ret->_clmesh=static_cast<MEDCouplingCurveLinearMesh*>(_clmesh->deepCpy());
5427   ret->deepCpyAttributes();
5428   return ret.retn();
5429 }
5430
5431 int MEDFileCurveLinearMesh::getMeshDimension() const
5432 {
5433   if(!((const MEDCouplingCurveLinearMesh*)_clmesh))
5434     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::getMeshDimension : unable to get meshdimension because no mesh set !");
5435   return _clmesh->getMeshDimension();
5436 }
5437
5438 std::string MEDFileCurveLinearMesh::simpleRepr() const
5439 {
5440   return MEDFileStructuredMesh::simpleRepr();
5441 }
5442
5443 std::string MEDFileCurveLinearMesh::advancedRepr() const
5444 {
5445   return simpleRepr();
5446 }
5447
5448 bool MEDFileCurveLinearMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
5449 {
5450   if(!MEDFileStructuredMesh::isEqual(other,eps,what))
5451     return false;
5452   const MEDFileCurveLinearMesh *otherC=dynamic_cast<const MEDFileCurveLinearMesh *>(other);
5453   if(!otherC)
5454     {
5455       what="Mesh types differ ! This is curve linear and other is NOT !";
5456       return false;
5457     }
5458   clearNonDiscrAttributes();
5459   otherC->clearNonDiscrAttributes();
5460   const MEDCouplingCurveLinearMesh *coo1=_clmesh;
5461   const MEDCouplingCurveLinearMesh *coo2=otherC->_clmesh;
5462   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
5463     {
5464       what="Mismatch of curve linear meshes ! One is defined and not other !";
5465       return false;
5466     }
5467   if(coo1)
5468     {
5469       bool ret=coo1->isEqual(coo2,eps);
5470       if(!ret)
5471         {
5472           what="curve linear meshes differ !";
5473           return false;
5474         }
5475     }
5476   return true;
5477 }
5478
5479 void MEDFileCurveLinearMesh::clearNonDiscrAttributes() const
5480 {
5481   MEDFileStructuredMesh::clearNonDiscrAttributes();
5482   MEDFileUMeshSplitL1::ClearNonDiscrAttributes(_clmesh);//to it is not a bug umeshsplit have already the method implemented
5483 }
5484
5485 void MEDFileCurveLinearMesh::synchronizeTinyInfoOnLeaves() const
5486 {
5487   const MEDCouplingCurveLinearMesh *clmesh=_clmesh;
5488   if(!clmesh)
5489     return;
5490   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setName(_name);
5491   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setDescription(_desc_name);
5492   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setTime(_time,_iteration,_order);
5493   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setTimeUnit(_dt_unit);
5494 }
5495
5496 const MEDCouplingCurveLinearMesh *MEDFileCurveLinearMesh::getMesh() const
5497 {
5498   synchronizeTinyInfoOnLeaves();
5499   return _clmesh;
5500 }
5501
5502 void MEDFileCurveLinearMesh::setMesh(MEDCouplingCurveLinearMesh *m)
5503 {
5504   dealWithTinyInfo(m);
5505   if(m)
5506     m->incrRef();
5507   _clmesh=m;
5508 }
5509
5510 const MEDCouplingStructuredMesh *MEDFileCurveLinearMesh::getStructuredMesh() const
5511 {
5512   synchronizeTinyInfoOnLeaves();
5513   return _clmesh;
5514 }
5515
5516 MEDFileCurveLinearMesh::MEDFileCurveLinearMesh()
5517 {
5518 }
5519
5520 MEDFileCurveLinearMesh::MEDFileCurveLinearMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
5521 try
5522 {
5523     loadCLMeshFromFile(fid,mName,dt,it,mrs);
5524 }
5525 catch(INTERP_KERNEL::Exception& e)
5526 {
5527     throw e;
5528 }
5529
5530 void MEDFileCurveLinearMesh::writeLL(med_idt fid) const
5531 {
5532   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
5533   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
5534   INTERP_KERNEL::AutoPtr<char> dtunit=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE);
5535   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
5536   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
5537   MEDLoaderBase::safeStrCpy(_dt_unit.c_str(),MED_LNAME_SIZE,dtunit,_too_long_str);
5538   int spaceDim=_clmesh->getSpaceDimension();
5539   int meshDim=_clmesh->getMeshDimension();
5540   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
5541   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
5542   const DataArrayDouble *coords=_clmesh->getCoords();
5543   if(!coords)
5544     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::writeLL : no coordinates set !");
5545   for(int i=0;i<spaceDim;i++)
5546     {
5547       std::string info(_clmesh->getCoords()->getInfoOnComponent(i));
5548       std::string c,u;
5549       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
5550       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
5551       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
5552     }
5553   MEDmeshCr(fid,maa,spaceDim,meshDim,MED_STRUCTURED_MESH,desc,dtunit,MED_SORT_DTIT,MED_CARTESIAN,comp,unit);
5554   MEDmeshUniversalNameWr(fid,maa);
5555   MEDmeshGridTypeWr(fid,maa,MED_CURVILINEAR_GRID);
5556   std::vector<int> nodeGridSt=_clmesh->getNodeGridStructure();
5557   MEDmeshGridStructWr(fid,maa,_iteration,_order,_time,&nodeGridSt[0]);
5558
5559   MEDmeshNodeCoordinateWr(fid,maa,_iteration,_order,_time,MED_FULL_INTERLACE,coords->getNumberOfTuples(),coords->begin());
5560   //
5561   std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE));
5562   MEDFileStructuredMesh::writeStructuredLL(fid,meshName);
5563 }
5564
5565 void MEDFileCurveLinearMesh::loadCLMeshFromFile(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
5566 {
5567   ParaMEDMEM::MEDCouplingMeshType meshType;
5568   int dummy0,dummy1;
5569   std::string dtunit;
5570   int mid=MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dtunit);
5571   if(meshType!=CURVE_LINEAR)
5572     {
5573       std::ostringstream oss; oss << "Trying to load as curve linear an existing mesh with name '" << mName << "' that is NOT curve linear !";
5574       throw INTERP_KERNEL::Exception(oss.str().c_str());
5575     }
5576   MEDFileCLMeshL2 loaderl2;
5577   loaderl2.loadAll(fid,mid,mName,dt,it);
5578   MEDCouplingCurveLinearMesh *mesh=loaderl2.getMesh();
5579   mesh->incrRef();
5580   _clmesh=mesh;
5581   loadStrMeshFromFile(&loaderl2,fid,mName,dt,it,mrs);
5582 }
5583
5584 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New()
5585 {
5586   return new MEDFileMeshMultiTS;
5587 }
5588
5589 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(const std::string& fileName)
5590 {
5591   return new MEDFileMeshMultiTS(fileName);
5592 }
5593
5594 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(const std::string& fileName, const std::string& mName)
5595 {
5596   return new MEDFileMeshMultiTS(fileName,mName);
5597 }
5598
5599 MEDFileMeshMultiTS *MEDFileMeshMultiTS::deepCpy() const
5600 {
5601   MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> ret=MEDFileMeshMultiTS::New();
5602   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> > meshOneTs(_mesh_one_ts.size());
5603   std::size_t i=0;
5604   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++,i++)
5605     if((const MEDFileMesh *)*it)
5606       meshOneTs[i]=(*it)->deepCpy();
5607   ret->_mesh_one_ts=meshOneTs;
5608   return ret.retn();
5609 }
5610
5611 std::size_t MEDFileMeshMultiTS::getHeapMemorySizeWithoutChildren() const
5612 {
5613   return _mesh_one_ts.capacity()*sizeof(MEDCouplingAutoRefCountObjectPtr<MEDFileMesh>);
5614 }
5615
5616 std::vector<const BigMemoryObject *> MEDFileMeshMultiTS::getDirectChildrenWithNull() const
5617 {
5618   std::vector<const BigMemoryObject *> ret;
5619   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
5620     ret.push_back((const MEDFileMesh *)*it);
5621   return ret;
5622 }
5623
5624 std::string MEDFileMeshMultiTS::getName() const
5625 {
5626   if(_mesh_one_ts.empty())
5627     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::getName : no time steps set !");
5628   return _mesh_one_ts[0]->getName();
5629 }
5630
5631 void MEDFileMeshMultiTS::setName(const std::string& newMeshName)
5632 {
5633   std::string oldName(getName());
5634   std::vector< std::pair<std::string,std::string> > v(1);
5635   v[0].first=oldName; v[0].second=newMeshName;
5636   changeNames(v);
5637 }
5638
5639 bool MEDFileMeshMultiTS::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab)
5640 {
5641   bool ret=false;
5642   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
5643     {
5644       MEDFileMesh *cur(*it);
5645       if(cur)
5646         ret=cur->changeNames(modifTab) || ret;
5647     }
5648   return ret;
5649 }
5650
5651 MEDFileMesh *MEDFileMeshMultiTS::getOneTimeStep() const
5652 {
5653   if(_mesh_one_ts.empty())
5654     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::getOneTimeStep : empty time step set !");
5655   return const_cast<MEDFileMesh *>(static_cast<const MEDFileMesh *>(_mesh_one_ts[0]));
5656 }
5657
5658 void MEDFileMeshMultiTS::setOneTimeStep(MEDFileMesh *mesh1TimeStep)
5659 {
5660   if(!mesh1TimeStep)
5661     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::setOneTimeStep : input pointer should be different from 0 !");
5662   _mesh_one_ts.resize(1);
5663   mesh1TimeStep->incrRef();
5664   //MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> toto=mesh1TimeStep;
5665   _mesh_one_ts[0]=mesh1TimeStep;
5666 }
5667
5668 void MEDFileMeshMultiTS::write(med_idt fid) const
5669 {
5670   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
5671     {
5672       (*it)->copyOptionsFrom(*this);
5673       (*it)->write(fid);
5674     }
5675 }
5676
5677 void MEDFileMeshMultiTS::write(const std::string& fileName, int mode) const
5678 {
5679   med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode);
5680   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),medmod);
5681   std::ostringstream oss; oss << "MEDFileMesh : error on attempt to write in file : \"" << fileName << "\""; 
5682   MEDFileUtilities::CheckMEDCode(fid,fid,oss.str());
5683   write(fid);
5684 }
5685
5686 void MEDFileMeshMultiTS::loadFromFile(const std::string& fileName, const std::string& mName)
5687 {//for the moment to be improved
5688   _mesh_one_ts.resize(1);
5689   _mesh_one_ts[0]=MEDFileMesh::New(fileName,mName,-1,-1);
5690 }
5691
5692 MEDFileMeshMultiTS::MEDFileMeshMultiTS()
5693 {
5694 }
5695
5696 MEDFileMeshMultiTS::MEDFileMeshMultiTS(const std::string& fileName)
5697 try
5698 {
5699     std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
5700     if(ms.empty())
5701       {
5702         std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
5703         throw INTERP_KERNEL::Exception(oss.str().c_str());
5704       }
5705     MEDFileUtilities::CheckFileForRead(fileName);
5706     MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
5707     int dt,it;
5708     ParaMEDMEM::MEDCouplingMeshType meshType;
5709     std::string dummy2;
5710     MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dt,it,dummy2);
5711     loadFromFile(fileName,ms.front());
5712 }
5713 catch(INTERP_KERNEL::Exception& e)
5714 {
5715     throw e;
5716 }
5717
5718 MEDFileMeshMultiTS::MEDFileMeshMultiTS(const std::string& fileName, const std::string& mName)
5719 try
5720 {
5721     loadFromFile(fileName,mName);
5722 }
5723 catch(INTERP_KERNEL::Exception& e)
5724 {
5725     throw e;
5726 }
5727
5728 MEDFileMeshes *MEDFileMeshes::New()
5729 {
5730   return new MEDFileMeshes;
5731 }
5732
5733 MEDFileMeshes *MEDFileMeshes::New(const std::string& fileName)
5734 {
5735   return new MEDFileMeshes(fileName);
5736 }
5737
5738 void MEDFileMeshes::write(med_idt fid) const
5739 {
5740   checkCoherency();
5741   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++)
5742     {
5743       (*it)->copyOptionsFrom(*this);
5744       (*it)->write(fid);
5745     }
5746 }
5747
5748 void MEDFileMeshes::write(const std::string& fileName, int mode) const
5749 {
5750   med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode);
5751   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),medmod);
5752   std::ostringstream oss; oss << "MEDFileMesh : error on attempt to write in file : \"" << fileName << "\""; 
5753   MEDFileUtilities::CheckMEDCode(fid,fid,oss.str());
5754   checkCoherency();
5755   write(fid);
5756 }
5757
5758 int MEDFileMeshes::getNumberOfMeshes() const
5759 {
5760   return _meshes.size();
5761 }
5762
5763 MEDFileMeshesIterator *MEDFileMeshes::iterator()
5764 {
5765   return new MEDFileMeshesIterator(this);
5766 }
5767
5768 /** Return a borrowed reference (caller is not responsible) */
5769 MEDFileMesh *MEDFileMeshes::getMeshAtPos(int i) const
5770 {
5771   if(i<0 || i>=(int)_meshes.size())
5772     {
5773       std::ostringstream oss; oss << "MEDFileMeshes::getMeshAtPos : invalid mesh id given in parameter ! Should be in [0;" << _meshes.size() << ") !";
5774       throw INTERP_KERNEL::Exception(oss.str().c_str());
5775     }
5776   return _meshes[i]->getOneTimeStep();
5777 }
5778
5779 /** Return a borrowed reference (caller is not responsible) */
5780 MEDFileMesh *MEDFileMeshes::getMeshWithName(const std::string& mname) const
5781 {
5782   std::vector<std::string> ms=getMeshesNames();
5783   std::vector<std::string>::iterator it=std::find(ms.begin(),ms.end(),mname);
5784   if(it==ms.end())
5785     {
5786       std::ostringstream oss; oss << "MEDFileMeshes::getMeshWithName : Mesh  \"" << mname << "\" does not exist in this ! Existing are : ";
5787       std::copy(ms.begin(),ms.end(),std::ostream_iterator<std::string>(oss," "));
5788       throw INTERP_KERNEL::Exception(oss.str().c_str());
5789     }
5790   return getMeshAtPos((int)std::distance(ms.begin(),it));
5791 }
5792
5793 std::vector<std::string> MEDFileMeshes::getMeshesNames() const
5794 {
5795   std::vector<std::string> ret(_meshes.size());
5796   int i=0;
5797   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
5798     {
5799       const MEDFileMeshMultiTS *f=(*it);
5800       if(f)
5801         {
5802           ret[i]=f->getName();
5803         }
5804       else
5805         {
5806           std::ostringstream oss; oss << "MEDFileMeshes::getMeshesNames : At rank #" << i << " mesh is not defined !";
5807           throw INTERP_KERNEL::Exception(oss.str().c_str());
5808         }
5809     }
5810   return ret;
5811 }
5812
5813 bool MEDFileMeshes::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab)
5814 {
5815   bool ret=false;
5816   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::iterator it=_meshes.begin();it!=_meshes.end();it++)
5817     {
5818       MEDFileMeshMultiTS *cur(*it);
5819       if(cur)
5820         ret=cur->changeNames(modifTab) || ret;
5821     }
5822   return ret;
5823 }
5824
5825 void MEDFileMeshes::resize(int newSize)
5826 {
5827   _meshes.resize(newSize);
5828 }
5829
5830 void MEDFileMeshes::pushMesh(MEDFileMesh *mesh)
5831 {
5832   if(!mesh)
5833     throw INTERP_KERNEL::Exception("MEDFileMeshes::pushMesh : invalid input pointer ! should be different from 0 !");
5834   MEDFileMeshMultiTS *elt=MEDFileMeshMultiTS::New();
5835   elt->setOneTimeStep(mesh);
5836   _meshes.push_back(elt);
5837 }
5838
5839 void MEDFileMeshes::setMeshAtPos(int i, MEDFileMesh *mesh)
5840 {
5841   if(!mesh)
5842     throw INTERP_KERNEL::Exception("MEDFileMeshes::setMeshAtPos : invalid input pointer ! should be different from 0 !");
5843   if(i>=(int)_meshes.size())
5844     _meshes.resize(i+1);
5845   MEDFileMeshMultiTS *elt=MEDFileMeshMultiTS::New();
5846   elt->setOneTimeStep(mesh);
5847   _meshes[i]=elt;
5848 }
5849
5850 void MEDFileMeshes::destroyMeshAtPos(int i)
5851 {
5852   if(i<0 || i>=(int)_meshes.size())
5853     {
5854       std::ostringstream oss; oss << "MEDFileMeshes::destroyMeshAtPos : Invalid given id in input (" << i << ") should be in [0," << _meshes.size() << ") !";
5855       throw INTERP_KERNEL::Exception(oss.str().c_str());
5856     }
5857   _meshes.erase(_meshes.begin()+i);
5858 }
5859
5860 void MEDFileMeshes::loadFromFile(const std::string& fileName)
5861 {
5862   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
5863   int i=0;
5864   _meshes.resize(ms.size());
5865   for(std::vector<std::string>::const_iterator it=ms.begin();it!=ms.end();it++,i++)
5866     _meshes[i]=MEDFileMeshMultiTS::New(fileName,(*it));
5867 }
5868
5869 MEDFileMeshes::MEDFileMeshes()
5870 {
5871 }
5872
5873 MEDFileMeshes::MEDFileMeshes(const std::string& fileName)
5874 try
5875 {
5876     loadFromFile(fileName);
5877 }
5878 catch(INTERP_KERNEL::Exception& /*e*/)
5879 {
5880 }
5881
5882 MEDFileMeshes *MEDFileMeshes::deepCpy() const
5883 {
5884   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> > meshes(_meshes.size());
5885   std::size_t i=0;
5886   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
5887     if((const MEDFileMeshMultiTS *)*it)
5888       meshes[i]=(*it)->deepCpy();
5889   MEDCouplingAutoRefCountObjectPtr<MEDFileMeshes> ret=MEDFileMeshes::New();
5890   ret->_meshes=meshes;
5891   return ret.retn();
5892 }
5893
5894 std::size_t MEDFileMeshes::getHeapMemorySizeWithoutChildren() const
5895 {
5896   return _meshes.capacity()*(sizeof(MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS>));
5897 }
5898
5899 std::vector<const BigMemoryObject *> MEDFileMeshes::getDirectChildrenWithNull() const
5900 {
5901   std::vector<const BigMemoryObject *> ret;
5902   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++)
5903     ret.push_back((const MEDFileMeshMultiTS *)*it);
5904   return ret;
5905 }
5906
5907 std::string MEDFileMeshes::simpleRepr() const
5908 {
5909   std::ostringstream oss;
5910   oss << "(*****************)\n(* MEDFileMeshes *)\n(*****************)\n\n";
5911   simpleReprWithoutHeader(oss);
5912   return oss.str();
5913 }
5914
5915 void MEDFileMeshes::simpleReprWithoutHeader(std::ostream& oss) const
5916 {
5917   int nbOfMeshes=getNumberOfMeshes();
5918   oss << "There are " << nbOfMeshes << " meshes with the following names : \n";
5919   std::vector<std::string> mns=getMeshesNames();
5920   for(int i=0;i<nbOfMeshes;i++)
5921     oss << "  - #" << i << " \"" << mns[i] << "\"\n";
5922 }
5923
5924 void MEDFileMeshes::checkCoherency() const
5925 {
5926   static const char MSG[]="MEDFileMeshes::checkCoherency : mesh at rank ";
5927   int i=0;
5928   std::set<std::string> s;
5929   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
5930     {
5931       const MEDFileMeshMultiTS *elt=(*it);
5932       if(!elt)
5933         {
5934           std::ostringstream oss; oss << MSG << i << "/" << _meshes.size() << " is empty !";
5935           throw INTERP_KERNEL::Exception(oss.str().c_str());
5936         }
5937       std::size_t sz=s.size();
5938       s.insert(std::string((*it)->getName()));
5939       if(s.size()==sz)
5940         {
5941           std::ostringstream oss; oss << MSG << i << " has a name (\"" << (*it)->getName() << "\") already used by an another mesh in list !";
5942           throw INTERP_KERNEL::Exception(oss.str().c_str());
5943         }
5944     }
5945 }
5946
5947 MEDFileMeshesIterator::MEDFileMeshesIterator(MEDFileMeshes *ms):_ms(ms),_iter_id(0),_nb_iter(0)
5948 {
5949   if(ms)
5950     {
5951       ms->incrRef();
5952       _nb_iter=ms->getNumberOfMeshes();
5953     }
5954 }
5955
5956 MEDFileMeshesIterator::~MEDFileMeshesIterator()
5957 {
5958 }
5959
5960 MEDFileMesh *MEDFileMeshesIterator::nextt()
5961 {
5962   if(_iter_id<_nb_iter)
5963     {
5964       MEDFileMeshes *ms(_ms);
5965       if(ms)
5966         return ms->getMeshAtPos(_iter_id++);
5967       else
5968         return 0;
5969     }
5970   else
5971     return 0;
5972 }