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