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