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