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