Salome HOME
Modification of the getHeapMemorySize computation.
[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<RefCountObject *> MEDFileMesh::getDirectChildren() const
58 {
59   return std::vector<RefCountObject *>();
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) throw(INTERP_KERNEL::Exception)
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) throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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) throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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) throw(INTERP_KERNEL::Exception)
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) throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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) throw(INTERP_KERNEL::Exception)
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() throw(INTERP_KERNEL::Exception)
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() throw(INTERP_KERNEL::Exception)
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) throw(INTERP_KERNEL::Exception)
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) throw(INTERP_KERNEL::Exception)
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() throw(INTERP_KERNEL::Exception)
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() throw(INTERP_KERNEL::Exception)
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) throw(INTERP_KERNEL::Exception)
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) throw(INTERP_KERNEL::Exception)
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) throw(INTERP_KERNEL::Exception)
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) throw(INTERP_KERNEL::Exception)
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) throw(INTERP_KERNEL::Exception)
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) throw(INTERP_KERNEL::Exception)
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) throw(INTERP_KERNEL::Exception)
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) throw(INTERP_KERNEL::Exception)
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) throw(INTERP_KERNEL::Exception)
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) throw(INTERP_KERNEL::Exception)
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) throw(INTERP_KERNEL::Exception)
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) throw(INTERP_KERNEL::Exception)
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) throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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() throw(INTERP_KERNEL::Exception)
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() throw(INTERP_KERNEL::Exception)
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() throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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) throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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) throw(INTERP_KERNEL::Exception)
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) throw(INTERP_KERNEL::Exception)
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) throw(INTERP_KERNEL::Exception)
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) throw(INTERP_KERNEL::Exception)
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) throw(INTERP_KERNEL::Exception)
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<RefCountObject *> MEDFileUMesh::getDirectChildren() const
1936 {
1937   std::vector<RefCountObject *> ret(MEDFileMesh::getDirectChildren());
1938   if((const DataArrayDouble*)_coords)
1939     ret.push_back(const_cast<DataArrayDouble *>((const DataArrayDouble*)_coords));
1940   if((const DataArrayInt *)_fam_coords)
1941     ret.push_back(const_cast<DataArrayInt *>((const DataArrayInt *)_fam_coords));
1942   if((const DataArrayInt *)_num_coords)
1943     ret.push_back(const_cast<DataArrayInt *>((const DataArrayInt *)_num_coords));
1944   if((const DataArrayInt *)_rev_num_coords)
1945     ret.push_back(const_cast<DataArrayInt *>((const DataArrayInt *)_rev_num_coords));
1946   if((const DataArrayAsciiChar *)_name_coords)
1947     ret.push_back(const_cast<DataArrayAsciiChar *>((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_cast<MEDFileUMeshSplitL1 *>((const MEDFileUMeshSplitL1*) *it));
1951   return ret;
1952 }
1953
1954 MEDFileMesh *MEDFileUMesh::shallowCpy() const throw(INTERP_KERNEL::Exception)
1955 {
1956   MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret=new MEDFileUMesh(*this);
1957   return ret.retn();
1958 }
1959
1960 MEDFileMesh *MEDFileUMesh::createNewEmpty() const throw(INTERP_KERNEL::Exception)
1961 {
1962   return new MEDFileUMesh;
1963 }
1964
1965 MEDFileMesh *MEDFileUMesh::deepCpy() const throw(INTERP_KERNEL::Exception)
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) throw(INTERP_KERNEL::Exception)
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) throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
2639 {
2640   std::size_t sz(st.getNumberOfItems());
2641   int mdim(getMeshDimension());
2642   for(std::size_t i=0;i<sz;i++)
2643     {
2644       INTERP_KERNEL::NormalizedCellType curGt(st[i].getGeo());
2645       const MEDCoupling1GTUMesh *m(getDirectUndergroundSingleGeoTypeMesh(curGt));
2646       if(st[i].getPflName().empty())
2647         m->computeNodeIdsAlg(nodesFetched);
2648       else
2649         {
2650           const DataArrayInt *arr(globs->getProfile(st[i].getPflName().c_str()));
2651           MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> m2(dynamic_cast<MEDCoupling1GTUMesh *>(m->buildPartOfMySelf(arr->begin(),arr->end(),true)));
2652           m2->computeNodeIdsAlg(nodesFetched);
2653         }
2654     }
2655 }
2656
2657 /*!
2658  * Returns the optional numbers of mesh entities of a given dimension transformed using
2659  * DataArrayInt::invertArrayN2O2O2N().
2660  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
2661  *  \return const DataArrayInt * - the array of the entity numbers transformed using
2662  *          DataArrayInt::invertArrayN2O2O2N().
2663  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2664  */
2665 const DataArrayInt *MEDFileUMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
2666 {
2667   if(meshDimRelToMaxExt==1)
2668     {
2669       if(!((const DataArrayInt *)_num_coords))
2670         throw INTERP_KERNEL::Exception("MEDFileUMesh::getRevNumberFieldAtLevel : no coordinates renum specified !");
2671       return _rev_num_coords;
2672     }
2673   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2674   return l1->getRevNumberField();
2675 }
2676
2677 /*!
2678  * Returns a pointer to the node coordinates array of \a this mesh \b without
2679  * incrementing its reference counter, thus there is no need to decrRef() it by the caller.
2680  */
2681 DataArrayDouble *MEDFileUMesh::getCoords() const
2682 {
2683   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp(_coords);
2684   if((DataArrayDouble *)tmp)
2685     {
2686       return tmp;
2687     }
2688   return 0;
2689 }
2690
2691 /*!
2692  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in a given
2693  * group of \a this mesh. Only mesh entities of a given dimension are included in the
2694  * new mesh.
2695  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
2696  *  \param [in] grp - the name of the group whose mesh entities are included in the
2697  *          new mesh.
2698  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
2699  *          according to the optional numbers of entities, if available.
2700  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
2701  *          delete this mesh using decrRef() as it is no more needed.
2702  *  \throw If the name of a nonexistent group is specified.
2703  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2704  */
2705 MEDCouplingUMesh *MEDFileUMesh::getGroup(int meshDimRelToMaxExt, const char *grp, bool renum) const throw(INTERP_KERNEL::Exception)
2706 {
2707   synchronizeTinyInfoOnLeaves();
2708   std::vector<std::string> tmp(1);
2709   tmp[0]=grp;
2710   return getGroups(meshDimRelToMaxExt,tmp,renum);
2711 }
2712
2713 /*!
2714  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in given
2715  * groups of \a this mesh. Only mesh entities of a given dimension are included in the
2716  * new mesh.
2717  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
2718  *  \param [in] grps - a sequence of group names whose mesh entities are included in the
2719  *          new mesh.
2720  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
2721  *          according to the optional numbers of entities, if available.
2722  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
2723  *          delete this mesh using decrRef() as it is no more needed.
2724  *  \throw If a name of a nonexistent group is present in \a grps.
2725  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2726  */
2727 MEDCouplingUMesh *MEDFileUMesh::getGroups(int meshDimRelToMaxExt, const std::vector<std::string>& grps, bool renum) const throw(INTERP_KERNEL::Exception)
2728 {
2729   synchronizeTinyInfoOnLeaves();
2730   std::vector<std::string> fams2=getFamiliesOnGroups(grps);
2731   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> zeRet=getFamilies(meshDimRelToMaxExt,fams2,renum);
2732   if(grps.size()==1 && ((MEDCouplingUMesh *)zeRet))
2733     zeRet->setName(grps[0].c_str());
2734   return zeRet.retn();
2735 }
2736
2737 /*!
2738  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in a given
2739  * family of \a this mesh. Only mesh entities of a given dimension are included in the
2740  * new mesh.
2741  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
2742  *  \param [in] fam - the name of the family whose mesh entities are included in the
2743  *          new mesh.
2744  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
2745  *          according to the optional numbers of entities, if available.
2746  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
2747  *          delete this mesh using decrRef() as it is no more needed.
2748  *  \throw If a name of a nonexistent family is present in \a grps.
2749  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2750  */
2751 MEDCouplingUMesh *MEDFileUMesh::getFamily(int meshDimRelToMaxExt, const char *fam, bool renum) const throw(INTERP_KERNEL::Exception)
2752 {
2753   synchronizeTinyInfoOnLeaves();
2754   std::vector<std::string> tmp(1);
2755   tmp[0]=fam;
2756   return getFamilies(meshDimRelToMaxExt,tmp,renum);
2757 }
2758
2759 /*!
2760  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in given
2761  * families of \a this mesh. Only mesh entities of a given dimension are included in the
2762  * new mesh.
2763  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
2764  *  \param [in] fams - a sequence of family names whose mesh entities are included in the
2765  *          new mesh.
2766  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
2767  *          according to the optional numbers of entities, if available.
2768  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
2769  *          delete this mesh using decrRef() as it is no more needed.
2770  *  \throw If a name of a nonexistent family is present in \a fams.
2771  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2772  */
2773 MEDCouplingUMesh *MEDFileUMesh::getFamilies(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const throw(INTERP_KERNEL::Exception)
2774 {
2775   synchronizeTinyInfoOnLeaves();
2776   if(meshDimRelToMaxExt==1)
2777     {
2778       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr=getFamiliesArr(1,fams,renum);
2779       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
2780       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> c=_coords->selectByTupleId(arr->getConstPointer(),arr->getConstPointer()+arr->getNbOfElems());
2781       ret->setCoords(c);
2782       return ret.retn();
2783     }
2784   std::vector<int> famIds=getFamiliesIds(fams);
2785   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2786   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> zeRet;
2787   if(!famIds.empty())
2788     zeRet=l1->getFamilyPart(&famIds[0],&famIds[0]+famIds.size(),renum);
2789   else
2790     zeRet=l1->getFamilyPart(0,0,renum);
2791   if(fams.size()==1 && ((MEDCouplingUMesh *)zeRet))
2792     zeRet->setName(fams[0].c_str());
2793   return zeRet.retn();
2794 }
2795
2796 /*!
2797  * Returns ids of mesh entities contained in given families of a given dimension.
2798  *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
2799  *          are required.
2800  *  \param [in] fams - the names of the families of interest.
2801  *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
2802  *          returned instead of ids.
2803  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
2804  *          numbers, if available and required, of mesh entities of the families. The caller
2805  *          is to delete this array using decrRef() as it is no more needed. 
2806  *  \throw If the family field is missing for \a meshDimRelToMaxExt.
2807  */
2808 DataArrayInt *MEDFileUMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const throw(INTERP_KERNEL::Exception)
2809 {
2810   std::vector<int> famIds=getFamiliesIds(fams);
2811   if(meshDimRelToMaxExt==1)
2812     {
2813       if((const DataArrayInt *)_fam_coords)
2814         {
2815           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
2816           if(!famIds.empty())
2817             da=_fam_coords->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
2818           else
2819             da=_fam_coords->getIdsEqualList(0,0);
2820           if(renum)
2821             return MEDFileUMeshSplitL1::Renumber(_num_coords,da);
2822           else
2823             return da.retn();
2824         }
2825       else
2826         throw INTERP_KERNEL::Exception("MEDFileUMesh::getFamiliesArr : no family array specified on nodes !");
2827     }
2828   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2829   if(!famIds.empty())
2830     return l1->getFamilyPartArr(&famIds[0],&famIds[0]+famIds.size(),renum);
2831   else
2832     return l1->getFamilyPartArr(0,0,renum);
2833 }
2834
2835 /*!
2836  * Returns a MEDCouplingUMesh of a given relative dimension.
2837  * \warning If \a meshDimRelToMaxExt == 1 (which means nodes), the returned mesh **is not
2838  * valid**. This is a feature, because MEDLoader does not create cells that do not exist! 
2839  * To build a valid MEDCouplingUMesh from the returned one in this case,
2840  * call MEDCouplingUMesh::Build0DMeshFromCoords().
2841  *  \param [in] meshDimRelToMax - the relative dimension of interest.
2842  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
2843  *          optional numbers of mesh entities.
2844  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
2845  *          delete using decrRef() as it is no more needed. 
2846  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2847  * \sa getGenMeshAtLevel()
2848  */
2849 MEDCouplingUMesh *MEDFileUMesh::getMeshAtLevel(int meshDimRelToMaxExt, bool renum) const throw(INTERP_KERNEL::Exception)
2850 {
2851   synchronizeTinyInfoOnLeaves();
2852   if(meshDimRelToMaxExt==1)
2853     {
2854       if(!renum)
2855         {
2856           MEDCouplingUMesh *umesh=MEDCouplingUMesh::New();
2857           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> cc=_coords->deepCpy();
2858           umesh->setCoords(cc);
2859           MEDFileUMeshSplitL1::ClearNonDiscrAttributes(umesh);
2860           umesh->setName(getName().c_str());
2861           return umesh;
2862         }
2863     }
2864   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2865   return l1->getWholeMesh(renum);
2866 }
2867
2868 /*!
2869  * Returns a MEDCouplingUMesh of a given relative dimension.
2870  * \warning If \a meshDimRelToMaxExt == 1 (which means nodes), the returned mesh **is not
2871  * valid**. This is a feature, because MEDLoader does not create cells that do not exist! 
2872  * To build a valid MEDCouplingUMesh from the returned one in this case,
2873  * call MEDCouplingUMesh::Build0DMeshFromCoords().
2874  *  \param [in] meshDimRelToMax - the relative dimension of interest.
2875  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
2876  *          optional numbers of mesh entities.
2877  *  \return MEDCouplingMesh * - a pointer to MEDCouplingUMesh that the caller is to
2878  *          delete using decrRef() as it is no more needed. 
2879  *  \throw If there are no mesh entities of \a meshDimRelToMax dimension in \a this mesh.
2880  * \sa getMeshAtLevel()
2881  */
2882 MEDCouplingMesh *MEDFileUMesh::getGenMeshAtLevel(int meshDimRelToMax, bool renum) const throw(INTERP_KERNEL::Exception)
2883 {
2884   return getMeshAtLevel(meshDimRelToMax,renum);
2885 }
2886
2887 std::vector<int> MEDFileUMesh::getDistributionOfTypes(int meshDimRelToMax) const throw(INTERP_KERNEL::Exception)
2888 {
2889   const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMax));
2890   return l1->getDistributionOfTypes();
2891 }
2892
2893 /*!
2894  * Returns a MEDCouplingUMesh of a relative dimension == 0.
2895  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
2896  *          optional numbers of mesh entities.
2897  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
2898  *          delete using decrRef() as it is no more needed. 
2899  *  \throw If there are no mesh entities of the relative dimension == 0 in \a this mesh.
2900  */
2901 MEDCouplingUMesh *MEDFileUMesh::getLevel0Mesh(bool renum) const throw(INTERP_KERNEL::Exception)
2902 {
2903   return getMeshAtLevel(0,renum);
2904 }
2905
2906 /*!
2907  * Returns a MEDCouplingUMesh of a relative dimension == -1.
2908  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
2909  *          optional numbers of mesh entities.
2910  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
2911  *          delete using decrRef() as it is no more needed. 
2912  *  \throw If there are no mesh entities of the relative dimension == -1 in \a this mesh.
2913  */
2914 MEDCouplingUMesh *MEDFileUMesh::getLevelM1Mesh(bool renum) const throw(INTERP_KERNEL::Exception)
2915 {
2916   return getMeshAtLevel(-1,renum);
2917 }
2918
2919 /*!
2920  * Returns a MEDCouplingUMesh of a relative dimension == -2.
2921  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
2922  *          optional numbers of mesh entities.
2923  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
2924  *          delete using decrRef() as it is no more needed. 
2925  *  \throw If there are no mesh entities of the relative dimension == -2 in \a this mesh.
2926  */
2927 MEDCouplingUMesh *MEDFileUMesh::getLevelM2Mesh(bool renum) const throw(INTERP_KERNEL::Exception)
2928 {
2929   return getMeshAtLevel(-2,renum);
2930 }
2931
2932 /*!
2933  * Returns a MEDCouplingUMesh of a relative dimension == -3.
2934  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
2935  *          optional numbers of mesh entities.
2936  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
2937  *          delete using decrRef() as it is no more needed. 
2938  *  \throw If there are no mesh entities of the relative dimension == -3 in \a this mesh.
2939  */
2940 MEDCouplingUMesh *MEDFileUMesh::getLevelM3Mesh(bool renum) const throw(INTERP_KERNEL::Exception)
2941 {
2942   return getMeshAtLevel(-3,renum);
2943 }
2944
2945 /*!
2946  * This method returns a vector of mesh parts containing each exactly one geometric type.
2947  * This method will never launch an automatic computation of split by type (an INTERP_KERNEL::Exception will be then thrown).
2948  * This method is only for memory aware users.
2949  * The returned pointers are **NOT** new object pointer. No need to mange them.
2950  */
2951 std::vector<MEDCoupling1GTUMesh *> MEDFileUMesh::getDirectUndergroundSingleGeoTypeMeshes(int meshDimRelToMax) const throw(INTERP_KERNEL::Exception)
2952 {
2953   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(meshDimRelToMax));
2954   return sp->getDirectUndergroundSingleGeoTypeMeshes();
2955 }
2956
2957 /*!
2958  * This method returns the part of \a this having the geometric type \a gt.
2959  * If such part is not existing an exception will be thrown.
2960  * The returned pointer is **NOT** new object pointer. No need to mange it.
2961  */
2962 MEDCoupling1GTUMesh *MEDFileUMesh::getDirectUndergroundSingleGeoTypeMesh(INTERP_KERNEL::NormalizedCellType gt) const throw(INTERP_KERNEL::Exception)
2963 {
2964   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
2965   int lev=(int)cm.getDimension()-getMeshDimension();
2966   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(lev));
2967   return sp->getDirectUndergroundSingleGeoTypeMesh(gt);
2968 }
2969
2970 const MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
2971 {
2972   if(meshDimRelToMaxExt==1)
2973     throw INTERP_KERNEL::Exception("Dimension request is invalid : asking for node level (1) !");
2974   if(meshDimRelToMaxExt>1)
2975     throw INTERP_KERNEL::Exception("Dimension request is invalid (>1) !");
2976   int tracucedRk=-meshDimRelToMaxExt;
2977   if(tracucedRk>=(int)_ms.size())
2978     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
2979   if((const MEDFileUMeshSplitL1 *)_ms[tracucedRk]==0)
2980     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
2981   return _ms[tracucedRk];
2982 }
2983
2984 MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt) throw(INTERP_KERNEL::Exception)
2985 {
2986    if(meshDimRelToMaxExt==1)
2987     throw INTERP_KERNEL::Exception("Dimension request is invalid : asking for node level (1) !");
2988   if(meshDimRelToMaxExt>1)
2989     throw INTERP_KERNEL::Exception("Dimension request is invalid (>1) !");
2990   int tracucedRk=-meshDimRelToMaxExt;
2991   if(tracucedRk>=(int)_ms.size())
2992     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
2993   if((const MEDFileUMeshSplitL1 *)_ms[tracucedRk]==0)
2994     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
2995   return _ms[tracucedRk];
2996 }
2997
2998 void MEDFileUMesh::checkMeshDimCoherency(int meshDim, int meshDimRelToMax) const throw(INTERP_KERNEL::Exception)
2999 {
3000   if(-meshDimRelToMax>=(int)_ms.size())
3001     throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMeshDimCoherency : The meshdim of mesh is not managed by 'this' !");
3002   int i=0;
3003   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,i++)
3004     {
3005       if(((const MEDFileUMeshSplitL1*) (*it))!=0)
3006         {
3007           int ref=(*it)->getMeshDimension();
3008           if(ref+i!=meshDim-meshDimRelToMax)
3009             throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMeshDimCoherency : no coherency between levels !");
3010         }
3011     }
3012 }
3013
3014 /*!
3015  * Sets the node coordinates array of \a this mesh.
3016  *  \param [in] coords - the new node coordinates array.
3017  *  \throw If \a coords == \c NULL.
3018  */
3019 void MEDFileUMesh::setCoords(DataArrayDouble *coords) throw(INTERP_KERNEL::Exception)
3020 {
3021   if(!coords)
3022     throw INTERP_KERNEL::Exception("MEDFileUMesh::setCoords : null pointer in input !");
3023   coords->checkAllocated();
3024   int nbOfTuples=coords->getNumberOfTuples();
3025   _coords=coords;
3026   coords->incrRef();
3027   _fam_coords=DataArrayInt::New();
3028   _fam_coords->alloc(nbOfTuples,1);
3029   _fam_coords->fillWithZero();
3030   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
3031     if((MEDFileUMeshSplitL1 *)(*it))
3032       (*it)->setCoords(coords);
3033 }
3034
3035 /*!
3036  * Removes all groups of a given dimension in \a this mesh.
3037  *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
3038  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3039  */
3040 void MEDFileUMesh::eraseGroupsAtLevel(int meshDimRelToMaxExt) throw(INTERP_KERNEL::Exception)
3041 {
3042   if(meshDimRelToMaxExt==1)
3043     {
3044       if((DataArrayInt *)_fam_coords)
3045         _fam_coords->fillWithZero();
3046       return ;
3047     }
3048   MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3049   l1->eraseFamilyField();
3050   optimizeFamilies();
3051 }
3052
3053 /*!
3054  * Removes all families with ids not present in the family fields of \a this mesh.
3055  */
3056 void MEDFileUMesh::optimizeFamilies() throw(INTERP_KERNEL::Exception)
3057 {
3058   std::vector<int> levs=getNonEmptyLevelsExt();
3059   std::set<int> allFamsIds;
3060   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
3061     {
3062       const DataArrayInt *ffield=getFamilyFieldAtLevel(*it);
3063       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=ffield->getDifferentValues();
3064       std::set<int> res;
3065       std::set_union(ids->begin(),ids->end(),allFamsIds.begin(),allFamsIds.end(),std::inserter(res,res.begin()));
3066       allFamsIds=res;
3067     }
3068   std::set<std::string> famNamesToKill;
3069   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
3070     {
3071       if(allFamsIds.find((*it).second)!=allFamsIds.end())
3072         famNamesToKill.insert((*it).first);
3073     }
3074   for(std::set<std::string>::const_iterator it=famNamesToKill.begin();it!=famNamesToKill.end();it++)
3075     _families.erase(*it);
3076   std::vector<std::string> grpNamesToKill;
3077   for(std::map<std::string, std::vector<std::string> >::iterator it=_groups.begin();it!=_groups.end();it++)
3078     {
3079       std::vector<std::string> tmp;
3080       for(std::vector<std::string>::const_iterator it2=(*it).second.begin();it2!=(*it).second.end();it2++)
3081         {
3082           if(famNamesToKill.find(*it2)==famNamesToKill.end())
3083             tmp.push_back(*it2);
3084         }
3085       if(!tmp.empty())
3086         (*it).second=tmp;
3087       else
3088         tmp.push_back((*it).first);
3089     }
3090   for(std::vector<std::string>::const_iterator it=grpNamesToKill.begin();it!=grpNamesToKill.end();it++)
3091     _groups.erase(*it);
3092 }
3093
3094 void MEDFileUMesh::duplicateNodesOnM1Group(const char *grpNameM1, DataArrayInt *&nodesDuplicated, DataArrayInt *&cellsModified, DataArrayInt *&cellsNotModified) throw(INTERP_KERNEL::Exception)
3095 {
3096   std::vector<int> levs=getNonEmptyLevels();
3097   if(std::find(levs.begin(),levs.end(),0)==levs.end() || std::find(levs.begin(),levs.end(),-1)==levs.end())
3098     throw INTERP_KERNEL::Exception("MEDFileUMesh::duplicateNodesOnM1Group : This method works only for mesh definied on level 0 and -1 !");
3099   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0=getMeshAtLevel(0);
3100   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1=getMeshAtLevel(-1);
3101   int nbNodes=m0->getNumberOfNodes();
3102   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m11=getGroup(-1,grpNameM1);
3103   DataArrayInt *tmp00=0,*tmp11=0,*tmp22=0;
3104   m0->findNodesToDuplicate(*m11,tmp00,tmp11,tmp22);
3105   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodeIdsToDuplicate(tmp00);
3106   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0(tmp11);
3107   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1(tmp22);
3108   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp0=static_cast<MEDCouplingUMesh *>(m0->buildPartOfMySelf(cellsToModifyConn0->begin(),cellsToModifyConn0->end(),true));
3109   // node renumbering of cells in m1 impacted by duplication of node but not in group 'grpNameM1' on level -1
3110   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descTmp0=DataArrayInt::New(),descITmp0=DataArrayInt::New(),revDescTmp0=DataArrayInt::New(),revDescITmp0=DataArrayInt::New();
3111   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp0Desc=tmp0->buildDescendingConnectivity(descTmp0,descITmp0,revDescTmp0,revDescITmp0);
3112   descTmp0=0; descITmp0=0; revDescTmp0=0; revDescITmp0=0;
3113   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsInM1ToRenumW2=tmp0Desc->getCellIdsLyingOnNodes(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),false);
3114   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cellsInM1ToRenumW3=static_cast<MEDCouplingUMesh *>(tmp0Desc->buildPartOfMySelf(cellsInM1ToRenumW2->begin(),cellsInM1ToRenumW2->end(),true));
3115   DataArrayInt *cellsInM1ToRenumW4Tmp=0;
3116   m1->areCellsIncludedIn(cellsInM1ToRenumW3,2,cellsInM1ToRenumW4Tmp);
3117   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsInM1ToRenumW4(cellsInM1ToRenumW4Tmp);
3118   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsInM1ToRenumW5=cellsInM1ToRenumW4->getIdsInRange(0,m1->getNumberOfCells());
3119   cellsInM1ToRenumW5->transformWithIndArr(cellsInM1ToRenumW4->begin(),cellsInM1ToRenumW4->end());
3120   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> grpIds=getGroupArr(-1,grpNameM1);
3121   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsInM1ToRenum=cellsInM1ToRenumW5->buildSubstraction(grpIds);
3122   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Part=static_cast<MEDCouplingUMesh *>(m1->buildPartOfMySelf(cellsInM1ToRenum->begin(),cellsInM1ToRenum->end(),true));
3123   m1Part->duplicateNodesInConn(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),nbNodes);
3124   m1->setPartOfMySelf(cellsInM1ToRenum->begin(),cellsInM1ToRenum->end(),*m1Part);
3125   // end of node renumbering of cells in m1 impacted by duplication of node but not in group of level -1 'grpNameM1'
3126   tmp0->duplicateNodes(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end());
3127   m0->setCoords(tmp0->getCoords());
3128   m0->setPartOfMySelf(cellsToModifyConn0->begin(),cellsToModifyConn0->end(),*tmp0);
3129   m1->setCoords(m0->getCoords());
3130   _coords=m0->getCoords(); _coords->incrRef();
3131   // duplication of cells in group 'grpNameM1' on level -1
3132   m11->duplicateNodesInConn(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),nbNodes); m11->setCoords(m0->getCoords());
3133   std::vector<const MEDCouplingUMesh *> v(2); v[0]=m1; v[1]=m11;
3134   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> newm1=MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(v,tmp00,tmp11);
3135   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> szOfCellGrpOfSameType(tmp00);
3136   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idInMsOfCellGrpOfSameType(tmp11);
3137   //
3138   newm1->setName(getName().c_str());
3139   const DataArrayInt *fam=getFamilyFieldAtLevel(-1);
3140   if(!fam)
3141     throw INTERP_KERNEL::Exception("MEDFileUMesh::duplicateNodesOnM1Group : internal problem !");
3142   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newFam=DataArrayInt::New();
3143   newFam->alloc(newm1->getNumberOfCells(),1);
3144   int idd=getMaxFamilyId()+1;
3145   int globStart=0,start=0,end,globEnd;
3146   int nbOfChunks=szOfCellGrpOfSameType->getNumberOfTuples();
3147   for(int i=0;i<nbOfChunks;i++)
3148     {
3149       globEnd=globStart+szOfCellGrpOfSameType->getIJ(i,0);
3150       if(idInMsOfCellGrpOfSameType->getIJ(i,0)==0)
3151         {
3152           end=start+szOfCellGrpOfSameType->getIJ(i,0);
3153           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=fam->selectByTupleId2(start,end,1);
3154           newFam->setPartOfValues1(part,globStart,globEnd,1,0,1,1,true);
3155           start=end;
3156         }
3157       else
3158         {
3159           newFam->setPartOfValuesSimple1(idd,globStart,globEnd,1,0,1,1);
3160         }
3161       globStart=globEnd;
3162     }
3163   newm1->setCoords(getCoords());
3164   setMeshAtLevel(-1,newm1);
3165   setFamilyFieldArr(-1,newFam);
3166   std::string grpName2(grpNameM1); grpName2+="_dup";
3167   addFamily(grpName2.c_str(),idd);
3168   addFamilyOnGrp(grpName2.c_str(),grpName2.c_str());
3169   //
3170   fam=_fam_coords;
3171   if(fam)
3172     {
3173       int newNbOfNodes=getCoords()->getNumberOfTuples();
3174       newFam=DataArrayInt::New(); newFam->alloc(newNbOfNodes,1);
3175       newFam->setPartOfValues1(fam,0,nbNodes,1,0,1,1,true);
3176       newFam->setPartOfValuesSimple1(0,nbNodes,newNbOfNodes,1,0,1,1);
3177       _fam_coords=newFam;
3178     }
3179   nodesDuplicated=nodeIdsToDuplicate.retn();
3180   cellsModified=cellsToModifyConn0.retn();
3181   cellsNotModified=cellsToModifyConn1.retn();
3182 }
3183
3184 /*!
3185  * \param [out] oldCode retrieves the distribution of types before the call if true is returned
3186  * \param [out] newCode etrieves the distribution of types after the call if true is returned
3187  * \param [out] o2nRenumCell tells for **all levels** the old 2 new renumbering of cells.
3188  * 
3189  * \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.
3190  * 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.
3191  */
3192 bool MEDFileUMesh::unPolyze(std::vector<int>& oldCode, std::vector<int>& newCode, DataArrayInt *& o2nRenumCell) throw(INTERP_KERNEL::Exception)
3193 {
3194   o2nRenumCell=0; oldCode.clear(); newCode.clear();
3195   std::vector<int> levs=getNonEmptyLevels();
3196   bool ret=false;
3197   std::vector< const DataArrayInt* > renumCellsSplited;//same than memorySaverIfThrow
3198   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > memorySaverIfThrow;//same than renumCellsSplited only in case of throw
3199   int start=0;
3200   int end=0;
3201   for(std::vector<int>::reverse_iterator it=levs.rbegin();it!=levs.rend();it++)
3202     {
3203       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=getMeshAtLevel(*it);
3204       std::vector<int> code1=m->getDistributionOfTypes();
3205       end=PutInThirdComponentOfCodeOffset(code1,start);
3206       oldCode.insert(oldCode.end(),code1.begin(),code1.end());
3207       bool hasChanged=m->unPolyze();
3208       DataArrayInt *fake=0;
3209       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nCellsPart=m->getLevArrPerCellTypes(MEDCouplingUMesh::MEDMEM_ORDER,
3210                                                                                            MEDCouplingUMesh::MEDMEM_ORDER+MEDCouplingUMesh::N_MEDMEM_ORDER,fake);
3211       fake->decrRef();
3212       renumCellsSplited.push_back(o2nCellsPart); memorySaverIfThrow.push_back(o2nCellsPart);
3213       if(hasChanged)
3214         {
3215           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nCellsPart2=o2nCellsPart->buildPermArrPerLevel();
3216           m->renumberCells(o2nCellsPart2->getConstPointer(),false);
3217           ret=true;
3218           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famField2,numField2;
3219           const DataArrayInt *famField=getFamilyFieldAtLevel(*it); if(famField) { famField->incrRef(); famField2=const_cast<DataArrayInt *>(famField); }
3220           const DataArrayInt *numField=getNumberFieldAtLevel(*it); if(numField) { numField->incrRef(); numField2=const_cast<DataArrayInt *>(numField); }
3221           setMeshAtLevel(*it,m);
3222           std::vector<int> code2=m->getDistributionOfTypes();
3223           end=PutInThirdComponentOfCodeOffset(code2,start);
3224           newCode.insert(newCode.end(),code2.begin(),code2.end());
3225           //
3226           if(o2nCellsPart2->isIdentity())
3227             continue;
3228           if(famField)
3229             {
3230               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newFamField=famField->renumber(o2nCellsPart2->getConstPointer());
3231               setFamilyFieldArr(*it,newFamField);
3232             }
3233           if(numField)
3234             {
3235               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newNumField=numField->renumber(o2nCellsPart2->getConstPointer());
3236               setRenumFieldArr(*it,newNumField);
3237             }
3238         }
3239       else
3240         {
3241           newCode.insert(newCode.end(),code1.begin(),code1.end());
3242         }
3243       start=end;
3244     }
3245   if(ret)
3246     {
3247       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renumCells=DataArrayInt::Aggregate(renumCellsSplited);
3248       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRenumCellRet=renumCells->buildPermArrPerLevel();
3249       o2nRenumCell=o2nRenumCellRet.retn();
3250     }
3251   return ret;
3252 }
3253
3254 struct MEDLoaderAccVisit1
3255 {
3256   MEDLoaderAccVisit1():_new_nb_of_nodes(0) { }
3257   int operator()(bool val) { return val?_new_nb_of_nodes++:-1; }
3258   int _new_nb_of_nodes;
3259 };
3260
3261 /*!
3262  * 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.
3263  * The maximum value stored in returned array is the number of nodes of \a this minus 1 after call of this method.
3264  * The size of returned array is the number of nodes of the old (previous to the call of this method) number of nodes.
3265  * -1 values in returned array means that the corresponding old node is no more used.
3266  *
3267  * \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
3268  *         is modified in \a this.
3269  * \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
3270  *  set coordinates.
3271  */
3272 DataArrayInt *MEDFileUMesh::zipCoords() throw(INTERP_KERNEL::Exception)
3273 {
3274   const DataArrayDouble *coo=getCoords();
3275   if(!coo)
3276     throw INTERP_KERNEL::Exception("MEDFileUMesh::zipCoords : no coordinates set in this !");
3277   int nbOfNodes=coo->getNumberOfTuples();
3278   std::vector<bool> nodeIdsInUse(nbOfNodes,false);
3279   std::vector<int> neLevs=getNonEmptyLevels();
3280   for(std::vector<int>::const_iterator lev=neLevs.begin();lev!=neLevs.end();lev++)
3281     {
3282       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=getMeshAtLevel(*lev);
3283       m->computeNodeIdsAlg(nodeIdsInUse);
3284     }
3285   int nbrOfNodesInUse=(int)std::count(nodeIdsInUse.begin(),nodeIdsInUse.end(),true);
3286   if(nbrOfNodesInUse==nbOfNodes)
3287     return 0;
3288   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodes,1);
3289   std::transform(nodeIdsInUse.begin(),nodeIdsInUse.end(),ret->getPointer(),MEDLoaderAccVisit1());
3290   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2=ret->invertArrayO2N2N2OBis(nbrOfNodesInUse);
3291   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->selectByTupleIdSafe(ret2->begin(),ret2->end());
3292   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newFamCoords;
3293   MEDCouplingAutoRefCountObjectPtr<DataArrayAsciiChar> newNameCoords;
3294   if((const DataArrayInt *)_fam_coords)
3295     newFamCoords=_fam_coords->selectByTupleIdSafe(ret2->begin(),ret2->end());
3296   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newNumCoords;
3297   if((const DataArrayInt *)_num_coords)
3298     newNumCoords=_num_coords->selectByTupleIdSafe(ret2->begin(),ret2->end());
3299   if((const DataArrayAsciiChar *)_name_coords)
3300     newNameCoords=static_cast<DataArrayAsciiChar *>(_name_coords->selectByTupleIdSafe(ret2->begin(),ret2->end()));
3301   _coords=newCoords; _fam_coords=newFamCoords; _num_coords=newNumCoords; _name_coords=newNameCoords; _rev_num_coords=0;
3302   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
3303     {
3304       if((MEDFileUMeshSplitL1*)*it)
3305         (*it)->renumberNodesInConn(ret->begin());
3306     }
3307   return ret.retn();
3308 }
3309
3310 /*!
3311  * Adds a group of nodes to \a this mesh.
3312  *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
3313  *          The ids should be sorted and different each other (MED file norm).
3314  *  \throw If the node coordinates array is not set.
3315  *  \throw If \a ids == \c NULL.
3316  *  \throw If \a ids->getName() == "".
3317  *  \throw If \a ids does not respect the MED file norm.
3318  *  \throw If a group with name \a ids->getName() already exists.
3319  */
3320 void MEDFileUMesh::addNodeGroup(const DataArrayInt *ids) throw(INTERP_KERNEL::Exception)
3321 {
3322   const DataArrayDouble *coords=_coords;
3323   if(!coords)
3324     throw INTERP_KERNEL::Exception("MEDFileUMesh::addNodeGroup : no coords set !");
3325   int nbOfNodes=coords->getNumberOfTuples();
3326   if(!((DataArrayInt *)_fam_coords))
3327     { _fam_coords=DataArrayInt::New(); _fam_coords->alloc(nbOfNodes,1); _fam_coords->fillWithZero(); }
3328   //
3329   addGroupUnderground(true,ids,_fam_coords);
3330 }
3331
3332 /*!
3333  * Adds a group of nodes/cells/faces/edges to \a this mesh.
3334  *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
3335  *          The ids should be sorted and different each other (MED file norm).
3336  *  \throw If the node coordinates array is not set.
3337  *  \throw If \a ids == \c NULL.
3338  *  \throw If \a ids->getName() == "".
3339  *  \throw If \a ids does not respect the MED file norm.
3340  *  \throw If a group with name \a ids->getName() already exists.
3341  */
3342 void MEDFileUMesh::addGroup(int meshDimRelToMaxExt, const DataArrayInt *ids) throw(INTERP_KERNEL::Exception)
3343 {
3344   std::vector<int> levs=getNonEmptyLevelsExt();
3345   if(std::find(levs.begin(),levs.end(),meshDimRelToMaxExt)==levs.end())
3346     { 
3347       std::ostringstream oss; oss << "MEDFileUMesh::addGroup : level " << meshDimRelToMaxExt << " not available ! Should be in ";
3348       std::copy(levs.begin(),levs.end(),std::ostream_iterator<int>(oss," ")); oss << " !"; throw INTERP_KERNEL::Exception(oss.str().c_str());
3349     }
3350   if(meshDimRelToMaxExt==1)
3351     { addNodeGroup(ids); return ; }
3352   MEDFileUMeshSplitL1 *lev=getMeshAtLevSafe(meshDimRelToMaxExt);
3353   DataArrayInt *fam=lev->getOrCreateAndGetFamilyField();
3354   addGroupUnderground(false,ids,fam);
3355 }
3356
3357 /*!
3358  * \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).
3359  * \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)
3360  */
3361 void MEDFileUMesh::addGroupUnderground(bool isNodeGroup, const DataArrayInt *ids, DataArrayInt *famArr) throw(INTERP_KERNEL::Exception)
3362 {
3363   if(!ids)
3364     throw INTERP_KERNEL::Exception("MEDFileUMesh::addGroup : NULL pointer in input !");
3365   std::string grpName(ids->getName());
3366   if(grpName.empty())
3367     throw INTERP_KERNEL::Exception("MEDFileUMesh::addGroup : empty group name ! MED file format do not accept empty group name !");
3368   ids->checkStrictlyMonotonic(true);
3369   famArr->incrRef(); MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famArrTmp(famArr);
3370   std::vector<std::string> grpsNames=getGroupsNames();
3371   if(std::find(grpsNames.begin(),grpsNames.end(),grpName)!=grpsNames.end())
3372     {
3373       std::ostringstream oss; oss << "MEDFileUMesh::addGroup : Group with name \"" << grpName << "\" already exists ! Destroy it before calling this method !";
3374       throw INTERP_KERNEL::Exception(oss.str().c_str());
3375     }
3376   std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > allFamIds=getAllNonNullFamilyIds();
3377   allFamIds.erase(std::find(allFamIds.begin(),allFamIds.end(),famArrTmp));
3378   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famIds=famArr->selectByTupleIdSafe(ids->begin(),ids->end());
3379   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffFamIds=famIds->getDifferentValues();
3380   std::vector<int> familyIds;
3381   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerfamiliyIds;
3382   int maxVal=getTheMaxAbsFamilyId()+1;
3383   std::map<std::string,int> families(_families);
3384   std::map<std::string, std::vector<std::string> > groups(_groups);
3385   std::vector<std::string> fams;
3386   bool created(false);
3387   for(const int *famId=diffFamIds->begin();famId!=diffFamIds->end();famId++)
3388     {
3389       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2Tmp=famIds->getIdsEqual(*famId);
3390       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=ids->selectByTupleId(ids2Tmp->begin(),ids2Tmp->end());
3391       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids1=famArr->getIdsEqual(*famId);
3392       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(ids1->buildSubstractionOptimized(ids2));
3393       if(ret0->empty())
3394         {
3395           bool isFamPresent=false;
3396           for(std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::const_iterator itl=allFamIds.begin();itl!=allFamIds.end() && !isFamPresent;itl++)
3397             isFamPresent=(*itl)->presenceOfValue(*famId);
3398           if(!isFamPresent)
3399             { familyIds.push_back(*famId); idsPerfamiliyIds.push_back(ret0); fams.push_back(FindOrCreateAndGiveFamilyWithId(families,*famId,created)); } // adding *famId in grp
3400           else
3401             {
3402               familyIds.push_back(isNodeGroup?maxVal:-maxVal); idsPerfamiliyIds.push_back(ids2);
3403               std::string locFamName=FindOrCreateAndGiveFamilyWithId(families,isNodeGroup?maxVal:-maxVal,created);
3404               fams.push_back(locFamName);
3405               if(existsFamily(*famId))
3406                 {
3407                   std::string locFamName2=getFamilyNameGivenId(*famId); std::vector<std::string> v(2); v[0]=locFamName2; v[1]=locFamName;
3408                   ChangeAllGroupsContainingFamily(groups,getFamilyNameGivenId(*famId).c_str(),v);
3409                 }
3410               maxVal++;
3411             } // modifying all other groups on *famId to lie on maxVal and lie the grp on maxVal
3412         }
3413       else
3414         {
3415           familyIds.push_back(isNodeGroup?maxVal:-maxVal); idsPerfamiliyIds.push_back(ret0); // modifying all other groups on *famId to lie on maxVal and on maxVal+1
3416           familyIds.push_back(isNodeGroup?maxVal+1:-maxVal-1); idsPerfamiliyIds.push_back(ids2);//grp lie only on maxVal+1
3417           std::string n2(FindOrCreateAndGiveFamilyWithId(families,isNodeGroup?maxVal+1:-maxVal-1,created)); fams.push_back(n2);
3418           if(existsFamily(*famId))
3419             {
3420               std::string n1(FindOrCreateAndGiveFamilyWithId(families,isNodeGroup?maxVal:-maxVal,created)); std::vector<std::string> v(2); v[0]=n1; v[1]=n2;
3421               ChangeAllGroupsContainingFamily(groups,getFamilyNameGivenId(*famId).c_str(),v);
3422             }
3423           maxVal+=2;
3424         }
3425     }
3426   for(std::size_t i=0;i<familyIds.size();i++)
3427     {
3428       DataArrayInt *da=idsPerfamiliyIds[i];
3429       famArr->setPartOfValuesSimple3(familyIds[i],da->begin(),da->end(),0,1,1);
3430     }
3431   _families=families;
3432   _groups=groups;
3433   _groups[grpName]=fams;
3434 }
3435
3436 /*!
3437  * Changes a name of a family specified by its id.
3438  *  \param [in] id - the id of the family of interest.
3439  *  \param [in] newFamName - the new family name.
3440  *  \throw If no family with the given \a id exists.
3441  */
3442 void MEDFileUMesh::setFamilyNameAttachedOnId(int id, const std::string& newFamName) throw(INTERP_KERNEL::Exception)
3443 {
3444   std::string oldName=getFamilyNameGivenId(id);
3445   _families.erase(oldName);
3446   _families[newFamName]=id;
3447 }
3448
3449 /*!
3450  * Removes a mesh of a given dimension.
3451  *  \param [in] meshDimRelToMax - the relative dimension of interest.
3452  *  \throw If there is no mesh at level \a meshDimRelToMax in \a this mesh.
3453  */
3454 void MEDFileUMesh::removeMeshAtLevel(int meshDimRelToMax) throw(INTERP_KERNEL::Exception)
3455 {
3456   std::vector<int> levSet=getNonEmptyLevels();
3457   std::vector<int>::const_iterator it=std::find(levSet.begin(),levSet.end(),meshDimRelToMax);
3458   if(it==levSet.end())
3459     throw INTERP_KERNEL::Exception("MEDFileUMesh::removeMeshAtLevel : the requested level is not existing !");
3460   int pos=(-meshDimRelToMax);
3461   _ms[pos]=0;
3462 }
3463
3464 /*!
3465  * Sets a new MEDCouplingUMesh at a given level in \a this mesh.
3466  *  \param [in] meshDimRelToMax - a relative level to set the mesh at.
3467  *  \param [in] m - the new mesh to set.
3468  *  \param [in] newOrOld - if \c true, cells in \a m are sorted by type to be ready for 
3469  *         writing \a this mesh in a MED file.
3470  *  \throw If the name or the description of \a this mesh and \a m are not empty and are
3471  *         different. 
3472  *  \throw If the node coordinates array is set \a this in mesh and \a m refers to
3473  *         another node coordinates array.
3474  *  \throw If the mesh dimension of \a m does not correspond to \a meshDimRelToMax or
3475  *         to the existing meshes of other levels of \a this mesh.
3476  */
3477 void MEDFileUMesh::setMeshAtLevel(int meshDimRelToMax, MEDCouplingUMesh *m, bool newOrOld) throw(INTERP_KERNEL::Exception)
3478 {
3479   dealWithTinyInfo(m);
3480   std::vector<int> levSet=getNonEmptyLevels();
3481   if(std::find(levSet.begin(),levSet.end(),meshDimRelToMax)==levSet.end())
3482     {
3483       if((DataArrayDouble *)_coords==0)
3484         {
3485           DataArrayDouble *c=m->getCoords();
3486           if(c)
3487             c->incrRef();
3488           _coords=c;
3489         }
3490       if(m->getCoords()!=_coords)
3491         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshAtLevel : Invalid Given Mesh ! The coordinates are not the same ! try to use tryToShareSameCoords !");
3492       int sz=(-meshDimRelToMax)+1;
3493       if(sz>=(int)_ms.size())
3494         _ms.resize(sz);
3495       checkMeshDimCoherency(m->getMeshDimension(),meshDimRelToMax);
3496       _ms[sz-1]=new MEDFileUMeshSplitL1(m,newOrOld);
3497     }
3498   else
3499     _ms[-meshDimRelToMax]=new MEDFileUMeshSplitL1(m,newOrOld);
3500 }
3501
3502 /*!
3503  * This method allows to set at once the content of different levels in \a this.
3504  * This method is equivalent to a series of call to MEDFileUMesh::setMeshAtLevel.
3505  *
3506  * \param [in] ms - List of unstructured meshes lying on the same coordinates and having different mesh dimesnion.
3507  * \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.
3508  *                     If false, an exception ois thrown. If true the mesh is reordered automatically. It is highly recommanded to let this parameter to false.
3509  *
3510  * \throw If \a there is a null pointer in \a ms.
3511  * \sa MEDFileUMesh::setMeshAtLevel
3512  */
3513 void MEDFileUMesh::setMeshes(const std::vector<const MEDCouplingUMesh *>& ms, bool renum) throw(INTERP_KERNEL::Exception)
3514 {
3515   if(ms.empty())
3516     return ;
3517   const MEDCouplingUMesh *mRef=ms[0];
3518   if(!mRef)
3519     throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : null instance in the first element of input meshes !");
3520   std::string name(mRef->getName());
3521   const DataArrayDouble *coo(mRef->getCoords());
3522   std::set<int> s;
3523   int zeDim=-1;
3524   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
3525     {
3526       const MEDCouplingUMesh *cur(*it);
3527       if(!cur)
3528         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : null instance in input vector of meshes !");
3529       if(coo!=cur->getCoords())
3530         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : The input meshes do not share the same coordinates !");
3531       int mdim=cur->getMeshDimension();
3532       zeDim=std::max(zeDim,mdim);
3533       if(s.find(mdim)!=s.end())
3534         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : The input meshes must share the same coordinates pointer, and should have different mesh dimension each other !");
3535     }
3536   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
3537     {
3538       int mdim=(*it)->getMeshDimension();
3539       setName((*it)->getName().c_str());
3540       setMeshAtLevel(mdim-zeDim,const_cast<MEDCouplingUMesh *>(*it),renum);
3541     }
3542   setName(name.c_str());
3543 }
3544
3545 /*!
3546  * Creates one MEDCouplingUMesh at a given level in \a this mesh from a sequence of
3547  * meshes each representing a group, and creates corresponding groups in \a this mesh.
3548  * The given meshes must share the same node coordinates array.
3549  *  \param [in] meshDimRelToMax - the relative dimension to create the mesh and groups at.
3550  *  \param [in] ms - the sequence of meshes. Each mesh in \a ms represents a group to
3551  *          create in \a this mesh.
3552  *  \throw If \a ms is empty.
3553  *  \throw If dimension of meshes in \a ms does not correspond to \a meshDimRelToMax or
3554  *         to the existing meshes of other levels of \a this mesh.
3555  *  \throw If the meshes in \a ms do not share the same node coordinates array.
3556  *  \throw If the node coordinates array of \a this mesh (if any) is not the same as that
3557  *         of the given meshes.
3558  *  \throw If \a ms[ i ] is not well defined (MEDCouplingUMesh::checkCoherency()).
3559  *  \throw If names of some meshes in \a ms are equal.
3560  *  \throw If \a ms includes a mesh with an empty name.
3561  */
3562 void MEDFileUMesh::setGroupsFromScratch(int meshDimRelToMax, const std::vector<const MEDCouplingUMesh *>& ms, bool renum) throw(INTERP_KERNEL::Exception)
3563 {
3564   if(ms.empty())
3565     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsFromScratch : expecting a non empty vector !");
3566   int sz=(-meshDimRelToMax)+1;
3567   if(sz>=(int)_ms.size())
3568     _ms.resize(sz);
3569   checkMeshDimCoherency(ms[0]->getMeshDimension(),meshDimRelToMax);
3570   DataArrayDouble *coo=checkMultiMesh(ms);
3571   if((DataArrayDouble *)_coords==0)
3572     {
3573       coo->incrRef();
3574       _coords=coo;
3575     }
3576   else
3577     if((DataArrayDouble *)_coords!=coo)
3578       throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsFromScratch : coordinates mismatches !");
3579   std::vector<DataArrayInt *> corr;
3580   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MEDCouplingUMesh::FuseUMeshesOnSameCoords(ms,_zipconn_pol,corr);
3581   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > corr3(corr.begin(),corr.end());
3582   setMeshAtLevel(meshDimRelToMax,m,renum);
3583   std::vector<const DataArrayInt *> corr2(corr.begin(),corr.end());
3584   setGroupsAtLevel(meshDimRelToMax,corr2,true);
3585 }
3586
3587 /*!
3588  * Creates groups at a given level in \a this mesh from a sequence of
3589  * meshes each representing a group.
3590  * The given meshes must share the same node coordinates array.
3591  *  \param [in] meshDimRelToMax - the relative dimension to create the groups at.
3592  *  \param [in] ms - the sequence of meshes. Each mesh in \a ms represents a group to
3593  *         create in \a this mesh.
3594  *  \param [in] renum - if \c true, then the optional numbers of entities are taken into
3595  *         account. 
3596  *  \throw If \a ms is empty.
3597  *  \throw If dimension of meshes in \a ms does not correspond to \a meshDimRelToMax or
3598  *         to the existing meshes of other levels of \a this mesh.
3599  *  \throw If the meshes in \a ms do not share the same node coordinates array.
3600  *  \throw If the node coordinates array of \a this mesh (if any) is not the same as that
3601  *         of the given meshes.
3602  *  \throw If \a ms[ i ] is not well defined (MEDCouplingUMesh::checkCoherency()).
3603  *  \throw If names of some meshes in \a ms are equal.
3604  *  \throw If \a ms includes a mesh with an empty name.
3605  */
3606 void MEDFileUMesh::setGroupsOnSetMesh(int meshDimRelToMax, const std::vector<const MEDCouplingUMesh *>& ms, bool renum) throw(INTERP_KERNEL::Exception)
3607 {
3608   if(ms.empty())
3609     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsOnSetMesh : expecting a non empty vector !");
3610   int sz=(-meshDimRelToMax)+1;
3611   if(sz>=(int)_ms.size())
3612     _ms.resize(sz);
3613   checkMeshDimCoherency(ms[0]->getMeshDimension(),meshDimRelToMax);
3614   DataArrayDouble *coo=checkMultiMesh(ms);
3615   if((DataArrayDouble *)_coords==0)
3616     {
3617       coo->incrRef();
3618       _coords=coo;
3619     }
3620   else
3621     if((DataArrayDouble *)_coords!=coo)
3622       throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsOnSetMesh : coordinates mismatches !");
3623   MEDCouplingUMesh *m=getMeshAtLevel(meshDimRelToMax,renum);
3624   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > corr(ms.size());
3625   int i=0;
3626   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++,i++)
3627     {
3628       DataArrayInt *arr=0;
3629       bool test=m->areCellsIncludedIn(*it,_zipconn_pol,arr);
3630       corr[i]=arr;
3631       if(!test)
3632         {
3633           std::ostringstream oss; oss << "MEDFileUMesh::setGroupsOnSetMesh : mesh #" << i << " is not part of whole mesh !";
3634           throw INTERP_KERNEL::Exception(oss.str().c_str());
3635         }
3636     }
3637   std::vector<const DataArrayInt *> corr2(corr.begin(),corr.end());
3638   setGroupsAtLevel(meshDimRelToMax,corr2,renum);
3639 }
3640
3641 DataArrayDouble *MEDFileUMesh::checkMultiMesh(const std::vector<const MEDCouplingUMesh *>& ms) const throw(INTERP_KERNEL::Exception)
3642 {
3643   const DataArrayDouble *ret=ms[0]->getCoords();
3644   int mdim=ms[0]->getMeshDimension();
3645   for(unsigned int i=1;i<ms.size();i++)
3646     {
3647       ms[i]->checkCoherency();
3648       if(ms[i]->getCoords()!=ret)
3649         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMultiMesh : meshes must share the same coords !");
3650       if(ms[i]->getMeshDimension()!=mdim)
3651         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMultiMesh : meshes have not same mesh dimension !");
3652     }
3653   return const_cast<DataArrayDouble *>(ret);
3654 }
3655
3656 /*!
3657  * Sets the family field of a given relative dimension.
3658  *  \param [in] meshDimRelToMaxExt - the relative dimension of entities for which
3659  *          the family field is set.
3660  *  \param [in] famArr - the array of the family field.
3661  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3662  *  \throw If \a famArr has an invalid size.
3663  */
3664 void MEDFileUMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr) throw(INTERP_KERNEL::Exception)
3665 {
3666   if(meshDimRelToMaxExt==1)
3667     {
3668       if(!famArr)
3669         {
3670           _fam_coords=0;
3671           return ;
3672         }
3673       DataArrayDouble *coo(_coords);
3674       if(!coo)
3675         throw INTERP_KERNEL::Exception("MEDFileUMesh::setFamilyFieldArr : the coordinates have not been set !");
3676       famArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),1,"MEDFileUMesh::setFamilyFieldArr : Problem in size of node family arr ! ");
3677       famArr->incrRef();
3678       _fam_coords=famArr;
3679       return ;
3680     }
3681   if(meshDimRelToMaxExt>1)
3682     throw INTERP_KERNEL::Exception("MEDFileUMesh::setFamilyFieldArr : Dimension request is invalid (>1) !");
3683   int traducedRk=-meshDimRelToMaxExt;
3684   if(traducedRk>=(int)_ms.size())
3685     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
3686   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
3687     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3688   return _ms[traducedRk]->setFamilyArr(famArr);
3689 }
3690
3691 /*!
3692  * Sets the optional numbers of mesh entities of a given dimension.
3693  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
3694  *  \param [in] renumArr - the array of the numbers.
3695  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3696  *  \throw If \a renumArr has an invalid size.
3697  */
3698 void MEDFileUMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr) throw(INTERP_KERNEL::Exception)
3699 {
3700   if(meshDimRelToMaxExt==1)
3701     {
3702       if(!renumArr)
3703         {
3704           _num_coords=0;
3705           _rev_num_coords=0;
3706           return ;
3707         }
3708       DataArrayDouble *coo(_coords);
3709       if(!coo)
3710         throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumFieldArr : the coordinates have not been set !");
3711       renumArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),1,"MEDFileUMesh::setRenumArr : Problem in size of node numbering arr ! ");
3712       renumArr->incrRef();
3713       _num_coords=renumArr;
3714       computeRevNum();
3715       return ;
3716     }
3717   if(meshDimRelToMaxExt>1)
3718     throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumArr : Dimension request is invalid (>1) !");
3719   int traducedRk=-meshDimRelToMaxExt;
3720   if(traducedRk>=(int)_ms.size())
3721     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
3722   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
3723     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3724   return _ms[traducedRk]->setRenumArr(renumArr);
3725 }
3726
3727 /*!
3728  * Sets the optional names of mesh entities of a given dimension.
3729  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
3730  *  \param [in] nameArr - the array of the names.
3731  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3732  *  \throw If \a nameArr has an invalid size.
3733  */
3734 void MEDFileUMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr) throw(INTERP_KERNEL::Exception)
3735 {
3736   if(meshDimRelToMaxExt==1)
3737     {
3738       if(!nameArr)
3739         {
3740           _name_coords=0;
3741           return ;
3742         }
3743       DataArrayDouble *coo(_coords);
3744       if(!coo)
3745         throw INTERP_KERNEL::Exception("MEDFileUMesh::setNameFieldAtLevel : the coordinates have not been set !");
3746       nameArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),MED_SNAME_SIZE,"MEDFileUMesh::setNameFieldAtLevel : Problem in size of node numbering arr ! ");
3747       nameArr->incrRef();
3748       _name_coords=nameArr;
3749       return ;
3750     }
3751   if(meshDimRelToMaxExt>1)
3752     throw INTERP_KERNEL::Exception("MEDFileUMesh::setNameFieldAtLevel : Dimension request is invalid (>1) !");
3753   int traducedRk=-meshDimRelToMaxExt;
3754   if(traducedRk>=(int)_ms.size())
3755     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
3756   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
3757     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3758   return _ms[traducedRk]->setNameArr(nameArr);
3759 }
3760
3761 void MEDFileUMesh::synchronizeTinyInfoOnLeaves() const
3762 {
3763   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
3764     if((const MEDFileUMeshSplitL1 *)(*it))
3765       (*it)->synchronizeTinyInfo(*this);
3766 }
3767
3768 /*!
3769  * This method is called by MEDFileMesh::changeFamilyId. It performs only one part of the family id modification.
3770  */
3771 void MEDFileUMesh::changeFamilyIdArr(int oldId, int newId) throw(INTERP_KERNEL::Exception)
3772 {
3773   DataArrayInt *arr=_fam_coords;
3774   if(arr)
3775     arr->changeValue(oldId,newId);
3776   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
3777     {
3778       MEDFileUMeshSplitL1 *sp=(*it);
3779       if(sp)
3780         {
3781           sp->changeFamilyIdArr(oldId,newId);
3782         }
3783     }
3784 }
3785
3786 std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > MEDFileUMesh::getAllNonNullFamilyIds() const
3787 {
3788   std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret;
3789   const DataArrayInt *da(_fam_coords);
3790   if(da)
3791     { da->incrRef(); ret.push_back(MEDCouplingAutoRefCountObjectPtr<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
3792   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
3793     {
3794       const MEDFileUMeshSplitL1 *elt(*it);
3795       if(elt)
3796         {
3797           da=elt->getFamilyField();
3798           if(da)
3799             { da->incrRef(); ret.push_back(MEDCouplingAutoRefCountObjectPtr<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
3800         }
3801     }
3802   return ret;
3803 }
3804
3805 void MEDFileUMesh::computeRevNum() const
3806 {
3807   if((const DataArrayInt *)_num_coords)
3808     {
3809       int pos;
3810       int maxValue=_num_coords->getMaxValue(pos);
3811       _rev_num_coords=_num_coords->invertArrayN2O2O2N(maxValue+1);
3812     }
3813 }
3814
3815 std::size_t MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren() const
3816 {
3817   return MEDFileMesh::getHeapMemorySizeWithoutChildren();
3818 }
3819
3820 std::vector<RefCountObject *> MEDFileStructuredMesh::getDirectChildren() const
3821 {
3822   std::vector<RefCountObject *> ret(MEDFileMesh::getDirectChildren());
3823   if((const DataArrayInt *)_fam_nodes)
3824     ret.push_back(const_cast<DataArrayInt *>((const DataArrayInt *)_fam_nodes));
3825   if((const DataArrayInt *)_num_nodes)
3826     ret.push_back(const_cast<DataArrayInt *>((const DataArrayInt *)_num_nodes));
3827   if((const DataArrayInt *)_fam_cells)
3828     ret.push_back(const_cast<DataArrayInt *>((const DataArrayInt *)_fam_cells));
3829   if((const DataArrayInt *)_num_cells)
3830     ret.push_back(const_cast<DataArrayInt *>((const DataArrayInt *)_num_nodes));
3831   if((const DataArrayInt *)_rev_num_nodes)
3832     ret.push_back(const_cast<DataArrayInt *>((const DataArrayInt *)_rev_num_nodes));
3833   if((const DataArrayInt *)_rev_num_cells)
3834     ret.push_back(const_cast<DataArrayInt *>((const DataArrayInt *)_rev_num_cells));
3835   return ret;
3836 }
3837
3838 int MEDFileStructuredMesh::getMaxAbsFamilyIdInArrays() const throw(INTERP_KERNEL::Exception)
3839 {
3840   int ret=-std::numeric_limits<int>::max(),tmp=-1;
3841   if((const DataArrayInt *)_fam_nodes)
3842     {
3843       int val=_fam_nodes->getMaxValue(tmp);
3844       ret=std::max(ret,std::abs(val));
3845     }
3846   if((const DataArrayInt *)_fam_cells)
3847     {
3848       int val=_fam_cells->getMaxValue(tmp);
3849       ret=std::max(ret,std::abs(val));
3850     }
3851   return ret;
3852 }
3853
3854 int MEDFileStructuredMesh::getMaxFamilyIdInArrays() const throw(INTERP_KERNEL::Exception)
3855 {
3856   int ret=-std::numeric_limits<int>::max(),tmp=-1;
3857   if((const DataArrayInt *)_fam_nodes)
3858     {
3859       int val=_fam_nodes->getMaxValue(tmp);
3860       ret=std::max(ret,val);
3861     }
3862   if((const DataArrayInt *)_fam_cells)
3863     {
3864       int val=_fam_cells->getMaxValue(tmp);
3865       ret=std::max(ret,val);
3866     }
3867   return ret;
3868 }
3869
3870 int MEDFileStructuredMesh::getMinFamilyIdInArrays() const throw(INTERP_KERNEL::Exception)
3871 {
3872   int ret=std::numeric_limits<int>::max(),tmp=-1;
3873   if((const DataArrayInt *)_fam_nodes)
3874     {
3875       int val=_fam_nodes->getMinValue(tmp);
3876       ret=std::min(ret,val);
3877     }
3878   if((const DataArrayInt *)_fam_cells)
3879     {
3880       int val=_fam_cells->getMinValue(tmp);
3881       ret=std::min(ret,val);
3882     }
3883   return ret;
3884 }
3885
3886 bool MEDFileStructuredMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
3887 {
3888   if(!MEDFileMesh::isEqual(other,eps,what))
3889     return false;
3890   const MEDFileStructuredMesh *otherC=dynamic_cast<const  MEDFileStructuredMesh *>(other);
3891   if(!otherC)
3892     {
3893       what="Mesh types differ ! This is structured and other is NOT !";
3894       return false;
3895     }
3896   const DataArrayInt *famc1=_fam_nodes;
3897   const DataArrayInt *famc2=otherC->_fam_nodes;
3898   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
3899     {
3900       what="Mismatch of families arr on nodes ! One is defined and not other !";
3901       return false;
3902     }
3903   if(famc1)
3904     {
3905       bool ret=famc1->isEqual(*famc2);
3906       if(!ret)
3907         {
3908           what="Families arr on nodes differ !";
3909           return false;
3910         }
3911     }
3912   famc1=_fam_cells;
3913   famc2=otherC->_fam_cells;
3914   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
3915     {
3916       what="Mismatch of families arr on cells ! One is defined and not other !";
3917       return false;
3918     }
3919   if(famc1)
3920     {
3921       bool ret=famc1->isEqual(*famc2);
3922       if(!ret)
3923         {
3924           what="Families arr on cells differ !";
3925           return false;
3926         }
3927     }
3928   famc1=_num_nodes;
3929   famc2=otherC->_num_nodes;
3930   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
3931     {
3932       what="Mismatch of numbering arr on nodes ! One is defined and not other !";
3933       return false;
3934     }
3935   if(famc1)
3936     {
3937       bool ret=famc1->isEqual(*famc2);
3938       if(!ret)
3939         {
3940           what="Numbering arr on nodes differ !";
3941           return false;
3942         }
3943     }
3944   famc1=_num_cells;
3945   famc2=otherC->_num_cells;
3946   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
3947     {
3948       what="Mismatch of numbering arr on cells ! One is defined and not other !";
3949       return false;
3950     }
3951   if(famc1)
3952     {
3953       bool ret=famc1->isEqual(*famc2);
3954       if(!ret)
3955         {
3956           what="Numbering arr on cells differ !";
3957           return false;
3958         }
3959     }
3960   const DataArrayAsciiChar *d1=_names_cells;
3961   const DataArrayAsciiChar *d2=otherC->_names_cells;
3962   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
3963     {
3964       what="Mismatch of naming arr on cells ! One is defined and not other !";
3965       return false;
3966     }
3967   if(d1)
3968     {
3969       bool ret=d1->isEqual(*d2);
3970       if(!ret)
3971         {
3972           what="Naming arr on cells differ !";
3973           return false;
3974         }
3975     }
3976   d1=_names_nodes;
3977   d2=otherC->_names_nodes;
3978   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
3979     {
3980       what="Mismatch of naming arr on nodes ! One is defined and not other !";
3981       return false;
3982     }
3983   if(d1)
3984     {
3985       bool ret=d1->isEqual(*d2);
3986       if(!ret)
3987         {
3988           what="Naming arr on nodes differ !";
3989           return false;
3990         }
3991     }
3992   return true;
3993 }
3994
3995 void MEDFileStructuredMesh::clearNonDiscrAttributes() const
3996 {
3997   MEDFileMesh::clearNonDiscrAttributes();
3998   const DataArrayInt *tmp=_fam_nodes;
3999   if(tmp)
4000     (const_cast<DataArrayInt *>(tmp))->setName("");
4001   tmp=_num_nodes;
4002   if(tmp)
4003     (const_cast<DataArrayInt *>(tmp))->setName("");
4004   tmp=_fam_cells;
4005   if(tmp)
4006     (const_cast<DataArrayInt *>(tmp))->setName("");
4007   tmp=_num_cells;
4008   if(tmp)
4009     (const_cast<DataArrayInt *>(tmp))->setName("");
4010 }
4011
4012 /*!
4013  * Returns ids of mesh entities contained in given families of a given dimension.
4014  *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
4015  *          are required.
4016  *  \param [in] fams - the names of the families of interest.
4017  *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
4018  *          returned instead of ids.
4019  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
4020  *          numbers, if available and required, of mesh entities of the families. The caller
4021  *          is to delete this array using decrRef() as it is no more needed. 
4022  *  \throw If the family field is missing for \a meshDimRelToMaxExt.
4023  */
4024 DataArrayInt *MEDFileStructuredMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const throw(INTERP_KERNEL::Exception)
4025 {
4026   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4027     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : Only available for levels 0 or 1 !");
4028   std::vector<int> famIds=getFamiliesIds(fams);
4029   if(meshDimRelToMaxExt==1)
4030     {
4031       if((const DataArrayInt *)_fam_nodes)
4032         {
4033           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
4034           if(!famIds.empty())
4035             da=_fam_nodes->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
4036           else
4037             da=_fam_nodes->getIdsEqualList(0,0);
4038           if(renum)
4039             return MEDFileUMeshSplitL1::Renumber(_num_nodes,da);
4040           else
4041             return da.retn();
4042         }
4043       else
4044         throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on nodes !");
4045     }
4046   else
4047     {
4048       if((const DataArrayInt *)_fam_cells)
4049         {
4050           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
4051           if(!famIds.empty())
4052             da=_fam_cells->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
4053           else
4054             da=_fam_cells->getIdsEqualList(0,0);
4055           if(renum)
4056             return MEDFileUMeshSplitL1::Renumber(_num_cells,da);
4057           else
4058             return da.retn();
4059         }
4060       else
4061         throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on cells !");
4062     }
4063 }
4064
4065 /*!
4066  * Sets the family field of a given relative dimension.
4067  *  \param [in] meshDimRelToMaxExt - the relative dimension of entities for which
4068  *          the family field is set.
4069  *  \param [in] famArr - the array of the family field.
4070  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4071  *  \throw If \a famArr has an invalid size.
4072  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
4073  */
4074 void MEDFileStructuredMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr) throw(INTERP_KERNEL::Exception)
4075 {
4076   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4077     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : Only available for levels 0 or 1 !");
4078   const MEDCouplingStructuredMesh *mesh=getStructuredMesh();
4079   if(!mesh)
4080     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setFamilyFieldArr : no structured mesh specified ! Impossible to set family array !");
4081   if(meshDimRelToMaxExt==0)
4082     {
4083       int nbCells=mesh->getNumberOfCells();
4084       famArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of cells of mesh !");
4085       _fam_cells=famArr;
4086     }
4087   else
4088     {
4089       int nbNodes=mesh->getNumberOfNodes();
4090       famArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !");
4091       _fam_nodes=famArr;
4092     }
4093   if(famArr)
4094     famArr->incrRef();
4095 }
4096
4097 /*!
4098  * Sets the optional numbers of mesh entities of a given dimension.
4099  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4100  *  \param [in] renumArr - the array of the numbers.
4101  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4102  *  \throw If \a renumArr has an invalid size.
4103  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
4104  */
4105 void MEDFileStructuredMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr) throw(INTERP_KERNEL::Exception)
4106 {
4107   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4108     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : Only available for levels 0 or 1 !");
4109   const MEDCouplingStructuredMesh *mesh=getStructuredMesh();
4110   if(!mesh)
4111     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : no structured mesh specified ! Impossible to set number array !");
4112   if(meshDimRelToMaxExt==0)
4113     {
4114       int nbCells=mesh->getNumberOfCells();
4115       renumArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Renum arr ! Mismatch with number of cells of mesh !");
4116       _num_cells=renumArr;
4117     }
4118   else
4119     {
4120       int nbNodes=mesh->getNumberOfNodes();
4121       renumArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !");
4122       _num_nodes=renumArr;
4123     }
4124   if(renumArr)
4125     renumArr->incrRef();
4126 }
4127
4128 /*!
4129  * Sets the optional names of mesh entities of a given dimension.
4130  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4131  *  \param [in] nameArr - the array of the names.
4132  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4133  *  \throw If \a nameArr has an invalid size.
4134  */
4135 void MEDFileStructuredMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr) throw(INTERP_KERNEL::Exception)
4136 {
4137   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4138     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : Only available for levels 0 or 1 !");
4139   const MEDCouplingStructuredMesh *mesh=getStructuredMesh();
4140   if(!mesh)
4141     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : no structured mesh specified ! Impossible to set names array !");
4142   if(meshDimRelToMaxExt==0)
4143     {
4144       int nbCells=mesh->getNumberOfCells();
4145       nameArr->checkNbOfTuplesAndComp(nbCells,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of cells of mesh !");
4146       _names_cells=nameArr;
4147     }
4148   else
4149     {
4150       int nbNodes=mesh->getNumberOfNodes();
4151       nameArr->checkNbOfTuplesAndComp(nbNodes,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of nodes of mesh !");
4152       _names_nodes=nameArr;
4153     }
4154   if(nameArr)
4155     nameArr->incrRef();
4156 }
4157
4158 /*!
4159  * Returns the family field for mesh entities of a given dimension.
4160  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4161  *  \return const DataArrayInt * - the family field. It is an array of ids of families
4162  *          each mesh entity belongs to. It can be \c NULL.
4163  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
4164  */
4165 const DataArrayInt *MEDFileStructuredMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
4166 {
4167   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4168     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamilyFieldAtLevel : Only available for levels 0 or 1 !");
4169   if(meshDimRelToMaxExt==0)
4170     return _fam_cells;
4171   else
4172     return _fam_nodes;
4173 }
4174
4175 /*!
4176  * Returns the optional numbers of mesh entities of a given dimension.
4177  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4178  *  \return const DataArrayInt * - the array of the entity numbers.
4179  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4180  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
4181  */
4182 const DataArrayInt *MEDFileStructuredMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
4183 {
4184   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4185     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberFieldAtLevel : Only available for levels 0 or 1 !");
4186   if(meshDimRelToMaxExt==0)
4187     return _num_cells;
4188   else
4189     return _num_nodes;
4190 }
4191
4192 /*!
4193  * Returns the optional numbers of mesh entities of a given dimension transformed using
4194  * DataArrayInt::invertArrayN2O2O2N().
4195  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4196  *  \return const DataArrayInt * - the array of the entity numbers transformed using
4197  *          DataArrayInt::invertArrayN2O2O2N().
4198  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
4199  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4200  */
4201 const DataArrayInt *MEDFileStructuredMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
4202 {
4203   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4204     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getRevNumberFieldAtLevel : Only available for levels 0 or 1 !");
4205   if(meshDimRelToMaxExt==0)
4206     {
4207       if((const DataArrayInt *)_num_cells)
4208         {
4209           int pos;
4210           int maxValue=_num_cells->getMaxValue(pos);
4211           _rev_num_cells=_num_cells->invertArrayN2O2O2N(maxValue+1);
4212           return _rev_num_cells;
4213         }
4214       else
4215         throw INTERP_KERNEL::Exception("MEDFileCMesh::getRevNumberFieldAtLevel : no cell renumbering for a request on reverse numbering !");
4216     }
4217   else
4218     {
4219       if((const DataArrayInt *)_num_nodes)
4220         {
4221           int pos;
4222           int maxValue=_num_nodes->getMaxValue(pos);
4223           _rev_num_nodes=_num_nodes->invertArrayN2O2O2N(maxValue+1);
4224           return _rev_num_nodes;
4225         }
4226       else
4227         throw INTERP_KERNEL::Exception("MEDFileCMesh::getRevNumberFieldAtLevel : no node renumbering for a request on reverse numbering !");
4228     }
4229 }
4230
4231 const DataArrayAsciiChar *MEDFileStructuredMesh::getNameFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
4232 {
4233   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4234     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNameFieldAtLevel : Only available for levels 0 or 1 !");
4235   if(meshDimRelToMaxExt==0)
4236     return _names_cells;
4237   else
4238     return _names_nodes;
4239 }
4240
4241 /*!
4242  * Returns relative dimensions of mesh entities (excluding nodes) present in \a this mesh.
4243  *  \return std::vector<int> - a sequence of the relative dimensions: [0].
4244  */
4245 std::vector<int> MEDFileStructuredMesh::getNonEmptyLevels() const
4246 {
4247   std::vector<int> ret(1);
4248   return ret;
4249 }
4250
4251 /*!
4252  * Returns relative dimensions of mesh entities (including nodes) present in \a this mesh.
4253  *  \return std::vector<int> - a sequence of the relative dimensions: [1,0].
4254  */
4255 std::vector<int> MEDFileStructuredMesh::getNonEmptyLevelsExt() const
4256 {
4257   std::vector<int> ret(2);
4258   ret[0]=1;
4259   return ret;
4260 }
4261
4262 /*!
4263  * Returns the set of extensive levels (nodes included) where not NULL family arr are defined.
4264  */
4265 std::vector<int> MEDFileStructuredMesh::getFamArrNonEmptyLevelsExt() const
4266 {
4267   std::vector<int> ret;
4268   const DataArrayInt *famNodes(_fam_nodes),*famCells(_fam_cells);
4269   if(famNodes)
4270     ret.push_back(1);
4271   if(famCells)
4272     ret.push_back(0);
4273   return ret;
4274 }
4275
4276 /*!
4277  * Returns the set of extensive levels (nodes included) where not NULL numbering arr are defined.
4278  */
4279 std::vector<int> MEDFileStructuredMesh::getNumArrNonEmptyLevelsExt() const
4280 {
4281   std::vector<int> ret;
4282   const DataArrayInt *numNodes(_num_nodes),*numCells(_num_cells);
4283   if(numNodes)
4284     ret.push_back(1);
4285   if(numCells)
4286     ret.push_back(0);
4287   return ret;
4288 }
4289
4290 /*!
4291  * Returns the set of extensive levels (nodes included) where not NULL naming arr are defined.
4292  */
4293 std::vector<int> MEDFileStructuredMesh::getNameArrNonEmptyLevelsExt() const
4294 {
4295   std::vector<int> ret;
4296   const DataArrayAsciiChar *namesCells(_names_cells);
4297   if(namesCells)
4298     ret.push_back(0);
4299   return ret;
4300 }
4301
4302 /*!
4303  * no implementation here, it is not a bug, but intresically no polyhedra in \a this.
4304  */
4305 bool MEDFileStructuredMesh::unPolyze(std::vector<int>& oldCode, std::vector<int>& newCode, DataArrayInt *& o2nRenumCell) throw(INTERP_KERNEL::Exception)
4306 {
4307   oldCode.clear(); newCode.clear(); o2nRenumCell=0;
4308   return false;
4309 }
4310
4311 void MEDFileStructuredMesh::changeFamilyIdArr(int oldId, int newId) throw(INTERP_KERNEL::Exception)
4312 {
4313   DataArrayInt *arr=_fam_nodes;
4314   if(arr)
4315     arr->changeValue(oldId,newId);
4316   arr=_fam_cells;
4317   if(arr)
4318     arr->changeValue(oldId,newId);
4319 }
4320
4321 void MEDFileStructuredMesh::deepCpyAttributes() throw(INTERP_KERNEL::Exception)
4322 {
4323   if((const DataArrayInt*)_fam_nodes)
4324     _fam_nodes=_fam_nodes->deepCpy();
4325   if((const DataArrayInt*)_num_nodes)
4326     _num_nodes=_num_nodes->deepCpy();
4327   if((const DataArrayInt*)_fam_cells)
4328     _fam_cells=_fam_cells->deepCpy();
4329   if((const DataArrayInt*)_num_cells)
4330     _num_cells=_num_cells->deepCpy();
4331   if((const DataArrayInt*)_rev_num_nodes)
4332     _rev_num_nodes=_rev_num_nodes->deepCpy();
4333   if((const DataArrayInt*)_rev_num_cells)
4334     _rev_num_cells=_rev_num_cells->deepCpy();
4335 }
4336
4337 /*!
4338  * Returns a pointer to mesh at the specified level (here 0 is compulsary for cartesian mesh).
4339  * 
4340  * \return a pointer to cartesian mesh that need to be managed by the caller.
4341  * \warning the returned pointer has to be managed by the caller.
4342  */
4343
4344 /*!
4345  * Returns a pointer to MEDCouplingStructuredMesh held by \a this. 
4346  *  \param [in] meshDimRelToMax - it must be \c 0.
4347  *  \param [in] renum - it must be \c false.
4348  *  \return MEDCouplingMesh * - a pointer to MEDCouplingMesh that the caller is to
4349  *          delete using decrRef() as it is no more needed. 
4350  */
4351 MEDCouplingMesh *MEDFileStructuredMesh::getGenMeshAtLevel(int meshDimRelToMax, bool renum) const throw(INTERP_KERNEL::Exception)
4352 {
4353   if(renum)
4354     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support renumbering ! To do it perform request of renum array directly !");
4355   if(meshDimRelToMax!=0)
4356     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support multi level for mesh 0 expected as input !");
4357   const MEDCouplingStructuredMesh *m=getStructuredMesh();
4358   if(m)
4359     m->incrRef();
4360   return const_cast<MEDCouplingStructuredMesh *>(m);
4361 }
4362
4363 /*!
4364  * Returns number of mesh entities of a given relative dimension in \a this mesh.
4365  *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
4366  *  \return int - the number of entities.
4367  *  \throw If no mesh entities of dimension \a meshDimRelToMaxExt are available in \a this mesh.
4368  */
4369 int MEDFileStructuredMesh::getSizeAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
4370 {
4371   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4372     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : Only available for levels 0 or 1 !");
4373   const MEDCouplingStructuredMesh *cmesh=getStructuredMesh();
4374   if(!cmesh)
4375     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : No structured mesh set !");
4376   if(meshDimRelToMaxExt==0)
4377     return cmesh->getNumberOfCells();
4378   else
4379     return cmesh->getNumberOfNodes();
4380 }
4381
4382 int MEDFileStructuredMesh::getNumberOfNodes() const throw(INTERP_KERNEL::Exception)
4383 {
4384   const MEDCouplingStructuredMesh *cmesh=getStructuredMesh();
4385   if(!cmesh)
4386     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberOfNodes : no cartesian mesh set !");
4387   return cmesh->getNumberOfNodes();
4388 }
4389
4390 void MEDFileStructuredMesh::whichAreNodesFetched(const MEDFileField1TSStructItem& st, const MEDFileFieldGlobsReal *globs, std::vector<bool>& nodesFetched) const throw(INTERP_KERNEL::Exception)
4391 {
4392   if(st.getNumberOfItems()!=1)
4393     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 !");
4394   if(st[0].getGeo()!=MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(getMeshDimension()))
4395     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : The sturture of field is not lying on expected geo type !");
4396   if(getNumberOfNodes()!=(int)nodesFetched.size())
4397     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : invalid size of array !");
4398   if(st[0].getPflName().empty())
4399     {
4400       std::fill(nodesFetched.begin(),nodesFetched.end(),true);
4401       return ;
4402     }
4403   const DataArrayInt *arr(globs->getProfile(st[0].getPflName().c_str()));
4404   const MEDCouplingStructuredMesh *cmesh=getStructuredMesh();//cmesh not null because getNumberOfNodes called before
4405   int sz(nodesFetched.size());
4406   for(const int *work=arr->begin();work!=arr->end();work++)
4407     {
4408       std::vector<int> conn;
4409       cmesh->getNodeIdsOfCell(*work,conn);
4410       for(std::vector<int>::const_iterator it=conn.begin();it!=conn.end();it++)
4411         if(*it>=0 && *it<sz)
4412           nodesFetched[*it]=true;
4413         else
4414           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : internal error !");
4415     }
4416 }
4417
4418 med_geometry_type MEDFileStructuredMesh::GetGeoTypeFromMeshDim(int meshDim) throw(INTERP_KERNEL::Exception)
4419 {
4420   med_geometry_type geoTypeReq=MED_NONE;
4421   switch(meshDim)
4422     {
4423     case 3:
4424       geoTypeReq=MED_HEXA8;
4425       break;
4426     case 2:
4427       geoTypeReq=MED_QUAD4;
4428       break;
4429     case 1:
4430       geoTypeReq=MED_SEG2;
4431       break;
4432     case 0:
4433       geoTypeReq=MED_POINT1;
4434       break;
4435     default:
4436       throw INTERP_KERNEL::Exception("Invalid meshdim detected for structured mesh ! Must be in (1,2,3) !");
4437     }
4438   return geoTypeReq;
4439 }
4440
4441 void MEDFileStructuredMesh::loadStrMeshFromFile(MEDFileStrMeshL2 *strm, med_idt fid, const char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception)
4442 {
4443   setName(strm->getName());
4444   setDescription(strm->getDescription());
4445   setUnivName(strm->getUnivName());
4446   setIteration(strm->getIteration());
4447   setOrder(strm->getOrder());
4448   setTimeValue(strm->getTime());
4449   setTimeUnit(strm->getTimeUnit());
4450   MEDFileMeshL2::ReadFamiliesAndGrps(fid,mName,_families,_groups,mrs);
4451   med_bool chgt=MED_FALSE,trsf=MED_FALSE;
4452   int nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_NODE,MED_NONE,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf);
4453   if(nbOfElt>0)
4454     {
4455       if(!mrs || mrs->isNodeFamilyFieldReading())
4456         {
4457           _fam_nodes=DataArrayInt::New();
4458           _fam_nodes->alloc(nbOfElt,1);
4459           MEDmeshEntityFamilyNumberRd(fid,mName,dt,it,MED_NODE,MED_NONE,_fam_nodes->getPointer());
4460         }
4461     }
4462   nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_NODE,MED_NONE,MED_NUMBER,MED_NODAL,&chgt,&trsf);
4463   if(nbOfElt>0)
4464     {
4465       if(!mrs || mrs->isNodeNumFieldReading())
4466         {
4467           _num_nodes=DataArrayInt::New();
4468           _num_nodes->alloc(nbOfElt,1);
4469           MEDmeshEntityNumberRd(fid,mName,dt,it,MED_NODE,MED_NONE,_num_nodes->getPointer());
4470         }
4471     }
4472   int meshDim=getStructuredMesh()->getMeshDimension();
4473   med_geometry_type geoTypeReq=GetGeoTypeFromMeshDim(meshDim);
4474   nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_CELL,geoTypeReq,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf);
4475   if(nbOfElt>0)
4476     {
4477       if(!mrs || mrs->isCellFamilyFieldReading())
4478         {
4479           _fam_cells=DataArrayInt::New();
4480           _fam_cells->alloc(nbOfElt,1);
4481           MEDmeshEntityFamilyNumberRd(fid,mName,dt,it,MED_CELL,geoTypeReq,_fam_cells->getPointer());
4482         }
4483     }
4484   nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_CELL,geoTypeReq,MED_NUMBER,MED_NODAL,&chgt,&trsf);
4485   if(nbOfElt>0)
4486     {
4487       if(!mrs || mrs->isCellNumFieldReading())
4488         {
4489           _num_cells=DataArrayInt::New();
4490           _num_cells->alloc(nbOfElt,1);
4491           MEDmeshEntityNumberRd(fid,mName,dt,it,MED_CELL,geoTypeReq,_num_cells->getPointer());
4492         }
4493     }
4494   nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_CELL,geoTypeReq,MED_NAME,MED_NODAL,&chgt,&trsf);
4495   if(nbOfElt>0)
4496     {
4497       if(!mrs || mrs->isCellNameFieldReading())
4498         {
4499           _names_cells=DataArrayAsciiChar::New();
4500           _names_cells->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end
4501           MEDmeshEntityNameRd(fid,mName,dt,it,MED_CELL,geoTypeReq,_names_cells->getPointer());
4502           _names_cells->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end
4503         }
4504     }
4505   nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_NODE,MED_NONE,MED_NAME,MED_NODAL,&chgt,&trsf);
4506   if(nbOfElt>0)
4507     {
4508       if(!mrs || mrs->isNodeNameFieldReading())
4509         {
4510           _names_nodes=DataArrayAsciiChar::New();
4511           _names_nodes->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end
4512           MEDmeshEntityNameRd(fid,mName,dt,it,MED_NODE,MED_NONE,_names_nodes->getPointer());
4513           _names_nodes->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end
4514         }
4515     }
4516 }
4517
4518 void MEDFileStructuredMesh::writeStructuredLL(med_idt fid, const char *maa) const throw(INTERP_KERNEL::Exception)
4519 {
4520   int meshDim=getStructuredMesh()->getMeshDimension();
4521   med_geometry_type geoTypeReq=GetGeoTypeFromMeshDim(meshDim);
4522   //
4523   if((const DataArrayInt *)_fam_cells)
4524     MEDmeshEntityFamilyNumberWr(fid,maa,_iteration,_order,MED_CELL,geoTypeReq,_fam_cells->getNumberOfTuples(),_fam_cells->getConstPointer());
4525   if((const DataArrayInt *)_fam_nodes)
4526     MEDmeshEntityFamilyNumberWr(fid,maa,_iteration,_order,MED_NODE,MED_NONE,_fam_nodes->getNumberOfTuples(),_fam_nodes->getConstPointer());
4527   if((const DataArrayInt *)_num_cells)
4528     MEDmeshEntityNumberWr(fid,maa,_iteration,_order,MED_CELL,geoTypeReq,_num_cells->getNumberOfTuples(),_num_cells->getConstPointer());
4529   if((const DataArrayInt *)_num_nodes)
4530     MEDmeshEntityNumberWr(fid,maa,_iteration,_order,MED_NODE,MED_NONE,_num_nodes->getNumberOfTuples(),_num_nodes->getConstPointer());
4531   if((const DataArrayAsciiChar *)_names_cells)
4532     {
4533       if(_names_cells->getNumberOfComponents()!=MED_SNAME_SIZE)
4534         {
4535           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on cells with number of components set to " << MED_SNAME_SIZE;
4536           oss << " ! The array has " << _names_cells->getNumberOfComponents() << " components !";
4537           throw INTERP_KERNEL::Exception(oss.str().c_str());
4538         }
4539       MEDmeshEntityNameWr(fid,maa,_iteration,_order,MED_CELL,geoTypeReq,_names_cells->getNumberOfTuples(),_names_cells->getConstPointer());
4540     }
4541   if((const DataArrayAsciiChar *)_names_nodes)
4542     {
4543       if(_names_nodes->getNumberOfComponents()!=MED_SNAME_SIZE)
4544         {
4545           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on nodes with number of components set to " << MED_SNAME_SIZE;
4546           oss << " ! The array has " << _names_cells->getNumberOfComponents() << " components !";
4547           throw INTERP_KERNEL::Exception(oss.str().c_str());
4548         }
4549       MEDmeshEntityNameWr(fid,maa,_iteration,_order,MED_NODE,MED_NONE,_names_nodes->getNumberOfTuples(),_names_nodes->getConstPointer());
4550     }
4551   //
4552   MEDFileUMeshL2::WriteFamiliesAndGrps(fid,maa,_families,_groups,_too_long_str);
4553 }
4554
4555 /*!
4556  * Returns an empty instance of MEDFileCMesh.
4557  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
4558  *          mesh using decrRef() as it is no more needed. 
4559  */
4560 MEDFileCMesh *MEDFileCMesh::New()
4561 {
4562   return new MEDFileCMesh;
4563 }
4564
4565 /*!
4566  * Returns a new MEDFileCMesh holding the mesh data that has been read from a given MED
4567  * file. The first mesh in the file is loaded.
4568  *  \param [in] fileName - the name of MED file to read.
4569  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
4570  *          mesh using decrRef() as it is no more needed. 
4571  *  \throw If the file is not readable.
4572  *  \throw If there is no meshes in the file.
4573  *  \throw If the mesh in the file is not a Cartesian one.
4574  */
4575 MEDFileCMesh *MEDFileCMesh::New(const char *fileName, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception)
4576 {
4577   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
4578   if(ms.empty())
4579     {
4580       std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
4581       throw INTERP_KERNEL::Exception(oss.str().c_str());
4582     }
4583   MEDFileUtilities::CheckFileForRead(fileName);
4584   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
4585   int dt,it;
4586   ParaMEDMEM::MEDCouplingMeshType meshType;
4587   std::string dummy2;
4588   MEDFileMeshL2::GetMeshIdFromName(fid,ms.front().c_str(),meshType,dt,it,dummy2);
4589   return new MEDFileCMesh(fid,ms.front().c_str(),dt,it,mrs);
4590 }
4591
4592 /*!
4593  * Returns a new MEDFileCMesh holding the mesh data that has been read from a given MED
4594  * file. The mesh to load is specified by its name and numbers of a time step and an
4595  * iteration.
4596  *  \param [in] fileName - the name of MED file to read.
4597  *  \param [in] mName - the name of the mesh to read.
4598  *  \param [in] dt - the number of a time step.
4599  *  \param [in] it - the number of an iteration.
4600  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
4601  *          mesh using decrRef() as it is no more needed. 
4602  *  \throw If the file is not readable.
4603  *  \throw If there is no mesh with given attributes in the file.
4604  *  \throw If the mesh in the file is not a Cartesian one.
4605  */
4606 MEDFileCMesh *MEDFileCMesh::New(const char *fileName, const char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception)
4607 {
4608   MEDFileUtilities::CheckFileForRead(fileName);
4609   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
4610   return new MEDFileCMesh(fid,mName,dt,it,mrs);
4611 }
4612
4613 std::size_t MEDFileCMesh::getHeapMemorySizeWithoutChildren() const
4614 {
4615   return MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren();
4616 }
4617
4618 std::vector<RefCountObject *> MEDFileCMesh::getDirectChildren() const
4619 {
4620   std::vector<RefCountObject *> ret(MEDFileStructuredMesh::getDirectChildren());
4621   if((const MEDCouplingCMesh *)_cmesh)
4622     ret.push_back(const_cast<MEDCouplingCMesh *>((const MEDCouplingCMesh *)_cmesh));
4623   return ret;
4624 }
4625
4626 /*!
4627  * Returns the dimension on cells in \a this mesh.
4628  *  \return int - the mesh dimension.
4629  *  \throw If there are no cells in this mesh.
4630  */
4631 int MEDFileCMesh::getMeshDimension() const throw(INTERP_KERNEL::Exception)
4632 {
4633   if(!((const MEDCouplingCMesh*)_cmesh))
4634     throw INTERP_KERNEL::Exception("MEDFileCMesh::getMeshDimension : unable to get meshdimension because no mesh set !");
4635   return _cmesh->getMeshDimension();
4636 }
4637
4638 /*!
4639  * Returns a string describing \a this mesh.
4640  *  \return std::string - the mesh information string.
4641  */
4642 std::string MEDFileCMesh::simpleRepr() const
4643 {
4644   return MEDFileStructuredMesh::simpleRepr();
4645 }
4646
4647 /*!
4648  * Returns a full textual description of \a this mesh.
4649  *  \return std::string - the string holding the mesh description.
4650  */
4651 std::string MEDFileCMesh::advancedRepr() const
4652 {
4653   return simpleRepr();
4654 }
4655
4656 MEDFileMesh *MEDFileCMesh::shallowCpy() const throw(INTERP_KERNEL::Exception)
4657 {
4658   MEDCouplingAutoRefCountObjectPtr<MEDFileCMesh> ret=new MEDFileCMesh(*this);
4659   return ret.retn();
4660 }
4661
4662 MEDFileMesh *MEDFileCMesh::createNewEmpty() const throw(INTERP_KERNEL::Exception)
4663 {
4664   return new MEDFileCMesh;
4665 }
4666
4667 MEDFileMesh *MEDFileCMesh::deepCpy() const throw(INTERP_KERNEL::Exception)
4668 {
4669   MEDCouplingAutoRefCountObjectPtr<MEDFileCMesh> ret=new MEDFileCMesh(*this);
4670   if((const MEDCouplingCMesh*)_cmesh)
4671     ret->_cmesh=static_cast<MEDCouplingCMesh*>(_cmesh->deepCpy());
4672   ret->deepCpyAttributes();
4673   return ret.retn();
4674 }
4675
4676 /*!
4677  * Checks if \a this and another mesh are equal.
4678  *  \param [in] other - the mesh to compare with.
4679  *  \param [in] eps - a precision used to compare real values.
4680  *  \param [in,out] what - the string returning description of unequal data.
4681  *  \return bool - \c true if the meshes are equal, \c false, else.
4682  */
4683 bool MEDFileCMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
4684 {
4685   if(!MEDFileStructuredMesh::isEqual(other,eps,what))
4686     return false;
4687   const MEDFileCMesh *otherC=dynamic_cast<const MEDFileCMesh *>(other);
4688   if(!otherC)
4689     {
4690       what="Mesh types differ ! This is cartesian and other is NOT !";
4691       return false;
4692     }
4693   clearNonDiscrAttributes();
4694   otherC->clearNonDiscrAttributes();
4695   const MEDCouplingCMesh *coo1=_cmesh;
4696   const MEDCouplingCMesh *coo2=otherC->_cmesh;
4697   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
4698     {
4699       what="Mismatch of cartesian meshes ! One is defined and not other !";
4700       return false;
4701     }
4702   if(coo1)
4703     {
4704       bool ret=coo1->isEqual(coo2,eps);
4705       if(!ret)
4706         {
4707           what="cartesian meshes differ !";
4708           return false;
4709         }
4710     }
4711   return true;
4712 }
4713
4714 /*!
4715  * Clears redundant attributes of incorporated data arrays.
4716  */
4717 void MEDFileCMesh::clearNonDiscrAttributes() const
4718 {
4719   MEDFileStructuredMesh::clearNonDiscrAttributes();
4720   MEDFileUMeshSplitL1::ClearNonDiscrAttributes(_cmesh);//to it is not a bug umeshsplit have already the method implemented
4721 }
4722
4723 MEDFileCMesh::MEDFileCMesh()
4724 {
4725 }
4726
4727 MEDFileCMesh::MEDFileCMesh(med_idt fid, const char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception)
4728 try
4729   {
4730     loadCMeshFromFile(fid,mName,dt,it,mrs);
4731   }
4732 catch(INTERP_KERNEL::Exception& e)
4733   {
4734     throw e;
4735   }
4736
4737 void MEDFileCMesh::loadCMeshFromFile(med_idt fid, const char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception)
4738 {
4739   ParaMEDMEM::MEDCouplingMeshType meshType;
4740   int dummy0,dummy1;
4741   std::string dtunit;
4742   int mid=MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dtunit);
4743   if(meshType!=CARTESIAN)
4744     {
4745       std::ostringstream oss; oss << "Trying to load as cartesian an existing mesh with name '" << mName << "' that is NOT cartesian !";
4746       throw INTERP_KERNEL::Exception(oss.str().c_str());
4747     }
4748   MEDFileCMeshL2 loaderl2;
4749   loaderl2.loadAll(fid,mid,mName,dt,it);
4750   MEDCouplingCMesh *mesh=loaderl2.getMesh();
4751   mesh->incrRef();
4752   _cmesh=mesh;
4753   loadStrMeshFromFile(&loaderl2,fid,mName,dt,it,mrs);
4754 }
4755
4756 /*!
4757  * Returns a const pointer to MEDCouplingCMesh held by \a this mesh.
4758  *  \return const MEDCouplingCMesh * - a pointer to the held MEDCouplingCMesh.
4759  */
4760 const MEDCouplingCMesh *MEDFileCMesh::getMesh() const
4761 {
4762   synchronizeTinyInfoOnLeaves();
4763   return _cmesh;
4764 }
4765
4766 const MEDCouplingStructuredMesh *MEDFileCMesh::getStructuredMesh() const
4767 {
4768   synchronizeTinyInfoOnLeaves();
4769   return _cmesh;
4770 }
4771
4772 /*!
4773  * Sets the MEDCouplingCMesh holding the data of \a this mesh.
4774  *  \param [in] m - the new MEDCouplingCMesh to refer to.
4775  *  \throw If the name or the description of \a this mesh and \a m are not empty and are
4776  *         different. 
4777  */
4778 void MEDFileCMesh::setMesh(MEDCouplingCMesh *m) throw(INTERP_KERNEL::Exception)
4779 {
4780   dealWithTinyInfo(m);
4781   if(m)
4782     m->incrRef();
4783   _cmesh=m;
4784 }
4785
4786 void MEDFileCMesh::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception)
4787 {
4788   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
4789   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
4790   INTERP_KERNEL::AutoPtr<char> dtunit=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE);
4791   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
4792   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
4793   MEDLoaderBase::safeStrCpy(_dt_unit.c_str(),MED_LNAME_SIZE,dtunit,_too_long_str);
4794   int spaceDim=_cmesh->getSpaceDimension();
4795   int meshDim=_cmesh->getMeshDimension();
4796   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
4797   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
4798   for(int i=0;i<spaceDim;i++)
4799     {
4800       std::string info(_cmesh->getCoordsAt(i)->getInfoOnComponent(0));
4801       std::string c,u;
4802       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
4803       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
4804       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
4805     }
4806   MEDmeshCr(fid,maa,spaceDim,meshDim,MED_STRUCTURED_MESH,desc,dtunit,MED_SORT_DTIT,MED_CARTESIAN,comp,unit);
4807   MEDmeshUniversalNameWr(fid,maa);
4808   MEDmeshGridTypeWr(fid,maa,MED_CARTESIAN_GRID);
4809   for(int i=0;i<spaceDim;i++)
4810     {
4811       const DataArrayDouble *da=_cmesh->getCoordsAt(i);
4812       MEDmeshGridIndexCoordinateWr(fid,maa,_iteration,_order,_time,i+1,da->getNumberOfTuples(),da->getConstPointer());
4813     }
4814   //
4815   MEDFileStructuredMesh::writeStructuredLL(fid,maa);
4816 }
4817
4818 void MEDFileCMesh::synchronizeTinyInfoOnLeaves() const
4819 {
4820   const MEDCouplingCMesh *cmesh=_cmesh;
4821   if(!cmesh)
4822     return;
4823   (const_cast<MEDCouplingCMesh *>(cmesh))->setName(_name.c_str());
4824   (const_cast<MEDCouplingCMesh *>(cmesh))->setDescription(_desc_name.c_str());
4825   (const_cast<MEDCouplingCMesh *>(cmesh))->setTime(_time,_iteration,_order);
4826   (const_cast<MEDCouplingCMesh *>(cmesh))->setTimeUnit(_dt_unit.c_str());
4827 }
4828
4829 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New()
4830 {
4831   return new MEDFileCurveLinearMesh;
4832 }
4833
4834 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const char *fileName, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception)
4835 {
4836   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
4837   if(ms.empty())
4838     {
4839       std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
4840       throw INTERP_KERNEL::Exception(oss.str().c_str());
4841     }
4842   MEDFileUtilities::CheckFileForRead(fileName);
4843   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
4844   int dt,it;
4845   ParaMEDMEM::MEDCouplingMeshType meshType;
4846   std::string dummy2;
4847   MEDFileMeshL2::GetMeshIdFromName(fid,ms.front().c_str(),meshType,dt,it,dummy2);
4848   return new MEDFileCurveLinearMesh(fid,ms.front().c_str(),dt,it,mrs);
4849 }
4850
4851 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const char *fileName, const char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception)
4852 {
4853   MEDFileUtilities::CheckFileForRead(fileName);
4854   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
4855   return new MEDFileCurveLinearMesh(fid,mName,dt,it,mrs);
4856 }
4857
4858 std::size_t MEDFileCurveLinearMesh::getHeapMemorySizeWithoutChildren() const
4859 {
4860   return MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren();
4861 }
4862
4863 std::vector<RefCountObject *> MEDFileCurveLinearMesh::getDirectChildren() const
4864 {
4865   std::vector<RefCountObject *> ret(MEDFileStructuredMesh::getDirectChildren());
4866   if((const MEDCouplingCurveLinearMesh *)_clmesh)
4867     ret.push_back(const_cast<MEDCouplingCurveLinearMesh *>((const MEDCouplingCurveLinearMesh *)_clmesh));
4868   return ret;
4869 }
4870
4871 MEDFileMesh *MEDFileCurveLinearMesh::shallowCpy() const throw(INTERP_KERNEL::Exception)
4872 {
4873   MEDCouplingAutoRefCountObjectPtr<MEDFileCurveLinearMesh> ret=new MEDFileCurveLinearMesh(*this);
4874   return ret.retn();
4875 }
4876
4877 MEDFileMesh *MEDFileCurveLinearMesh::createNewEmpty() const throw(INTERP_KERNEL::Exception)
4878 {
4879   return new MEDFileCurveLinearMesh;
4880 }
4881
4882 MEDFileMesh *MEDFileCurveLinearMesh::deepCpy() const throw(INTERP_KERNEL::Exception)
4883 {
4884   MEDCouplingAutoRefCountObjectPtr<MEDFileCurveLinearMesh> ret=new MEDFileCurveLinearMesh(*this);
4885   if((const MEDCouplingCurveLinearMesh*)_clmesh)
4886     ret->_clmesh=static_cast<MEDCouplingCurveLinearMesh*>(_clmesh->deepCpy());
4887   ret->deepCpyAttributes();
4888   return ret.retn();
4889 }
4890
4891 int MEDFileCurveLinearMesh::getMeshDimension() const throw(INTERP_KERNEL::Exception)
4892 {
4893   if(!((const MEDCouplingCurveLinearMesh*)_clmesh))
4894     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::getMeshDimension : unable to get meshdimension because no mesh set !");
4895   return _clmesh->getMeshDimension();
4896 }
4897
4898 std::string MEDFileCurveLinearMesh::simpleRepr() const
4899 {
4900   return MEDFileStructuredMesh::simpleRepr();
4901 }
4902
4903 std::string MEDFileCurveLinearMesh::advancedRepr() const
4904 {
4905   return simpleRepr();
4906 }
4907
4908 bool MEDFileCurveLinearMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
4909 {
4910   if(!MEDFileStructuredMesh::isEqual(other,eps,what))
4911     return false;
4912   const MEDFileCurveLinearMesh *otherC=dynamic_cast<const MEDFileCurveLinearMesh *>(other);
4913   if(!otherC)
4914     {
4915       what="Mesh types differ ! This is curve linear and other is NOT !";
4916       return false;
4917     }
4918   clearNonDiscrAttributes();
4919   otherC->clearNonDiscrAttributes();
4920   const MEDCouplingCurveLinearMesh *coo1=_clmesh;
4921   const MEDCouplingCurveLinearMesh *coo2=otherC->_clmesh;
4922   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
4923     {
4924       what="Mismatch of curve linear meshes ! One is defined and not other !";
4925       return false;
4926     }
4927   if(coo1)
4928     {
4929       bool ret=coo1->isEqual(coo2,eps);
4930       if(!ret)
4931         {
4932           what="curve linear meshes differ !";
4933           return false;
4934         }
4935     }
4936   return true;
4937 }
4938
4939 void MEDFileCurveLinearMesh::clearNonDiscrAttributes() const
4940 {
4941   MEDFileStructuredMesh::clearNonDiscrAttributes();
4942   MEDFileUMeshSplitL1::ClearNonDiscrAttributes(_clmesh);//to it is not a bug umeshsplit have already the method implemented
4943 }
4944
4945 void MEDFileCurveLinearMesh::synchronizeTinyInfoOnLeaves() const
4946 {
4947   const MEDCouplingCurveLinearMesh *clmesh=_clmesh;
4948   if(!clmesh)
4949     return;
4950   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setName(_name.c_str());
4951   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setDescription(_desc_name.c_str());
4952   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setTime(_time,_iteration,_order);
4953   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setTimeUnit(_dt_unit.c_str());
4954 }
4955
4956 const MEDCouplingCurveLinearMesh *MEDFileCurveLinearMesh::getMesh() const
4957 {
4958   synchronizeTinyInfoOnLeaves();
4959   return _clmesh;
4960 }
4961
4962 void MEDFileCurveLinearMesh::setMesh(MEDCouplingCurveLinearMesh *m) throw(INTERP_KERNEL::Exception)
4963 {
4964   dealWithTinyInfo(m);
4965   if(m)
4966     m->incrRef();
4967   _clmesh=m;
4968 }
4969
4970 const MEDCouplingStructuredMesh *MEDFileCurveLinearMesh::getStructuredMesh() const
4971 {
4972   synchronizeTinyInfoOnLeaves();
4973   return _clmesh;
4974 }
4975
4976 MEDFileCurveLinearMesh::MEDFileCurveLinearMesh()
4977 {
4978 }
4979
4980 MEDFileCurveLinearMesh::MEDFileCurveLinearMesh(med_idt fid, const char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception)
4981 try
4982   {
4983     loadCLMeshFromFile(fid,mName,dt,it,mrs);
4984   }
4985 catch(INTERP_KERNEL::Exception& e)
4986   {
4987     throw e;
4988   }
4989
4990 void MEDFileCurveLinearMesh::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception)
4991 {
4992   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
4993   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
4994   INTERP_KERNEL::AutoPtr<char> dtunit=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE);
4995   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
4996   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
4997   MEDLoaderBase::safeStrCpy(_dt_unit.c_str(),MED_LNAME_SIZE,dtunit,_too_long_str);
4998   int spaceDim=_clmesh->getSpaceDimension();
4999   int meshDim=_clmesh->getMeshDimension();
5000   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
5001   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
5002   const DataArrayDouble *coords=_clmesh->getCoords();
5003   if(!coords)
5004     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::writeLL : no coordinates set !");
5005   for(int i=0;i<spaceDim;i++)
5006     {
5007       std::string info(_clmesh->getCoords()->getInfoOnComponent(i));
5008       std::string c,u;
5009       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
5010       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
5011       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
5012     }
5013   MEDmeshCr(fid,maa,spaceDim,meshDim,MED_STRUCTURED_MESH,desc,dtunit,MED_SORT_DTIT,MED_CARTESIAN,comp,unit);
5014   MEDmeshUniversalNameWr(fid,maa);
5015   MEDmeshGridTypeWr(fid,maa,MED_CURVILINEAR_GRID);
5016   std::vector<int> nodeGridSt=_clmesh->getNodeGridStructure();
5017   MEDmeshGridStructWr(fid,maa,_iteration,_order,_time,&nodeGridSt[0]);
5018   
5019   MEDmeshNodeCoordinateWr(fid,maa,_iteration,_order,_time,MED_FULL_INTERLACE,coords->getNumberOfTuples(),coords->begin());
5020   //
5021   MEDFileStructuredMesh::writeStructuredLL(fid,maa);
5022 }
5023
5024 void MEDFileCurveLinearMesh::loadCLMeshFromFile(med_idt fid, const char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception)
5025 {
5026   ParaMEDMEM::MEDCouplingMeshType meshType;
5027   int dummy0,dummy1;
5028   std::string dtunit;
5029   int mid=MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dtunit);
5030   if(meshType!=CURVE_LINEAR)
5031     {
5032       std::ostringstream oss; oss << "Trying to load as curve linear an existing mesh with name '" << mName << "' that is NOT curve linear !";
5033       throw INTERP_KERNEL::Exception(oss.str().c_str());
5034     }
5035   MEDFileCLMeshL2 loaderl2;
5036   loaderl2.loadAll(fid,mid,mName,dt,it);
5037   MEDCouplingCurveLinearMesh *mesh=loaderl2.getMesh();
5038   mesh->incrRef();
5039   _clmesh=mesh;
5040   loadStrMeshFromFile(&loaderl2,fid,mName,dt,it,mrs);
5041 }
5042
5043 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New()
5044 {
5045   return new MEDFileMeshMultiTS;
5046 }
5047
5048 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(const char *fileName) throw(INTERP_KERNEL::Exception)
5049 {
5050   return new MEDFileMeshMultiTS(fileName);
5051 }
5052
5053 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(const char *fileName, const char *mName) throw(INTERP_KERNEL::Exception)
5054 {
5055   return new MEDFileMeshMultiTS(fileName,mName);
5056 }
5057
5058 MEDFileMeshMultiTS *MEDFileMeshMultiTS::deepCpy() const throw(INTERP_KERNEL::Exception)
5059 {
5060   MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> ret=MEDFileMeshMultiTS::New();
5061   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> > meshOneTs(_mesh_one_ts.size());
5062   std::size_t i=0;
5063   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++,i++)
5064     if((const MEDFileMesh *)*it)
5065       meshOneTs[i]=(*it)->deepCpy();
5066   ret->_mesh_one_ts=meshOneTs;
5067   return ret.retn();
5068 }
5069
5070 std::size_t MEDFileMeshMultiTS::getHeapMemorySizeWithoutChildren() const
5071 {
5072   return _mesh_one_ts.capacity()*sizeof(MEDCouplingAutoRefCountObjectPtr<MEDFileMesh>);
5073 }
5074
5075 std::vector<RefCountObject *> MEDFileMeshMultiTS::getDirectChildren() const
5076 {
5077   std::vector<RefCountObject *> ret;
5078   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
5079     {
5080       const MEDFileMesh *cur(*it);
5081       if(cur)
5082         ret.push_back(const_cast<MEDFileMesh *>(cur));
5083     }
5084   return ret;
5085 }
5086
5087 std::string MEDFileMeshMultiTS::getName() const throw(INTERP_KERNEL::Exception)
5088 {
5089   if(_mesh_one_ts.empty())
5090     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::getName : no time steps set !");
5091   return _mesh_one_ts[0]->getName();
5092 }
5093
5094 void MEDFileMeshMultiTS::setName(const char *newMeshName) throw(INTERP_KERNEL::Exception)
5095 {
5096   std::string oldName(getName());
5097   std::vector< std::pair<std::string,std::string> > v(1);
5098   v[0].first=oldName; v[0].second=newMeshName;
5099   changeNames(v);
5100 }
5101
5102 bool MEDFileMeshMultiTS::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab) throw(INTERP_KERNEL::Exception)
5103 {
5104   bool ret=false;
5105   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
5106     {
5107       MEDFileMesh *cur(*it);
5108       if(cur)
5109         ret=cur->changeNames(modifTab) || ret;
5110     }
5111   return ret;
5112 }
5113
5114 MEDFileMesh *MEDFileMeshMultiTS::getOneTimeStep() const throw(INTERP_KERNEL::Exception)
5115 {
5116   if(_mesh_one_ts.empty())
5117     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::getOneTimeStep : empty time step set !");
5118   return const_cast<MEDFileMesh *>(static_cast<const MEDFileMesh *>(_mesh_one_ts[0]));
5119 }
5120
5121 void MEDFileMeshMultiTS::setOneTimeStep(MEDFileMesh *mesh1TimeStep) throw(INTERP_KERNEL::Exception)
5122 {
5123   if(!mesh1TimeStep)
5124     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::setOneTimeStep : input pointer should be different from 0 !");
5125   _mesh_one_ts.resize(1);
5126   mesh1TimeStep->incrRef();
5127   //MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> toto=mesh1TimeStep;
5128   _mesh_one_ts[0]=mesh1TimeStep;
5129 }
5130
5131 void MEDFileMeshMultiTS::write(med_idt fid) const throw(INTERP_KERNEL::Exception)
5132 {
5133   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
5134     {
5135       (*it)->copyOptionsFrom(*this);
5136       (*it)->write(fid);
5137     }
5138 }
5139
5140 void MEDFileMeshMultiTS::write(const char *fileName, int mode) const throw(INTERP_KERNEL::Exception)
5141 {
5142   med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode);
5143   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,medmod);
5144   std::ostringstream oss; oss << "MEDFileMesh : error on attempt to write in file : \"" << fileName << "\""; 
5145   MEDFileUtilities::CheckMEDCode(fid,fid,oss.str().c_str());
5146   write(fid);
5147 }
5148
5149 void MEDFileMeshMultiTS::loadFromFile(const char *fileName, const char *mName) throw(INTERP_KERNEL::Exception)
5150 {//for the moment to be improved
5151   _mesh_one_ts.resize(1);
5152   _mesh_one_ts[0]=MEDFileMesh::New(fileName,mName,-1,-1);
5153 }
5154
5155 MEDFileMeshMultiTS::MEDFileMeshMultiTS()
5156 {
5157 }
5158
5159 MEDFileMeshMultiTS::MEDFileMeshMultiTS(const char *fileName) throw(INTERP_KERNEL::Exception)
5160 try
5161   {
5162     std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
5163     if(ms.empty())
5164     {
5165       std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
5166       throw INTERP_KERNEL::Exception(oss.str().c_str());
5167     }
5168     MEDFileUtilities::CheckFileForRead(fileName);
5169     MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
5170     int dt,it;
5171     ParaMEDMEM::MEDCouplingMeshType meshType;
5172     std::string dummy2;
5173     MEDFileMeshL2::GetMeshIdFromName(fid,ms.front().c_str(),meshType,dt,it,dummy2);
5174     loadFromFile(fileName,ms.front().c_str());
5175   }
5176 catch(INTERP_KERNEL::Exception& e)
5177   {
5178     throw e;
5179   }
5180
5181 MEDFileMeshMultiTS::MEDFileMeshMultiTS(const char *fileName, const char *mName) throw(INTERP_KERNEL::Exception)
5182 try
5183   {
5184     loadFromFile(fileName,mName);
5185   }
5186 catch(INTERP_KERNEL::Exception& e)
5187   {
5188     throw e;
5189   }
5190
5191 MEDFileMeshes *MEDFileMeshes::New()
5192 {
5193   return new MEDFileMeshes;
5194 }
5195
5196 MEDFileMeshes *MEDFileMeshes::New(const char *fileName) throw(INTERP_KERNEL::Exception)
5197 {
5198   return new MEDFileMeshes(fileName);
5199 }
5200
5201 void MEDFileMeshes::write(med_idt fid) const throw(INTERP_KERNEL::Exception)
5202 {
5203   checkCoherency();
5204   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++)
5205     {
5206       (*it)->copyOptionsFrom(*this);
5207       (*it)->write(fid);
5208     }
5209 }
5210
5211 void MEDFileMeshes::write(const char *fileName, int mode) const throw(INTERP_KERNEL::Exception)
5212 {
5213   med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode);
5214   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,medmod);
5215   std::ostringstream oss; oss << "MEDFileMesh : error on attempt to write in file : \"" << fileName << "\""; 
5216   MEDFileUtilities::CheckMEDCode(fid,fid,oss.str().c_str());
5217   checkCoherency();
5218   write(fid);
5219 }
5220
5221 int MEDFileMeshes::getNumberOfMeshes() const throw(INTERP_KERNEL::Exception)
5222 {
5223   return _meshes.size();
5224 }
5225
5226 MEDFileMeshesIterator *MEDFileMeshes::iterator() throw(INTERP_KERNEL::Exception)
5227 {
5228   return new MEDFileMeshesIterator(this);
5229 }
5230
5231 MEDFileMesh *MEDFileMeshes::getMeshAtPos(int i) const throw(INTERP_KERNEL::Exception)
5232 {
5233   if(i<0 || i>=(int)_meshes.size())
5234     {
5235       std::ostringstream oss; oss << "MEDFileMeshes::getMeshAtPos : invalid mesh id given in parameter ! Should be in [0;" << _meshes.size() << ") !";
5236       throw INTERP_KERNEL::Exception(oss.str().c_str());
5237     }
5238   return _meshes[i]->getOneTimeStep();
5239 }
5240
5241 MEDFileMesh *MEDFileMeshes::getMeshWithName(const char *mname) const throw(INTERP_KERNEL::Exception)
5242 {
5243   std::vector<std::string> ms=getMeshesNames();
5244   std::vector<std::string>::iterator it=std::find(ms.begin(),ms.end(),mname);
5245   if(it==ms.end())
5246     {
5247       std::ostringstream oss; oss << "MEDFileMeshes::getMeshWithName : Mesh  \"" << mname << "\" does not exist in this ! Existing are : ";
5248       std::copy(ms.begin(),ms.end(),std::ostream_iterator<std::string>(oss," "));
5249       throw INTERP_KERNEL::Exception(oss.str().c_str());
5250     }
5251   return getMeshAtPos((int)std::distance(ms.begin(),it));
5252 }
5253
5254 std::vector<std::string> MEDFileMeshes::getMeshesNames() const throw(INTERP_KERNEL::Exception)
5255 {
5256   std::vector<std::string> ret(_meshes.size());
5257   int i=0;
5258   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
5259     {
5260       const MEDFileMeshMultiTS *f=(*it);
5261       if(f)
5262         {
5263           ret[i]=f->getName();
5264         }
5265       else
5266         {
5267           std::ostringstream oss; oss << "MEDFileMeshes::getMeshesNames : At rank #" << i << " mesh is not defined !";
5268           throw INTERP_KERNEL::Exception(oss.str().c_str());
5269         }
5270     }
5271   return ret;
5272 }
5273
5274 bool MEDFileMeshes::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab) throw(INTERP_KERNEL::Exception)
5275 {
5276   bool ret=false;
5277   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::iterator it=_meshes.begin();it!=_meshes.end();it++)
5278     {
5279       MEDFileMeshMultiTS *cur(*it);
5280       if(cur)
5281         ret=cur->changeNames(modifTab) || ret;
5282     }
5283   return ret;
5284 }
5285
5286 void MEDFileMeshes::resize(int newSize) throw(INTERP_KERNEL::Exception)
5287 {
5288   _meshes.resize(newSize);
5289 }
5290
5291 void MEDFileMeshes::pushMesh(MEDFileMesh *mesh) throw(INTERP_KERNEL::Exception)
5292 {
5293   if(!mesh)
5294     throw INTERP_KERNEL::Exception("MEDFileMeshes::pushMesh : invalid input pointer ! should be different from 0 !");
5295   MEDFileMeshMultiTS *elt=MEDFileMeshMultiTS::New();
5296   elt->setOneTimeStep(mesh);
5297   _meshes.push_back(elt);
5298 }
5299
5300 void MEDFileMeshes::setMeshAtPos(int i, MEDFileMesh *mesh) throw(INTERP_KERNEL::Exception)
5301 {
5302   if(!mesh)
5303     throw INTERP_KERNEL::Exception("MEDFileMeshes::setMeshAtPos : invalid input pointer ! should be different from 0 !");
5304   if(i>=(int)_meshes.size())
5305     _meshes.resize(i+1);
5306   MEDFileMeshMultiTS *elt=MEDFileMeshMultiTS::New();
5307   elt->setOneTimeStep(mesh);
5308   _meshes[i]=elt;
5309 }
5310
5311 void MEDFileMeshes::destroyMeshAtPos(int i) throw(INTERP_KERNEL::Exception)
5312 {
5313   if(i<0 || i>=(int)_meshes.size())
5314     {
5315       std::ostringstream oss; oss << "MEDFileMeshes::destroyMeshAtPos : Invalid given id in input (" << i << ") should be in [0," << _meshes.size() << ") !";
5316       throw INTERP_KERNEL::Exception(oss.str().c_str());
5317     }
5318   _meshes.erase(_meshes.begin()+i);
5319 }
5320
5321 void MEDFileMeshes::loadFromFile(const char *fileName) throw(INTERP_KERNEL::Exception)
5322 {
5323   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
5324   int i=0;
5325   _meshes.resize(ms.size());
5326   for(std::vector<std::string>::const_iterator it=ms.begin();it!=ms.end();it++,i++)
5327     _meshes[i]=MEDFileMeshMultiTS::New(fileName,(*it).c_str());
5328 }
5329
5330 MEDFileMeshes::MEDFileMeshes()
5331 {
5332 }
5333
5334 MEDFileMeshes::MEDFileMeshes(const char *fileName) throw(INTERP_KERNEL::Exception)
5335 try
5336   {
5337     loadFromFile(fileName);
5338   }
5339 catch(INTERP_KERNEL::Exception& /*e*/)
5340   {
5341   }
5342
5343 MEDFileMeshes *MEDFileMeshes::deepCpy() const throw(INTERP_KERNEL::Exception)
5344 {
5345   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> > meshes(_meshes.size());
5346   std::size_t i=0;
5347   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
5348     if((const MEDFileMeshMultiTS *)*it)
5349       meshes[i]=(*it)->deepCpy();
5350   MEDCouplingAutoRefCountObjectPtr<MEDFileMeshes> ret=MEDFileMeshes::New();
5351   ret->_meshes=meshes;
5352   return ret.retn();
5353 }
5354
5355 std::size_t MEDFileMeshes::getHeapMemorySizeWithoutChildren() const
5356 {
5357   return _meshes.capacity()*(sizeof(MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS>));
5358 }
5359
5360 std::vector<RefCountObject *> MEDFileMeshes::getDirectChildren() const
5361 {
5362   std::vector<RefCountObject *> ret;
5363   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++)
5364     {
5365       const MEDFileMeshMultiTS *cur(*it);
5366       if(cur)
5367         ret.push_back(const_cast<MEDFileMeshMultiTS *>(cur));
5368     }
5369   return ret;
5370 }
5371
5372 std::string MEDFileMeshes::simpleRepr() const
5373 {
5374   std::ostringstream oss;
5375   oss << "(*****************)\n(* MEDFileMeshes *)\n(*****************)\n\n";
5376   simpleReprWithoutHeader(oss);
5377   return oss.str();
5378 }
5379
5380 void MEDFileMeshes::simpleReprWithoutHeader(std::ostream& oss) const
5381 {
5382   int nbOfMeshes=getNumberOfMeshes();
5383   oss << "There are " << nbOfMeshes << " meshes with the following names : \n";
5384   std::vector<std::string> mns=getMeshesNames();
5385   for(int i=0;i<nbOfMeshes;i++)
5386     oss << "  - #" << i << " \"" << mns[i] << "\"\n";
5387 }
5388
5389 void MEDFileMeshes::checkCoherency() const throw(INTERP_KERNEL::Exception)
5390 {
5391   static const char MSG[]="MEDFileMeshes::checkCoherency : mesh at rank ";
5392   int i=0;
5393   std::set<std::string> s;
5394   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
5395     {
5396       const MEDFileMeshMultiTS *elt=(*it);
5397       if(!elt)
5398         {
5399           std::ostringstream oss; oss << MSG << i << "/" << _meshes.size() << " is empty !";
5400           throw INTERP_KERNEL::Exception(oss.str().c_str());
5401         }
5402       std::size_t sz=s.size();
5403       s.insert(std::string((*it)->getName()));
5404       if(s.size()==sz)
5405         {
5406           std::ostringstream oss; oss << MSG << i << " has a name (\"" << (*it)->getName() << "\") already used by an another mesh in list !";
5407           throw INTERP_KERNEL::Exception(oss.str().c_str());
5408         }
5409     }
5410 }
5411
5412 MEDFileMeshesIterator::MEDFileMeshesIterator(MEDFileMeshes *ms):_ms(ms),_iter_id(0),_nb_iter(0)
5413 {
5414   if(ms)
5415     {
5416       ms->incrRef();
5417       _nb_iter=ms->getNumberOfMeshes();
5418     }
5419 }
5420
5421 MEDFileMeshesIterator::~MEDFileMeshesIterator()
5422 {
5423 }
5424
5425 MEDFileMesh *MEDFileMeshesIterator::nextt()
5426 {
5427   if(_iter_id<_nb_iter)
5428     {
5429       MEDFileMeshes *ms(_ms);
5430       if(ms)
5431         return ms->getMeshAtPos(_iter_id++);
5432       else
5433         return 0;
5434     }
5435   else
5436     return 0;
5437 }