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