Salome HOME
f9ac17e960b23947fb11fd5e0c26a9867056f178
[tools/medcoupling.git] / src / MEDLoader / MEDFileMesh.cxx
1 // Copyright (C) 2007-2015  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, or (at your option) any later version.
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 "MEDFileSafeCaller.txx"
27 #include "MEDLoaderBase.hxx"
28
29 #include "MEDCouplingUMesh.hxx"
30
31 #include "InterpKernelAutoPtr.hxx"
32
33 #include <limits>
34 #include <cmath>
35
36 extern med_geometry_type typmai3[34];
37
38 using namespace ParaMEDMEM;
39
40 const char MEDFileMesh::DFT_FAM_NAME[]="FAMILLE_ZERO";
41
42 MEDFileMesh::MEDFileMesh():_order(-1),_iteration(-1),_time(0.),_univ_wr_status(true)
43 {
44 }
45
46 std::size_t MEDFileMesh::getHeapMemorySizeWithoutChildren() const
47 {
48   std::size_t ret(_dt_unit.capacity()+_name.capacity()+_univ_name.capacity()+_desc_name.capacity());
49   for(std::map<std::string, std::vector<std::string> >::const_iterator it=_groups.begin();it!=_groups.end();it++)
50     {
51       ret+=(*it).first.capacity()+(*it).second.capacity()*sizeof(std::string);
52       for(std::vector<std::string>::const_iterator it2=(*it).second.begin();it2!=(*it).second.end();it2++)
53         ret+=(*it2).capacity();
54     }
55   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
56     ret+=(*it).first.capacity()+sizeof(int);
57   return ret;
58 }
59
60 std::vector<const BigMemoryObject *> MEDFileMesh::getDirectChildrenWithNull() const
61 {
62   std::vector<const BigMemoryObject *> ret(1);
63   ret[0]=(const MEDFileEquivalences *)_equiv;
64   return ret;
65 }
66
67 /*!
68  * Returns a new MEDFileMesh holding the mesh data that has been read from a given MED
69  * file. The first mesh in the file is loaded.
70  *  \param [in] fileName - the name of MED file to read.
71  *  \return MEDFileMesh * - a new instance of MEDFileMesh. The caller is to delete this
72  *          mesh using decrRef() as it is no more needed. 
73  *  \throw If the file is not readable.
74  *  \throw If there is no meshes in the file.
75  *  \throw If the mesh in the file is of a not supported type.
76  */
77 MEDFileMesh *MEDFileMesh::New(const std::string& fileName, MEDFileMeshReadSelector *mrs)
78 {
79   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
80   if(ms.empty())
81     {
82       std::ostringstream oss; oss << "MEDFileMesh::New : no meshes in file \"" << fileName << "\" !";
83       throw INTERP_KERNEL::Exception(oss.str().c_str());
84     }
85   MEDFileUtilities::CheckFileForRead(fileName);
86   ParaMEDMEM::MEDCouplingMeshType meshType;
87   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
88   int dt,it;
89   std::string dummy2;
90   MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dt,it,dummy2);
91   MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> ret;
92   switch(meshType)
93   {
94     case UNSTRUCTURED:
95       {
96         ret=MEDFileUMesh::New();
97         break;
98       }
99     case CARTESIAN:
100       {
101         ret=MEDFileCMesh::New();
102         break;
103       }
104     case CURVE_LINEAR:
105       {
106         ret=MEDFileCurveLinearMesh::New();
107         break;
108       }
109     default:
110       {
111         std::ostringstream oss; oss << "MEDFileMesh::New : MED file exists and has mesh '" << ms.front() << "' exists but unsupported type yet !";
112         throw INTERP_KERNEL::Exception(oss.str().c_str());
113       }
114   }
115   ret->loadLLWithAdditionalItems(fid,ms.front(),dt,it,mrs);
116   return ret.retn();
117 }
118
119 /*!
120  * Returns a new MEDFileMesh holding the mesh data that has been read from a given MED
121  * file. The mesh to load is specified by its name and numbers of a time step and an
122  * iteration.
123  *  \param [in] fileName - the name of MED file to read.
124  *  \param [in] mName - the name of the mesh to read.
125  *  \param [in] dt - the number of a time step.
126  *  \param [in] it - the number of an iteration.
127  *  \param [in] joints - the sub-domain joints to use instead of those that can be read
128  *          from the MED file. Usually this joints are those just read by another iteration
129  *          of mName mesh, when this method is called by MEDFileMeshMultiTS::New()
130  *  \return MEDFileMesh * - a new instance of MEDFileMesh. The caller is to delete this
131  *          mesh using decrRef() as it is no more needed. 
132  *  \throw If the file is not readable.
133  *  \throw If there is no mesh with given attributes in the file.
134  *  \throw If the mesh in the file is of a not supported type.
135  */
136 MEDFileMesh *MEDFileMesh::New(const std::string& fileName, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs, MEDFileJoints* joints)
137 {
138   MEDFileUtilities::CheckFileForRead(fileName);
139   ParaMEDMEM::MEDCouplingMeshType meshType;
140   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
141   int dummy0,dummy1;
142   std::string dummy2;
143   MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dummy2);
144   MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> ret;
145   switch(meshType)
146   {
147     case UNSTRUCTURED:
148       {
149         ret=MEDFileUMesh::New();
150         break;
151       }
152     case CARTESIAN:
153       {
154         ret=MEDFileCMesh::New();
155         break;
156       }
157     case CURVE_LINEAR:
158       {
159         ret=MEDFileCurveLinearMesh::New();
160         break;
161       }
162     default:
163       {
164         std::ostringstream oss; oss << "MEDFileMesh::New : MED file exists and has mesh '" << mName << "' exists but unsupported type yet !";
165         throw INTERP_KERNEL::Exception(oss.str().c_str());
166       }
167   }
168   ret->loadLLWithAdditionalItems(fid,mName,dt,it,mrs);
169   return ret.retn();
170 }
171
172 /*!
173  * Writes \a this mesh into an open MED file specified by its descriptor.
174  *  \param [in] fid - the MED file descriptor.
175  *  \throw If the mesh name is not set.
176  *  \throw If the file is open for reading only.
177  *  \throw If the writing mode == 1 and the same data is present in an existing file.
178  */
179 void MEDFileMesh::write(med_idt fid) const
180 {
181   if(!existsFamily(0))
182     const_cast<MEDFileMesh *>(this)->addFamily(DFT_FAM_NAME,0);
183   if(_name.empty())
184     throw INTERP_KERNEL::Exception("MEDFileMesh : name is empty. MED file ask for a NON EMPTY name !");
185   writeLL(fid);
186   writeJoints(fid);
187   const MEDFileEquivalences *eqs(_equiv);
188   if(eqs)
189     eqs->write(fid);
190 }
191
192 /*!
193  * Writes \a this mesh into a MED file specified by its name.
194  *  \param [in] fileName - the MED file name.
195  *  \param [in] mode - the writing mode. For more on \a mode, see \ref AdvMEDLoaderBasics.
196  * - 2 - erase; an existing file is removed.
197  * - 1 - append; same data should not be present in an existing file.
198  * - 0 - overwrite; same data present in an existing file is overwritten.
199  *  \throw If the mesh name is not set.
200  *  \throw If \a mode == 1 and the same data is present in an existing file.
201  */
202 void MEDFileMesh::write(const std::string& fileName, int mode) const
203 {
204   med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode);
205   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),medmod);
206   std::ostringstream oss; oss << "MEDFileMesh : error on attempt to write in file : \"" << fileName << "\""; 
207   MEDFileUtilities::CheckMEDCode(fid,fid,oss.str());
208   write(fid);
209 }
210
211 /*!
212  * Checks if \a this and another mesh are equal.
213  *  \param [in] other - the mesh to compare with.
214  *  \param [in] eps - a precision used to compare real values.
215  *  \param [in,out] what - the string returning description of unequal data.
216  *  \return bool - \c true if the meshes are equal, \c false, else.
217  */
218 bool MEDFileMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
219 {
220   if(_order!=other->_order)
221     {
222       what="Orders differ !";
223       return false;
224     }
225   if(_iteration!=other->_iteration)
226     {
227       what="Iterations differ !";
228       return false;
229     }
230   if(fabs(_time-other->_time)>eps)
231     {
232       what="Time values differ !";
233       return false;
234     }
235   if(_dt_unit!=other->_dt_unit)
236     {
237       what="Time units differ !";
238       return false;
239     }
240   if(_name!=other->_name)
241     {
242       what="Names differ !";
243       return false;
244     }
245   //univ_name has been ignored -> not a bug because it is a mutable attribute
246   if(_desc_name!=other->_desc_name)
247     {
248       what="Description names differ !";
249       return false;
250     }
251   if(!areGrpsEqual(other,what))
252     return false;
253   if(!areFamsEqual(other,what))
254     return false;
255   if(!areEquivalencesEqual(other,what))
256     return false;
257   return true;
258 }
259
260 void MEDFileMesh::setName(const std::string& name)
261 {
262   _name=name;
263 }
264
265 /*!
266  * Clears redundant attributes of incorporated data arrays.
267  */
268 void MEDFileMesh::clearNonDiscrAttributes() const
269 {
270
271 }
272
273 bool MEDFileMesh::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab)
274 {
275   for(std::vector< std::pair<std::string,std::string> >::const_iterator it=modifTab.begin();it!=modifTab.end();it++)
276     {
277       if((*it).first==_name)
278         {
279           _name=(*it).second;
280           return true;
281         }
282     }
283   return false;
284 }
285
286 /*!
287  * Copies data on groups and families from another mesh.
288  *  \param [in] other - the mesh to copy the data from.
289  */
290 void MEDFileMesh::copyFamGrpMapsFrom(const MEDFileMesh& other)
291 {
292   _groups=other._groups;
293   _families=other._families;
294 }
295
296
297 /*!
298  * This method clear all the groups in the map.
299  * So this method does not operate at all on arrays.
300  * So this method can lead to orphan families.
301  * 
302  * \sa MEDFileMesh::clearFamMap, MEDFileMesh::clearFamGrpMaps
303  */
304 void MEDFileMesh::clearGrpMap()
305 {
306   _groups.clear();
307 }
308
309 /*!
310  * This method clear all the families in the map.
311  * So this method does not operate at all on arrays.
312  * WARNING ! if there are some groups lying on cleared families, those groups will be impacted !
313  *
314  * \sa MEDFileMesh::clearFamMap, MEDFileMesh::clearFamGrpMaps
315  */
316 void MEDFileMesh::clearFamMap()
317 {
318   _families.clear();
319 }
320
321 /*!
322  * This method clear all the families and groups in the map.
323  * So this method does not operate at all on arrays.
324  * As all groups and families entry will be removed after 
325  * the call of MEDFileMesh::setFamilyFieldArr method with 0 or None (python) in the 2nd parameter can be useful to reduce the size of the object.
326  *
327  * \sa MEDFileMesh::clearFamMap, MEDFileMesh::clearFamMap
328  */
329 void MEDFileMesh::clearFamGrpMaps()
330 {
331   clearGrpMap();
332   clearFamMap();
333 }
334
335 /*!
336  * Returns names of families constituting a group.
337  *  \param [in] name - the name of the group of interest.
338  *  \return std::vector<std::string> - a sequence of names of the families.
339  *  \throw If the name of a nonexistent group is specified.
340  */
341 std::vector<std::string> MEDFileMesh::getFamiliesOnGroup(const std::string& name) const
342 {
343   std::string oname(name);
344   std::map<std::string, std::vector<std::string> >::const_iterator it=_groups.find(oname);
345   if(it==_groups.end())
346     {
347       std::vector<std::string> grps=getGroupsNames();
348       std::ostringstream oss; oss << "No such groupname \"" << name << "\" !\nAvailable groups are :";
349       std::copy(grps.begin(),grps.end(),std::ostream_iterator<std::string>(oss," "));
350       throw INTERP_KERNEL::Exception(oss.str().c_str());
351     }
352   return (*it).second;
353 }
354
355 /*!
356  * Returns names of families constituting some groups.
357  *  \param [in] grps - a sequence of names of groups of interest.
358  *  \return std::vector<std::string> - a sequence of names of the families.
359  *  \throw If a name of a nonexistent group is present in \a grps.
360  */
361 std::vector<std::string> MEDFileMesh::getFamiliesOnGroups(const std::vector<std::string>& grps) const
362 {
363   std::set<std::string> fams;
364   for(std::vector<std::string>::const_iterator it=grps.begin();it!=grps.end();it++)
365     {
366       std::map<std::string, std::vector<std::string> >::const_iterator it2=_groups.find(*it);
367       if(it2==_groups.end())
368         {
369           std::ostringstream oss; oss << "No such group in mesh \"" << _name << "\" : " << *it; 
370           std::vector<std::string> grps2=getGroupsNames(); oss << "\" !\nAvailable groups are :";
371           std::copy(grps2.begin(),grps2.end(),std::ostream_iterator<std::string>(oss," "));
372           throw INTERP_KERNEL::Exception(oss.str().c_str());
373         }
374       fams.insert((*it2).second.begin(),(*it2).second.end());
375     }
376   std::vector<std::string> fams2(fams.begin(),fams.end());
377   return fams2;
378 }
379
380 /*!
381  * Returns ids of families constituting a group.
382  *  \param [in] name - the name of the group of interest.
383  *  \return std::vector<int> - sequence of ids of the families.
384  *  \throw If the name of a nonexistent group is specified.
385  */
386 std::vector<int> MEDFileMesh::getFamiliesIdsOnGroup(const std::string& name) const
387 {
388   std::string oname(name);
389   std::map<std::string, std::vector<std::string> >::const_iterator it=_groups.find(oname);
390   std::vector<std::string> grps=getGroupsNames();
391   if(it==_groups.end())
392     {
393       std::ostringstream oss; oss << "No such groupname \"" << name << "\" !\nAvailable groups are :";
394       std::copy(grps.begin(),grps.end(),std::ostream_iterator<std::string>(oss," "));
395       throw INTERP_KERNEL::Exception(oss.str().c_str());
396     }
397   return getFamiliesIds((*it).second);
398 }
399
400 /*!
401  * Sets names of families constituting a group. If data on families of this group is
402  * already present, it is overwritten. Every family in \a fams is checked, and if a
403  family is not yet in \a this mesh, the default group id \c 0 is assigned to it.
404  *  \param [in] name - the name of the group of interest.
405  *  \param [in] fams - a sequence of names of families constituting the group.
406  */
407 void MEDFileMesh::setFamiliesOnGroup(const std::string& name, const std::vector<std::string>& fams)
408 {
409   std::string oname(name);
410   _groups[oname]=fams;
411   for(std::vector<std::string>::const_iterator it1=fams.begin();it1!=fams.end();it1++)
412     {
413       std::map<std::string,int>::iterator it2=_families.find(*it1);
414       if(it2==_families.end())
415         _families[*it1]=0;
416     }
417 }
418
419 /*!
420  * Sets families constituting a group. The families are specified by their ids.
421  * If a family name is not found by its id, an exception is thrown.
422  * If several families have same id, the first one in lexical order is taken.
423  *  \param [in] name - the name of the group of interest.
424  *  \param [in] famIds - a sequence of ids of families constituting the group.
425  *  \throw If a family name is not found by its id.
426  */
427 void MEDFileMesh::setFamiliesIdsOnGroup(const std::string& name, const std::vector<int>& famIds)
428 {
429   std::string oname(name);
430   std::vector<std::string> fams(famIds.size());
431   int i=0;
432   for(std::vector<int>::const_iterator it1=famIds.begin();it1!=famIds.end();it1++,i++)
433     {
434       std::string name2=getFamilyNameGivenId(*it1);
435       fams[i]=name2;
436     }
437   _groups[oname]=fams;
438 }
439
440 /*!
441  * Returns names of groups including a given family.
442  *  \param [in] name - the name of the family of interest.
443  *  \return std::vector<std::string> - a sequence of names of groups including the family.
444  */
445 std::vector<std::string> MEDFileMesh::getGroupsOnFamily(const std::string& name) const
446 {
447   std::vector<std::string> ret;
448   for(std::map<std::string, std::vector<std::string> >::const_iterator it1=_groups.begin();it1!=_groups.end();it1++)
449     {
450       for(std::vector<std::string>::const_iterator it2=(*it1).second.begin();it2!=(*it1).second.end();it2++)
451         if((*it2)==name)
452           {
453             ret.push_back((*it1).first);
454             break;
455           }
456     }
457   return ret;
458 }
459
460 /*!
461  * Adds an existing family to groups.
462  *  \param [in] famName - a name of family to add to \a grps.
463  *  \param [in] grps - a sequence of group names to add the family in.
464  *  \throw If a family named \a famName not yet exists.
465  */
466 void MEDFileMesh::setGroupsOnFamily(const std::string& famName, const std::vector<std::string>& grps)
467 {
468   std::string fName(famName);
469   const std::map<std::string,int>::const_iterator it=_families.find(fName);
470   if(it==_families.end())
471     {
472       std::vector<std::string> fams=getFamiliesNames();
473       std::ostringstream oss; oss << "No such familyname \"" << fName << "\" !\nAvailable families are :";
474       std::copy(fams.begin(),fams.end(),std::ostream_iterator<std::string>(oss," "));
475       throw INTERP_KERNEL::Exception(oss.str().c_str());
476     }
477   for(std::vector<std::string>::const_iterator it3=grps.begin();it3!=grps.end();it3++)
478     {
479       std::map< std::string, std::vector<std::string> >::iterator it2=_groups.find(*it3);
480       if(it2!=_groups.end())
481         (*it2).second.push_back(fName);
482       else
483         {
484           std::vector<std::string> grps2(1,fName);
485           _groups[*it3]=grps2;
486         }
487     }
488 }
489
490 /*!
491  * Returns names of all groups of \a this mesh.
492  *  \return std::vector<std::string> - a sequence of group names.
493  */
494 std::vector<std::string> MEDFileMesh::getGroupsNames() const
495 {
496   std::vector<std::string> ret(_groups.size());
497   int i=0;
498   for(std::map<std::string, std::vector<std::string> >::const_iterator it=_groups.begin();it!=_groups.end();it++,i++)
499     ret[i]=(*it).first;
500   return ret;
501 }
502
503 /*!
504  * Returns names of all families of \a this mesh.
505  *  \return std::vector<std::string> - a sequence of family names.
506  */
507 std::vector<std::string> MEDFileMesh::getFamiliesNames() const
508 {
509   std::vector<std::string> ret(_families.size());
510   int i=0;
511   for(std::map<std::string, int >::const_iterator it=_families.begin();it!=_families.end();it++,i++)
512     ret[i]=(*it).first;
513   return ret;
514 }
515
516 /*!
517  * Returns names of all families of \a this mesh but like they would be in file.
518  * This method is here only for MED file families gurus. If you are a kind user forget this method :-)
519  * This method is only useful for aggressive users that want to have in their file a same family lying both on cells and on nodes. This is not a good idea for lisibility !
520  * For your information internaly in memory such families are renamed to have a nicer API.
521  */
522 std::vector<std::string> MEDFileMesh::getFamiliesNamesWithFilePointOfView() const
523 {
524   std::vector<std::string> ret(getFamiliesNames());
525   MEDFileMeshL2::RenameFamiliesFromMemToFile(ret);
526   return ret;
527 }
528
529 std::string MEDFileMesh::GetMagicFamilyStr()
530 {
531   return std::string(MEDFileMeshL2::ZE_SEP_FOR_FAMILY_KILLERS);
532 }
533
534 /*!
535  * Changes a name of every family, included in one group only, to be same as the group name.
536  *  \throw If there are families with equal names in \a this mesh.
537  */
538 void MEDFileMesh::assignFamilyNameWithGroupName()
539 {
540   std::map<std::string, std::vector<std::string> > groups(_groups);
541   std::map<std::string,int> newFams;
542   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
543     {
544       std::vector<std::string> grps=getGroupsOnFamily((*it).first);
545       if(grps.size()==1 && groups[grps[0]].size()==1)
546         {
547           if(newFams.find(grps[0])!=newFams.end())
548             {
549               std::ostringstream oss; oss << "MEDFileMesh::assignFamilyNameWithGroupName : Family \"" << grps[0] << "\" already exists !";
550               throw INTERP_KERNEL::Exception(oss.str().c_str());
551             }
552           newFams[grps[0]]=(*it).second;
553           std::vector<std::string>& grps2=groups[grps[0]];
554           std::size_t pos=std::distance(grps2.begin(),std::find(grps2.begin(),grps2.end(),(*it).first));
555           grps2[pos]=grps[0];
556         }
557       else
558         {
559           if(newFams.find((*it).first)!=newFams.end())
560             {
561               std::ostringstream oss; oss << "MEDFileMesh::assignFamilyNameWithGroupName : Family \"" << (*it).first << "\" already exists !";
562               throw INTERP_KERNEL::Exception(oss.str().c_str());
563             }
564           newFams[(*it).first]=(*it).second;
565         }
566     }
567   _families=newFams;
568   _groups=groups;
569 }
570
571 /*!
572  * Removes all groups lying on no family. If there is no empty groups, \a this is let untouched.
573  * 
574  * \return the removed groups.
575  */
576 std::vector<std::string> MEDFileMesh::removeEmptyGroups()
577 {
578   std::vector<std::string> ret;
579   std::map<std::string, std::vector<std::string> > newGrps;
580   for(std::map<std::string, std::vector<std::string> >::const_iterator it=_groups.begin();it!=_groups.end();it++)
581     {
582       if((*it).second.empty())
583         ret.push_back((*it).first);
584       else
585         newGrps[(*it).first]=(*it).second;
586     }
587   if(!ret.empty())
588     _groups=newGrps;
589   return ret;
590 }
591
592 /*!
593  * Removes a group from \a this mesh.
594  *  \param [in] name - the name of the group to remove.
595  *  \throw If no group with such a \a name exists.
596  */
597 void MEDFileMesh::removeGroup(const std::string& name)
598 {
599   std::string oname(name);
600   std::map<std::string, std::vector<std::string> >::iterator it=_groups.find(oname);
601   std::vector<std::string> grps=getGroupsNames();
602   if(it==_groups.end())
603     {
604       std::ostringstream oss; oss << "No such groupname \"" << name << "\" !\nAvailable groups are :";
605       std::copy(grps.begin(),grps.end(),std::ostream_iterator<std::string>(oss," "));
606       throw INTERP_KERNEL::Exception(oss.str().c_str());
607     }
608   _groups.erase(it);
609 }
610
611 /*!
612  * Removes a family from \a this mesh.
613  *  \param [in] name - the name of the family to remove.
614  *  \throw If no family with such a \a name exists.
615  */
616 void MEDFileMesh::removeFamily(const std::string& name)
617 {
618   std::string oname(name);
619   std::map<std::string, int >::iterator it=_families.find(oname);
620   std::vector<std::string> fams=getFamiliesNames();
621   if(it==_families.end())
622     {
623       std::ostringstream oss; oss << "No such familyname \"" << name << "\" !\nAvailable families are :";
624       std::copy(fams.begin(),fams.end(),std::ostream_iterator<std::string>(oss," "));
625       throw INTERP_KERNEL::Exception(oss.str().c_str());
626     }
627   _families.erase(it);
628   for(std::map<std::string, std::vector<std::string> >::iterator it3=_groups.begin();it3!=_groups.end();it3++)
629     {
630       std::vector<std::string>& v=(*it3).second;
631       std::vector<std::string>::iterator it4=std::find(v.begin(),v.end(),oname);
632       if(it4!=v.end())
633         v.erase(it4);
634     }
635 }
636
637 /*!
638  * Removes all groups in \a this that are orphan. A group is orphan if this group lies on
639  * a set of families, themselves orphan. A family is said orphan if its id appears nowhere in
640  * family field whatever its level. This method also suppresses the orphan families.
641  * 
642  * \return - The list of removed groups names. 
643  *
644  * \sa MEDFileMesh::removeOrphanFamilies.
645  */
646 std::vector<std::string> MEDFileMesh::removeOrphanGroups()
647 {
648   removeOrphanFamilies();
649   return removeEmptyGroups();
650 }
651
652 /*!
653  * Removes all families in \a this that are orphan. A family is said orphan if its id appears nowhere in
654  * 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.
655  * 
656  * \return - The list of removed families names.
657  * \sa MEDFileMesh::removeOrphanGroups.
658  */
659 std::vector<std::string> MEDFileMesh::removeOrphanFamilies()
660 {
661   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> allFamIdsInUse=computeAllFamilyIdsInUse();
662   std::vector<std::string> ret;
663   if(!((DataArrayInt*)allFamIdsInUse))
664     {
665       ret=getFamiliesNames();
666       _families.clear(); _groups.clear();
667       return ret;
668     }
669   std::map<std::string,int> famMap;
670   std::map<std::string, std::vector<std::string> > grps(_groups);
671   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
672     {
673       if(allFamIdsInUse->presenceOfValue((*it).second))
674         famMap[(*it).first]=(*it).second;
675       else
676         {
677           ret.push_back((*it).first);
678           std::vector<std::string> grpsOnEraseFam=getGroupsOnFamily((*it).first);
679           for(std::vector<std::string>::const_iterator it2=grpsOnEraseFam.begin();it2!=grpsOnEraseFam.end();it2++)
680             {
681               std::map<std::string, std::vector<std::string> >::iterator it3=grps.find(*it2);//it3!=grps.empty() thanks to copy
682               std::vector<std::string>& famv=(*it3).second;
683               std::vector<std::string>::iterator it4=std::find(famv.begin(),famv.end(),(*it).first);//it4!=famv.end() thanks to copy
684               famv.erase(it4);
685             }
686         }
687     }
688   if(!ret.empty())
689     { _families=famMap; _groups=grps; }
690   return ret;
691 }
692
693 /*!
694  * This method operates only on maps in \a this. The arrays are not considered here. So this method will remove a family (except "FAMILLE_ZERO" family) if no group lies on it whatever
695  * this family is orphan or not.
696  *
697  * \warning this method is different from removeOrphanFamilies that scans family field array to find orphan families.
698  */
699 void MEDFileMesh::removeFamiliesReferedByNoGroups()
700 {
701   std::map<std::string,int> fams;
702   std::set<std::string> sfams;
703   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
704     sfams.insert((*it).first);
705   for(std::map<std::string, std::vector<std::string> >::const_iterator it0=_groups.begin();it0!=_groups.end();it0++)
706     for(std::vector<std::string>::const_iterator it1=(*it0).second.begin();it1!=(*it0).second.end();it1++)
707       sfams.erase(*it1);
708   for(std::set<std::string>::const_iterator it=sfams.begin();it!=sfams.end();it++)
709     if(*it!=DFT_FAM_NAME)
710       _families.erase(*it);
711 }
712
713 /*!
714  * This method has no impact on groups. This method only works on families. This method firstly removes families not refered by any groups in \a this, then all unused entities
715  * are put as belonging to family 0 ("FAMILLE_ZERO"). Finally, all orphanFamilies are killed.
716  * This method raises an exception if "FAMILLE_ZERO" is already belonging to a group.
717  *
718  * \sa MEDFileMesh::removeOrphanFamilies
719  */
720 void MEDFileMesh::rearrangeFamilies()
721 {
722   checkOrphanFamilyZero();
723   removeFamiliesReferedByNoGroups();
724   //
725   std::vector<int> levels(getNonEmptyLevelsExt());
726   std::set<int> idsRefed;
727   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
728     idsRefed.insert((*it).second);
729   for(std::vector<int>::const_iterator it=levels.begin();it!=levels.end();it++)
730     {
731       const DataArrayInt *fams(0);
732       try
733       {
734           fams=getFamilyFieldAtLevel(*it);
735       }
736       catch(INTERP_KERNEL::Exception& e) { }
737       if(!fams)
738         continue;
739       std::vector<bool> v(fams->getNumberOfTuples(),false);
740       for(std::set<int>::const_iterator pt=idsRefed.begin();pt!=idsRefed.end();pt++)
741         fams->switchOnTupleEqualTo(*pt,v);
742       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> unfetchedIds(DataArrayInt::BuildListOfSwitchedOff(v));
743       if(!unfetchedIds->empty())
744         {
745           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newFams(fams->deepCpy());
746           newFams->setPartOfValuesSimple3(0,unfetchedIds->begin(),unfetchedIds->end(),0,1,1);
747           setFamilyFieldArr(*it,newFams);
748         }
749     }
750   removeOrphanFamilies();
751 }
752
753 /*!
754  * This method only checks that "FAMILLE_ZERO" is orphan (not belonging to a group).
755  */
756 void MEDFileMesh::checkOrphanFamilyZero() const
757 {
758   for(std::map<std::string, std::vector<std::string> >::const_iterator it=_groups.begin();it!=_groups.end();it++)
759     {
760       if(std::find((*it).second.begin(),(*it).second.end(),DFT_FAM_NAME)!=(*it).second.end())
761         {
762           std::ostringstream oss; oss << "MEDFileMesh::rearrangeFamilies : Groups \"" << (*it).first << "\" is lying on family \"" << DFT_FAM_NAME << "\" !";
763           throw INTERP_KERNEL::Exception(oss.str().c_str());
764         }
765     }
766 }
767
768 /*!
769  * Renames a group in \a this mesh.
770  *  \param [in] oldName - a current name of the group to rename.
771  *  \param [in] newName - a new group name.
772  *  \throw If no group named \a oldName exists in \a this mesh.
773  *  \throw If a group named \a newName already exists.
774  */
775 void MEDFileMesh::changeGroupName(const std::string& oldName, const std::string& newName)
776 {
777   std::string oname(oldName);
778   std::map<std::string, std::vector<std::string> >::iterator it=_groups.find(oname);
779   std::vector<std::string> grps=getGroupsNames();
780   if(it==_groups.end())
781     {
782       std::ostringstream oss; oss << "No such groupname \"" << oldName << "\" !\nAvailable groups are :";
783       std::copy(grps.begin(),grps.end(),std::ostream_iterator<std::string>(oss," "));
784       throw INTERP_KERNEL::Exception(oss.str().c_str());
785     }
786   std::string nname(newName);
787   std::map<std::string, std::vector<std::string> >::iterator it2=_groups.find(nname);
788   if(it2!=_groups.end())
789     {
790       std::ostringstream oss; oss << "Such groupname \"" << newName << "\" already exists ! Kill it before !";
791       throw INTERP_KERNEL::Exception(oss.str().c_str());
792     }
793   std::vector<std::string> cpy=(*it).second;
794   _groups.erase(it);
795   _groups[newName]=cpy;
796 }
797
798 /*!
799  * Changes an id of a family in \a this mesh. 
800  * This method calls changeFamilyIdArr().
801  *  \param [in] oldId - a current id of the family.
802  *  \param [in] newId - a new family id.
803  */
804 void MEDFileMesh::changeFamilyId(int oldId, int newId)
805 {
806   changeFamilyIdArr(oldId,newId);
807   std::map<std::string,int> fam2;
808   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
809     {
810       if((*it).second==oldId)
811         fam2[(*it).first]=newId;
812       else
813         fam2[(*it).first]=(*it).second;
814     }
815   _families=fam2;
816 }
817
818 /*!
819  * Renames a family in \a this mesh.
820  *  \param [in] oldName - a current name of the family to rename.
821  *  \param [in] newName - a new family name.
822  *  \throw If no family named \a oldName exists in \a this mesh.
823  *  \throw If a family named \a newName already exists.
824  */
825 void MEDFileMesh::changeFamilyName(const std::string& oldName, const std::string& newName)
826 {
827   std::string oname(oldName);
828   std::map<std::string, int >::iterator it=_families.find(oname);
829   std::vector<std::string> fams=getFamiliesNames();
830   if(it==_families.end())
831     {
832       std::ostringstream oss; oss << "No such familyname \"" << oldName << "\" !\nAvailable families are :";
833       std::copy(fams.begin(),fams.end(),std::ostream_iterator<std::string>(oss," "));
834       throw INTERP_KERNEL::Exception(oss.str().c_str());
835     }
836   std::string nname(newName);
837   std::map<std::string, int >::iterator it2=_families.find(nname);
838   if(it2!=_families.end())
839     {
840       std::ostringstream oss; oss << "Such familyname \"" << newName << " already exists ! Kill it before !";
841       throw INTERP_KERNEL::Exception(oss.str().c_str());
842     }
843   int cpy=(*it).second;
844   _families.erase(it);
845   _families[newName]=cpy;
846   for(std::map<std::string, std::vector<std::string> >::iterator it3=_groups.begin();it3!=_groups.end();it3++)
847     {
848       std::vector<std::string>& v=(*it3).second;
849       std::vector<std::string>::iterator it4=std::find(v.begin(),v.end(),oname);
850       if(it4!=v.end())
851         (*it4)=nname;
852     }
853 }
854
855 /*!
856  * Checks if \a this and another mesh contains the same families.
857  *  \param [in] other - the mesh to compare with \a this one.
858  *  \param [in,out] what - an unused parameter.
859  *  \return bool - \c true if number of families and their ids are the same in the two
860  *          meshes. Families with the id == \c 0 are not considered.
861  */
862 bool MEDFileMesh::areFamsEqual(const MEDFileMesh *other, std::string& what) const
863 {
864   if(_families==other->_families)
865     return true;
866   std::map<std::string,int> fam0;
867   std::map<std::string,int> fam1;
868   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
869     if((*it).second!=0)
870       fam0[(*it).first]=(*it).second;
871   for(std::map<std::string,int>::const_iterator it=other->_families.begin();it!=other->_families.end();it++)
872     if((*it).second!=0)
873       fam1[(*it).first]=(*it).second;
874   return fam0==fam1;
875 }
876
877 /*!
878  * Checks if \a this and another mesh contains the same groups.
879  *  \param [in] other - the mesh to compare with \a this one.
880  *  \param [in,out] what - a string describing a difference of groups of the two meshes
881  *          in case if this method returns \c false.
882  *  \return bool - \c true if number of groups and families constituting them are the
883  *          same in the two meshes.
884  */
885 bool MEDFileMesh::areGrpsEqual(const MEDFileMesh *other, std::string& what) const
886 {
887   if(_groups==other->_groups)
888     return true;
889   bool ret=true;
890   std::size_t sz=_groups.size();
891   if(sz!=other->_groups.size())
892     {
893       what="Groups differ because not same number !\n";
894       ret=false;
895     }
896   if(ret)
897     {
898       std::map<std::string, std::vector<std::string> >::const_iterator it1=_groups.begin();
899       for(std::size_t i=0;i<sz && ret;i++,it1++)
900         {
901           std::map<std::string, std::vector<std::string> >::const_iterator it2=other->_groups.find((*it1).first);
902           if(it2!=other->_groups.end())
903             {
904               std::set<std::string> s1((*it1).second.begin(),(*it1).second.end());
905               std::set<std::string> s2((*it2).second.begin(),(*it2).second.end());
906               ret=(s1==s2);
907             }
908           else
909             {
910               ret=false;
911               what="A group in first mesh exists not in other !\n";
912             }
913         }
914     }
915   if(!ret)
916     {
917       std::ostringstream oss; oss << "Groups description differs :\n";
918       oss << "First group description :\n";
919       for(std::map<std::string, std::vector<std::string> >::const_iterator it=_groups.begin();it!=_groups.end();it++)
920         {
921           oss << " Group \"" << (*it).first << "\" on following families :\n";
922           for(std::vector<std::string>::const_iterator it2=(*it).second.begin();it2!=(*it).second.end();it2++)
923             oss << "    \"" << *it2 << "\n";
924         }
925       oss << "Second group description :\n";
926       for(std::map<std::string, std::vector<std::string> >::const_iterator it=other->_groups.begin();it!=other->_groups.end();it++)
927         {
928           oss << " Group \"" << (*it).first << "\" on following families :\n";
929           for(std::vector<std::string>::const_iterator it2=(*it).second.begin();it2!=(*it).second.end();it2++)
930             oss << "    \"" << *it2 << "\n";
931         }
932       what+=oss.str();
933     }
934   return ret;
935 }
936
937 /*!
938  * Checks if a group with a given name exists in \a this mesh.
939  *  \param [in] groupName - the group name.
940  *  \return bool - \c true the group \a groupName exists in \a this mesh.
941  */
942 bool MEDFileMesh::existsGroup(const std::string& groupName) const
943 {
944   std::string grpName(groupName);
945   return _groups.find(grpName)!=_groups.end();
946 }
947
948 /*!
949  * Checks if a family with a given id exists in \a this mesh.
950  *  \param [in] famId - the family id.
951  *  \return bool - \c true the family with the id \a famId exists in \a this mesh.
952  */
953 bool MEDFileMesh::existsFamily(int famId) const
954 {
955   for(std::map<std::string,int>::const_iterator it2=_families.begin();it2!=_families.end();it2++)
956     if((*it2).second==famId)
957       return true;
958   return false;
959 }
960
961 /*!
962  * Checks if a family with a given name exists in \a this mesh.
963  *  \param [in] familyName - the family name.
964  *  \return bool - \c true the family \a familyName exists in \a this mesh.
965  */
966 bool MEDFileMesh::existsFamily(const std::string& familyName) const
967 {
968   std::string fname(familyName);
969   return _families.find(fname)!=_families.end();
970 }
971
972 /*!
973  * Sets an id of a family.
974  *  \param [in] familyName - the family name.
975  *  \param [in] id - a new id of the family.
976  */
977 void MEDFileMesh::setFamilyId(const std::string& familyName, int id)
978 {
979   std::string fname(familyName);
980   _families[fname]=id;
981 }
982
983 void MEDFileMesh::setFamilyIdUnique(const std::string& familyName, int id)
984 {
985   std::string fname(familyName);
986   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
987     if((*it).second==id)
988       {
989         if((*it).first!=familyName)
990           {
991             std::ostringstream oss; oss << "MEDFileMesh::setFamilyIdUnique : Family id #" << id << " is already belonging to family with name \"" << (*it).first << "\" !";
992             throw INTERP_KERNEL::Exception(oss.str().c_str());
993           }
994       }
995   _families[fname]=id;
996 }
997
998 /*!
999  * Adds a family to \a this mesh.
1000  *  \param [in] familyName - a name of the family.
1001  *  \param [in] famId - an id of the family.
1002  *  \throw If a family with the same name or id already exists in \a this mesh.
1003  */
1004 void MEDFileMesh::addFamily(const std::string& familyName, int famId)
1005 {
1006   std::string fname(familyName);
1007   std::map<std::string,int>::const_iterator it=_families.find(fname);
1008   if(it==_families.end())
1009     {
1010       for(std::map<std::string,int>::const_iterator it2=_families.begin();it2!=_families.end();it2++)
1011         if((*it2).second==famId)
1012           {
1013             std::ostringstream oss;
1014             oss << "MEDFileMesh::addFamily : Family \"" << (*it2).first << "\" already exists with specified id : " << famId << " !";
1015             throw INTERP_KERNEL::Exception(oss.str().c_str());
1016           }
1017       _families[fname]=famId;
1018     }
1019   else
1020     {
1021       if((*it).second!=famId)
1022         {
1023           std::ostringstream oss;
1024           oss << "MEDFileMesh::addFamily : Family \"" << fname << "\" already exists but has id set to " << (*it).second << " different from asked famId " << famId << " !";
1025           throw INTERP_KERNEL::Exception(oss.str().c_str());
1026         }
1027     }
1028 }
1029
1030 /*!
1031  * Creates a group including all mesh entities of given dimension.
1032  * \warning This method does \b not guarantee that the created group includes mesh
1033  * entities of only \a meshDimRelToMaxExt dimension in the case if some family id is
1034  * present in family fields of different dimensions. To assure this, call
1035  * ensureDifferentFamIdsPerLevel() \b before calling this method.
1036  *  \param [in] meshDimRelToMaxExt - a relative dimension of mesh entities to include to
1037  *          the group.
1038  *  \param [in] groupName - a name of the new group.
1039  *  \throw If a group named \a groupName already exists.
1040  *  \throw If no mesh entities of dimension \a meshDimRelToMaxExt exist in \a this mesh.
1041  *  \throw If no family field of dimension \a meshDimRelToMaxExt is present in \a this mesh.
1042  */
1043 void MEDFileMesh::createGroupOnAll(int meshDimRelToMaxExt, const std::string& groupName)
1044 {
1045   std::string grpName(groupName);
1046   std::vector<int> levs=getNonEmptyLevelsExt();
1047   if(std::find(levs.begin(),levs.end(),meshDimRelToMaxExt)==levs.end())
1048     {
1049       std::ostringstream oss; oss << "MEDFileMesh::createGroupOnAll : The relative ext dimension " << meshDimRelToMaxExt << " is not available !" << std::endl;
1050       oss << "Available relative ext levels are : ";
1051       std::copy(levs.begin(),levs.end(),std::ostream_iterator<int>(oss," "));
1052       throw INTERP_KERNEL::Exception(oss.str().c_str());
1053     }
1054   if(existsGroup(groupName))
1055     {
1056       std::ostringstream oss; oss << "MEDFileMesh::createGroupOnAll : The groups \"" << grpName << "\" already exists in this !" << std::endl;
1057       oss << "Already existing groups are : ";
1058       std::copy(levs.begin(),levs.end(),std::ostream_iterator<int>(oss," "));
1059       oss << std::endl << "Please choose an another group name or call removeGroup(\"" << grpName << "\") method !";
1060       throw INTERP_KERNEL::Exception(oss.str().c_str());
1061     }
1062   const DataArrayInt *fieldFamIds=getFamilyFieldAtLevel(meshDimRelToMaxExt);
1063   if(fieldFamIds==0)
1064     throw INTERP_KERNEL::Exception("MEDFileMesh::createGroupOnAll : Family field arr ids is not defined for this level !");
1065   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famIds=fieldFamIds->getDifferentValues();
1066   std::vector<std::string> familiesOnWholeGroup;
1067   for(const int *it=famIds->begin();it!=famIds->end();it++)
1068     {
1069       bool tmp;
1070       familiesOnWholeGroup.push_back(findOrCreateAndGiveFamilyWithId(*it,tmp));
1071     }
1072   _groups[grpName]=familiesOnWholeGroup;
1073 }
1074
1075 /*!
1076  * Ensures that given family ids do not present in family fields of dimensions different
1077  * than given ones. If a family id is present in the family fields of dimensions different
1078  * than the given ones, a new family is created and the whole data is updated accordingly.
1079  *  \param [in] famIds - a sequence of family ids to check.
1080  *  \param [in] vMeshDimRelToMaxExt - a sequence of relative dimensions to which the \a
1081  *          famIds should exclusively belong.
1082  *  \return bool - \c true if no modification is done in \a this mesh by this method.
1083  */
1084 bool MEDFileMesh::keepFamIdsOnlyOnLevs(const std::vector<int>& famIds, const std::vector<int>& vMeshDimRelToMaxExt)
1085 {
1086   std::set<int> levsInput(vMeshDimRelToMaxExt.begin(),vMeshDimRelToMaxExt.end());
1087   std::vector<int> levs=getNonEmptyLevelsExt();
1088   std::set<int> levs2(levs.begin(),levs.end());
1089   std::vector<int> levsToTest;
1090   std::set_difference(levs2.begin(),levs2.end(),levsInput.begin(),levsInput.end(),std::back_insert_iterator< std::vector<int> >(levsToTest));
1091   std::set<int> famIds2(famIds.begin(),famIds.end());
1092   bool ret=true;
1093   int maxFamId=1;
1094   if(!_families.empty())
1095     maxFamId=getMaxFamilyId()+1;
1096   std::vector<std::string> allFams=getFamiliesNames();
1097   for(std::vector<int>::const_iterator it=levsToTest.begin();it!=levsToTest.end();it++)
1098     {
1099       const DataArrayInt *fieldFamIds=getFamilyFieldAtLevel(*it);
1100       if(fieldFamIds)
1101         {
1102           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famIds3=fieldFamIds->getDifferentValues();
1103           std::vector<int> tmp;
1104           std::set_intersection(famIds3->begin(),famIds3->end(),famIds2.begin(),famIds2.end(),std::back_insert_iterator< std::vector<int> >(tmp));
1105           for(std::vector<int>::const_iterator it2=tmp.begin();it2!=tmp.end();it2++)
1106             {
1107               ret=false;
1108               std::string famName=getFamilyNameGivenId(*it2);
1109               std::ostringstream oss; oss << "Family_" << maxFamId;
1110               std::string zeName=CreateNameNotIn(oss.str(),allFams);
1111               addFamilyOnAllGroupsHaving(famName,zeName);
1112               _families[zeName]=maxFamId;
1113               (const_cast<DataArrayInt *>(fieldFamIds))->changeValue(*it2,maxFamId);
1114               maxFamId++;
1115             }
1116         }
1117     }
1118   return ret;
1119 }
1120
1121 /*!
1122  * Adds a family to a given group in \a this mesh. If the group with a given name does
1123  * not exist, it is created.
1124  *  \param [in] grpName - the name of the group to add the family in.
1125  *  \param [in] famName - the name of the family to add to the group named \a grpName.
1126  *  \throw If \a grpName or \a famName is an empty string.
1127  *  \throw If no family named \a famName is present in \a this mesh.
1128  */
1129 void MEDFileMesh::addFamilyOnGrp(const std::string& grpName, const std::string& famName)
1130 {
1131   std::string grpn(grpName);
1132   std::string famn(famName);
1133   if(grpn.empty() || famn.empty())
1134     throw INTERP_KERNEL::Exception("MEDFileMesh::addFamilyOnGrp : input strings must be non null !");
1135   std::vector<std::string> fams=getFamiliesNames();
1136   if(std::find(fams.begin(),fams.end(),famn)==fams.end())
1137     {
1138       std::ostringstream oss; oss << "MEDFileMesh::addFamilyOnGrp : Family \"" << famn << "\" does not exist !" << std::endl;
1139       oss << "Create this family or choose an existing one ! Existing fams are : ";
1140       std::copy(fams.begin(),fams.end(),std::ostream_iterator<std::string>(oss," ")); oss << ".";
1141       throw INTERP_KERNEL::Exception(oss.str().c_str());
1142     }
1143   std::map<std::string, std::vector<std::string> >::iterator it=_groups.find(grpn);
1144   if(it==_groups.end())
1145     {
1146       _groups[grpn].push_back(famn);
1147     }
1148   else
1149     {
1150       std::vector<std::string>::iterator it2=std::find((*it).second.begin(),(*it).second.end(),famn);
1151       if(it2==(*it).second.end())
1152         (*it).second.push_back(famn);
1153     }
1154 }
1155
1156 /*!
1157  * This method adds to all groups lying on family with name 'famName' the other family name 'otherFamName'.
1158  * This method is quite underground because it can lead to unconsistency because family 'otherFamName' is \b not added into _families.
1159  * This method is used by MEDFileMesh::keepFamIdsOnlyOnLevs method.
1160  */
1161 void MEDFileMesh::addFamilyOnAllGroupsHaving(const std::string& famName, const std::string& otherFamName)
1162 {
1163   std::string famNameCpp(famName);
1164   std::string otherCpp(otherFamName);
1165   for(std::map<std::string, std::vector<std::string> >::iterator it=_groups.begin();it!=_groups.end();it++)
1166     {
1167       std::vector<std::string>& v=(*it).second;
1168       if(std::find(v.begin(),v.end(),famNameCpp)!=v.end())
1169         {
1170           v.push_back(otherCpp);
1171         }
1172     }
1173 }
1174
1175 /*!
1176  * \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).
1177  * \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)
1178  */
1179 void MEDFileMesh::addGroupUnderground(bool isNodeGroup, const DataArrayInt *ids, DataArrayInt *famArr)
1180 {
1181   if(!ids)
1182     throw INTERP_KERNEL::Exception("MEDFileUMesh::addGroup : NULL pointer in input !");
1183   std::string grpName(ids->getName());
1184   if(grpName.empty())
1185     throw INTERP_KERNEL::Exception("MEDFileUMesh::addGroup : empty group name ! MED file format do not accept empty group name !");
1186   ids->checkStrictlyMonotonic(true);
1187   famArr->incrRef(); MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famArrTmp(famArr);
1188   std::vector<std::string> grpsNames=getGroupsNames();
1189   if(std::find(grpsNames.begin(),grpsNames.end(),grpName)!=grpsNames.end())
1190     {
1191       std::ostringstream oss; oss << "MEDFileUMesh::addGroup : Group with name \"" << grpName << "\" already exists ! Destroy it before calling this method !";
1192       throw INTERP_KERNEL::Exception(oss.str().c_str());
1193     }
1194   std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > allFamIds(getAllNonNullFamilyIds());
1195   allFamIds.erase(std::find(allFamIds.begin(),allFamIds.end(),famArrTmp));
1196   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famIds=famArr->selectByTupleIdSafe(ids->begin(),ids->end());
1197   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffFamIds=famIds->getDifferentValues();
1198   std::vector<int> familyIds;
1199   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerfamiliyIds;
1200   int maxVal=getTheMaxAbsFamilyId()+1;
1201   std::map<std::string,int> families(_families);
1202   std::map<std::string, std::vector<std::string> > groups(_groups);
1203   std::vector<std::string> fams;
1204   bool created(false);
1205   for(const int *famId=diffFamIds->begin();famId!=diffFamIds->end();famId++)
1206     {
1207       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2Tmp=famIds->getIdsEqual(*famId);
1208       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=ids->selectByTupleId(ids2Tmp->begin(),ids2Tmp->end());
1209       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids1=famArr->getIdsEqual(*famId);
1210       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(ids1->buildSubstractionOptimized(ids2));
1211       if(ret0->empty())
1212         {
1213           bool isFamPresent=false;
1214           for(std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::const_iterator itl=allFamIds.begin();itl!=allFamIds.end() && !isFamPresent;itl++)
1215             isFamPresent=(*itl)->presenceOfValue(*famId);
1216           if(!isFamPresent)
1217             { familyIds.push_back(*famId); idsPerfamiliyIds.push_back(ret0); fams.push_back(FindOrCreateAndGiveFamilyWithId(families,*famId,created)); } // adding *famId in grp
1218           else
1219             {
1220               familyIds.push_back(isNodeGroup?maxVal:-maxVal); idsPerfamiliyIds.push_back(ids2);
1221               std::string locFamName=FindOrCreateAndGiveFamilyWithId(families,isNodeGroup?maxVal:-maxVal,created);
1222               fams.push_back(locFamName);
1223               if(existsFamily(*famId))
1224                 {
1225                   std::string locFamName2=getFamilyNameGivenId(*famId); std::vector<std::string> v(2); v[0]=locFamName2; v[1]=locFamName;
1226                   ChangeAllGroupsContainingFamily(groups,getFamilyNameGivenId(*famId),v);
1227                 }
1228               maxVal++;
1229             } // modifying all other groups on *famId to lie on maxVal and lie the grp on maxVal
1230         }
1231       else
1232         {
1233           familyIds.push_back(isNodeGroup?maxVal:-maxVal); idsPerfamiliyIds.push_back(ret0); // modifying all other groups on *famId to lie on maxVal and on maxVal+1
1234           familyIds.push_back(isNodeGroup?maxVal+1:-maxVal-1); idsPerfamiliyIds.push_back(ids2);//grp lie only on maxVal+1
1235           std::string n2(FindOrCreateAndGiveFamilyWithId(families,isNodeGroup?maxVal+1:-maxVal-1,created)); fams.push_back(n2);
1236           if(existsFamily(*famId))
1237             {
1238               std::string n1(FindOrCreateAndGiveFamilyWithId(families,isNodeGroup?maxVal:-maxVal,created)); std::vector<std::string> v(2); v[0]=n1; v[1]=n2;
1239               ChangeAllGroupsContainingFamily(groups,getFamilyNameGivenId(*famId),v);
1240             }
1241           maxVal+=2;
1242         }
1243     }
1244   for(std::size_t i=0;i<familyIds.size();i++)
1245     {
1246       DataArrayInt *da=idsPerfamiliyIds[i];
1247       famArr->setPartOfValuesSimple3(familyIds[i],da->begin(),da->end(),0,1,1);
1248     }
1249   _families=families;
1250   _groups=groups;
1251   _groups[grpName]=fams;
1252 }
1253
1254 void MEDFileMesh::changeAllGroupsContainingFamily(const std::string& familyNameToChange, const std::vector<std::string>& newFamiliesNames)
1255 {
1256   ChangeAllGroupsContainingFamily(_groups,familyNameToChange,newFamiliesNames);
1257 }
1258
1259 void MEDFileMesh::ChangeAllGroupsContainingFamily(std::map<std::string, std::vector<std::string> >& groups, const std::string& familyNameToChange, const std::vector<std::string>& newFamiliesNames)
1260 {
1261   std::string fam(familyNameToChange);
1262   for(std::map<std::string, std::vector<std::string> >::iterator it=groups.begin();it!=groups.end();it++)
1263     {
1264       std::vector<std::string>& fams((*it).second);
1265       std::vector<std::string>::iterator it2=std::find(fams.begin(),fams.end(),fam);
1266       if(it2!=fams.end())
1267         {
1268           fams.erase(it2);
1269           fams.insert(fams.end(),newFamiliesNames.begin(),newFamiliesNames.end());
1270         }
1271     }
1272 }
1273
1274 /*!
1275  * Returns a name of the family having a given id or, if no such a family exists, creates
1276  * a new uniquely named family and returns its name.
1277  *  \param [in] id - the id of the family whose name is required.
1278  *  \param [out] created - returns \c true if the new family has been created, \c false, else.
1279  *  \return std::string - the name of the existing or the created family.
1280  *  \throw If it is not possible to create a unique family name.
1281  */
1282 std::string MEDFileMesh::findOrCreateAndGiveFamilyWithId(int id, bool& created)
1283 {
1284   return FindOrCreateAndGiveFamilyWithId(_families,id,created);
1285 }
1286
1287 /*!
1288  * If it exists a family whose family id is equal to 'id' this method behaves as MEDFileMesh::getFamilyNameGivenId.
1289  * In this case, 'this' internal states remains unchanged and 'created' out parameter will be set to false.
1290  * If there is no family whose family id is equal to 'id' a family is created with a name different from those
1291  * already existing. In this case 'created' will be returned with a value set to true, and internal state
1292  * will be modified.
1293  * This method will throws an exception if it is not possible to create a unique family name.
1294  */
1295 std::string MEDFileMesh::FindOrCreateAndGiveFamilyWithId(std::map<std::string,int>& families, int id, bool& created)
1296 {
1297   std::vector<std::string> famAlreadyExisting(families.size());
1298   int ii=0;
1299   for(std::map<std::string,int>::const_iterator it=families.begin();it!=families.end();it++,ii++)
1300     {
1301       if((*it).second!=id)
1302         {
1303           famAlreadyExisting[ii]=(*it).first;
1304         }
1305       else
1306         {
1307           created=false;
1308           return (*it).first;
1309         }
1310     }
1311   created=true;
1312   std::ostringstream oss; oss << "Family_" << id;
1313   std::string ret=CreateNameNotIn(oss.str(),famAlreadyExisting);
1314   families[ret]=id;
1315   return ret;
1316 }
1317
1318 /*!
1319  * Sets names and ids of all families in \a this mesh.
1320  *  \param [in] info - a map of a family name to a family id.
1321  */
1322 void MEDFileMesh::setFamilyInfo(const std::map<std::string,int>& info)
1323 {
1324   _families=info;
1325 }
1326
1327 /*!
1328  * Sets names of all groups and families constituting them in \a this mesh.
1329  *  \param [in] info - a map of a group name to a vector of names of families
1330  *          constituting the group.
1331  */
1332 void MEDFileMesh::setGroupInfo(const std::map<std::string, std::vector<std::string> >&info)
1333 {
1334   _groups=info;
1335 }
1336
1337 /*!
1338  * Returns an id of the family having a given name.
1339  *  \param [in] name - the name of the family of interest.
1340  *  \return int - the id of the family of interest.
1341  *  \throw If no family with such a \a name exists.
1342  */
1343 int MEDFileMesh::getFamilyId(const std::string& name) const
1344 {
1345   std::string oname(name);
1346   std::map<std::string, int>::const_iterator it=_families.find(oname);
1347   std::vector<std::string> fams=getFamiliesNames();
1348   if(it==_families.end())
1349     {
1350       std::ostringstream oss; oss << "No such familyname \"" << name << "\" !\nAvailable families are :";
1351       std::copy(fams.begin(),fams.end(),std::ostream_iterator<std::string>(oss," "));
1352       throw INTERP_KERNEL::Exception(oss.str().c_str());
1353     }
1354   return (*it).second;
1355 }
1356
1357 /*!
1358  * Returns ids of the families having given names.
1359  *  \param [in] fams - a sequence of the names of families of interest.
1360  *  \return std::vector<int> - a sequence of the ids of families of interest.
1361  *  \throw If \a fams contains a name of an inexistent family.
1362  */
1363 std::vector<int> MEDFileMesh::getFamiliesIds(const std::vector<std::string>& fams) const
1364 {
1365   std::vector<int> ret(fams.size());
1366   int i=0;
1367   for(std::vector<std::string>::const_iterator it=fams.begin();it!=fams.end();it++,i++)
1368     {
1369       std::map<std::string, int>::const_iterator it2=_families.find(*it);
1370       if(it2==_families.end())
1371         {
1372           std::vector<std::string> fams2=getFamiliesNames();
1373           std::ostringstream oss; oss << "No such familyname \"" << *it << "\" in input list !\nAvailable families are :";
1374           std::copy(fams2.begin(),fams2.end(),std::ostream_iterator<std::string>(oss," "));
1375           throw INTERP_KERNEL::Exception(oss.str().c_str());
1376         }
1377       ret[i]=(*it2).second;
1378     }
1379   return ret;
1380 }
1381
1382 /*!
1383  * Returns a maximal abs(id) of families in \a this mesh.
1384  *  \return int - the maximal norm of family id.
1385  *  \throw If there are no families in \a this mesh.
1386  */
1387 int MEDFileMesh::getMaxAbsFamilyId() const
1388 {
1389   if(_families.empty())
1390     throw INTERP_KERNEL::Exception("MEDFileMesh::getMaxFamilyId : no families set !");
1391   int ret=-std::numeric_limits<int>::max();
1392   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
1393     {
1394       ret=std::max(std::abs((*it).second),ret);
1395     }
1396   return ret;
1397 }
1398
1399 /*!
1400  * Returns a maximal id of families in \a this mesh.
1401  *  \return int - the maximal family id.
1402  *  \throw If there are no families in \a this mesh.
1403  */
1404 int MEDFileMesh::getMaxFamilyId() const
1405 {
1406   if(_families.empty())
1407     throw INTERP_KERNEL::Exception("MEDFileMesh::getMaxFamilyId : no families set !");
1408   int ret=-std::numeric_limits<int>::max();
1409   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
1410     {
1411       ret=std::max((*it).second,ret);
1412     }
1413   return ret;
1414 }
1415
1416 /*!
1417  * Returns a minimal id of families in \a this mesh.
1418  *  \return int - the minimal family id.
1419  *  \throw If there are no families in \a this mesh.
1420  */
1421 int MEDFileMesh::getMinFamilyId() const
1422 {
1423   if(_families.empty())
1424     throw INTERP_KERNEL::Exception("MEDFileMesh::getMinFamilyId : no families set !");
1425   int ret=std::numeric_limits<int>::max();
1426   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
1427     {
1428       ret=std::min((*it).second,ret);
1429     }
1430   return ret;
1431 }
1432
1433 /*!
1434  * Returns a maximal id of families in \a this mesh. Not only named families are
1435  * considered but all family fields as well.
1436  *  \return int - the maximal family id.
1437  */
1438 int MEDFileMesh::getTheMaxAbsFamilyId() const
1439 {
1440   int m1=-std::numeric_limits<int>::max();
1441   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
1442     m1=std::max(std::abs((*it).second),m1);
1443   int m2=getMaxAbsFamilyIdInArrays();
1444   return std::max(m1,m2);
1445 }
1446
1447 /*!
1448  * Returns a maximal id of families in \a this mesh. Not only named families are
1449  * considered but all family fields as well.
1450  *  \return int - the maximal family id.
1451  */
1452 int MEDFileMesh::getTheMaxFamilyId() const
1453 {
1454   int m1=-std::numeric_limits<int>::max();
1455   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
1456     m1=std::max((*it).second,m1);
1457   int m2=getMaxFamilyIdInArrays();
1458   return std::max(m1,m2);
1459 }
1460
1461 /*!
1462  * Returns a minimal id of families in \a this mesh. Not only named families are
1463  * considered but all family fields as well.
1464  *  \return int - the minimal family id.
1465  */
1466 int MEDFileMesh::getTheMinFamilyId() const
1467 {
1468   int m1=std::numeric_limits<int>::max();
1469   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
1470     m1=std::min((*it).second,m1);
1471   int m2=getMinFamilyIdInArrays();
1472   return std::min(m1,m2);
1473 }
1474
1475 /*!
1476  * This method only considers the maps. The contain of family array is ignored here.
1477  * 
1478  * \sa MEDFileMesh::computeAllFamilyIdsInUse
1479  */
1480 DataArrayInt *MEDFileMesh::getAllFamiliesIdsReferenced() const
1481 {
1482   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1483   std::set<int> v;
1484   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
1485     v.insert((*it).second);
1486   ret->alloc((int)v.size(),1);
1487   std::copy(v.begin(),v.end(),ret->getPointer());
1488   return ret.retn();
1489 }
1490
1491 /*!
1492  * This method does not consider map of family name, family id. Only family field array on different levels is considered.
1493  * 
1494  * \sa MEDFileMesh::getAllFamiliesIdsReferenced
1495  */
1496 DataArrayInt *MEDFileMesh::computeAllFamilyIdsInUse() const
1497 {
1498   std::vector<int> famLevs=getFamArrNonEmptyLevelsExt();
1499   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret;
1500   for(std::vector<int>::const_iterator it=famLevs.begin();it!=famLevs.end();it++)
1501     {
1502       const DataArrayInt *arr=getFamilyFieldAtLevel(*it);//arr not null due to spec of getFamArrNonEmptyLevelsExt
1503       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dv=arr->getDifferentValues();
1504       if((DataArrayInt *) ret)
1505         ret=dv->buildUnion(ret);
1506       else
1507         ret=dv;
1508     }
1509   return ret.retn();
1510 }
1511
1512 /*!
1513  * true is returned if no modification has been needed. false if family
1514  * renumbering has been needed.       
1515  */
1516 bool MEDFileMesh::ensureDifferentFamIdsPerLevel()
1517 {
1518   std::vector<int> levs=getNonEmptyLevelsExt();
1519   std::set<int> allFamIds;
1520   int maxId=getMaxFamilyId()+1;
1521   std::map<int,std::vector<int> > famIdsToRenum;
1522   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
1523     {
1524       const DataArrayInt *fam=getFamilyFieldAtLevel(*it);
1525       if(fam)
1526         {
1527           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=fam->getDifferentValues();
1528           std::set<int> r2;
1529           std::set_intersection(tmp->begin(),tmp->end(),allFamIds.begin(),allFamIds.end(),std::inserter(r2,r2.end()));
1530           if(!r2.empty())
1531             famIdsToRenum[*it].insert(famIdsToRenum[*it].end(),r2.begin(),r2.end());
1532           std::set<int> r3;
1533           std::set_union(tmp->begin(),tmp->end(),allFamIds.begin(),allFamIds.end(),std::inserter(r3,r3.end()));
1534         }
1535     }
1536   if(famIdsToRenum.empty())
1537     return true;
1538   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> allIds=getAllFamiliesIdsReferenced();
1539   for(std::map<int,std::vector<int> >::const_iterator it2=famIdsToRenum.begin();it2!=famIdsToRenum.end();it2++)
1540     {
1541       DataArrayInt *fam=const_cast<DataArrayInt *>(getFamilyFieldAtLevel((*it2).first));
1542       int *famIdsToChange=fam->getPointer();
1543       std::map<int,int> ren;
1544       for(std::vector<int>::const_iterator it3=(*it2).second.begin();it3!=(*it2).second.end();it3++,maxId++)
1545         {
1546           if(allIds->presenceOfValue(*it3))
1547             {
1548               std::string famName=getFamilyNameGivenId(*it3);
1549               std::vector<std::string> grps=getGroupsOnFamily(famName);
1550               ren[*it3]=maxId;
1551               bool dummy;
1552               std::string newFam=findOrCreateAndGiveFamilyWithId(maxId,dummy);
1553               for(std::vector<std::string>::const_iterator it4=grps.begin();it4!=grps.end();it4++)
1554                 addFamilyOnGrp((*it4),newFam);
1555             }
1556         }
1557       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=fam->getIdsEqualList(&(*it2).second[0],&(*it2).second[0]+(*it2).second.size());
1558       for(const int *id=ids->begin();id!=ids->end();id++)
1559         famIdsToChange[*id]=ren[famIdsToChange[*id]];
1560     }
1561   return false;
1562 }
1563
1564 /*!
1565  * This method normalizes fam id with the policy explained underneath. This policy is close to those implemented in SMESH.
1566  * Level #0 famids > 0, Level #-1 famids < 0, Level #-2 famids=0, Level #1 famids=0
1567  * This policy is those used by SMESH and Trio and that is the opposite of those in MED file.
1568  * This method will throw an exception if a same family id is detected in different level.
1569  * \warning This policy is the opposite of those in MED file documentation ...
1570  */
1571 void MEDFileMesh::normalizeFamIdsTrio()
1572 {
1573   ensureDifferentFamIdsPerLevel();
1574   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> allIds=getAllFamiliesIdsReferenced();
1575   std::vector<int> levs=getNonEmptyLevelsExt();
1576   std::set<int> levsS(levs.begin(),levs.end());
1577   std::set<std::string> famsFetched;
1578   std::map<std::string,int> families;
1579   if(std::find(levs.begin(),levs.end(),0)!=levs.end())
1580     {
1581       levsS.erase(0);
1582       const DataArrayInt *fam=getFamilyFieldAtLevel(0);
1583       if(fam)
1584         {
1585           int refId=1;
1586           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=fam->getDifferentValues();
1587           std::map<int,int> ren;
1588           for(const int *it=tmp->begin();it!=tmp->end();it++,refId++)
1589             ren[*it]=refId;
1590           int nbOfTuples=fam->getNumberOfTuples();
1591           int *start=const_cast<DataArrayInt *>(fam)->getPointer();
1592           for(int *w=start;w!=start+nbOfTuples;w++)
1593             *w=ren[*w];
1594           for(const int *it=tmp->begin();it!=tmp->end();it++)
1595             {
1596               if(allIds->presenceOfValue(*it))
1597                 {
1598                   std::string famName=getFamilyNameGivenId(*it);
1599                   families[famName]=ren[*it];
1600                   famsFetched.insert(famName);
1601                 }
1602             }
1603         }
1604     }
1605   if(std::find(levs.begin(),levs.end(),-1)!=levs.end())
1606     {
1607       levsS.erase(-1);
1608       const DataArrayInt *fam=getFamilyFieldAtLevel(-1);
1609       if(fam)
1610         {
1611           int refId=-1;
1612           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=fam->getDifferentValues();
1613           std::map<int,int> ren;
1614           for(const int *it=tmp->begin();it!=tmp->end();it++,refId--)
1615             ren[*it]=refId;
1616           int nbOfTuples=fam->getNumberOfTuples();
1617           int *start=const_cast<DataArrayInt *>(fam)->getPointer();
1618           for(int *w=start;w!=start+nbOfTuples;w++)
1619             *w=ren[*w];
1620           for(const int *it=tmp->begin();it!=tmp->end();it++)
1621             {
1622               if(allIds->presenceOfValue(*it))
1623                 {
1624                   std::string famName=getFamilyNameGivenId(*it);
1625                   families[famName]=ren[*it];
1626                   famsFetched.insert(famName);
1627                 }
1628             }
1629         }
1630     }
1631   for(std::set<int>::const_iterator it2=levsS.begin();it2!=levsS.end();it2++)
1632     {
1633       DataArrayInt *fam=const_cast<DataArrayInt*>(getFamilyFieldAtLevel(*it2));
1634       if(fam)
1635         {
1636           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=fam->getDifferentValues();
1637           fam->fillWithZero();
1638           for(const int *it3=tmp->begin();it3!=tmp->end();it3++)
1639             if(allIds->presenceOfValue(*it3))
1640               {
1641                 std::string famName=getFamilyNameGivenId(*it3);
1642                 families[famName]=0;
1643                 famsFetched.insert(famName);
1644               }
1645         }
1646     }
1647   //
1648   std::vector<std::string> allFams=getFamiliesNames();
1649   std::set<std::string> allFamsS(allFams.begin(),allFams.end());
1650   std::set<std::string> unFetchedIds;
1651   std::set_difference(allFamsS.begin(),allFamsS.end(),famsFetched.begin(),famsFetched.end(),std::inserter(unFetchedIds,unFetchedIds.end()));
1652   for(std::set<std::string>::const_iterator it4=unFetchedIds.begin();it4!=unFetchedIds.end();it4++)
1653     families[*it4]=_families[*it4];
1654   _families=families;
1655 }
1656
1657 /*!
1658  * This method normalizes fam id with the following policy.
1659  * Level #0 famids < 0, Level #-1 famids < 0 and for Level #1 famids >= 0
1660  * This policy is those defined in the MED file format but is the opposite of those implemented in SMESH and Trio.
1661  * This method will throw an exception if a same family id is detected in different level.
1662  */
1663 void MEDFileMesh::normalizeFamIdsMEDFile()
1664 {
1665   ensureDifferentFamIdsPerLevel();
1666   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> allIds=getAllFamiliesIdsReferenced();
1667   std::vector<int> levs=getNonEmptyLevelsExt();
1668   std::set<int> levsS(levs.begin(),levs.end());
1669   std::set<std::string> famsFetched;
1670   std::map<std::string,int> families;
1671   int refId=1;
1672   if(std::find(levs.begin(),levs.end(),1)!=levs.end())
1673     {
1674       levsS.erase(1);
1675       const DataArrayInt *fam=getFamilyFieldAtLevel(1);
1676       if(fam)
1677         {
1678           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=fam->getDifferentValues();
1679           std::map<int,int> ren;
1680           for(const int *it=tmp->begin();it!=tmp->end();it++,refId++)
1681             ren[*it]=refId;
1682           int nbOfTuples=fam->getNumberOfTuples();
1683           int *start=const_cast<DataArrayInt *>(fam)->getPointer();
1684           for(int *w=start;w!=start+nbOfTuples;w++)
1685             *w=ren[*w];
1686           for(const int *it=tmp->begin();it!=tmp->end();it++)
1687             {
1688               if(allIds->presenceOfValue(*it))
1689                 {
1690                   std::string famName=getFamilyNameGivenId(*it);
1691                   families[famName]=ren[*it];
1692                   famsFetched.insert(famName);
1693                 }
1694             }
1695         }
1696     }
1697   refId=-1;
1698   for(std::set<int>::const_reverse_iterator it2=levsS.rbegin();it2!=levsS.rend();it2++)
1699     {
1700       const DataArrayInt *fam=getFamilyFieldAtLevel(*it2);
1701       if(fam)
1702         {
1703           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=fam->getDifferentValues();
1704           std::map<int,int> ren;
1705           for(const int *it=tmp->begin();it!=tmp->end();it++,refId--)
1706             ren[*it]=refId;
1707           int nbOfTuples=fam->getNumberOfTuples();
1708           int *start=const_cast<DataArrayInt *>(fam)->getPointer();
1709           for(int *w=start;w!=start+nbOfTuples;w++)
1710             *w=ren[*w];
1711           for(const int *it=tmp->begin();it!=tmp->end();it++)
1712             {
1713               if(allIds->presenceOfValue(*it))
1714                 {
1715                   std::string famName=getFamilyNameGivenId(*it);
1716                   families[famName]=ren[*it];
1717                   famsFetched.insert(famName);
1718                 }
1719             }
1720         }
1721     }
1722   //
1723   std::vector<std::string> allFams=getFamiliesNames();
1724   std::set<std::string> allFamsS(allFams.begin(),allFams.end());
1725   std::set<std::string> unFetchedIds;
1726   std::set_difference(allFamsS.begin(),allFamsS.end(),famsFetched.begin(),famsFetched.end(),std::inserter(unFetchedIds,unFetchedIds.end()));
1727   for(std::set<std::string>::const_iterator it4=unFetchedIds.begin();it4!=unFetchedIds.end();it4++)
1728     families[*it4]=_families[*it4];
1729   _families=families;
1730 }
1731
1732 /*!
1733  * Returns a name of the family by its id. If there are several families having the given
1734  * id, the name first in lexical order is returned.
1735  *  \param [in] id - the id of the family whose name is required.
1736  *  \return std::string - the name of the found family.
1737  *  \throw If no family with the given \a id exists.
1738  */
1739 std::string MEDFileMesh::getFamilyNameGivenId(int id) const
1740 {
1741   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
1742     if((*it).second==id)
1743       return (*it).first;
1744   std::ostringstream oss; oss << "MEDFileUMesh::getFamilyNameGivenId : no such family id : " << id;
1745   throw INTERP_KERNEL::Exception(oss.str().c_str());
1746 }
1747
1748 /*!
1749  * Returns a string describing \a this mesh. This description includes the mesh name and
1750  * the mesh description string.
1751  *  \return std::string - the mesh information string.
1752  */
1753 std::string MEDFileMesh::simpleRepr() const
1754 {
1755   std::ostringstream oss;
1756   oss << "(*************************************)\n(* GENERAL INFORMATION ON THE MESH : *)\n(*************************************)\n";
1757   oss << "- Name of the mesh : <<" << getName() << ">>\n";
1758   oss << "- Description associated to the mesh : " << getDescription() << std::endl;
1759   return oss.str();
1760 }
1761
1762 /*!
1763  * This method is nearly like getFamilyFieldAtLevel method. Except that if the array does not exist at the specified level \a meshDimRelToMaxExt
1764  * an empty one is created.
1765  */
1766 DataArrayInt *MEDFileMesh::getOrCreateAndGetFamilyFieldAtLevel(int meshDimRelToMaxExt)
1767 {
1768   DataArrayInt *ret(getFamilyFieldAtLevel(meshDimRelToMaxExt));
1769   if(ret)
1770     return ret;
1771   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr(DataArrayInt::New());
1772   arr->alloc(getSizeAtLevel(meshDimRelToMaxExt),1);
1773   arr->fillWithZero();
1774   setFamilyFieldArr(meshDimRelToMaxExt,arr);
1775   return getFamilyFieldAtLevel(meshDimRelToMaxExt);
1776 }
1777
1778 /*!
1779  * Returns ids of mesh entities contained in a given group of a given dimension.
1780  *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
1781  *          are required.
1782  *  \param [in] grp - the name of the group of interest.
1783  *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
1784  *          returned instead of ids. 
1785  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
1786  *          numbers, if available and required, of mesh entities of the group. The caller
1787  *          is to delete this array using decrRef() as it is no more needed. 
1788  *  \throw If the name of a nonexistent group is specified.
1789  *  \throw If the family field is missing for \a meshDimRelToMaxExt.
1790  */
1791 DataArrayInt *MEDFileMesh::getGroupArr(int meshDimRelToMaxExt, const std::string& grp, bool renum) const
1792 {
1793   std::vector<std::string> tmp(1);
1794   tmp[0]=grp;
1795   DataArrayInt *ret=getGroupsArr(meshDimRelToMaxExt,tmp,renum);
1796   ret->setName(grp);
1797   return ret;
1798 }
1799
1800 /*!
1801  * Returns ids of mesh entities contained in given groups of a given dimension.
1802  *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
1803  *          are required.
1804  *  \param [in] grps - the names of the groups of interest.
1805  *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
1806  *          returned instead of ids.
1807  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
1808  *          numbers, if available and required, of mesh entities of the groups. The caller
1809  *          is to delete this array using decrRef() as it is no more needed. 
1810  *  \throw If the name of a nonexistent group is present in \a grps.
1811  *  \throw If the family field is missing for \a meshDimRelToMaxExt.
1812  */
1813 DataArrayInt *MEDFileMesh::getGroupsArr(int meshDimRelToMaxExt, const std::vector<std::string>& grps, bool renum) const
1814 {
1815   std::vector<std::string> fams2=getFamiliesOnGroups(grps);
1816   return getFamiliesArr(meshDimRelToMaxExt,fams2,renum);
1817 }
1818
1819 /*!
1820  * Returns ids of mesh entities contained in a given family of a given dimension.
1821  *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
1822  *          are required.
1823  *  \param [in] fam - the name of the family of interest.
1824  *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
1825  *          returned instead of ids. 
1826  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
1827  *          numbers, if available and required, of mesh entities of the family. The caller
1828  *          is to delete this array using decrRef() as it is no more needed. 
1829  *  \throw If the family field is missing for \a meshDimRelToMaxExt.
1830  */
1831 DataArrayInt *MEDFileMesh::getFamilyArr(int meshDimRelToMaxExt, const std::string& fam, bool renum) const
1832 {
1833   std::vector<std::string> tmp(1);
1834   tmp[0]=fam;
1835   DataArrayInt *ret=getFamiliesArr(meshDimRelToMaxExt,tmp,renum);
1836   ret->setName(fam);
1837   return ret;
1838 }
1839
1840 /*!
1841  * Returns ids of nodes contained in a given group.
1842  *  \param [in] grp - the name of the group of interest.
1843  *  \param [in] renum - if \c true, the optional numbers of nodes, if available, are
1844  *          returned instead of ids. 
1845  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
1846  *          numbers, if available and required, of nodes of the group. The caller
1847  *          is to delete this array using decrRef() as it is no more needed. 
1848  *  \throw If the name of a nonexistent group is specified.
1849  *  \throw If the family field is missing for nodes.
1850  */
1851 DataArrayInt *MEDFileMesh::getNodeGroupArr(const std::string& grp, bool renum) const
1852 {
1853   std::vector<std::string> tmp(1);
1854   tmp[0]=grp;
1855   DataArrayInt *ret=getNodeGroupsArr(tmp,renum);
1856   ret->setName(grp);
1857   return ret;
1858 }
1859
1860 /*!
1861  * Returns ids of nodes contained in given groups.
1862  *  \param [in] grps - the names of the groups of interest.
1863  *  \param [in] renum - if \c true, the optional numbers of nodes, if available, are
1864  *          returned instead of ids. 
1865  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
1866  *          numbers, if available and required, of nodes of the groups. The caller
1867  *          is to delete this array using decrRef() as it is no more needed. 
1868  *  \throw If the name of a nonexistent group is present in \a grps.
1869  *  \throw If the family field is missing for nodes.
1870  */
1871 DataArrayInt *MEDFileMesh::getNodeGroupsArr(const std::vector<std::string>& grps, bool renum) const
1872 {
1873   return getGroupsArr(1,grps,renum);
1874 }
1875
1876 /*!
1877  * Returns ids of nodes contained in a given group.
1878  *  \param [in] grp - the name of the group of interest.
1879  *  \param [in] renum - if \c true, the optional numbers of nodes, if available, are
1880  *          returned instead of ids. 
1881  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
1882  *          numbers, if available and required, of nodes of the group. The caller
1883  *          is to delete this array using decrRef() as it is no more needed. 
1884  *  \throw If the name of a nonexistent group is specified.
1885  *  \throw If the family field is missing for nodes.
1886  */
1887 DataArrayInt *MEDFileMesh::getNodeFamilyArr(const std::string& fam, bool renum) const
1888 {
1889   std::vector<std::string> tmp(1);
1890   tmp[0]=fam;
1891   DataArrayInt *ret=getNodeFamiliesArr(tmp,renum);
1892   ret->setName(fam);
1893   return ret;
1894 }
1895
1896 /*!
1897  * Returns ids of nodes contained in given families.
1898  *  \param [in] fams - the names of the families of interest.
1899  *  \param [in] renum - if \c true, the optional numbers of nodes, if available, are
1900  *          returned instead of ids. 
1901  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
1902  *          numbers, if available and required, of nodes of the families. The caller
1903  *          is to delete this array using decrRef() as it is no more needed. 
1904  *  \throw If the family field is missing for nodes.
1905  */
1906 DataArrayInt *MEDFileMesh::getNodeFamiliesArr(const std::vector<std::string>& fams, bool renum) const
1907 {
1908   return getFamiliesArr(1,fams,renum);
1909 }
1910
1911 /*!
1912  * Adds groups of given dimension and creates corresponding families and family fields
1913  * given ids of mesh entities of each group.
1914  *  \param [in] meshDimRelToMaxExt - the relative mesh dimension of given mesh entities.
1915  *  \param [in] grps - a sequence of arrays of ids each describing a group.
1916  *  \param [in] renum - \c true means that \a grps contains not ids but optional numbers
1917  *          of mesh entities.
1918  *  \throw If names of some groups in \a grps are equal.
1919  *  \throw If \a grps includes a group with an empty name.
1920  *  \throw If \a grps includes invalid ids (or numbers if \a renum == \c true ).
1921  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
1922  */
1923 void MEDFileMesh::setGroupsAtLevel(int meshDimRelToMaxExt, const std::vector<const DataArrayInt *>& grps, bool renum)
1924 {
1925   if(grps.empty())
1926     return ;
1927   std::set<std::string> grpsName;
1928   std::vector<std::string> grpsName2(grps.size());
1929   int i=0;
1930
1931   for(std::vector<const DataArrayInt *>::const_iterator it=grps.begin();it!=grps.end();it++,i++)
1932     {
1933       grpsName.insert((*it)->getName());
1934       grpsName2[i]=(*it)->getName();
1935     }
1936   if(grpsName.size()!=grps.size())
1937     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsAtLevel : groups name must be different each other !");
1938   if(grpsName.find(std::string(""))!=grpsName.end())
1939     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsAtLevel : groups name must be different empty string !");
1940   int sz=getSizeAtLevel(meshDimRelToMaxExt);
1941   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fam;
1942   std::vector< std::vector<int> > fidsOfGroups;
1943   if(!renum)
1944     {
1945       fam=DataArrayInt::MakePartition(grps,sz,fidsOfGroups);
1946     }
1947   else
1948     {
1949       std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > grps2(grps.size());
1950       for(unsigned int ii=0;ii<grps.size();ii++)
1951         {
1952           grps2[ii]=MEDFileUMeshSplitL1::Renumber(getRevNumberFieldAtLevel(meshDimRelToMaxExt),grps[ii]);
1953           grps2[ii]->setName(grps[ii]->getName());
1954         }
1955       std::vector<const DataArrayInt *> grps3(grps2.begin(),grps2.end());
1956       fam=DataArrayInt::MakePartition(grps3,sz,fidsOfGroups);
1957     }
1958   int offset=1;
1959   if(!_families.empty())
1960     offset=getMaxAbsFamilyId()+1;
1961   TranslateFamilyIds(meshDimRelToMaxExt==1?offset:-offset,fam,fidsOfGroups);
1962   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=fam->getDifferentValues();
1963   appendFamilyEntries(ids,fidsOfGroups,grpsName2);
1964   setFamilyFieldArr(meshDimRelToMaxExt,fam);
1965 }
1966
1967 /*!
1968  * This method append into '_families' attribute the families whose ids are in 'famIds'. Warning 'famIds' are expected to be ids
1969  * not in '_families'. Groups information are given in parameters in order to give to families representative names.
1970  * For the moment, the two last input parameters are not taken into account.
1971  */
1972 void MEDFileMesh::appendFamilyEntries(const DataArrayInt *famIds, const std::vector< std::vector<int> >& fidsOfGrps, const std::vector<std::string>& grpNames)
1973 {
1974   std::map<int,std::string> famInv;
1975   for(const int *it=famIds->begin();it!=famIds->end();it++)
1976     {
1977       std::ostringstream oss;
1978       oss << "Family_" << (*it);
1979       _families[oss.str()]=(*it);
1980       famInv[*it]=oss.str();
1981     }
1982   int i=0;
1983   for(std::vector< std::vector<int> >::const_iterator it1=fidsOfGrps.begin();it1!=fidsOfGrps.end();it1++,i++)
1984     {
1985       for(std::vector<int>::const_iterator it2=(*it1).begin();it2!=(*it1).end();it2++)
1986         {
1987           _groups[grpNames[i]].push_back(famInv[*it2]);
1988         }
1989     }
1990 }
1991
1992 std::vector<INTERP_KERNEL::NormalizedCellType> MEDFileMesh::getAllGeoTypes() const
1993 {
1994   std::vector<int> levs(getNonEmptyLevels());
1995   std::vector<INTERP_KERNEL::NormalizedCellType> ret;
1996   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
1997     {
1998       std::vector<INTERP_KERNEL::NormalizedCellType> elts(getGeoTypesAtLevel(*it));
1999       ret.insert(ret.end(),elts.begin(),elts.end());
2000     }
2001   return ret;
2002 }
2003
2004 std::vector<int> MEDFileMesh::getDistributionOfTypes(int meshDimRelToMax) const
2005 {
2006   MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> mLev(getGenMeshAtLevel(meshDimRelToMax));
2007   return mLev->getDistributionOfTypes();
2008 }
2009
2010 void MEDFileMesh::loadLLWithAdditionalItems(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
2011 {
2012   loadLL(fid,mName,dt,it,mrs);
2013   loadJointsFromFile(fid);
2014   loadEquivalences(fid);
2015 }
2016
2017 void MEDFileMesh::TranslateFamilyIds(int offset, DataArrayInt *famArr, std::vector< std::vector<int> >& famIdsPerGrp)
2018 {
2019   famArr->applyLin(offset>0?1:-1,offset,0);
2020   for(std::vector< std::vector<int> >::iterator it1=famIdsPerGrp.begin();it1!=famIdsPerGrp.end();it1++)
2021     {
2022       if(offset<0)
2023         std::transform((*it1).begin(),(*it1).end(),(*it1).begin(),std::negate<int>());
2024       std::transform((*it1).begin(),(*it1).end(),(*it1).begin(),std::bind2nd(std::plus<int>(),offset));
2025     }
2026 }
2027
2028 /*!
2029  * Warning no check is done on 'nameTry' in parameter. It should be non empty.
2030  * This method returns a name close to 'nameTry' so that it is not already into 'namesToAvoid'.
2031  * If this method fails to find such a name it will throw an exception.
2032  */
2033 std::string MEDFileMesh::CreateNameNotIn(const std::string& nameTry, const std::vector<std::string>& namesToAvoid)
2034 {
2035   //attempt #0
2036   if(std::find(namesToAvoid.begin(),namesToAvoid.end(),nameTry)==namesToAvoid.end())
2037     return nameTry;
2038   //attempt #1
2039   std::size_t len=nameTry.length();
2040   for(std::size_t ii=1;ii<len;ii++)
2041     {
2042       std::string tmp=nameTry.substr(ii,len-ii);
2043       if(std::find(namesToAvoid.begin(),namesToAvoid.end(),tmp)==namesToAvoid.end())
2044         return tmp;
2045     }
2046   //attempt #2
2047   if(len>=1)
2048     {
2049       for(std::size_t i=1;i<30;i++)
2050         {
2051           std::string tmp1(nameTry.at(0),i);
2052           tmp1+=nameTry;
2053           if(std::find(namesToAvoid.begin(),namesToAvoid.end(),tmp1)==namesToAvoid.end())
2054             return tmp1;
2055         }
2056     }
2057   //attempt #3
2058   std::string tmp2;
2059   for(std::vector<std::string>::const_iterator it2=namesToAvoid.begin();it2!=namesToAvoid.end();it2++)
2060     tmp2+=(*it2);
2061   if(std::find(namesToAvoid.begin(),namesToAvoid.end(),tmp2)==namesToAvoid.end())
2062     return tmp2;
2063   throw INTERP_KERNEL::Exception("MEDFileMesh::CreateNameNotIn : impossible to find a not already used name !");
2064 }
2065
2066 int MEDFileMesh::PutInThirdComponentOfCodeOffset(std::vector<int>& code, int strt)
2067 {
2068   std::size_t nbOfChunks=code.size()/3;
2069   if(code.size()%3!=0)
2070     throw INTERP_KERNEL::Exception("MEDFileMesh::PutInThirdComponentOfCodeOffset : code has invalid size : should be of size 3*x !");
2071   int ret=strt;
2072   for(std::size_t i=0;i<nbOfChunks;i++)
2073     {
2074       code[3*i+2]=ret;
2075       ret+=code[3*i+1];
2076     }
2077   return ret;
2078 }
2079
2080 /*!
2081  * This method should be called by any set* method of subclasses to deal automatically with _name attribute.
2082  * If _name attribute is empty the name of 'm' if taken as _name attribute.
2083  * If _name is not empty and that 'm' has the same name nothing is done.
2084  * If _name is not emplt and that 'm' has \b NOT the same name an exception is thrown.
2085  */
2086 void MEDFileMesh::dealWithTinyInfo(const MEDCouplingMesh *m)
2087 {
2088   if(!m)
2089     throw INTERP_KERNEL::Exception("MEDFileMesh::dealWithTinyInfo : input mesh in NULL !");
2090   if(_name.empty())
2091     _name=m->getName();
2092   else
2093     {
2094       std::string name(m->getName());
2095       if(!name.empty())
2096         {
2097           if(_name!=name)
2098             {
2099               std::ostringstream oss; oss << "MEDFileMesh::dealWithTinyInfo : name of current MEDfile mesh is '" << _name << "' whereas name of input mesh is : '";
2100               oss << name << "' ! Names must match !";
2101               throw INTERP_KERNEL::Exception(oss.str().c_str());
2102             }
2103         }
2104     }
2105   if(_desc_name.empty())
2106     _desc_name=m->getDescription();
2107   else
2108     {
2109       std::string name(m->getDescription());
2110       if(!name.empty())
2111         {
2112           if(_desc_name!=name)
2113             {
2114               std::ostringstream oss; oss << "MEDFileMesh::dealWithTinyInfo : description of current MEDfile mesh is '" << _desc_name << "' whereas name of input mesh is : '";
2115               oss << name << "' ! Names must match !";
2116               throw INTERP_KERNEL::Exception(oss.str().c_str());
2117             }
2118         }
2119     }
2120 }
2121
2122 void MEDFileMesh::getFamilyRepr(std::ostream& oss) const
2123 {
2124   oss << "(**************************)\n(* FAMILIES OF THE MESH : *)\n(**************************)\n";
2125   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
2126     {
2127       oss << "- Family with name \"" << (*it).first << "\" with number " << (*it).second << std::endl;
2128       oss << "  - Groups lying on this family : ";
2129       std::vector<std::string> grps=getGroupsOnFamily((*it).first);
2130       std::copy(grps.begin(),grps.end(),std::ostream_iterator<std::string>(oss," "));
2131       oss << std::endl << std::endl;
2132     }
2133 }
2134
2135 /*!
2136  * Returns a new MEDFileUMesh holding the mesh data that has been read from a given MED
2137  * file. The mesh to load is specified by its name and numbers of a time step and an
2138  * iteration.
2139  *  \param [in] fileName - the name of MED file to read.
2140  *  \param [in] mName - the name of the mesh to read.
2141  *  \param [in] dt - the number of a time step.
2142  *  \param [in] it - the number of an iteration.
2143  *  \return MEDFileUMesh * - a new instance of MEDFileUMesh. The caller is to delete this
2144  *          mesh using decrRef() as it is no more needed. 
2145  *  \throw If the file is not readable.
2146  *  \throw If there is no mesh with given attributes in the file.
2147  *  \throw If the mesh in the file is not an unstructured one.
2148  */
2149 MEDFileUMesh *MEDFileUMesh::New(const std::string& fileName, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
2150 {
2151   MEDFileUtilities::CheckFileForRead(fileName);
2152   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
2153   return new MEDFileUMesh(fid,mName,dt,it,mrs);
2154 }
2155
2156 /*!
2157  * Returns a new MEDFileUMesh holding the mesh data that has been read from a given MED
2158  * file. The first mesh in the file is loaded.
2159  *  \param [in] fileName - the name of MED file to read.
2160  *  \return MEDFileUMesh * - a new instance of MEDFileUMesh. The caller is to delete this
2161  *          mesh using decrRef() as it is no more needed. 
2162  *  \throw If the file is not readable.
2163  *  \throw If there is no meshes in the file.
2164  *  \throw If the mesh in the file is not an unstructured one.
2165  */
2166 MEDFileUMesh *MEDFileUMesh::New(const std::string& fileName, MEDFileMeshReadSelector *mrs)
2167 {
2168   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
2169   if(ms.empty())
2170     {
2171       std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
2172       throw INTERP_KERNEL::Exception(oss.str().c_str());
2173     }
2174   MEDFileUtilities::CheckFileForRead(fileName);
2175   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
2176   int dt,it;
2177   ParaMEDMEM::MEDCouplingMeshType meshType;
2178   std::string dummy2;
2179   MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dt,it,dummy2);
2180   return new MEDFileUMesh(fid,ms.front(),dt,it,mrs);
2181 }
2182
2183 /*!
2184  * Returns an empty instance of MEDFileUMesh.
2185  *  \return MEDFileUMesh * - a new instance of MEDFileUMesh. The caller is to delete this
2186  *          mesh using decrRef() as it is no more needed. 
2187  */
2188 MEDFileUMesh *MEDFileUMesh::New()
2189 {
2190   return new MEDFileUMesh;
2191 }
2192
2193 /*!
2194  * This method loads from file with name \a fileName the mesh called \a mName as New does. The difference is that
2195  * here only a part of cells contained in the file will be loaded. The selection of cell is specified using the two consecutive parameters
2196  * \a types and \a slicPerTyp. This method allows to load from a mesh (typically huge) in a MED file a part of cells of that mesh.
2197  * The part of cells is specified using triplet (start,stop,step) for each geometric type. Only nodes lying on selected cells will be loaded to reduce
2198  * at most the memory consumtion.
2199  *
2200  * \param [in] fileName - the name of the file.
2201  * \param [in] mName - the name of the mesh to be read.
2202  * \param [in] types - the list of the geo types of which some part will be taken. A geometric type in \a types must appear only once at most.
2203  * \param [in] slicPerType - an array of size 3 times larger than \a types that specifies for each type in \a types (in the same order) resp the start, the stop and the step.
2204  * \param [in] dt - the iteration, that is to say the first element of the pair that locates the asked time step.
2205  * \param [in] it - the order, that is to say the second element of the pair that locates the asked time step.
2206  * \param [in] mrs - the request for what to be loaded.
2207  * \return MEDFileUMesh * - a new instance of MEDFileUMesh. The caller is to delete this mesh using decrRef() as it is no more needed.
2208  */
2209 MEDFileUMesh *MEDFileUMesh::LoadPartOf(const std::string& fileName, const std::string& mName, const std::vector<INTERP_KERNEL::NormalizedCellType>& types, const std::vector<int>& slicPerTyp, int dt, int it, MEDFileMeshReadSelector *mrs)
2210 {
2211   MEDFileUtilities::CheckFileForRead(fileName);
2212   MEDFileUtilities::AutoFid fid(MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY));
2213   return MEDFileUMesh::LoadPartOf(fid,mName,types,slicPerTyp,dt,it,mrs);
2214 }
2215
2216 /*!
2217  * Please refer to the other MEDFileUMesh::LoadPartOf method that has the same semantic and the same parameter (excepted the first).
2218  * This method is \b NOT wrapped into python.
2219  */
2220 MEDFileUMesh *MEDFileUMesh::LoadPartOf(med_idt fid, const std::string& mName, const std::vector<INTERP_KERNEL::NormalizedCellType>& types, const std::vector<int>& slicPerTyp, int dt, int it, MEDFileMeshReadSelector *mrs)
2221 {
2222   MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret(MEDFileUMesh::New());
2223   ret->loadPartUMeshFromFile(fid,mName,types,slicPerTyp,dt,it,mrs);
2224   return ret.retn();
2225 }
2226
2227 std::size_t MEDFileUMesh::getHeapMemorySizeWithoutChildren() const
2228 {
2229   std::size_t ret(MEDFileMesh::getHeapMemorySizeWithoutChildren());
2230   ret+=_ms.capacity()*(sizeof(MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1>));
2231   return ret;
2232 }
2233
2234 std::vector<const BigMemoryObject *> MEDFileUMesh::getDirectChildrenWithNull() const
2235 {
2236   std::vector<const BigMemoryObject *> ret(MEDFileMesh::getDirectChildrenWithNull());
2237   ret.push_back((const DataArrayDouble*)_coords);
2238   ret.push_back((const DataArrayInt *)_fam_coords);
2239   ret.push_back((const DataArrayInt *)_num_coords);
2240   ret.push_back((const DataArrayInt *)_rev_num_coords);
2241   ret.push_back((const DataArrayAsciiChar *)_name_coords);
2242   ret.push_back((const PartDefinition *)_part_coords);
2243   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2244     ret.push_back((const MEDFileUMeshSplitL1*) *it);
2245   return ret;
2246 }
2247
2248 MEDFileMesh *MEDFileUMesh::shallowCpy() const
2249 {
2250   MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret=new MEDFileUMesh(*this);
2251   return ret.retn();
2252 }
2253
2254 MEDFileMesh *MEDFileUMesh::createNewEmpty() const
2255 {
2256   return new MEDFileUMesh;
2257 }
2258
2259 MEDFileMesh *MEDFileUMesh::deepCpy() const
2260 {
2261   MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret=new MEDFileUMesh(*this);
2262   ret->deepCpyEquivalences(*this);
2263   if((const DataArrayDouble*)_coords)
2264     ret->_coords=_coords->deepCpy();
2265   if((const DataArrayInt*)_fam_coords)
2266     ret->_fam_coords=_fam_coords->deepCpy();
2267   if((const DataArrayInt*)_num_coords)
2268     ret->_num_coords=_num_coords->deepCpy();
2269   if((const DataArrayInt*)_rev_num_coords)
2270     ret->_rev_num_coords=_rev_num_coords->deepCpy();
2271   if((const DataArrayAsciiChar*)_name_coords)
2272     ret->_name_coords=_name_coords->deepCpy();
2273   std::size_t i=0;
2274   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,i++)
2275     {
2276       if((const MEDFileUMeshSplitL1 *)(*it))
2277         ret->_ms[i]=(*it)->deepCpy(ret->_coords);
2278     }
2279   if((const PartDefinition*)_part_coords)
2280     ret->_part_coords=_part_coords->deepCpy();
2281   return ret.retn();
2282 }
2283
2284 /*!
2285  * Checks if \a this and another mesh are equal.
2286  *  \param [in] other - the mesh to compare with.
2287  *  \param [in] eps - a precision used to compare real values.
2288  *  \param [in,out] what - the string returning description of unequal data.
2289  *  \return bool - \c true if the meshes are equal, \c false, else.
2290  */
2291 bool MEDFileUMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
2292 {
2293   if(!MEDFileMesh::isEqual(other,eps,what))
2294     return false;
2295   const MEDFileUMesh *otherC=dynamic_cast<const MEDFileUMesh *>(other);
2296   if(!otherC)
2297     {
2298       what="Mesh types differ ! This is unstructured and other is NOT !";
2299       return false;
2300     }
2301   clearNonDiscrAttributes();
2302   otherC->clearNonDiscrAttributes();
2303   const DataArrayDouble *coo1=_coords;
2304   const DataArrayDouble *coo2=otherC->_coords;
2305   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
2306     {
2307       what="Mismatch of coordinates ! One is defined and not other !";
2308       return false;
2309     }
2310   if(coo1)
2311     {
2312       bool ret=coo1->isEqual(*coo2,eps);
2313       if(!ret)
2314         {
2315           what="Coords differ !";
2316           return false;
2317         }
2318     }
2319   const DataArrayInt *famc1=_fam_coords;
2320   const DataArrayInt *famc2=otherC->_fam_coords;
2321   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
2322     {
2323       what="Mismatch of families arr on nodes ! One is defined and not other !";
2324       return false;
2325     }
2326   if(famc1)
2327     {
2328       bool ret=famc1->isEqual(*famc2);
2329       if(!ret)
2330         {
2331           what="Families arr on node differ !";
2332           return false;
2333         }
2334     }
2335   const DataArrayInt *numc1=_num_coords;
2336   const DataArrayInt *numc2=otherC->_num_coords;
2337   if((numc1==0 && numc2!=0) || (numc1!=0 && numc2==0))
2338     {
2339       what="Mismatch of numbering arr on nodes ! One is defined and not other !";
2340       return false;
2341     }
2342   if(numc1)
2343     {
2344       bool ret=numc1->isEqual(*numc2);
2345       if(!ret)
2346         {
2347           what="Numbering arr on node differ !";
2348           return false;
2349         }
2350     }
2351   const DataArrayAsciiChar *namec1=_name_coords;
2352   const DataArrayAsciiChar *namec2=otherC->_name_coords;
2353   if((namec1==0 && namec2!=0) || (namec1!=0 && namec2==0))
2354     {
2355       what="Mismatch of naming arr on nodes ! One is defined and not other !";
2356       return false;
2357     }
2358   if(namec1)
2359     {
2360       bool ret=namec1->isEqual(*namec2);
2361       if(!ret)
2362         {
2363           what="Names arr on node differ !";
2364           return false;
2365         }
2366     }
2367   if(_ms.size()!=otherC->_ms.size())
2368     {
2369       what="Number of levels differs !";
2370       return false;
2371     }
2372   std::size_t sz=_ms.size();
2373   for(std::size_t i=0;i<sz;i++)
2374     {
2375       const MEDFileUMeshSplitL1 *s1=_ms[i];
2376       const MEDFileUMeshSplitL1 *s2=otherC->_ms[i];
2377       if((s1==0 && s2!=0) || (s1!=0 && s2==0))
2378         {
2379           what="Mismatch of presence of sub levels !";
2380           return false;
2381         }
2382       if(s1)
2383         {
2384           bool ret=s1->isEqual(s2,eps,what);
2385           if(!ret)
2386             return false;
2387         }
2388     }
2389   const PartDefinition *pd0(_part_coords),*pd1(otherC->_part_coords);
2390   if(!pd0 && !pd1)
2391     return true;
2392   if((!pd0 && pd1) || (pd0 && !pd1))
2393     {
2394       what=std::string("node part def is defined only for one among this or other !");
2395       return false;
2396     }
2397   return pd0->isEqual(pd1,what);
2398 }
2399
2400 /*!
2401  * Clears redundant attributes of incorporated data arrays.
2402  */
2403 void MEDFileUMesh::clearNonDiscrAttributes() const
2404 {
2405   MEDFileMesh::clearNonDiscrAttributes();
2406   const DataArrayDouble *coo1=_coords;
2407   if(coo1)
2408     (const_cast<DataArrayDouble *>(coo1))->setName("");//This parameter is not discriminant for comparison
2409   const DataArrayInt *famc1=_fam_coords;
2410   if(famc1)
2411     (const_cast<DataArrayInt *>(famc1))->setName("");//This parameter is not discriminant for comparison
2412   const DataArrayInt *numc1=_num_coords;
2413   if(numc1)
2414     (const_cast<DataArrayInt *>(numc1))->setName("");//This parameter is not discriminant for comparison
2415   const DataArrayAsciiChar *namc1=_name_coords;
2416   if(namc1)
2417     (const_cast<DataArrayAsciiChar *>(namc1))->setName("");//This parameter is not discriminant for comparison
2418   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2419     {
2420       const MEDFileUMeshSplitL1 *tmp=(*it);
2421       if(tmp)
2422         tmp->clearNonDiscrAttributes();
2423     }
2424 }
2425
2426 void MEDFileUMesh::setName(const std::string& name)
2427 {
2428   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
2429     if((MEDFileUMeshSplitL1 *)(*it)!=0)
2430       (*it)->setName(name);
2431   MEDFileMesh::setName(name);
2432 }
2433
2434 MEDFileUMesh::MEDFileUMesh()
2435 {
2436 }
2437
2438 MEDFileUMesh::MEDFileUMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
2439 try
2440 {
2441     loadLLWithAdditionalItems(fid,mName,dt,it,mrs);
2442 }
2443 catch(INTERP_KERNEL::Exception& e)
2444 {
2445     throw e;
2446 }
2447
2448 /*!
2449  * This method loads only a part of specified cells (given by range of cell ID per geometric type)
2450  * See MEDFileUMesh::LoadPartOf for detailed description.
2451  *
2452  * \sa loadLL
2453  */
2454 void MEDFileUMesh::loadPartUMeshFromFile(med_idt fid, const std::string& mName, const std::vector<INTERP_KERNEL::NormalizedCellType>& types, const std::vector<int>& slicPerTyp, int dt, int it, MEDFileMeshReadSelector *mrs)
2455 {
2456   MEDFileUMeshL2 loaderl2;
2457   ParaMEDMEM::MEDCouplingMeshType meshType;
2458   int dummy0,dummy1;
2459   std::string dummy2;
2460   int mid(MEDFileUMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dummy2));
2461   if(meshType!=UNSTRUCTURED)
2462     {
2463       std::ostringstream oss; oss << "loadPartUMeshFromFile : Trying to load as unstructured an existing mesh with name '" << mName << "' !";
2464       throw INTERP_KERNEL::Exception(oss.str().c_str());
2465     }
2466   loaderl2.loadPart(fid,mid,mName,types,slicPerTyp,dt,it,mrs);
2467   dispatchLoadedPart(fid,loaderl2,mName,mrs);
2468 }
2469
2470 /*!
2471  * \brief Write joints in a file
2472  */
2473 void MEDFileMesh::writeJoints(med_idt fid) const
2474 {
2475   if ( (const MEDFileJoints*) _joints )
2476     _joints->write(fid);
2477 }
2478
2479 /*!
2480  * \brief Load joints in a file or use provided ones
2481  */
2482 //================================================================================
2483 /*!
2484  * \brief Load joints in a file or use provided ones
2485  *  \param [in] fid - MED file descriptor
2486  *  \param [in] toUseInstedOfReading - optional joints to use instead of reading,
2487  *          Usually this joints are those just read by another iteration
2488  *          of namesake mesh, when this method is called by MEDFileMeshMultiTS::New()
2489  */
2490 //================================================================================
2491
2492 void MEDFileMesh::loadJointsFromFile(med_idt fid, MEDFileJoints* toUseInstedOfReading)
2493 {
2494   if ( toUseInstedOfReading )
2495     setJoints( toUseInstedOfReading );
2496   else
2497     _joints = MEDFileJoints::New( fid, _name );
2498 }
2499
2500 void MEDFileMesh::loadEquivalences(med_idt fid)
2501 {
2502   int nbOfEq(MEDFileEquivalences::PresenceOfEquivalences(fid,_name));
2503   if(nbOfEq>0)
2504     _equiv=MEDFileEquivalences::Load(fid,nbOfEq,this);
2505 }
2506
2507 void MEDFileMesh::deepCpyEquivalences(const MEDFileMesh& other)
2508 {
2509   const MEDFileEquivalences *equiv(other._equiv);
2510   if(equiv)
2511     _equiv=equiv->deepCpy(this);
2512 }
2513
2514 bool MEDFileMesh::areEquivalencesEqual(const MEDFileMesh *other, std::string& what) const
2515 {
2516   const MEDFileEquivalences *thisEq(_equiv),*otherEq(other->_equiv);
2517   if(!thisEq && !otherEq)
2518     return true;
2519   if(thisEq && otherEq)
2520     return thisEq->isEqual(otherEq,what);
2521   else
2522     {
2523       what+="Equivalence differs : defined in this and not in other (or reversely) !";
2524       return false;
2525     }
2526 }
2527
2528 void MEDFileMesh::getEquivalencesRepr(std::ostream& oss) const
2529 {
2530   const MEDFileEquivalences *equiv(_equiv);
2531   if(!equiv)
2532     return ;
2533   oss << "(******************************)\n(* EQUIVALENCES OF THE MESH : *)\n(******************************)\n";
2534   _equiv->getRepr(oss);
2535 }
2536
2537 /*!
2538  * \brief Return number of joints, which is equal to number of adjacent mesh domains
2539  */
2540 int MEDFileMesh::getNumberOfJoints() const
2541 {
2542   return ( (const MEDFileJoints *) _joints ) ? _joints->getNumberOfJoints() : 0;
2543 }
2544
2545 /*!
2546  * \brief Return joints with all adjacent mesh domains
2547  */
2548 MEDFileJoints * MEDFileMesh::getJoints() const
2549 {
2550   return const_cast<MEDFileJoints*>(& (*_joints));
2551 }
2552
2553 void MEDFileMesh::setJoints( MEDFileJoints* joints )
2554 {
2555   if ( joints != _joints )
2556     {
2557       _joints = joints;
2558       if ( joints )
2559         joints->incrRef();
2560     }
2561 }
2562
2563 /*!
2564  * This method loads \b all \b the \b mesh \a mName in the file with \a fid descriptor.
2565  *
2566  * \sa loadPartUMeshFromFile
2567  */
2568 void MEDFileUMesh::loadLL(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
2569 {
2570   MEDFileUMeshL2 loaderl2;
2571   ParaMEDMEM::MEDCouplingMeshType meshType;
2572   int dummy0,dummy1;
2573   std::string dummy2;
2574   int mid(MEDFileUMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dummy2));
2575   if(meshType!=UNSTRUCTURED)
2576     {
2577       std::ostringstream oss; oss << "Trying to load as unstructured an existing mesh with name '" << mName << "' !";
2578       throw INTERP_KERNEL::Exception(oss.str().c_str());
2579     }
2580   loaderl2.loadAll(fid,mid,mName,dt,it,mrs);
2581   dispatchLoadedPart(fid,loaderl2,mName,mrs);
2582 }
2583
2584 void MEDFileUMesh::dispatchLoadedPart(med_idt fid, const MEDFileUMeshL2& loaderl2, const std::string& mName, MEDFileMeshReadSelector *mrs)
2585 {
2586   int lev=loaderl2.getNumberOfLevels();
2587   _ms.resize(lev);
2588   for(int i=0;i<lev;i++)
2589     {
2590       if(!loaderl2.emptyLev(i))
2591         _ms[i]=new MEDFileUMeshSplitL1(loaderl2,mName,i);
2592       else
2593         _ms[i]=0;
2594     }
2595   MEDFileMeshL2::ReadFamiliesAndGrps(fid,mName,_families,_groups,mrs);
2596   //
2597   setName(loaderl2.getName());
2598   setDescription(loaderl2.getDescription());
2599   setUnivName(loaderl2.getUnivName());
2600   setIteration(loaderl2.getIteration());
2601   setOrder(loaderl2.getOrder());
2602   setTimeValue(loaderl2.getTime());
2603   setTimeUnit(loaderl2.getTimeUnit());
2604   _coords=loaderl2.getCoords();
2605   if(!mrs || mrs->isNodeFamilyFieldReading())
2606     _fam_coords=loaderl2.getCoordsFamily();
2607   if(!mrs || mrs->isNodeNumFieldReading())
2608     _num_coords=loaderl2.getCoordsNum();
2609   if(!mrs || mrs->isNodeNameFieldReading())
2610     _name_coords=loaderl2.getCoordsName();
2611   _part_coords=loaderl2.getPartDefOfCoo();
2612   computeRevNum();
2613 }
2614
2615 MEDFileUMesh::~MEDFileUMesh()
2616 {
2617 }
2618
2619 void MEDFileUMesh::writeLL(med_idt fid) const
2620 {
2621   const DataArrayDouble *coo=_coords;
2622   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
2623   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
2624   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
2625   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
2626   int spaceDim=coo?coo->getNumberOfComponents():0;
2627   int mdim(0);
2628   if(!_ms.empty())
2629     mdim=getMeshDimension();
2630   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
2631   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
2632   for(int i=0;i<spaceDim;i++)
2633     {
2634       std::string info=coo->getInfoOnComponent(i);
2635       std::string c,u;
2636       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
2637       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
2638       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
2639     }
2640   MEDFILESAFECALLERWR0(MEDmeshCr,(fid,maa,spaceDim,mdim,MED_UNSTRUCTURED_MESH,desc,"",MED_SORT_DTIT,MED_CARTESIAN,comp,unit));
2641   if(_univ_wr_status)
2642     MEDFILESAFECALLERWR0(MEDmeshUniversalNameWr,(fid,maa));
2643   std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE));
2644   MEDFileUMeshL2::WriteCoords(fid,meshName,_iteration,_order,_time,_coords,_fam_coords,_num_coords,_name_coords);
2645   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2646     if((const MEDFileUMeshSplitL1 *)(*it)!=0)
2647       (*it)->write(fid,meshName,mdim);
2648   MEDFileUMeshL2::WriteFamiliesAndGrps(fid,meshName,_families,_groups,_too_long_str);
2649 }
2650
2651 /*!
2652  * Returns relative dimensions of mesh entities (excluding nodes) present in \a this mesh.
2653  *  \return std::vector<int> - a sequence of the relative dimensions.
2654  */
2655 std::vector<int> MEDFileUMesh::getNonEmptyLevels() const
2656 {
2657   std::vector<int> ret;
2658   int lev=0;
2659   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
2660     if((const MEDFileUMeshSplitL1 *)(*it)!=0)
2661       if(!(*it)->empty())
2662         ret.push_back(lev);
2663   return ret;
2664 }
2665
2666 /*!
2667  * Returns relative dimensions of mesh entities (including nodes) present in \a this mesh.
2668  *  \return std::vector<int> - a sequence of the relative dimensions.
2669  */
2670 std::vector<int> MEDFileUMesh::getNonEmptyLevelsExt() const
2671 {
2672   std::vector<int> ret0=getNonEmptyLevels();
2673   if((const DataArrayDouble *) _coords)
2674     {
2675       std::vector<int> ret(ret0.size()+1);
2676       ret[0]=1;
2677       std::copy(ret0.begin(),ret0.end(),ret.begin()+1);
2678       return ret;
2679     }
2680   return ret0;
2681 }
2682
2683 std::vector<int> MEDFileUMesh::getFamArrNonEmptyLevelsExt() const
2684 {
2685   std::vector<int> ret;
2686   const DataArrayInt *famCoo(_fam_coords);
2687   if(famCoo)
2688     ret.push_back(1);
2689   int lev=0;
2690   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
2691     {
2692       const MEDFileUMeshSplitL1 *cur(*it);
2693       if(cur)
2694         if(cur->getFamilyField())
2695           ret.push_back(lev);
2696     }
2697   return ret;
2698 }
2699
2700 std::vector<int> MEDFileUMesh::getNumArrNonEmptyLevelsExt() const
2701 {
2702   std::vector<int> ret;
2703   const DataArrayInt *numCoo(_num_coords);
2704   if(numCoo)
2705     ret.push_back(1);
2706   int lev=0;
2707   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
2708     {
2709       const MEDFileUMeshSplitL1 *cur(*it);
2710       if(cur)
2711         if(cur->getNumberField())
2712           ret.push_back(lev);
2713     }
2714   return ret;
2715 }
2716
2717 std::vector<int> MEDFileUMesh::getNameArrNonEmptyLevelsExt() const
2718 {
2719   std::vector<int> ret;
2720   const DataArrayAsciiChar *nameCoo(_name_coords);
2721   if(nameCoo)
2722     ret.push_back(1);
2723   int lev=0;
2724   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
2725     {
2726       const MEDFileUMeshSplitL1 *cur(*it);
2727       if(cur)
2728         if(cur->getNameField())
2729           ret.push_back(lev);
2730     }
2731   return ret;
2732 }
2733
2734 /*!
2735  * Returns all relative mesh levels (**excluding nodes**) where a given group is defined.
2736  * To include nodes, call getGrpNonEmptyLevelsExt() method.
2737  *  \param [in] grp - the name of the group of interest.
2738  *  \return std::vector<int> - a sequence of the relative dimensions.
2739  */
2740 std::vector<int> MEDFileUMesh::getGrpNonEmptyLevels(const std::string& grp) const
2741 {
2742   std::vector<std::string> fams=getFamiliesOnGroup(grp);
2743   return getFamsNonEmptyLevels(fams);
2744 }
2745
2746 /*!
2747  * Returns all relative mesh levels (including nodes) where a given group is defined.
2748  *  \param [in] grp - the name of the group of interest.
2749  *  \return std::vector<int> - a sequence of the relative dimensions.
2750  */
2751 std::vector<int> MEDFileUMesh::getGrpNonEmptyLevelsExt(const std::string& grp) const
2752 {
2753   std::vector<std::string> fams=getFamiliesOnGroup(grp);
2754   return getFamsNonEmptyLevelsExt(fams);
2755 }
2756
2757 /*!
2758  * Returns all relative mesh levels (**excluding nodes**) where a given family is defined.
2759  * To include nodes, call getFamNonEmptyLevelsExt() method.
2760  *  \param [in] fam - the name of the family of interest.
2761  *  \return std::vector<int> - a sequence of the relative dimensions.
2762  */
2763 std::vector<int> MEDFileUMesh::getFamNonEmptyLevels(const std::string& fam) const
2764 {
2765   std::vector<std::string> fams(1,std::string(fam));
2766   return getFamsNonEmptyLevels(fams);
2767 }
2768
2769 /*!
2770  * Returns all relative mesh levels (including nodes) where a given family is defined.
2771  *  \param [in] fam - the name of the family of interest.
2772  *  \return std::vector<int> - a sequence of the relative dimensions.
2773  */
2774 std::vector<int> MEDFileUMesh::getFamNonEmptyLevelsExt(const std::string& fam) const
2775 {
2776   std::vector<std::string> fams(1,std::string(fam));
2777   return getFamsNonEmptyLevelsExt(fams);
2778 }
2779
2780 /*!
2781  * Returns all relative mesh levels (**excluding nodes**) where given groups are defined.
2782  * To include nodes, call getGrpsNonEmptyLevelsExt() method.
2783  *  \param [in] grps - a sequence of names of the groups of interest.
2784  *  \return std::vector<int> - a sequence of the relative dimensions.
2785  */
2786 std::vector<int> MEDFileUMesh::getGrpsNonEmptyLevels(const std::vector<std::string>& grps) const
2787 {
2788   std::vector<std::string> fams=getFamiliesOnGroups(grps);
2789   return getFamsNonEmptyLevels(fams);
2790 }
2791
2792 /*!
2793  * Returns all relative mesh levels (including nodes) where given groups are defined.
2794  *  \param [in] grps - a sequence of names of the groups of interest.
2795  *  \return std::vector<int> - a sequence of the relative dimensions.
2796  */
2797 std::vector<int> MEDFileUMesh::getGrpsNonEmptyLevelsExt(const std::vector<std::string>& grps) const
2798 {
2799   std::vector<std::string> fams=getFamiliesOnGroups(grps);
2800   return getFamsNonEmptyLevelsExt(fams);
2801 }
2802
2803 /*!
2804  * Returns all relative mesh levels (**excluding nodes**) where given families are defined.
2805  * To include nodes, call getFamsNonEmptyLevelsExt() method.
2806  *  \param [in] fams - the name of the family of interest.
2807  *  \return std::vector<int> - a sequence of the relative dimensions.
2808  */
2809 std::vector<int> MEDFileUMesh::getFamsNonEmptyLevels(const std::vector<std::string>& fams) const
2810 {
2811   std::vector<int> ret;
2812   std::vector<int> levs=getNonEmptyLevels();
2813   std::vector<int> famIds=getFamiliesIds(fams);
2814   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
2815     if(_ms[-(*it)]->presenceOfOneFams(famIds))
2816       ret.push_back(*it);
2817   return ret;
2818 }
2819
2820 /*!
2821  * Returns all relative mesh levels (including nodes) where given families are defined.
2822  *  \param [in] fams - the names of the families of interest.
2823  *  \return std::vector<int> - a sequence of the relative dimensions.
2824  */
2825 std::vector<int> MEDFileUMesh::getFamsNonEmptyLevelsExt(const std::vector<std::string>& fams) const
2826 {
2827   std::vector<int> ret0=getFamsNonEmptyLevels(fams);
2828   const DataArrayInt *famCoords=_fam_coords;
2829   if(!famCoords)
2830     return ret0;
2831   std::vector<int> famIds=getFamiliesIds(fams);
2832   if(famCoords->presenceOfValue(famIds))
2833     {
2834       std::vector<int> ret(ret0.size()+1);
2835       ret[0]=1;
2836       std::copy(ret0.begin(),ret0.end(),ret.begin()+1);
2837       return ret;
2838     }
2839   else
2840     return ret0;
2841 }
2842
2843 /*!
2844  * Returns names of groups that partly or fully appear on the level \a meshDimRelToMaxExt.
2845  *  \param [in] meshDimRelToMaxExt - a relative dimension of interest.
2846  *  \return std::vector<std::string> - a sequence of group names at \a meshDimRelToMaxExt
2847  *          level. 
2848  */
2849 std::vector<std::string> MEDFileUMesh::getGroupsOnSpecifiedLev(int meshDimRelToMaxExt) const
2850 {
2851   std::vector<std::string> ret;
2852   std::vector<std::string> allGrps=getGroupsNames();
2853   for(std::vector<std::string>::const_iterator it=allGrps.begin();it!=allGrps.end();it++)
2854     {
2855       std::vector<int> levs=getGrpNonEmptyLevelsExt((*it));
2856       if(std::find(levs.begin(),levs.end(),meshDimRelToMaxExt)!=levs.end())
2857         ret.push_back(*it);
2858     }
2859   return ret;
2860 }
2861
2862 int MEDFileUMesh::getMaxAbsFamilyIdInArrays() const
2863 {
2864   int ret=-std::numeric_limits<int>::max(),tmp=-1;
2865   if((const DataArrayInt *)_fam_coords)
2866     {
2867       int val=_fam_coords->getMaxValue(tmp);
2868       ret=std::max(ret,std::abs(val));
2869     }
2870   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2871     {
2872       if((const MEDFileUMeshSplitL1 *)(*it))
2873         {
2874           const DataArrayInt *da=(*it)->getFamilyField();
2875           if(da)
2876             {
2877               int val=da->getMaxValue(tmp);
2878               ret=std::max(ret,std::abs(val));
2879             }
2880         }
2881     }
2882   return ret;
2883 }
2884
2885 int MEDFileUMesh::getMaxFamilyIdInArrays() const
2886 {
2887   int ret=-std::numeric_limits<int>::max(),tmp=-1;
2888   if((const DataArrayInt *)_fam_coords)
2889     {
2890       int val=_fam_coords->getMaxValue(tmp);
2891       ret=std::max(ret,val);
2892     }
2893   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2894     {
2895       if((const MEDFileUMeshSplitL1 *)(*it))
2896         {
2897           const DataArrayInt *da=(*it)->getFamilyField();
2898           if(da)
2899             {
2900               int val=da->getMaxValue(tmp);
2901               ret=std::max(ret,val);
2902             }
2903         }
2904     }
2905   return ret;
2906 }
2907
2908 int MEDFileUMesh::getMinFamilyIdInArrays() const
2909 {
2910   int ret=std::numeric_limits<int>::max(),tmp=-1;
2911   if((const DataArrayInt *)_fam_coords)
2912     {
2913       int val=_fam_coords->getMinValue(tmp);
2914       ret=std::min(ret,val);
2915     }
2916   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2917     {
2918       if((const MEDFileUMeshSplitL1 *)(*it))
2919         {
2920           const DataArrayInt *da=(*it)->getFamilyField();
2921           if(da)
2922             {
2923               int val=da->getMinValue(tmp);
2924               ret=std::min(ret,val);
2925             }
2926         }
2927     }
2928   return ret;
2929 }
2930
2931 /*!
2932  * Returns the dimension on cells in \a this mesh.
2933  *  \return int - the mesh dimension.
2934  *  \throw If there are no cells in this mesh.
2935  */
2936 int MEDFileUMesh::getMeshDimension() const
2937 {
2938   int lev=0;
2939   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev++)
2940     if((const MEDFileUMeshSplitL1 *)(*it)!=0)
2941       return (*it)->getMeshDimension()+lev;
2942   throw INTERP_KERNEL::Exception("MEDFileUMesh::getMeshDimension : impossible to find a mesh dimension !");
2943 }
2944
2945 /*!
2946  * Returns the space dimension of \a this mesh that is equal to number of components in
2947  * the node coordinates array.
2948  *  \return int - the space dimension of \a this mesh.
2949  *  \throw If the node coordinates array is not available.
2950  */
2951 int MEDFileUMesh::getSpaceDimension() const
2952 {
2953   const DataArrayDouble *coo=_coords;
2954   if(!coo)
2955     throw INTERP_KERNEL::Exception(" MEDFileUMesh::getSpaceDimension : no coords set !");
2956   return coo->getNumberOfComponents();
2957 }
2958
2959 /*!
2960  * Returns a string describing \a this mesh.
2961  *  \return std::string - the mesh information string.
2962  */
2963 std::string MEDFileUMesh::simpleRepr() const
2964 {
2965   std::ostringstream oss;
2966   oss << MEDFileMesh::simpleRepr();
2967   const DataArrayDouble *coo=_coords;
2968   oss << "- The dimension of the space is ";
2969   static const char MSG1[]= "*** NO COORDS SET ***";
2970   static const char MSG2[]= "*** NO CONNECTIVITY SET FOR THIS LEVEL***";
2971   if(coo)
2972     oss << _coords->getNumberOfComponents() << std::endl;
2973   else
2974     oss << MSG1 << std::endl;
2975   oss << "- Type of the mesh : UNSTRUCTURED\n";
2976   oss << "- Number of nodes : ";
2977   if(coo)
2978     oss << _coords->getNumberOfTuples() << std::endl;
2979   else
2980     oss << MSG1 << std::endl;
2981   std::size_t nbOfLev=_ms.size();
2982   oss << "- Number of levels allocated : " << nbOfLev << std::endl;
2983   for(std::size_t i=0;i<nbOfLev;i++)
2984     {
2985       const MEDFileUMeshSplitL1 *lev=_ms[i];
2986       oss << "  - Level #" << -((int) i) << " has dimension : ";
2987       if(lev)
2988         {
2989           oss << lev->getMeshDimension() << std::endl;
2990           lev->simpleRepr(oss);
2991         }
2992       else
2993         oss << MSG2 << std::endl;
2994     }
2995   oss << "- Number of families : " << _families.size() << std::endl << std::endl;
2996   if(coo)
2997     {
2998       oss << "(***********************)\n(* NODES OF THE MESH : *)\n(***********************)\n";
2999       oss << "- Names of coordinates :" << std::endl;
3000       std::vector<std::string> vars=coo->getVarsOnComponent();
3001       std::copy(vars.begin(),vars.end(),std::ostream_iterator<std::string>(oss," "));
3002       oss << std::endl << "- Units of coordinates : " << std::endl;
3003       std::vector<std::string> units=coo->getUnitsOnComponent();
3004       std::copy(units.begin(),units.end(),std::ostream_iterator<std::string>(oss," "));
3005     }
3006   oss << std::endl << std::endl;
3007   getFamilyRepr(oss);
3008   getEquivalencesRepr(oss);
3009   return oss.str();
3010 }
3011
3012 /*!
3013  * Returns a full textual description of \a this mesh.
3014  *  \return std::string - the string holding the mesh description.
3015  */
3016 std::string MEDFileUMesh::advancedRepr() const
3017 {
3018   return simpleRepr();
3019 }
3020
3021 /*!
3022  * Returns number of mesh entities of a given relative dimension in \a this mesh.
3023  *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
3024  *  \return int - the number of entities.
3025  *  \throw If no mesh entities of dimension \a meshDimRelToMaxExt are available in \a this mesh.
3026  */
3027 int MEDFileUMesh::getSizeAtLevel(int meshDimRelToMaxExt) const
3028 {
3029   if(meshDimRelToMaxExt==1)
3030     {
3031       if(!((const DataArrayDouble *)_coords))
3032         throw INTERP_KERNEL::Exception("MEDFileUMesh::getSizeAtLevel : no coordinates specified !");
3033       return _coords->getNumberOfTuples();
3034     }
3035   return getMeshAtLevSafe(meshDimRelToMaxExt)->getSize();
3036 }
3037
3038 /*!
3039  * Returns the family field for mesh entities of a given dimension.
3040  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
3041  *  \return const DataArrayInt * - the family field. It is an array of ids of families
3042  *          each mesh entity belongs to. It can be \c NULL.
3043  */
3044 const DataArrayInt *MEDFileUMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) const
3045 {
3046   if(meshDimRelToMaxExt==1)
3047     return _fam_coords;
3048   const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMaxExt));
3049   return l1->getFamilyField();
3050 }
3051
3052 DataArrayInt *MEDFileUMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt)
3053 {
3054   if(meshDimRelToMaxExt==1)
3055     return _fam_coords;
3056   MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMaxExt));
3057   return l1->getFamilyField();
3058 }
3059
3060 /*!
3061  * Returns the optional numbers of mesh entities of a given dimension.
3062  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
3063  *  \return const DataArrayInt * - the array of the entity numbers.
3064  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3065  */
3066 const DataArrayInt *MEDFileUMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) const
3067 {
3068   if(meshDimRelToMaxExt==1)
3069     return _num_coords;
3070   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3071   return l1->getNumberField();
3072 }
3073
3074 const DataArrayAsciiChar *MEDFileUMesh::getNameFieldAtLevel(int meshDimRelToMaxExt) const
3075 {
3076   if(meshDimRelToMaxExt==1)
3077     return _name_coords;
3078   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3079   return l1->getNameField();
3080 }
3081
3082 /*!
3083  * This method returns for a specified relative level \a meshDimRelToMaxExt the part effectively read (if the instance is the result of the read of a file).
3084  *
3085  * \param [in] meshDimRelToMaxExt - the extended relative level for which the part definition is requested.
3086  * \param [in] gt - The input geometric type for which the part definition is requested.
3087  * \return the part definition owned by \a this. So no need to deallocate the returned instance.
3088  */
3089 const PartDefinition *MEDFileUMesh::getPartDefAtLevel(int meshDimRelToMaxExt, INTERP_KERNEL::NormalizedCellType gt) const
3090 {
3091   if(meshDimRelToMaxExt==1)
3092     return _part_coords;
3093   const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMaxExt));
3094   return l1->getPartDef(gt);
3095 }
3096
3097 int MEDFileUMesh::getNumberOfNodes() const
3098 {
3099   const DataArrayDouble *coo(_coords);
3100   if(!coo)
3101     throw INTERP_KERNEL::Exception(" MEDFileUMesh::getNumberOfNodes : no coords set !");
3102   return coo->getNumberOfTuples();
3103 }
3104
3105 int MEDFileUMesh::getNumberOfCellsAtLevel(int meshDimRelToMaxExt) const
3106 {
3107   const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMaxExt));
3108   return l1->getNumberOfCells();
3109 }
3110
3111 bool MEDFileUMesh::hasImplicitPart() const
3112 {
3113   return false;
3114 }
3115
3116 int MEDFileUMesh::buildImplicitPartIfAny(INTERP_KERNEL::NormalizedCellType gt) const
3117 {
3118   throw INTERP_KERNEL::Exception("MEDFileUMesh::buildImplicitPartIfAny : unstructured meshes do not have implicit part !");
3119 }
3120
3121 void MEDFileUMesh::releaseImplicitPartIfAny() const
3122 {
3123 }
3124
3125 void MEDFileUMesh::whichAreNodesFetched(const MEDFileField1TSStructItem& st, const MEDFileFieldGlobsReal *globs, std::vector<bool>& nodesFetched) const
3126 {
3127   std::size_t sz(st.getNumberOfItems());
3128   for(std::size_t i=0;i<sz;i++)
3129     {
3130       INTERP_KERNEL::NormalizedCellType curGt(st[i].getGeo());
3131       const MEDCoupling1GTUMesh *m(getDirectUndergroundSingleGeoTypeMesh(curGt));
3132       if(st[i].getPflName().empty())
3133         m->computeNodeIdsAlg(nodesFetched);
3134       else
3135         {
3136           const DataArrayInt *arr(globs->getProfile(st[i].getPflName()));
3137           MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> m2(dynamic_cast<MEDCoupling1GTUMesh *>(m->buildPartOfMySelf(arr->begin(),arr->end(),true)));
3138           m2->computeNodeIdsAlg(nodesFetched);
3139         }
3140     }
3141 }
3142
3143 /*!
3144  * Returns the optional numbers of mesh entities of a given dimension transformed using
3145  * DataArrayInt::invertArrayN2O2O2N().
3146  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
3147  *  \return const DataArrayInt * - the array of the entity numbers transformed using
3148  *          DataArrayInt::invertArrayN2O2O2N().
3149  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3150  */
3151 const DataArrayInt *MEDFileUMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxExt) const
3152 {
3153   if(meshDimRelToMaxExt==1)
3154     {
3155       if(!((const DataArrayInt *)_num_coords))
3156         throw INTERP_KERNEL::Exception("MEDFileUMesh::getRevNumberFieldAtLevel : no coordinates renum specified !");
3157       return _rev_num_coords;
3158     }
3159   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3160   return l1->getRevNumberField();
3161 }
3162
3163 /*!
3164  * Returns a pointer to the node coordinates array of \a this mesh \b without
3165  * incrementing its reference counter, thus there is no need to decrRef() it by the caller.
3166  */
3167 DataArrayDouble *MEDFileUMesh::getCoords() const
3168 {
3169   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp(_coords);
3170   if((DataArrayDouble *)tmp)
3171     {
3172       return tmp;
3173     }
3174   return 0;
3175 }
3176
3177 /*!
3178  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in a given
3179  * group of \a this mesh. Only mesh entities of a given dimension are included in the
3180  * new mesh.
3181  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
3182  *  \param [in] grp - the name of the group whose mesh entities are included in the
3183  *          new mesh.
3184  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
3185  *          according to the optional numbers of entities, if available.
3186  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
3187  *          delete this mesh using decrRef() as it is no more needed.
3188  *  \throw If the name of a nonexistent group is specified.
3189  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3190  */
3191 MEDCouplingUMesh *MEDFileUMesh::getGroup(int meshDimRelToMaxExt, const std::string& grp, bool renum) const
3192 {
3193   synchronizeTinyInfoOnLeaves();
3194   std::vector<std::string> tmp(1);
3195   tmp[0]=grp;
3196   return getGroups(meshDimRelToMaxExt,tmp,renum);
3197 }
3198
3199 /*!
3200  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in given
3201  * groups of \a this mesh. Only mesh entities of a given dimension are included in the
3202  * new mesh.
3203  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
3204  *  \param [in] grps - a sequence of group names whose mesh entities are included in the
3205  *          new mesh.
3206  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
3207  *          according to the optional numbers of entities, if available.
3208  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
3209  *          delete this mesh using decrRef() as it is no more needed.
3210  *  \throw If a name of a nonexistent group is present in \a grps.
3211  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3212  */
3213 MEDCouplingUMesh *MEDFileUMesh::getGroups(int meshDimRelToMaxExt, const std::vector<std::string>& grps, bool renum) const
3214 {
3215   synchronizeTinyInfoOnLeaves();
3216   std::vector<std::string> fams2=getFamiliesOnGroups(grps);
3217   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> zeRet=getFamilies(meshDimRelToMaxExt,fams2,renum);
3218   if(grps.size()==1 && ((MEDCouplingUMesh *)zeRet))
3219     zeRet->setName(grps[0]);
3220   return zeRet.retn();
3221 }
3222
3223 /*!
3224  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in a given
3225  * family of \a this mesh. Only mesh entities of a given dimension are included in the
3226  * new mesh.
3227  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
3228  *  \param [in] fam - the name of the family whose mesh entities are included in the
3229  *          new mesh.
3230  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
3231  *          according to the optional numbers of entities, if available.
3232  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
3233  *          delete this mesh using decrRef() as it is no more needed.
3234  *  \throw If a name of a nonexistent family is present in \a grps.
3235  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3236  */
3237 MEDCouplingUMesh *MEDFileUMesh::getFamily(int meshDimRelToMaxExt, const std::string& fam, bool renum) const
3238 {
3239   synchronizeTinyInfoOnLeaves();
3240   std::vector<std::string> tmp(1);
3241   tmp[0]=fam;
3242   return getFamilies(meshDimRelToMaxExt,tmp,renum);
3243 }
3244
3245 /*!
3246  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in given
3247  * families of \a this mesh. Only mesh entities of a given dimension are included in the
3248  * new mesh.
3249  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
3250  *  \param [in] fams - a sequence of family names whose mesh entities are included in the
3251  *          new mesh.
3252  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
3253  *          according to the optional numbers of entities, if available.
3254  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
3255  *          delete this mesh using decrRef() as it is no more needed.
3256  *  \throw If a name of a nonexistent family is present in \a fams.
3257  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3258  */
3259 MEDCouplingUMesh *MEDFileUMesh::getFamilies(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const
3260 {
3261   synchronizeTinyInfoOnLeaves();
3262   if(meshDimRelToMaxExt==1)
3263     {
3264       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr=getFamiliesArr(1,fams,renum);
3265       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3266       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> c=_coords->selectByTupleId(arr->getConstPointer(),arr->getConstPointer()+arr->getNbOfElems());
3267       ret->setCoords(c);
3268       return ret.retn();
3269     }
3270   std::vector<int> famIds=getFamiliesIds(fams);
3271   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3272   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> zeRet;
3273   if(!famIds.empty())
3274     zeRet=l1->getFamilyPart(&famIds[0],&famIds[0]+famIds.size(),renum);
3275   else
3276     zeRet=l1->getFamilyPart(0,0,renum);
3277   if(fams.size()==1 && ((MEDCouplingUMesh *)zeRet))
3278     zeRet->setName(fams[0]);
3279   return zeRet.retn();
3280 }
3281
3282 /*!
3283  * Returns ids of mesh entities contained in given families of a given dimension.
3284  *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
3285  *          are required.
3286  *  \param [in] fams - the names of the families of interest.
3287  *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
3288  *          returned instead of ids.
3289  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
3290  *          numbers, if available and required, of mesh entities of the families. The caller
3291  *          is to delete this array using decrRef() as it is no more needed. 
3292  *  \throw If the family field is missing for \a meshDimRelToMaxExt.
3293  */
3294 DataArrayInt *MEDFileUMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const
3295 {
3296   std::vector<int> famIds=getFamiliesIds(fams);
3297   if(meshDimRelToMaxExt==1)
3298     {
3299       if((const DataArrayInt *)_fam_coords)
3300         {
3301           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
3302           if(!famIds.empty())
3303             da=_fam_coords->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
3304           else
3305             da=_fam_coords->getIdsEqualList(0,0);
3306           if(renum)
3307             return MEDFileUMeshSplitL1::Renumber(_num_coords,da);
3308           else
3309             return da.retn();
3310         }
3311       else
3312         throw INTERP_KERNEL::Exception("MEDFileUMesh::getFamiliesArr : no family array specified on nodes !");
3313     }
3314   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3315   if(!famIds.empty())
3316     return l1->getFamilyPartArr(&famIds[0],&famIds[0]+famIds.size(),renum);
3317   else
3318     return l1->getFamilyPartArr(0,0,renum);
3319 }
3320
3321 /*!
3322  * Returns a MEDCouplingUMesh of a given relative dimension.
3323  * \warning If \a meshDimRelToMaxExt == 1 (which means nodes), the returned mesh **is not
3324  * valid**. This is a feature, because MEDLoader does not create cells that do not exist! 
3325  * To build a valid MEDCouplingUMesh from the returned one in this case,
3326  * call MEDCouplingUMesh::Build0DMeshFromCoords().
3327  *  \param [in] meshDimRelToMax - the relative dimension of interest.
3328  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3329  *          optional numbers of mesh entities.
3330  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
3331  *          delete using decrRef() as it is no more needed. 
3332  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3333  * \sa getGenMeshAtLevel()
3334  */
3335 MEDCouplingUMesh *MEDFileUMesh::getMeshAtLevel(int meshDimRelToMaxExt, bool renum) const
3336 {
3337   synchronizeTinyInfoOnLeaves();
3338   if(meshDimRelToMaxExt==1)
3339     {
3340       if(!renum)
3341         {
3342           MEDCouplingUMesh *umesh=MEDCouplingUMesh::New();
3343           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> cc=_coords->deepCpy();
3344           umesh->setCoords(cc);
3345           MEDFileUMeshSplitL1::ClearNonDiscrAttributes(umesh);
3346           umesh->setName(getName());
3347           return umesh;
3348         }
3349     }
3350   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3351   return l1->getWholeMesh(renum);
3352 }
3353
3354 /*!
3355  * Returns a MEDCouplingUMesh of a given relative dimension.
3356  * \warning If \a meshDimRelToMaxExt == 1 (which means nodes), the returned mesh **is not
3357  * valid**. This is a feature, because MEDLoader does not create cells that do not exist! 
3358  * To build a valid MEDCouplingUMesh from the returned one in this case,
3359  * call MEDCouplingUMesh::Build0DMeshFromCoords().
3360  *  \param [in] meshDimRelToMax - the relative dimension of interest.
3361  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3362  *          optional numbers of mesh entities.
3363  *  \return MEDCouplingMesh * - a pointer to MEDCouplingUMesh that the caller is to
3364  *          delete using decrRef() as it is no more needed. 
3365  *  \throw If there are no mesh entities of \a meshDimRelToMax dimension in \a this mesh.
3366  * \sa getMeshAtLevel()
3367  */
3368 MEDCouplingMesh *MEDFileUMesh::getGenMeshAtLevel(int meshDimRelToMax, bool renum) const
3369 {
3370   return getMeshAtLevel(meshDimRelToMax,renum);
3371 }
3372
3373 std::vector<int> MEDFileUMesh::getDistributionOfTypes(int meshDimRelToMax) const
3374 {
3375   const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMax));
3376   return l1->getDistributionOfTypes();
3377 }
3378
3379 /*!
3380  * Returns a MEDCouplingUMesh of a relative dimension == 0.
3381  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3382  *          optional numbers of mesh entities.
3383  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
3384  *          delete using decrRef() as it is no more needed. 
3385  *  \throw If there are no mesh entities of the relative dimension == 0 in \a this mesh.
3386  */
3387 MEDCouplingUMesh *MEDFileUMesh::getLevel0Mesh(bool renum) const
3388 {
3389   return getMeshAtLevel(0,renum);
3390 }
3391
3392 /*!
3393  * Returns a MEDCouplingUMesh of a relative dimension == -1.
3394  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3395  *          optional numbers of mesh entities.
3396  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
3397  *          delete using decrRef() as it is no more needed. 
3398  *  \throw If there are no mesh entities of the relative dimension == -1 in \a this mesh.
3399  */
3400 MEDCouplingUMesh *MEDFileUMesh::getLevelM1Mesh(bool renum) const
3401 {
3402   return getMeshAtLevel(-1,renum);
3403 }
3404
3405 /*!
3406  * Returns a MEDCouplingUMesh of a relative dimension == -2.
3407  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3408  *          optional numbers of mesh entities.
3409  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
3410  *          delete using decrRef() as it is no more needed. 
3411  *  \throw If there are no mesh entities of the relative dimension == -2 in \a this mesh.
3412  */
3413 MEDCouplingUMesh *MEDFileUMesh::getLevelM2Mesh(bool renum) const
3414 {
3415   return getMeshAtLevel(-2,renum);
3416 }
3417
3418 /*!
3419  * Returns a MEDCouplingUMesh of a relative dimension == -3.
3420  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3421  *          optional numbers of mesh entities.
3422  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
3423  *          delete using decrRef() as it is no more needed. 
3424  *  \throw If there are no mesh entities of the relative dimension == -3 in \a this mesh.
3425  */
3426 MEDCouplingUMesh *MEDFileUMesh::getLevelM3Mesh(bool renum) const
3427 {
3428   return getMeshAtLevel(-3,renum);
3429 }
3430
3431 /*!
3432  * This method is for advanced users. There is two storing strategy of mesh in \a this.
3433  * Either MEDCouplingUMesh, or vector of MEDCoupling1GTUMesh instances.
3434  * When assignement is done the first one is done, which is not optimal in write mode for MED file.
3435  * This method allows to switch from MEDCouplingUMesh mode to MEDCoupling1GTUMesh mode.
3436  */
3437 void MEDFileUMesh::forceComputationOfParts() const
3438 {
3439   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
3440     {
3441       const MEDFileUMeshSplitL1 *elt(*it);
3442       if(elt)
3443         elt->forceComputationOfParts();
3444     }
3445 }
3446
3447 /*!
3448  * This method returns a vector of mesh parts containing each exactly one geometric type.
3449  * This method will never launch an automatic computation of split by type (an INTERP_KERNEL::Exception will be then thrown).
3450  * This method is only for memory aware users.
3451  * The returned pointers are **NOT** new object pointer. No need to mange them.
3452  */
3453 std::vector<MEDCoupling1GTUMesh *> MEDFileUMesh::getDirectUndergroundSingleGeoTypeMeshes(int meshDimRelToMax) const
3454 {
3455   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(meshDimRelToMax));
3456   return sp->getDirectUndergroundSingleGeoTypeMeshes();
3457 }
3458
3459 /*!
3460  * This method returns the part of \a this having the geometric type \a gt.
3461  * If such part is not existing an exception will be thrown.
3462  * The returned pointer is **NOT** new object pointer. No need to mange it.
3463  */
3464 MEDCoupling1GTUMesh *MEDFileUMesh::getDirectUndergroundSingleGeoTypeMesh(INTERP_KERNEL::NormalizedCellType gt) const
3465 {
3466   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
3467   int lev=(int)cm.getDimension()-getMeshDimension();
3468   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(lev));
3469   return sp->getDirectUndergroundSingleGeoTypeMesh(gt);
3470 }
3471
3472 /*!
3473  * Given a relative level \a meshDimRelToMax it returns the sorted vector of geometric types present in \a this.
3474  * \throw if the reqsuested \a meshDimRelToMax does not exist.
3475  */
3476 std::vector<INTERP_KERNEL::NormalizedCellType> MEDFileUMesh::getGeoTypesAtLevel(int meshDimRelToMax) const
3477 {
3478   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(meshDimRelToMax));
3479   return sp->getGeoTypes();
3480 }
3481
3482 int MEDFileUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType ct) const
3483 {
3484   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(ct);
3485   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe( ((int)cm.getDimension())-getMeshDimension() ));
3486   return sp->getNumberOfCellsWithType(ct);
3487 }
3488
3489 /*!
3490  * This method extracts from whole family field ids the part relative to the input parameter \a gt.
3491  * \param [in] gt - the geometric type for which the family field is asked.
3492  * \return DataArrayInt * - a pointer to DataArrayInt that the caller is to
3493  *          delete using decrRef() as it is no more needed.
3494  * \sa MEDFileUMesh::extractNumberFieldOnGeoType
3495  */
3496 DataArrayInt *MEDFileUMesh::extractFamilyFieldOnGeoType(INTERP_KERNEL::NormalizedCellType gt) const
3497 {
3498   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
3499   int lev=(int)cm.getDimension()-getMeshDimension();
3500   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(lev));
3501   return sp->extractFamilyFieldOnGeoType(gt);
3502 }
3503
3504 /*!
3505  * This method extracts from whole number field ids the part relative to the input parameter \a gt.
3506  * \param [in] gt - the geometric type for which the number field is asked.
3507  * \return DataArrayInt * - a pointer to DataArrayInt that the caller is to
3508  *          delete using decrRef() as it is no more needed.
3509  * \sa MEDFileUMesh::extractFamilyFieldOnGeoType
3510  */
3511 DataArrayInt *MEDFileUMesh::extractNumberFieldOnGeoType(INTERP_KERNEL::NormalizedCellType gt) const
3512 {
3513   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
3514   int lev=(int)cm.getDimension()-getMeshDimension();
3515   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(lev));
3516   return sp->extractNumberFieldOnGeoType(gt);
3517 }
3518
3519 /*!
3520  * This method returns for specified geometric type \a gt the relative level to \a this.
3521  * If the relative level is empty an exception will be thrown.
3522  */
3523 int MEDFileUMesh::getRelativeLevOnGeoType(INTERP_KERNEL::NormalizedCellType gt) const
3524 {
3525   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
3526   int ret((int)cm.getDimension()-getMeshDimension());
3527   getMeshAtLevSafe(ret);//To test that returned value corresponds to a valid level.
3528   return ret;
3529 }
3530
3531 const MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt) const
3532 {
3533   if(meshDimRelToMaxExt==1)
3534     throw INTERP_KERNEL::Exception("Dimension request is invalid : asking for node level (1) !");
3535   if(meshDimRelToMaxExt>1)
3536     throw INTERP_KERNEL::Exception("Dimension request is invalid (>1) !");
3537   int tracucedRk=-meshDimRelToMaxExt;
3538   if(tracucedRk>=(int)_ms.size())
3539     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
3540   if((const MEDFileUMeshSplitL1 *)_ms[tracucedRk]==0)
3541     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3542   return _ms[tracucedRk];
3543 }
3544
3545 MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt)
3546 {
3547   if(meshDimRelToMaxExt==1)
3548     throw INTERP_KERNEL::Exception("Dimension request is invalid : asking for node level (1) !");
3549   if(meshDimRelToMaxExt>1)
3550     throw INTERP_KERNEL::Exception("Dimension request is invalid (>1) !");
3551   int tracucedRk=-meshDimRelToMaxExt;
3552   if(tracucedRk>=(int)_ms.size())
3553     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
3554   if((const MEDFileUMeshSplitL1 *)_ms[tracucedRk]==0)
3555     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3556   return _ms[tracucedRk];
3557 }
3558
3559 void MEDFileUMesh::checkMeshDimCoherency(int meshDim, int meshDimRelToMax) const
3560 {
3561   if(-meshDimRelToMax>=(int)_ms.size())
3562     throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMeshDimCoherency : The meshdim of mesh is not managed by 'this' !");
3563   int i=0;
3564   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,i++)
3565     {
3566       if(((const MEDFileUMeshSplitL1*) (*it))!=0)
3567         {
3568           int ref=(*it)->getMeshDimension();
3569           if(ref+i!=meshDim-meshDimRelToMax)
3570             throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMeshDimCoherency : no coherency between levels !");
3571         }
3572     }
3573 }
3574
3575 /*!
3576  * Sets the node coordinates array of \a this mesh.
3577  *  \param [in] coords - the new node coordinates array.
3578  *  \throw If \a coords == \c NULL.
3579  */
3580 void MEDFileUMesh::setCoords(DataArrayDouble *coords)
3581 {
3582   if(!coords)
3583     throw INTERP_KERNEL::Exception("MEDFileUMesh::setCoords : null pointer in input !");
3584   coords->checkAllocated();
3585   int nbOfTuples=coords->getNumberOfTuples();
3586   _coords=coords;
3587   coords->incrRef();
3588   _fam_coords=DataArrayInt::New();
3589   _fam_coords->alloc(nbOfTuples,1);
3590   _fam_coords->fillWithZero();
3591   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
3592     if((MEDFileUMeshSplitL1 *)(*it))
3593       (*it)->setCoords(coords);
3594 }
3595
3596 /*!
3597  * Removes all groups of a given dimension in \a this mesh.
3598  *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
3599  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3600  */
3601 void MEDFileUMesh::eraseGroupsAtLevel(int meshDimRelToMaxExt)
3602 {
3603   if(meshDimRelToMaxExt==1)
3604     {
3605       if((DataArrayInt *)_fam_coords)
3606         _fam_coords->fillWithZero();
3607       return ;
3608     }
3609   MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3610   l1->eraseFamilyField();
3611   optimizeFamilies();
3612 }
3613
3614 /*!
3615  * Removes all families with ids not present in the family fields of \a this mesh.
3616  */
3617 void MEDFileUMesh::optimizeFamilies()
3618 {
3619   std::vector<int> levs=getNonEmptyLevelsExt();
3620   std::set<int> allFamsIds;
3621   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
3622     {
3623       const DataArrayInt *ffield=getFamilyFieldAtLevel(*it);
3624       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=ffield->getDifferentValues();
3625       std::set<int> res;
3626       std::set_union(ids->begin(),ids->end(),allFamsIds.begin(),allFamsIds.end(),std::inserter(res,res.begin()));
3627       allFamsIds=res;
3628     }
3629   std::set<std::string> famNamesToKill;
3630   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
3631     {
3632       if(allFamsIds.find((*it).second)!=allFamsIds.end())
3633         famNamesToKill.insert((*it).first);
3634     }
3635   for(std::set<std::string>::const_iterator it=famNamesToKill.begin();it!=famNamesToKill.end();it++)
3636     _families.erase(*it);
3637   std::vector<std::string> grpNamesToKill;
3638   for(std::map<std::string, std::vector<std::string> >::iterator it=_groups.begin();it!=_groups.end();it++)
3639     {
3640       std::vector<std::string> tmp;
3641       for(std::vector<std::string>::const_iterator it2=(*it).second.begin();it2!=(*it).second.end();it2++)
3642         {
3643           if(famNamesToKill.find(*it2)==famNamesToKill.end())
3644             tmp.push_back(*it2);
3645         }
3646       if(!tmp.empty())
3647         (*it).second=tmp;
3648       else
3649         tmp.push_back((*it).first);
3650     }
3651   for(std::vector<std::string>::const_iterator it=grpNamesToKill.begin();it!=grpNamesToKill.end();it++)
3652     _groups.erase(*it);
3653 }
3654
3655 /**
3656  * \b this must be filled at level 0 and -1, typically the -1 level being (part of) the descending connectivity
3657  * of the top level. This method build a "crack", or an inner boundary, in \b this along the group of level -1 named grpNameM1.
3658  * The boundary is built according to the following method:
3659  *  - all nodes along the boundary which are not lying on an internal extremity of the (-1)-level group are duplicated (so the
3660  * coordinates array is extended).
3661  *  - new (-1)-level cells are built lying on those new nodes. So the edges/faces along the group are duplicated.
3662  *  After this operation a top-level cell bordering the group will loose some neighbors (typically the cell which is  on the
3663  *  other side of the group is no more a neighbor)
3664  *   - finally, the connectivity of (part of) the top level-cells bordering the group is also modified so that some cells
3665  *  bordering the newly created boundary use the newly computed nodes.
3666  *
3667  *  \param[in] grpNameM1 name of the (-1)-level group defining the boundary
3668  *  \param[out] nodesDuplicated ids of the initial nodes which have been duplicated (and whose copy is put at the end of
3669  *  the coord array)
3670  *  \param[out] cellsModified ids of the cells whose connectivity has been modified (to use the newly created nodes)
3671  *  \param[out] cellsNotModified ids of the rest of cells bordering the new boundary whose connectivity remains unchanged.
3672  */
3673 void MEDFileUMesh::buildInnerBoundaryAlongM1Group(const std::string& grpNameM1, DataArrayInt *&nodesDuplicated,
3674                                            DataArrayInt *&cellsModified, DataArrayInt *&cellsNotModified)
3675 {
3676   std::vector<int> levs=getNonEmptyLevels();
3677   if(std::find(levs.begin(),levs.end(),0)==levs.end() || std::find(levs.begin(),levs.end(),-1)==levs.end())
3678     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildInnerBoundaryAlongM1Group : This method works only for mesh definied on level 0 and -1 !");
3679   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0=getMeshAtLevel(0);
3680   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1=getMeshAtLevel(-1);
3681   int nbNodes=m0->getNumberOfNodes();
3682   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m11=getGroup(-1,grpNameM1);
3683   DataArrayInt *tmp00=0,*tmp11=0,*tmp22=0;
3684   m0->findNodesToDuplicate(*m11,tmp00,tmp11,tmp22);
3685   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodeIdsToDuplicate(tmp00);
3686   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0(tmp11);
3687   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1(tmp22);
3688   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp0=static_cast<MEDCouplingUMesh *>(m0->buildPartOfMySelf(cellsToModifyConn0->begin(),cellsToModifyConn0->end(),true));
3689   // node renumbering of cells in m1 impacted by duplication of node but not in group 'grpNameM1' on level -1
3690   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descTmp0=DataArrayInt::New(),descITmp0=DataArrayInt::New(),revDescTmp0=DataArrayInt::New(),revDescITmp0=DataArrayInt::New();
3691   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp0Desc=tmp0->buildDescendingConnectivity(descTmp0,descITmp0,revDescTmp0,revDescITmp0);
3692   descTmp0=0; descITmp0=0; revDescTmp0=0; revDescITmp0=0;
3693   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsInM1ToRenumW2=tmp0Desc->getCellIdsLyingOnNodes(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),false);
3694   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cellsInM1ToRenumW3=static_cast<MEDCouplingUMesh *>(tmp0Desc->buildPartOfMySelf(cellsInM1ToRenumW2->begin(),cellsInM1ToRenumW2->end(),true));
3695   DataArrayInt *cellsInM1ToRenumW4Tmp=0;
3696   m1->areCellsIncludedIn(cellsInM1ToRenumW3,2,cellsInM1ToRenumW4Tmp);
3697   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsInM1ToRenumW4(cellsInM1ToRenumW4Tmp);
3698   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsInM1ToRenumW5=cellsInM1ToRenumW4->getIdsInRange(0,m1->getNumberOfCells());
3699   cellsInM1ToRenumW5->transformWithIndArr(cellsInM1ToRenumW4->begin(),cellsInM1ToRenumW4->end());
3700   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> grpIds=getGroupArr(-1,grpNameM1);
3701   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsInM1ToRenum=cellsInM1ToRenumW5->buildSubstraction(grpIds);
3702   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Part=static_cast<MEDCouplingUMesh *>(m1->buildPartOfMySelf(cellsInM1ToRenum->begin(),cellsInM1ToRenum->end(),true));
3703   m1Part->duplicateNodesInConn(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),nbNodes);
3704   m1->setPartOfMySelf(cellsInM1ToRenum->begin(),cellsInM1ToRenum->end(),*m1Part);
3705   // end of node renumbering of cells in m1 impacted by duplication of node but not in group of level -1 'grpNameM1'
3706   tmp0->duplicateNodes(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end());
3707   m0->setCoords(tmp0->getCoords());
3708   m0->setPartOfMySelf(cellsToModifyConn0->begin(),cellsToModifyConn0->end(),*tmp0);
3709   m1->setCoords(m0->getCoords());
3710   _coords=m0->getCoords(); _coords->incrRef();
3711   // duplication of cells in group 'grpNameM1' on level -1
3712   m11->duplicateNodesInConn(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),nbNodes); m11->setCoords(m0->getCoords());
3713   std::vector<const MEDCouplingUMesh *> v(2); v[0]=m1; v[1]=m11;
3714   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> newm1=MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(v,tmp00,tmp11);
3715   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> szOfCellGrpOfSameType(tmp00);
3716   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idInMsOfCellGrpOfSameType(tmp11);
3717   //
3718   newm1->setName(getName());
3719   const DataArrayInt *fam=getFamilyFieldAtLevel(-1);
3720   if(!fam)
3721     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildInnerBoundaryAlongM1Group : internal problem !");
3722   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newFam=DataArrayInt::New();
3723   newFam->alloc(newm1->getNumberOfCells(),1);
3724   // Get a new family ID: care must be taken if we need a positive ID or a negative one:
3725   // Positive ID for family of nodes, negative for all the rest.
3726   int idd;
3727   if (m1->getMeshDimension() == 0)
3728     idd=getMaxFamilyId()+1;
3729   else
3730     idd=getMinFamilyId()-1;
3731   int globStart=0,start=0,end,globEnd;
3732   int nbOfChunks=szOfCellGrpOfSameType->getNumberOfTuples();
3733   for(int i=0;i<nbOfChunks;i++)
3734     {
3735       globEnd=globStart+szOfCellGrpOfSameType->getIJ(i,0);
3736       if(idInMsOfCellGrpOfSameType->getIJ(i,0)==0)
3737         {
3738           end=start+szOfCellGrpOfSameType->getIJ(i,0);
3739           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=fam->selectByTupleId2(start,end,1);
3740           newFam->setPartOfValues1(part,globStart,globEnd,1,0,1,1,true);
3741           start=end;
3742         }
3743       else
3744         {
3745           newFam->setPartOfValuesSimple1(idd,globStart,globEnd,1,0,1,1);
3746         }
3747       globStart=globEnd;
3748     }
3749   newm1->setCoords(getCoords());
3750   setMeshAtLevel(-1,newm1);
3751   setFamilyFieldArr(-1,newFam);
3752   std::string grpName2(grpNameM1); grpName2+="_dup";
3753   addFamily(grpName2,idd);
3754   addFamilyOnGrp(grpName2,grpName2);
3755   //
3756   fam=_fam_coords;
3757   if(fam)
3758     {
3759       int newNbOfNodes=getCoords()->getNumberOfTuples();
3760       newFam=DataArrayInt::New(); newFam->alloc(newNbOfNodes,1);
3761       newFam->setPartOfValues1(fam,0,nbNodes,1,0,1,1,true);
3762       newFam->setPartOfValuesSimple1(0,nbNodes,newNbOfNodes,1,0,1,1);
3763       _fam_coords=newFam;
3764     }
3765   nodesDuplicated=nodeIdsToDuplicate.retn();
3766   cellsModified=cellsToModifyConn0.retn();
3767   cellsNotModified=cellsToModifyConn1.retn();
3768 }
3769
3770 /*!
3771  * \param [out] oldCode retrieves the distribution of types before the call if true is returned
3772  * \param [out] newCode etrieves the distribution of types after the call if true is returned
3773  * \param [out] o2nRenumCell tells for **all levels** the old 2 new renumbering of cells.
3774  * 
3775  * \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.
3776  * 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.
3777  */
3778 bool MEDFileUMesh::unPolyze(std::vector<int>& oldCode, std::vector<int>& newCode, DataArrayInt *& o2nRenumCell)
3779 {
3780   o2nRenumCell=0; oldCode.clear(); newCode.clear();
3781   std::vector<int> levs=getNonEmptyLevels();
3782   bool ret=false;
3783   std::vector< const DataArrayInt* > renumCellsSplited;//same than memorySaverIfThrow
3784   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > memorySaverIfThrow;//same than renumCellsSplited only in case of throw
3785   int start=0;
3786   int end=0;
3787   for(std::vector<int>::reverse_iterator it=levs.rbegin();it!=levs.rend();it++)
3788     {
3789       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=getMeshAtLevel(*it);
3790       std::vector<int> code1=m->getDistributionOfTypes();
3791       end=PutInThirdComponentOfCodeOffset(code1,start);
3792       oldCode.insert(oldCode.end(),code1.begin(),code1.end());
3793       bool hasChanged=m->unPolyze();
3794       DataArrayInt *fake=0;
3795       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nCellsPart=m->getLevArrPerCellTypes(MEDCouplingUMesh::MEDMEM_ORDER,
3796           MEDCouplingUMesh::MEDMEM_ORDER+MEDCouplingUMesh::N_MEDMEM_ORDER,fake);
3797       fake->decrRef();
3798       renumCellsSplited.push_back(o2nCellsPart); memorySaverIfThrow.push_back(o2nCellsPart);
3799       if(hasChanged)
3800         {
3801           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nCellsPart2=o2nCellsPart->buildPermArrPerLevel();
3802           m->renumberCells(o2nCellsPart2->getConstPointer(),false);
3803           ret=true;
3804           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famField2,numField2;
3805           const DataArrayInt *famField=getFamilyFieldAtLevel(*it); if(famField) { famField->incrRef(); famField2=const_cast<DataArrayInt *>(famField); }
3806           const DataArrayInt *numField=getNumberFieldAtLevel(*it); if(numField) { numField->incrRef(); numField2=const_cast<DataArrayInt *>(numField); }
3807           setMeshAtLevel(*it,m);
3808           std::vector<int> code2=m->getDistributionOfTypes();
3809           end=PutInThirdComponentOfCodeOffset(code2,start);
3810           newCode.insert(newCode.end(),code2.begin(),code2.end());
3811           //
3812           if(o2nCellsPart2->isIdentity())
3813             continue;
3814           if(famField)
3815             {
3816               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newFamField=famField->renumber(o2nCellsPart2->getConstPointer());
3817               setFamilyFieldArr(*it,newFamField);
3818             }
3819           if(numField)
3820             {
3821               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newNumField=numField->renumber(o2nCellsPart2->getConstPointer());
3822               setRenumFieldArr(*it,newNumField);
3823             }
3824         }
3825       else
3826         {
3827           newCode.insert(newCode.end(),code1.begin(),code1.end());
3828         }
3829       start=end;
3830     }
3831   if(ret)
3832     {
3833       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renumCells=DataArrayInt::Aggregate(renumCellsSplited);
3834       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRenumCellRet=renumCells->buildPermArrPerLevel();
3835       o2nRenumCell=o2nRenumCellRet.retn();
3836     }
3837   return ret;
3838 }
3839
3840 /*! \cond HIDDEN_ITEMS */
3841 struct MEDLoaderAccVisit1
3842 {
3843   MEDLoaderAccVisit1():_new_nb_of_nodes(0) { }
3844   int operator()(bool val) { return val?_new_nb_of_nodes++:-1; }
3845   int _new_nb_of_nodes;
3846 };
3847 /*! \endcond */
3848
3849 /*!
3850  * 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.
3851  * The maximum value stored in returned array is the number of nodes of \a this minus 1 after call of this method.
3852  * The size of returned array is the number of nodes of the old (previous to the call of this method) number of nodes.
3853  * -1 values in returned array means that the corresponding old node is no more used.
3854  *
3855  * \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
3856  *         is modified in \a this.
3857  * \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
3858  *  set coordinates.
3859  */
3860 DataArrayInt *MEDFileUMesh::zipCoords()
3861 {
3862   const DataArrayDouble *coo(getCoords());
3863   if(!coo)
3864     throw INTERP_KERNEL::Exception("MEDFileUMesh::zipCoords : no coordinates set in this !");
3865   int nbOfNodes(coo->getNumberOfTuples());
3866   std::vector<bool> nodeIdsInUse(nbOfNodes,false);
3867   std::vector<int> neLevs(getNonEmptyLevels());
3868   for(std::vector<int>::const_iterator lev=neLevs.begin();lev!=neLevs.end();lev++)
3869     {
3870       const MEDFileUMeshSplitL1 *zeLev(getMeshAtLevSafe(*lev));
3871       if(zeLev->isMeshStoredSplitByType())
3872         {
3873           std::vector<MEDCoupling1GTUMesh *> ms(zeLev->getDirectUndergroundSingleGeoTypeMeshes());
3874           for(std::vector<MEDCoupling1GTUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
3875             if(*it)
3876               (*it)->computeNodeIdsAlg(nodeIdsInUse);
3877         }
3878       else
3879         {
3880           MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh(zeLev->getWholeMesh(false));
3881           mesh->computeNodeIdsAlg(nodeIdsInUse);
3882         }
3883     }
3884   int nbrOfNodesInUse((int)std::count(nodeIdsInUse.begin(),nodeIdsInUse.end(),true));
3885   if(nbrOfNodesInUse==nbOfNodes)
3886     return 0;//no need to update _part_coords
3887   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodes,1);
3888   std::transform(nodeIdsInUse.begin(),nodeIdsInUse.end(),ret->getPointer(),MEDLoaderAccVisit1());
3889   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(ret->invertArrayO2N2N2OBis(nbrOfNodesInUse));
3890   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(coo->selectByTupleIdSafe(ret2->begin(),ret2->end()));
3891   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newFamCoords;
3892   MEDCouplingAutoRefCountObjectPtr<DataArrayAsciiChar> newNameCoords;
3893   if((const DataArrayInt *)_fam_coords)
3894     newFamCoords=_fam_coords->selectByTupleIdSafe(ret2->begin(),ret2->end());
3895   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newNumCoords;
3896   if((const DataArrayInt *)_num_coords)
3897     newNumCoords=_num_coords->selectByTupleIdSafe(ret2->begin(),ret2->end());
3898   if((const DataArrayAsciiChar *)_name_coords)
3899     newNameCoords=static_cast<DataArrayAsciiChar *>(_name_coords->selectByTupleIdSafe(ret2->begin(),ret2->end()));
3900   _coords=newCoords; _fam_coords=newFamCoords; _num_coords=newNumCoords; _name_coords=newNameCoords; _rev_num_coords=0;
3901   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
3902     {
3903       if((MEDFileUMeshSplitL1*)*it)
3904         {
3905           (*it)->renumberNodesInConn(ret->begin());
3906           (*it)->setCoords(_coords);
3907         }
3908     }
3909   // updates _part_coords
3910   const PartDefinition *pc(_part_coords);
3911   if(pc)
3912     {
3913       MEDCouplingAutoRefCountObjectPtr<PartDefinition> tmpPD(DataArrayPartDefinition::New(ret2));
3914       _part_coords=tmpPD->composeWith(pc);
3915     }
3916   return ret.retn();
3917 }
3918
3919 /*!
3920  * This method performs an extrusion along a path defined by \a m1D.
3921  * \a this is expected to be a mesh with max mesh dimension equal to 2.
3922  * \a m1D is expected to be a mesh with space dimesion equal to 3 and mesh dimension equal to 1.
3923  * Mesh dimensions of returned mesh is incremented by one compared to thoose in \a this.
3924  * This method scans all levels in \a this
3925  * and put them in the returned mesh. All groups in \a this are also put in the returned mesh.
3926  *
3927  * \param [in] m1D - the mesh defining the extrusion path.
3928  * \param [in] policy - defines the policy of extrusion (see MEDCouplingUMesh::buildExtrudedMesh for more details)
3929  * \return - a new reference on mesh (you have to deal with using decrRef). The returned mesh will have the same name than \a this.
3930  *
3931  * \sa MEDCouplingUMesh::buildExtrudedMesh
3932  */
3933 MEDFileUMesh *MEDFileUMesh::buildExtrudedMesh(const MEDCouplingUMesh *m1D, int policy) const
3934 {
3935   if(getMeshDimension()!=2)
3936     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildExtrudedMesh : this is expected to be with mesh dimension equal to 2 !");
3937   MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret(MEDFileUMesh::New());
3938   m1D->checkCoherency();
3939   if(m1D->getMeshDimension()!=1)
3940     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildExtrudedMesh : input mesh must have a mesh dimension equal to one !");
3941   int nbRep(m1D->getNumberOfCells());
3942   std::vector<int> levs(getNonEmptyLevels());
3943   std::vector<std::string> grps(getGroupsNames());
3944   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > zeList;
3945   DataArrayDouble *coords(0);
3946   std::size_t nbOfLevsOut(levs.size()+1);
3947   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > o2ns(nbOfLevsOut);
3948   for(std::vector<int>::const_iterator lev=levs.begin();lev!=levs.end();lev++)
3949     {
3950       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> item(getMeshAtLevel(*lev));
3951       item=item->clone(false);
3952       item->changeSpaceDimension(3+(*lev),0.);//no problem non const but change DataArrayDouble for coordinates do not alter data
3953       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp(static_cast<MEDCouplingUMesh *>(m1D->deepCpy()));
3954       tmp->changeSpaceDimension(3+(*lev),0.);
3955       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(item->buildExtrudedMesh(tmp,policy));
3956       zeList.push_back(elt);
3957       if(*lev==0)
3958         coords=elt->getCoords();
3959     }
3960   if(!coords)
3961     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildExtrudedMesh : internal error !");
3962   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> >::iterator it=zeList.begin();it!=zeList.end();it++)
3963     {
3964       (*it)->setName(getName());
3965       (*it)->setCoords(coords);
3966     }
3967   for(std::size_t ii=0;ii!=zeList.size();ii++)
3968     {
3969       int lev(levs[ii]);
3970       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(zeList[ii]);
3971       if(lev<=-1)
3972         {
3973           MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt1(getMeshAtLevel(lev+1));
3974           MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt2(elt1->clone(false));
3975           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(elt2->getNodalConnectivity()->deepCpy());
3976           elt2->setConnectivity(tmp,elt2->getNodalConnectivityIndex());
3977           elt2->shiftNodeNumbersInConn(nbRep*elt1->getNumberOfNodes());
3978           elt1->setCoords(elt->getCoords()); elt2->setCoords(elt->getCoords());
3979           std::vector<const MEDCouplingUMesh *> elts(3);
3980           elts[0]=elt; elts[1]=elt1; elts[2]=elt2;
3981           elt=MEDCouplingUMesh::MergeUMeshesOnSameCoords(elts);
3982           elt->setName(getName());
3983         }
3984       //
3985       o2ns[ii]=elt->sortCellsInMEDFileFrmt();
3986       ret->setMeshAtLevel(lev,elt);
3987     }
3988   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> endLev(getMeshAtLevel(levs.back())),endLev2;
3989   endLev=endLev->clone(false); endLev->setCoords(coords);
3990   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(endLev->getNodalConnectivity()->deepCpy());
3991   endLev2=endLev->clone(false); endLev2->setConnectivity(tmp,endLev->getNodalConnectivityIndex());
3992   endLev2->shiftNodeNumbersInConn(nbRep*getNumberOfNodes());
3993   endLev=MEDCouplingUMesh::MergeUMeshesOnSameCoords(endLev,endLev2);
3994   o2ns[levs.size()]=endLev->sortCellsInMEDFileFrmt();
3995   endLev->setName(getName());
3996   ret->setMeshAtLevel(levs.back()-1,endLev);
3997   //
3998   for(std::size_t ii=0;ii!=zeList.size();ii++)
3999     {
4000       int lev(levs[ii]);
4001       std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > outGrps;
4002       std::vector< const DataArrayInt * > outGrps2;
4003       if(lev<=-1)
4004         {
4005           for(std::vector<std::string>::const_iterator grp=grps.begin();grp!=grps.end();grp++)
4006             {
4007               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> grpArr(getGroupArr(lev+1,*grp));
4008               if(!grpArr->empty())
4009                 {
4010                   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> grpArr1(grpArr->deepCpy()),grpArr2(grpArr->deepCpy());
4011                   int offset0(zeList[ii]->getNumberOfCells());
4012                   int offset1(offset0+getNumberOfCellsAtLevel(lev+1));
4013                   grpArr1->applyLin(1,offset0); grpArr2->applyLin(1,offset1);
4014                   std::ostringstream oss; oss << grpArr2->getName() << "_top";
4015                   grpArr2->setName(oss.str());
4016                   grpArr1->transformWithIndArr(o2ns[ii]->begin(),o2ns[ii]->end());
4017                   grpArr2->transformWithIndArr(o2ns[ii]->begin(),o2ns[ii]->end());
4018                   outGrps.push_back(grpArr1); outGrps.push_back(grpArr2);
4019                   outGrps2.push_back(grpArr1); outGrps2.push_back(grpArr2);
4020                 }
4021             }
4022         }
4023       //
4024       for(std::vector<std::string>::const_iterator grp=grps.begin();grp!=grps.end();grp++)
4025         {
4026           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> grpArr(getGroupArr(lev,*grp));
4027           if(!grpArr->empty())
4028             {
4029               int nbCellsB4Extrusion(getNumberOfCellsAtLevel(lev));
4030               std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > grpArrs(nbRep);
4031               std::vector< const DataArrayInt *> grpArrs2(nbRep);
4032               for(int iii=0;iii<nbRep;iii++)
4033                 {
4034                   grpArrs[iii]=grpArr->deepCpy(); grpArrs[iii]->applyLin(1,iii*nbCellsB4Extrusion);
4035                   grpArrs2[iii]=grpArrs[iii];
4036                 }
4037               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> grpArrExt(DataArrayInt::Aggregate(grpArrs2));
4038               grpArrExt->transformWithIndArr(o2ns[ii]->begin(),o2ns[ii]->end());
4039               std::ostringstream grpName; grpName << *grp << "_extruded";
4040               grpArrExt->setName(grpName.str());
4041               outGrps.push_back(grpArrExt);
4042               outGrps2.push_back(grpArrExt);
4043             }
4044         }
4045       ret->setGroupsAtLevel(lev,outGrps2);
4046     }
4047   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > outGrps;
4048   std::vector< const DataArrayInt * > outGrps2;
4049   for(std::vector<std::string>::const_iterator grp=grps.begin();grp!=grps.end();grp++)
4050     {
4051       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> grpArr1(getGroupArr(levs.back(),*grp));
4052       if(grpArr1->empty())
4053         continue;
4054       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> grpArr2(grpArr1->deepCpy());
4055       std::ostringstream grpName; grpName << *grp << "_top";
4056       grpArr2->setName(grpName.str());
4057       grpArr2->applyLin(1,getNumberOfCellsAtLevel(levs.back()));
4058       outGrps.push_back(grpArr1); outGrps.push_back(grpArr2);
4059       outGrps2.push_back(grpArr1); outGrps2.push_back(grpArr2);
4060     }
4061   ret->setGroupsAtLevel(levs.back()-1,outGrps2);
4062   return ret.retn();
4063 }
4064
4065 /*!
4066  * This method converts all linear cells in \a this into quadratic cells (following the \a conversionType policy).
4067  * All the cells converted are put in the returned instance. This method applies all the groups and families in \a this to returned instance.
4068  * Groups on nodes and families on nodes are copied directly to the returned instance without transformation.
4069  *
4070  * \param [in] conversionType - conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4071  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
4072  * \param [in] eps - detection threshold for coordinates.
4073  * \return A new instance that is the result of the conversion. The caller has the ownership of this returned instance.
4074  *
4075  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic , quadraticToLinear
4076  */
4077 MEDFileUMesh *MEDFileUMesh::linearToQuadratic(int conversionType, double eps) const
4078 {
4079   MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret(MEDFileUMesh::New());
4080   int initialNbNodes(getNumberOfNodes());
4081   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Tmp(getMeshAtLevel(0));
4082   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0(dynamic_cast<MEDCouplingUMesh *>(m0Tmp->deepCpy()));
4083   {
4084     MEDCouplingAutoRefCountObjectPtr<DataArrayInt> notUsed(m0->convertLinearCellsToQuadratic(conversionType));
4085   }
4086   DataArrayDouble *zeCoords(m0->getCoords());
4087   ret->setMeshAtLevel(0,m0);
4088   std::vector<int> levs(getNonEmptyLevels());
4089   const DataArrayInt *famField(getFamilyFieldAtLevel(0));
4090   if(famField)
4091     {
4092       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famFieldCpy(famField->deepCpy());
4093       ret->setFamilyFieldArr(0,famFieldCpy);
4094     }
4095   famField=getFamilyFieldAtLevel(1);
4096   if(famField)
4097     {
4098       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fam(DataArrayInt::New()); fam->alloc(zeCoords->getNumberOfTuples(),1);
4099       fam->fillWithZero();
4100       fam->setPartOfValues1(famField,0,initialNbNodes,1,0,1,1);
4101       ret->setFamilyFieldArr(1,fam);
4102     }
4103   ret->copyFamGrpMapsFrom(*this);
4104   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> partZeCoords(zeCoords->selectByTupleId2(initialNbNodes,zeCoords->getNumberOfTuples(),1));
4105   for(std::vector<int>::const_iterator lev=levs.begin();lev!=levs.end();lev++)
4106     {
4107       if(*lev==0)
4108         continue;
4109       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Tmp(getMeshAtLevel(*lev));
4110       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1(dynamic_cast<MEDCouplingUMesh *>(m1Tmp->deepCpy()));
4111       if(m1->getMeshDimension()!=0)
4112         {
4113           {
4114             MEDCouplingAutoRefCountObjectPtr<DataArrayInt> notUsed(m1->convertLinearCellsToQuadratic(conversionType));
4115           }//kill unused notUsed var
4116           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> m1Coords(m1->getCoords()->selectByTupleId2(initialNbNodes,m1->getNumberOfNodes(),1));
4117           DataArrayInt *b(0);
4118           bool a(partZeCoords->areIncludedInMe(m1Coords,eps,b));
4119           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> bSafe(b);
4120           if(!a)
4121             {
4122               std::ostringstream oss; oss << "MEDFileUMesh::linearCellsToQuadratic : for level " << *lev << " problem to identify nodes generated !";
4123               throw INTERP_KERNEL::Exception(oss.str().c_str());
4124             }
4125           b->applyLin(1,initialNbNodes);
4126           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> l0(DataArrayInt::New()); l0->alloc(initialNbNodes,1); l0->iota();
4127           std::vector<const DataArrayInt *> v(2); v[0]=l0; v[1]=b;
4128           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum(DataArrayInt::Aggregate(v));
4129           m1->renumberNodesInConn(renum->begin());
4130         }
4131       m1->setCoords(zeCoords);
4132       ret->setMeshAtLevel(*lev,m1);
4133       famField=getFamilyFieldAtLevel(*lev);
4134       if(famField)
4135         {
4136           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famFieldCpy(famField->deepCpy());
4137           ret->setFamilyFieldArr(*lev,famFieldCpy);
4138         }
4139     }
4140   return ret.retn();
4141 }
4142
4143 /*!
4144  * This method converts all quadratic cells in \a this into linear cells.
4145  * All the cells converted are put in the returned instance. This method applies all the groups and families in \a this to returned instance.
4146  * Groups on nodes and families on nodes are copied directly to the returned instance without transformation.
4147  *
4148  * \param [in] eps - detection threshold for coordinates.
4149  * \return A new instance that is the result of the conversion. The caller has the ownership of this returned instance.
4150  *
4151  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic , linearToQuadratic
4152  */
4153 MEDFileUMesh *MEDFileUMesh::quadraticToLinear(double eps) const
4154 {
4155   MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret(MEDFileUMesh::New());
4156   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Tmp(getMeshAtLevel(0));
4157   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0(dynamic_cast<MEDCouplingUMesh *>(m0Tmp->deepCpy()));
4158   m0->convertQuadraticCellsToLinear();
4159   m0->zipCoords();
4160   DataArrayDouble *zeCoords(m0->getCoords());
4161   ret->setMeshAtLevel(0,m0);
4162   std::vector<int> levs(getNonEmptyLevels());
4163   const DataArrayInt *famField(getFamilyFieldAtLevel(0));
4164   if(famField)
4165     {
4166       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famFieldCpy(famField->deepCpy());
4167       ret->setFamilyFieldArr(0,famFieldCpy);
4168     }
4169   famField=getFamilyFieldAtLevel(1);
4170   if(famField)
4171     {
4172       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fam(famField->selectByTupleId2(0,zeCoords->getNumberOfTuples(),1));
4173       ret->setFamilyFieldArr(1,fam);
4174     }
4175   ret->copyFamGrpMapsFrom(*this);
4176   for(std::vector<int>::const_iterator lev=levs.begin();lev!=levs.end();lev++)
4177     {
4178       if(*lev==0)
4179         continue;
4180       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Tmp(getMeshAtLevel(*lev));
4181       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1(dynamic_cast<MEDCouplingUMesh *>(m1Tmp->deepCpy()));
4182       m1->convertQuadraticCellsToLinear();
4183       m1->zipCoords();
4184       DataArrayInt *b(0);
4185       bool a(zeCoords->areIncludedInMe(m1->getCoords(),eps,b));
4186       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> bSafe(b);
4187       if(!a)
4188         {
4189           std::ostringstream oss; oss << "MEDFileUMesh::quadraticToLinear : for level " << *lev << " problem to identify nodes generated !";
4190           throw INTERP_KERNEL::Exception(oss.str().c_str());
4191         }
4192       m1->renumberNodesInConn(b->begin());
4193       m1->setCoords(zeCoords);
4194       ret->setMeshAtLevel(*lev,m1);
4195       famField=getFamilyFieldAtLevel(*lev);
4196       if(famField)
4197         {
4198           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famFieldCpy(famField->deepCpy());
4199           ret->setFamilyFieldArr(*lev,famFieldCpy);
4200         }
4201     }
4202   return ret.retn();
4203 }
4204
4205 void MEDFileUMesh::serialize(std::vector<double>& tinyDouble, std::vector<int>& tinyInt, std::vector<std::string>& tinyStr, std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >& bigArraysI, MEDCouplingAutoRefCountObjectPtr<DataArrayDouble>& bigArrayD)
4206 {
4207   clearNonDiscrAttributes();
4208   forceComputationOfParts();
4209   tinyDouble.clear(); tinyInt.clear(); tinyStr.clear(); bigArraysI.clear(); bigArrayD=0;
4210   std::vector<int> layer0;
4211   layer0.push_back(_order); //0 i
4212   layer0.push_back(_iteration);//1 i
4213   layer0.push_back(getSpaceDimension());//2 i
4214   tinyDouble.push_back(_time);//0 d
4215   tinyStr.push_back(_name);//0 s
4216   tinyStr.push_back(_desc_name);//1 s
4217   for(int i=0;i<getSpaceDimension();i++)
4218     tinyStr.push_back(_coords->getInfoOnComponent(i));
4219   layer0.push_back((int)_families.size());//3 i <- key info aa layer#0
4220   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
4221     {
4222       tinyStr.push_back((*it).first);
4223       layer0.push_back((*it).second);
4224     }
4225   layer0.push_back((int)_groups.size());//3+aa i <- key info bb layer#0
4226   for(std::map<std::string, std::vector<std::string> >::const_iterator it0=_groups.begin();it0!=_groups.end();it0++)
4227     {
4228       layer0.push_back((int)(*it0).second.size());
4229       tinyStr.push_back((*it0).first);
4230       for(std::vector<std::string>::const_iterator it1=((*it0).second).begin();it1!=((*it0).second).end();it1++)
4231         tinyStr.push_back(*it1);
4232     }
4233   // sizeof(layer0)==3+aa+1+bb layer#0
4234   bigArrayD=_coords;// 0 bd
4235   bigArraysI.push_back(_fam_coords);// 0 bi
4236   bigArraysI.push_back(_num_coords);// 1 bi
4237   const PartDefinition *pd(_part_coords);
4238   if(!pd)
4239     layer0.push_back(-1);
4240   else
4241     {
4242       std::vector<int> tmp0;
4243       pd->serialize(tmp0,bigArraysI);
4244       tinyInt.push_back(tmp0.size());
4245       tinyInt.insert(tinyInt.end(),tmp0.begin(),tmp0.end());
4246     }
4247   //
4248   std::vector<int> layer1;
4249   std::vector<int> levs(getNonEmptyLevels());
4250   layer1.push_back((int)levs.size());// 0 i <- key
4251   layer1.insert(layer1.end(),levs.begin(),levs.end());
4252   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
4253     {
4254       const MEDFileUMeshSplitL1 *lev(getMeshAtLevSafe(*it));
4255       lev->serialize(layer1,bigArraysI);
4256     }
4257   // put layers all together.
4258   tinyInt.push_back(layer0.size());
4259   tinyInt.insert(tinyInt.end(),layer0.begin(),layer0.end());
4260   tinyInt.push_back(layer1.size());
4261   tinyInt.insert(tinyInt.end(),layer1.begin(),layer1.end());
4262 }
4263
4264 void MEDFileUMesh::unserialize(std::vector<double>& tinyDouble, std::vector<int>& tinyInt, std::vector<std::string>& tinyStr,
4265                                std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >& bigArraysI, MEDCouplingAutoRefCountObjectPtr<DataArrayDouble>& bigArrayD)
4266 {
4267   int sz0(tinyInt[0]);
4268   std::vector<int> layer0(tinyInt.begin()+1,tinyInt.begin()+1+sz0);
4269   int sz1(tinyInt[sz0+1]);
4270   std::vector<int> layer1(tinyInt.begin()+2+sz0,tinyInt.begin()+2+sz0+sz1);
4271   //
4272   std::reverse(layer0.begin(),layer0.end());
4273   std::reverse(layer1.begin(),layer1.end());
4274   std::reverse(tinyDouble.begin(),tinyDouble.end());
4275   std::reverse(tinyStr.begin(),tinyStr.end());
4276   std::reverse(bigArraysI.begin(),bigArraysI.end());
4277   //
4278   _order=layer0.back(); layer0.pop_back();
4279   _iteration=layer0.back(); layer0.pop_back();
4280   int spaceDim(layer0.back()); layer0.pop_back();
4281   _time=tinyDouble.back(); tinyDouble.pop_back();
4282   _name=tinyStr.back(); tinyStr.pop_back();
4283   _desc_name=tinyStr.back(); tinyStr.pop_back();
4284   _coords=bigArrayD; _coords->rearrange(spaceDim);
4285   for(int i=0;i<spaceDim;i++)
4286     {
4287       _coords->setInfoOnComponent(i,tinyStr.back());
4288       tinyStr.pop_back();
4289     }
4290   int nbOfFams(layer0.back()); layer0.pop_back();
4291   _families.clear();
4292   for(int i=0;i<nbOfFams;i++)
4293     {
4294       _families[tinyStr.back()]=layer0.back();
4295       tinyStr.pop_back(); layer0.pop_back();
4296     }
4297   int nbGroups(layer0.back()); layer0.pop_back();
4298   _groups.clear();
4299   for(int i=0;i<nbGroups;i++)
4300     {
4301       std::string grpName(tinyStr.back()); tinyStr.pop_back();
4302       int nbOfFamsOnGrp(layer0.back()); layer0.pop_back();
4303       std::vector<std::string> fams(nbOfFamsOnGrp);
4304       for(int j=0;j<nbOfFamsOnGrp;j++)
4305         {
4306           fams[j]=tinyStr.back(); tinyStr.pop_back();
4307         }
4308       _groups[grpName]=fams;
4309     }
4310   _fam_coords=bigArraysI.back(); bigArraysI.pop_back();
4311   _num_coords=bigArraysI.back(); bigArraysI.pop_back();
4312   _part_coords=0;
4313   int isPd(layer0.back()); layer0.pop_back();
4314   if(isPd!=-1)
4315     {
4316       std::vector<int> tmp0(layer0.begin(),layer0.begin()+isPd);
4317       layer0.erase(layer0.begin(),layer0.begin()+isPd);
4318       _part_coords=PartDefinition::Unserialize(tmp0,bigArraysI);
4319     }
4320   if(!layer0.empty())
4321     throw INTERP_KERNEL::Exception("MEDFileUMesh::unserialize : something wrong during unserialization #1 !");
4322   //
4323   int nbLevs(layer1.back()); layer1.pop_back();
4324   std::vector<int> levs(layer1.rbegin(),layer1.rbegin()+nbLevs); layer1.erase(layer1.end()-nbLevs,layer1.end());
4325   _ms.clear();
4326   int maxLev(-(*std::min_element(levs.begin(),levs.end())));
4327   _ms.resize(maxLev+1);
4328   for(int i=0;i<nbLevs;i++)
4329     {
4330       int lev(levs[i]);
4331       int pos(-lev);
4332       _ms[pos]=MEDFileUMeshSplitL1::Unserialize(_name,_coords,layer1,bigArraysI);
4333     }
4334 }
4335
4336 /*!
4337  * Adds a group of nodes to \a this mesh.
4338  *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
4339  *          The ids should be sorted and different each other (MED file norm).
4340  *
4341  *  \warning this method can alter default "FAMILLE_ZERO" family.
4342  *  For users sensitive to this a call to MEDFileMesh::rearrangeFamilies will be necessary after addGroup session.
4343  *
4344  *  \throw If the node coordinates array is not set.
4345  *  \throw If \a ids == \c NULL.
4346  *  \throw If \a ids->getName() == "".
4347  *  \throw If \a ids does not respect the MED file norm.
4348  *  \throw If a group with name \a ids->getName() already exists.
4349  */
4350 void MEDFileUMesh::addNodeGroup(const DataArrayInt *ids)
4351 {
4352   const DataArrayDouble *coords(_coords);
4353   if(!coords)
4354     throw INTERP_KERNEL::Exception("MEDFileUMesh::addNodeGroup : no coords set !");
4355   int nbOfNodes(coords->getNumberOfTuples());
4356   if(!((DataArrayInt *)_fam_coords))
4357     { _fam_coords=DataArrayInt::New(); _fam_coords->alloc(nbOfNodes,1); _fam_coords->fillWithZero(); }
4358   //
4359   addGroupUnderground(true,ids,_fam_coords);
4360 }
4361
4362 /*!
4363  * Adds a group of nodes/cells/faces/edges to \a this mesh.
4364  *
4365  *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
4366  *          The ids should be sorted and different each other (MED file norm).
4367  *
4368  * \warning this method can alter default "FAMILLE_ZERO" family.
4369  * For users sensitive to this a call to MEDFileMesh::rearrangeFamilies will be necessary after addGroup session.
4370  *
4371  *  \throw If the node coordinates array is not set.
4372  *  \throw If \a ids == \c NULL.
4373  *  \throw If \a ids->getName() == "".
4374  *  \throw If \a ids does not respect the MED file norm.
4375  *  \throw If a group with name \a ids->getName() already exists.
4376  */
4377 void MEDFileUMesh::addGroup(int meshDimRelToMaxExt, const DataArrayInt *ids)
4378 {
4379   std::vector<int> levs(getNonEmptyLevelsExt());
4380   if(std::find(levs.begin(),levs.end(),meshDimRelToMaxExt)==levs.end())
4381     { 
4382       std::ostringstream oss; oss << "MEDFileUMesh::addGroup : level " << meshDimRelToMaxExt << " not available ! Should be in ";
4383       std::copy(levs.begin(),levs.end(),std::ostream_iterator<int>(oss," ")); oss << " !"; throw INTERP_KERNEL::Exception(oss.str().c_str());
4384     }
4385   if(meshDimRelToMaxExt==1)
4386     { addNodeGroup(ids); return ; }
4387   MEDFileUMeshSplitL1 *lev(getMeshAtLevSafe(meshDimRelToMaxExt));
4388   DataArrayInt *fam(lev->getOrCreateAndGetFamilyField());
4389   addGroupUnderground(false,ids,fam);
4390 }
4391
4392 /*!
4393  * Changes a name of a family specified by its id.
4394  *  \param [in] id - the id of the family of interest.
4395  *  \param [in] newFamName - the new family name.
4396  *  \throw If no family with the given \a id exists.
4397  */
4398 void MEDFileUMesh::setFamilyNameAttachedOnId(int id, const std::string& newFamName)
4399 {
4400   std::string oldName=getFamilyNameGivenId(id);
4401   _families.erase(oldName);
4402   _families[newFamName]=id;
4403 }
4404
4405 /*!
4406  * Removes a mesh of a given dimension.
4407  *  \param [in] meshDimRelToMax - the relative dimension of interest.
4408  *  \throw If there is no mesh at level \a meshDimRelToMax in \a this mesh.
4409  */
4410 void MEDFileUMesh::removeMeshAtLevel(int meshDimRelToMax)
4411 {
4412   std::vector<int> levSet=getNonEmptyLevels();
4413   std::vector<int>::const_iterator it=std::find(levSet.begin(),levSet.end(),meshDimRelToMax);
4414   if(it==levSet.end())
4415     throw INTERP_KERNEL::Exception("MEDFileUMesh::removeMeshAtLevel : the requested level is not existing !");
4416   int pos=(-meshDimRelToMax);
4417   _ms[pos]=0;
4418 }
4419
4420 /*!
4421  * Sets a new MEDCoupling1GTUMesh at a given level in \a this mesh.
4422  *  \param [in] meshDimRelToMax - a relative level to set the mesh at.
4423  *  \param [in] m - the new mesh to set.
4424  *  \throw If the name or the description of \a this mesh and \a m are not empty and are
4425  *         different. 
4426  *  \throw If the node coordinates array is set \a this in mesh and \a m refers to
4427  *         another node coordinates array.
4428  *  \throw If the mesh dimension of \a m does not correspond to \a meshDimRelToMax or
4429  *         to the existing meshes of other levels of \a this mesh.
4430  */
4431 void MEDFileUMesh::setMeshAtLevel(int meshDimRelToMax, MEDCoupling1GTUMesh *m)
4432 {
4433   MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> elt(new MEDFileUMeshSplitL1(m));
4434   checkAndGiveEntryInSplitL1(meshDimRelToMax,m)=elt;
4435 }
4436
4437 /*!
4438  * Sets a new MEDCouplingUMesh at a given level in \a this mesh.
4439  *  \param [in] meshDimRelToMax - a relative level to set the mesh at.
4440  *  \param [in] m - the new mesh to set.
4441  *  \param [in] newOrOld - if \c true, cells in \a m are sorted by type to be ready for 
4442  *         writing \a this mesh in a MED file.
4443  *  \throw If the name or the description of \a this mesh and \a m are not empty and are
4444  *         different. 
4445  *  \throw If the node coordinates array is set \a this in mesh and \a m refers to
4446  *         another node coordinates array.
4447  *  \throw If the mesh dimension of \a m does not correspond to \a meshDimRelToMax or
4448  *         to the existing meshes of other levels of \a this mesh.
4449  */
4450 void MEDFileUMesh::setMeshAtLevel(int meshDimRelToMax, MEDCouplingUMesh *m, bool newOrOld)
4451 {
4452   MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> elt(new MEDFileUMeshSplitL1(m,newOrOld));
4453   checkAndGiveEntryInSplitL1(meshDimRelToMax,m)=elt;
4454 }
4455
4456 MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1>& MEDFileUMesh::checkAndGiveEntryInSplitL1(int meshDimRelToMax, MEDCouplingPointSet *m)
4457 {
4458   dealWithTinyInfo(m);
4459   std::vector<int> levSet=getNonEmptyLevels();
4460   if(std::find(levSet.begin(),levSet.end(),meshDimRelToMax)==levSet.end())
4461     {
4462       if((DataArrayDouble *)_coords==0)
4463         {
4464           DataArrayDouble *c=m->getCoords();
4465           if(c)
4466             c->incrRef();
4467           _coords=c;
4468         }
4469       if(m->getCoords()!=_coords)
4470         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshAtLevel : Invalid Given Mesh ! The coordinates are not the same ! try to use tryToShareSameCoords !");
4471       int sz=(-meshDimRelToMax)+1;
4472       if(sz>=(int)_ms.size())
4473         _ms.resize(sz);
4474       checkMeshDimCoherency(m->getMeshDimension(),meshDimRelToMax);
4475       return _ms[sz-1];
4476     }
4477   else
4478     return _ms[-meshDimRelToMax];
4479 }
4480
4481 /*!
4482  * This method allows to set at once the content of different levels in \a this.
4483  * This method is equivalent to a series of call to MEDFileUMesh::setMeshAtLevel.
4484  *
4485  * \param [in] ms - List of unstructured meshes lying on the same coordinates and having different mesh dimesnion.
4486  * \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.
4487  *                     If false, an exception ois thrown. If true the mesh is reordered automatically. It is highly recommanded to let this parameter to false.
4488  *
4489  * \throw If \a there is a null pointer in \a ms.
4490  * \sa MEDFileUMesh::setMeshAtLevel
4491  */
4492 void MEDFileUMesh::setMeshes(const std::vector<const MEDCouplingUMesh *>& ms, bool renum)
4493 {
4494   if(ms.empty())
4495     return ;
4496   const MEDCouplingUMesh *mRef=ms[0];
4497   if(!mRef)
4498     throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : null instance in the first element of input meshes !");
4499   std::string name(mRef->getName());
4500   const DataArrayDouble *coo(mRef->getCoords());
4501   std::set<int> s;
4502   int zeDim=-1;
4503   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
4504     {
4505       const MEDCouplingUMesh *cur(*it);
4506       if(!cur)
4507         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : null instance in input vector of meshes !");
4508       if(coo!=cur->getCoords())
4509         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : The input meshes do not share the same coordinates !");
4510       int mdim=cur->getMeshDimension();
4511       zeDim=std::max(zeDim,mdim);
4512       if(s.find(mdim)!=s.end())
4513         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : The input meshes must share the same coordinates pointer, and should have different mesh dimension each other !");
4514     }
4515   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
4516     {
4517       int mdim=(*it)->getMeshDimension();
4518       setName((*it)->getName());
4519       setMeshAtLevel(mdim-zeDim,const_cast<MEDCouplingUMesh *>(*it),renum);
4520     }
4521   setName(name);
4522 }
4523
4524 /*!
4525  * Creates one MEDCouplingUMesh at a given level in \a this mesh from a sequence of
4526  * meshes each representing a group, and creates corresponding groups in \a this mesh.
4527  * The given meshes must share the same node coordinates array.
4528  *  \param [in] meshDimRelToMax - the relative dimension to create the mesh and groups at.
4529  *  \param [in] ms - the sequence of meshes. Each mesh in \a ms represents a group to
4530  *          create in \a this mesh.
4531  *  \throw If \a ms is empty.
4532  *  \throw If dimension of meshes in \a ms does not correspond to \a meshDimRelToMax or
4533  *         to the existing meshes of other levels of \a this mesh.
4534  *  \throw If the meshes in \a ms do not share the same node coordinates array.
4535  *  \throw If the node coordinates array of \a this mesh (if any) is not the same as that
4536  *         of the given meshes.
4537  *  \throw If \a ms[ i ] is not well defined (MEDCouplingUMesh::checkCoherency()).
4538  *  \throw If names of some meshes in \a ms are equal.
4539  *  \throw If \a ms includes a mesh with an empty name.
4540  */
4541 void MEDFileUMesh::setGroupsFromScratch(int meshDimRelToMax, const std::vector<const MEDCouplingUMesh *>& ms, bool renum)
4542 {
4543   if(ms.empty())
4544     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsFromScratch : expecting a non empty vector !");
4545   int sz=(-meshDimRelToMax)+1;
4546   if(sz>=(int)_ms.size())
4547     _ms.resize(sz);
4548   checkMeshDimCoherency(ms[0]->getMeshDimension(),meshDimRelToMax);
4549   DataArrayDouble *coo=checkMultiMesh(ms);
4550   if((DataArrayDouble *)_coords==0)
4551     {
4552       coo->incrRef();
4553       _coords=coo;
4554     }
4555   else
4556     if((DataArrayDouble *)_coords!=coo)
4557       throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsFromScratch : coordinates mismatches !");
4558   std::vector<DataArrayInt *> corr;
4559   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MEDCouplingUMesh::FuseUMeshesOnSameCoords(ms,_zipconn_pol,corr);
4560   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > corr3(corr.begin(),corr.end());
4561   setMeshAtLevel(meshDimRelToMax,m,renum);
4562   std::vector<const DataArrayInt *> corr2(corr.begin(),corr.end());
4563   setGroupsAtLevel(meshDimRelToMax,corr2,true);
4564 }
4565
4566 /*!
4567  * Creates groups at a given level in \a this mesh from a sequence of
4568  * meshes each representing a group.
4569  * The given meshes must share the same node coordinates array.
4570  *  \param [in] meshDimRelToMax - the relative dimension to create the groups at.
4571  *  \param [in] ms - the sequence of meshes. Each mesh in \a ms represents a group to
4572  *         create in \a this mesh.
4573  *  \param [in] renum - if \c true, then the optional numbers of entities are taken into
4574  *         account. 
4575  *  \throw If \a ms is empty.
4576  *  \throw If dimension of meshes in \a ms does not correspond to \a meshDimRelToMax or
4577  *         to the existing meshes of other levels of \a this mesh.
4578  *  \throw If the meshes in \a ms do not share the same node coordinates array.
4579  *  \throw If the node coordinates array of \a this mesh (if any) is not the same as that
4580  *         of the given meshes.
4581  *  \throw If \a ms[ i ] is not well defined (MEDCouplingUMesh::checkCoherency()).
4582  *  \throw If names of some meshes in \a ms are equal.
4583  *  \throw If \a ms includes a mesh with an empty name.
4584  */
4585 void MEDFileUMesh::setGroupsOnSetMesh(int meshDimRelToMax, const std::vector<const MEDCouplingUMesh *>& ms, bool renum)
4586 {
4587   if(ms.empty())
4588     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsOnSetMesh : expecting a non empty vector !");
4589   int sz=(-meshDimRelToMax)+1;
4590   if(sz>=(int)_ms.size())
4591     _ms.resize(sz);
4592   checkMeshDimCoherency(ms[0]->getMeshDimension(),meshDimRelToMax);
4593   DataArrayDouble *coo=checkMultiMesh(ms);
4594   if((DataArrayDouble *)_coords==0)
4595     {
4596       coo->incrRef();
4597       _coords=coo;
4598     }
4599   else
4600     if((DataArrayDouble *)_coords!=coo)
4601       throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsOnSetMesh : coordinates mismatches !");
4602   MEDCouplingUMesh *m=getMeshAtLevel(meshDimRelToMax,renum);
4603   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > corr(ms.size());
4604   int i=0;
4605   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++,i++)
4606     {
4607       DataArrayInt *arr=0;
4608       bool test=m->areCellsIncludedIn(*it,_zipconn_pol,arr);
4609       corr[i]=arr;
4610       if(!test)
4611         {
4612           std::ostringstream oss; oss << "MEDFileUMesh::setGroupsOnSetMesh : mesh #" << i << " is not part of whole mesh !";
4613           throw INTERP_KERNEL::Exception(oss.str().c_str());
4614         }
4615     }
4616   std::vector<const DataArrayInt *> corr2(corr.begin(),corr.end());
4617   setGroupsAtLevel(meshDimRelToMax,corr2,renum);
4618 }
4619
4620 DataArrayDouble *MEDFileUMesh::checkMultiMesh(const std::vector<const MEDCouplingUMesh *>& ms) const
4621 {
4622   const DataArrayDouble *ret=ms[0]->getCoords();
4623   int mdim=ms[0]->getMeshDimension();
4624   for(unsigned int i=1;i<ms.size();i++)
4625     {
4626       ms[i]->checkCoherency();
4627       if(ms[i]->getCoords()!=ret)
4628         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMultiMesh : meshes must share the same coords !");
4629       if(ms[i]->getMeshDimension()!=mdim)
4630         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMultiMesh : meshes have not same mesh dimension !");
4631     }
4632   return const_cast<DataArrayDouble *>(ret);
4633 }
4634
4635 /*!
4636  * Sets the family field of a given relative dimension.
4637  *  \param [in] meshDimRelToMaxExt - the relative dimension of entities for which
4638  *          the family field is set.
4639  *  \param [in] famArr - the array of the family field.
4640  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4641  *  \throw If \a famArr has an invalid size.
4642  */
4643 void MEDFileUMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr)
4644 {
4645   if(meshDimRelToMaxExt==1)
4646     {
4647       if(!famArr)
4648         {
4649           _fam_coords=0;
4650           return ;
4651         }
4652       DataArrayDouble *coo(_coords);
4653       if(!coo)
4654         throw INTERP_KERNEL::Exception("MEDFileUMesh::setFamilyFieldArr : the coordinates have not been set !");
4655       famArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),1,"MEDFileUMesh::setFamilyFieldArr : Problem in size of node family arr ! ");
4656       famArr->incrRef();
4657       _fam_coords=famArr;
4658       return ;
4659     }
4660   if(meshDimRelToMaxExt>1)
4661     throw INTERP_KERNEL::Exception("MEDFileUMesh::setFamilyFieldArr : Dimension request is invalid (>1) !");
4662   int traducedRk=-meshDimRelToMaxExt;
4663   if(traducedRk>=(int)_ms.size())
4664     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
4665   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
4666     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
4667   return _ms[traducedRk]->setFamilyArr(famArr);
4668 }
4669
4670 /*!
4671  * Sets the optional numbers of mesh entities of a given dimension.
4672  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4673  *  \param [in] renumArr - the array of the numbers.
4674  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4675  *  \throw If \a renumArr has an invalid size.
4676  */
4677 void MEDFileUMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr)
4678 {
4679   if(meshDimRelToMaxExt==1)
4680     {
4681       if(!renumArr)
4682         {
4683           _num_coords=0;
4684           _rev_num_coords=0;
4685           return ;
4686         }
4687       DataArrayDouble *coo(_coords);
4688       if(!coo)
4689         throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumFieldArr : the coordinates have not been set !");
4690       renumArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),1,"MEDFileUMesh::setRenumArr : Problem in size of node numbering arr ! ");
4691       renumArr->incrRef();
4692       _num_coords=renumArr;
4693       computeRevNum();
4694       return ;
4695     }
4696   if(meshDimRelToMaxExt>1)
4697     throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumArr : Dimension request is invalid (>1) !");
4698   int traducedRk=-meshDimRelToMaxExt;
4699   if(traducedRk>=(int)_ms.size())
4700     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
4701   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
4702     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
4703   return _ms[traducedRk]->setRenumArr(renumArr);
4704 }
4705
4706 /*!
4707  * Sets the optional names of mesh entities of a given dimension.
4708  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4709  *  \param [in] nameArr - the array of the names.
4710  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4711  *  \throw If \a nameArr has an invalid size.
4712  */
4713 void MEDFileUMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr)
4714 {
4715   if(meshDimRelToMaxExt==1)
4716     {
4717       if(!nameArr)
4718         {
4719           _name_coords=0;
4720           return ;
4721         }
4722       DataArrayDouble *coo(_coords);
4723       if(!coo)
4724         throw INTERP_KERNEL::Exception("MEDFileUMesh::setNameFieldAtLevel : the coordinates have not been set !");
4725       nameArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),MED_SNAME_SIZE,"MEDFileUMesh::setNameFieldAtLevel : Problem in size of node numbering arr ! ");
4726       nameArr->incrRef();
4727       _name_coords=nameArr;
4728       return ;
4729     }
4730   if(meshDimRelToMaxExt>1)
4731     throw INTERP_KERNEL::Exception("MEDFileUMesh::setNameFieldAtLevel : Dimension request is invalid (>1) !");
4732   int traducedRk=-meshDimRelToMaxExt;
4733   if(traducedRk>=(int)_ms.size())
4734     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
4735   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
4736     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
4737   return _ms[traducedRk]->setNameArr(nameArr);
4738 }
4739
4740 void MEDFileUMesh::synchronizeTinyInfoOnLeaves() const
4741 {
4742   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
4743     if((const MEDFileUMeshSplitL1 *)(*it))
4744       (*it)->synchronizeTinyInfo(*this);
4745 }
4746
4747 /*!
4748  * This method is called by MEDFileMesh::changeFamilyId. It performs only one part of the family id modification.
4749  */
4750 void MEDFileUMesh::changeFamilyIdArr(int oldId, int newId)
4751 {
4752   DataArrayInt *arr=_fam_coords;
4753   if(arr)
4754     arr->changeValue(oldId,newId);
4755   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
4756     {
4757       MEDFileUMeshSplitL1 *sp=(*it);
4758       if(sp)
4759         {
4760           sp->changeFamilyIdArr(oldId,newId);
4761         }
4762     }
4763 }
4764
4765 std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > MEDFileUMesh::getAllNonNullFamilyIds() const
4766 {
4767   std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret;
4768   const DataArrayInt *da(_fam_coords);
4769   if(da)
4770     { da->incrRef(); ret.push_back(MEDCouplingAutoRefCountObjectPtr<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
4771   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
4772     {
4773       const MEDFileUMeshSplitL1 *elt(*it);
4774       if(elt)
4775         {
4776           da=elt->getFamilyField();
4777           if(da)
4778             { da->incrRef(); ret.push_back(MEDCouplingAutoRefCountObjectPtr<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
4779         }
4780     }
4781   return ret;
4782 }
4783
4784 void MEDFileUMesh::computeRevNum() const
4785 {
4786   if((const DataArrayInt *)_num_coords)
4787     {
4788       int pos;
4789       int maxValue=_num_coords->getMaxValue(pos);
4790       _rev_num_coords=_num_coords->invertArrayN2O2O2N(maxValue+1);
4791     }
4792 }
4793
4794 std::size_t MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren() const
4795 {
4796   return MEDFileMesh::getHeapMemorySizeWithoutChildren();
4797 }
4798
4799 std::vector<const BigMemoryObject *> MEDFileStructuredMesh::getDirectChildrenWithNull() const
4800 {
4801   std::vector<const BigMemoryObject *> ret(MEDFileMesh::getDirectChildrenWithNull());
4802   ret.push_back((const DataArrayInt *)_fam_nodes);
4803   ret.push_back((const DataArrayInt *)_num_nodes);
4804   ret.push_back((const DataArrayAsciiChar *)_names_nodes);
4805   ret.push_back((const DataArrayInt *)_fam_cells);
4806   ret.push_back((const DataArrayInt *)_num_cells);
4807   ret.push_back((const DataArrayAsciiChar *)_names_cells);
4808   ret.push_back((const DataArrayInt *)_fam_faces);
4809   ret.push_back((const DataArrayInt *)_num_faces);
4810   ret.push_back((const DataArrayInt *)_rev_num_nodes);
4811   ret.push_back((const DataArrayAsciiChar *)_names_faces);
4812   ret.push_back((const DataArrayInt *)_rev_num_cells);
4813   ret.push_back((const MEDCoupling1SGTUMesh*)_faces_if_necessary);
4814   return ret;
4815 }
4816
4817 int MEDFileStructuredMesh::getMaxAbsFamilyIdInArrays() const
4818 {
4819   int ret=-std::numeric_limits<int>::max(),tmp=-1;
4820   if((const DataArrayInt *)_fam_nodes)
4821     {
4822       int val=_fam_nodes->getMaxValue(tmp);
4823       ret=std::max(ret,std::abs(val));
4824     }
4825   if((const DataArrayInt *)_fam_cells)
4826     {
4827       int val=_fam_cells->getMaxValue(tmp);
4828       ret=std::max(ret,std::abs(val));
4829     }
4830   if((const DataArrayInt *)_fam_faces)
4831     {
4832       int val=_fam_faces->getMaxValue(tmp);
4833       ret=std::max(ret,std::abs(val));
4834     }
4835   return ret;
4836 }
4837
4838 int MEDFileStructuredMesh::getMaxFamilyIdInArrays() const
4839 {
4840   int ret=-std::numeric_limits<int>::max(),tmp=-1;
4841   if((const DataArrayInt *)_fam_nodes)
4842     {
4843       int val=_fam_nodes->getMaxValue(tmp);
4844       ret=std::max(ret,val);
4845     }
4846   if((const DataArrayInt *)_fam_cells)
4847     {
4848       int val=_fam_cells->getMaxValue(tmp);
4849       ret=std::max(ret,val);
4850     }
4851   if((const DataArrayInt *)_fam_faces)
4852     {
4853       int val=_fam_faces->getMaxValue(tmp);
4854       ret=std::max(ret,val);
4855     }
4856   return ret;
4857 }
4858
4859 int MEDFileStructuredMesh::getMinFamilyIdInArrays() const
4860 {
4861   int ret=std::numeric_limits<int>::max(),tmp=-1;
4862   if((const DataArrayInt *)_fam_nodes)
4863     {
4864       int val=_fam_nodes->getMinValue(tmp);
4865       ret=std::min(ret,val);
4866     }
4867   if((const DataArrayInt *)_fam_cells)
4868     {
4869       int val=_fam_cells->getMinValue(tmp);
4870       ret=std::min(ret,val);
4871     }
4872   if((const DataArrayInt *)_fam_faces)
4873     {
4874       int val=_fam_faces->getMinValue(tmp);
4875       ret=std::min(ret,val);
4876     }
4877   return ret;
4878 }
4879
4880 bool MEDFileStructuredMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
4881 {
4882   if(!MEDFileMesh::isEqual(other,eps,what))
4883     return false;
4884   const MEDFileStructuredMesh *otherC=dynamic_cast<const  MEDFileStructuredMesh *>(other);
4885   if(!otherC)
4886     {
4887       what="Mesh types differ ! This is structured and other is NOT !";
4888       return false;
4889     }
4890   const DataArrayInt *famc1=_fam_nodes;
4891   const DataArrayInt *famc2=otherC->_fam_nodes;
4892   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
4893     {
4894       what="Mismatch of families arr on nodes ! One is defined and not other !";
4895       return false;
4896     }
4897   if(famc1)
4898     {
4899       bool ret=famc1->isEqual(*famc2);
4900       if(!ret)
4901         {
4902           what="Families arr on nodes differ !";
4903           return false;
4904         }
4905     }
4906   famc1=_fam_cells;
4907   famc2=otherC->_fam_cells;
4908   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
4909     {
4910       what="Mismatch of families arr on cells ! One is defined and not other !";
4911       return false;
4912     }
4913   if(famc1)
4914     {
4915       bool ret=famc1->isEqual(*famc2);
4916       if(!ret)
4917         {
4918           what="Families arr on cells differ !";
4919           return false;
4920         }
4921     }
4922   famc1=_fam_faces;
4923   famc2=otherC->_fam_faces;
4924   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
4925     {
4926       what="Mismatch of families arr on faces ! One is defined and not other !";
4927       return false;
4928     }
4929   if(famc1)
4930     {
4931       bool ret=famc1->isEqual(*famc2);
4932       if(!ret)
4933         {
4934           what="Families arr on faces differ !";
4935           return false;
4936         }
4937     }
4938   famc1=_num_nodes;
4939   famc2=otherC->_num_nodes;
4940   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
4941     {
4942       what="Mismatch of numbering arr on nodes ! One is defined and not other !";
4943       return false;
4944     }
4945   if(famc1)
4946     {
4947       bool ret=famc1->isEqual(*famc2);
4948       if(!ret)
4949         {
4950           what="Numbering arr on nodes differ !";
4951           return false;
4952         }
4953     }
4954   famc1=_num_cells;
4955   famc2=otherC->_num_cells;
4956   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
4957     {
4958       what="Mismatch of numbering arr on cells ! One is defined and not other !";
4959       return false;
4960     }
4961   if(famc1)
4962     {
4963       bool ret=famc1->isEqual(*famc2);
4964       if(!ret)
4965         {
4966           what="Numbering arr on cells differ !";
4967           return false;
4968         }
4969     }
4970   famc1=_num_faces;
4971   famc2=otherC->_num_faces;
4972   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
4973     {
4974       what="Mismatch of numbering arr on faces ! One is defined and not other !";
4975       return false;
4976     }
4977   if(famc1)
4978     {
4979       bool ret=famc1->isEqual(*famc2);
4980       if(!ret)
4981         {
4982           what="Numbering arr on faces differ !";
4983           return false;
4984         }
4985     }
4986   const DataArrayAsciiChar *d1=_names_cells;
4987   const DataArrayAsciiChar *d2=otherC->_names_cells;
4988   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
4989     {
4990       what="Mismatch of naming arr on cells ! One is defined and not other !";
4991       return false;
4992     }
4993   if(d1)
4994     {
4995       bool ret=d1->isEqual(*d2);
4996       if(!ret)
4997         {
4998           what="Naming arr on cells differ !";
4999           return false;
5000         }
5001     }
5002   d1=_names_faces;
5003   d2=otherC->_names_faces;
5004   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
5005     {
5006       what="Mismatch of naming arr on faces ! One is defined and not other !";
5007       return false;
5008     }
5009   if(d1)
5010     {
5011       bool ret=d1->isEqual(*d2);
5012       if(!ret)
5013         {
5014           what="Naming arr on faces differ !";
5015           return false;
5016         }
5017     }
5018   d1=_names_nodes;
5019   d2=otherC->_names_nodes;
5020   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
5021     {
5022       what="Mismatch of naming arr on nodes ! One is defined and not other !";
5023       return false;
5024     }
5025   if(d1)
5026     {
5027       bool ret=d1->isEqual(*d2);
5028       if(!ret)
5029         {
5030           what="Naming arr on nodes differ !";
5031           return false;
5032         }
5033     }
5034   return true;
5035 }
5036
5037 void MEDFileStructuredMesh::clearNonDiscrAttributes() const
5038 {
5039   MEDFileMesh::clearNonDiscrAttributes();
5040   const DataArrayInt *tmp=_fam_nodes;
5041   if(tmp)
5042     (const_cast<DataArrayInt *>(tmp))->setName("");
5043   tmp=_num_nodes;
5044   if(tmp)
5045     (const_cast<DataArrayInt *>(tmp))->setName("");
5046   tmp=_fam_cells;
5047   if(tmp)
5048     (const_cast<DataArrayInt *>(tmp))->setName("");
5049   tmp=_num_cells;
5050   if(tmp)
5051     (const_cast<DataArrayInt *>(tmp))->setName("");
5052   tmp=_fam_faces;
5053   if(tmp)
5054     (const_cast<DataArrayInt *>(tmp))->setName("");
5055   tmp=_num_faces;
5056   if(tmp)
5057     (const_cast<DataArrayInt *>(tmp))->setName("");
5058 }
5059
5060 /*!
5061  * Returns ids of mesh entities contained in given families of a given dimension.
5062  *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
5063  *          are required.
5064  *  \param [in] fams - the names of the families of interest.
5065  *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
5066  *          returned instead of ids.
5067  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
5068  *          numbers, if available and required, of mesh entities of the families. The caller
5069  *          is to delete this array using decrRef() as it is no more needed. 
5070  *  \throw If the family field is missing for \a meshDimRelToMaxExt.
5071  */
5072 DataArrayInt *MEDFileStructuredMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const
5073 {
5074   std::vector<int> famIds(getFamiliesIds(fams));
5075   switch(meshDimRelToMaxExt)
5076   {
5077     case 1:
5078       {
5079         if((const DataArrayInt *)_fam_nodes)
5080           {
5081             MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
5082             if(!famIds.empty())
5083               da=_fam_nodes->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
5084             else
5085               da=_fam_nodes->getIdsEqualList(0,0);
5086             if(renum)
5087               return MEDFileUMeshSplitL1::Renumber(_num_nodes,da);
5088             else
5089               return da.retn();
5090           }
5091         else
5092           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on nodes !");
5093         break;
5094       }
5095     case 0:
5096       {
5097         if((const DataArrayInt *)_fam_cells)
5098           {
5099             MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
5100             if(!famIds.empty())
5101               da=_fam_cells->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
5102             else
5103               da=_fam_cells->getIdsEqualList(0,0);
5104             if(renum)
5105               return MEDFileUMeshSplitL1::Renumber(_num_cells,da);
5106             else
5107               return da.retn();
5108           }
5109         else
5110           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on cells !");
5111         break;
5112       }
5113     case -1:
5114       {
5115         if((const DataArrayInt *)_fam_faces)
5116           {
5117             MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
5118             if(!famIds.empty())
5119               da=_fam_faces->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
5120             else
5121               da=_fam_faces->getIdsEqualList(0,0);
5122             if(renum)
5123               return MEDFileUMeshSplitL1::Renumber(_num_faces,da);
5124             else
5125               return da.retn();
5126           }
5127         else
5128           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on faces !");
5129         break;
5130       }
5131     default:
5132       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : input meshDimRelative must be in [0,1,-1] !");
5133   }
5134   throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : unmanaged case !");
5135 }
5136
5137 /*!
5138  * Sets the family field of a given relative dimension.
5139  *  \param [in] meshDimRelToMaxExt - the relative dimension of entities for which
5140  *          the family field is set.
5141  *  \param [in] famArr - the array of the family field.
5142  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5143  *  \throw If \a famArr has an invalid size.
5144  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1 and \a meshDimRelToMaxExt != -1.
5145  */
5146 void MEDFileStructuredMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr)
5147 {
5148   const MEDCouplingStructuredMesh *mesh(getStructuredMesh());
5149   if(!mesh)
5150     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setFamilyFieldArr : no structured mesh specified ! Impossible to set family array !");
5151   switch(meshDimRelToMaxExt)
5152   {
5153     case 0:
5154       {
5155         int nbCells=mesh->getNumberOfCells();
5156         famArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of cells of mesh !");
5157         _fam_cells=famArr;
5158         break;
5159       }
5160     case 1:
5161       {
5162         int nbNodes=mesh->getNumberOfNodes();
5163         famArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !");
5164         _fam_nodes=famArr;
5165         break;
5166       }
5167     case -1:
5168       {
5169         int nbCells=mesh->getNumberOfCellsOfSubLevelMesh();
5170         famArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of faces of mesh !");
5171         _fam_faces=famArr;
5172         break;
5173       }
5174     default:
5175       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setFamilyFieldArr : Only available for levels 0 or 1 or -1 !");
5176   }
5177   if(famArr)
5178     famArr->incrRef();
5179 }
5180
5181 /*!
5182  * Sets the optional numbers of mesh entities of a given dimension.
5183  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5184  *  \param [in] renumArr - the array of the numbers.
5185  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5186  *  \throw If \a renumArr has an invalid size.
5187  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
5188  */
5189 void MEDFileStructuredMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr)
5190 {
5191   const MEDCouplingStructuredMesh *mesh=getStructuredMesh();
5192   if(!mesh)
5193     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : no structured mesh specified ! Impossible to set number array !");
5194   switch(meshDimRelToMaxExt)
5195   {
5196     case 0:
5197       {
5198         int nbCells=mesh->getNumberOfCells();
5199         renumArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Renum arr ! Mismatch with number of cells of mesh !");
5200         _num_cells=renumArr;
5201         break;
5202       }
5203     case 1:
5204       {
5205         int nbNodes=mesh->getNumberOfNodes();
5206         renumArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !");
5207         _num_nodes=renumArr;
5208         break;
5209       }
5210     case -1:
5211       {
5212         int nbCells=mesh->getNumberOfCellsOfSubLevelMesh();
5213         renumArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Renum arr ! Mismatch with number of faces of mesh !");
5214         _num_faces=renumArr;
5215         break;
5216       }
5217     default:
5218       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : Only available for levels 0 or 1 or -1 !");
5219   }
5220   if(renumArr)
5221     renumArr->incrRef();
5222 }
5223
5224 /*!
5225  * Sets the optional names of mesh entities of a given dimension.
5226  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5227  *  \param [in] nameArr - the array of the names.
5228  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5229  *  \throw If \a nameArr has an invalid size.
5230  */
5231 void MEDFileStructuredMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr)
5232 {
5233   const MEDCouplingStructuredMesh *mesh(getStructuredMesh());
5234   if(!mesh)
5235     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : no structured mesh specified ! Impossible to set names array !");
5236   switch(meshDimRelToMaxExt)
5237   {
5238     case 0:
5239       {
5240         int nbCells=mesh->getNumberOfCells();
5241         nameArr->checkNbOfTuplesAndComp(nbCells,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of cells of mesh !");
5242         _names_cells=nameArr;
5243         break;
5244       }
5245     case 1:
5246       {
5247         int nbNodes=mesh->getNumberOfNodes();
5248         nameArr->checkNbOfTuplesAndComp(nbNodes,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of nodes of mesh !");
5249         _names_nodes=nameArr;
5250         break;
5251       }
5252     case -1:
5253       {
5254         int nbCells=mesh->getNumberOfCellsOfSubLevelMesh();
5255         nameArr->checkNbOfTuplesAndComp(nbCells,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of faces of mesh !");
5256         _names_cells=nameArr;
5257       }
5258     default:
5259       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : Only available for levels 0 or 1 or -1 !");
5260   }
5261   if(nameArr)
5262     nameArr->incrRef();
5263 }
5264
5265 /*!
5266  * Adds a group of nodes to \a this mesh.
5267  *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
5268  *          The ids should be sorted and different each other (MED file norm).
5269  *
5270  *  \warning this method can alter default "FAMILLE_ZERO" family.
5271  *  For users sensitive to this a call to MEDFileMesh::rearrangeFamilies will be necessary after addGroup session.
5272  *
5273  *  \throw If the node coordinates array is not set.
5274  *  \throw If \a ids == \c NULL.
5275  *  \throw If \a ids->getName() == "".
5276  *  \throw If \a ids does not respect the MED file norm.
5277  *  \throw If a group with name \a ids->getName() already exists.
5278  */
5279 void MEDFileStructuredMesh::addNodeGroup(const DataArrayInt *ids)
5280 {
5281   addGroup(1,ids);
5282 }
5283
5284 /*!
5285  * Adds a group of nodes/cells/faces/edges to \a this mesh.
5286  *
5287  *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
5288  *          The ids should be sorted and different each other (MED file norm).
5289  *
5290  * \warning this method can alter default "FAMILLE_ZERO" family.
5291  * For users sensitive to this a call to MEDFileMesh::rearrangeFamilies will be necessary after addGroup session.
5292  *
5293  *  \throw If the node coordinates array is not set.
5294  *  \throw If \a ids == \c NULL.
5295  *  \throw If \a ids->getName() == "".
5296  *  \throw If \a ids does not respect the MED file norm.
5297  *  \throw If a group with name \a ids->getName() already exists.
5298  */
5299 void MEDFileStructuredMesh::addGroup(int meshDimRelToMaxExt, const DataArrayInt *ids)
5300 {
5301   DataArrayInt *fam(getOrCreateAndGetFamilyFieldAtLevel(meshDimRelToMaxExt));
5302   addGroupUnderground(false,ids,fam);
5303   return ;
5304 }
5305
5306 /*!
5307  * Returns the family field for mesh entities of a given dimension.
5308  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5309  *  \return const DataArrayInt * - the family field. It is an array of ids of families
5310  *          each mesh entity belongs to. It can be \c NULL.
5311  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
5312  */
5313 const DataArrayInt *MEDFileStructuredMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) const
5314 {
5315   switch(meshDimRelToMaxExt)
5316   {
5317     case 0:
5318       return _fam_cells;
5319     case 1:
5320       return _fam_nodes;
5321     case -1:
5322       return _fam_faces;
5323     default:
5324       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamilyFieldAtLevel : Only available for levels 0 or 1 or -1 !");
5325   }
5326 }
5327
5328 /*!
5329  * Returns the family field for mesh entities of a given dimension.
5330  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5331  *  \return const DataArrayInt * - the family field. It is an array of ids of families
5332  *          each mesh entity belongs to. It can be \c NULL.
5333  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
5334  */
5335 DataArrayInt *MEDFileStructuredMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt)
5336 {
5337   switch(meshDimRelToMaxExt)
5338   {
5339     case 0:
5340       return _fam_cells;
5341     case 1:
5342       return _fam_nodes;
5343     case -1:
5344       return _fam_faces;
5345     default:
5346       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamilyFieldAtLevel : Only available for levels 0 or 1 or -1 !");
5347   }
5348 }
5349
5350 /*!
5351  * Returns the optional numbers of mesh entities of a given dimension.
5352  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5353  *  \return const DataArrayInt * - the array of the entity numbers.
5354  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5355  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
5356  */
5357 const DataArrayInt *MEDFileStructuredMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) const
5358 {
5359   switch(meshDimRelToMaxExt)
5360   {
5361     case 0:
5362       return _num_cells;
5363     case 1:
5364       return _num_nodes;
5365     case -1:
5366       return _num_faces;
5367     default:
5368       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberFieldAtLevel : Only available for levels 0 or 1 or -1 !");
5369   }
5370 }
5371
5372 /*!
5373  * Returns the optional numbers of mesh entities of a given dimension transformed using
5374  * DataArrayInt::invertArrayN2O2O2N().
5375  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5376  *  \return const DataArrayInt * - the array of the entity numbers transformed using
5377  *          DataArrayInt::invertArrayN2O2O2N().
5378  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
5379  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5380  */
5381 const DataArrayInt *MEDFileStructuredMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxExt) const
5382 {
5383   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
5384     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getRevNumberFieldAtLevel : Only available for levels 0 or 1 !");
5385   if(meshDimRelToMaxExt==0)
5386     {
5387       if((const DataArrayInt *)_num_cells)
5388         {
5389           int pos;
5390           int maxValue=_num_cells->getMaxValue(pos);
5391           _rev_num_cells=_num_cells->invertArrayN2O2O2N(maxValue+1);
5392           return _rev_num_cells;
5393         }
5394       else
5395         throw INTERP_KERNEL::Exception("MEDFileCMesh::getRevNumberFieldAtLevel : no cell renumbering for a request on reverse numbering !");
5396     }
5397   else
5398     {
5399       if((const DataArrayInt *)_num_nodes)
5400         {
5401           int pos;
5402           int maxValue=_num_nodes->getMaxValue(pos);
5403           _rev_num_nodes=_num_nodes->invertArrayN2O2O2N(maxValue+1);
5404           return _rev_num_nodes;
5405         }
5406       else
5407         throw INTERP_KERNEL::Exception("MEDFileCMesh::getRevNumberFieldAtLevel : no node renumbering for a request on reverse numbering !");
5408     }
5409 }
5410
5411 const DataArrayAsciiChar *MEDFileStructuredMesh::getNameFieldAtLevel(int meshDimRelToMaxExt) const
5412 {
5413   switch(meshDimRelToMaxExt)
5414   {
5415     case 0:
5416       return _names_cells;
5417     case 1:
5418       return _names_nodes;
5419     case -1:
5420       return _names_faces;
5421     default:
5422       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNameFieldAtLevel : Only available for levels 0 or 1 or -1 !");
5423   }
5424 }
5425
5426 /*!
5427  * Returns relative dimensions of mesh entities (excluding nodes) present in \a this mesh.
5428  *  \return std::vector<int> - a sequence of the relative dimensions: [0].
5429  */
5430 std::vector<int> MEDFileStructuredMesh::getNonEmptyLevels() const
5431 {
5432   std::vector<int> ret(1);
5433   return ret;
5434 }
5435
5436 /*!
5437  * Returns relative dimensions of mesh entities (including nodes) present in \a this mesh.
5438  *  \return std::vector<int> - a sequence of the relative dimensions: [1,0].
5439  */
5440 std::vector<int> MEDFileStructuredMesh::getNonEmptyLevelsExt() const
5441 {
5442   std::vector<int> ret(2);
5443   ret[0]=1;
5444   return ret;
5445 }
5446
5447 /*!
5448  * Returns the set of extensive levels (nodes included) where not NULL family arr are defined.
5449  */
5450 std::vector<int> MEDFileStructuredMesh::getFamArrNonEmptyLevelsExt() const
5451 {
5452   std::vector<int> ret;
5453   const DataArrayInt *famNodes(_fam_nodes),*famCells(_fam_cells),*famFaces(_fam_faces);
5454   if(famNodes)
5455     ret.push_back(1);
5456   if(famCells)
5457     ret.push_back(0);
5458   if(famFaces)
5459     ret.push_back(-1);
5460   return ret;
5461 }
5462
5463 /*!
5464  * Returns the set of extensive levels (nodes included) where not NULL numbering arr are defined.
5465  */
5466 std::vector<int> MEDFileStructuredMesh::getNumArrNonEmptyLevelsExt() const
5467 {
5468   std::vector<int> ret;
5469   const DataArrayInt *numNodes(_num_nodes),*numCells(_num_cells),*numFaces(_num_faces);
5470   if(numNodes)
5471     ret.push_back(1);
5472   if(numCells)
5473     ret.push_back(0);
5474   if(numFaces)
5475     ret.push_back(-1);
5476   return ret;
5477 }
5478
5479 /*!
5480  * Returns the set of extensive levels (nodes included) where not NULL naming arr are defined.
5481  */
5482 std::vector<int> MEDFileStructuredMesh::getNameArrNonEmptyLevelsExt() const
5483 {
5484   std::vector<int> ret;
5485   const DataArrayAsciiChar *namesNodes(_names_nodes),*namesCells(_names_cells),*namesFaces(_names_faces);
5486   if(namesNodes)
5487     ret.push_back(1);
5488   if(namesCells)
5489     ret.push_back(0);
5490   if(namesFaces)
5491     ret.push_back(-1);
5492   return ret;
5493 }
5494
5495 /*!
5496  * no implementation here, it is not a bug, but intresically no polyhedra in \a this.
5497  */
5498 bool MEDFileStructuredMesh::unPolyze(std::vector<int>& oldCode, std::vector<int>& newCode, DataArrayInt *& o2nRenumCell)
5499 {
5500   oldCode.clear(); newCode.clear(); o2nRenumCell=0;
5501   return false;
5502 }
5503
5504 void MEDFileStructuredMesh::changeFamilyIdArr(int oldId, int newId)
5505 {
5506   DataArrayInt *arr=_fam_nodes;
5507   if(arr)
5508     arr->changeValue(oldId,newId);
5509   arr=_fam_cells;
5510   if(arr)
5511     arr->changeValue(oldId,newId);
5512   arr=_fam_faces;
5513   if(arr)
5514     arr->changeValue(oldId,newId);
5515 }
5516
5517 std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > MEDFileStructuredMesh::getAllNonNullFamilyIds() const
5518 {
5519   std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret;
5520   const DataArrayInt *da(_fam_nodes);
5521   if(da)
5522     { da->incrRef(); ret.push_back(MEDCouplingAutoRefCountObjectPtr<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
5523   da=_fam_cells;
5524   if(da)
5525     { da->incrRef(); ret.push_back(MEDCouplingAutoRefCountObjectPtr<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
5526   da=_fam_faces;
5527   if(da)
5528     { da->incrRef(); ret.push_back(MEDCouplingAutoRefCountObjectPtr<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
5529   return ret;
5530 }
5531
5532 void MEDFileStructuredMesh::deepCpyAttributes()
5533 {
5534   if((const DataArrayInt*)_fam_nodes)
5535     _fam_nodes=_fam_nodes->deepCpy();
5536   if((const DataArrayInt*)_num_nodes)
5537     _num_nodes=_num_nodes->deepCpy();
5538   if((const DataArrayAsciiChar*)_names_nodes)
5539     _names_nodes=_names_nodes->deepCpy();
5540   if((const DataArrayInt*)_fam_cells)
5541     _fam_cells=_fam_cells->deepCpy();
5542   if((const DataArrayInt*)_num_cells)
5543     _num_cells=_num_cells->deepCpy();
5544   if((const DataArrayAsciiChar*)_names_cells)
5545     _names_cells=_names_cells->deepCpy();
5546   if((const DataArrayInt*)_fam_faces)
5547     _fam_faces=_fam_faces->deepCpy();
5548   if((const DataArrayInt*)_num_faces)
5549     _num_faces=_num_faces->deepCpy();
5550   if((const DataArrayAsciiChar*)_names_faces)
5551     _names_faces=_names_faces->deepCpy();
5552   if((const DataArrayInt*)_rev_num_nodes)
5553     _rev_num_nodes=_rev_num_nodes->deepCpy();
5554   if((const DataArrayInt*)_rev_num_cells)
5555     _rev_num_cells=_rev_num_cells->deepCpy();
5556 }
5557
5558 /*!
5559  * Returns a pointer to mesh at the specified level (here 0 is compulsary for cartesian mesh).
5560  * 
5561  * \return a pointer to cartesian mesh that need to be managed by the caller.
5562  * \warning the returned pointer has to be managed by the caller.
5563  */
5564
5565 /*!
5566  * Returns a pointer to MEDCouplingStructuredMesh held by \a this. 
5567  *  \param [in] meshDimRelToMax - it must be \c 0 or \c -1.
5568  *  \param [in] renum - it must be \c false.
5569  *  \return MEDCouplingMesh * - a pointer to MEDCouplingMesh that the caller is to
5570  *          delete using decrRef() as it is no more needed. 
5571  */
5572 MEDCouplingMesh *MEDFileStructuredMesh::getGenMeshAtLevel(int meshDimRelToMax, bool renum) const
5573 {
5574   if(renum)
5575     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support renumbering ! To do it perform request of renum array directly !");
5576   const MEDCouplingStructuredMesh *m(getStructuredMesh());
5577   switch(meshDimRelToMax)
5578   {
5579     case 0:
5580       {
5581         if(m)
5582           m->incrRef();
5583         return const_cast<MEDCouplingStructuredMesh *>(m);
5584       }
5585     case -1:
5586       {
5587         if(!m)
5588           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGenMeshAtLevel : level -1 requested must be non empty to be able to compute unstructured sub mesh !");
5589         buildMinusOneImplicitPartIfNeeded();
5590         MEDCouplingMesh *ret(_faces_if_necessary);
5591         if(ret)
5592           ret->incrRef();
5593         return ret;
5594       }
5595     default:
5596       throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support multi level for mesh 0 expected as input !");
5597   }
5598 }
5599
5600 /*!
5601  * Returns number of mesh entities of a given relative dimension in \a this mesh.
5602  *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
5603  *  \return int - the number of entities.
5604  *  \throw If no mesh entities of dimension \a meshDimRelToMaxExt are available in \a this mesh.
5605  */
5606 int MEDFileStructuredMesh::getSizeAtLevel(int meshDimRelToMaxExt) const
5607 {
5608   const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
5609   if(!cmesh)
5610     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : No structured mesh set !");
5611   switch(meshDimRelToMaxExt)
5612   {
5613     case 0:
5614       return cmesh->getNumberOfCells();
5615     case 1:
5616       return cmesh->getNumberOfNodes();
5617     case -1:
5618       return cmesh->getNumberOfCellsOfSubLevelMesh();
5619     default:
5620       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : Only available for levels 0 or 1 or -1 !");
5621   }
5622 }
5623
5624 int MEDFileStructuredMesh::getNumberOfNodes() const
5625 {
5626   const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
5627   if(!cmesh)
5628     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberOfNodes : no cartesian mesh set !");
5629   return cmesh->getNumberOfNodes();
5630 }
5631
5632 int MEDFileStructuredMesh::getNumberOfCellsAtLevel(int meshDimRelToMaxExt) const
5633 {
5634   const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
5635   if(!cmesh)
5636     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberOfNodes : no cartesian mesh set !");
5637   switch(meshDimRelToMaxExt)
5638   {
5639     case 0:
5640       return cmesh->getNumberOfCells();
5641     case -1:
5642       return cmesh->getNumberOfCellsOfSubLevelMesh();
5643     default:
5644       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberOfNodes : only meshDimRelToMax=0 and meshDimRelToMax=-1 supported !");
5645     }
5646 }
5647
5648 bool MEDFileStructuredMesh::hasImplicitPart() const
5649 {
5650   return true;
5651 }
5652
5653 /*!
5654  * \sa MEDFileStructuredMesh::getImplicitFaceMesh
5655  */
5656 int MEDFileStructuredMesh::buildImplicitPartIfAny(INTERP_KERNEL::NormalizedCellType gt) const
5657 {
5658   static const char MSG[]="MEDFileStructuredMesh::buildImplicitPartIfAny : the given geo type is not manageable by a structured mesh !";
5659   const MEDCoupling1SGTUMesh *zeFaceMesh(_faces_if_necessary);
5660   if(!zeFaceMesh)
5661     {
5662       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(getMeshDimension())));
5663       if(cm.getReverseExtrudedType()!=gt)
5664         throw INTERP_KERNEL::Exception(MSG);
5665       buildImplicitPart();
5666       return getStructuredMesh()->getNumberOfCellsOfSubLevelMesh();
5667     }
5668   else
5669     {
5670       if(gt!=zeFaceMesh->getCellModelEnum())
5671         throw INTERP_KERNEL::Exception(MSG);
5672       return zeFaceMesh->getNumberOfCells();
5673     }
5674 }
5675
5676 void MEDFileStructuredMesh::buildMinusOneImplicitPartIfNeeded() const
5677 {
5678   const MEDCoupling1SGTUMesh *zeFaceMesh(_faces_if_necessary);
5679   if(!zeFaceMesh)
5680     buildImplicitPart();
5681 }
5682
5683 void MEDFileStructuredMesh::buildImplicitPart() const
5684 {
5685   const MEDCouplingStructuredMesh *mcmesh(getStructuredMesh());
5686   if(!mcmesh)
5687     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::buildImplicitPart : Unable to build the implicit part of structured mesh because no structured mesh at level 0 defined !");
5688   _faces_if_necessary=mcmesh->build1SGTSubLevelMesh();
5689 }
5690
5691 void MEDFileStructuredMesh::releaseImplicitPartIfAny() const
5692 {
5693   _faces_if_necessary=0;
5694 }
5695
5696 /*!
5697  * Retrieves the internal pointer (no decrRef requested) of the implicit face mesh if any.
5698  * To force to build it you can invoke MEDFileStructuredMesh::buildImplicitPartIfAny method.
5699  * 
5700  * \sa MEDFileStructuredMesh::buildImplicitPartIfAny
5701  */
5702 MEDCoupling1SGTUMesh *MEDFileStructuredMesh::getImplicitFaceMesh() const
5703 {
5704   return _faces_if_necessary;
5705 }
5706
5707 std::vector<INTERP_KERNEL::NormalizedCellType> MEDFileStructuredMesh::getGeoTypesAtLevel(int meshDimRelToMax) const
5708 {
5709   const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
5710   if(!cmesh)
5711     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGeoTypesAtLevel : No structured mesh set !");
5712   switch(meshDimRelToMax)
5713   {
5714     case 0:
5715       {
5716         std::vector<INTERP_KERNEL::NormalizedCellType> ret(1,cmesh->getTypeOfCell(0));
5717         return ret;
5718       }
5719     case -1:
5720       {
5721         int mdim(cmesh->getMeshDimension());
5722         if(mdim<1)
5723           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGeoTypesAtLevel : only one level available for structured meshes ! Input 0 is mandatory or 0D mesh !");
5724         std::vector<INTERP_KERNEL::NormalizedCellType> ret(1,MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(mdim-1));
5725         return ret;
5726       }
5727     default:
5728       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGeoTypesAtLevel : only 2 levels available at most : 0 and -1 !");
5729   }
5730 }
5731
5732 int MEDFileStructuredMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType ct) const
5733 {
5734   if(ct!=MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(getMeshDimension()))
5735     return 0;
5736   else
5737     return getNumberOfCellsAtLevel(0);
5738 }
5739
5740 void MEDFileStructuredMesh::whichAreNodesFetched(const MEDFileField1TSStructItem& st, const MEDFileFieldGlobsReal *globs, std::vector<bool>& nodesFetched) const
5741 {
5742   if(st.getNumberOfItems()!=1)
5743     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 !");
5744   if(st[0].getGeo()!=MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(getMeshDimension()))
5745     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : The sturture of field is not lying on expected geo type !");
5746   if(getNumberOfNodes()!=(int)nodesFetched.size())
5747     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : invalid size of array !");
5748   if(st[0].getPflName().empty())
5749     {
5750       std::fill(nodesFetched.begin(),nodesFetched.end(),true);
5751       return ;
5752     }
5753   const DataArrayInt *arr(globs->getProfile(st[0].getPflName()));
5754   const MEDCouplingStructuredMesh *cmesh=getStructuredMesh();//cmesh not null because getNumberOfNodes called before
5755   int sz(nodesFetched.size());
5756   for(const int *work=arr->begin();work!=arr->end();work++)
5757     {
5758       std::vector<int> conn;
5759       cmesh->getNodeIdsOfCell(*work,conn);
5760       for(std::vector<int>::const_iterator it=conn.begin();it!=conn.end();it++)
5761         if(*it>=0 && *it<sz)
5762           nodesFetched[*it]=true;
5763         else
5764           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : internal error !");
5765     }
5766 }
5767
5768 med_geometry_type MEDFileStructuredMesh::GetGeoTypeFromMeshDim(int meshDim)
5769 {
5770   INTERP_KERNEL::NormalizedCellType ct(MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(meshDim));
5771   return typmai3[ct];
5772 }
5773
5774 void MEDFileStructuredMesh::LoadStrMeshDAFromFile(med_idt fid, int meshDim, int dt, int it, const std::string& mName, MEDFileMeshReadSelector *mrs,
5775                                                   MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& famCells, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& numCells, MEDCouplingAutoRefCountObjectPtr<DataArrayAsciiChar>& namesCells)
5776 {
5777   med_bool chgt=MED_FALSE,trsf=MED_FALSE;
5778   med_geometry_type geoTypeReq=MEDFileStructuredMesh::GetGeoTypeFromMeshDim(meshDim);
5779   int nbOfElt(0);
5780   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf);
5781   if(nbOfElt>0)
5782     {
5783       if(!mrs || mrs->isCellFamilyFieldReading())
5784         {
5785           famCells=DataArrayInt::New();
5786           famCells->alloc(nbOfElt,1);
5787           MEDFILESAFECALLERRD0(MEDmeshEntityFamilyNumberRd,(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,famCells->getPointer()));
5788         }
5789     }
5790   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,MED_NUMBER,MED_NODAL,&chgt,&trsf);
5791   if(nbOfElt>0)
5792     {
5793       if(!mrs || mrs->isCellNumFieldReading())
5794         {
5795           numCells=DataArrayInt::New();
5796           numCells->alloc(nbOfElt,1);
5797           MEDFILESAFECALLERRD0(MEDmeshEntityNumberRd,(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,numCells->getPointer()));
5798         }
5799     }
5800   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,MED_NAME,MED_NODAL,&chgt,&trsf);
5801   if(nbOfElt>0)
5802     {
5803       if(!mrs || mrs->isCellNameFieldReading())
5804         {
5805           namesCells=DataArrayAsciiChar::New();
5806           namesCells->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end
5807           MEDFILESAFECALLERRD0(MEDmeshEntityNameRd,(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,namesCells->getPointer()));
5808           namesCells->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end
5809         }
5810     }
5811 }
5812
5813 void MEDFileStructuredMesh::loadStrMeshFromFile(MEDFileStrMeshL2 *strm, med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
5814 {
5815   setName(strm->getName());
5816   setDescription(strm->getDescription());
5817   setUnivName(strm->getUnivName());
5818   setIteration(strm->getIteration());
5819   setOrder(strm->getOrder());
5820   setTimeValue(strm->getTime());
5821   setTimeUnit(strm->getTimeUnit());
5822   MEDFileMeshL2::ReadFamiliesAndGrps(fid,mName,_families,_groups,mrs);
5823   med_bool chgt=MED_FALSE,trsf=MED_FALSE;
5824   int nbOfElt(MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf));
5825   if(nbOfElt>0)
5826     {
5827       if(!mrs || mrs->isNodeFamilyFieldReading())
5828         {
5829           int nbNodes(getNumberOfNodes());
5830           if(nbOfElt>nbNodes)
5831             throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::loadStrMeshFromFile : invalid size of family node array regarding number of nodes in this ! File seems to be corrupted !");
5832           _fam_nodes=DataArrayInt::New();
5833           _fam_nodes->alloc(nbNodes,1);//yes nbNodes and not nbOfElt see next line.
5834           if(nbNodes>nbOfElt)//yes it appends some times... It explains surely the mdump implementation. Bug revealed by PARAVIS EDF #2475 on structured.med file where only 12 first nodes are !=0 so nbOfElt=12 and nbOfNodes=378...
5835             _fam_nodes->fillWithZero();
5836           MEDFILESAFECALLERRD0(MEDmeshEntityFamilyNumberRd,(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,_fam_nodes->getPointer()));
5837         }
5838     }
5839   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_NUMBER,MED_NODAL,&chgt,&trsf);
5840   if(nbOfElt>0)
5841     {
5842       if(!mrs || mrs->isNodeNumFieldReading())
5843         {
5844           _num_nodes=DataArrayInt::New();
5845           _num_nodes->alloc(nbOfElt,1);
5846           MEDFILESAFECALLERRD0(MEDmeshEntityNumberRd,(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,_num_nodes->getPointer()));
5847         }
5848     }
5849   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_NAME,MED_NODAL,&chgt,&trsf);
5850   if(nbOfElt>0)
5851     {
5852       if(!mrs || mrs->isNodeNameFieldReading())
5853         {
5854           _names_nodes=DataArrayAsciiChar::New();
5855           _names_nodes->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end
5856           MEDFILESAFECALLERRD0(MEDmeshEntityNameRd,(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,_names_nodes->getPointer()));
5857           _names_nodes->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end
5858         }
5859     }
5860   int meshDim(getStructuredMesh()->getMeshDimension());
5861   LoadStrMeshDAFromFile(fid,meshDim,dt,it,mName,mrs,_fam_cells,_num_cells,_names_cells);
5862   if(meshDim>=1)
5863     LoadStrMeshDAFromFile(fid,meshDim-1,dt,it,mName,mrs,_fam_faces,_num_faces,_names_faces);
5864 }
5865
5866 void MEDFileStructuredMesh::writeStructuredLL(med_idt fid, const std::string& maa) const
5867 {
5868   int meshDim(getStructuredMesh()->getMeshDimension());
5869   med_geometry_type geoTypeReq(GetGeoTypeFromMeshDim(meshDim)),geoTypeReq2(GetGeoTypeFromMeshDim(meshDim-1));
5870   //
5871   if((const DataArrayInt *)_fam_cells)
5872     MEDFILESAFECALLERWR0(MEDmeshEntityFamilyNumberWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq,_fam_cells->getNumberOfTuples(),_fam_cells->getConstPointer()));
5873   if((const DataArrayInt *)_fam_faces)
5874     MEDFILESAFECALLERWR0(MEDmeshEntityFamilyNumberWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq2,_fam_faces->getNumberOfTuples(),_fam_faces->getConstPointer()));
5875   if((const DataArrayInt *)_fam_nodes)
5876     MEDFILESAFECALLERWR0(MEDmeshEntityFamilyNumberWr,(fid,maa.c_str(),_iteration,_order,MED_NODE,MED_NONE,_fam_nodes->getNumberOfTuples(),_fam_nodes->getConstPointer()));
5877   if((const DataArrayInt *)_num_cells)
5878     MEDFILESAFECALLERWR0(MEDmeshEntityNumberWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq,_num_cells->getNumberOfTuples(),_num_cells->getConstPointer()));
5879   if((const DataArrayInt *)_num_faces)
5880     MEDFILESAFECALLERWR0(MEDmeshEntityNumberWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq2,_num_faces->getNumberOfTuples(),_num_faces->getConstPointer()));
5881   if((const DataArrayInt *)_num_nodes)
5882     MEDFILESAFECALLERWR0(MEDmeshEntityNumberWr,(fid,maa.c_str(),_iteration,_order,MED_NODE,MED_NONE,_num_nodes->getNumberOfTuples(),_num_nodes->getConstPointer()));
5883   if((const DataArrayAsciiChar *)_names_cells)
5884     {
5885       if(_names_cells->getNumberOfComponents()!=MED_SNAME_SIZE)
5886         {
5887           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on cells with number of components set to " << MED_SNAME_SIZE;
5888           oss << " ! The array has " << _names_cells->getNumberOfComponents() << " components !";
5889           throw INTERP_KERNEL::Exception(oss.str().c_str());
5890         }
5891       MEDFILESAFECALLERWR0(MEDmeshEntityNameWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq,_names_cells->getNumberOfTuples(),_names_cells->getConstPointer()));
5892     }
5893   if((const DataArrayAsciiChar *)_names_faces)
5894     {
5895       if(_names_faces->getNumberOfComponents()!=MED_SNAME_SIZE)
5896         {
5897           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on faces with number of components set to " << MED_SNAME_SIZE;
5898           oss << " ! The array has " << _names_faces->getNumberOfComponents() << " components !";
5899           throw INTERP_KERNEL::Exception(oss.str().c_str());
5900         }
5901       MEDFILESAFECALLERWR0(MEDmeshEntityNameWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq2,_names_faces->getNumberOfTuples(),_names_faces->getConstPointer()));
5902     }
5903   if((const DataArrayAsciiChar *)_names_nodes)
5904     {
5905       if(_names_nodes->getNumberOfComponents()!=MED_SNAME_SIZE)
5906         {
5907           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on nodes with number of components set to " << MED_SNAME_SIZE;
5908           oss << " ! The array has " << _names_cells->getNumberOfComponents() << " components !";
5909           throw INTERP_KERNEL::Exception(oss.str().c_str());
5910         }
5911       MEDFILESAFECALLERWR0(MEDmeshEntityNameWr,(fid,maa.c_str(),_iteration,_order,MED_NODE,MED_NONE,_names_nodes->getNumberOfTuples(),_names_nodes->getConstPointer()));
5912     }
5913   //
5914   MEDFileUMeshL2::WriteFamiliesAndGrps(fid,maa.c_str(),_families,_groups,_too_long_str);
5915 }
5916
5917 /*!
5918  * Returns an empty instance of MEDFileCMesh.
5919  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
5920  *          mesh using decrRef() as it is no more needed. 
5921  */
5922 MEDFileCMesh *MEDFileCMesh::New()
5923 {
5924   return new MEDFileCMesh;
5925 }
5926
5927 /*!
5928  * Returns a new MEDFileCMesh holding the mesh data that has been read from a given MED
5929  * file. The first mesh in the file is loaded.
5930  *  \param [in] fileName - the name of MED file to read.
5931  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
5932  *          mesh using decrRef() as it is no more needed. 
5933  *  \throw If the file is not readable.
5934  *  \throw If there is no meshes in the file.
5935  *  \throw If the mesh in the file is not a Cartesian one.
5936  */
5937 MEDFileCMesh *MEDFileCMesh::New(const std::string& fileName, MEDFileMeshReadSelector *mrs)
5938 {
5939   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
5940   if(ms.empty())
5941     {
5942       std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
5943       throw INTERP_KERNEL::Exception(oss.str().c_str());
5944     }
5945   MEDFileUtilities::CheckFileForRead(fileName);
5946   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
5947   int dt,it;
5948   ParaMEDMEM::MEDCouplingMeshType meshType;
5949   std::string dummy2;
5950   MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dt,it,dummy2);
5951   return new MEDFileCMesh(fid,ms.front(),dt,it,mrs);
5952 }
5953
5954 /*!
5955  * Returns a new MEDFileCMesh holding the mesh data that has been read from a given MED
5956  * file. The mesh to load is specified by its name and numbers of a time step and an
5957  * iteration.
5958  *  \param [in] fileName - the name of MED file to read.
5959  *  \param [in] mName - the name of the mesh to read.
5960  *  \param [in] dt - the number of a time step.
5961  *  \param [in] it - the number of an iteration.
5962  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
5963  *          mesh using decrRef() as it is no more needed. 
5964  *  \throw If the file is not readable.
5965  *  \throw If there is no mesh with given attributes in the file.
5966  *  \throw If the mesh in the file is not a Cartesian one.
5967  */
5968 MEDFileCMesh *MEDFileCMesh::New(const std::string& fileName, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
5969 {
5970   MEDFileUtilities::CheckFileForRead(fileName);
5971   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
5972   return new MEDFileCMesh(fid,mName,dt,it,mrs);
5973 }
5974
5975 std::size_t MEDFileCMesh::getHeapMemorySizeWithoutChildren() const
5976 {
5977   return MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren();
5978 }
5979
5980 std::vector<const BigMemoryObject *> MEDFileCMesh::getDirectChildrenWithNull() const
5981 {
5982   std::vector<const BigMemoryObject *> ret(MEDFileStructuredMesh::getDirectChildrenWithNull());
5983   ret.push_back((const MEDCouplingCMesh *)_cmesh);
5984   return ret;
5985 }
5986
5987 /*!
5988  * Returns the dimension on cells in \a this mesh.
5989  *  \return int - the mesh dimension.
5990  *  \throw If there are no cells in this mesh.
5991  */
5992 int MEDFileCMesh::getMeshDimension() const
5993 {
5994   if(!((const MEDCouplingCMesh*)_cmesh))
5995     throw INTERP_KERNEL::Exception("MEDFileCMesh::getMeshDimension : unable to get meshdimension because no mesh set !");
5996   return _cmesh->getMeshDimension();
5997 }
5998
5999 /*!
6000  * Returns the dimension on nodes in \a this mesh.
6001  *  \return int - the space dimension.
6002  *  \throw If there are no cells in this mesh.
6003  */
6004 int MEDFileCMesh::getSpaceDimension() const
6005 {
6006   if(!((const MEDCouplingCMesh*)_cmesh))
6007     throw INTERP_KERNEL::Exception("MEDFileCMesh::getSpaceDimension : unable to get spacedimension because no mesh set !");
6008   return _cmesh->getSpaceDimension();
6009 }
6010
6011 /*!
6012  * Returns a string describing \a this mesh.
6013  *  \return std::string - the mesh information string.
6014  */
6015 std::string MEDFileCMesh::simpleRepr() const
6016 {
6017   return MEDFileStructuredMesh::simpleRepr();
6018 }
6019
6020 /*!
6021  * Returns a full textual description of \a this mesh.
6022  *  \return std::string - the string holding the mesh description.
6023  */
6024 std::string MEDFileCMesh::advancedRepr() const
6025 {
6026   return simpleRepr();
6027 }
6028
6029 MEDFileMesh *MEDFileCMesh::shallowCpy() const
6030 {
6031   MEDCouplingAutoRefCountObjectPtr<MEDFileCMesh> ret=new MEDFileCMesh(*this);
6032   return ret.retn();
6033 }
6034
6035 MEDFileMesh *MEDFileCMesh::createNewEmpty() const
6036 {
6037   return new MEDFileCMesh;
6038 }
6039
6040 MEDFileMesh *MEDFileCMesh::deepCpy() const
6041 {
6042   MEDCouplingAutoRefCountObjectPtr<MEDFileCMesh> ret=new MEDFileCMesh(*this);
6043   ret->deepCpyEquivalences(*this);
6044   if((const MEDCouplingCMesh*)_cmesh)
6045     ret->_cmesh=static_cast<MEDCouplingCMesh*>(_cmesh->deepCpy());
6046   ret->deepCpyAttributes();
6047   return ret.retn();
6048 }
6049
6050 /*!
6051  * Checks if \a this and another mesh are equal.
6052  *  \param [in] other - the mesh to compare with.
6053  *  \param [in] eps - a precision used to compare real values.
6054  *  \param [in,out] what - the string returning description of unequal data.
6055  *  \return bool - \c true if the meshes are equal, \c false, else.
6056  */
6057 bool MEDFileCMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
6058 {
6059   if(!MEDFileStructuredMesh::isEqual(other,eps,what))
6060     return false;
6061   const MEDFileCMesh *otherC=dynamic_cast<const MEDFileCMesh *>(other);
6062   if(!otherC)
6063     {
6064       what="Mesh types differ ! This is cartesian and other is NOT !";
6065       return false;
6066     }
6067   clearNonDiscrAttributes();
6068   otherC->clearNonDiscrAttributes();
6069   const MEDCouplingCMesh *coo1=_cmesh;
6070   const MEDCouplingCMesh *coo2=otherC->_cmesh;
6071   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
6072     {
6073       what="Mismatch of cartesian meshes ! One is defined and not other !";
6074       return false;
6075     }
6076   if(coo1)
6077     {
6078       bool ret=coo1->isEqual(coo2,eps);
6079       if(!ret)
6080         {
6081           what="cartesian meshes differ !";
6082           return false;
6083         }
6084     }
6085   return true;
6086 }
6087
6088 /*!
6089  * Clears redundant attributes of incorporated data arrays.
6090  */
6091 void MEDFileCMesh::clearNonDiscrAttributes() const
6092 {
6093   MEDFileStructuredMesh::clearNonDiscrAttributes();
6094   MEDFileUMeshSplitL1::ClearNonDiscrAttributes(_cmesh);//to it is not a bug umeshsplit have already the method implemented
6095 }
6096
6097 MEDFileCMesh::MEDFileCMesh()
6098 {
6099 }
6100
6101 MEDFileCMesh::MEDFileCMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6102 try
6103 {
6104     loadLLWithAdditionalItems(fid,mName,dt,it,mrs);
6105 }
6106 catch(INTERP_KERNEL::Exception& e)
6107 {
6108     throw e;
6109 }
6110
6111 void MEDFileCMesh::loadLL(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6112 {
6113   ParaMEDMEM::MEDCouplingMeshType meshType;
6114   int dummy0,dummy1;
6115   std::string dtunit;
6116   int mid=MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dtunit);
6117   if(meshType!=CARTESIAN)
6118     {
6119       std::ostringstream oss; oss << "Trying to load as cartesian an existing mesh with name '" << mName << "' that is NOT cartesian !";
6120       throw INTERP_KERNEL::Exception(oss.str().c_str());
6121     }
6122   MEDFileCMeshL2 loaderl2;
6123   loaderl2.loadAll(fid,mid,mName,dt,it);
6124   MEDCouplingCMesh *mesh=loaderl2.getMesh();
6125   mesh->incrRef();
6126   _cmesh=mesh;
6127   loadStrMeshFromFile(&loaderl2,fid,mName,dt,it,mrs);
6128 }
6129
6130 /*!
6131  * Returns a const pointer to MEDCouplingCMesh held by \a this mesh.
6132  *  \return const MEDCouplingCMesh * - a pointer to the held MEDCouplingCMesh.
6133  */
6134 const MEDCouplingCMesh *MEDFileCMesh::getMesh() const
6135 {
6136   synchronizeTinyInfoOnLeaves();
6137   return _cmesh;
6138 }
6139
6140 const MEDCouplingStructuredMesh *MEDFileCMesh::getStructuredMesh() const
6141 {
6142   synchronizeTinyInfoOnLeaves();
6143   return _cmesh;
6144 }
6145
6146 /*!
6147  * Sets the MEDCouplingCMesh holding the data of \a this mesh.
6148  *  \param [in] m - the new MEDCouplingCMesh to refer to.
6149  *  \throw If the name or the description of \a this mesh and \a m are not empty and are
6150  *         different. 
6151  */
6152 void MEDFileCMesh::setMesh(MEDCouplingCMesh *m)
6153 {
6154   dealWithTinyInfo(m);
6155   if(m)
6156     m->incrRef();
6157   _cmesh=m;
6158 }
6159
6160 void MEDFileCMesh::writeLL(med_idt fid) const
6161 {
6162   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
6163   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
6164   INTERP_KERNEL::AutoPtr<char> dtunit=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE);
6165   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
6166   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
6167   MEDLoaderBase::safeStrCpy(_dt_unit.c_str(),MED_LNAME_SIZE,dtunit,_too_long_str);
6168   int spaceDim(_cmesh->getSpaceDimension());
6169   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
6170   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
6171   for(int i=0;i<spaceDim;i++)
6172     {
6173       std::string info(_cmesh->getCoordsAt(i)->getInfoOnComponent(0));
6174       std::string c,u;
6175       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
6176       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
6177       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
6178     }
6179   MEDFILESAFECALLERWR0(MEDmeshCr,(fid,maa,spaceDim,spaceDim,MED_STRUCTURED_MESH,desc,dtunit,MED_SORT_DTIT,MED_CARTESIAN,comp,unit));
6180   if(_univ_wr_status)
6181     MEDFILESAFECALLERWR0(MEDmeshUniversalNameWr,(fid,maa));
6182   MEDFILESAFECALLERWR0(MEDmeshGridTypeWr,(fid,maa,MED_CARTESIAN_GRID));
6183   for(int i=0;i<spaceDim;i++)
6184     {
6185       const DataArrayDouble *da=_cmesh->getCoordsAt(i);
6186       MEDFILESAFECALLERWR0(MEDmeshGridIndexCoordinateWr,(fid,maa,_iteration,_order,_time,i+1,da->getNumberOfTuples(),da->getConstPointer()));
6187     }
6188   //
6189   std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE));
6190   MEDFileStructuredMesh::writeStructuredLL(fid,meshName);
6191 }
6192
6193 void MEDFileCMesh::synchronizeTinyInfoOnLeaves() const
6194 {
6195   const MEDCouplingCMesh *cmesh=_cmesh;
6196   if(!cmesh)
6197     return;
6198   (const_cast<MEDCouplingCMesh *>(cmesh))->setName(_name);
6199   (const_cast<MEDCouplingCMesh *>(cmesh))->setDescription(_desc_name);
6200   (const_cast<MEDCouplingCMesh *>(cmesh))->setTime(_time,_iteration,_order);
6201   (const_cast<MEDCouplingCMesh *>(cmesh))->setTimeUnit(_dt_unit);
6202 }
6203
6204 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New()
6205 {
6206   return new MEDFileCurveLinearMesh;
6207 }
6208
6209 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const std::string& fileName, MEDFileMeshReadSelector *mrs)
6210 {
6211   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
6212   if(ms.empty())
6213     {
6214       std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
6215       throw INTERP_KERNEL::Exception(oss.str().c_str());
6216     }
6217   MEDFileUtilities::CheckFileForRead(fileName);
6218   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
6219   int dt,it;
6220   ParaMEDMEM::MEDCouplingMeshType meshType;
6221   std::string dummy2;
6222   MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dt,it,dummy2);
6223   return new MEDFileCurveLinearMesh(fid,ms.front(),dt,it,mrs);
6224 }
6225
6226 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const std::string& fileName, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6227 {
6228   MEDFileUtilities::CheckFileForRead(fileName);
6229   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
6230   return new MEDFileCurveLinearMesh(fid,mName,dt,it,mrs);
6231 }
6232
6233 std::size_t MEDFileCurveLinearMesh::getHeapMemorySizeWithoutChildren() const
6234 {
6235   return MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren();
6236 }
6237
6238 std::vector<const BigMemoryObject *> MEDFileCurveLinearMesh::getDirectChildrenWithNull() const
6239 {
6240   std::vector<const BigMemoryObject *> ret(MEDFileStructuredMesh::getDirectChildrenWithNull());
6241   ret.push_back((const MEDCouplingCurveLinearMesh *)_clmesh);
6242   return ret;
6243 }
6244
6245 MEDFileMesh *MEDFileCurveLinearMesh::shallowCpy() const
6246 {
6247   MEDCouplingAutoRefCountObjectPtr<MEDFileCurveLinearMesh> ret=new MEDFileCurveLinearMesh(*this);
6248   return ret.retn();
6249 }
6250
6251 MEDFileMesh *MEDFileCurveLinearMesh::createNewEmpty() const
6252 {
6253   return new MEDFileCurveLinearMesh;
6254 }
6255
6256 MEDFileMesh *MEDFileCurveLinearMesh::deepCpy() const
6257 {
6258   MEDCouplingAutoRefCountObjectPtr<MEDFileCurveLinearMesh> ret=new MEDFileCurveLinearMesh(*this);
6259   ret->deepCpyEquivalences(*this);
6260   if((const MEDCouplingCurveLinearMesh*)_clmesh)
6261     ret->_clmesh=static_cast<MEDCouplingCurveLinearMesh*>(_clmesh->deepCpy());
6262   ret->deepCpyAttributes();
6263   return ret.retn();
6264 }
6265
6266 int MEDFileCurveLinearMesh::getMeshDimension() const
6267 {
6268   if(!((const MEDCouplingCurveLinearMesh*)_clmesh))
6269     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::getMeshDimension : unable to get meshdimension because no mesh set !");
6270   return _clmesh->getMeshDimension();
6271 }
6272
6273 std::string MEDFileCurveLinearMesh::simpleRepr() const
6274 {
6275   return MEDFileStructuredMesh::simpleRepr();
6276 }
6277
6278 std::string MEDFileCurveLinearMesh::advancedRepr() const
6279 {
6280   return simpleRepr();
6281 }
6282
6283 bool MEDFileCurveLinearMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
6284 {
6285   if(!MEDFileStructuredMesh::isEqual(other,eps,what))
6286     return false;
6287   const MEDFileCurveLinearMesh *otherC=dynamic_cast<const MEDFileCurveLinearMesh *>(other);
6288   if(!otherC)
6289     {
6290       what="Mesh types differ ! This is curve linear and other is NOT !";
6291       return false;
6292     }
6293   clearNonDiscrAttributes();
6294   otherC->clearNonDiscrAttributes();
6295   const MEDCouplingCurveLinearMesh *coo1=_clmesh;
6296   const MEDCouplingCurveLinearMesh *coo2=otherC->_clmesh;
6297   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
6298     {
6299       what="Mismatch of curve linear meshes ! One is defined and not other !";
6300       return false;
6301     }
6302   if(coo1)
6303     {
6304       bool ret=coo1->isEqual(coo2,eps);
6305       if(!ret)
6306         {
6307           what="curve linear meshes differ !";
6308           return false;
6309         }
6310     }
6311   return true;
6312 }
6313
6314 void MEDFileCurveLinearMesh::clearNonDiscrAttributes() const
6315 {
6316   MEDFileStructuredMesh::clearNonDiscrAttributes();
6317   MEDFileUMeshSplitL1::ClearNonDiscrAttributes(_clmesh);//to it is not a bug umeshsplit have already the method implemented
6318 }
6319
6320 void MEDFileCurveLinearMesh::synchronizeTinyInfoOnLeaves() const
6321 {
6322   const MEDCouplingCurveLinearMesh *clmesh=_clmesh;
6323   if(!clmesh)
6324     return;
6325   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setName(_name);
6326   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setDescription(_desc_name);
6327   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setTime(_time,_iteration,_order);
6328   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setTimeUnit(_dt_unit);
6329 }
6330
6331 const MEDCouplingCurveLinearMesh *MEDFileCurveLinearMesh::getMesh() const
6332 {
6333   synchronizeTinyInfoOnLeaves();
6334   return _clmesh;
6335 }
6336
6337 void MEDFileCurveLinearMesh::setMesh(MEDCouplingCurveLinearMesh *m)
6338 {
6339   dealWithTinyInfo(m);
6340   if(m)
6341     m->incrRef();
6342   _clmesh=m;
6343 }
6344
6345 const MEDCouplingStructuredMesh *MEDFileCurveLinearMesh::getStructuredMesh() const
6346 {
6347   synchronizeTinyInfoOnLeaves();
6348   return _clmesh;
6349 }
6350
6351 MEDFileCurveLinearMesh::MEDFileCurveLinearMesh()
6352 {
6353 }
6354
6355 MEDFileCurveLinearMesh::MEDFileCurveLinearMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6356 try
6357 {
6358     loadLLWithAdditionalItems(fid,mName,dt,it,mrs);
6359 }
6360 catch(INTERP_KERNEL::Exception& e)
6361 {
6362     throw e;
6363 }
6364
6365 void MEDFileCurveLinearMesh::writeLL(med_idt fid) const
6366 {
6367   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
6368   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
6369   INTERP_KERNEL::AutoPtr<char> dtunit=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE);
6370   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
6371   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
6372   MEDLoaderBase::safeStrCpy(_dt_unit.c_str(),MED_LNAME_SIZE,dtunit,_too_long_str);
6373   int spaceDim=_clmesh->getSpaceDimension();
6374   int meshDim=_clmesh->getMeshDimension();
6375   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
6376   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
6377   const DataArrayDouble *coords=_clmesh->getCoords();
6378   if(!coords)
6379     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::writeLL : no coordinates set !");
6380   for(int i=0;i<spaceDim;i++)
6381     {
6382       std::string info(_clmesh->getCoords()->getInfoOnComponent(i));
6383       std::string c,u;
6384       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
6385       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
6386       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
6387     }
6388   MEDFILESAFECALLERWR0(MEDmeshCr,(fid,maa,spaceDim,meshDim,MED_STRUCTURED_MESH,desc,dtunit,MED_SORT_DTIT,MED_CARTESIAN,comp,unit));
6389   if(_univ_wr_status)
6390     MEDFILESAFECALLERWR0(MEDmeshUniversalNameWr,(fid,maa));
6391   MEDFILESAFECALLERWR0(MEDmeshGridTypeWr,(fid,maa,MED_CURVILINEAR_GRID));
6392   std::vector<int> nodeGridSt=_clmesh->getNodeGridStructure();
6393   MEDFILESAFECALLERWR0(MEDmeshGridStructWr,(fid,maa,_iteration,_order,_time,&nodeGridSt[0]));
6394
6395   MEDFILESAFECALLERWR0(MEDmeshNodeCoordinateWr,(fid,maa,_iteration,_order,_time,MED_FULL_INTERLACE,coords->getNumberOfTuples(),coords->begin()));
6396   //
6397   std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE));
6398   MEDFileStructuredMesh::writeStructuredLL(fid,meshName);
6399 }
6400
6401 void MEDFileCurveLinearMesh::loadLL(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6402 {
6403   ParaMEDMEM::MEDCouplingMeshType meshType;
6404   int dummy0,dummy1;
6405   std::string dtunit;
6406   int mid=MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dtunit);
6407   if(meshType!=CURVE_LINEAR)
6408     {
6409       std::ostringstream oss; oss << "Trying to load as curve linear an existing mesh with name '" << mName << "' that is NOT curve linear !";
6410       throw INTERP_KERNEL::Exception(oss.str().c_str());
6411     }
6412   MEDFileCLMeshL2 loaderl2;
6413   loaderl2.loadAll(fid,mid,mName,dt,it);
6414   MEDCouplingCurveLinearMesh *mesh=loaderl2.getMesh();
6415   mesh->incrRef();
6416   _clmesh=mesh;
6417   loadStrMeshFromFile(&loaderl2,fid,mName,dt,it,mrs);
6418 }
6419
6420 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New()
6421 {
6422   return new MEDFileMeshMultiTS;
6423 }
6424
6425 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(const std::string& fileName)
6426 {
6427   return new MEDFileMeshMultiTS(fileName);
6428 }
6429
6430 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(const std::string& fileName, const std::string& mName)
6431 {
6432   return new MEDFileMeshMultiTS(fileName,mName);
6433 }
6434
6435 MEDFileMeshMultiTS *MEDFileMeshMultiTS::deepCpy() const
6436 {
6437   MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> ret=MEDFileMeshMultiTS::New();
6438   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> > meshOneTs(_mesh_one_ts.size());
6439   std::size_t i=0;
6440   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++,i++)
6441     if((const MEDFileMesh *)*it)
6442       meshOneTs[i]=(*it)->deepCpy();
6443   ret->_mesh_one_ts=meshOneTs;
6444   return ret.retn();
6445 }
6446
6447 std::size_t MEDFileMeshMultiTS::getHeapMemorySizeWithoutChildren() const
6448 {
6449   return _mesh_one_ts.capacity()*sizeof(MEDCouplingAutoRefCountObjectPtr<MEDFileMesh>);
6450 }
6451
6452 std::vector<const BigMemoryObject *> MEDFileMeshMultiTS::getDirectChildrenWithNull() const
6453 {
6454   std::vector<const BigMemoryObject *> ret;
6455   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
6456     ret.push_back((const MEDFileMesh *)*it);
6457   return ret;
6458 }
6459
6460 std::string MEDFileMeshMultiTS::getName() const
6461 {
6462   if(_mesh_one_ts.empty())
6463     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::getName : no time steps set !");
6464   return _mesh_one_ts[0]->getName();
6465 }
6466
6467 void MEDFileMeshMultiTS::setName(const std::string& newMeshName)
6468 {
6469   std::string oldName(getName());
6470   std::vector< std::pair<std::string,std::string> > v(1);
6471   v[0].first=oldName; v[0].second=newMeshName;
6472   changeNames(v);
6473 }
6474
6475 bool MEDFileMeshMultiTS::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab)
6476 {
6477   bool ret=false;
6478   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
6479     {
6480       MEDFileMesh *cur(*it);
6481       if(cur)
6482         ret=cur->changeNames(modifTab) || ret;
6483     }
6484   return ret;
6485 }
6486
6487 MEDFileMesh *MEDFileMeshMultiTS::getOneTimeStep() const
6488 {
6489   if(_mesh_one_ts.empty())
6490     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::getOneTimeStep : empty time step set !");
6491   return const_cast<MEDFileMesh *>(static_cast<const MEDFileMesh *>(_mesh_one_ts[0]));
6492 }
6493
6494 void MEDFileMeshMultiTS::setOneTimeStep(MEDFileMesh *mesh1TimeStep)
6495 {
6496   if(!mesh1TimeStep)
6497     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::setOneTimeStep : input pointer should be different from 0 !");
6498   _mesh_one_ts.resize(1);
6499   mesh1TimeStep->incrRef();
6500   //MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> toto=mesh1TimeStep;
6501   _mesh_one_ts[0]=mesh1TimeStep;
6502 }
6503
6504 MEDFileJoints * MEDFileMeshMultiTS::getJoints() const
6505 {
6506   if ( MEDFileMesh* m = getOneTimeStep() )
6507     return m->getJoints();
6508   return 0;
6509 }
6510
6511 /*!
6512  * \brief Set Joints that are common to all time-stamps
6513  */
6514 void MEDFileMeshMultiTS::setJoints( MEDFileJoints* joints )
6515 {
6516   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
6517     {
6518       (*it)->setJoints( joints );
6519     }
6520 }
6521
6522 void MEDFileMeshMultiTS::write(med_idt fid) const
6523 {
6524   MEDFileJoints *joints(getJoints());
6525   bool jointsWritten(false);
6526
6527   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
6528     {
6529       if ( jointsWritten )
6530         const_cast<MEDFileMesh&>(**it).setJoints( 0 );
6531       else
6532         jointsWritten = true;
6533
6534       (*it)->copyOptionsFrom(*this);
6535       (*it)->write(fid);
6536     }
6537
6538   (const_cast<MEDFileMeshMultiTS*>(this))->setJoints( joints ); // restore joints
6539 }
6540
6541 void MEDFileMeshMultiTS::write(const std::string& fileName, int mode) const
6542 {
6543   med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode);
6544   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),medmod);
6545   std::ostringstream oss; oss << "MEDFileMesh : error on attempt to write in file : \"" << fileName << "\""; 
6546   MEDFileUtilities::CheckMEDCode(fid,fid,oss.str());
6547   write(fid);
6548 }
6549
6550 void MEDFileMeshMultiTS::loadFromFile(const std::string& fileName, const std::string& mName)
6551 {
6552   MEDFileJoints* joints = 0;
6553   if ( !_mesh_one_ts.empty() && getOneTimeStep() )
6554     {
6555       // joints of mName already read, pass them to MEDFileMesh::New() to prevent repeated reading
6556       joints = getOneTimeStep()->getJoints();
6557     }
6558
6559   _mesh_one_ts.clear();  //for the moment to be improved
6560   _mesh_one_ts.push_back( MEDFileMesh::New(fileName,mName,-1,-1,0, joints ));
6561 }
6562
6563 MEDFileMeshMultiTS::MEDFileMeshMultiTS()
6564 {
6565 }
6566
6567 MEDFileMeshMultiTS::MEDFileMeshMultiTS(const std::string& fileName)
6568 try
6569 {
6570     std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
6571     if(ms.empty())
6572       {
6573         std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
6574         throw INTERP_KERNEL::Exception(oss.str().c_str());
6575       }
6576     MEDFileUtilities::CheckFileForRead(fileName);
6577     MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
6578     int dt,it;
6579     ParaMEDMEM::MEDCouplingMeshType meshType;
6580     std::string dummy2;
6581     MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dt,it,dummy2);
6582     loadFromFile(fileName,ms.front());
6583 }
6584 catch(INTERP_KERNEL::Exception& e)
6585 {
6586     throw e;
6587 }
6588
6589 MEDFileMeshMultiTS::MEDFileMeshMultiTS(const std::string& fileName, const std::string& mName)
6590 try
6591 {
6592     loadFromFile(fileName,mName);
6593 }
6594 catch(INTERP_KERNEL::Exception& e)
6595 {
6596     throw e;
6597 }
6598
6599 MEDFileMeshes *MEDFileMeshes::New()
6600 {
6601   return new MEDFileMeshes;
6602 }
6603
6604 MEDFileMeshes *MEDFileMeshes::New(const std::string& fileName)
6605 {
6606   return new MEDFileMeshes(fileName);
6607 }
6608
6609 void MEDFileMeshes::write(med_idt fid) const
6610 {
6611   checkCoherency();
6612   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++)
6613     {
6614       (*it)->copyOptionsFrom(*this);
6615       (*it)->write(fid);
6616     }
6617 }
6618
6619 void MEDFileMeshes::write(const std::string& fileName, int mode) const
6620 {
6621   med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode);
6622   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),medmod);
6623   std::ostringstream oss; oss << "MEDFileMesh : error on attempt to write in file : \"" << fileName << "\""; 
6624   MEDFileUtilities::CheckMEDCode(fid,fid,oss.str());
6625   checkCoherency();
6626   write(fid);
6627 }
6628
6629 int MEDFileMeshes::getNumberOfMeshes() const
6630 {
6631   return _meshes.size();
6632 }
6633
6634 MEDFileMeshesIterator *MEDFileMeshes::iterator()
6635 {
6636   return new MEDFileMeshesIterator(this);
6637 }
6638
6639 /** Return a borrowed reference (caller is not responsible) */
6640 MEDFileMesh *MEDFileMeshes::getMeshAtPos(int i) const
6641 {
6642   if(i<0 || i>=(int)_meshes.size())
6643     {
6644       std::ostringstream oss; oss << "MEDFileMeshes::getMeshAtPos : invalid mesh id given in parameter ! Should be in [0;" << _meshes.size() << ") !";
6645       throw INTERP_KERNEL::Exception(oss.str().c_str());
6646     }
6647   return _meshes[i]->getOneTimeStep();
6648 }
6649
6650 /** Return a borrowed reference (caller is not responsible) */
6651 MEDFileMesh *MEDFileMeshes::getMeshWithName(const std::string& mname) const
6652 {
6653   std::vector<std::string> ms=getMeshesNames();
6654   std::vector<std::string>::iterator it=std::find(ms.begin(),ms.end(),mname);
6655   if(it==ms.end())
6656     {
6657       std::ostringstream oss; oss << "MEDFileMeshes::getMeshWithName : Mesh  \"" << mname << "\" does not exist in this ! Existing are : ";
6658       std::copy(ms.begin(),ms.end(),std::ostream_iterator<std::string>(oss," "));
6659       throw INTERP_KERNEL::Exception(oss.str().c_str());
6660     }
6661   return getMeshAtPos((int)std::distance(ms.begin(),it));
6662 }
6663
6664 std::vector<std::string> MEDFileMeshes::getMeshesNames() const
6665 {
6666   std::vector<std::string> ret(_meshes.size());
6667   int i=0;
6668   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
6669     {
6670       const MEDFileMeshMultiTS *f=(*it);
6671       if(f)
6672         {
6673           ret[i]=f->getName();
6674         }
6675       else
6676         {
6677           std::ostringstream oss; oss << "MEDFileMeshes::getMeshesNames : At rank #" << i << " mesh is not defined !";
6678           throw INTERP_KERNEL::Exception(oss.str().c_str());
6679         }
6680     }
6681   return ret;
6682 }
6683 /*const MEDFileJoints* MEDFileMeshes::getJoints() const
6684 {
6685   const MEDFileJoints *ret=_joints;
6686   if(!ret)
6687   {
6688     std::ostringstream oss; oss << "MEDFileMeshes::getJoints : joints is not defined !";
6689     throw INTERP_KERNEL::Exception(oss.str().c_str());
6690   }
6691   return ret;
6692 }*/
6693
6694 bool MEDFileMeshes::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab)
6695 {
6696   bool ret=false;
6697   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::iterator it=_meshes.begin();it!=_meshes.end();it++)
6698     {
6699       MEDFileMeshMultiTS *cur(*it);
6700       if(cur)
6701         ret=cur->changeNames(modifTab) || ret;
6702     }
6703   return ret;
6704 }
6705
6706 void MEDFileMeshes::resize(int newSize)
6707 {
6708   _meshes.resize(newSize);
6709 }
6710
6711 void MEDFileMeshes::pushMesh(MEDFileMesh *mesh)
6712 {
6713   if(!mesh)
6714     throw INTERP_KERNEL::Exception("MEDFileMeshes::pushMesh : invalid input pointer ! should be different from 0 !");
6715   MEDFileMeshMultiTS *elt=MEDFileMeshMultiTS::New();
6716   elt->setOneTimeStep(mesh);
6717   _meshes.push_back(elt);
6718 }
6719
6720 void MEDFileMeshes::setMeshAtPos(int i, MEDFileMesh *mesh)
6721 {
6722   if(!mesh)
6723     throw INTERP_KERNEL::Exception("MEDFileMeshes::setMeshAtPos : invalid input pointer ! should be different from 0 !");
6724   if(i>=(int)_meshes.size())
6725     _meshes.resize(i+1);
6726   MEDFileMeshMultiTS *elt=MEDFileMeshMultiTS::New();
6727   elt->setOneTimeStep(mesh);
6728   _meshes[i]=elt;
6729 }
6730
6731 void MEDFileMeshes::destroyMeshAtPos(int i)
6732 {
6733   if(i<0 || i>=(int)_meshes.size())
6734     {
6735       std::ostringstream oss; oss << "MEDFileMeshes::destroyMeshAtPos : Invalid given id in input (" << i << ") should be in [0," << _meshes.size() << ") !";
6736       throw INTERP_KERNEL::Exception(oss.str().c_str());
6737     }
6738   _meshes.erase(_meshes.begin()+i);
6739 }
6740
6741 void MEDFileMeshes::loadFromFile(const std::string& fileName)
6742 {
6743   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
6744   int i=0;
6745   _meshes.resize(ms.size());
6746   for(std::vector<std::string>::const_iterator it=ms.begin();it!=ms.end();it++,i++)
6747     _meshes[i]=MEDFileMeshMultiTS::New(fileName,(*it));
6748 }
6749
6750 MEDFileMeshes::MEDFileMeshes()
6751 {
6752 }
6753
6754 MEDFileMeshes::MEDFileMeshes(const std::string& fileName)
6755 try
6756 {
6757     loadFromFile(fileName);
6758 }
6759 catch(INTERP_KERNEL::Exception& /*e*/)
6760 {
6761 }
6762
6763 MEDFileMeshes *MEDFileMeshes::deepCpy() const
6764 {
6765   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> > meshes(_meshes.size());
6766   std::size_t i=0;
6767   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
6768     if((const MEDFileMeshMultiTS *)*it)
6769       meshes[i]=(*it)->deepCpy();
6770   MEDCouplingAutoRefCountObjectPtr<MEDFileMeshes> ret=MEDFileMeshes::New();
6771   ret->_meshes=meshes;
6772   return ret.retn();
6773 }
6774
6775 std::size_t MEDFileMeshes::getHeapMemorySizeWithoutChildren() const
6776 {
6777   return _meshes.capacity()*(sizeof(MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS>));
6778 }
6779
6780 std::vector<const BigMemoryObject *> MEDFileMeshes::getDirectChildrenWithNull() const
6781 {
6782   std::vector<const BigMemoryObject *> ret;
6783   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++)
6784     ret.push_back((const MEDFileMeshMultiTS *)*it);
6785   return ret;
6786 }
6787
6788 std::string MEDFileMeshes::simpleRepr() const
6789 {
6790   std::ostringstream oss;
6791   oss << "(*****************)\n(* MEDFileMeshes *)\n(*****************)\n\n";
6792   simpleReprWithoutHeader(oss);
6793   return oss.str();
6794 }
6795
6796 void MEDFileMeshes::simpleReprWithoutHeader(std::ostream& oss) const
6797 {
6798   int nbOfMeshes=getNumberOfMeshes();
6799   oss << "There are " << nbOfMeshes << " meshes with the following names : \n";
6800   std::vector<std::string> mns=getMeshesNames();
6801   for(int i=0;i<nbOfMeshes;i++)
6802     oss << "  - #" << i << " \"" << mns[i] << "\"\n";
6803 }
6804
6805 void MEDFileMeshes::checkCoherency() const
6806 {
6807   static const char MSG[]="MEDFileMeshes::checkCoherency : mesh at rank ";
6808   int i=0;
6809   std::set<std::string> s;
6810   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
6811     {
6812       const MEDFileMeshMultiTS *elt=(*it);
6813       if(!elt)
6814         {
6815           std::ostringstream oss; oss << MSG << i << "/" << _meshes.size() << " is empty !";
6816           throw INTERP_KERNEL::Exception(oss.str().c_str());
6817         }
6818       std::size_t sz=s.size();
6819       s.insert(std::string((*it)->getName()));
6820       if(s.size()==sz)
6821         {
6822           std::ostringstream oss; oss << MSG << i << " has a name (\"" << (*it)->getName() << "\") already used by an another mesh in list !";
6823           throw INTERP_KERNEL::Exception(oss.str().c_str());
6824         }
6825     }
6826 }
6827
6828 MEDFileMeshesIterator::MEDFileMeshesIterator(MEDFileMeshes *ms):_ms(ms),_iter_id(0),_nb_iter(0)
6829 {
6830   if(ms)
6831     {
6832       ms->incrRef();
6833       _nb_iter=ms->getNumberOfMeshes();
6834     }
6835 }
6836
6837 MEDFileMeshesIterator::~MEDFileMeshesIterator()
6838 {
6839 }
6840
6841 MEDFileMesh *MEDFileMeshesIterator::nextt()
6842 {
6843   if(_iter_id<_nb_iter)
6844     {
6845       MEDFileMeshes *ms(_ms);
6846       if(ms)
6847         return ms->getMeshAtPos(_iter_id++);
6848       else
6849         return 0;
6850     }
6851   else
6852     return 0;
6853 }