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