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