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