Salome HOME
615abd7aaace8a0c9bd0483bbbe254288dcb0959
[modules/med.git] / src / MEDLoader / MEDFileMesh.cxx
1 // Copyright (C) 2007-2013  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (CEA/DEN)
20
21 #include "MEDFileMesh.hxx"
22 #include "MEDFileUtilities.hxx"
23 #include "MEDFileFieldOverView.hxx"
24 #include "MEDFileField.hxx"
25 #include "MEDLoader.hxx"
26 #include "MEDLoaderBase.hxx"
27
28 #include "MEDCouplingUMesh.hxx"
29
30 #include "InterpKernelAutoPtr.hxx"
31
32 #include <limits>
33 #include <cmath>
34
35 using namespace ParaMEDMEM;
36
37 const char MEDFileMesh::DFT_FAM_NAME[]="FAMILLE_ZERO";
38
39 MEDFileMesh::MEDFileMesh():_order(-1),_iteration(-1),_time(0.),_univ_wr_status(true)
40 {
41 }
42
43 std::size_t MEDFileMesh::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 void MEDFileMesh::TranslateFamilyIds(int offset, DataArrayInt *famArr, std::vector< std::vector<int> >& famIdsPerGrp)
1742 {
1743   famArr->applyLin(offset>0?1:-1,offset,0);
1744   for(std::vector< std::vector<int> >::iterator it1=famIdsPerGrp.begin();it1!=famIdsPerGrp.end();it1++)
1745     {
1746       if(offset<0)
1747         std::transform((*it1).begin(),(*it1).end(),(*it1).begin(),std::negate<int>());
1748       std::transform((*it1).begin(),(*it1).end(),(*it1).begin(),std::bind2nd(std::plus<int>(),offset));
1749     }
1750 }
1751
1752 /*!
1753  * Warning no check is done on 'nameTry' in parameter. It should be non empty.
1754  * This method returns a name close to 'nameTry' so that it is not already into 'namesToAvoid'.
1755  * If this method fails to find such a name it will throw an exception.
1756  */
1757 std::string MEDFileMesh::CreateNameNotIn(const std::string& nameTry, const std::vector<std::string>& namesToAvoid) throw(INTERP_KERNEL::Exception)
1758 {
1759   //attempt #0
1760   if(std::find(namesToAvoid.begin(),namesToAvoid.end(),nameTry)==namesToAvoid.end())
1761     return nameTry;
1762   //attempt #1
1763   std::size_t len=nameTry.length();
1764   for(std::size_t ii=1;ii<len;ii++)
1765     {
1766       std::string tmp=nameTry.substr(ii,len-ii);
1767       if(std::find(namesToAvoid.begin(),namesToAvoid.end(),tmp)==namesToAvoid.end())
1768         return tmp;
1769     }
1770   //attempt #2
1771   if(len>=1)
1772     {
1773       for(std::size_t i=1;i<30;i++)
1774         {
1775           std::string tmp1(nameTry.at(0),i);
1776           tmp1+=nameTry;
1777           if(std::find(namesToAvoid.begin(),namesToAvoid.end(),tmp1)==namesToAvoid.end())
1778             return tmp1;
1779         }
1780     }
1781   //attempt #3
1782   std::string tmp2;
1783   for(std::vector<std::string>::const_iterator it2=namesToAvoid.begin();it2!=namesToAvoid.end();it2++)
1784     tmp2+=(*it2);
1785   if(std::find(namesToAvoid.begin(),namesToAvoid.end(),tmp2)==namesToAvoid.end())
1786     return tmp2;
1787   throw INTERP_KERNEL::Exception("MEDFileMesh::CreateNameNotIn : impossible to find a not already used name !");
1788 }
1789
1790 int MEDFileMesh::PutInThirdComponentOfCodeOffset(std::vector<int>& code, int strt) throw(INTERP_KERNEL::Exception)
1791 {
1792   std::size_t nbOfChunks=code.size()/3;
1793   if(code.size()%3!=0)
1794     throw INTERP_KERNEL::Exception("MEDFileMesh::PutInThirdComponentOfCodeOffset : code has invalid size : should be of size 3*x !");
1795   int ret=strt;
1796   for(std::size_t i=0;i<nbOfChunks;i++)
1797     {
1798       code[3*i+2]=ret;
1799       ret+=code[3*i+1];
1800     }
1801   return ret;
1802 }
1803
1804 /*!
1805  * This method should be called by any set* method of subclasses to deal automatically with _name attribute.
1806  * If _name attribute is empty the name of 'm' if taken as _name attribute.
1807  * If _name is not empty and that 'm' has the same name nothing is done.
1808  * If _name is not emplt and that 'm' has \b NOT the same name an exception is thrown.
1809  */
1810 void MEDFileMesh::dealWithTinyInfo(const MEDCouplingMesh *m) throw(INTERP_KERNEL::Exception)
1811 {
1812   if(!m)
1813     throw INTERP_KERNEL::Exception("MEDFileMesh::dealWithTinyInfo : input mesh in NULL !");
1814   if(_name.empty())
1815     _name=m->getName();
1816   else
1817     {
1818       std::string name(m->getName());
1819       if(!name.empty())
1820         {
1821           if(_name!=name)
1822             {
1823               std::ostringstream oss; oss << "MEDFileMesh::dealWithTinyInfo : name of current MEDfile mesh is '" << _name << "' whereas name of input mesh is : '";
1824               oss << name << "' ! Names must match !";
1825               throw INTERP_KERNEL::Exception(oss.str().c_str());
1826             }
1827         }
1828     }
1829   if(_desc_name.empty())
1830     _desc_name=m->getDescription();
1831   else
1832     {
1833       std::string name(m->getDescription());
1834       if(!name.empty())
1835         {
1836           if(_desc_name!=name)
1837             {
1838               std::ostringstream oss; oss << "MEDFileMesh::dealWithTinyInfo : description of current MEDfile mesh is '" << _desc_name << "' whereas name of input mesh is : '";
1839               oss << name << "' ! Names must match !";
1840               throw INTERP_KERNEL::Exception(oss.str().c_str());
1841             }
1842         }
1843     }
1844 }
1845
1846 void MEDFileMesh::getFamilyRepr(std::ostream& oss) const
1847 {
1848   oss << "(**************************)\n(* FAMILIES OF THE MESH : *)\n(**************************)\n";
1849   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
1850     {
1851       oss << "- Family with name \"" << (*it).first << "\" with number " << (*it).second << std::endl;
1852       oss << "  - Groups lying on this family : ";
1853       std::vector<std::string> grps=getGroupsOnFamily((*it).first.c_str());
1854       std::copy(grps.begin(),grps.end(),std::ostream_iterator<std::string>(oss," "));
1855       oss << std::endl << std::endl;
1856     }
1857 }
1858
1859 /*!
1860  * Returns a new MEDFileUMesh holding the mesh data that has been read from a given MED
1861  * file. The mesh to load is specified by its name and numbers of a time step and an
1862  * iteration.
1863  *  \param [in] fileName - the name of MED file to read.
1864  *  \param [in] mName - the name of the mesh to read.
1865  *  \param [in] dt - the number of a time step.
1866  *  \param [in] it - the number of an iteration.
1867  *  \return MEDFileUMesh * - a new instance of MEDFileUMesh. The caller is to delete this
1868  *          mesh using decrRef() as it is no more needed. 
1869  *  \throw If the file is not readable.
1870  *  \throw If there is no mesh with given attributes in the file.
1871  *  \throw If the mesh in the file is not an unstructured one.
1872  */
1873 MEDFileUMesh *MEDFileUMesh::New(const char *fileName, const char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception)
1874 {
1875   MEDFileUtilities::CheckFileForRead(fileName);
1876   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
1877   return new MEDFileUMesh(fid,mName,dt,it,mrs);
1878 }
1879
1880 /*!
1881  * Returns a new MEDFileUMesh holding the mesh data that has been read from a given MED
1882  * file. The first mesh in the file is loaded.
1883  *  \param [in] fileName - the name of MED file to read.
1884  *  \return MEDFileUMesh * - a new instance of MEDFileUMesh. The caller is to delete this
1885  *          mesh using decrRef() as it is no more needed. 
1886  *  \throw If the file is not readable.
1887  *  \throw If there is no meshes in the file.
1888  *  \throw If the mesh in the file is not an unstructured one.
1889  */
1890 MEDFileUMesh *MEDFileUMesh::New(const char *fileName, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception)
1891 {
1892   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
1893   if(ms.empty())
1894     {
1895       std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
1896       throw INTERP_KERNEL::Exception(oss.str().c_str());
1897     }
1898   MEDFileUtilities::CheckFileForRead(fileName);
1899   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
1900   int dt,it;
1901   ParaMEDMEM::MEDCouplingMeshType meshType;
1902   std::string dummy2;
1903   MEDFileMeshL2::GetMeshIdFromName(fid,ms.front().c_str(),meshType,dt,it,dummy2);
1904   return new MEDFileUMesh(fid,ms.front().c_str(),dt,it,mrs);
1905 }
1906
1907 /*!
1908  * Returns an empty instance of MEDFileUMesh.
1909  *  \return MEDFileUMesh * - a new instance of MEDFileUMesh. The caller is to delete this
1910  *          mesh using decrRef() as it is no more needed. 
1911  */
1912 MEDFileUMesh *MEDFileUMesh::New()
1913 {
1914   return new MEDFileUMesh;
1915 }
1916
1917 std::size_t MEDFileUMesh::getHeapMemorySize() const
1918 {
1919   std::size_t ret=MEDFileMesh::getHeapMemorySize();
1920   if((const DataArrayDouble*)_coords)
1921     ret+=_coords->getHeapMemorySize();
1922   if((const DataArrayInt *)_fam_coords)
1923     ret+=_fam_coords->getHeapMemorySize();
1924   if((const DataArrayInt *)_num_coords)
1925     ret+=_num_coords->getHeapMemorySize();
1926   if((const DataArrayInt *)_rev_num_coords)
1927     ret+=_rev_num_coords->getHeapMemorySize();
1928   if((const DataArrayAsciiChar *)_name_coords)
1929     ret+=_name_coords->getHeapMemorySize();
1930   ret+=_ms.capacity()*(sizeof(MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1>));
1931   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
1932     if((const MEDFileUMeshSplitL1*) *it)
1933       ret+=(*it)->getHeapMemorySize();
1934   return ret;
1935 }
1936
1937 MEDFileMesh *MEDFileUMesh::shallowCpy() const throw(INTERP_KERNEL::Exception)
1938 {
1939   MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret=new MEDFileUMesh(*this);
1940   return ret.retn();
1941 }
1942
1943 MEDFileMesh *MEDFileUMesh::createNewEmpty() const throw(INTERP_KERNEL::Exception)
1944 {
1945   return new MEDFileUMesh;
1946 }
1947
1948 MEDFileMesh *MEDFileUMesh::deepCpy() const throw(INTERP_KERNEL::Exception)
1949 {
1950   MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret=new MEDFileUMesh(*this);
1951   if((const DataArrayDouble*)_coords)
1952     ret->_coords=_coords->deepCpy();
1953   if((const DataArrayInt*)_fam_coords)
1954     ret->_fam_coords=_fam_coords->deepCpy();
1955   if((const DataArrayInt*)_num_coords)
1956     ret->_num_coords=_num_coords->deepCpy();
1957   if((const DataArrayInt*)_rev_num_coords)
1958     ret->_rev_num_coords=_rev_num_coords->deepCpy();
1959   if((const DataArrayAsciiChar*)_name_coords)
1960     ret->_name_coords=_name_coords->deepCpy();
1961   std::size_t i=0;
1962   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,i++)
1963     {
1964       if((const MEDFileUMeshSplitL1 *)(*it))
1965         ret->_ms[i]=(*it)->deepCpy(ret->_coords);
1966     }
1967   return ret.retn();
1968 }
1969
1970 /*!
1971  * Checks if \a this and another mesh are equal.
1972  *  \param [in] other - the mesh to compare with.
1973  *  \param [in] eps - a precision used to compare real values.
1974  *  \param [in,out] what - the string returning description of unequal data.
1975  *  \return bool - \c true if the meshes are equal, \c false, else.
1976  */
1977 bool MEDFileUMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
1978 {
1979   if(!MEDFileMesh::isEqual(other,eps,what))
1980     return false;
1981   const MEDFileUMesh *otherC=dynamic_cast<const MEDFileUMesh *>(other);
1982   if(!otherC)
1983     {
1984       what="Mesh types differ ! This is unstructured and other is NOT !";
1985       return false;
1986     }
1987   clearNonDiscrAttributes();
1988   otherC->clearNonDiscrAttributes();
1989   const DataArrayDouble *coo1=_coords;
1990   const DataArrayDouble *coo2=otherC->_coords;
1991   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
1992     {
1993       what="Mismatch of coordinates ! One is defined and not other !";
1994       return false;
1995     }
1996   if(coo1)
1997     {
1998       bool ret=coo1->isEqual(*coo2,eps);
1999       if(!ret)
2000         {
2001           what="Coords differ !";
2002           return false;
2003         }
2004     }
2005   const DataArrayInt *famc1=_fam_coords;
2006   const DataArrayInt *famc2=otherC->_fam_coords;
2007   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
2008     {
2009       what="Mismatch of families arr on nodes ! One is defined and not other !";
2010       return false;
2011     }
2012   if(famc1)
2013     {
2014       bool ret=famc1->isEqual(*famc2);
2015       if(!ret)
2016         {
2017           what="Families arr on node differ !";
2018           return false;
2019         }
2020     }
2021   const DataArrayInt *numc1=_num_coords;
2022   const DataArrayInt *numc2=otherC->_num_coords;
2023   if((numc1==0 && numc2!=0) || (numc1!=0 && numc2==0))
2024     {
2025       what="Mismatch of numbering arr on nodes ! One is defined and not other !";
2026       return false;
2027     }
2028   if(numc1)
2029     {
2030       bool ret=numc1->isEqual(*numc2);
2031       if(!ret)
2032         {
2033           what="Numbering arr on node differ !";
2034           return false;
2035         }
2036     }
2037   const DataArrayAsciiChar *namec1=_name_coords;
2038   const DataArrayAsciiChar *namec2=otherC->_name_coords;
2039   if((namec1==0 && namec2!=0) || (namec1!=0 && namec2==0))
2040     {
2041       what="Mismatch of naming arr on nodes ! One is defined and not other !";
2042       return false;
2043     }
2044   if(namec1)
2045     {
2046       bool ret=namec1->isEqual(*namec2);
2047       if(!ret)
2048         {
2049           what="Names arr on node differ !";
2050           return false;
2051         }
2052     }
2053   if(_ms.size()!=otherC->_ms.size())
2054     {
2055       what="Number of levels differs !";
2056       return false;
2057     }
2058   std::size_t sz=_ms.size();
2059   for(std::size_t i=0;i<sz;i++)
2060     {
2061       const MEDFileUMeshSplitL1 *s1=_ms[i];
2062       const MEDFileUMeshSplitL1 *s2=otherC->_ms[i];
2063       if((s1==0 && s2!=0) || (s1!=0 && s2==0))
2064         {
2065           what="Mismatch of presence of sub levels !";
2066           return false;
2067         }
2068       if(s1)
2069         {
2070           bool ret=s1->isEqual(s2,eps,what);
2071           if(!ret)
2072             return false;
2073         }
2074     }
2075   return true;
2076 }
2077
2078 /*!
2079  * Clears redundant attributes of incorporated data arrays.
2080  */
2081 void MEDFileUMesh::clearNonDiscrAttributes() const
2082 {
2083   MEDFileMesh::clearNonDiscrAttributes();
2084   const DataArrayDouble *coo1=_coords;
2085   if(coo1)
2086     (const_cast<DataArrayDouble *>(coo1))->setName("");//This parameter is not discriminant for comparison
2087   const DataArrayInt *famc1=_fam_coords;
2088   if(famc1)
2089     (const_cast<DataArrayInt *>(famc1))->setName("");//This parameter is not discriminant for comparison
2090   const DataArrayInt *numc1=_num_coords;
2091   if(numc1)
2092     (const_cast<DataArrayInt *>(numc1))->setName("");//This parameter is not discriminant for comparison
2093   const DataArrayAsciiChar *namc1=_name_coords;
2094   if(namc1)
2095     (const_cast<DataArrayAsciiChar *>(namc1))->setName("");//This parameter is not discriminant for comparison
2096   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2097     {
2098       const MEDFileUMeshSplitL1 *tmp=(*it);
2099       if(tmp)
2100         tmp->clearNonDiscrAttributes();
2101     }
2102 }
2103
2104 MEDFileUMesh::MEDFileUMesh()
2105 {
2106 }
2107
2108 MEDFileUMesh::MEDFileUMesh(med_idt fid, const char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception)
2109 try
2110   {
2111     loadUMeshFromFile(fid,mName,dt,it,mrs);
2112   }
2113 catch(INTERP_KERNEL::Exception& e)
2114   {
2115     throw e;
2116   }
2117
2118 void MEDFileUMesh::loadUMeshFromFile(med_idt fid, const char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception)
2119 {
2120   MEDFileUMeshL2 loaderl2;
2121   ParaMEDMEM::MEDCouplingMeshType meshType;
2122   int dummy0,dummy1;
2123   std::string dummy2;
2124   int mid=MEDFileUMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dummy2);
2125   if(meshType!=UNSTRUCTURED)
2126     {
2127       std::ostringstream oss; oss << "Trying to load as unstructured an existing mesh with name '" << mName << "' !";
2128       throw INTERP_KERNEL::Exception(oss.str().c_str());
2129     }
2130   loaderl2.loadAll(fid,mid,mName,dt,it,mrs);
2131   int lev=loaderl2.getNumberOfLevels();
2132   _ms.resize(lev);
2133   for(int i=0;i<lev;i++)
2134     {
2135       if(!loaderl2.emptyLev(i))
2136         _ms[i]=new MEDFileUMeshSplitL1(loaderl2,mName,i);
2137       else
2138         _ms[i]=0;
2139     }
2140   MEDFileMeshL2::ReadFamiliesAndGrps(fid,mName,_families,_groups,mrs);
2141   //
2142   setName(loaderl2.getName());
2143   setDescription(loaderl2.getDescription());
2144   setUnivName(loaderl2.getUnivName());
2145   setIteration(loaderl2.getIteration());
2146   setOrder(loaderl2.getOrder());
2147   setTimeValue(loaderl2.getTime());
2148   setTimeUnit(loaderl2.getTimeUnit());
2149   _coords=loaderl2.getCoords();
2150   if(!mrs || mrs->isNodeFamilyFieldReading())
2151     _fam_coords=loaderl2.getCoordsFamily();
2152   if(!mrs || mrs->isNodeNumFieldReading())
2153     _num_coords=loaderl2.getCoordsNum();
2154   if(!mrs || mrs->isNodeNameFieldReading())
2155     _name_coords=loaderl2.getCoordsName();
2156   computeRevNum();
2157 }
2158
2159 MEDFileUMesh::~MEDFileUMesh()
2160 {
2161 }
2162
2163 void MEDFileUMesh::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception)
2164 {
2165   const DataArrayDouble *coo=_coords;
2166   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
2167   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
2168   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
2169   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
2170   int spaceDim=coo?coo->getNumberOfComponents():0;
2171   int mdim=getMeshDimension();
2172   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
2173   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
2174   for(int i=0;i<spaceDim;i++)
2175     {
2176       std::string info=coo->getInfoOnComponent(i);
2177       std::string c,u;
2178       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
2179       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
2180       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
2181     }
2182   MEDmeshCr(fid,maa,spaceDim,mdim,MED_UNSTRUCTURED_MESH,desc,"",MED_SORT_DTIT,MED_CARTESIAN,comp,unit);
2183   MEDmeshUniversalNameWr(fid,maa);
2184   MEDFileUMeshL2::WriteCoords(fid,maa,_iteration,_order,_time,_coords,_fam_coords,_num_coords,_name_coords);
2185   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2186     if((const MEDFileUMeshSplitL1 *)(*it)!=0)
2187       (*it)->write(fid,maa,mdim);
2188   MEDFileUMeshL2::WriteFamiliesAndGrps(fid,maa,_families,_groups,_too_long_str);
2189 }
2190
2191 /*!
2192  * Returns relative dimensions of mesh entities (excluding nodes) present in \a this mesh.
2193  *  \return std::vector<int> - a sequence of the relative dimensions.
2194  */
2195 std::vector<int> MEDFileUMesh::getNonEmptyLevels() const
2196 {
2197   std::vector<int> ret;
2198   int lev=0;
2199   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
2200     if((const MEDFileUMeshSplitL1 *)(*it)!=0)
2201       if(!(*it)->empty())
2202         ret.push_back(lev);
2203   return ret;
2204 }
2205
2206 /*!
2207  * Returns relative dimensions of mesh entities (including nodes) present in \a this mesh.
2208  *  \return std::vector<int> - a sequence of the relative dimensions.
2209  */
2210 std::vector<int> MEDFileUMesh::getNonEmptyLevelsExt() const
2211 {
2212   std::vector<int> ret0=getNonEmptyLevels();
2213   if((const DataArrayDouble *) _coords)
2214     {
2215       std::vector<int> ret(ret0.size()+1);
2216       ret[0]=1;
2217       std::copy(ret0.begin(),ret0.end(),ret.begin()+1);
2218       return ret;
2219     }
2220   return ret0;
2221 }
2222
2223 std::vector<int> MEDFileUMesh::getFamArrNonEmptyLevelsExt() const
2224 {
2225   std::vector<int> ret;
2226   const DataArrayInt *famCoo(_fam_coords);
2227   if(famCoo)
2228     ret.push_back(1);
2229   int lev=0;
2230   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
2231     {
2232       const MEDFileUMeshSplitL1 *cur(*it);
2233       if(cur)
2234         if(cur->getFamilyField())
2235           ret.push_back(lev);
2236     }
2237   return ret;
2238 }
2239
2240 std::vector<int> MEDFileUMesh::getNumArrNonEmptyLevelsExt() const
2241 {
2242   std::vector<int> ret;
2243   const DataArrayInt *numCoo(_num_coords);
2244   if(numCoo)
2245     ret.push_back(1);
2246   int lev=0;
2247   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
2248     {
2249       const MEDFileUMeshSplitL1 *cur(*it);
2250       if(cur)
2251         if(cur->getNumberField())
2252           ret.push_back(lev);
2253     }
2254   return ret;
2255 }
2256
2257 std::vector<int> MEDFileUMesh::getNameArrNonEmptyLevelsExt() const
2258 {
2259   std::vector<int> ret;
2260   const DataArrayAsciiChar *nameCoo(_name_coords);
2261   if(nameCoo)
2262     ret.push_back(1);
2263   int lev=0;
2264   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
2265     {
2266       const MEDFileUMeshSplitL1 *cur(*it);
2267       if(cur)
2268         if(cur->getNameField())
2269           ret.push_back(lev);
2270     }
2271   return ret;
2272 }
2273
2274 /*!
2275  * Returns all relative mesh levels (**excluding nodes**) where a given group is defined.
2276  * To include nodes, call getGrpNonEmptyLevelsExt() method.
2277  *  \param [in] grp - the name of the group of interest.
2278  *  \return std::vector<int> - a sequence of the relative dimensions.
2279  */
2280 std::vector<int> MEDFileUMesh::getGrpNonEmptyLevels(const char *grp) const throw(INTERP_KERNEL::Exception)
2281 {
2282   std::vector<std::string> fams=getFamiliesOnGroup(grp);
2283   return getFamsNonEmptyLevels(fams);
2284 }
2285
2286 /*!
2287  * Returns all relative mesh levels (including nodes) where a given group is defined.
2288  *  \param [in] grp - the name of the group of interest.
2289  *  \return std::vector<int> - a sequence of the relative dimensions.
2290  */
2291 std::vector<int> MEDFileUMesh::getGrpNonEmptyLevelsExt(const char *grp) const throw(INTERP_KERNEL::Exception)
2292 {
2293   std::vector<std::string> fams=getFamiliesOnGroup(grp);
2294   return getFamsNonEmptyLevelsExt(fams);
2295 }
2296
2297 /*!
2298  * Returns all relative mesh levels (**excluding nodes**) where a given family is defined.
2299  * To include nodes, call getFamNonEmptyLevelsExt() method.
2300  *  \param [in] fam - the name of the family of interest.
2301  *  \return std::vector<int> - a sequence of the relative dimensions.
2302  */
2303 std::vector<int> MEDFileUMesh::getFamNonEmptyLevels(const char *fam) const throw(INTERP_KERNEL::Exception)
2304 {
2305   std::vector<std::string> fams(1,std::string(fam));
2306   return getFamsNonEmptyLevels(fams);
2307 }
2308
2309 /*!
2310  * Returns all relative mesh levels (including nodes) where a given family is defined.
2311  *  \param [in] fam - the name of the family of interest.
2312  *  \return std::vector<int> - a sequence of the relative dimensions.
2313  */
2314 std::vector<int> MEDFileUMesh::getFamNonEmptyLevelsExt(const char *fam) const throw(INTERP_KERNEL::Exception)
2315 {
2316   std::vector<std::string> fams(1,std::string(fam));
2317   return getFamsNonEmptyLevelsExt(fams);
2318 }
2319
2320 /*!
2321  * Returns all relative mesh levels (**excluding nodes**) where given groups are defined.
2322  * To include nodes, call getGrpsNonEmptyLevelsExt() method.
2323  *  \param [in] grps - a sequence of names of the groups of interest.
2324  *  \return std::vector<int> - a sequence of the relative dimensions.
2325  */
2326 std::vector<int> MEDFileUMesh::getGrpsNonEmptyLevels(const std::vector<std::string>& grps) const throw(INTERP_KERNEL::Exception)
2327 {
2328   std::vector<std::string> fams=getFamiliesOnGroups(grps);
2329   return getFamsNonEmptyLevels(fams);
2330 }
2331
2332 /*!
2333  * Returns all relative mesh levels (including nodes) where given groups are defined.
2334  *  \param [in] grps - a sequence of names of the groups of interest.
2335  *  \return std::vector<int> - a sequence of the relative dimensions.
2336  */
2337 std::vector<int> MEDFileUMesh::getGrpsNonEmptyLevelsExt(const std::vector<std::string>& grps) const throw(INTERP_KERNEL::Exception)
2338 {
2339   std::vector<std::string> fams=getFamiliesOnGroups(grps);
2340   return getFamsNonEmptyLevelsExt(fams);
2341 }
2342
2343 /*!
2344  * Returns all relative mesh levels (**excluding nodes**) where given families are defined.
2345  * To include nodes, call getFamsNonEmptyLevelsExt() method.
2346  *  \param [in] fams - the name of the family of interest.
2347  *  \return std::vector<int> - a sequence of the relative dimensions.
2348  */
2349 std::vector<int> MEDFileUMesh::getFamsNonEmptyLevels(const std::vector<std::string>& fams) const throw(INTERP_KERNEL::Exception)
2350 {
2351   std::vector<int> ret;
2352   std::vector<int> levs=getNonEmptyLevels();
2353   std::vector<int> famIds=getFamiliesIds(fams);
2354   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
2355     if(_ms[-(*it)]->presenceOfOneFams(famIds))
2356       ret.push_back(*it);
2357   return ret;
2358 }
2359
2360 /*!
2361  * Returns all relative mesh levels (including nodes) where given families are defined.
2362  *  \param [in] fams - the names of the families of interest.
2363  *  \return std::vector<int> - a sequence of the relative dimensions.
2364  */
2365 std::vector<int> MEDFileUMesh::getFamsNonEmptyLevelsExt(const std::vector<std::string>& fams) const throw(INTERP_KERNEL::Exception)
2366 {
2367   std::vector<int> ret0=getFamsNonEmptyLevels(fams);
2368   const DataArrayInt *famCoords=_fam_coords;
2369   if(!famCoords)
2370     return ret0;
2371   std::vector<int> famIds=getFamiliesIds(fams);
2372   if(famCoords->presenceOfValue(famIds))
2373     {
2374       std::vector<int> ret(ret0.size()+1);
2375       ret[0]=1;
2376       std::copy(ret0.begin(),ret0.end(),ret.begin()+1);
2377       return ret;
2378     }
2379   else
2380     return ret0;
2381 }
2382
2383 /*!
2384  * Returns names of groups that partly or fully appear on the level \a meshDimRelToMaxExt.
2385  *  \param [in] meshDimRelToMaxExt - a relative dimension of interest.
2386  *  \return std::vector<std::string> - a sequence of group names at \a meshDimRelToMaxExt
2387  *          level. 
2388  */
2389 std::vector<std::string> MEDFileUMesh::getGroupsOnSpecifiedLev(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
2390 {
2391   std::vector<std::string> ret;
2392   std::vector<std::string> allGrps=getGroupsNames();
2393   for(std::vector<std::string>::const_iterator it=allGrps.begin();it!=allGrps.end();it++)
2394     {
2395       std::vector<int> levs=getGrpNonEmptyLevelsExt((*it).c_str());
2396       if(std::find(levs.begin(),levs.end(),meshDimRelToMaxExt)!=levs.end())
2397         ret.push_back(*it);
2398     }
2399   return ret;
2400 }
2401
2402 int MEDFileUMesh::getMaxAbsFamilyIdInArrays() const throw(INTERP_KERNEL::Exception)
2403 {
2404   int ret=-std::numeric_limits<int>::max(),tmp=-1;
2405   if((const DataArrayInt *)_fam_coords)
2406     {
2407       int val=_fam_coords->getMaxValue(tmp);
2408       ret=std::max(ret,std::abs(val));
2409     }
2410   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2411     {
2412       if((const MEDFileUMeshSplitL1 *)(*it))
2413         {
2414           const DataArrayInt *da=(*it)->getFamilyField();
2415           if(da)
2416             {
2417               int val=da->getMaxValue(tmp);
2418               ret=std::max(ret,std::abs(val));
2419             }
2420         }
2421     }
2422   return ret;
2423 }
2424
2425 int MEDFileUMesh::getMaxFamilyIdInArrays() const throw(INTERP_KERNEL::Exception)
2426 {
2427   int ret=-std::numeric_limits<int>::max(),tmp=-1;
2428   if((const DataArrayInt *)_fam_coords)
2429     {
2430       int val=_fam_coords->getMaxValue(tmp);
2431       ret=std::max(ret,val);
2432     }
2433   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2434     {
2435       if((const MEDFileUMeshSplitL1 *)(*it))
2436         {
2437           const DataArrayInt *da=(*it)->getFamilyField();
2438           if(da)
2439             {
2440               int val=da->getMaxValue(tmp);
2441               ret=std::max(ret,val);
2442             }
2443         }
2444     }
2445   return ret;
2446 }
2447
2448 int MEDFileUMesh::getMinFamilyIdInArrays() const throw(INTERP_KERNEL::Exception)
2449 {
2450   int ret=std::numeric_limits<int>::max(),tmp=-1;
2451   if((const DataArrayInt *)_fam_coords)
2452     {
2453       int val=_fam_coords->getMinValue(tmp);
2454       ret=std::min(ret,val);
2455     }
2456   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2457     {
2458       if((const MEDFileUMeshSplitL1 *)(*it))
2459         {
2460           const DataArrayInt *da=(*it)->getFamilyField();
2461           if(da)
2462             {
2463               int val=da->getMinValue(tmp);
2464               ret=std::min(ret,val);
2465             }
2466         }
2467     }
2468   return ret;
2469 }
2470
2471 /*!
2472  * Returns the dimension on cells in \a this mesh.
2473  *  \return int - the mesh dimension.
2474  *  \throw If there are no cells in this mesh.
2475  */
2476 int MEDFileUMesh::getMeshDimension() const throw(INTERP_KERNEL::Exception)
2477 {
2478   int lev=0;
2479   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev++)
2480     if((const MEDFileUMeshSplitL1 *)(*it)!=0)
2481       return (*it)->getMeshDimension()+lev;
2482   throw INTERP_KERNEL::Exception("MEDFileUMesh::getMeshDimension : impossible to find a mesh dimension !");
2483 }
2484
2485 /*!
2486  * Returns the space dimension of \a this mesh that is equal to number of components in
2487  * the node coordinates array.
2488  *  \return int - the space dimension of \a this mesh.
2489  *  \throw If the node coordinates array is not available.
2490  */
2491 int MEDFileUMesh::getSpaceDimension() const throw(INTERP_KERNEL::Exception)
2492 {
2493   const DataArrayDouble *coo=_coords;
2494   if(!coo)
2495     throw INTERP_KERNEL::Exception(" MEDFileUMesh::getSpaceDimension : no coords set !");
2496   return coo->getNumberOfComponents();
2497 }
2498
2499 /*!
2500  * Returns a string describing \a this mesh.
2501  *  \return std::string - the mesh information string.
2502  */
2503 std::string MEDFileUMesh::simpleRepr() const
2504 {
2505   std::ostringstream oss;
2506   oss << MEDFileMesh::simpleRepr();
2507   const DataArrayDouble *coo=_coords;
2508   oss << "- The dimension of the space is ";
2509   static const char MSG1[]= "*** NO COORDS SET ***";
2510   static const char MSG2[]= "*** NO CONNECTIVITY SET FOR THIS LEVEL***";
2511   if(coo)
2512     oss << _coords->getNumberOfComponents() << std::endl;
2513   else
2514     oss << MSG1 << std::endl;
2515   oss << "- Type of the mesh : UNSTRUCTURED\n";
2516   oss << "- Number of nodes : ";
2517   if(coo)
2518     oss << _coords->getNumberOfTuples() << std::endl;
2519   else
2520     oss << MSG1 << std::endl;
2521   std::size_t nbOfLev=_ms.size();
2522   oss << "- Number of levels allocated : " << nbOfLev << std::endl;
2523   for(std::size_t i=0;i<nbOfLev;i++)
2524     {
2525       const MEDFileUMeshSplitL1 *lev=_ms[i];
2526       oss << "  - Level #" << -((int) i) << " has dimension : ";
2527       if(lev)
2528         {
2529           oss << lev->getMeshDimension() << std::endl;
2530           lev->simpleRepr(oss);
2531         }
2532       else
2533         oss << MSG2 << std::endl;
2534     }
2535   oss << "- Number of families : " << _families.size() << std::endl << std::endl;
2536   if(coo)
2537     {
2538       oss << "(***********************)\n(* NODES OF THE MESH : *)\n(***********************)\n";
2539       oss << "- Names of coordinates :" << std::endl;
2540       std::vector<std::string> vars=coo->getVarsOnComponent();
2541       std::copy(vars.begin(),vars.end(),std::ostream_iterator<std::string>(oss," "));
2542       oss << std::endl << "- Units of coordinates : " << std::endl;
2543       std::vector<std::string> units=coo->getUnitsOnComponent();
2544       std::copy(units.begin(),units.end(),std::ostream_iterator<std::string>(oss," "));
2545     }
2546   oss << std::endl << std::endl;
2547   getFamilyRepr(oss);
2548   return oss.str();
2549 }
2550
2551 /*!
2552  * Returns a full textual description of \a this mesh.
2553  *  \return std::string - the string holding the mesh description.
2554  */
2555 std::string MEDFileUMesh::advancedRepr() const
2556 {
2557   return simpleRepr();
2558 }
2559
2560 /*!
2561  * Returns number of mesh entities of a given relative dimension in \a this mesh.
2562  *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
2563  *  \return int - the number of entities.
2564  *  \throw If no mesh entities of dimension \a meshDimRelToMaxExt are available in \a this mesh.
2565  */
2566 int MEDFileUMesh::getSizeAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
2567 {
2568   if(meshDimRelToMaxExt==1)
2569     {
2570       if(!((const DataArrayDouble *)_coords))
2571         throw INTERP_KERNEL::Exception("MEDFileUMesh::getSizeAtLevel : no coordinates specified !");
2572       return _coords->getNumberOfTuples();
2573     }
2574   return getMeshAtLevSafe(meshDimRelToMaxExt)->getSize();
2575 }
2576
2577 /*!
2578  * Returns the family field for mesh entities of a given dimension.
2579  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
2580  *  \return const DataArrayInt * - the family field. It is an array of ids of families
2581  *          each mesh entity belongs to. It can be \c NULL.
2582  */
2583 const DataArrayInt *MEDFileUMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
2584 {
2585   if(meshDimRelToMaxExt==1)
2586     return _fam_coords;
2587   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2588   return l1->getFamilyField();
2589 }
2590
2591 /*!
2592  * Returns the optional numbers of mesh entities of a given dimension.
2593  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
2594  *  \return const DataArrayInt * - the array of the entity numbers.
2595  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2596  */
2597 const DataArrayInt *MEDFileUMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
2598 {
2599   if(meshDimRelToMaxExt==1)
2600     return _num_coords;
2601   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2602   return l1->getNumberField();
2603 }
2604
2605 const DataArrayAsciiChar *MEDFileUMesh::getNameFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
2606 {
2607   if(meshDimRelToMaxExt==1)
2608     return _name_coords;
2609   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2610   return l1->getNameField();
2611 }
2612
2613 int MEDFileUMesh::getNumberOfNodes() const throw(INTERP_KERNEL::Exception)
2614 {
2615   const DataArrayDouble *coo=_coords;
2616   if(!coo)
2617     throw INTERP_KERNEL::Exception(" MEDFileUMesh::getNumberOfNodes : no coords set !");
2618   return coo->getNumberOfTuples();
2619 }
2620
2621 void MEDFileUMesh::whichAreNodesFetched(const MEDFileField1TSStructItem& st, const MEDFileFieldGlobsReal *globs, std::vector<bool>& nodesFetched) const throw(INTERP_KERNEL::Exception)
2622 {
2623   std::size_t sz(st.getNumberOfItems());
2624   int mdim(getMeshDimension());
2625   for(std::size_t i=0;i<sz;i++)
2626     {
2627       INTERP_KERNEL::NormalizedCellType curGt(st[i].getGeo());
2628       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(curGt);
2629       int relDim((int)cm.getDimension()-mdim);
2630       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> um(getMeshAtLevel(relDim));
2631       std::vector<int> d(um->getDistributionOfTypes());
2632       std::size_t nbOfTypes(d.size()/3);
2633       int offset=0,nbOfEltWT=-1;
2634       for(std::size_t j=0;j<nbOfTypes;j++)
2635         {
2636           if(d[3*j]!=(int)curGt)
2637             offset+=d[3*j+1];
2638           else
2639             { break; nbOfEltWT=d[3*j+1]; }
2640         }
2641       if(nbOfEltWT==-1)
2642         throw INTERP_KERNEL::Exception("MEDFileUMesh::whichAreNodesFetched : asking for a geo type not present in this !");
2643       um=dynamic_cast<MEDCouplingUMesh *>(um->buildPartOfMySelf2(offset,offset+nbOfEltWT,1,true));
2644       if(st[i].getPflName().empty())
2645         um->computeNodeIdsAlg(nodesFetched);
2646       else
2647         {
2648           const DataArrayInt *arr(globs->getProfile(st[i].getPflName().c_str()));
2649           um=dynamic_cast<MEDCouplingUMesh *>(um->buildPartOfMySelf(arr->begin(),arr->end(),true));
2650           um->computeNodeIdsAlg(nodesFetched);
2651         }
2652     }
2653 }
2654
2655 /*!
2656  * Returns the optional numbers of mesh entities of a given dimension transformed using
2657  * DataArrayInt::invertArrayN2O2O2N().
2658  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
2659  *  \return const DataArrayInt * - the array of the entity numbers transformed using
2660  *          DataArrayInt::invertArrayN2O2O2N().
2661  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2662  */
2663 const DataArrayInt *MEDFileUMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
2664 {
2665   if(meshDimRelToMaxExt==1)
2666     {
2667       if(!((const DataArrayInt *)_num_coords))
2668         throw INTERP_KERNEL::Exception("MEDFileUMesh::getRevNumberFieldAtLevel : no coordinates renum specified !");
2669       return _rev_num_coords;
2670     }
2671   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2672   return l1->getRevNumberField();
2673 }
2674
2675 /*!
2676  * Returns a pointer to the node coordinates array of \a this mesh \b without
2677  * incrementing its reference counter, thus there is no need to decrRef() it by the caller.
2678  */
2679 DataArrayDouble *MEDFileUMesh::getCoords() const
2680 {
2681   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp(_coords);
2682   if((DataArrayDouble *)tmp)
2683     {
2684       return tmp;
2685     }
2686   return 0;
2687 }
2688
2689 /*!
2690  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in a given
2691  * group of \a this mesh. Only mesh entities of a given dimension are included in the
2692  * new mesh.
2693  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
2694  *  \param [in] grp - the name of the group whose mesh entities are included in the
2695  *          new mesh.
2696  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
2697  *          according to the optional numbers of entities, if available.
2698  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
2699  *          delete this mesh using decrRef() as it is no more needed.
2700  *  \throw If the name of a nonexistent group is specified.
2701  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2702  */
2703 MEDCouplingUMesh *MEDFileUMesh::getGroup(int meshDimRelToMaxExt, const char *grp, bool renum) const throw(INTERP_KERNEL::Exception)
2704 {
2705   synchronizeTinyInfoOnLeaves();
2706   std::vector<std::string> tmp(1);
2707   tmp[0]=grp;
2708   return getGroups(meshDimRelToMaxExt,tmp,renum);
2709 }
2710
2711 /*!
2712  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in given
2713  * groups of \a this mesh. Only mesh entities of a given dimension are included in the
2714  * new mesh.
2715  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
2716  *  \param [in] grps - a sequence of group names whose mesh entities are included in the
2717  *          new mesh.
2718  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
2719  *          according to the optional numbers of entities, if available.
2720  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
2721  *          delete this mesh using decrRef() as it is no more needed.
2722  *  \throw If a name of a nonexistent group is present in \a grps.
2723  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2724  */
2725 MEDCouplingUMesh *MEDFileUMesh::getGroups(int meshDimRelToMaxExt, const std::vector<std::string>& grps, bool renum) const throw(INTERP_KERNEL::Exception)
2726 {
2727   synchronizeTinyInfoOnLeaves();
2728   std::vector<std::string> fams2=getFamiliesOnGroups(grps);
2729   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> zeRet=getFamilies(meshDimRelToMaxExt,fams2,renum);
2730   if(grps.size()==1 && ((MEDCouplingUMesh *)zeRet))
2731     zeRet->setName(grps[0].c_str());
2732   return zeRet.retn();
2733 }
2734
2735 /*!
2736  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in a given
2737  * family of \a this mesh. Only mesh entities of a given dimension are included in the
2738  * new mesh.
2739  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
2740  *  \param [in] fam - the name of the family whose mesh entities are included in the
2741  *          new mesh.
2742  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
2743  *          according to the optional numbers of entities, if available.
2744  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
2745  *          delete this mesh using decrRef() as it is no more needed.
2746  *  \throw If a name of a nonexistent family is present in \a grps.
2747  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2748  */
2749 MEDCouplingUMesh *MEDFileUMesh::getFamily(int meshDimRelToMaxExt, const char *fam, bool renum) const throw(INTERP_KERNEL::Exception)
2750 {
2751   synchronizeTinyInfoOnLeaves();
2752   std::vector<std::string> tmp(1);
2753   tmp[0]=fam;
2754   return getFamilies(meshDimRelToMaxExt,tmp,renum);
2755 }
2756
2757 /*!
2758  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in given
2759  * families of \a this mesh. Only mesh entities of a given dimension are included in the
2760  * new mesh.
2761  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
2762  *  \param [in] fams - a sequence of family names whose mesh entities are included in the
2763  *          new mesh.
2764  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
2765  *          according to the optional numbers of entities, if available.
2766  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
2767  *          delete this mesh using decrRef() as it is no more needed.
2768  *  \throw If a name of a nonexistent family is present in \a fams.
2769  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2770  */
2771 MEDCouplingUMesh *MEDFileUMesh::getFamilies(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const throw(INTERP_KERNEL::Exception)
2772 {
2773   synchronizeTinyInfoOnLeaves();
2774   if(meshDimRelToMaxExt==1)
2775     {
2776       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr=getFamiliesArr(1,fams,renum);
2777       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
2778       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> c=_coords->selectByTupleId(arr->getConstPointer(),arr->getConstPointer()+arr->getNbOfElems());
2779       ret->setCoords(c);
2780       return ret.retn();
2781     }
2782   std::vector<int> famIds=getFamiliesIds(fams);
2783   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2784   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> zeRet;
2785   if(!famIds.empty())
2786     zeRet=l1->getFamilyPart(&famIds[0],&famIds[0]+famIds.size(),renum);
2787   else
2788     zeRet=l1->getFamilyPart(0,0,renum);
2789   if(fams.size()==1 && ((MEDCouplingUMesh *)zeRet))
2790     zeRet->setName(fams[0].c_str());
2791   return zeRet.retn();
2792 }
2793
2794 /*!
2795  * Returns ids of mesh entities contained in given families of a given dimension.
2796  *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
2797  *          are required.
2798  *  \param [in] fams - the names of the families of interest.
2799  *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
2800  *          returned instead of ids.
2801  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
2802  *          numbers, if available and required, of mesh entities of the families. The caller
2803  *          is to delete this array using decrRef() as it is no more needed. 
2804  *  \throw If the family field is missing for \a meshDimRelToMaxExt.
2805  */
2806 DataArrayInt *MEDFileUMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const throw(INTERP_KERNEL::Exception)
2807 {
2808   std::vector<int> famIds=getFamiliesIds(fams);
2809   if(meshDimRelToMaxExt==1)
2810     {
2811       if((const DataArrayInt *)_fam_coords)
2812         {
2813           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
2814           if(!famIds.empty())
2815             da=_fam_coords->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
2816           else
2817             da=_fam_coords->getIdsEqualList(0,0);
2818           if(renum)
2819             return MEDFileUMeshSplitL1::Renumber(_num_coords,da);
2820           else
2821             return da.retn();
2822         }
2823       else
2824         throw INTERP_KERNEL::Exception("MEDFileUMesh::getFamiliesArr : no family array specified on nodes !");
2825     }
2826   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2827   if(!famIds.empty())
2828     return l1->getFamilyPartArr(&famIds[0],&famIds[0]+famIds.size(),renum);
2829   else
2830     return l1->getFamilyPartArr(0,0,renum);
2831 }
2832
2833 /*!
2834  * Returns a MEDCouplingUMesh of a given relative dimension.
2835  * \warning If \a meshDimRelToMaxExt == 1 (which means nodes), the returned mesh **is not
2836  * valid**. This is a feature, because MEDLoader does not create cells that do not exist! 
2837  * To build a valid MEDCouplingUMesh from the returned one in this case,
2838  * call MEDCouplingUMesh::Build0DMeshFromCoords().
2839  *  \param [in] meshDimRelToMax - the relative dimension of interest.
2840  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
2841  *          optional numbers of mesh entities.
2842  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
2843  *          delete using decrRef() as it is no more needed. 
2844  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2845  * \sa getGenMeshAtLevel()
2846  */
2847 MEDCouplingUMesh *MEDFileUMesh::getMeshAtLevel(int meshDimRelToMaxExt, bool renum) const throw(INTERP_KERNEL::Exception)
2848 {
2849   synchronizeTinyInfoOnLeaves();
2850   if(meshDimRelToMaxExt==1)
2851     {
2852       if(!renum)
2853         {
2854           MEDCouplingUMesh *umesh=MEDCouplingUMesh::New();
2855           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> cc=_coords->deepCpy();
2856           umesh->setCoords(cc);
2857           MEDFileUMeshSplitL1::ClearNonDiscrAttributes(umesh);
2858           umesh->setName(getName().c_str());
2859           return umesh;
2860         }
2861     }
2862   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2863   return l1->getWholeMesh(renum);
2864 }
2865
2866 /*!
2867  * Returns a MEDCouplingUMesh of a given relative dimension.
2868  * \warning If \a meshDimRelToMaxExt == 1 (which means nodes), the returned mesh **is not
2869  * valid**. This is a feature, because MEDLoader does not create cells that do not exist! 
2870  * To build a valid MEDCouplingUMesh from the returned one in this case,
2871  * call MEDCouplingUMesh::Build0DMeshFromCoords().
2872  *  \param [in] meshDimRelToMax - the relative dimension of interest.
2873  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
2874  *          optional numbers of mesh entities.
2875  *  \return MEDCouplingMesh * - a pointer to MEDCouplingUMesh that the caller is to
2876  *          delete using decrRef() as it is no more needed. 
2877  *  \throw If there are no mesh entities of \a meshDimRelToMax dimension in \a this mesh.
2878  * \sa getMeshAtLevel()
2879  */
2880 MEDCouplingMesh *MEDFileUMesh::getGenMeshAtLevel(int meshDimRelToMax, bool renum) const throw(INTERP_KERNEL::Exception)
2881 {
2882   return getMeshAtLevel(meshDimRelToMax,renum);
2883 }
2884
2885 /*!
2886  * Returns a MEDCouplingUMesh of a relative dimension == 0.
2887  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
2888  *          optional numbers of mesh entities.
2889  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
2890  *          delete using decrRef() as it is no more needed. 
2891  *  \throw If there are no mesh entities of the relative dimension == 0 in \a this mesh.
2892  */
2893 MEDCouplingUMesh *MEDFileUMesh::getLevel0Mesh(bool renum) const throw(INTERP_KERNEL::Exception)
2894 {
2895   return getMeshAtLevel(0,renum);
2896 }
2897
2898 /*!
2899  * Returns a MEDCouplingUMesh of a relative dimension == -1.
2900  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
2901  *          optional numbers of mesh entities.
2902  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
2903  *          delete using decrRef() as it is no more needed. 
2904  *  \throw If there are no mesh entities of the relative dimension == -1 in \a this mesh.
2905  */
2906 MEDCouplingUMesh *MEDFileUMesh::getLevelM1Mesh(bool renum) const throw(INTERP_KERNEL::Exception)
2907 {
2908   return getMeshAtLevel(-1,renum);
2909 }
2910
2911 /*!
2912  * Returns a MEDCouplingUMesh of a relative dimension == -2.
2913  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
2914  *          optional numbers of mesh entities.
2915  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
2916  *          delete using decrRef() as it is no more needed. 
2917  *  \throw If there are no mesh entities of the relative dimension == -2 in \a this mesh.
2918  */
2919 MEDCouplingUMesh *MEDFileUMesh::getLevelM2Mesh(bool renum) const throw(INTERP_KERNEL::Exception)
2920 {
2921   return getMeshAtLevel(-2,renum);
2922 }
2923
2924 /*!
2925  * Returns a MEDCouplingUMesh of a relative dimension == -3.
2926  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
2927  *          optional numbers of mesh entities.
2928  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
2929  *          delete using decrRef() as it is no more needed. 
2930  *  \throw If there are no mesh entities of the relative dimension == -3 in \a this mesh.
2931  */
2932 MEDCouplingUMesh *MEDFileUMesh::getLevelM3Mesh(bool renum) const throw(INTERP_KERNEL::Exception)
2933 {
2934   return getMeshAtLevel(-3,renum);
2935 }
2936
2937 /*!
2938  * This method returns a vector of mesh parts containing each exactly one geometric type.
2939  * This method will never launch an automatic computation of split by type (an INTERP_KERNEL::Exception will be then thrown).
2940  * This method is only for memory aware users.
2941  */
2942 std::vector<MEDCoupling1GTUMesh *> MEDFileUMesh::getDirectUndergroundSingleGeoTypeMeshes(int meshDimRelToMax) const throw(INTERP_KERNEL::Exception)
2943 {
2944   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(meshDimRelToMax));
2945   return sp->getDirectUndergroundSingleGeoTypeMeshes();
2946 }
2947
2948 /*!
2949  * This method returns the part of \a this having the geometric type \a gt.
2950  * If such part is not existing an exception will be thrown.
2951  */
2952 MEDCoupling1GTUMesh *MEDFileUMesh::getDirectUndergroundSingleGeoTypeMesh(INTERP_KERNEL::NormalizedCellType gt) const throw(INTERP_KERNEL::Exception)
2953 {
2954   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
2955   int lev=(int)cm.getDimension()-getMeshDimension();
2956   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(lev));
2957   return sp->getDirectUndergroundSingleGeoTypeMesh(gt);
2958 }
2959
2960 const MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
2961 {
2962   if(meshDimRelToMaxExt==1)
2963     throw INTERP_KERNEL::Exception("Dimension request is invalid : asking for node level (1) !");
2964   if(meshDimRelToMaxExt>1)
2965     throw INTERP_KERNEL::Exception("Dimension request is invalid (>1) !");
2966   int tracucedRk=-meshDimRelToMaxExt;
2967   if(tracucedRk>=(int)_ms.size())
2968     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
2969   if((const MEDFileUMeshSplitL1 *)_ms[tracucedRk]==0)
2970     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
2971   return _ms[tracucedRk];
2972 }
2973
2974 MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt) 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 void MEDFileUMesh::checkMeshDimCoherency(int meshDim, int meshDimRelToMax) const throw(INTERP_KERNEL::Exception)
2989 {
2990   if(-meshDimRelToMax>=(int)_ms.size())
2991     throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMeshDimCoherency : The meshdim of mesh is not managed by 'this' !");
2992   int i=0;
2993   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,i++)
2994     {
2995       if(((const MEDFileUMeshSplitL1*) (*it))!=0)
2996         {
2997           int ref=(*it)->getMeshDimension();
2998           if(ref+i!=meshDim-meshDimRelToMax)
2999             throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMeshDimCoherency : no coherency between levels !");
3000         }
3001     }
3002 }
3003
3004 /*!
3005  * Sets the node coordinates array of \a this mesh.
3006  *  \param [in] coords - the new node coordinates array.
3007  *  \throw If \a coords == \c NULL.
3008  */
3009 void MEDFileUMesh::setCoords(DataArrayDouble *coords) throw(INTERP_KERNEL::Exception)
3010 {
3011   if(!coords)
3012     throw INTERP_KERNEL::Exception("MEDFileUMesh::setCoords : null pointer in input !");
3013   coords->checkAllocated();
3014   int nbOfTuples=coords->getNumberOfTuples();
3015   _coords=coords;
3016   coords->incrRef();
3017   _fam_coords=DataArrayInt::New();
3018   _fam_coords->alloc(nbOfTuples,1);
3019   _fam_coords->fillWithZero();
3020   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
3021     if((MEDFileUMeshSplitL1 *)(*it))
3022       (*it)->setCoords(coords);
3023 }
3024
3025 /*!
3026  * Removes all groups of a given dimension in \a this mesh.
3027  *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
3028  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3029  */
3030 void MEDFileUMesh::eraseGroupsAtLevel(int meshDimRelToMaxExt) throw(INTERP_KERNEL::Exception)
3031 {
3032   if(meshDimRelToMaxExt==1)
3033     {
3034       if((DataArrayInt *)_fam_coords)
3035         _fam_coords->fillWithZero();
3036       return ;
3037     }
3038   MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3039   l1->eraseFamilyField();
3040   optimizeFamilies();
3041 }
3042
3043 /*!
3044  * Removes all families with ids not present in the family fields of \a this mesh.
3045  */
3046 void MEDFileUMesh::optimizeFamilies() throw(INTERP_KERNEL::Exception)
3047 {
3048   std::vector<int> levs=getNonEmptyLevelsExt();
3049   std::set<int> allFamsIds;
3050   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
3051     {
3052       const DataArrayInt *ffield=getFamilyFieldAtLevel(*it);
3053       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=ffield->getDifferentValues();
3054       std::set<int> res;
3055       std::set_union(ids->begin(),ids->end(),allFamsIds.begin(),allFamsIds.end(),std::inserter(res,res.begin()));
3056       allFamsIds=res;
3057     }
3058   std::set<std::string> famNamesToKill;
3059   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
3060     {
3061       if(allFamsIds.find((*it).second)!=allFamsIds.end())
3062         famNamesToKill.insert((*it).first);
3063     }
3064   for(std::set<std::string>::const_iterator it=famNamesToKill.begin();it!=famNamesToKill.end();it++)
3065     _families.erase(*it);
3066   std::vector<std::string> grpNamesToKill;
3067   for(std::map<std::string, std::vector<std::string> >::iterator it=_groups.begin();it!=_groups.end();it++)
3068     {
3069       std::vector<std::string> tmp;
3070       for(std::vector<std::string>::const_iterator it2=(*it).second.begin();it2!=(*it).second.end();it2++)
3071         {
3072           if(famNamesToKill.find(*it2)==famNamesToKill.end())
3073             tmp.push_back(*it2);
3074         }
3075       if(!tmp.empty())
3076         (*it).second=tmp;
3077       else
3078         tmp.push_back((*it).first);
3079     }
3080   for(std::vector<std::string>::const_iterator it=grpNamesToKill.begin();it!=grpNamesToKill.end();it++)
3081     _groups.erase(*it);
3082 }
3083
3084 void MEDFileUMesh::duplicateNodesOnM1Group(const char *grpNameM1, DataArrayInt *&nodesDuplicated, DataArrayInt *&cellsModified, DataArrayInt *&cellsNotModified) throw(INTERP_KERNEL::Exception)
3085 {
3086   std::vector<int> levs=getNonEmptyLevels();
3087   if(std::find(levs.begin(),levs.end(),0)==levs.end() || std::find(levs.begin(),levs.end(),-1)==levs.end())
3088     throw INTERP_KERNEL::Exception("MEDFileUMesh::duplicateNodesOnM1Group : This method works only for mesh definied on level 0 and -1 !");
3089   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0=getMeshAtLevel(0);
3090   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1=getMeshAtLevel(-1);
3091   int nbNodes=m0->getNumberOfNodes();
3092   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m11=getGroup(-1,grpNameM1);
3093   DataArrayInt *tmp00=0,*tmp11=0,*tmp22=0;
3094   m0->findNodesToDuplicate(*m11,tmp00,tmp11,tmp22);
3095   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodeIdsToDuplicate(tmp00);
3096   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0(tmp11);
3097   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1(tmp22);
3098   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp0=static_cast<MEDCouplingUMesh *>(m0->buildPartOfMySelf(cellsToModifyConn0->begin(),cellsToModifyConn0->end(),true));
3099   // node renumbering of cells in m1 impacted by duplication of node but not in group 'grpNameM1' on level -1
3100   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descTmp0=DataArrayInt::New(),descITmp0=DataArrayInt::New(),revDescTmp0=DataArrayInt::New(),revDescITmp0=DataArrayInt::New();
3101   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp0Desc=tmp0->buildDescendingConnectivity(descTmp0,descITmp0,revDescTmp0,revDescITmp0);
3102   descTmp0=0; descITmp0=0; revDescTmp0=0; revDescITmp0=0;
3103   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsInM1ToRenumW2=tmp0Desc->getCellIdsLyingOnNodes(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),false);
3104   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cellsInM1ToRenumW3=static_cast<MEDCouplingUMesh *>(tmp0Desc->buildPartOfMySelf(cellsInM1ToRenumW2->begin(),cellsInM1ToRenumW2->end(),true));
3105   DataArrayInt *cellsInM1ToRenumW4Tmp=0;
3106   m1->areCellsIncludedIn(cellsInM1ToRenumW3,2,cellsInM1ToRenumW4Tmp);
3107   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsInM1ToRenumW4(cellsInM1ToRenumW4Tmp);
3108   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsInM1ToRenumW5=cellsInM1ToRenumW4->getIdsInRange(0,m1->getNumberOfCells());
3109   cellsInM1ToRenumW5->transformWithIndArr(cellsInM1ToRenumW4->begin(),cellsInM1ToRenumW4->end());
3110   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> grpIds=getGroupArr(-1,grpNameM1);
3111   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsInM1ToRenum=cellsInM1ToRenumW5->buildSubstraction(grpIds);
3112   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Part=static_cast<MEDCouplingUMesh *>(m1->buildPartOfMySelf(cellsInM1ToRenum->begin(),cellsInM1ToRenum->end(),true));
3113   m1Part->duplicateNodesInConn(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),nbNodes);
3114   m1->setPartOfMySelf(cellsInM1ToRenum->begin(),cellsInM1ToRenum->end(),*m1Part);
3115   // end of node renumbering of cells in m1 impacted by duplication of node but not in group of level -1 'grpNameM1'
3116   tmp0->duplicateNodes(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end());
3117   m0->setCoords(tmp0->getCoords());
3118   m0->setPartOfMySelf(cellsToModifyConn0->begin(),cellsToModifyConn0->end(),*tmp0);
3119   m1->setCoords(m0->getCoords());
3120   _coords=m0->getCoords(); _coords->incrRef();
3121   // duplication of cells in group 'grpNameM1' on level -1
3122   m11->duplicateNodesInConn(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),nbNodes); m11->setCoords(m0->getCoords());
3123   std::vector<const MEDCouplingUMesh *> v(2); v[0]=m1; v[1]=m11;
3124   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> newm1=MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(v,tmp00,tmp11);
3125   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> szOfCellGrpOfSameType(tmp00);
3126   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idInMsOfCellGrpOfSameType(tmp11);
3127   //
3128   newm1->setName(getName().c_str());
3129   const DataArrayInt *fam=getFamilyFieldAtLevel(-1);
3130   if(!fam)
3131     throw INTERP_KERNEL::Exception("MEDFileUMesh::duplicateNodesOnM1Group : internal problem !");
3132   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newFam=DataArrayInt::New();
3133   newFam->alloc(newm1->getNumberOfCells(),1);
3134   int idd=getMaxFamilyId()+1;
3135   int globStart=0,start=0,end,globEnd;
3136   int nbOfChunks=szOfCellGrpOfSameType->getNumberOfTuples();
3137   for(int i=0;i<nbOfChunks;i++)
3138     {
3139       globEnd=globStart+szOfCellGrpOfSameType->getIJ(i,0);
3140       if(idInMsOfCellGrpOfSameType->getIJ(i,0)==0)
3141         {
3142           end=start+szOfCellGrpOfSameType->getIJ(i,0);
3143           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=fam->selectByTupleId2(start,end,1);
3144           newFam->setPartOfValues1(part,globStart,globEnd,1,0,1,1,true);
3145           start=end;
3146         }
3147       else
3148         {
3149           newFam->setPartOfValuesSimple1(idd,globStart,globEnd,1,0,1,1);
3150         }
3151       globStart=globEnd;
3152     }
3153   newm1->setCoords(getCoords());
3154   setMeshAtLevel(-1,newm1);
3155   setFamilyFieldArr(-1,newFam);
3156   std::string grpName2(grpNameM1); grpName2+="_dup";
3157   addFamily(grpName2.c_str(),idd);
3158   addFamilyOnGrp(grpName2.c_str(),grpName2.c_str());
3159   //
3160   fam=_fam_coords;
3161   if(fam)
3162     {
3163       int newNbOfNodes=getCoords()->getNumberOfTuples();
3164       newFam=DataArrayInt::New(); newFam->alloc(newNbOfNodes,1);
3165       newFam->setPartOfValues1(fam,0,nbNodes,1,0,1,1,true);
3166       newFam->setPartOfValuesSimple1(0,nbNodes,newNbOfNodes,1,0,1,1);
3167       _fam_coords=newFam;
3168     }
3169   nodesDuplicated=nodeIdsToDuplicate.retn();
3170   cellsModified=cellsToModifyConn0.retn();
3171   cellsNotModified=cellsToModifyConn1.retn();
3172 }
3173
3174 /*!
3175  * \param [out] oldCode retrieves the distribution of types before the call if true is returned
3176  * \param [out] newCode etrieves the distribution of types after the call if true is returned
3177  * \param [out] o2nRenumCell tells for **all levels** the old 2 new renumbering of cells.
3178  * 
3179  * \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.
3180  * 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.
3181  */
3182 bool MEDFileUMesh::unPolyze(std::vector<int>& oldCode, std::vector<int>& newCode, DataArrayInt *& o2nRenumCell) throw(INTERP_KERNEL::Exception)
3183 {
3184   o2nRenumCell=0; oldCode.clear(); newCode.clear();
3185   std::vector<int> levs=getNonEmptyLevels();
3186   bool ret=false;
3187   std::vector< const DataArrayInt* > renumCellsSplited;//same than memorySaverIfThrow
3188   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > memorySaverIfThrow;//same than renumCellsSplited only in case of throw
3189   int start=0;
3190   int end=0;
3191   for(std::vector<int>::reverse_iterator it=levs.rbegin();it!=levs.rend();it++)
3192     {
3193       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=getMeshAtLevel(*it);
3194       std::vector<int> code1=m->getDistributionOfTypes();
3195       end=PutInThirdComponentOfCodeOffset(code1,start);
3196       oldCode.insert(oldCode.end(),code1.begin(),code1.end());
3197       bool hasChanged=m->unPolyze();
3198       DataArrayInt *fake=0;
3199       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nCellsPart=m->getLevArrPerCellTypes(MEDCouplingUMesh::MEDMEM_ORDER,
3200                                                                                            MEDCouplingUMesh::MEDMEM_ORDER+MEDCouplingUMesh::N_MEDMEM_ORDER,fake);
3201       fake->decrRef();
3202       renumCellsSplited.push_back(o2nCellsPart); memorySaverIfThrow.push_back(o2nCellsPart);
3203       if(hasChanged)
3204         {
3205           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nCellsPart2=o2nCellsPart->buildPermArrPerLevel();
3206           m->renumberCells(o2nCellsPart2->getConstPointer(),false);
3207           ret=true;
3208           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famField2,numField2;
3209           const DataArrayInt *famField=getFamilyFieldAtLevel(*it); if(famField) { famField->incrRef(); famField2=const_cast<DataArrayInt *>(famField); }
3210           const DataArrayInt *numField=getNumberFieldAtLevel(*it); if(numField) { numField->incrRef(); numField2=const_cast<DataArrayInt *>(numField); }
3211           setMeshAtLevel(*it,m);
3212           std::vector<int> code2=m->getDistributionOfTypes();
3213           end=PutInThirdComponentOfCodeOffset(code2,start);
3214           newCode.insert(newCode.end(),code2.begin(),code2.end());
3215           //
3216           if(o2nCellsPart2->isIdentity())
3217             continue;
3218           if(famField)
3219             {
3220               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newFamField=famField->renumber(o2nCellsPart2->getConstPointer());
3221               setFamilyFieldArr(*it,newFamField);
3222             }
3223           if(numField)
3224             {
3225               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newNumField=numField->renumber(o2nCellsPart2->getConstPointer());
3226               setRenumFieldArr(*it,newNumField);
3227             }
3228         }
3229       else
3230         {
3231           newCode.insert(newCode.end(),code1.begin(),code1.end());
3232         }
3233       start=end;
3234     }
3235   if(ret)
3236     {
3237       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renumCells=DataArrayInt::Aggregate(renumCellsSplited);
3238       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRenumCellRet=renumCells->buildPermArrPerLevel();
3239       o2nRenumCell=o2nRenumCellRet.retn();
3240     }
3241   return ret;
3242 }
3243
3244 struct MEDLoaderAccVisit1
3245 {
3246   MEDLoaderAccVisit1():_new_nb_of_nodes(0) { }
3247   int operator()(bool val) { return val?_new_nb_of_nodes++:-1; }
3248   int _new_nb_of_nodes;
3249 };
3250
3251 /*!
3252  * 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.
3253  * The maximum value stored in returned array is the number of nodes of \a this minus 1 after call of this method.
3254  * The size of returned array is the number of nodes of the old (previous to the call of this method) number of nodes.
3255  * -1 values in returned array means that the corresponding old node is no more used.
3256  *
3257  * \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
3258  *         is modified in \a this.
3259  * \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
3260  *  set coordinates.
3261  */
3262 DataArrayInt *MEDFileUMesh::zipCoords() throw(INTERP_KERNEL::Exception)
3263 {
3264   const DataArrayDouble *coo=getCoords();
3265   if(!coo)
3266     throw INTERP_KERNEL::Exception("MEDFileUMesh::zipCoords : no coordinates set in this !");
3267   int nbOfNodes=coo->getNumberOfTuples();
3268   std::vector<bool> nodeIdsInUse(nbOfNodes,false);
3269   std::vector<int> neLevs=getNonEmptyLevels();
3270   for(std::vector<int>::const_iterator lev=neLevs.begin();lev!=neLevs.end();lev++)
3271     {
3272       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=getMeshAtLevel(*lev);
3273       m->computeNodeIdsAlg(nodeIdsInUse);
3274     }
3275   int nbrOfNodesInUse=(int)std::count(nodeIdsInUse.begin(),nodeIdsInUse.end(),true);
3276   if(nbrOfNodesInUse==nbOfNodes)
3277     return 0;
3278   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodes,1);
3279   std::transform(nodeIdsInUse.begin(),nodeIdsInUse.end(),ret->getPointer(),MEDLoaderAccVisit1());
3280   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2=ret->invertArrayO2N2N2OBis(nbrOfNodesInUse);
3281   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->selectByTupleIdSafe(ret2->begin(),ret2->end());
3282   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newFamCoords;
3283   MEDCouplingAutoRefCountObjectPtr<DataArrayAsciiChar> newNameCoords;
3284   if((const DataArrayInt *)_fam_coords)
3285     newFamCoords=_fam_coords->selectByTupleIdSafe(ret2->begin(),ret2->end());
3286   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newNumCoords;
3287   if((const DataArrayInt *)_num_coords)
3288     newNumCoords=_num_coords->selectByTupleIdSafe(ret2->begin(),ret2->end());
3289   if((const DataArrayAsciiChar *)_name_coords)
3290     newNameCoords=static_cast<DataArrayAsciiChar *>(_name_coords->selectByTupleIdSafe(ret2->begin(),ret2->end()));
3291   _coords=newCoords; _fam_coords=newFamCoords; _num_coords=newNumCoords; _name_coords=newNameCoords; _rev_num_coords=0;
3292   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
3293     {
3294       if((MEDFileUMeshSplitL1*)*it)
3295         (*it)->renumberNodesInConn(ret->begin());
3296     }
3297   return ret.retn();
3298 }
3299
3300 /*!
3301  * Adds a group of nodes to \a this mesh.
3302  *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
3303  *          The ids should be sorted and different each other (MED file norm).
3304  *  \throw If the node coordinates array is not set.
3305  *  \throw If \a ids == \c NULL.
3306  *  \throw If \a ids->getName() == "".
3307  *  \throw If \a ids does not respect the MED file norm.
3308  *  \throw If a group with name \a ids->getName() already exists.
3309  */
3310 void MEDFileUMesh::addNodeGroup(const DataArrayInt *ids) throw(INTERP_KERNEL::Exception)
3311 {
3312   const DataArrayDouble *coords=_coords;
3313   if(!coords)
3314     throw INTERP_KERNEL::Exception("MEDFileUMesh::addNodeGroup : no coords set !");
3315   int nbOfNodes=coords->getNumberOfTuples();
3316   if(!((DataArrayInt *)_fam_coords))
3317     { _fam_coords=DataArrayInt::New(); _fam_coords->alloc(nbOfNodes,1); _fam_coords->fillWithZero(); }
3318   //
3319   addGroupUnderground(true,ids,_fam_coords);
3320 }
3321
3322 /*!
3323  * Adds a group of nodes/cells/faces/edges to \a this mesh.
3324  *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
3325  *          The ids should be sorted and different each other (MED file norm).
3326  *  \throw If the node coordinates array is not set.
3327  *  \throw If \a ids == \c NULL.
3328  *  \throw If \a ids->getName() == "".
3329  *  \throw If \a ids does not respect the MED file norm.
3330  *  \throw If a group with name \a ids->getName() already exists.
3331  */
3332 void MEDFileUMesh::addGroup(int meshDimRelToMaxExt, const DataArrayInt *ids) throw(INTERP_KERNEL::Exception)
3333 {
3334   std::vector<int> levs=getNonEmptyLevelsExt();
3335   if(std::find(levs.begin(),levs.end(),meshDimRelToMaxExt)==levs.end())
3336     { 
3337       std::ostringstream oss; oss << "MEDFileUMesh::addGroup : level " << meshDimRelToMaxExt << " not available ! Should be in ";
3338       std::copy(levs.begin(),levs.end(),std::ostream_iterator<int>(oss," ")); oss << " !"; throw INTERP_KERNEL::Exception(oss.str().c_str());
3339     }
3340   if(meshDimRelToMaxExt==1)
3341     { addNodeGroup(ids); return ; }
3342   MEDFileUMeshSplitL1 *lev=getMeshAtLevSafe(meshDimRelToMaxExt);
3343   DataArrayInt *fam=lev->getOrCreateAndGetFamilyField();
3344   addGroupUnderground(false,ids,fam);
3345 }
3346
3347 /*!
3348  * \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).
3349  * \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)
3350  */
3351 void MEDFileUMesh::addGroupUnderground(bool isNodeGroup, const DataArrayInt *ids, DataArrayInt *famArr) throw(INTERP_KERNEL::Exception)
3352 {
3353   if(!ids)
3354     throw INTERP_KERNEL::Exception("MEDFileUMesh::addGroup : NULL pointer in input !");
3355   std::string grpName(ids->getName());
3356   if(grpName.empty())
3357     throw INTERP_KERNEL::Exception("MEDFileUMesh::addGroup : empty group name ! MED file format do not accept empty group name !");
3358   ids->checkStrictlyMonotonic(true);
3359   famArr->incrRef(); MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famArrTmp(famArr);
3360   std::vector<std::string> grpsNames=getGroupsNames();
3361   if(std::find(grpsNames.begin(),grpsNames.end(),grpName)!=grpsNames.end())
3362     {
3363       std::ostringstream oss; oss << "MEDFileUMesh::addGroup : Group with name \"" << grpName << "\" already exists ! Destroy it before calling this method !";
3364       throw INTERP_KERNEL::Exception(oss.str().c_str());
3365     }
3366   std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > allFamIds=getAllNonNullFamilyIds();
3367   allFamIds.erase(std::find(allFamIds.begin(),allFamIds.end(),famArrTmp));
3368   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famIds=famArr->selectByTupleIdSafe(ids->begin(),ids->end());
3369   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffFamIds=famIds->getDifferentValues();
3370   std::vector<int> familyIds;
3371   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerfamiliyIds;
3372   int maxVal=getTheMaxAbsFamilyId()+1;
3373   std::map<std::string,int> families(_families);
3374   std::map<std::string, std::vector<std::string> > groups(_groups);
3375   std::vector<std::string> fams;
3376   bool created(false);
3377   for(const int *famId=diffFamIds->begin();famId!=diffFamIds->end();famId++)
3378     {
3379       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2Tmp=famIds->getIdsEqual(*famId);
3380       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=ids->selectByTupleId(ids2Tmp->begin(),ids2Tmp->end());
3381       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids1=famArr->getIdsEqual(*famId);
3382       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(ids1->buildSubstractionOptimized(ids2));
3383       if(ret0->empty())
3384         {
3385           bool isFamPresent=false;
3386           for(std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::const_iterator itl=allFamIds.begin();itl!=allFamIds.end() && !isFamPresent;itl++)
3387             isFamPresent=(*itl)->presenceOfValue(*famId);
3388           if(!isFamPresent)
3389             { familyIds.push_back(*famId); idsPerfamiliyIds.push_back(ret0); fams.push_back(FindOrCreateAndGiveFamilyWithId(families,*famId,created)); } // adding *famId in grp
3390           else
3391             {
3392               familyIds.push_back(isNodeGroup?maxVal:-maxVal); idsPerfamiliyIds.push_back(ids2);
3393               std::string locFamName=FindOrCreateAndGiveFamilyWithId(families,isNodeGroup?maxVal:-maxVal,created);
3394               fams.push_back(locFamName);
3395               if(existsFamily(*famId))
3396                 {
3397                   std::string locFamName2=getFamilyNameGivenId(*famId); std::vector<std::string> v(2); v[0]=locFamName2; v[1]=locFamName;
3398                   ChangeAllGroupsContainingFamily(groups,getFamilyNameGivenId(*famId).c_str(),v);
3399                 }
3400               maxVal++;
3401             } // modifying all other groups on *famId to lie on maxVal and lie the grp on maxVal
3402         }
3403       else
3404         {
3405           familyIds.push_back(isNodeGroup?maxVal:-maxVal); idsPerfamiliyIds.push_back(ret0); // modifying all other groups on *famId to lie on maxVal and on maxVal+1
3406           familyIds.push_back(isNodeGroup?maxVal+1:-maxVal-1); idsPerfamiliyIds.push_back(ids2);//grp lie only on maxVal+1
3407           std::string n2(FindOrCreateAndGiveFamilyWithId(families,isNodeGroup?maxVal+1:-maxVal-1,created)); fams.push_back(n2);
3408           if(existsFamily(*famId))
3409             {
3410               std::string n1(FindOrCreateAndGiveFamilyWithId(families,isNodeGroup?maxVal:-maxVal,created)); std::vector<std::string> v(2); v[0]=n1; v[1]=n2;
3411               ChangeAllGroupsContainingFamily(groups,getFamilyNameGivenId(*famId).c_str(),v);
3412             }
3413           maxVal+=2;
3414         }
3415     }
3416   for(std::size_t i=0;i<familyIds.size();i++)
3417     {
3418       DataArrayInt *da=idsPerfamiliyIds[i];
3419       famArr->setPartOfValuesSimple3(familyIds[i],da->begin(),da->end(),0,1,1);
3420     }
3421   _families=families;
3422   _groups=groups;
3423   _groups[grpName]=fams;
3424 }
3425
3426 /*!
3427  * Changes a name of a family specified by its id.
3428  *  \param [in] id - the id of the family of interest.
3429  *  \param [in] newFamName - the new family name.
3430  *  \throw If no family with the given \a id exists.
3431  */
3432 void MEDFileUMesh::setFamilyNameAttachedOnId(int id, const std::string& newFamName) throw(INTERP_KERNEL::Exception)
3433 {
3434   std::string oldName=getFamilyNameGivenId(id);
3435   _families.erase(oldName);
3436   _families[newFamName]=id;
3437 }
3438
3439 /*!
3440  * Removes a mesh of a given dimension.
3441  *  \param [in] meshDimRelToMax - the relative dimension of interest.
3442  *  \throw If there is no mesh at level \a meshDimRelToMax in \a this mesh.
3443  */
3444 void MEDFileUMesh::removeMeshAtLevel(int meshDimRelToMax) throw(INTERP_KERNEL::Exception)
3445 {
3446   std::vector<int> levSet=getNonEmptyLevels();
3447   std::vector<int>::const_iterator it=std::find(levSet.begin(),levSet.end(),meshDimRelToMax);
3448   if(it==levSet.end())
3449     throw INTERP_KERNEL::Exception("MEDFileUMesh::removeMeshAtLevel : the requested level is not existing !");
3450   int pos=(-meshDimRelToMax);
3451   _ms[pos]=0;
3452 }
3453
3454 /*!
3455  * Sets a new MEDCouplingUMesh at a given level in \a this mesh.
3456  *  \param [in] meshDimRelToMax - a relative level to set the mesh at.
3457  *  \param [in] m - the new mesh to set.
3458  *  \param [in] newOrOld - if \c true, cells in \a m are sorted by type to be ready for 
3459  *         writing \a this mesh in a MED file.
3460  *  \throw If the name or the description of \a this mesh and \a m are not empty and are
3461  *         different. 
3462  *  \throw If the node coordinates array is set \a this in mesh and \a m refers to
3463  *         another node coordinates array.
3464  *  \throw If the mesh dimension of \a m does not correspond to \a meshDimRelToMax or
3465  *         to the existing meshes of other levels of \a this mesh.
3466  */
3467 void MEDFileUMesh::setMeshAtLevel(int meshDimRelToMax, MEDCouplingUMesh *m, bool newOrOld) throw(INTERP_KERNEL::Exception)
3468 {
3469   dealWithTinyInfo(m);
3470   std::vector<int> levSet=getNonEmptyLevels();
3471   if(std::find(levSet.begin(),levSet.end(),meshDimRelToMax)==levSet.end())
3472     {
3473       if((DataArrayDouble *)_coords==0)
3474         {
3475           DataArrayDouble *c=m->getCoords();
3476           if(c)
3477             c->incrRef();
3478           _coords=c;
3479         }
3480       if(m->getCoords()!=_coords)
3481         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshAtLevel : Invalid Given Mesh ! The coordinates are not the same ! try to use tryToShareSameCoords !");
3482       int sz=(-meshDimRelToMax)+1;
3483       if(sz>=(int)_ms.size())
3484         _ms.resize(sz);
3485       checkMeshDimCoherency(m->getMeshDimension(),meshDimRelToMax);
3486       _ms[sz-1]=new MEDFileUMeshSplitL1(m,newOrOld);
3487     }
3488   else
3489     _ms[-meshDimRelToMax]=new MEDFileUMeshSplitL1(m,newOrOld);
3490 }
3491
3492 /*!
3493  * This method allows to set at once the content of different levels in \a this.
3494  * This method is equivalent to a series of call to MEDFileUMesh::setMeshAtLevel.
3495  *
3496  * \param [in] ms - List of unstructured meshes lying on the same coordinates and having different mesh dimesnion.
3497  * \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.
3498  *                     If false, an exception ois thrown. If true the mesh is reordered automatically. It is highly recommanded to let this parameter to false.
3499  *
3500  * \throw If \a there is a null pointer in \a ms.
3501  * \sa MEDFileUMesh::setMeshAtLevel
3502  */
3503 void MEDFileUMesh::setMeshes(const std::vector<const MEDCouplingUMesh *>& ms, bool renum) throw(INTERP_KERNEL::Exception)
3504 {
3505   if(ms.empty())
3506     return ;
3507   const MEDCouplingUMesh *mRef=ms[0];
3508   if(!mRef)
3509     throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : null instance in the first element of input meshes !");
3510   std::string name(mRef->getName());
3511   const DataArrayDouble *coo(mRef->getCoords());
3512   std::set<int> s;
3513   int zeDim=-1;
3514   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
3515     {
3516       const MEDCouplingUMesh *cur(*it);
3517       if(!cur)
3518         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : null instance in input vector of meshes !");
3519       if(coo!=cur->getCoords())
3520         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : The input meshes do not share the same coordinates !");
3521       int mdim=cur->getMeshDimension();
3522       zeDim=std::max(zeDim,mdim);
3523       if(s.find(mdim)!=s.end())
3524         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : The input meshes must share the same coordinates pointer, and should have different mesh dimension each other !");
3525     }
3526   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
3527     {
3528       int mdim=(*it)->getMeshDimension();
3529       setName((*it)->getName().c_str());
3530       setMeshAtLevel(mdim-zeDim,const_cast<MEDCouplingUMesh *>(*it),renum);
3531     }
3532   setName(name.c_str());
3533 }
3534
3535 /*!
3536  * Creates one MEDCouplingUMesh at a given level in \a this mesh from a sequence of
3537  * meshes each representing a group, and creates corresponding groups in \a this mesh.
3538  * The given meshes must share the same node coordinates array.
3539  *  \param [in] meshDimRelToMax - the relative dimension to create the mesh and groups at.
3540  *  \param [in] ms - the sequence of meshes. Each mesh in \a ms represents a group to
3541  *          create in \a this mesh.
3542  *  \throw If \a ms is empty.
3543  *  \throw If dimension of meshes in \a ms does not correspond to \a meshDimRelToMax or
3544  *         to the existing meshes of other levels of \a this mesh.
3545  *  \throw If the meshes in \a ms do not share the same node coordinates array.
3546  *  \throw If the node coordinates array of \a this mesh (if any) is not the same as that
3547  *         of the given meshes.
3548  *  \throw If \a ms[ i ] is not well defined (MEDCouplingUMesh::checkCoherency()).
3549  *  \throw If names of some meshes in \a ms are equal.
3550  *  \throw If \a ms includes a mesh with an empty name.
3551  */
3552 void MEDFileUMesh::setGroupsFromScratch(int meshDimRelToMax, const std::vector<const MEDCouplingUMesh *>& ms, bool renum) throw(INTERP_KERNEL::Exception)
3553 {
3554   if(ms.empty())
3555     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsFromScratch : expecting a non empty vector !");
3556   int sz=(-meshDimRelToMax)+1;
3557   if(sz>=(int)_ms.size())
3558     _ms.resize(sz);
3559   checkMeshDimCoherency(ms[0]->getMeshDimension(),meshDimRelToMax);
3560   DataArrayDouble *coo=checkMultiMesh(ms);
3561   if((DataArrayDouble *)_coords==0)
3562     {
3563       coo->incrRef();
3564       _coords=coo;
3565     }
3566   else
3567     if((DataArrayDouble *)_coords!=coo)
3568       throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsFromScratch : coordinates mismatches !");
3569   std::vector<DataArrayInt *> corr;
3570   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MEDCouplingUMesh::FuseUMeshesOnSameCoords(ms,_zipconn_pol,corr);
3571   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > corr3(corr.begin(),corr.end());
3572   setMeshAtLevel(meshDimRelToMax,m,renum);
3573   std::vector<const DataArrayInt *> corr2(corr.begin(),corr.end());
3574   setGroupsAtLevel(meshDimRelToMax,corr2,true);
3575 }
3576
3577 /*!
3578  * Creates groups at a given level in \a this mesh from a sequence of
3579  * meshes each representing a group.
3580  * The given meshes must share the same node coordinates array.
3581  *  \param [in] meshDimRelToMax - the relative dimension to create the groups at.
3582  *  \param [in] ms - the sequence of meshes. Each mesh in \a ms represents a group to
3583  *         create in \a this mesh.
3584  *  \param [in] renum - if \c true, then the optional numbers of entities are taken into
3585  *         account. 
3586  *  \throw If \a ms is empty.
3587  *  \throw If dimension of meshes in \a ms does not correspond to \a meshDimRelToMax or
3588  *         to the existing meshes of other levels of \a this mesh.
3589  *  \throw If the meshes in \a ms do not share the same node coordinates array.
3590  *  \throw If the node coordinates array of \a this mesh (if any) is not the same as that
3591  *         of the given meshes.
3592  *  \throw If \a ms[ i ] is not well defined (MEDCouplingUMesh::checkCoherency()).
3593  *  \throw If names of some meshes in \a ms are equal.
3594  *  \throw If \a ms includes a mesh with an empty name.
3595  */
3596 void MEDFileUMesh::setGroupsOnSetMesh(int meshDimRelToMax, const std::vector<const MEDCouplingUMesh *>& ms, bool renum) throw(INTERP_KERNEL::Exception)
3597 {
3598   if(ms.empty())
3599     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsOnSetMesh : expecting a non empty vector !");
3600   int sz=(-meshDimRelToMax)+1;
3601   if(sz>=(int)_ms.size())
3602     _ms.resize(sz);
3603   checkMeshDimCoherency(ms[0]->getMeshDimension(),meshDimRelToMax);
3604   DataArrayDouble *coo=checkMultiMesh(ms);
3605   if((DataArrayDouble *)_coords==0)
3606     {
3607       coo->incrRef();
3608       _coords=coo;
3609     }
3610   else
3611     if((DataArrayDouble *)_coords!=coo)
3612       throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsOnSetMesh : coordinates mismatches !");
3613   MEDCouplingUMesh *m=getMeshAtLevel(meshDimRelToMax,renum);
3614   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > corr(ms.size());
3615   int i=0;
3616   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++,i++)
3617     {
3618       DataArrayInt *arr=0;
3619       bool test=m->areCellsIncludedIn(*it,_zipconn_pol,arr);
3620       corr[i]=arr;
3621       if(!test)
3622         {
3623           std::ostringstream oss; oss << "MEDFileUMesh::setGroupsOnSetMesh : mesh #" << i << " is not part of whole mesh !";
3624           throw INTERP_KERNEL::Exception(oss.str().c_str());
3625         }
3626     }
3627   std::vector<const DataArrayInt *> corr2(corr.begin(),corr.end());
3628   setGroupsAtLevel(meshDimRelToMax,corr2,renum);
3629 }
3630
3631 DataArrayDouble *MEDFileUMesh::checkMultiMesh(const std::vector<const MEDCouplingUMesh *>& ms) const throw(INTERP_KERNEL::Exception)
3632 {
3633   const DataArrayDouble *ret=ms[0]->getCoords();
3634   int mdim=ms[0]->getMeshDimension();
3635   for(unsigned int i=1;i<ms.size();i++)
3636     {
3637       ms[i]->checkCoherency();
3638       if(ms[i]->getCoords()!=ret)
3639         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMultiMesh : meshes must share the same coords !");
3640       if(ms[i]->getMeshDimension()!=mdim)
3641         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMultiMesh : meshes have not same mesh dimension !");
3642     }
3643   return const_cast<DataArrayDouble *>(ret);
3644 }
3645
3646 /*!
3647  * Sets the family field of a given relative dimension.
3648  *  \param [in] meshDimRelToMaxExt - the relative dimension of entities for which
3649  *          the family field is set.
3650  *  \param [in] famArr - the array of the family field.
3651  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3652  *  \throw If \a famArr has an invalid size.
3653  */
3654 void MEDFileUMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr) throw(INTERP_KERNEL::Exception)
3655 {
3656   if(meshDimRelToMaxExt==1)
3657     {
3658       if(!famArr)
3659         {
3660           _fam_coords=0;
3661           return ;
3662         }
3663       DataArrayDouble *coo(_coords);
3664       if(!coo)
3665         throw INTERP_KERNEL::Exception("MEDFileUMesh::setFamilyFieldArr : the coordinates have not been set !");
3666       famArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),1,"MEDFileUMesh::setFamilyFieldArr : Problem in size of node family arr ! ");
3667       famArr->incrRef();
3668       _fam_coords=famArr;
3669       return ;
3670     }
3671   if(meshDimRelToMaxExt>1)
3672     throw INTERP_KERNEL::Exception("MEDFileUMesh::setFamilyFieldArr : Dimension request is invalid (>1) !");
3673   int traducedRk=-meshDimRelToMaxExt;
3674   if(traducedRk>=(int)_ms.size())
3675     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
3676   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
3677     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3678   return _ms[traducedRk]->setFamilyArr(famArr);
3679 }
3680
3681 /*!
3682  * Sets the optional numbers of mesh entities of a given dimension.
3683  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
3684  *  \param [in] renumArr - the array of the numbers.
3685  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3686  *  \throw If \a renumArr has an invalid size.
3687  */
3688 void MEDFileUMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr) throw(INTERP_KERNEL::Exception)
3689 {
3690   if(meshDimRelToMaxExt==1)
3691     {
3692       if(!renumArr)
3693         {
3694           _num_coords=0;
3695           _rev_num_coords=0;
3696           return ;
3697         }
3698       DataArrayDouble *coo(_coords);
3699       if(!coo)
3700         throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumFieldArr : the coordinates have not been set !");
3701       renumArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),1,"MEDFileUMesh::setRenumArr : Problem in size of node numbering arr ! ");
3702       renumArr->incrRef();
3703       _num_coords=renumArr;
3704       computeRevNum();
3705       return ;
3706     }
3707   if(meshDimRelToMaxExt>1)
3708     throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumArr : Dimension request is invalid (>1) !");
3709   int traducedRk=-meshDimRelToMaxExt;
3710   if(traducedRk>=(int)_ms.size())
3711     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
3712   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
3713     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3714   return _ms[traducedRk]->setRenumArr(renumArr);
3715 }
3716
3717 /*!
3718  * Sets the optional names of mesh entities of a given dimension.
3719  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
3720  *  \param [in] nameArr - the array of the names.
3721  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3722  *  \throw If \a nameArr has an invalid size.
3723  */
3724 void MEDFileUMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr) throw(INTERP_KERNEL::Exception)
3725 {
3726   if(meshDimRelToMaxExt==1)
3727     {
3728       if(!nameArr)
3729         {
3730           _name_coords=0;
3731           return ;
3732         }
3733       DataArrayDouble *coo(_coords);
3734       if(!coo)
3735         throw INTERP_KERNEL::Exception("MEDFileUMesh::setNameFieldAtLevel : the coordinates have not been set !");
3736       nameArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),MED_SNAME_SIZE,"MEDFileUMesh::setNameFieldAtLevel : Problem in size of node numbering arr ! ");
3737       nameArr->incrRef();
3738       _name_coords=nameArr;
3739       return ;
3740     }
3741   if(meshDimRelToMaxExt>1)
3742     throw INTERP_KERNEL::Exception("MEDFileUMesh::setNameFieldAtLevel : Dimension request is invalid (>1) !");
3743   int traducedRk=-meshDimRelToMaxExt;
3744   if(traducedRk>=(int)_ms.size())
3745     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
3746   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
3747     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3748   return _ms[traducedRk]->setNameArr(nameArr);
3749 }
3750
3751 void MEDFileUMesh::synchronizeTinyInfoOnLeaves() const
3752 {
3753   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
3754     if((const MEDFileUMeshSplitL1 *)(*it))
3755       (*it)->synchronizeTinyInfo(*this);
3756 }
3757
3758 /*!
3759  * This method is called by MEDFileMesh::changeFamilyId. It performs only one part of the family id modification.
3760  */
3761 void MEDFileUMesh::changeFamilyIdArr(int oldId, int newId) throw(INTERP_KERNEL::Exception)
3762 {
3763   DataArrayInt *arr=_fam_coords;
3764   if(arr)
3765     arr->changeValue(oldId,newId);
3766   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
3767     {
3768       MEDFileUMeshSplitL1 *sp=(*it);
3769       if(sp)
3770         {
3771           sp->changeFamilyIdArr(oldId,newId);
3772         }
3773     }
3774 }
3775
3776 std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > MEDFileUMesh::getAllNonNullFamilyIds() const
3777 {
3778   std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret;
3779   const DataArrayInt *da(_fam_coords);
3780   if(da)
3781     { da->incrRef(); ret.push_back(MEDCouplingAutoRefCountObjectPtr<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
3782   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
3783     {
3784       const MEDFileUMeshSplitL1 *elt(*it);
3785       if(elt)
3786         {
3787           da=elt->getFamilyField();
3788           if(da)
3789             { da->incrRef(); ret.push_back(MEDCouplingAutoRefCountObjectPtr<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
3790         }
3791     }
3792   return ret;
3793 }
3794
3795 void MEDFileUMesh::computeRevNum() const
3796 {
3797   if((const DataArrayInt *)_num_coords)
3798     {
3799       int pos;
3800       int maxValue=_num_coords->getMaxValue(pos);
3801       _rev_num_coords=_num_coords->invertArrayN2O2O2N(maxValue+1);
3802     }
3803 }
3804
3805 std::size_t MEDFileStructuredMesh::getHeapMemorySize() const
3806 {
3807   std::size_t ret=MEDFileMesh::getHeapMemorySize();
3808   if((const DataArrayInt*)_fam_nodes)
3809     ret+=_fam_nodes->getHeapMemorySize();
3810   if((const DataArrayInt*)_num_nodes)
3811     ret+=_num_nodes->getHeapMemorySize();
3812   if((const DataArrayInt*)_fam_cells)
3813     ret+=_fam_cells->getHeapMemorySize();
3814   if((const DataArrayInt*)_num_cells)
3815     ret+=_num_cells->getHeapMemorySize();
3816   if((const DataArrayInt*)_rev_num_nodes)
3817     ret+=_rev_num_nodes->getHeapMemorySize();
3818   if((const DataArrayInt*)_rev_num_cells)
3819     ret+=_rev_num_cells->getHeapMemorySize();
3820   return ret;
3821 }
3822
3823 int MEDFileStructuredMesh::getMaxAbsFamilyIdInArrays() const throw(INTERP_KERNEL::Exception)
3824 {
3825   int ret=-std::numeric_limits<int>::max(),tmp=-1;
3826   if((const DataArrayInt *)_fam_nodes)
3827     {
3828       int val=_fam_nodes->getMaxValue(tmp);
3829       ret=std::max(ret,std::abs(val));
3830     }
3831   if((const DataArrayInt *)_fam_cells)
3832     {
3833       int val=_fam_cells->getMaxValue(tmp);
3834       ret=std::max(ret,std::abs(val));
3835     }
3836   return ret;
3837 }
3838
3839 int MEDFileStructuredMesh::getMaxFamilyIdInArrays() const throw(INTERP_KERNEL::Exception)
3840 {
3841   int ret=-std::numeric_limits<int>::max(),tmp=-1;
3842   if((const DataArrayInt *)_fam_nodes)
3843     {
3844       int val=_fam_nodes->getMaxValue(tmp);
3845       ret=std::max(ret,val);
3846     }
3847   if((const DataArrayInt *)_fam_cells)
3848     {
3849       int val=_fam_cells->getMaxValue(tmp);
3850       ret=std::max(ret,val);
3851     }
3852   return ret;
3853 }
3854
3855 int MEDFileStructuredMesh::getMinFamilyIdInArrays() const throw(INTERP_KERNEL::Exception)
3856 {
3857   int ret=std::numeric_limits<int>::max(),tmp=-1;
3858   if((const DataArrayInt *)_fam_nodes)
3859     {
3860       int val=_fam_nodes->getMinValue(tmp);
3861       ret=std::min(ret,val);
3862     }
3863   if((const DataArrayInt *)_fam_cells)
3864     {
3865       int val=_fam_cells->getMinValue(tmp);
3866       ret=std::min(ret,val);
3867     }
3868   return ret;
3869 }
3870
3871 bool MEDFileStructuredMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
3872 {
3873   if(!MEDFileMesh::isEqual(other,eps,what))
3874     return false;
3875   const MEDFileStructuredMesh *otherC=dynamic_cast<const  MEDFileStructuredMesh *>(other);
3876   if(!otherC)
3877     {
3878       what="Mesh types differ ! This is structured and other is NOT !";
3879       return false;
3880     }
3881   const DataArrayInt *famc1=_fam_nodes;
3882   const DataArrayInt *famc2=otherC->_fam_nodes;
3883   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
3884     {
3885       what="Mismatch of families arr on nodes ! One is defined and not other !";
3886       return false;
3887     }
3888   if(famc1)
3889     {
3890       bool ret=famc1->isEqual(*famc2);
3891       if(!ret)
3892         {
3893           what="Families arr on nodes differ !";
3894           return false;
3895         }
3896     }
3897   famc1=_fam_cells;
3898   famc2=otherC->_fam_cells;
3899   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
3900     {
3901       what="Mismatch of families arr on cells ! One is defined and not other !";
3902       return false;
3903     }
3904   if(famc1)
3905     {
3906       bool ret=famc1->isEqual(*famc2);
3907       if(!ret)
3908         {
3909           what="Families arr on cells differ !";
3910           return false;
3911         }
3912     }
3913   famc1=_num_nodes;
3914   famc2=otherC->_num_nodes;
3915   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
3916     {
3917       what="Mismatch of numbering arr on nodes ! One is defined and not other !";
3918       return false;
3919     }
3920   if(famc1)
3921     {
3922       bool ret=famc1->isEqual(*famc2);
3923       if(!ret)
3924         {
3925           what="Numbering arr on nodes differ !";
3926           return false;
3927         }
3928     }
3929   famc1=_num_cells;
3930   famc2=otherC->_num_cells;
3931   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
3932     {
3933       what="Mismatch of numbering arr on cells ! One is defined and not other !";
3934       return false;
3935     }
3936   if(famc1)
3937     {
3938       bool ret=famc1->isEqual(*famc2);
3939       if(!ret)
3940         {
3941           what="Numbering arr on cells differ !";
3942           return false;
3943         }
3944     }
3945   const DataArrayAsciiChar *d1=_names_cells;
3946   const DataArrayAsciiChar *d2=otherC->_names_cells;
3947   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
3948     {
3949       what="Mismatch of naming arr on cells ! One is defined and not other !";
3950       return false;
3951     }
3952   if(d1)
3953     {
3954       bool ret=d1->isEqual(*d2);
3955       if(!ret)
3956         {
3957           what="Naming arr on cells differ !";
3958           return false;
3959         }
3960     }
3961   d1=_names_nodes;
3962   d2=otherC->_names_nodes;
3963   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
3964     {
3965       what="Mismatch of naming arr on nodes ! One is defined and not other !";
3966       return false;
3967     }
3968   if(d1)
3969     {
3970       bool ret=d1->isEqual(*d2);
3971       if(!ret)
3972         {
3973           what="Naming arr on nodes differ !";
3974           return false;
3975         }
3976     }
3977   return true;
3978 }
3979
3980 void MEDFileStructuredMesh::clearNonDiscrAttributes() const
3981 {
3982   MEDFileMesh::clearNonDiscrAttributes();
3983   const DataArrayInt *tmp=_fam_nodes;
3984   if(tmp)
3985     (const_cast<DataArrayInt *>(tmp))->setName("");
3986   tmp=_num_nodes;
3987   if(tmp)
3988     (const_cast<DataArrayInt *>(tmp))->setName("");
3989   tmp=_fam_cells;
3990   if(tmp)
3991     (const_cast<DataArrayInt *>(tmp))->setName("");
3992   tmp=_num_cells;
3993   if(tmp)
3994     (const_cast<DataArrayInt *>(tmp))->setName("");
3995 }
3996
3997 /*!
3998  * Returns ids of mesh entities contained in given families of a given dimension.
3999  *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
4000  *          are required.
4001  *  \param [in] fams - the names of the families of interest.
4002  *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
4003  *          returned instead of ids.
4004  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
4005  *          numbers, if available and required, of mesh entities of the families. The caller
4006  *          is to delete this array using decrRef() as it is no more needed. 
4007  *  \throw If the family field is missing for \a meshDimRelToMaxExt.
4008  */
4009 DataArrayInt *MEDFileStructuredMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const throw(INTERP_KERNEL::Exception)
4010 {
4011   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4012     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : Only available for levels 0 or 1 !");
4013   std::vector<int> famIds=getFamiliesIds(fams);
4014   if(meshDimRelToMaxExt==1)
4015     {
4016       if((const DataArrayInt *)_fam_nodes)
4017         {
4018           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
4019           if(!famIds.empty())
4020             da=_fam_nodes->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
4021           else
4022             da=_fam_nodes->getIdsEqualList(0,0);
4023           if(renum)
4024             return MEDFileUMeshSplitL1::Renumber(_num_nodes,da);
4025           else
4026             return da.retn();
4027         }
4028       else
4029         throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on nodes !");
4030     }
4031   else
4032     {
4033       if((const DataArrayInt *)_fam_cells)
4034         {
4035           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
4036           if(!famIds.empty())
4037             da=_fam_cells->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
4038           else
4039             da=_fam_cells->getIdsEqualList(0,0);
4040           if(renum)
4041             return MEDFileUMeshSplitL1::Renumber(_num_cells,da);
4042           else
4043             return da.retn();
4044         }
4045       else
4046         throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on cells !");
4047     }
4048 }
4049
4050 /*!
4051  * Sets the family field of a given relative dimension.
4052  *  \param [in] meshDimRelToMaxExt - the relative dimension of entities for which
4053  *          the family field is set.
4054  *  \param [in] famArr - the array of the family field.
4055  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4056  *  \throw If \a famArr has an invalid size.
4057  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
4058  */
4059 void MEDFileStructuredMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr) throw(INTERP_KERNEL::Exception)
4060 {
4061   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4062     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : Only available for levels 0 or 1 !");
4063   const MEDCouplingStructuredMesh *mesh=getStructuredMesh();
4064   if(!mesh)
4065     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setFamilyFieldArr : no structured mesh specified ! Impossible to set family array !");
4066   if(meshDimRelToMaxExt==0)
4067     {
4068       int nbCells=mesh->getNumberOfCells();
4069       famArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of cells of mesh !");
4070       _fam_cells=famArr;
4071     }
4072   else
4073     {
4074       int nbNodes=mesh->getNumberOfNodes();
4075       famArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !");
4076       _fam_nodes=famArr;
4077     }
4078   if(famArr)
4079     famArr->incrRef();
4080 }
4081
4082 /*!
4083  * Sets the optional numbers of mesh entities of a given dimension.
4084  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4085  *  \param [in] renumArr - the array of the numbers.
4086  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4087  *  \throw If \a renumArr has an invalid size.
4088  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
4089  */
4090 void MEDFileStructuredMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr) throw(INTERP_KERNEL::Exception)
4091 {
4092   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4093     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : Only available for levels 0 or 1 !");
4094   const MEDCouplingStructuredMesh *mesh=getStructuredMesh();
4095   if(!mesh)
4096     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : no structured mesh specified ! Impossible to set number array !");
4097   if(meshDimRelToMaxExt==0)
4098     {
4099       int nbCells=mesh->getNumberOfCells();
4100       renumArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Renum arr ! Mismatch with number of cells of mesh !");
4101       _num_cells=renumArr;
4102     }
4103   else
4104     {
4105       int nbNodes=mesh->getNumberOfNodes();
4106       renumArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !");
4107       _num_nodes=renumArr;
4108     }
4109   if(renumArr)
4110     renumArr->incrRef();
4111 }
4112
4113 /*!
4114  * Sets the optional names of mesh entities of a given dimension.
4115  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4116  *  \param [in] nameArr - the array of the names.
4117  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4118  *  \throw If \a nameArr has an invalid size.
4119  */
4120 void MEDFileStructuredMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr) throw(INTERP_KERNEL::Exception)
4121 {
4122   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4123     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : Only available for levels 0 or 1 !");
4124   const MEDCouplingStructuredMesh *mesh=getStructuredMesh();
4125   if(!mesh)
4126     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : no structured mesh specified ! Impossible to set names array !");
4127   if(meshDimRelToMaxExt==0)
4128     {
4129       int nbCells=mesh->getNumberOfCells();
4130       nameArr->checkNbOfTuplesAndComp(nbCells,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of cells of mesh !");
4131       _names_cells=nameArr;
4132     }
4133   else
4134     {
4135       int nbNodes=mesh->getNumberOfNodes();
4136       nameArr->checkNbOfTuplesAndComp(nbNodes,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of nodes of mesh !");
4137       _names_nodes=nameArr;
4138     }
4139   if(nameArr)
4140     nameArr->incrRef();
4141 }
4142
4143 /*!
4144  * Returns the family field for mesh entities of a given dimension.
4145  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4146  *  \return const DataArrayInt * - the family field. It is an array of ids of families
4147  *          each mesh entity belongs to. It can be \c NULL.
4148  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
4149  */
4150 const DataArrayInt *MEDFileStructuredMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
4151 {
4152   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4153     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamilyFieldAtLevel : Only available for levels 0 or 1 !");
4154   if(meshDimRelToMaxExt==0)
4155     return _fam_cells;
4156   else
4157     return _fam_nodes;
4158 }
4159
4160 /*!
4161  * Returns the optional numbers of mesh entities of a given dimension.
4162  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4163  *  \return const DataArrayInt * - the array of the entity numbers.
4164  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4165  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
4166  */
4167 const DataArrayInt *MEDFileStructuredMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
4168 {
4169   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4170     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberFieldAtLevel : Only available for levels 0 or 1 !");
4171   if(meshDimRelToMaxExt==0)
4172     return _num_cells;
4173   else
4174     return _num_nodes;
4175 }
4176
4177 /*!
4178  * Returns the optional numbers of mesh entities of a given dimension transformed using
4179  * DataArrayInt::invertArrayN2O2O2N().
4180  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4181  *  \return const DataArrayInt * - the array of the entity numbers transformed using
4182  *          DataArrayInt::invertArrayN2O2O2N().
4183  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
4184  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4185  */
4186 const DataArrayInt *MEDFileStructuredMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
4187 {
4188   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4189     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getRevNumberFieldAtLevel : Only available for levels 0 or 1 !");
4190   if(meshDimRelToMaxExt==0)
4191     {
4192       if((const DataArrayInt *)_num_cells)
4193         {
4194           int pos;
4195           int maxValue=_num_cells->getMaxValue(pos);
4196           _rev_num_cells=_num_cells->invertArrayN2O2O2N(maxValue+1);
4197           return _rev_num_cells;
4198         }
4199       else
4200         throw INTERP_KERNEL::Exception("MEDFileCMesh::getRevNumberFieldAtLevel : no cell renumbering for a request on reverse numbering !");
4201     }
4202   else
4203     {
4204       if((const DataArrayInt *)_num_nodes)
4205         {
4206           int pos;
4207           int maxValue=_num_nodes->getMaxValue(pos);
4208           _rev_num_nodes=_num_nodes->invertArrayN2O2O2N(maxValue+1);
4209           return _rev_num_nodes;
4210         }
4211       else
4212         throw INTERP_KERNEL::Exception("MEDFileCMesh::getRevNumberFieldAtLevel : no node renumbering for a request on reverse numbering !");
4213     }
4214 }
4215
4216 const DataArrayAsciiChar *MEDFileStructuredMesh::getNameFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
4217 {
4218   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4219     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNameFieldAtLevel : Only available for levels 0 or 1 !");
4220   if(meshDimRelToMaxExt==0)
4221     return _names_cells;
4222   else
4223     return _names_nodes;
4224 }
4225
4226 /*!
4227  * Returns relative dimensions of mesh entities (excluding nodes) present in \a this mesh.
4228  *  \return std::vector<int> - a sequence of the relative dimensions: [0].
4229  */
4230 std::vector<int> MEDFileStructuredMesh::getNonEmptyLevels() const
4231 {
4232   std::vector<int> ret(1);
4233   return ret;
4234 }
4235
4236 /*!
4237  * Returns relative dimensions of mesh entities (including nodes) present in \a this mesh.
4238  *  \return std::vector<int> - a sequence of the relative dimensions: [1,0].
4239  */
4240 std::vector<int> MEDFileStructuredMesh::getNonEmptyLevelsExt() const
4241 {
4242   std::vector<int> ret(2);
4243   ret[0]=1;
4244   return ret;
4245 }
4246
4247 /*!
4248  * Returns the set of extensive levels (nodes included) where not NULL family arr are defined.
4249  */
4250 std::vector<int> MEDFileStructuredMesh::getFamArrNonEmptyLevelsExt() const
4251 {
4252   std::vector<int> ret;
4253   const DataArrayInt *famNodes(_fam_nodes),*famCells(_fam_cells);
4254   if(famNodes)
4255     ret.push_back(1);
4256   if(famCells)
4257     ret.push_back(0);
4258   return ret;
4259 }
4260
4261 /*!
4262  * Returns the set of extensive levels (nodes included) where not NULL numbering arr are defined.
4263  */
4264 std::vector<int> MEDFileStructuredMesh::getNumArrNonEmptyLevelsExt() const
4265 {
4266   std::vector<int> ret;
4267   const DataArrayInt *numNodes(_num_nodes),*numCells(_num_cells);
4268   if(numNodes)
4269     ret.push_back(1);
4270   if(numCells)
4271     ret.push_back(0);
4272   return ret;
4273 }
4274
4275 /*!
4276  * Returns the set of extensive levels (nodes included) where not NULL naming arr are defined.
4277  */
4278 std::vector<int> MEDFileStructuredMesh::getNameArrNonEmptyLevelsExt() const
4279 {
4280   std::vector<int> ret;
4281   const DataArrayAsciiChar *namesCells(_names_cells);
4282   if(namesCells)
4283     ret.push_back(0);
4284   return ret;
4285 }
4286
4287 /*!
4288  * no implementation here, it is not a bug, but intresically no polyhedra in \a this.
4289  */
4290 bool MEDFileStructuredMesh::unPolyze(std::vector<int>& oldCode, std::vector<int>& newCode, DataArrayInt *& o2nRenumCell) throw(INTERP_KERNEL::Exception)
4291 {
4292   oldCode.clear(); newCode.clear(); o2nRenumCell=0;
4293   return false;
4294 }
4295
4296 void MEDFileStructuredMesh::changeFamilyIdArr(int oldId, int newId) throw(INTERP_KERNEL::Exception)
4297 {
4298   DataArrayInt *arr=_fam_nodes;
4299   if(arr)
4300     arr->changeValue(oldId,newId);
4301   arr=_fam_cells;
4302   if(arr)
4303     arr->changeValue(oldId,newId);
4304 }
4305
4306 void MEDFileStructuredMesh::deepCpyAttributes() throw(INTERP_KERNEL::Exception)
4307 {
4308   if((const DataArrayInt*)_fam_nodes)
4309     _fam_nodes=_fam_nodes->deepCpy();
4310   if((const DataArrayInt*)_num_nodes)
4311     _num_nodes=_num_nodes->deepCpy();
4312   if((const DataArrayInt*)_fam_cells)
4313     _fam_cells=_fam_cells->deepCpy();
4314   if((const DataArrayInt*)_num_cells)
4315     _num_cells=_num_cells->deepCpy();
4316   if((const DataArrayInt*)_rev_num_nodes)
4317     _rev_num_nodes=_rev_num_nodes->deepCpy();
4318   if((const DataArrayInt*)_rev_num_cells)
4319     _rev_num_cells=_rev_num_cells->deepCpy();
4320 }
4321
4322 /*!
4323  * Returns a pointer to mesh at the specified level (here 0 is compulsary for cartesian mesh).
4324  * 
4325  * \return a pointer to cartesian mesh that need to be managed by the caller.
4326  * \warning the returned pointer has to be managed by the caller.
4327  */
4328
4329 /*!
4330  * Returns a pointer to MEDCouplingStructuredMesh held by \a this. 
4331  *  \param [in] meshDimRelToMax - it must be \c 0.
4332  *  \param [in] renum - it must be \c false.
4333  *  \return MEDCouplingMesh * - a pointer to MEDCouplingMesh that the caller is to
4334  *          delete using decrRef() as it is no more needed. 
4335  */
4336 MEDCouplingMesh *MEDFileStructuredMesh::getGenMeshAtLevel(int meshDimRelToMax, bool renum) const throw(INTERP_KERNEL::Exception)
4337 {
4338   if(renum)
4339     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support renumbering ! To do it perform request of renum array directly !");
4340   if(meshDimRelToMax!=0)
4341     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support multi level for mesh 0 expected as input !");
4342   const MEDCouplingStructuredMesh *m=getStructuredMesh();
4343   if(m)
4344     m->incrRef();
4345   return const_cast<MEDCouplingStructuredMesh *>(m);
4346 }
4347
4348 /*!
4349  * Returns number of mesh entities of a given relative dimension in \a this mesh.
4350  *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
4351  *  \return int - the number of entities.
4352  *  \throw If no mesh entities of dimension \a meshDimRelToMaxExt are available in \a this mesh.
4353  */
4354 int MEDFileStructuredMesh::getSizeAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
4355 {
4356   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4357     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : Only available for levels 0 or 1 !");
4358   const MEDCouplingStructuredMesh *cmesh=getStructuredMesh();
4359   if(!cmesh)
4360     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : No structured mesh set !");
4361   if(meshDimRelToMaxExt==0)
4362     return cmesh->getNumberOfCells();
4363   else
4364     return cmesh->getNumberOfNodes();
4365 }
4366
4367 int MEDFileStructuredMesh::getNumberOfNodes() const throw(INTERP_KERNEL::Exception)
4368 {
4369   const MEDCouplingStructuredMesh *cmesh=getStructuredMesh();
4370   if(!cmesh)
4371     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberOfNodes : no cartesian mesh set !");
4372   return cmesh->getNumberOfNodes();
4373 }
4374
4375 void MEDFileStructuredMesh::whichAreNodesFetched(const MEDFileField1TSStructItem& st, const MEDFileFieldGlobsReal *globs, std::vector<bool>& nodesFetched) const throw(INTERP_KERNEL::Exception)
4376 {
4377   if(st.getNumberOfItems()!=1)
4378     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 !");
4379   if(st[0].getGeo()!=MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(getMeshDimension()))
4380     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : The sturture of field is not lying on expected geo type !");
4381   if(getNumberOfNodes()!=(int)nodesFetched.size())
4382     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : invalid size of array !");
4383   if(st[0].getPflName().empty())
4384     {
4385       std::fill(nodesFetched.begin(),nodesFetched.end(),true);
4386       return ;
4387     }
4388   const DataArrayInt *arr(globs->getProfile(st[0].getPflName().c_str()));
4389   const MEDCouplingStructuredMesh *cmesh=getStructuredMesh();//cmesh not null because getNumberOfNodes called before
4390   int sz(nodesFetched.size());
4391   for(const int *work=arr->begin();work!=arr->end();work++)
4392     {
4393       std::vector<int> conn;
4394       cmesh->getNodeIdsOfCell(*work,conn);
4395       for(std::vector<int>::const_iterator it=conn.begin();it!=conn.end();it++)
4396         if(*it>=0 && *it<sz)
4397           nodesFetched[*it]=true;
4398         else
4399           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : internal error !");
4400     }
4401 }
4402
4403 med_geometry_type MEDFileStructuredMesh::GetGeoTypeFromMeshDim(int meshDim) throw(INTERP_KERNEL::Exception)
4404 {
4405   med_geometry_type geoTypeReq=MED_NONE;
4406   switch(meshDim)
4407     {
4408     case 3:
4409       geoTypeReq=MED_HEXA8;
4410       break;
4411     case 2:
4412       geoTypeReq=MED_QUAD4;
4413       break;
4414     case 1:
4415       geoTypeReq=MED_SEG2;
4416       break;
4417     case 0:
4418       geoTypeReq=MED_POINT1;
4419       break;
4420     default:
4421       throw INTERP_KERNEL::Exception("Invalid meshdim detected for structured mesh ! Must be in (1,2,3) !");
4422     }
4423   return geoTypeReq;
4424 }
4425
4426 void MEDFileStructuredMesh::loadStrMeshFromFile(MEDFileStrMeshL2 *strm, med_idt fid, const char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception)
4427 {
4428   setName(strm->getName());
4429   setDescription(strm->getDescription());
4430   setUnivName(strm->getUnivName());
4431   setIteration(strm->getIteration());
4432   setOrder(strm->getOrder());
4433   setTimeValue(strm->getTime());
4434   setTimeUnit(strm->getTimeUnit());
4435   MEDFileMeshL2::ReadFamiliesAndGrps(fid,mName,_families,_groups,mrs);
4436   med_bool chgt=MED_FALSE,trsf=MED_FALSE;
4437   int nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_NODE,MED_NONE,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf);
4438   if(nbOfElt>0)
4439     {
4440       if(!mrs || mrs->isNodeFamilyFieldReading())
4441         {
4442           _fam_nodes=DataArrayInt::New();
4443           _fam_nodes->alloc(nbOfElt,1);
4444           MEDmeshEntityFamilyNumberRd(fid,mName,dt,it,MED_NODE,MED_NONE,_fam_nodes->getPointer());
4445         }
4446     }
4447   nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_NODE,MED_NONE,MED_NUMBER,MED_NODAL,&chgt,&trsf);
4448   if(nbOfElt>0)
4449     {
4450       if(!mrs || mrs->isNodeNumFieldReading())
4451         {
4452           _num_nodes=DataArrayInt::New();
4453           _num_nodes->alloc(nbOfElt,1);
4454           MEDmeshEntityNumberRd(fid,mName,dt,it,MED_NODE,MED_NONE,_num_nodes->getPointer());
4455         }
4456     }
4457   int meshDim=getStructuredMesh()->getMeshDimension();
4458   med_geometry_type geoTypeReq=GetGeoTypeFromMeshDim(meshDim);
4459   nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_CELL,geoTypeReq,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf);
4460   if(nbOfElt>0)
4461     {
4462       if(!mrs || mrs->isCellFamilyFieldReading())
4463         {
4464           _fam_cells=DataArrayInt::New();
4465           _fam_cells->alloc(nbOfElt,1);
4466           MEDmeshEntityFamilyNumberRd(fid,mName,dt,it,MED_CELL,geoTypeReq,_fam_cells->getPointer());
4467         }
4468     }
4469   nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_CELL,geoTypeReq,MED_NUMBER,MED_NODAL,&chgt,&trsf);
4470   if(nbOfElt>0)
4471     {
4472       if(!mrs || mrs->isCellNumFieldReading())
4473         {
4474           _num_cells=DataArrayInt::New();
4475           _num_cells->alloc(nbOfElt,1);
4476           MEDmeshEntityNumberRd(fid,mName,dt,it,MED_CELL,geoTypeReq,_num_cells->getPointer());
4477         }
4478     }
4479   nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_CELL,geoTypeReq,MED_NAME,MED_NODAL,&chgt,&trsf);
4480   if(nbOfElt>0)
4481     {
4482       if(!mrs || mrs->isCellNameFieldReading())
4483         {
4484           _names_cells=DataArrayAsciiChar::New();
4485           _names_cells->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end
4486           MEDmeshEntityNameRd(fid,mName,dt,it,MED_CELL,geoTypeReq,_names_cells->getPointer());
4487           _names_cells->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end
4488         }
4489     }
4490   nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_NODE,MED_NONE,MED_NAME,MED_NODAL,&chgt,&trsf);
4491   if(nbOfElt>0)
4492     {
4493       if(!mrs || mrs->isNodeNameFieldReading())
4494         {
4495           _names_nodes=DataArrayAsciiChar::New();
4496           _names_nodes->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end
4497           MEDmeshEntityNameRd(fid,mName,dt,it,MED_NODE,MED_NONE,_names_nodes->getPointer());
4498           _names_nodes->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end
4499         }
4500     }
4501 }
4502
4503 void MEDFileStructuredMesh::writeStructuredLL(med_idt fid, const char *maa) const throw(INTERP_KERNEL::Exception)
4504 {
4505   int meshDim=getStructuredMesh()->getMeshDimension();
4506   med_geometry_type geoTypeReq=GetGeoTypeFromMeshDim(meshDim);
4507   //
4508   if((const DataArrayInt *)_fam_cells)
4509     MEDmeshEntityFamilyNumberWr(fid,maa,_iteration,_order,MED_CELL,geoTypeReq,_fam_cells->getNumberOfTuples(),_fam_cells->getConstPointer());
4510   if((const DataArrayInt *)_fam_nodes)
4511     MEDmeshEntityFamilyNumberWr(fid,maa,_iteration,_order,MED_NODE,MED_NONE,_fam_nodes->getNumberOfTuples(),_fam_nodes->getConstPointer());
4512   if((const DataArrayInt *)_num_cells)
4513     MEDmeshEntityNumberWr(fid,maa,_iteration,_order,MED_CELL,geoTypeReq,_num_cells->getNumberOfTuples(),_num_cells->getConstPointer());
4514   if((const DataArrayInt *)_num_nodes)
4515     MEDmeshEntityNumberWr(fid,maa,_iteration,_order,MED_NODE,MED_NONE,_num_nodes->getNumberOfTuples(),_num_nodes->getConstPointer());
4516   if((const DataArrayAsciiChar *)_names_cells)
4517     {
4518       if(_names_cells->getNumberOfComponents()!=MED_SNAME_SIZE)
4519         {
4520           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on cells with number of components set to " << MED_SNAME_SIZE;
4521           oss << " ! The array has " << _names_cells->getNumberOfComponents() << " components !";
4522           throw INTERP_KERNEL::Exception(oss.str().c_str());
4523         }
4524       MEDmeshEntityNameWr(fid,maa,_iteration,_order,MED_CELL,geoTypeReq,_names_cells->getNumberOfTuples(),_names_cells->getConstPointer());
4525     }
4526   if((const DataArrayAsciiChar *)_names_nodes)
4527     {
4528       if(_names_nodes->getNumberOfComponents()!=MED_SNAME_SIZE)
4529         {
4530           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on nodes with number of components set to " << MED_SNAME_SIZE;
4531           oss << " ! The array has " << _names_cells->getNumberOfComponents() << " components !";
4532           throw INTERP_KERNEL::Exception(oss.str().c_str());
4533         }
4534       MEDmeshEntityNameWr(fid,maa,_iteration,_order,MED_NODE,MED_NONE,_names_nodes->getNumberOfTuples(),_names_nodes->getConstPointer());
4535     }
4536   //
4537   MEDFileUMeshL2::WriteFamiliesAndGrps(fid,maa,_families,_groups,_too_long_str);
4538 }
4539
4540 /*!
4541  * Returns an empty instance of MEDFileCMesh.
4542  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
4543  *          mesh using decrRef() as it is no more needed. 
4544  */
4545 MEDFileCMesh *MEDFileCMesh::New()
4546 {
4547   return new MEDFileCMesh;
4548 }
4549
4550 /*!
4551  * Returns a new MEDFileCMesh holding the mesh data that has been read from a given MED
4552  * file. The first mesh in the file is loaded.
4553  *  \param [in] fileName - the name of MED file to read.
4554  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
4555  *          mesh using decrRef() as it is no more needed. 
4556  *  \throw If the file is not readable.
4557  *  \throw If there is no meshes in the file.
4558  *  \throw If the mesh in the file is not a Cartesian one.
4559  */
4560 MEDFileCMesh *MEDFileCMesh::New(const char *fileName, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception)
4561 {
4562   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
4563   if(ms.empty())
4564     {
4565       std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
4566       throw INTERP_KERNEL::Exception(oss.str().c_str());
4567     }
4568   MEDFileUtilities::CheckFileForRead(fileName);
4569   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
4570   int dt,it;
4571   ParaMEDMEM::MEDCouplingMeshType meshType;
4572   std::string dummy2;
4573   MEDFileMeshL2::GetMeshIdFromName(fid,ms.front().c_str(),meshType,dt,it,dummy2);
4574   return new MEDFileCMesh(fid,ms.front().c_str(),dt,it,mrs);
4575 }
4576
4577 /*!
4578  * Returns a new MEDFileCMesh holding the mesh data that has been read from a given MED
4579  * file. The mesh to load is specified by its name and numbers of a time step and an
4580  * iteration.
4581  *  \param [in] fileName - the name of MED file to read.
4582  *  \param [in] mName - the name of the mesh to read.
4583  *  \param [in] dt - the number of a time step.
4584  *  \param [in] it - the number of an iteration.
4585  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
4586  *          mesh using decrRef() as it is no more needed. 
4587  *  \throw If the file is not readable.
4588  *  \throw If there is no mesh with given attributes in the file.
4589  *  \throw If the mesh in the file is not a Cartesian one.
4590  */
4591 MEDFileCMesh *MEDFileCMesh::New(const char *fileName, const char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception)
4592 {
4593   MEDFileUtilities::CheckFileForRead(fileName);
4594   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
4595   return new MEDFileCMesh(fid,mName,dt,it,mrs);
4596 }
4597
4598 std::size_t MEDFileCMesh::getHeapMemorySize() const
4599 {
4600   std::size_t ret=MEDFileStructuredMesh::getHeapMemorySize();
4601   if((const MEDCouplingCMesh *)_cmesh)
4602     ret+=_cmesh->getHeapMemorySize();
4603   return ret;
4604 }
4605
4606 /*!
4607  * Returns the dimension on cells in \a this mesh.
4608  *  \return int - the mesh dimension.
4609  *  \throw If there are no cells in this mesh.
4610  */
4611 int MEDFileCMesh::getMeshDimension() const throw(INTERP_KERNEL::Exception)
4612 {
4613   if(!((const MEDCouplingCMesh*)_cmesh))
4614     throw INTERP_KERNEL::Exception("MEDFileCMesh::getMeshDimension : unable to get meshdimension because no mesh set !");
4615   return _cmesh->getMeshDimension();
4616 }
4617
4618 /*!
4619  * Returns a string describing \a this mesh.
4620  *  \return std::string - the mesh information string.
4621  */
4622 std::string MEDFileCMesh::simpleRepr() const
4623 {
4624   return MEDFileStructuredMesh::simpleRepr();
4625 }
4626
4627 /*!
4628  * Returns a full textual description of \a this mesh.
4629  *  \return std::string - the string holding the mesh description.
4630  */
4631 std::string MEDFileCMesh::advancedRepr() const
4632 {
4633   return simpleRepr();
4634 }
4635
4636 MEDFileMesh *MEDFileCMesh::shallowCpy() const throw(INTERP_KERNEL::Exception)
4637 {
4638   MEDCouplingAutoRefCountObjectPtr<MEDFileCMesh> ret=new MEDFileCMesh(*this);
4639   return ret.retn();
4640 }
4641
4642 MEDFileMesh *MEDFileCMesh::createNewEmpty() const throw(INTERP_KERNEL::Exception)
4643 {
4644   return new MEDFileCMesh;
4645 }
4646
4647 MEDFileMesh *MEDFileCMesh::deepCpy() const throw(INTERP_KERNEL::Exception)
4648 {
4649   MEDCouplingAutoRefCountObjectPtr<MEDFileCMesh> ret=new MEDFileCMesh(*this);
4650   if((const MEDCouplingCMesh*)_cmesh)
4651     ret->_cmesh=static_cast<MEDCouplingCMesh*>(_cmesh->deepCpy());
4652   ret->deepCpyAttributes();
4653   return ret.retn();
4654 }
4655
4656 /*!
4657  * Checks if \a this and another mesh are equal.
4658  *  \param [in] other - the mesh to compare with.
4659  *  \param [in] eps - a precision used to compare real values.
4660  *  \param [in,out] what - the string returning description of unequal data.
4661  *  \return bool - \c true if the meshes are equal, \c false, else.
4662  */
4663 bool MEDFileCMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
4664 {
4665   if(!MEDFileStructuredMesh::isEqual(other,eps,what))
4666     return false;
4667   const MEDFileCMesh *otherC=dynamic_cast<const MEDFileCMesh *>(other);
4668   if(!otherC)
4669     {
4670       what="Mesh types differ ! This is cartesian and other is NOT !";
4671       return false;
4672     }
4673   clearNonDiscrAttributes();
4674   otherC->clearNonDiscrAttributes();
4675   const MEDCouplingCMesh *coo1=_cmesh;
4676   const MEDCouplingCMesh *coo2=otherC->_cmesh;
4677   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
4678     {
4679       what="Mismatch of cartesian meshes ! One is defined and not other !";
4680       return false;
4681     }
4682   if(coo1)
4683     {
4684       bool ret=coo1->isEqual(coo2,eps);
4685       if(!ret)
4686         {
4687           what="cartesian meshes differ !";
4688           return false;
4689         }
4690     }
4691   return true;
4692 }
4693
4694 /*!
4695  * Clears redundant attributes of incorporated data arrays.
4696  */
4697 void MEDFileCMesh::clearNonDiscrAttributes() const
4698 {
4699   MEDFileStructuredMesh::clearNonDiscrAttributes();
4700   MEDFileUMeshSplitL1::ClearNonDiscrAttributes(_cmesh);//to it is not a bug umeshsplit have already the method implemented
4701 }
4702
4703 MEDFileCMesh::MEDFileCMesh()
4704 {
4705 }
4706
4707 MEDFileCMesh::MEDFileCMesh(med_idt fid, const char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception)
4708 try
4709   {
4710     loadCMeshFromFile(fid,mName,dt,it,mrs);
4711   }
4712 catch(INTERP_KERNEL::Exception& e)
4713   {
4714     throw e;
4715   }
4716
4717 void MEDFileCMesh::loadCMeshFromFile(med_idt fid, const char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception)
4718 {
4719   ParaMEDMEM::MEDCouplingMeshType meshType;
4720   int dummy0,dummy1;
4721   std::string dtunit;
4722   int mid=MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dtunit);
4723   if(meshType!=CARTESIAN)
4724     {
4725       std::ostringstream oss; oss << "Trying to load as cartesian an existing mesh with name '" << mName << "' that is NOT cartesian !";
4726       throw INTERP_KERNEL::Exception(oss.str().c_str());
4727     }
4728   MEDFileCMeshL2 loaderl2;
4729   loaderl2.loadAll(fid,mid,mName,dt,it);
4730   MEDCouplingCMesh *mesh=loaderl2.getMesh();
4731   mesh->incrRef();
4732   _cmesh=mesh;
4733   loadStrMeshFromFile(&loaderl2,fid,mName,dt,it,mrs);
4734 }
4735
4736 /*!
4737  * Returns a const pointer to MEDCouplingCMesh held by \a this mesh.
4738  *  \return const MEDCouplingCMesh * - a pointer to the held MEDCouplingCMesh.
4739  */
4740 const MEDCouplingCMesh *MEDFileCMesh::getMesh() const
4741 {
4742   synchronizeTinyInfoOnLeaves();
4743   return _cmesh;
4744 }
4745
4746 const MEDCouplingStructuredMesh *MEDFileCMesh::getStructuredMesh() const
4747 {
4748   synchronizeTinyInfoOnLeaves();
4749   return _cmesh;
4750 }
4751
4752 /*!
4753  * Sets the MEDCouplingCMesh holding the data of \a this mesh.
4754  *  \param [in] m - the new MEDCouplingCMesh to refer to.
4755  *  \throw If the name or the description of \a this mesh and \a m are not empty and are
4756  *         different. 
4757  */
4758 void MEDFileCMesh::setMesh(MEDCouplingCMesh *m) throw(INTERP_KERNEL::Exception)
4759 {
4760   dealWithTinyInfo(m);
4761   if(m)
4762     m->incrRef();
4763   _cmesh=m;
4764 }
4765
4766 void MEDFileCMesh::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception)
4767 {
4768   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
4769   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
4770   INTERP_KERNEL::AutoPtr<char> dtunit=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE);
4771   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
4772   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
4773   MEDLoaderBase::safeStrCpy(_dt_unit.c_str(),MED_LNAME_SIZE,dtunit,_too_long_str);
4774   int spaceDim=_cmesh->getSpaceDimension();
4775   int meshDim=_cmesh->getMeshDimension();
4776   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
4777   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
4778   for(int i=0;i<spaceDim;i++)
4779     {
4780       std::string info(_cmesh->getCoordsAt(i)->getInfoOnComponent(0));
4781       std::string c,u;
4782       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
4783       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
4784       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
4785     }
4786   MEDmeshCr(fid,maa,spaceDim,meshDim,MED_STRUCTURED_MESH,desc,dtunit,MED_SORT_DTIT,MED_CARTESIAN,comp,unit);
4787   MEDmeshUniversalNameWr(fid,maa);
4788   MEDmeshGridTypeWr(fid,maa,MED_CARTESIAN_GRID);
4789   for(int i=0;i<spaceDim;i++)
4790     {
4791       const DataArrayDouble *da=_cmesh->getCoordsAt(i);
4792       MEDmeshGridIndexCoordinateWr(fid,maa,_iteration,_order,_time,i+1,da->getNumberOfTuples(),da->getConstPointer());
4793     }
4794   //
4795   MEDFileStructuredMesh::writeStructuredLL(fid,maa);
4796 }
4797
4798 void MEDFileCMesh::synchronizeTinyInfoOnLeaves() const
4799 {
4800   const MEDCouplingCMesh *cmesh=_cmesh;
4801   if(!cmesh)
4802     return;
4803   (const_cast<MEDCouplingCMesh *>(cmesh))->setName(_name.c_str());
4804   (const_cast<MEDCouplingCMesh *>(cmesh))->setDescription(_desc_name.c_str());
4805   (const_cast<MEDCouplingCMesh *>(cmesh))->setTime(_time,_iteration,_order);
4806   (const_cast<MEDCouplingCMesh *>(cmesh))->setTimeUnit(_dt_unit.c_str());
4807 }
4808
4809 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New()
4810 {
4811   return new MEDFileCurveLinearMesh;
4812 }
4813
4814 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const char *fileName, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception)
4815 {
4816   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
4817   if(ms.empty())
4818     {
4819       std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
4820       throw INTERP_KERNEL::Exception(oss.str().c_str());
4821     }
4822   MEDFileUtilities::CheckFileForRead(fileName);
4823   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
4824   int dt,it;
4825   ParaMEDMEM::MEDCouplingMeshType meshType;
4826   std::string dummy2;
4827   MEDFileMeshL2::GetMeshIdFromName(fid,ms.front().c_str(),meshType,dt,it,dummy2);
4828   return new MEDFileCurveLinearMesh(fid,ms.front().c_str(),dt,it,mrs);
4829 }
4830
4831 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const char *fileName, const char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception)
4832 {
4833   MEDFileUtilities::CheckFileForRead(fileName);
4834   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
4835   return new MEDFileCurveLinearMesh(fid,mName,dt,it,mrs);
4836 }
4837
4838 std::size_t MEDFileCurveLinearMesh::getHeapMemorySize() const
4839 {
4840   std::size_t ret=MEDFileStructuredMesh::getHeapMemorySize();
4841   if((const MEDCouplingCurveLinearMesh *)_clmesh)
4842     ret+=_clmesh->getHeapMemorySize();
4843   return ret;
4844 }
4845
4846 MEDFileMesh *MEDFileCurveLinearMesh::shallowCpy() const throw(INTERP_KERNEL::Exception)
4847 {
4848   MEDCouplingAutoRefCountObjectPtr<MEDFileCurveLinearMesh> ret=new MEDFileCurveLinearMesh(*this);
4849   return ret.retn();
4850 }
4851
4852 MEDFileMesh *MEDFileCurveLinearMesh::createNewEmpty() const throw(INTERP_KERNEL::Exception)
4853 {
4854   return new MEDFileCurveLinearMesh;
4855 }
4856
4857 MEDFileMesh *MEDFileCurveLinearMesh::deepCpy() const throw(INTERP_KERNEL::Exception)
4858 {
4859   MEDCouplingAutoRefCountObjectPtr<MEDFileCurveLinearMesh> ret=new MEDFileCurveLinearMesh(*this);
4860   if((const MEDCouplingCurveLinearMesh*)_clmesh)
4861     ret->_clmesh=static_cast<MEDCouplingCurveLinearMesh*>(_clmesh->deepCpy());
4862   ret->deepCpyAttributes();
4863   return ret.retn();
4864 }
4865
4866 int MEDFileCurveLinearMesh::getMeshDimension() const throw(INTERP_KERNEL::Exception)
4867 {
4868   if(!((const MEDCouplingCurveLinearMesh*)_clmesh))
4869     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::getMeshDimension : unable to get meshdimension because no mesh set !");
4870   return _clmesh->getMeshDimension();
4871 }
4872
4873 std::string MEDFileCurveLinearMesh::simpleRepr() const
4874 {
4875   return MEDFileStructuredMesh::simpleRepr();
4876 }
4877
4878 std::string MEDFileCurveLinearMesh::advancedRepr() const
4879 {
4880   return simpleRepr();
4881 }
4882
4883 bool MEDFileCurveLinearMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
4884 {
4885   if(!MEDFileStructuredMesh::isEqual(other,eps,what))
4886     return false;
4887   const MEDFileCurveLinearMesh *otherC=dynamic_cast<const MEDFileCurveLinearMesh *>(other);
4888   if(!otherC)
4889     {
4890       what="Mesh types differ ! This is curve linear and other is NOT !";
4891       return false;
4892     }
4893   clearNonDiscrAttributes();
4894   otherC->clearNonDiscrAttributes();
4895   const MEDCouplingCurveLinearMesh *coo1=_clmesh;
4896   const MEDCouplingCurveLinearMesh *coo2=otherC->_clmesh;
4897   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
4898     {
4899       what="Mismatch of curve linear meshes ! One is defined and not other !";
4900       return false;
4901     }
4902   if(coo1)
4903     {
4904       bool ret=coo1->isEqual(coo2,eps);
4905       if(!ret)
4906         {
4907           what="curve linear meshes differ !";
4908           return false;
4909         }
4910     }
4911   return true;
4912 }
4913
4914 void MEDFileCurveLinearMesh::clearNonDiscrAttributes() const
4915 {
4916   MEDFileStructuredMesh::clearNonDiscrAttributes();
4917   MEDFileUMeshSplitL1::ClearNonDiscrAttributes(_clmesh);//to it is not a bug umeshsplit have already the method implemented
4918 }
4919
4920 void MEDFileCurveLinearMesh::synchronizeTinyInfoOnLeaves() const
4921 {
4922   const MEDCouplingCurveLinearMesh *clmesh=_clmesh;
4923   if(!clmesh)
4924     return;
4925   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setName(_name.c_str());
4926   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setDescription(_desc_name.c_str());
4927   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setTime(_time,_iteration,_order);
4928   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setTimeUnit(_dt_unit.c_str());
4929 }
4930
4931 const MEDCouplingCurveLinearMesh *MEDFileCurveLinearMesh::getMesh() const
4932 {
4933   synchronizeTinyInfoOnLeaves();
4934   return _clmesh;
4935 }
4936
4937 void MEDFileCurveLinearMesh::setMesh(MEDCouplingCurveLinearMesh *m) throw(INTERP_KERNEL::Exception)
4938 {
4939   dealWithTinyInfo(m);
4940   if(m)
4941     m->incrRef();
4942   _clmesh=m;
4943 }
4944
4945 const MEDCouplingStructuredMesh *MEDFileCurveLinearMesh::getStructuredMesh() const
4946 {
4947   synchronizeTinyInfoOnLeaves();
4948   return _clmesh;
4949 }
4950
4951 MEDFileCurveLinearMesh::MEDFileCurveLinearMesh()
4952 {
4953 }
4954
4955 MEDFileCurveLinearMesh::MEDFileCurveLinearMesh(med_idt fid, const char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception)
4956 try
4957   {
4958     loadCLMeshFromFile(fid,mName,dt,it,mrs);
4959   }
4960 catch(INTERP_KERNEL::Exception& e)
4961   {
4962     throw e;
4963   }
4964
4965 void MEDFileCurveLinearMesh::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception)
4966 {
4967   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
4968   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
4969   INTERP_KERNEL::AutoPtr<char> dtunit=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE);
4970   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
4971   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
4972   MEDLoaderBase::safeStrCpy(_dt_unit.c_str(),MED_LNAME_SIZE,dtunit,_too_long_str);
4973   int spaceDim=_clmesh->getSpaceDimension();
4974   int meshDim=_clmesh->getMeshDimension();
4975   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
4976   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
4977   const DataArrayDouble *coords=_clmesh->getCoords();
4978   if(!coords)
4979     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::writeLL : no coordinates set !");
4980   for(int i=0;i<spaceDim;i++)
4981     {
4982       std::string info(_clmesh->getCoords()->getInfoOnComponent(i));
4983       std::string c,u;
4984       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
4985       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
4986       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
4987     }
4988   MEDmeshCr(fid,maa,spaceDim,meshDim,MED_STRUCTURED_MESH,desc,dtunit,MED_SORT_DTIT,MED_CARTESIAN,comp,unit);
4989   MEDmeshUniversalNameWr(fid,maa);
4990   MEDmeshGridTypeWr(fid,maa,MED_CURVILINEAR_GRID);
4991   std::vector<int> nodeGridSt=_clmesh->getNodeGridStructure();
4992   MEDmeshGridStructWr(fid,maa,_iteration,_order,_time,&nodeGridSt[0]);
4993   
4994   MEDmeshNodeCoordinateWr(fid,maa,_iteration,_order,_time,MED_FULL_INTERLACE,coords->getNumberOfTuples(),coords->begin());
4995   //
4996   MEDFileStructuredMesh::writeStructuredLL(fid,maa);
4997 }
4998
4999 void MEDFileCurveLinearMesh::loadCLMeshFromFile(med_idt fid, const char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception)
5000 {
5001   ParaMEDMEM::MEDCouplingMeshType meshType;
5002   int dummy0,dummy1;
5003   std::string dtunit;
5004   int mid=MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dtunit);
5005   if(meshType!=CURVE_LINEAR)
5006     {
5007       std::ostringstream oss; oss << "Trying to load as curve linear an existing mesh with name '" << mName << "' that is NOT curve linear !";
5008       throw INTERP_KERNEL::Exception(oss.str().c_str());
5009     }
5010   MEDFileCLMeshL2 loaderl2;
5011   loaderl2.loadAll(fid,mid,mName,dt,it);
5012   MEDCouplingCurveLinearMesh *mesh=loaderl2.getMesh();
5013   mesh->incrRef();
5014   _clmesh=mesh;
5015   loadStrMeshFromFile(&loaderl2,fid,mName,dt,it,mrs);
5016 }
5017
5018 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New()
5019 {
5020   return new MEDFileMeshMultiTS;
5021 }
5022
5023 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(const char *fileName) throw(INTERP_KERNEL::Exception)
5024 {
5025   return new MEDFileMeshMultiTS(fileName);
5026 }
5027
5028 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(const char *fileName, const char *mName) throw(INTERP_KERNEL::Exception)
5029 {
5030   return new MEDFileMeshMultiTS(fileName,mName);
5031 }
5032
5033 MEDFileMeshMultiTS *MEDFileMeshMultiTS::deepCpy() const throw(INTERP_KERNEL::Exception)
5034 {
5035   MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> ret=MEDFileMeshMultiTS::New();
5036   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> > meshOneTs(_mesh_one_ts.size());
5037   std::size_t i=0;
5038   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++,i++)
5039     if((const MEDFileMesh *)*it)
5040       meshOneTs[i]=(*it)->deepCpy();
5041   ret->_mesh_one_ts=meshOneTs;
5042   return ret.retn();
5043 }
5044
5045 std::size_t MEDFileMeshMultiTS::getHeapMemorySize() const
5046 {
5047   std::size_t ret=_mesh_one_ts.capacity()*sizeof(MEDCouplingAutoRefCountObjectPtr<MEDFileMesh>);
5048   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
5049     ret+=(*it)->getHeapMemorySize();
5050   return ret;
5051 }
5052
5053 std::string MEDFileMeshMultiTS::getName() const throw(INTERP_KERNEL::Exception)
5054 {
5055   if(_mesh_one_ts.empty())
5056     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::getName : no time steps set !");
5057   return _mesh_one_ts[0]->getName();
5058 }
5059
5060 void MEDFileMeshMultiTS::setName(const char *newMeshName) throw(INTERP_KERNEL::Exception)
5061 {
5062   std::string oldName(getName());
5063   std::vector< std::pair<std::string,std::string> > v(1);
5064   v[0].first=oldName; v[0].second=newMeshName;
5065   changeNames(v);
5066 }
5067
5068 bool MEDFileMeshMultiTS::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab) throw(INTERP_KERNEL::Exception)
5069 {
5070   bool ret=false;
5071   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
5072     {
5073       MEDFileMesh *cur(*it);
5074       if(cur)
5075         ret=cur->changeNames(modifTab) || ret;
5076     }
5077   return ret;
5078 }
5079
5080 MEDFileMesh *MEDFileMeshMultiTS::getOneTimeStep() const throw(INTERP_KERNEL::Exception)
5081 {
5082   if(_mesh_one_ts.empty())
5083     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::getOneTimeStep : empty time step set !");
5084   return const_cast<MEDFileMesh *>(static_cast<const MEDFileMesh *>(_mesh_one_ts[0]));
5085 }
5086
5087 void MEDFileMeshMultiTS::setOneTimeStep(MEDFileMesh *mesh1TimeStep) throw(INTERP_KERNEL::Exception)
5088 {
5089   if(!mesh1TimeStep)
5090     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::setOneTimeStep : input pointer should be different from 0 !");
5091   _mesh_one_ts.resize(1);
5092   mesh1TimeStep->incrRef();
5093   //MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> toto=mesh1TimeStep;
5094   _mesh_one_ts[0]=mesh1TimeStep;
5095 }
5096
5097 void MEDFileMeshMultiTS::write(med_idt fid) const throw(INTERP_KERNEL::Exception)
5098 {
5099   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
5100     {
5101       (*it)->copyOptionsFrom(*this);
5102       (*it)->write(fid);
5103     }
5104 }
5105
5106 void MEDFileMeshMultiTS::write(const char *fileName, int mode) const throw(INTERP_KERNEL::Exception)
5107 {
5108   med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode);
5109   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,medmod);
5110   std::ostringstream oss; oss << "MEDFileMesh : error on attempt to write in file : \"" << fileName << "\""; 
5111   MEDFileUtilities::CheckMEDCode(fid,fid,oss.str().c_str());
5112   write(fid);
5113 }
5114
5115 void MEDFileMeshMultiTS::loadFromFile(const char *fileName, const char *mName) throw(INTERP_KERNEL::Exception)
5116 {//for the moment to be improved
5117   _mesh_one_ts.resize(1);
5118   _mesh_one_ts[0]=MEDFileMesh::New(fileName,mName,-1,-1);
5119 }
5120
5121 MEDFileMeshMultiTS::MEDFileMeshMultiTS()
5122 {
5123 }
5124
5125 MEDFileMeshMultiTS::MEDFileMeshMultiTS(const char *fileName) throw(INTERP_KERNEL::Exception)
5126 try
5127   {
5128     std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
5129     if(ms.empty())
5130     {
5131       std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
5132       throw INTERP_KERNEL::Exception(oss.str().c_str());
5133     }
5134     MEDFileUtilities::CheckFileForRead(fileName);
5135     MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
5136     int dt,it;
5137     ParaMEDMEM::MEDCouplingMeshType meshType;
5138     std::string dummy2;
5139     MEDFileMeshL2::GetMeshIdFromName(fid,ms.front().c_str(),meshType,dt,it,dummy2);
5140     loadFromFile(fileName,ms.front().c_str());
5141   }
5142 catch(INTERP_KERNEL::Exception& e)
5143   {
5144     throw e;
5145   }
5146
5147 MEDFileMeshMultiTS::MEDFileMeshMultiTS(const char *fileName, const char *mName) throw(INTERP_KERNEL::Exception)
5148 try
5149   {
5150     loadFromFile(fileName,mName);
5151   }
5152 catch(INTERP_KERNEL::Exception& e)
5153   {
5154     throw e;
5155   }
5156
5157 MEDFileMeshes *MEDFileMeshes::New()
5158 {
5159   return new MEDFileMeshes;
5160 }
5161
5162 MEDFileMeshes *MEDFileMeshes::New(const char *fileName) throw(INTERP_KERNEL::Exception)
5163 {
5164   return new MEDFileMeshes(fileName);
5165 }
5166
5167 void MEDFileMeshes::write(med_idt fid) const throw(INTERP_KERNEL::Exception)
5168 {
5169   checkCoherency();
5170   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++)
5171     {
5172       (*it)->copyOptionsFrom(*this);
5173       (*it)->write(fid);
5174     }
5175 }
5176
5177 void MEDFileMeshes::write(const char *fileName, int mode) const throw(INTERP_KERNEL::Exception)
5178 {
5179   med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode);
5180   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,medmod);
5181   std::ostringstream oss; oss << "MEDFileMesh : error on attempt to write in file : \"" << fileName << "\""; 
5182   MEDFileUtilities::CheckMEDCode(fid,fid,oss.str().c_str());
5183   checkCoherency();
5184   write(fid);
5185 }
5186
5187 int MEDFileMeshes::getNumberOfMeshes() const throw(INTERP_KERNEL::Exception)
5188 {
5189   return _meshes.size();
5190 }
5191
5192 MEDFileMeshesIterator *MEDFileMeshes::iterator() throw(INTERP_KERNEL::Exception)
5193 {
5194   return new MEDFileMeshesIterator(this);
5195 }
5196
5197 MEDFileMesh *MEDFileMeshes::getMeshAtPos(int i) const throw(INTERP_KERNEL::Exception)
5198 {
5199   if(i<0 || i>=(int)_meshes.size())
5200     {
5201       std::ostringstream oss; oss << "MEDFileMeshes::getMeshAtPos : invalid mesh id given in parameter ! Should be in [0;" << _meshes.size() << ") !";
5202       throw INTERP_KERNEL::Exception(oss.str().c_str());
5203     }
5204   return _meshes[i]->getOneTimeStep();
5205 }
5206
5207 MEDFileMesh *MEDFileMeshes::getMeshWithName(const char *mname) const throw(INTERP_KERNEL::Exception)
5208 {
5209   std::vector<std::string> ms=getMeshesNames();
5210   std::vector<std::string>::iterator it=std::find(ms.begin(),ms.end(),mname);
5211   if(it==ms.end())
5212     {
5213       std::ostringstream oss; oss << "MEDFileMeshes::getMeshWithName : Mesh  \"" << mname << "\" does not exist in this ! Existing are : ";
5214       std::copy(ms.begin(),ms.end(),std::ostream_iterator<std::string>(oss," "));
5215       throw INTERP_KERNEL::Exception(oss.str().c_str());
5216     }
5217   return getMeshAtPos((int)std::distance(ms.begin(),it));
5218 }
5219
5220 std::vector<std::string> MEDFileMeshes::getMeshesNames() const throw(INTERP_KERNEL::Exception)
5221 {
5222   std::vector<std::string> ret(_meshes.size());
5223   int i=0;
5224   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
5225     {
5226       const MEDFileMeshMultiTS *f=(*it);
5227       if(f)
5228         {
5229           ret[i]=f->getName();
5230         }
5231       else
5232         {
5233           std::ostringstream oss; oss << "MEDFileMeshes::getMeshesNames : At rank #" << i << " mesh is not defined !";
5234           throw INTERP_KERNEL::Exception(oss.str().c_str());
5235         }
5236     }
5237   return ret;
5238 }
5239
5240 bool MEDFileMeshes::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab) throw(INTERP_KERNEL::Exception)
5241 {
5242   bool ret=false;
5243   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::iterator it=_meshes.begin();it!=_meshes.end();it++)
5244     {
5245       MEDFileMeshMultiTS *cur(*it);
5246       if(cur)
5247         ret=cur->changeNames(modifTab) || ret;
5248     }
5249   return ret;
5250 }
5251
5252 void MEDFileMeshes::resize(int newSize) throw(INTERP_KERNEL::Exception)
5253 {
5254   _meshes.resize(newSize);
5255 }
5256
5257 void MEDFileMeshes::pushMesh(MEDFileMesh *mesh) throw(INTERP_KERNEL::Exception)
5258 {
5259   if(!mesh)
5260     throw INTERP_KERNEL::Exception("MEDFileMeshes::pushMesh : invalid input pointer ! should be different from 0 !");
5261   MEDFileMeshMultiTS *elt=MEDFileMeshMultiTS::New();
5262   elt->setOneTimeStep(mesh);
5263   _meshes.push_back(elt);
5264 }
5265
5266 void MEDFileMeshes::setMeshAtPos(int i, MEDFileMesh *mesh) throw(INTERP_KERNEL::Exception)
5267 {
5268   if(!mesh)
5269     throw INTERP_KERNEL::Exception("MEDFileMeshes::setMeshAtPos : invalid input pointer ! should be different from 0 !");
5270   if(i>=(int)_meshes.size())
5271     _meshes.resize(i+1);
5272   MEDFileMeshMultiTS *elt=MEDFileMeshMultiTS::New();
5273   elt->setOneTimeStep(mesh);
5274   _meshes[i]=elt;
5275 }
5276
5277 void MEDFileMeshes::destroyMeshAtPos(int i) throw(INTERP_KERNEL::Exception)
5278 {
5279   if(i<0 || i>=(int)_meshes.size())
5280     {
5281       std::ostringstream oss; oss << "MEDFileMeshes::destroyMeshAtPos : Invalid given id in input (" << i << ") should be in [0," << _meshes.size() << ") !";
5282       throw INTERP_KERNEL::Exception(oss.str().c_str());
5283     }
5284   _meshes.erase(_meshes.begin()+i);
5285 }
5286
5287 void MEDFileMeshes::loadFromFile(const char *fileName) throw(INTERP_KERNEL::Exception)
5288 {
5289   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
5290   int i=0;
5291   _meshes.resize(ms.size());
5292   for(std::vector<std::string>::const_iterator it=ms.begin();it!=ms.end();it++,i++)
5293     _meshes[i]=MEDFileMeshMultiTS::New(fileName,(*it).c_str());
5294 }
5295
5296 MEDFileMeshes::MEDFileMeshes()
5297 {
5298 }
5299
5300 MEDFileMeshes::MEDFileMeshes(const char *fileName) throw(INTERP_KERNEL::Exception)
5301 try
5302   {
5303     loadFromFile(fileName);
5304   }
5305 catch(INTERP_KERNEL::Exception& e)
5306   {
5307   }
5308
5309 MEDFileMeshes *MEDFileMeshes::deepCpy() const throw(INTERP_KERNEL::Exception)
5310 {
5311   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> > meshes(_meshes.size());
5312   std::size_t i=0;
5313   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
5314     if((const MEDFileMeshMultiTS *)*it)
5315       meshes[i]=(*it)->deepCpy();
5316   MEDCouplingAutoRefCountObjectPtr<MEDFileMeshes> ret=MEDFileMeshes::New();
5317   ret->_meshes=meshes;
5318   return ret.retn();
5319 }
5320
5321 std::size_t MEDFileMeshes::getHeapMemorySize() const
5322 {
5323   std::size_t ret=_meshes.capacity()*(sizeof(MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS>));
5324   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++)
5325     if((const MEDFileMeshMultiTS*)*it)
5326       ret+=(*it)->getHeapMemorySize();
5327   return ret; 
5328 }
5329
5330 std::string MEDFileMeshes::simpleRepr() const
5331 {
5332   std::ostringstream oss;
5333   oss << "(*****************)\n(* MEDFileMeshes *)\n(*****************)\n\n";
5334   simpleReprWithoutHeader(oss);
5335   return oss.str();
5336 }
5337
5338 void MEDFileMeshes::simpleReprWithoutHeader(std::ostream& oss) const
5339 {
5340   int nbOfMeshes=getNumberOfMeshes();
5341   oss << "There are " << nbOfMeshes << " meshes with the following names : \n";
5342   std::vector<std::string> mns=getMeshesNames();
5343   for(int i=0;i<nbOfMeshes;i++)
5344     oss << "  - #" << i << " \"" << mns[i] << "\"\n";
5345 }
5346
5347 void MEDFileMeshes::checkCoherency() const throw(INTERP_KERNEL::Exception)
5348 {
5349   static const char MSG[]="MEDFileMeshes::checkCoherency : mesh at rank ";
5350   int i=0;
5351   std::set<std::string> s;
5352   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
5353     {
5354       const MEDFileMeshMultiTS *elt=(*it);
5355       if(!elt)
5356         {
5357           std::ostringstream oss; oss << MSG << i << "/" << _meshes.size() << " is empty !";
5358           throw INTERP_KERNEL::Exception(oss.str().c_str());
5359         }
5360       std::size_t sz=s.size();
5361       s.insert(std::string((*it)->getName()));
5362       if(s.size()==sz)
5363         {
5364           std::ostringstream oss; oss << MSG << i << " has a name (\"" << (*it)->getName() << "\") already used by an another mesh in list !";
5365           throw INTERP_KERNEL::Exception(oss.str().c_str());
5366         }
5367     }
5368 }
5369
5370 MEDFileMeshesIterator::MEDFileMeshesIterator(MEDFileMeshes *ms):_ms(ms),_iter_id(0),_nb_iter(0)
5371 {
5372   if(ms)
5373     {
5374       ms->incrRef();
5375       _nb_iter=ms->getNumberOfMeshes();
5376     }
5377 }
5378
5379 MEDFileMeshesIterator::~MEDFileMeshesIterator()
5380 {
5381 }
5382
5383 MEDFileMesh *MEDFileMeshesIterator::nextt()
5384 {
5385   if(_iter_id<_nb_iter)
5386     {
5387       MEDFileMeshes *ms(_ms);
5388       if(ms)
5389         return ms->getMeshAtPos(_iter_id++);
5390       else
5391         return 0;
5392     }
5393   else
5394     return 0;
5395 }