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