Salome HOME
Implementation of MEDFileUMesh::computeFetchedNodeIds
[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 std::size_t MEDFileUMesh::getHeapMemorySizeWithoutChildren() const
2482 {
2483   std::size_t ret(MEDFileMesh::getHeapMemorySizeWithoutChildren());
2484   ret+=_ms.capacity()*(sizeof(MCAuto<MEDFileUMeshSplitL1>))+_elt_str.capacity()*sizeof(MCAuto<MEDFileEltStruct4Mesh>);
2485   return ret;
2486 }
2487
2488 std::vector<const BigMemoryObject *> MEDFileUMesh::getDirectChildrenWithNull() const
2489 {
2490   std::vector<const BigMemoryObject *> ret(MEDFileMesh::getDirectChildrenWithNull());
2491   ret.push_back((const DataArrayDouble*)_coords);
2492   ret.push_back((const DataArrayIdType *)_fam_coords);
2493   ret.push_back((const DataArrayIdType *)_num_coords);
2494   ret.push_back((const DataArrayIdType *)_global_num_coords);
2495   ret.push_back((const DataArrayIdType *)_rev_num_coords);
2496   ret.push_back((const DataArrayAsciiChar *)_name_coords);
2497   ret.push_back((const PartDefinition *)_part_coords);
2498   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2499     ret.push_back((const MEDFileUMeshSplitL1*) *it);
2500   for(std::vector< MCAuto<MEDFileEltStruct4Mesh> >::const_iterator it=_elt_str.begin();it!=_elt_str.end();it++)
2501     ret.push_back((const MEDFileEltStruct4Mesh *)*it);
2502   return ret;
2503 }
2504
2505 MEDFileUMesh *MEDFileUMesh::shallowCpy() const
2506 {
2507   MCAuto<MEDFileUMesh> ret(new MEDFileUMesh(*this));
2508   return ret.retn();
2509 }
2510
2511 MEDFileMesh *MEDFileUMesh::createNewEmpty() const
2512 {
2513   return new MEDFileUMesh;
2514 }
2515
2516 MEDFileUMesh *MEDFileUMesh::deepCopy() const
2517 {
2518   MCAuto<MEDFileUMesh> ret(new MEDFileUMesh(*this));
2519   ret->deepCpyEquivalences(*this);
2520   if(_coords.isNotNull())
2521     ret->_coords=_coords->deepCopy();
2522   if(_fam_coords.isNotNull())
2523     ret->_fam_coords=_fam_coords->deepCopy();
2524   if(_num_coords.isNotNull())
2525     ret->_num_coords=_num_coords->deepCopy();
2526   if(_global_num_coords.isNotNull())
2527     ret->_global_num_coords=_global_num_coords->deepCopy();
2528   if(_rev_num_coords.isNotNull())
2529     ret->_rev_num_coords=_rev_num_coords->deepCopy();
2530   if(_name_coords.isNotNull())
2531     ret->_name_coords=_name_coords->deepCopy();
2532   std::size_t i=0;
2533   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,i++)
2534     {
2535       if((const MEDFileUMeshSplitL1 *)(*it))
2536         ret->_ms[i]=(*it)->deepCopy(ret->_coords);
2537     }
2538   if((const PartDefinition*)_part_coords)
2539     ret->_part_coords=_part_coords->deepCopy();
2540   return ret.retn();
2541 }
2542
2543 /*!
2544  * Checks if \a this and another mesh are equal.
2545  *  \param [in] other - the mesh to compare with.
2546  *  \param [in] eps - a precision used to compare real values.
2547  *  \param [in,out] what - the string returning description of unequal data.
2548  *  \return bool - \c true if the meshes are equal, \c false, else.
2549  */
2550 bool MEDFileUMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
2551 {
2552   if(!MEDFileMesh::isEqual(other,eps,what))
2553     return false;
2554   const MEDFileUMesh *otherC=dynamic_cast<const MEDFileUMesh *>(other);
2555   if(!otherC)
2556     {
2557       what="Mesh types differ ! This is unstructured and other is NOT !";
2558       return false;
2559     }
2560   clearNonDiscrAttributes();
2561   otherC->clearNonDiscrAttributes();
2562   const DataArrayDouble *coo1=_coords;
2563   const DataArrayDouble *coo2=otherC->_coords;
2564   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
2565     {
2566       what="Mismatch of coordinates ! One is defined and not other !";
2567       return false;
2568     }
2569   if(coo1)
2570     {
2571       bool ret=coo1->isEqual(*coo2,eps);
2572       if(!ret)
2573         {
2574           what="Coords differ !";
2575           return false;
2576         }
2577     }
2578   {
2579     const DataArrayIdType *famc1(_fam_coords),*famc2(otherC->_fam_coords);
2580     if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
2581       {
2582         what="Mismatch of families arr on nodes ! One is defined and not other !";
2583         return false;
2584       }
2585     if(famc1)
2586       {
2587         bool ret=famc1->isEqual(*famc2);
2588         if(!ret)
2589           {
2590             what="Families arr on node differ !";
2591             return false;
2592           }
2593       }
2594   }
2595   {
2596     const DataArrayIdType *numc1(_num_coords),*numc2(otherC->_num_coords);
2597     if((numc1==0 && numc2!=0) || (numc1!=0 && numc2==0))
2598       {
2599         what="Mismatch of numbering arr on nodes ! One is defined and not other !";
2600         return false;
2601       }
2602     if(numc1)
2603       {
2604         bool ret=numc1->isEqual(*numc2);
2605         if(!ret)
2606           {
2607             what="Numbering arr on node differ !";
2608             return false;
2609           }
2610       }
2611   }
2612   {
2613     const DataArrayIdType *gnumc1(_global_num_coords),*gnumc2(otherC->_global_num_coords);
2614     if((gnumc1==0 && gnumc2!=0) || (gnumc1!=0 && gnumc2==0))
2615       {
2616         what="Mismatch of numbering arr on nodes ! One is defined and not other !";
2617         return false;
2618       }
2619     if(gnumc1)
2620       {
2621         bool ret=gnumc1->isEqual(*gnumc2);
2622         if(!ret)
2623           {
2624             what="Global numbering arr on node differ !";
2625             return false;
2626           }
2627       }
2628   }
2629   {
2630     const DataArrayAsciiChar *namec1(_name_coords),*namec2(otherC->_name_coords);
2631     if((namec1==0 && namec2!=0) || (namec1!=0 && namec2==0))
2632       {
2633         what="Mismatch of naming arr on nodes ! One is defined and not other !";
2634         return false;
2635       }
2636     if(namec1)
2637       {
2638         bool ret=namec1->isEqual(*namec2);
2639         if(!ret)
2640           {
2641             what="Names arr on node differ !";
2642             return false;
2643           }
2644       }
2645   }
2646   if(_ms.size()!=otherC->_ms.size())
2647     {
2648       what="Number of levels differs !";
2649       return false;
2650     }
2651   std::size_t sz=_ms.size();
2652   for(std::size_t i=0;i<sz;i++)
2653     {
2654       const MEDFileUMeshSplitL1 *s1=_ms[i];
2655       const MEDFileUMeshSplitL1 *s2=otherC->_ms[i];
2656       if((s1==0 && s2!=0) || (s1!=0 && s2==0))
2657         {
2658           what="Mismatch of presence of sub levels !";
2659           return false;
2660         }
2661       if(s1)
2662         {
2663           bool ret=s1->isEqual(s2,eps,what);
2664           if(!ret)
2665             return false;
2666         }
2667     }
2668   const PartDefinition *pd0(_part_coords),*pd1(otherC->_part_coords);
2669   if(!pd0 && !pd1)
2670     return true;
2671   if((!pd0 && pd1) || (pd0 && !pd1))
2672     {
2673       what=std::string("node part def is defined only for one among this or other !");
2674       return false;
2675     }
2676   return pd0->isEqual(pd1,what);
2677 }
2678
2679 /*!
2680  * Check that the current object MEDFileUMesh is consistent. This does not check the optional renumbering of
2681  * nodes and cells. This last item is important for SMESH, see checkSMESHConsistency().
2682  * \throw if any internal part (i.e. mesh sub-levels and single geometric-type meshes) are inconsistent
2683  * \throw if internal family array is inconsistent
2684  * \sa checkSMESHConsistency()
2685  */
2686 void MEDFileUMesh::checkConsistency() const
2687 {
2688   if(!_coords || !_coords->isAllocated())
2689     {
2690       if(!_ms.size())
2691         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkConsistency(): coords are null but some mesh parts are present!");
2692       if (!_fam_coords)
2693         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkConsistency(): coords are null but not the internal node family array!");
2694       if (_num_coords.isNotNull() || _rev_num_coords.isNotNull() || _global_num_coords.isNotNull())
2695         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkConsistency(): coords are null but not the internal node numbering array!");
2696     }
2697   else
2698     {
2699       mcIdType nbCoo = _coords->getNumberOfTuples();
2700       if (_fam_coords.isNotNull())
2701         _fam_coords->checkNbOfTuplesAndComp(nbCoo,1,"MEDFileUMesh::checkConsistency(): inconsistent internal node family array!");
2702       if (_num_coords.isNotNull())
2703         {
2704           _num_coords->checkNbOfTuplesAndComp(nbCoo,1,"MEDFileUMesh::checkConsistency(): inconsistent internal node numbering array!");
2705           mcIdType pos;
2706           mcIdType maxValue=_num_coords->getMaxValue(pos);
2707           if (!_rev_num_coords || _rev_num_coords->getNumberOfTuples() != (maxValue+1))
2708             throw INTERP_KERNEL::Exception("MEDFileUMesh::checkConsistency(): inconsistent internal revert node numbering array!");
2709         }
2710       if (_global_num_coords.isNotNull())
2711         {
2712           _global_num_coords->checkNbOfTuplesAndComp(nbCoo,1,"MEDFileUMesh::checkConsistency(): inconsistent global node numbering array!");
2713         }
2714       if ((_num_coords && !_rev_num_coords) || (!_num_coords && _rev_num_coords))
2715         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkConsistency(): inconsistent internal numbering arrays (one is null)!");
2716       if (_num_coords && !_num_coords->hasUniqueValues())
2717         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkConsistency(): inconsistent internal node numbering array: duplicates found!");
2718       if (_name_coords)
2719         _name_coords->checkNbOfTuplesAndComp(nbCoo,MED_SNAME_SIZE,"MEDFileUMesh::checkConsistency(): inconsistent internal coord name array!");
2720       // Now sub part check:
2721       for (std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();
2722           it != _ms.end(); it++)
2723         (*it)->checkConsistency();
2724     }
2725 }
2726
2727 /**
2728  * Same as checkConsistency() but also checks that optional entities (edges, faces, volumes) numbers are
2729  * consistent, i.e. the numbering is either set to null for all sub-levels (thus letting SMESH numbers the
2730  * entities as it likes), or non overlapping between all sub-levels.
2731  * \throw if the condition above is not respected
2732  */
2733 void MEDFileUMesh::checkSMESHConsistency() const
2734 {
2735   checkConsistency();
2736   // For all sub-levels, numbering is either always null or with void intersection:
2737   if (_ms.size())
2738     {
2739       std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();
2740       std::vector< const DataArrayIdType * > v;
2741       bool voidOrNot = ((*it)->_num == 0);
2742       for (it++; it != _ms.end(); it++)
2743         if( ((*it)->_num == 0) != voidOrNot )
2744           throw INTERP_KERNEL::Exception("MEDFileUMesh::checkConsistency(): inconsistent numbering between mesh sub-levels!");
2745         else if (!voidOrNot)
2746           v.push_back((*it)->_num);
2747       if (!voidOrNot)
2748         {
2749           // don't forget the 1st one:
2750           v.push_back(_ms[0]->_num);
2751           MCAuto<DataArrayIdType> inter = DataArrayIdType::BuildIntersection(v);
2752           if (inter->getNumberOfTuples())
2753             throw INTERP_KERNEL::Exception("MEDFileUMesh::checkConsistency(): overlapping entity numbering between mesh sub-levels!");
2754         }
2755     }
2756 }
2757
2758 /**
2759  * Reset optional node and cell numbering for all sub levels in this. This particularly useful to make
2760  * sure SMESH will handle the mesh correctly, as it tries to use those numbers if given.
2761  */
2762 void MEDFileUMesh::clearNodeAndCellNumbers()
2763 {
2764   _num_coords.nullify();
2765   _rev_num_coords.nullify();
2766   _global_num_coords.nullify();
2767   for (std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=_ms.begin(); it != _ms.end(); it++)
2768     {
2769       (*it)->_num.nullify();
2770       (*it)->_rev_num.nullify();
2771       (*it)->_global_num.nullify();
2772     }
2773 }
2774
2775 /*!
2776  * Clears redundant attributes of incorporated data arrays.
2777  */
2778 void MEDFileUMesh::clearNonDiscrAttributes() const
2779 {
2780   MEDFileMesh::clearNonDiscrAttributes();
2781   if(_coords.isNotNull())
2782     _coords.iAmATrollConstCast()->setName("");//This parameter is not discriminant for comparison
2783   if(_fam_coords.isNotNull())
2784     _fam_coords.iAmATrollConstCast()->setName("");//This parameter is not discriminant for comparison
2785   if(_num_coords.isNotNull())
2786     _num_coords.iAmATrollConstCast()->setName("");//This parameter is not discriminant for comparison
2787   if(_name_coords.isNotNull())
2788     _name_coords.iAmATrollConstCast()->setName("");//This parameter is not discriminant for comparison
2789   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2790     {
2791       if((*it).isNotNull())
2792         (*it)->clearNonDiscrAttributes();
2793     }
2794 }
2795
2796 void MEDFileUMesh::setName(const std::string& name)
2797 {
2798   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
2799     if((*it).isNotNull())
2800       (*it)->setName(name);
2801   MEDFileMesh::setName(name);
2802 }
2803
2804 MEDFileUMesh::MEDFileUMesh()
2805 {
2806 }
2807
2808 MEDFileUMesh::MEDFileUMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
2809 try
2810 {
2811     loadLLWithAdditionalItems(fid,mName,dt,it,mrs);
2812 }
2813 catch(INTERP_KERNEL::Exception& e)
2814 {
2815     throw e;
2816 }
2817
2818 /*!
2819  * This method loads only a part of specified cells (given by range of cell ID per geometric type)
2820  * See MEDFileUMesh::LoadPartOf for detailed description.
2821  *
2822  * \sa loadLL
2823  */
2824 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)
2825 {
2826   MEDFileUMeshL2 loaderl2;
2827   MEDCoupling::MEDCouplingMeshType meshType;
2828   int dummy0,dummy1;
2829   std::string dummy2;
2830   MEDCoupling::MEDCouplingAxisType dummy3;
2831   INTERP_KERNEL::AutoCppPtr<MeshOrStructMeshCls> mid(MEDFileUMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy3,dummy0,dummy1,dummy2));
2832   if(meshType!=UNSTRUCTURED)
2833     {
2834       std::ostringstream oss; oss << "loadPartUMeshFromFile : Trying to load as unstructured an existing mesh with name '" << mName << "' !";
2835       throw INTERP_KERNEL::Exception(oss.str().c_str());
2836     }
2837   loaderl2.loadPart(fid,mid,mName,types,slicPerTyp,dt,it,mrs);
2838   dispatchLoadedPart(fid,loaderl2,mName,mrs);
2839 }
2840
2841 /*!
2842  * \brief Write joints in a file
2843  */
2844 void MEDFileMesh::writeJoints(med_idt fid) const
2845 {
2846   if ( _joints.isNotNull() )
2847     _joints->writeLL(fid);
2848 }
2849
2850 /*!
2851  * \brief Load joints in a file or use provided ones
2852  */
2853 //================================================================================
2854 /*!
2855  * \brief Load joints in a file or use provided ones
2856  *  \param [in] fid - MED file descriptor
2857  *  \param [in] toUseInstedOfReading - optional joints to use instead of reading,
2858  *          Usually this joints are those just read by another iteration
2859  *          of namesake mesh, when this method is called by MEDFileMeshMultiTS::New()
2860  */
2861 //================================================================================
2862
2863 void MEDFileMesh::loadJointsFromFile(med_idt fid, MEDFileJoints* toUseInstedOfReading)
2864 {
2865   if ( toUseInstedOfReading )
2866     setJoints( toUseInstedOfReading );
2867   else
2868     _joints = MEDFileJoints::New( fid, _name );
2869 }
2870
2871 void MEDFileMesh::loadEquivalences(med_idt fid)
2872 {
2873   int nbOfEq(MEDFileEquivalences::PresenceOfEquivalences(fid,_name));
2874   if(nbOfEq>0)
2875     _equiv=MEDFileEquivalences::Load(fid,nbOfEq,this);
2876 }
2877
2878 void MEDFileMesh::deepCpyEquivalences(const MEDFileMesh& other)
2879 {
2880   const MEDFileEquivalences *equiv(other._equiv);
2881   if(equiv)
2882     _equiv=equiv->deepCopy(this);
2883 }
2884
2885 bool MEDFileMesh::areEquivalencesEqual(const MEDFileMesh *other, std::string& what) const
2886 {
2887   const MEDFileEquivalences *thisEq(_equiv),*otherEq(other->_equiv);
2888   if(!thisEq && !otherEq)
2889     return true;
2890   if(thisEq && otherEq)
2891     return thisEq->isEqual(otherEq,what);
2892   else
2893     {
2894       what+="Equivalence differs : defined in this and not in other (or reversely) !";
2895       return false;
2896     }
2897 }
2898
2899 void MEDFileMesh::getEquivalencesRepr(std::ostream& oss) const
2900 {
2901   const MEDFileEquivalences *equiv(_equiv);
2902   if(!equiv)
2903     return ;
2904   oss << "(******************************)\n(* EQUIVALENCES OF THE MESH : *)\n(******************************)\n";
2905   _equiv->getRepr(oss);
2906 }
2907
2908 void MEDFileMesh::checkCartesian() const
2909 {
2910   if(getAxisType()!=AX_CART)
2911     {
2912       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()) << ").";
2913       oss << std::endl << "To perform operation you have two possibilities :" << std::endl;
2914       oss << " - call setAxisType(AX_CART)" << std::endl;
2915       oss << " - call cartesianize()";
2916       throw INTERP_KERNEL::Exception(oss.str().c_str());
2917     }
2918 }
2919
2920 /*!
2921  * \brief Return number of joints, which is equal to number of adjacent mesh domains
2922  */
2923 int MEDFileMesh::getNumberOfJoints() const
2924 {
2925   return ( (const MEDFileJoints *) _joints ) ? _joints->getNumberOfJoints() : 0;
2926 }
2927
2928 /*!
2929  * \brief Return joints with all adjacent mesh domains
2930  */
2931 MEDFileJoints * MEDFileMesh::getJoints() const
2932 {
2933   return const_cast<MEDFileJoints*>(& (*_joints));
2934 }
2935
2936 void MEDFileMesh::setJoints( MEDFileJoints* joints )
2937 {
2938   if ( joints != _joints )
2939     {
2940       _joints = joints;
2941       if ( joints )
2942         joints->incrRef();
2943     }
2944 }
2945
2946 /*!
2947  * This method loads \b all \b the \b mesh \a mName in the file with \a fid descriptor.
2948  *
2949  * \sa loadPartUMeshFromFile
2950  */
2951 void MEDFileUMesh::loadLL(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
2952 {
2953   MEDFileUMeshL2 loaderl2;
2954   MEDCoupling::MEDCouplingMeshType meshType;
2955   int dummy0,dummy1;
2956   std::string dummy2;
2957   MEDCoupling::MEDCouplingAxisType axType;
2958   INTERP_KERNEL::AutoCppPtr<MeshOrStructMeshCls> mid(MEDFileUMeshL2::GetMeshIdFromName(fid,mName,meshType,axType,dummy0,dummy1,dummy2));
2959   setAxisType(axType);
2960   if(meshType!=UNSTRUCTURED)
2961     {
2962       std::ostringstream oss; oss << "Trying to load as unstructured an existing mesh with name '" << mName << "' !";
2963       throw INTERP_KERNEL::Exception(oss.str().c_str());
2964     }
2965   loaderl2.loadAll(fid,mid,mName,dt,it,mrs);
2966   dispatchLoadedPart(fid,loaderl2,mName,mrs);
2967   // Structure element part...
2968   med_int nModels(-1);
2969   {
2970     med_bool chgt=MED_FALSE,trsf=MED_FALSE;
2971     nModels=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_STRUCT_ELEMENT,MED_GEO_ALL,MED_CONNECTIVITY,MED_NODAL,&chgt,&trsf);
2972   }
2973   if(nModels<=0)
2974     return ;
2975   _elt_str.resize(nModels);
2976   for(int i=0;i<nModels;i++)
2977     _elt_str[i]=MEDFileEltStruct4Mesh::New(fid,mName,dt,it,i,mrs);
2978 }
2979
2980 void MEDFileUMesh::dispatchLoadedPart(med_idt fid, const MEDFileUMeshL2& loaderl2, const std::string& mName, MEDFileMeshReadSelector *mrs)
2981 {
2982   int lev=loaderl2.getNumberOfLevels();
2983   _ms.resize(lev);
2984   for(int i=0;i<lev;i++)
2985     {
2986       if(!loaderl2.emptyLev(i))
2987         _ms[i]=new MEDFileUMeshSplitL1(loaderl2,mName,i);
2988       else
2989         _ms[i]=0;
2990     }
2991   MEDFileMeshL2::ReadFamiliesAndGrps(fid,mName,_families,_groups,mrs);
2992   //
2993   setName(loaderl2.getName());
2994   setDescription(loaderl2.getDescription());
2995   setUnivName(loaderl2.getUnivName());
2996   setIteration(loaderl2.getIteration());
2997   setOrder(loaderl2.getOrder());
2998   setTimeValue(loaderl2.getTime());
2999   setTimeUnit(loaderl2.getTimeUnit());
3000   _coords=loaderl2.getCoords();
3001   if(!mrs || mrs->isNodeFamilyFieldReading())
3002     _fam_coords=loaderl2.getCoordsFamily();
3003   if(!mrs || mrs->isNodeNumFieldReading())
3004     _num_coords=loaderl2.getCoordsNum();
3005   if(!mrs || mrs->isNodeNameFieldReading())
3006     _name_coords=loaderl2.getCoordsName();
3007   if(!mrs || mrs->isGlobalNodeNumFieldReading())
3008     _global_num_coords=loaderl2.getCoordsGlobalNum();
3009   _part_coords=loaderl2.getPartDefOfCoo();
3010   computeRevNum();
3011 }
3012
3013 MEDFileUMesh::~MEDFileUMesh()
3014 {
3015 }
3016
3017 void MEDFileUMesh::writeMeshLL(med_idt fid) const
3018 {
3019   const DataArrayDouble *coo=_coords;
3020   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
3021   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
3022   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
3023   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
3024   int spaceDim=(int)(coo?coo->getNumberOfComponents():0);
3025   int mdim(0);
3026   if(!_ms.empty())
3027     mdim=getMeshDimension();
3028   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
3029   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
3030   for(int i=0;i<spaceDim;i++)
3031     {
3032       std::string info=coo->getInfoOnComponent(i);
3033       std::string c,u;
3034       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
3035       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
3036       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
3037     }
3038   MEDFILESAFECALLERWR0(MEDmeshCr,(fid,maa,spaceDim,mdim,MED_UNSTRUCTURED_MESH,desc,"",MED_SORT_DTIT,MEDFileMeshL2::TraduceAxisTypeRev(getAxisType()),comp,unit));
3039   if(_univ_wr_status)
3040     MEDFILESAFECALLERWR0(MEDmeshUniversalNameWr,(fid,maa));
3041   std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE));
3042   MEDFileUMeshL2::WriteCoords(fid,meshName,_iteration,_order,_time,_coords,_fam_coords,_num_coords,_name_coords,_global_num_coords);
3043   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
3044     if((const MEDFileUMeshSplitL1 *)(*it)!=0)
3045       (*it)->write(fid,meshName,mdim);
3046   MEDFileUMeshL2::WriteFamiliesAndGrps(fid,meshName,_families,_groups,_too_long_str);
3047 }
3048
3049 /*!
3050  * Returns relative dimensions of mesh entities (excluding nodes) present in \a this mesh.
3051  *  \return std::vector<int> - a sequence of the relative dimensions.
3052  */
3053 std::vector<int> MEDFileUMesh::getNonEmptyLevels() const
3054 {
3055   std::vector<int> ret;
3056   int lev=0;
3057   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
3058     if((const MEDFileUMeshSplitL1 *)(*it)!=0)
3059       if(!(*it)->empty())
3060         ret.push_back(lev);
3061   return ret;
3062 }
3063
3064 /*!
3065  * Returns relative dimensions of mesh entities (including nodes) present in \a this mesh.
3066  *  \return std::vector<int> - a sequence of the relative dimensions.
3067  */
3068 std::vector<int> MEDFileUMesh::getNonEmptyLevelsExt() const
3069 {
3070   std::vector<int> ret0=getNonEmptyLevels();
3071   if((const DataArrayDouble *) _coords)
3072     {
3073       std::vector<int> ret(ret0.size()+1);
3074       ret[0]=1;
3075       std::copy(ret0.begin(),ret0.end(),ret.begin()+1);
3076       return ret;
3077     }
3078   return ret0;
3079 }
3080
3081 std::vector<int> MEDFileUMesh::getFamArrNonEmptyLevelsExt() const
3082 {
3083   std::vector<int> ret;
3084   const DataArrayIdType *famCoo(_fam_coords);
3085   if(famCoo)
3086     ret.push_back(1);
3087   int lev=0;
3088   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
3089     {
3090       const MEDFileUMeshSplitL1 *cur(*it);
3091       if(cur)
3092         if(cur->getFamilyField())
3093           ret.push_back(lev);
3094     }
3095   return ret;
3096 }
3097
3098 std::vector<int> MEDFileUMesh::getNumArrNonEmptyLevelsExt() const
3099 {
3100   std::vector<int> ret;
3101   if(_num_coords.isNotNull())
3102     ret.push_back(1);
3103   int lev=0;
3104   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
3105     {
3106       const MEDFileUMeshSplitL1 *cur(*it);
3107       if(cur)
3108         if(cur->getNumberField())
3109           ret.push_back(lev);
3110     }
3111   return ret;
3112 }
3113
3114 std::vector<int> MEDFileUMesh::getNameArrNonEmptyLevelsExt() const
3115 {
3116   std::vector<int> ret;
3117   const DataArrayAsciiChar *nameCoo(_name_coords);
3118   if(nameCoo)
3119     ret.push_back(1);
3120   int lev=0;
3121   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
3122     {
3123       const MEDFileUMeshSplitL1 *cur(*it);
3124       if(cur)
3125         if(cur->getNameField())
3126           ret.push_back(lev);
3127     }
3128   return ret;
3129 }
3130
3131 /*!
3132  * Returns all relative mesh levels (**excluding nodes**) where given families are defined.
3133  * To include nodes, call getFamsNonEmptyLevelsExt() method.
3134  *  \param [in] fams - the name of the family of interest.
3135  *  \return std::vector<int> - a sequence of the relative dimensions.
3136  */
3137 std::vector<mcIdType> MEDFileUMesh::getFamsNonEmptyLevels(const std::vector<std::string>& fams) const
3138 {
3139   std::vector<mcIdType> ret;
3140   std::vector<int> levs(getNonEmptyLevels());
3141   std::vector<mcIdType> famIds(getFamiliesIds(fams));
3142   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
3143     if(_ms[-(*it)]->presenceOfOneFams(famIds))
3144       ret.push_back(*it);
3145   return ret;
3146 }
3147
3148 /*!
3149  * Returns all relative mesh levels (including nodes) where given families are defined.
3150  *  \param [in] fams - the names of the families of interest.
3151  *  \return std::vector<int> - a sequence of the relative dimensions.
3152  */
3153 std::vector<mcIdType> MEDFileUMesh::getFamsNonEmptyLevelsExt(const std::vector<std::string>& fams) const
3154 {
3155   std::vector<mcIdType> ret0(getFamsNonEmptyLevels(fams));
3156   const DataArrayIdType *famCoords(_fam_coords);
3157   if(!famCoords)
3158     return ret0;
3159   std::vector<mcIdType> famIds(getFamiliesIds(fams));
3160   if(famCoords->presenceOfValue(famIds))
3161     {
3162       std::vector<mcIdType> ret(ret0.size()+1);
3163       ret[0]=1;
3164       std::copy(ret0.begin(),ret0.end(),ret.begin()+1);
3165       return ret;
3166     }
3167   else
3168     return ret0;
3169 }
3170
3171 mcIdType MEDFileUMesh::getMaxAbsFamilyIdInArrays() const
3172 {
3173   mcIdType ret=-std::numeric_limits<mcIdType>::max(),tmp=-1;
3174   if((const DataArrayIdType *)_fam_coords)
3175     {
3176       mcIdType val=_fam_coords->getMaxValue(tmp);
3177       ret=std::max(ret,std::abs(val));
3178     }
3179   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
3180     {
3181       if((const MEDFileUMeshSplitL1 *)(*it))
3182         {
3183           const DataArrayIdType *da=(*it)->getFamilyField();
3184           if(da)
3185             {
3186               mcIdType val=da->getMaxValue(tmp);
3187               ret=std::max(ret,std::abs(val));
3188             }
3189         }
3190     }
3191   return ret;
3192 }
3193
3194 mcIdType MEDFileUMesh::getMaxFamilyIdInArrays() const
3195 {
3196   mcIdType ret=-std::numeric_limits<mcIdType>::max(),tmp=-1;
3197   if((const DataArrayIdType *)_fam_coords)
3198     {
3199       mcIdType val=_fam_coords->getMaxValue(tmp);
3200       ret=std::max(ret,val);
3201     }
3202   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
3203     {
3204       if((const MEDFileUMeshSplitL1 *)(*it))
3205         {
3206           const DataArrayIdType *da=(*it)->getFamilyField();
3207           if(da)
3208             {
3209               mcIdType val=da->getMaxValue(tmp);
3210               ret=std::max(ret,val);
3211             }
3212         }
3213     }
3214   return ret;
3215 }
3216
3217 mcIdType MEDFileUMesh::getMinFamilyIdInArrays() const
3218 {
3219   mcIdType ret=std::numeric_limits<mcIdType>::max(),tmp=-1;
3220   if((const DataArrayIdType *)_fam_coords)
3221     {
3222       mcIdType val=_fam_coords->getMinValue(tmp);
3223       ret=std::min(ret,val);
3224     }
3225   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
3226     {
3227       if((const MEDFileUMeshSplitL1 *)(*it))
3228         {
3229           const DataArrayIdType *da=(*it)->getFamilyField();
3230           if(da)
3231             {
3232               mcIdType val=da->getMinValue(tmp);
3233               ret=std::min(ret,val);
3234             }
3235         }
3236     }
3237   return ret;
3238 }
3239
3240 /*!
3241  * Returns the dimension on cells in \a this mesh.
3242  *  \return int - the mesh dimension.
3243  *  \throw If there are no cells in this mesh.
3244  */
3245 int MEDFileUMesh::getMeshDimension() const
3246 {
3247   int lev=0;
3248   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev++)
3249     if((const MEDFileUMeshSplitL1 *)(*it)!=0)
3250       return (*it)->getMeshDimension()+lev;
3251   throw INTERP_KERNEL::Exception("MEDFileUMesh::getMeshDimension : impossible to find a mesh dimension !");
3252 }
3253
3254 /*!
3255  * Returns the space dimension of \a this mesh that is equal to number of components in
3256  * the node coordinates array.
3257  *  \return int - the space dimension of \a this mesh.
3258  *  \throw If the node coordinates array is not available.
3259  */
3260 int MEDFileUMesh::getSpaceDimension() const
3261 {
3262   const DataArrayDouble *coo=_coords;
3263   if(!coo)
3264     throw INTERP_KERNEL::Exception(" MEDFileUMesh::getSpaceDimension : no coords set !");
3265   return (int)coo->getNumberOfComponents();
3266 }
3267
3268 /*!
3269  * Returns a string describing \a this mesh.
3270  *  \return std::string - the mesh information string.
3271  */
3272 std::string MEDFileUMesh::simpleRepr() const
3273 {
3274   std::ostringstream oss;
3275   oss << MEDFileMesh::simpleRepr();
3276   const DataArrayDouble *coo=_coords;
3277   oss << "- The dimension of the space is ";
3278   static const char MSG1[]= "*** NO COORDS SET ***";
3279   static const char MSG2[]= "*** NO CONNECTIVITY SET FOR THIS LEVEL***";
3280   if(coo)
3281     oss << _coords->getNumberOfComponents() << std::endl;
3282   else
3283     oss << MSG1 << std::endl;
3284   oss << "- Type of the mesh : UNSTRUCTURED\n";
3285   oss << "- Number of nodes : ";
3286   if(coo)
3287     oss << _coords->getNumberOfTuples() << std::endl;
3288   else
3289     oss << MSG1 << std::endl;
3290   std::size_t nbOfLev=_ms.size();
3291   oss << "- Number of levels allocated : " << nbOfLev << std::endl;
3292   for(std::size_t i=0;i<nbOfLev;i++)
3293     {
3294       const MEDFileUMeshSplitL1 *lev=_ms[i];
3295       oss << "  - Level #" << -((int) i) << " has dimension : ";
3296       if(lev)
3297         {
3298           oss << lev->getMeshDimension() << std::endl;
3299           lev->simpleRepr(oss);
3300         }
3301       else
3302         oss << MSG2 << std::endl;
3303     }
3304   oss << "- Number of families : " << _families.size() << std::endl << std::endl;
3305   if(coo)
3306     {
3307       oss << "(***********************)\n(* NODES OF THE MESH : *)\n(***********************)\n";
3308       oss << "- Names of coordinates :" << std::endl;
3309       std::vector<std::string> vars=coo->getVarsOnComponent();
3310       std::copy(vars.begin(),vars.end(),std::ostream_iterator<std::string>(oss," "));
3311       oss << std::endl << "- Units of coordinates : " << std::endl;
3312       std::vector<std::string> units=coo->getUnitsOnComponent();
3313       std::copy(units.begin(),units.end(),std::ostream_iterator<std::string>(oss," "));
3314     }
3315   oss << std::endl << std::endl;
3316   getFamilyRepr(oss);
3317   getEquivalencesRepr(oss);
3318   return oss.str();
3319 }
3320
3321 /*!
3322  * Returns a full textual description of \a this mesh.
3323  *  \return std::string - the string holding the mesh description.
3324  */
3325 std::string MEDFileUMesh::advancedRepr() const
3326 {
3327   return simpleRepr();
3328 }
3329
3330 /*!
3331  * Returns number of mesh entities of a given relative dimension in \a this mesh.
3332  *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
3333  *  \return mcIdType - the number of entities.
3334  *  \throw If no mesh entities of dimension \a meshDimRelToMaxExt are available in \a this mesh.
3335  */
3336 mcIdType MEDFileUMesh::getSizeAtLevel(int meshDimRelToMaxExt) const
3337 {
3338   if(meshDimRelToMaxExt==1)
3339     {
3340       if(!((const DataArrayDouble *)_coords))
3341         throw INTERP_KERNEL::Exception("MEDFileUMesh::getSizeAtLevel : no coordinates specified !");
3342       return _coords->getNumberOfTuples();
3343     }
3344   return getMeshAtLevSafe(meshDimRelToMaxExt)->getSize();
3345 }
3346
3347 /*!
3348  * Returns the family field for mesh entities of a given dimension.
3349  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
3350  *  \return const DataArrayIdType * - the family field. It is an array of ids of families
3351  *          each mesh entity belongs to. It can be \c NULL.
3352  */
3353 const DataArrayIdType *MEDFileUMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) const
3354 {
3355   if(meshDimRelToMaxExt==1)
3356     return _fam_coords;
3357   const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMaxExt));
3358   return l1->getFamilyField();
3359 }
3360
3361 DataArrayIdType *MEDFileUMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt)
3362 {
3363   if(meshDimRelToMaxExt==1)
3364     return _fam_coords;
3365   MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMaxExt));
3366   return l1->getFamilyField();
3367 }
3368
3369 /*!
3370  * Returns the optional numbers of mesh entities of a given dimension.
3371  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
3372  *  \return const DataArrayIdType * - the array of the entity numbers.
3373  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3374  */
3375 const DataArrayIdType *MEDFileUMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) const
3376 {
3377   if(meshDimRelToMaxExt==1)
3378     return _num_coords;
3379   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3380   return l1->getNumberField();
3381 }
3382
3383 const DataArrayAsciiChar *MEDFileUMesh::getNameFieldAtLevel(int meshDimRelToMaxExt) const
3384 {
3385   if(meshDimRelToMaxExt==1)
3386     return _name_coords;
3387   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3388   return l1->getNameField();
3389 }
3390
3391 MCAuto<DataArrayIdType> MEDFileUMesh::getGlobalNumFieldAtLevel(int meshDimRelToMaxExt) const
3392 {
3393   if(meshDimRelToMaxExt!=1)
3394     throw INTERP_KERNEL::Exception("MEDFileUMesh::getGlobalNumFieldAtLevel : not implemented yet for structured mesh !");
3395   return _global_num_coords;
3396 }
3397
3398 /*!
3399  * 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).
3400  *
3401  * \param [in] meshDimRelToMaxExt - the extended relative level for which the part definition is requested.
3402  * \param [in] gt - The input geometric type for which the part definition is requested.
3403  * \return the part definition owned by \a this. So no need to deallocate the returned instance.
3404  */
3405 const PartDefinition *MEDFileUMesh::getPartDefAtLevel(int meshDimRelToMaxExt, INTERP_KERNEL::NormalizedCellType gt) const
3406 {
3407   if(meshDimRelToMaxExt==1)
3408     return _part_coords;
3409   const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMaxExt));
3410   return l1->getPartDef(gt);
3411 }
3412
3413 mcIdType MEDFileUMesh::getNumberOfNodes() const
3414 {
3415   const DataArrayDouble *coo(_coords);
3416   if(!coo)
3417     throw INTERP_KERNEL::Exception(" MEDFileUMesh::getNumberOfNodes : no coords set !");
3418   return coo->getNumberOfTuples();
3419 }
3420
3421 mcIdType MEDFileUMesh::getNumberOfCellsAtLevel(int meshDimRelToMaxExt) const
3422 {
3423   const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMaxExt));
3424   return l1->getNumberOfCells();
3425 }
3426
3427 bool MEDFileUMesh::hasImplicitPart() const
3428 {
3429   return false;
3430 }
3431
3432 mcIdType MEDFileUMesh::buildImplicitPartIfAny(INTERP_KERNEL::NormalizedCellType gt) const
3433 {
3434   throw INTERP_KERNEL::Exception("MEDFileUMesh::buildImplicitPartIfAny : unstructured meshes do not have implicit part !");
3435 }
3436
3437 void MEDFileUMesh::releaseImplicitPartIfAny() const
3438 {
3439 }
3440
3441 void MEDFileUMesh::whichAreNodesFetched(const MEDFileField1TSStructItem& st, const MEDFileFieldGlobsReal *globs, std::vector<bool>& nodesFetched) const
3442 {
3443   std::size_t sz(st.getNumberOfItems());
3444   for(std::size_t i=0;i<sz;i++)
3445     {
3446       INTERP_KERNEL::NormalizedCellType curGt(st[i].getGeo());
3447       const MEDCoupling1GTUMesh *m(getDirectUndergroundSingleGeoTypeMesh(curGt));
3448       if(st[i].getPflName().empty())
3449         m->computeNodeIdsAlg(nodesFetched);
3450       else
3451         {
3452           const DataArrayIdType *arr(globs->getProfile(st[i].getPflName()));
3453           MCAuto<MEDCoupling1GTUMesh> m2(dynamic_cast<MEDCoupling1GTUMesh *>(m->buildPartOfMySelf(arr->begin(),arr->end(),true)));
3454           m2->computeNodeIdsAlg(nodesFetched);
3455         }
3456     }
3457 }
3458
3459 MEDFileMesh *MEDFileUMesh::cartesianize() const
3460 {
3461   if(getAxisType()==AX_CART)
3462     {
3463       incrRef();
3464       return const_cast<MEDFileUMesh *>(this);
3465     }
3466   else
3467     {
3468       MCAuto<MEDFileUMesh> ret(new MEDFileUMesh(*this));
3469       const DataArrayDouble *coords(_coords);
3470       if(!coords)
3471         throw INTERP_KERNEL::Exception("MEDFileUMesh::cartesianize : coordinates are null !");
3472       MCAuto<DataArrayDouble> coordsCart(_coords->cartesianize(getAxisType()));
3473       for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=ret->_ms.begin();it!=ret->_ms.end();it++)
3474         if((const MEDFileUMeshSplitL1 *)(*it))
3475           *it=(*it)->shallowCpyUsingCoords(coordsCart);
3476       ret->_coords=coordsCart;
3477       ret->setAxisType(AX_CART);
3478       return ret.retn();
3479     }
3480 }
3481
3482 bool MEDFileUMesh::presenceOfStructureElements() const
3483 {
3484   for(std::vector< MCAuto<MEDFileEltStruct4Mesh> >::const_iterator it=_elt_str.begin();it!=_elt_str.end();it++)
3485     if((*it).isNotNull())
3486       return true;
3487   return false;
3488 }
3489
3490 void MEDFileUMesh::killStructureElements()
3491 {
3492   _elt_str.clear();
3493 }
3494
3495 /*!
3496  * Returns the optional numbers of mesh entities of a given dimension transformed using
3497  * DataArrayIdType::invertArrayN2O2O2N().
3498  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
3499  *  \return const DataArrayIdType * - the array of the entity numbers transformed using
3500  *          DataArrayIdType::invertArrayN2O2O2N().
3501  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3502  */
3503 const DataArrayIdType *MEDFileUMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxExt) const
3504 {
3505   if(meshDimRelToMaxExt==1)
3506     {
3507       if(_num_coords.isNull())
3508         throw INTERP_KERNEL::Exception("MEDFileUMesh::getRevNumberFieldAtLevel : no coordinates renum specified !");
3509       return _rev_num_coords;
3510     }
3511   const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMaxExt));
3512   return l1->getRevNumberField();
3513 }
3514
3515 /*!
3516  * Returns a pointer to the node coordinates array of \a this mesh \b without
3517  * incrementing its reference counter, thus there is no need to decrRef() it by the caller.
3518  */
3519 DataArrayDouble *MEDFileUMesh::getCoords() const
3520 {
3521   checkCartesian();
3522   MCAuto<DataArrayDouble> tmp(_coords);
3523   if((DataArrayDouble *)tmp)
3524     {
3525       return tmp;
3526     }
3527   return 0;
3528 }
3529
3530 /*!
3531  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in a given
3532  * group of \a this mesh. Only mesh entities of a given dimension are included in the
3533  * new mesh.
3534  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
3535  *  \param [in] grp - the name of the group whose mesh entities are included in the
3536  *          new mesh.
3537  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
3538  *          according to the optional numbers of entities, if available.
3539  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
3540  *          delete this mesh using decrRef() as it is no more needed.
3541  *  \throw If the name of a nonexistent group is specified.
3542  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3543  */
3544 MEDCouplingUMesh *MEDFileUMesh::getGroup(int meshDimRelToMaxExt, const std::string& grp, bool renum) const
3545 {
3546   checkCartesian();
3547   synchronizeTinyInfoOnLeaves();
3548   std::vector<std::string> tmp(1);
3549   tmp[0]=grp;
3550   return getGroups(meshDimRelToMaxExt,tmp,renum);
3551 }
3552
3553 /*!
3554  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in given
3555  * groups of \a this mesh. Only mesh entities of a given dimension are included in the
3556  * new mesh.
3557  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
3558  *  \param [in] grps - a sequence of group names whose mesh entities are included in the
3559  *          new mesh.
3560  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
3561  *          according to the optional numbers of entities, if available.
3562  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
3563  *          delete this mesh using decrRef() as it is no more needed.
3564  *  \throw If a name of a nonexistent group is present in \a grps.
3565  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3566  */
3567 MEDCouplingUMesh *MEDFileUMesh::getGroups(int meshDimRelToMaxExt, const std::vector<std::string>& grps, bool renum) const
3568 {
3569   checkCartesian();
3570   synchronizeTinyInfoOnLeaves();
3571   std::vector<std::string> fams2=getFamiliesOnGroups(grps);
3572   MCAuto<MEDCouplingUMesh> zeRet=getFamilies(meshDimRelToMaxExt,fams2,renum);
3573   if(grps.size()==1 && ((MEDCouplingUMesh *)zeRet))
3574     zeRet->setName(grps[0]);
3575   return zeRet.retn();
3576 }
3577
3578 /*!
3579  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in a given
3580  * family of \a this mesh. Only mesh entities of a given dimension are included in the
3581  * new mesh.
3582  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
3583  *  \param [in] fam - the name of the family whose mesh entities are included in the
3584  *          new mesh.
3585  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
3586  *          according to the optional numbers of entities, if available.
3587  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
3588  *          delete this mesh using decrRef() as it is no more needed.
3589  *  \throw If a name of a nonexistent family is present in \a grps.
3590  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3591  */
3592 MEDCouplingUMesh *MEDFileUMesh::getFamily(int meshDimRelToMaxExt, const std::string& fam, bool renum) const
3593 {
3594   checkCartesian();
3595   synchronizeTinyInfoOnLeaves();
3596   std::vector<std::string> tmp(1);
3597   tmp[0]=fam;
3598   return getFamilies(meshDimRelToMaxExt,tmp,renum);
3599 }
3600
3601 /*!
3602  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in given
3603  * families of \a this mesh. Only mesh entities of a given dimension are included in the
3604  * new mesh.
3605  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
3606  *  \param [in] fams - a sequence of family names whose mesh entities are included in the
3607  *          new mesh.
3608  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
3609  *          according to the optional numbers of entities, if available.
3610  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
3611  *          delete this mesh using decrRef() as it is no more needed.
3612  *  \throw If a name of a nonexistent family is present in \a fams.
3613  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3614  */
3615 MEDCouplingUMesh *MEDFileUMesh::getFamilies(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const
3616 {
3617   checkCartesian();
3618   synchronizeTinyInfoOnLeaves();
3619   if(meshDimRelToMaxExt==1)
3620     {
3621       MCAuto<DataArrayIdType> arr=getFamiliesArr(1,fams,renum);
3622       MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3623       MCAuto<DataArrayDouble> c=_coords->selectByTupleId(arr->getConstPointer(),arr->getConstPointer()+arr->getNbOfElems());
3624       ret->setCoords(c);
3625       return ret.retn();
3626     }
3627   std::vector<mcIdType> famIds=getFamiliesIds(fams);
3628   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3629   MCAuto<MEDCouplingUMesh> zeRet;
3630   if(!famIds.empty())
3631     zeRet=l1->getFamilyPart(&famIds[0],&famIds[0]+famIds.size(),renum);
3632   else
3633     zeRet=l1->getFamilyPart(0,0,renum);
3634   if(fams.size()==1 && ((MEDCouplingUMesh *)zeRet))
3635     zeRet->setName(fams[0]);
3636   return zeRet.retn();
3637 }
3638
3639 /*!
3640  * Returns ids of mesh entities contained in given families of a given dimension.
3641  *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
3642  *          are required.
3643  *  \param [in] fams - the names of the families of interest.
3644  *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
3645  *          returned instead of ids.
3646  *  \return DataArrayIdType * - a new instance of DataArrayIdType holding either ids or
3647  *          numbers, if available and required, of mesh entities of the families. The caller
3648  *          is to delete this array using decrRef() as it is no more needed. 
3649  *  \throw If the family field is missing for \a meshDimRelToMaxExt.
3650  */
3651 DataArrayIdType *MEDFileUMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const
3652 {
3653   std::vector<mcIdType> famIds=getFamiliesIds(fams);
3654   if(meshDimRelToMaxExt==1)
3655     {
3656       if((const DataArrayIdType *)_fam_coords)
3657         {
3658           MCAuto<DataArrayIdType> da;
3659           if(!famIds.empty())
3660             da=_fam_coords->findIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
3661           else
3662             da=_fam_coords->findIdsEqualList(0,0);
3663           if(renum)
3664             return MEDFileUMeshSplitL1::Renumber(_num_coords,da);
3665           else
3666             return da.retn();
3667         }
3668       else
3669         throw INTERP_KERNEL::Exception("MEDFileUMesh::getFamiliesArr : no family array specified on nodes !");
3670     }
3671   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3672   if(!famIds.empty())
3673     return l1->getFamilyPartArr(&famIds[0],&famIds[0]+famIds.size(),renum);
3674   else
3675     return l1->getFamilyPartArr(0,0,renum);
3676 }
3677
3678 /*!
3679  * Returns a MEDCouplingUMesh of a given relative dimension.
3680  * \warning If \a meshDimRelToMaxExt == 1 (which means nodes), the returned mesh **is not
3681  * valid**. This is a feature, because MEDLoader does not create cells that do not exist! 
3682  * To build a valid MEDCouplingUMesh from the returned one in this case,
3683  * call MEDCouplingUMesh::Build0DMeshFromCoords().
3684  *  \param [in] meshDimRelToMax - the relative dimension of interest.
3685  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3686  *          optional numbers of mesh entities.
3687  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
3688  *          delete using decrRef() as it is no more needed. 
3689  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3690  */
3691 MEDCouplingUMesh *MEDFileUMesh::getMeshAtLevel(int meshDimRelToMaxExt, bool renum) const
3692 {
3693   checkCartesian();
3694   synchronizeTinyInfoOnLeaves();
3695   if(meshDimRelToMaxExt==1)
3696     {
3697       if(!renum)
3698         {
3699           MEDCouplingUMesh *umesh=MEDCouplingUMesh::New();
3700           MCAuto<DataArrayDouble> cc=_coords->deepCopy();
3701           umesh->setCoords(cc);
3702           MEDFileUMeshSplitL1::ClearNonDiscrAttributes(umesh);
3703           umesh->setName(getName());
3704           return umesh;
3705         }
3706     }
3707   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3708   return l1->getWholeMesh(renum);
3709 }
3710
3711 std::vector<mcIdType> MEDFileUMesh::getDistributionOfTypes(int meshDimRelToMax) const
3712 {
3713   const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMax));
3714   return l1->getDistributionOfTypes();
3715 }
3716
3717 /*!
3718  * Returns a MEDCouplingUMesh of a relative dimension == 0.
3719  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3720  *          optional numbers of mesh entities.
3721  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
3722  *          delete using decrRef() as it is no more needed. 
3723  *  \throw If there are no mesh entities of the relative dimension == 0 in \a this mesh.
3724  */
3725 MEDCouplingUMesh *MEDFileUMesh::getLevel0Mesh(bool renum) const
3726 {
3727   return getMeshAtLevel(0,renum);
3728 }
3729
3730 /*!
3731  * Returns a MEDCouplingUMesh of a relative dimension == -1.
3732  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3733  *          optional numbers of mesh entities.
3734  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
3735  *          delete using decrRef() as it is no more needed. 
3736  *  \throw If there are no mesh entities of the relative dimension == -1 in \a this mesh.
3737  */
3738 MEDCouplingUMesh *MEDFileUMesh::getLevelM1Mesh(bool renum) const
3739 {
3740   return getMeshAtLevel(-1,renum);
3741 }
3742
3743 /*!
3744  * Returns a MEDCouplingUMesh of a relative dimension == -2.
3745  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3746  *          optional numbers of mesh entities.
3747  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
3748  *          delete using decrRef() as it is no more needed. 
3749  *  \throw If there are no mesh entities of the relative dimension == -2 in \a this mesh.
3750  */
3751 MEDCouplingUMesh *MEDFileUMesh::getLevelM2Mesh(bool renum) const
3752 {
3753   return getMeshAtLevel(-2,renum);
3754 }
3755
3756 /*!
3757  * Returns a MEDCouplingUMesh of a relative dimension == -3.
3758  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3759  *          optional numbers of mesh entities.
3760  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
3761  *          delete using decrRef() as it is no more needed. 
3762  *  \throw If there are no mesh entities of the relative dimension == -3 in \a this mesh.
3763  */
3764 MEDCouplingUMesh *MEDFileUMesh::getLevelM3Mesh(bool renum) const
3765 {
3766   return getMeshAtLevel(-3,renum);
3767 }
3768
3769 /*!
3770  * This method is for advanced users. There is two storing strategy of mesh in \a this.
3771  * Either MEDCouplingUMesh, or vector of MEDCoupling1GTUMesh instances.
3772  * When assignment is done the first one is done, which is not optimal in write mode for MED file.
3773  * This method allows to switch from MEDCouplingUMesh mode to MEDCoupling1GTUMesh mode.
3774  */
3775 void MEDFileUMesh::forceComputationOfParts() const
3776 {
3777   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
3778     {
3779       const MEDFileUMeshSplitL1 *elt(*it);
3780       if(elt)
3781         elt->forceComputationOfParts();
3782     }
3783 }
3784
3785 /*!
3786  * This method returns a vector of mesh parts containing each exactly one geometric type.
3787  * This method will never launch an automatic computation of split by type (an INTERP_KERNEL::Exception will be then thrown).
3788  * This method is only for memory aware users.
3789  * The returned pointers are **NOT** new object pointer. No need to mange them.
3790  */
3791 std::vector<MEDCoupling1GTUMesh *> MEDFileUMesh::getDirectUndergroundSingleGeoTypeMeshes(int meshDimRelToMax) const
3792 {
3793   checkCartesian();
3794   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(meshDimRelToMax));
3795   return sp->getDirectUndergroundSingleGeoTypeMeshes();
3796 }
3797
3798 /*!
3799  * This method returns the part of \a this having the geometric type \a gt.
3800  * If such part is not existing an exception will be thrown.
3801  * The returned pointer is **NOT** new object pointer. No need to mange it.
3802  */
3803 MEDCoupling1GTUMesh *MEDFileUMesh::getDirectUndergroundSingleGeoTypeMesh(INTERP_KERNEL::NormalizedCellType gt) const
3804 {
3805   checkCartesian();
3806   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(gt));
3807   int lev=(int)cm.getDimension()-getMeshDimension();
3808   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(lev));
3809   return sp->getDirectUndergroundSingleGeoTypeMesh(gt);
3810 }
3811
3812 /*!
3813  * This method returns for each geo types in \a this number of cells with this geo type.
3814  * 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.
3815  * This method also returns the number of nodes of \a this (key associated is NORM_ERROR)
3816  *
3817  * \sa getDistributionOfTypes
3818  */
3819 std::vector< std::pair<int,mcIdType> > MEDFileUMesh::getAllDistributionOfTypes() const
3820 {
3821   std::vector< std::pair<int,mcIdType> > ret;
3822   std::vector<int> nel(getNonEmptyLevels());
3823   for(std::vector<int>::reverse_iterator it=nel.rbegin();it!=nel.rend();it++)
3824     {
3825       std::vector<INTERP_KERNEL::NormalizedCellType> gt(getGeoTypesAtLevel(*it));
3826       for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it1=gt.begin();it1!=gt.end();it1++)
3827         {
3828           mcIdType nbCells(getNumberOfCellsWithType(*it1));
3829           ret.push_back(std::pair<int,mcIdType>(*it1,nbCells));
3830         }
3831     }
3832   ret.push_back(std::pair<int,mcIdType>(INTERP_KERNEL::NORM_ERROR,getNumberOfNodes()));
3833   return ret;
3834 }
3835
3836 /*!
3837  * Given a relative level \a meshDimRelToMax it returns the sorted vector of geometric types present in \a this.
3838  * \throw if the reqsuested \a meshDimRelToMax does not exist.
3839  */
3840 std::vector<INTERP_KERNEL::NormalizedCellType> MEDFileUMesh::getGeoTypesAtLevel(int meshDimRelToMax) const
3841 {
3842   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(meshDimRelToMax));
3843   return sp->getGeoTypes();
3844 }
3845
3846 mcIdType MEDFileUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType ct) const
3847 {
3848   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(ct);
3849   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe( ((int)cm.getDimension())-getMeshDimension() ));
3850   return sp->getNumberOfCellsWithType(ct);
3851 }
3852
3853 /*!
3854  * This method extracts from whole family field ids the part relative to the input parameter \a gt.
3855  * \param [in] gt - the geometric type for which the family field is asked.
3856  * \return DataArrayIdType * - a pointer to DataArrayIdType that the caller is to
3857  *          delete using decrRef() as it is no more needed.
3858  * \sa MEDFileUMesh::extractNumberFieldOnGeoType
3859  */
3860 DataArrayIdType *MEDFileUMesh::extractFamilyFieldOnGeoType(INTERP_KERNEL::NormalizedCellType gt) const
3861 {
3862   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
3863   int lev=(int)cm.getDimension()-getMeshDimension();
3864   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(lev));
3865   return sp->extractFamilyFieldOnGeoType(gt);
3866 }
3867
3868 /*!
3869  * This method extracts from whole number field ids the part relative to the input parameter \a gt.
3870  * \param [in] gt - the geometric type for which the number field is asked.
3871  * \return DataArrayIdType * - a pointer to DataArrayIdType that the caller is to
3872  *          delete using decrRef() as it is no more needed.
3873  * \sa MEDFileUMesh::extractFamilyFieldOnGeoType
3874  */
3875 DataArrayIdType *MEDFileUMesh::extractNumberFieldOnGeoType(INTERP_KERNEL::NormalizedCellType gt) const
3876 {
3877   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
3878   int lev=(int)cm.getDimension()-getMeshDimension();
3879   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(lev));
3880   return sp->extractNumberFieldOnGeoType(gt);
3881 }
3882
3883 /*!
3884  * This method returns for specified geometric type \a gt the relative level to \a this.
3885  * If the relative level is empty an exception will be thrown.
3886  */
3887 int MEDFileUMesh::getRelativeLevOnGeoType(INTERP_KERNEL::NormalizedCellType gt) const
3888 {
3889   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
3890   int ret((int)cm.getDimension()-getMeshDimension());
3891   getMeshAtLevSafe(ret);//To test that returned value corresponds to a valid level.
3892   return ret;
3893 }
3894
3895 const MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt) const
3896 {
3897   if(meshDimRelToMaxExt==1)
3898     throw INTERP_KERNEL::Exception("Dimension request is invalid : asking for node level (1) !");
3899   if(meshDimRelToMaxExt>1)
3900     throw INTERP_KERNEL::Exception("Dimension request is invalid (>1) !");
3901   int tracucedRk=-meshDimRelToMaxExt;
3902   if(tracucedRk>=(int)_ms.size())
3903     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
3904   if((const MEDFileUMeshSplitL1 *)_ms[tracucedRk]==0)
3905     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3906   return _ms[tracucedRk];
3907 }
3908
3909 MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt)
3910 {
3911   if(meshDimRelToMaxExt==1)
3912     throw INTERP_KERNEL::Exception("Dimension request is invalid : asking for node level (1) !");
3913   if(meshDimRelToMaxExt>1)
3914     throw INTERP_KERNEL::Exception("Dimension request is invalid (>1) !");
3915   int tracucedRk=-meshDimRelToMaxExt;
3916   if(tracucedRk>=(int)_ms.size())
3917     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
3918   if((const MEDFileUMeshSplitL1 *)_ms[tracucedRk]==0)
3919     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3920   return _ms[tracucedRk];
3921 }
3922
3923 void MEDFileUMesh::checkMeshDimCoherency(int meshDim, int meshDimRelToMax) const
3924 {
3925   if(-meshDimRelToMax>=(int)_ms.size())
3926     throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMeshDimCoherency : The meshdim of mesh is not managed by 'this' !");
3927   int i=0;
3928   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,i++)
3929     {
3930       if(((const MEDFileUMeshSplitL1*) (*it))!=0)
3931         {
3932           int ref=(*it)->getMeshDimension();
3933           if(ref+i!=meshDim-meshDimRelToMax)
3934             throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMeshDimCoherency : no coherency between levels !");
3935         }
3936     }
3937 }
3938
3939 /*!
3940  * Sets the node coordinates array of \a this mesh.
3941  *  \param [in] coords - the new node coordinates array.
3942  *  \throw If \a coords == \c NULL.
3943  */
3944 void MEDFileUMesh::setCoords(DataArrayDouble *coords)
3945 {
3946   if(!coords)
3947     throw INTERP_KERNEL::Exception("MEDFileUMesh::setCoords : null pointer in input !");
3948   if(coords==(DataArrayDouble *)_coords)
3949     return ;
3950   coords->checkAllocated();
3951   mcIdType nbOfTuples(coords->getNumberOfTuples());
3952   _coords.takeRef(coords);
3953   _fam_coords=DataArrayIdType::New();
3954   _fam_coords->alloc(nbOfTuples,1);
3955   _fam_coords->fillWithZero();
3956   _num_coords.nullify(); _rev_num_coords.nullify(); _name_coords.nullify(); _global_num_coords.nullify();
3957   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
3958     if((MEDFileUMeshSplitL1 *)(*it))
3959       (*it)->setCoords(coords);
3960 }
3961
3962 /*!
3963  * Change coords without changing anything concerning families and numbering on nodes.
3964  */
3965 void MEDFileUMesh::setCoordsForced(DataArrayDouble *coords)
3966 {
3967   if(!coords)
3968     throw INTERP_KERNEL::Exception("MEDFileUMesh::setCoordsForced : null pointer in input !");
3969   if(coords==(DataArrayDouble *)_coords)
3970     return ;
3971   coords->checkAllocated();
3972   mcIdType nbOfTuples(coords->getNumberOfTuples());
3973   if(_coords.isNull())
3974     {
3975       _coords=coords;
3976       coords->incrRef();
3977     }
3978   else
3979     {
3980       mcIdType oldNbTuples(_coords->getNumberOfTuples());
3981       if(oldNbTuples!=nbOfTuples)
3982         throw INTERP_KERNEL::Exception("MEDFileUMesh::setCoordsForced : number of tuples is not the same -> invoke setCoords instead !");
3983       _coords=coords;
3984       coords->incrRef();
3985     }
3986   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
3987     if((MEDFileUMeshSplitL1 *)(*it))
3988       (*it)->setCoords(coords);
3989 }
3990
3991 /*!
3992  * Removes all groups of a given dimension in \a this mesh.
3993  *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
3994  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3995  */
3996 void MEDFileUMesh::eraseGroupsAtLevel(int meshDimRelToMaxExt)
3997 {
3998   if(meshDimRelToMaxExt==1)
3999     {
4000       if((DataArrayIdType *)_fam_coords)
4001         _fam_coords->fillWithZero();
4002       return ;
4003     }
4004   MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
4005   l1->eraseFamilyField();
4006   optimizeFamilies();
4007 }
4008
4009 /*!
4010  * Removes all families with ids not present in the family fields of \a this mesh.
4011  */
4012 void MEDFileUMesh::optimizeFamilies()
4013 {
4014   std::vector<int> levs=getNonEmptyLevelsExt();
4015   std::set<mcIdType> allFamsIds;
4016   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
4017     {
4018       const DataArrayIdType *ffield=getFamilyFieldAtLevel(*it);
4019       MCAuto<DataArrayIdType> ids=ffield->getDifferentValues();
4020       std::set<mcIdType> res;
4021       std::set_union(ids->begin(),ids->end(),allFamsIds.begin(),allFamsIds.end(),std::inserter(res,res.begin()));
4022       allFamsIds=res;
4023     }
4024   std::set<std::string> famNamesToKill;
4025   for(std::map<std::string,mcIdType>::const_iterator it=_families.begin();it!=_families.end();it++)
4026     {
4027       if(allFamsIds.find((*it).second)!=allFamsIds.end())
4028         famNamesToKill.insert((*it).first);
4029     }
4030   for(std::set<std::string>::const_iterator it=famNamesToKill.begin();it!=famNamesToKill.end();it++)
4031     _families.erase(*it);
4032   std::vector<std::string> grpNamesToKill;
4033   for(std::map<std::string, std::vector<std::string> >::iterator it=_groups.begin();it!=_groups.end();it++)
4034     {
4035       std::vector<std::string> tmp;
4036       for(std::vector<std::string>::const_iterator it2=(*it).second.begin();it2!=(*it).second.end();it2++)
4037         {
4038           if(famNamesToKill.find(*it2)==famNamesToKill.end())
4039             tmp.push_back(*it2);
4040         }
4041       if(!tmp.empty())
4042         (*it).second=tmp;
4043       else
4044         tmp.push_back((*it).first);
4045     }
4046   for(std::vector<std::string>::const_iterator it=grpNamesToKill.begin();it!=grpNamesToKill.end();it++)
4047     _groups.erase(*it);
4048 }
4049
4050 /**
4051  * \b this must be filled at level 0 and -1, typically the -1 level being (part of) the descending connectivity
4052  * of the top level. This method build a "crack", or an inner boundary, in \b this along the group of level -1 named grpNameM1.
4053  * The boundary is built according to the following method:
4054  *  - all nodes along the boundary which are not lying on an internal extremity of the (-1)-level group are duplicated (so the
4055  * coordinates array is extended).
4056  *  - new (-1)-level cells are built lying on those new nodes. So the edges/faces along the group are duplicated. A new group
4057  *  called "<grpNameM1>_dup" containing the effectively duplicated cells is created. Note that in 3D some cells of the group
4058  *  might not be duplicated at all.
4059  *  After this operation a top-level cell bordering the group will loose some neighbors (typically the cell which is  on the
4060  *  other side of the group is no more a neighbor)
4061  *   - finally, the connectivity of (part of) the top level-cells bordering the group is also modified so that some cells
4062  *  bordering the newly created boundary use the newly computed nodes.
4063  *  Finally note that optional cell numbers are also affected by this method and might become invalid for SMESH.
4064  *  Use clearNodeAndCellNumbers() afterwards to ensure a proper SMESH loading.
4065  *
4066  *  \param[in] grpNameM1 name of the (-1)-level group defining the boundary
4067  *  \param[out] nodesDuplicated ids of the initial nodes which have been duplicated (and whose copy is put at the end of
4068  *  the coord array)
4069  *  \param[out] cellsModified ids of the cells whose connectivity has been modified (to use the newly created nodes)
4070  *  \param[out] cellsNotModified ids of the rest of cells bordering the new boundary whose connectivity remains unchanged.
4071  *  \sa clearNodeAndCellNumbers()
4072  */
4073 void MEDFileUMesh::buildInnerBoundaryAlongM1Group(const std::string& grpNameM1, DataArrayIdType *&nodesDuplicated,
4074                                            DataArrayIdType *&cellsModified, DataArrayIdType *&cellsNotModified)
4075 {
4076   typedef MCAuto<MEDCouplingUMesh> MUMesh;
4077   typedef MCAuto<DataArrayIdType> DAInt;
4078
4079   std::vector<int> levs=getNonEmptyLevels();
4080   if(std::find(levs.begin(),levs.end(),0)==levs.end() || std::find(levs.begin(),levs.end(),-1)==levs.end())
4081     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildInnerBoundaryAlongM1Group : This method works only for mesh defined on level 0 and -1 !");
4082   MUMesh m0=getMeshAtLevel(0);
4083   MUMesh m1=getMeshAtLevel(-1);
4084   mcIdType nbNodes=m0->getNumberOfNodes();
4085   MUMesh m11=getGroup(-1,grpNameM1);
4086   DataArrayIdType *tmp00=0,*tmp11=0,*tmp22=0;
4087   m0->findNodesToDuplicate(*m11,tmp00,tmp11,tmp22);
4088   DAInt nodeIdsToDuplicate(tmp00);
4089   DAInt cellsToModifyConn0(tmp11);
4090   DAInt cellsToModifyConn1(tmp22);
4091   MUMesh tmp0=static_cast<MEDCouplingUMesh *>(m0->buildPartOfMySelf(cellsToModifyConn0->begin(),cellsToModifyConn0->end(),true));
4092   // node renumbering of cells in m1 impacted by duplication of node but not in group 'grpNameM1' on level -1
4093   DAInt descTmp0=DataArrayIdType::New(),descITmp0=DataArrayIdType::New(),revDescTmp0=DataArrayIdType::New(),revDescITmp0=DataArrayIdType::New();
4094   MUMesh tmp0Desc=tmp0->buildDescendingConnectivity(descTmp0,descITmp0,revDescTmp0,revDescITmp0);
4095   descTmp0=0; descITmp0=0; revDescTmp0=0; revDescITmp0=0;
4096   DAInt cellsInM1ToRenumW2=tmp0Desc->getCellIdsLyingOnNodes(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),false);
4097   MUMesh cellsInM1ToRenumW3=static_cast<MEDCouplingUMesh *>(tmp0Desc->buildPartOfMySelf(cellsInM1ToRenumW2->begin(),cellsInM1ToRenumW2->end(),true));
4098   DataArrayIdType *cellsInM1ToRenumW4Tmp=0;
4099   m1->areCellsIncludedIn(cellsInM1ToRenumW3,2,cellsInM1ToRenumW4Tmp);
4100   DAInt cellsInM1ToRenumW4(cellsInM1ToRenumW4Tmp);
4101   DAInt cellsInM1ToRenumW5=cellsInM1ToRenumW4->findIdsInRange(0,m1->getNumberOfCells());
4102   cellsInM1ToRenumW5->transformWithIndArr(cellsInM1ToRenumW4->begin(),cellsInM1ToRenumW4->end());
4103   DAInt grpIds=getGroupArr(-1,grpNameM1);
4104   DAInt cellsInM1ToRenum=cellsInM1ToRenumW5->buildSubstraction(grpIds);
4105   MUMesh m1Part=static_cast<MEDCouplingUMesh *>(m1->buildPartOfMySelf(cellsInM1ToRenum->begin(),cellsInM1ToRenum->end(),true));
4106   m1Part->duplicateNodesInConn(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),nbNodes);
4107   m1->setPartOfMySelf(cellsInM1ToRenum->begin(),cellsInM1ToRenum->end(),*m1Part);
4108   // end of node renumbering of cells in m1 impacted by duplication of node but not in group of level -1 'grpNameM1'
4109   tmp0->duplicateNodes(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end());
4110   m0->setCoords(tmp0->getCoords());
4111   m0->setPartOfMySelf(cellsToModifyConn0->begin(),cellsToModifyConn0->end(),*tmp0);
4112   _ms[0]->forceComputationOfParts();  // necessary because we modify the connectivity of some internal part
4113   m1->setCoords(m0->getCoords());
4114   _coords=m0->getCoords(); _coords->incrRef();
4115   // duplication of cells in group 'grpNameM1' on level -1, but not duplicating cells for which nothing has changed
4116   m11->duplicateNodesInConn(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),nbNodes); m11->setCoords(m0->getCoords());
4117   DataArrayIdType * duplCells;
4118   m1->areCellsIncludedIn(m11, 0, duplCells);
4119   DAInt zeIds = duplCells->findIdsNotInRange(-1, m1->getNumberOfCells()-1); duplCells->decrRef();
4120   MUMesh m11Part=static_cast<MEDCouplingUMesh *>(m11->buildPartOfMySelf(zeIds->begin(),zeIds->end(),true));
4121   std::vector<const MEDCouplingUMesh *> v(2); v[0]=m1; v[1]=m11Part;
4122   MUMesh newm1=MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(v,tmp00,tmp11);
4123   DAInt szOfCellGrpOfSameType(tmp00);
4124   DAInt idInMsOfCellGrpOfSameType(tmp11);
4125   //
4126   newm1->setName(getName());
4127   const DataArrayIdType *fam=getFamilyFieldAtLevel(-1);
4128   if(!fam)
4129     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildInnerBoundaryAlongM1Group(): internal error no family field !");
4130   DAInt newFam=DataArrayIdType::New();
4131   newFam->alloc(newm1->getNumberOfCells(),1);
4132   // Get a new family ID: care must be taken if we need a positive ID or a negative one:
4133   // Positive ID for family of nodes, negative for all the rest.
4134   mcIdType idd;
4135   if (m1->getMeshDimension() == 0)
4136     idd=getMaxFamilyId()+1;
4137   else
4138     idd=getMinFamilyId()-1;
4139   mcIdType globStart=0,start=0,end,globEnd;
4140   mcIdType nbOfChunks=szOfCellGrpOfSameType->getNumberOfTuples();
4141   for(mcIdType i=0;i<nbOfChunks;i++)
4142     {
4143       globEnd=globStart+szOfCellGrpOfSameType->getIJ(i,0);
4144       if(idInMsOfCellGrpOfSameType->getIJ(i,0)==0)
4145         {
4146           end=start+szOfCellGrpOfSameType->getIJ(i,0);
4147           DAInt part=fam->selectByTupleIdSafeSlice(start,end,1);
4148           newFam->setPartOfValues1(part,globStart,globEnd,1,0,1,1,true);
4149           start=end;
4150         }
4151       else
4152         {
4153           newFam->setPartOfValuesSimple1(idd,globStart,globEnd,1,0,1,1);
4154         }
4155       globStart=globEnd;
4156     }
4157   newm1->setCoords(getCoords());
4158   setMeshAtLevel(-1,newm1);
4159   setFamilyFieldArr(-1,newFam);
4160   std::string grpName2(grpNameM1); grpName2+="_dup";
4161   addFamily(grpName2,idd);
4162   addFamilyOnGrp(grpName2,grpName2);
4163   //
4164   fam=_fam_coords;
4165   if(fam)
4166     {
4167       mcIdType newNbOfNodes=getCoords()->getNumberOfTuples();
4168       newFam=DataArrayIdType::New(); newFam->alloc(newNbOfNodes,1);
4169       newFam->setPartOfValues1(fam,0,nbNodes,1,0,1,1,true);
4170       newFam->setPartOfValuesSimple1(0,nbNodes,newNbOfNodes,1,0,1,1);
4171       _fam_coords=newFam;
4172     }
4173
4174   _num_coords.nullify(); _rev_num_coords.nullify(); _global_num_coords.nullify();
4175   
4176   for (std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();
4177       it != _ms.end(); it++)
4178     {
4179       (*it)->_num = 0;
4180       (*it)->_rev_num = 0;
4181     }
4182   nodesDuplicated=nodeIdsToDuplicate.retn();
4183   cellsModified=cellsToModifyConn0.retn();
4184   cellsNotModified=cellsToModifyConn1.retn();
4185 }
4186
4187 /*! Similar to MEDCouplingUMesh::unPolyze():  converts all polygons (if \a this is a 2D mesh) or polyhedrons
4188  * (if \a this is a 3D mesh) to cells of classical types. The cells remain correctly sorted by geometric type
4189  * in this method.
4190  *
4191  * \param [out] oldCode retrieves the distribution of types before the call if true is returned
4192  * \param [out] newCode retrieves the distribution of types after the call if true is returned
4193  * \param [out] o2nRenumCell tells for **all levels** the old 2 new renumbering of cells.
4194  * 
4195  * \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.
4196  * 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.
4197  */
4198 bool MEDFileUMesh::unPolyze(std::vector<mcIdType>& oldCode, std::vector<mcIdType>& newCode, DataArrayIdType *& o2nRenumCell)
4199 {
4200   o2nRenumCell=0; oldCode.clear(); newCode.clear();
4201   std::vector<int> levs=getNonEmptyLevels();
4202   bool ret=false;
4203   std::vector< const DataArrayIdType* > renumCellsSplited;//same than memorySaverIfThrow
4204   std::vector< MCAuto<DataArrayIdType> > memorySaverIfThrow;//same than renumCellsSplited only in case of throw
4205   mcIdType start=0;
4206   mcIdType end=0;
4207   for(std::vector<int>::reverse_iterator it=levs.rbegin();it!=levs.rend();it++)
4208     {
4209       MCAuto<MEDCouplingUMesh> m=getMeshAtLevel(*it);
4210       std::vector<mcIdType> code1=m->getDistributionOfTypes();
4211       end=PutInThirdComponentOfCodeOffset(code1,start);
4212       oldCode.insert(oldCode.end(),code1.begin(),code1.end());
4213       bool hasChanged=m->unPolyze();
4214       DataArrayIdType *fake=0;
4215       MCAuto<DataArrayIdType> o2nCellsPart=m->getLevArrPerCellTypes(MEDCouplingUMesh::MEDMEM_ORDER,
4216           MEDCouplingUMesh::MEDMEM_ORDER+MEDCouplingUMesh::N_MEDMEM_ORDER,fake);
4217       fake->decrRef();
4218       renumCellsSplited.push_back(o2nCellsPart); memorySaverIfThrow.push_back(o2nCellsPart);
4219       if(hasChanged)
4220         {
4221           MCAuto<DataArrayIdType> o2nCellsPart2=o2nCellsPart->buildPermArrPerLevel();
4222           m->renumberCells(o2nCellsPart2->getConstPointer(),false);
4223           ret=true;
4224           MCAuto<DataArrayIdType> famField2,numField2;
4225           const DataArrayIdType *famField=getFamilyFieldAtLevel(*it); if(famField) { famField->incrRef(); famField2=const_cast<DataArrayIdType *>(famField); }
4226           const DataArrayIdType *numField=getNumberFieldAtLevel(*it); if(numField) { numField->incrRef(); numField2=const_cast<DataArrayIdType *>(numField); }
4227           setMeshAtLevel(*it,m);
4228           std::vector<mcIdType> code2=m->getDistributionOfTypes();
4229           end=PutInThirdComponentOfCodeOffset(code2,start);
4230           newCode.insert(newCode.end(),code2.begin(),code2.end());
4231           //
4232           if(o2nCellsPart2->isIota(o2nCellsPart2->getNumberOfTuples()))
4233             continue;
4234           if(famField)
4235             {
4236               MCAuto<DataArrayIdType> newFamField=famField->renumber(o2nCellsPart2->getConstPointer());
4237               setFamilyFieldArr(*it,newFamField);
4238             }
4239           if(numField)
4240             {
4241               MCAuto<DataArrayIdType> newNumField=numField->renumber(o2nCellsPart2->getConstPointer());
4242               setRenumFieldArr(*it,newNumField);
4243             }
4244         }
4245       else
4246         {
4247           newCode.insert(newCode.end(),code1.begin(),code1.end());
4248         }
4249       start=end;
4250     }
4251   if(ret)
4252     {
4253       MCAuto<DataArrayIdType> renumCells=DataArrayIdType::Aggregate(renumCellsSplited);
4254       MCAuto<DataArrayIdType> o2nRenumCellRet=renumCells->buildPermArrPerLevel();
4255       o2nRenumCell=o2nRenumCellRet.retn();
4256     }
4257   return ret;
4258 }
4259
4260 /*! \cond HIDDEN_ITEMS */
4261 struct MEDLoaderAccVisit1
4262 {
4263   MEDLoaderAccVisit1():_new_nb_of_nodes(0) { }
4264   mcIdType operator()(bool val) { return val?_new_nb_of_nodes++:-1; }
4265   mcIdType _new_nb_of_nodes;
4266 };
4267 /*! \endcond */
4268
4269 /*!
4270  * 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.
4271  * The maximum value stored in returned array is the number of nodes of \a this minus 1 after call of this method.
4272  * The size of returned array is the number of nodes of the old (previous to the call of this method) number of nodes.
4273  * -1 values in returned array means that the corresponding old node is no more used.
4274  *
4275  * \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
4276  *         is modified in \a this.
4277  * \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
4278  *  set coordinates.
4279  */
4280 DataArrayIdType *MEDFileUMesh::zipCoords()
4281 {
4282   const DataArrayDouble *coo(getCoords());
4283   if(!coo)
4284     throw INTERP_KERNEL::Exception("MEDFileUMesh::zipCoords : no coordinates set in this !");
4285   mcIdType nbOfNodes(coo->getNumberOfTuples());
4286   std::vector<bool> nodeIdsInUse(nbOfNodes,false);
4287   std::vector<int> neLevs(getNonEmptyLevels());
4288   for(std::vector<int>::const_iterator lev=neLevs.begin();lev!=neLevs.end();lev++)
4289     {
4290       const MEDFileUMeshSplitL1 *zeLev(getMeshAtLevSafe(*lev));
4291       if(zeLev->isMeshStoredSplitByType())
4292         {
4293           std::vector<MEDCoupling1GTUMesh *> ms(zeLev->getDirectUndergroundSingleGeoTypeMeshes());
4294           for(std::vector<MEDCoupling1GTUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
4295             if(*it)
4296               (*it)->computeNodeIdsAlg(nodeIdsInUse);
4297         }
4298       else
4299         {
4300           MCAuto<MEDCouplingUMesh> mesh(zeLev->getWholeMesh(false));
4301           mesh->computeNodeIdsAlg(nodeIdsInUse);
4302         }
4303     }
4304   mcIdType nbrOfNodesInUse((mcIdType)std::count(nodeIdsInUse.begin(),nodeIdsInUse.end(),true));
4305   if(nbrOfNodesInUse==nbOfNodes)
4306     return 0;//no need to update _part_coords
4307   MCAuto<DataArrayIdType> ret(DataArrayIdType::New()); ret->alloc(nbOfNodes,1);
4308   std::transform(nodeIdsInUse.begin(),nodeIdsInUse.end(),ret->getPointer(),MEDLoaderAccVisit1());
4309   MCAuto<DataArrayIdType> ret2(ret->invertArrayO2N2N2OBis(nbrOfNodesInUse));
4310   MCAuto<DataArrayDouble> newCoords(coo->selectByTupleIdSafe(ret2->begin(),ret2->end()));
4311   MCAuto<DataArrayIdType> newFamCoords;
4312   MCAuto<DataArrayAsciiChar> newNameCoords;
4313   if((const DataArrayIdType *)_fam_coords)
4314     newFamCoords=_fam_coords->selectByTupleIdSafe(ret2->begin(),ret2->end());
4315   MCAuto<DataArrayIdType> newNumCoords,newGlobalNumCoords;
4316   if(_num_coords.isNotNull())
4317     newNumCoords=_num_coords->selectByTupleIdSafe(ret2->begin(),ret2->end());
4318   if(_global_num_coords.isNotNull())
4319     newGlobalNumCoords=_global_num_coords->selectByTupleIdSafe(ret2->begin(),ret2->end());
4320   if(_name_coords.isNotNull())
4321     newNameCoords=static_cast<DataArrayAsciiChar *>(_name_coords->selectByTupleIdSafe(ret2->begin(),ret2->end()));
4322   _coords=newCoords; _fam_coords=newFamCoords; _num_coords=newNumCoords; _global_num_coords=newGlobalNumCoords; _name_coords=newNameCoords; _rev_num_coords.nullify();
4323   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
4324     {
4325       if((MEDFileUMeshSplitL1*)*it)
4326         {
4327           (*it)->renumberNodesInConn(ret->begin());
4328           (*it)->setCoords(_coords);
4329         }
4330     }
4331   // updates _part_coords
4332   const PartDefinition *pc(_part_coords);
4333   if(pc)
4334     {
4335       MCAuto<PartDefinition> tmpPD(DataArrayPartDefinition::New(ret2));
4336       _part_coords=tmpPD->composeWith(pc);
4337     }
4338   return ret.retn();
4339 }
4340
4341 /*!
4342  * This method is the extension of MEDCouplingUMesh::computeFetchedNodeIds. Except that here all levels are considered here.
4343  * 
4344  * \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.
4345  */
4346 DataArrayIdType *MEDFileUMesh::computeFetchedNodeIds() const
4347 {
4348   std::vector<int> neLevs(this->getNonEmptyLevels());
4349   std::vector<bool> nodesHighlighted(this->getNumberOfNodes(),false);
4350   for(auto lev : neLevs)
4351   {
4352     const MEDFileUMeshSplitL1 *zeLev(this->getMeshAtLevSafe(lev));
4353     zeLev->highlightUsedNodes(nodesHighlighted);
4354   }
4355   return DataArrayIdType::BuildListOfSwitchedOn(nodesHighlighted);
4356 }
4357
4358 /*!
4359  * This method is a const method. It computes the minimal set of node ids covered by the cell extraction of \a this.
4360  * The extraction of \a this is specified by the extractDef \a input map.
4361  * This map tells for each level of cells, the cells kept in the extraction.
4362  * 
4363  * \return - a new reference of DataArrayIdType that represents sorted node ids, the extraction is lying on.
4364  * \sa MEDFileField1TS::extractPart, MEDFileUMesh::extractPart
4365  */
4366 DataArrayIdType *MEDFileUMesh::deduceNodeSubPartFromCellSubPart(const std::map<int, MCAuto<DataArrayIdType> >& extractDef) const
4367 {
4368   std::vector<int> levs(getNonEmptyLevels());
4369   std::vector<bool> fetchedNodes(getNumberOfNodes(),false);
4370   for(std::map<int, MCAuto<DataArrayIdType> >::const_iterator it=extractDef.begin();it!=extractDef.end();it++)
4371     {
4372       if((*it).first>1)
4373         throw INTERP_KERNEL::Exception("MEDFileUMesh::deduceNodeSubPartFromCellSubPart : invalid key ! Must be <=1 !");
4374       if((*it).second.isNull())
4375         throw INTERP_KERNEL::Exception("MEDFileUMesh::deduceNodeSubPartFromCellSubPart : presence of a value with null pointer !");
4376       if((*it).first==1)
4377         continue;
4378       if(std::find(levs.begin(),levs.end(),(*it).first)==levs.end())
4379         {
4380           std::ostringstream oss; oss << "MEDFileUMesh::deduceNodeSubPartFromCellSubPart : invalid level " << (*it).first << " ! Not present in this !";
4381           throw INTERP_KERNEL::Exception(oss.str());
4382         }
4383       MCAuto<MEDCouplingUMesh> m(getMeshAtLevel((*it).first));
4384       MCAuto<MEDCouplingUMesh> mPart(m->buildPartOfMySelf((*it).second->begin(),(*it).second->end(),true));
4385       mPart->computeNodeIdsAlg(fetchedNodes);
4386     }
4387   return DataArrayIdType::BuildListOfSwitchedOn(fetchedNodes);
4388 }
4389
4390 /*!
4391  * This method returns a new MEDFileUMesh that is the result of the extraction of cells/nodes in \a this.
4392  * 
4393  * \return - a new reference of MEDFileUMesh
4394  * \sa MEDFileUMesh::deduceNodeSubPartFromCellSubPart, MEDFileFields::extractPart
4395  */
4396 MEDFileUMesh *MEDFileUMesh::extractPart(const std::map<int, MCAuto<DataArrayIdType> >& extractDef) const
4397 {
4398   MCAuto<MEDFileUMesh> ret(MEDFileUMesh::New()); ret->setName(getName()); ret->copyFamGrpMapsFrom(*this);
4399   std::vector<int> levs(getNonEmptyLevels());
4400   for(std::map<int, MCAuto<DataArrayIdType> >::const_iterator it=extractDef.begin();it!=extractDef.end();it++)
4401     {
4402       if((*it).first>1)
4403         throw INTERP_KERNEL::Exception("MEDFileUMesh::extractPart : invalid key ! Must be <=1 !");
4404       if((*it).second.isNull())
4405         throw INTERP_KERNEL::Exception("MEDFileUMesh::extractPart : presence of a value with null pointer !");
4406       if((*it).first==1)
4407         continue;
4408       if(std::find(levs.begin(),levs.end(),(*it).first)==levs.end())
4409         {
4410           std::ostringstream oss; oss << "MEDFileUMesh::extractPart : invalid level " << (*it).first << " ! Not present in this !";
4411           throw INTERP_KERNEL::Exception(oss.str());
4412         }
4413       MCAuto<MEDCouplingUMesh> m(getMeshAtLevel((*it).first));
4414       MCAuto<MEDCouplingUMesh> mPart(m->buildPartOfMySelf((*it).second->begin(),(*it).second->end(),true));
4415       ret->setMeshAtLevel((*it).first,mPart);
4416       const DataArrayIdType *fam(getFamilyFieldAtLevel((*it).first)),*num(getNumberFieldAtLevel((*it).first));
4417       if(fam)
4418         {
4419           MCAuto<DataArrayIdType> famPart(fam->selectByTupleIdSafe((*it).second->begin(),(*it).second->end()));
4420           ret->setFamilyFieldArr((*it).first,famPart);
4421         }
4422       if(num)
4423         {
4424           MCAuto<DataArrayIdType> numPart(num->selectByTupleIdSafe((*it).second->begin(),(*it).second->end()));
4425           ret->setFamilyFieldArr((*it).first,numPart);
4426         }
4427     }
4428   std::map<int, MCAuto<DataArrayIdType> >::const_iterator it2(extractDef.find(1));
4429   if(it2!=extractDef.end())
4430     {
4431       const DataArrayDouble *coo(ret->getCoords());
4432       if(!coo)
4433         throw INTERP_KERNEL::Exception("MEDFileUMesh::extractPart : trying to extract nodes whereas there is no nodes !");
4434       MCAuto<DataArrayIdType> o2nNodes(((*it2).second)->invertArrayN2O2O2N(coo->getNumberOfTuples()));
4435       MCAuto<DataArrayDouble> cooPart(coo->selectByTupleIdSafe((*it2).second->begin(),(*it2).second->end()));
4436       ret->setCoords(cooPart);
4437       const DataArrayIdType *fam(getFamilyFieldAtLevel(1)),*num(getNumberFieldAtLevel(1));
4438       if(fam)
4439         {
4440           MCAuto<DataArrayIdType> famPart(fam->selectByTupleIdSafe((*it2).second->begin(),(*it2).second->end()));
4441           ret->setFamilyFieldArr(1,famPart);
4442         }
4443       if(num)
4444         {
4445           MCAuto<DataArrayIdType> numPart(num->selectByTupleIdSafe((*it2).second->begin(),(*it2).second->end()));
4446           ret->setFamilyFieldArr(1,numPart);
4447         }
4448       for(std::map<int, MCAuto<DataArrayIdType> >::const_iterator it3=extractDef.begin();it3!=extractDef.end();it3++)
4449         {
4450           if((*it3).first==1)
4451             continue;
4452           MCAuto<MEDCouplingUMesh> m(ret->getMeshAtLevel((*it3).first));
4453           m->renumberNodesInConn(o2nNodes->begin());
4454           ret->setMeshAtLevel((*it3).first,m);
4455         }
4456     }
4457   return ret.retn();
4458 }
4459
4460 /*!
4461  * This method performs an extrusion along a path defined by \a m1D.
4462  * \a this is expected to be a mesh with max mesh dimension equal to 2.
4463  * \a m1D is expected to be a mesh with space dimesion equal to 3 and mesh dimension equal to 1.
4464  * Mesh dimensions of returned mesh is incremented by one compared to thoose in \a this.
4465  * This method scans all levels in \a this
4466  * and put them in the returned mesh. All groups in \a this are also put in the returned mesh.
4467  *
4468  * \param [in] m1D - the mesh defining the extrusion path.
4469  * \param [in] policy - defines the policy of extrusion (see MEDCouplingUMesh::buildExtrudedMesh for more details)
4470  * \return - a new reference on mesh (you have to deal with using decrRef). The returned mesh will have the same name than \a this.
4471  *
4472  * \sa MEDCouplingUMesh::buildExtrudedMesh
4473  */
4474 MEDFileUMesh *MEDFileUMesh::buildExtrudedMesh(const MEDCouplingUMesh *m1D, int policy) const
4475 {
4476   checkCartesian();
4477   if(getMeshDimension()!=2)
4478     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildExtrudedMesh : this is expected to be with mesh dimension equal to 2 !");
4479   MCAuto<MEDFileUMesh> ret(MEDFileUMesh::New());
4480   m1D->checkConsistencyLight();
4481   if(m1D->getMeshDimension()!=1)
4482     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildExtrudedMesh : input mesh must have a mesh dimension equal to one !");
4483   mcIdType nbRep(m1D->getNumberOfCells());
4484   std::vector<int> levs(getNonEmptyLevels());
4485   std::vector<std::string> grps(getGroupsNames());
4486   std::vector< MCAuto<MEDCouplingUMesh> > zeList;
4487   DataArrayDouble *coords(0);
4488   std::size_t nbOfLevsOut(levs.size()+1);
4489   std::vector< MCAuto<DataArrayIdType> > o2ns(nbOfLevsOut);
4490   for(std::vector<int>::const_iterator lev=levs.begin();lev!=levs.end();lev++)
4491     {
4492       MCAuto<MEDCouplingUMesh> item(getMeshAtLevel(*lev));
4493       item=item->clone(false);
4494       item->changeSpaceDimension(3+(*lev),0.);//no problem non const but change DataArrayDouble for coordinates do not alter data
4495       MCAuto<MEDCouplingUMesh> tmp(static_cast<MEDCouplingUMesh *>(m1D->deepCopy()));
4496       tmp->changeSpaceDimension(3+(*lev),0.);
4497       MCAuto<MEDCouplingUMesh> elt(item->buildExtrudedMesh(tmp,policy));
4498       zeList.push_back(elt);
4499       if(*lev==0)
4500         coords=elt->getCoords();
4501     }
4502   if(!coords)
4503     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildExtrudedMesh : internal error !");
4504   for(std::vector< MCAuto<MEDCouplingUMesh> >::iterator it=zeList.begin();it!=zeList.end();it++)
4505     {
4506       (*it)->setName(getName());
4507       (*it)->setCoords(coords);
4508     }
4509   for(std::size_t ii=0;ii!=zeList.size();ii++)
4510     {
4511       int lev(levs[ii]);
4512       MCAuto<MEDCouplingUMesh> elt(zeList[ii]);
4513       if(lev<=-1)
4514         {
4515           MCAuto<MEDCouplingUMesh> elt1(getMeshAtLevel(lev+1));
4516           MCAuto<MEDCouplingUMesh> elt2(elt1->clone(false));
4517           MCAuto<DataArrayIdType> tmp(elt2->getNodalConnectivity()->deepCopy());
4518           elt2->setConnectivity(tmp,elt2->getNodalConnectivityIndex());
4519           elt2->shiftNodeNumbersInConn(nbRep*elt1->getNumberOfNodes());
4520           elt1->setCoords(elt->getCoords()); elt2->setCoords(elt->getCoords());
4521           std::vector<const MEDCouplingUMesh *> elts(3);
4522           elts[0]=elt; elts[1]=elt1; elts[2]=elt2;
4523           elt=MEDCouplingUMesh::MergeUMeshesOnSameCoords(elts);
4524           elt->setName(getName());
4525         }
4526       //
4527       o2ns[ii]=elt->sortCellsInMEDFileFrmt();
4528       ret->setMeshAtLevel(lev,elt);
4529     }
4530   MCAuto<MEDCouplingUMesh> endLev(getMeshAtLevel(levs.back())),endLev2;
4531   endLev=endLev->clone(false); endLev->setCoords(coords);
4532   MCAuto<DataArrayIdType> tmp(endLev->getNodalConnectivity()->deepCopy());
4533   endLev2=endLev->clone(false); endLev2->setConnectivity(tmp,endLev->getNodalConnectivityIndex());
4534   endLev2->shiftNodeNumbersInConn(nbRep*getNumberOfNodes());
4535   endLev=MEDCouplingUMesh::MergeUMeshesOnSameCoords(endLev,endLev2);
4536   o2ns[levs.size()]=endLev->sortCellsInMEDFileFrmt();
4537   endLev->setName(getName());
4538   ret->setMeshAtLevel(levs.back()-1,endLev);
4539   //
4540   for(std::size_t ii=0;ii!=zeList.size();ii++)
4541     {
4542       int lev(levs[ii]);
4543       std::vector< MCAuto<DataArrayIdType> > outGrps;
4544       std::vector< const DataArrayIdType * > outGrps2;
4545       if(lev<=-1)
4546         {
4547           for(std::vector<std::string>::const_iterator grp=grps.begin();grp!=grps.end();grp++)
4548             {
4549               MCAuto<DataArrayIdType> grpArr(getGroupArr(lev+1,*grp));
4550               if(!grpArr->empty())
4551                 {
4552                   MCAuto<DataArrayIdType> grpArr1(grpArr->deepCopy()),grpArr2(grpArr->deepCopy());
4553                   mcIdType offset0(zeList[ii]->getNumberOfCells());
4554                   mcIdType offset1(offset0+getNumberOfCellsAtLevel(lev+1));
4555                   grpArr1->applyLin(1,offset0); grpArr2->applyLin(1,offset1);
4556                   std::ostringstream oss; oss << grpArr2->getName() << "_top";
4557                   grpArr2->setName(oss.str());
4558                   grpArr1->transformWithIndArr(o2ns[ii]->begin(),o2ns[ii]->end());
4559                   grpArr2->transformWithIndArr(o2ns[ii]->begin(),o2ns[ii]->end());
4560                   outGrps.push_back(grpArr1); outGrps.push_back(grpArr2);
4561                   outGrps2.push_back(grpArr1); outGrps2.push_back(grpArr2);
4562                 }
4563             }
4564         }
4565       //
4566       for(std::vector<std::string>::const_iterator grp=grps.begin();grp!=grps.end();grp++)
4567         {
4568           MCAuto<DataArrayIdType> grpArr(getGroupArr(lev,*grp));
4569           if(!grpArr->empty())
4570             {
4571               mcIdType nbCellsB4Extrusion(getNumberOfCellsAtLevel(lev));
4572               std::vector< MCAuto<DataArrayIdType> > grpArrs(nbRep);
4573               std::vector< const DataArrayIdType *> grpArrs2(nbRep);
4574               for(int iii=0;iii<nbRep;iii++)
4575                 {
4576                   grpArrs[iii]=grpArr->deepCopy(); grpArrs[iii]->applyLin(1,iii*nbCellsB4Extrusion);
4577                   grpArrs2[iii]=grpArrs[iii];
4578                 }
4579               MCAuto<DataArrayIdType> grpArrExt(DataArrayIdType::Aggregate(grpArrs2));
4580               grpArrExt->transformWithIndArr(o2ns[ii]->begin(),o2ns[ii]->end());
4581               std::ostringstream grpName; grpName << *grp << "_extruded";
4582               grpArrExt->setName(grpName.str());
4583               outGrps.push_back(grpArrExt);
4584               outGrps2.push_back(grpArrExt);
4585             }
4586         }
4587       ret->setGroupsAtLevel(lev,outGrps2);
4588     }
4589   std::vector< MCAuto<DataArrayIdType> > outGrps;
4590   std::vector< const DataArrayIdType * > outGrps2;
4591   for(std::vector<std::string>::const_iterator grp=grps.begin();grp!=grps.end();grp++)
4592     {
4593       MCAuto<DataArrayIdType> grpArr1(getGroupArr(levs.back(),*grp));
4594       if(grpArr1->empty())
4595         continue;
4596       MCAuto<DataArrayIdType> grpArr2(grpArr1->deepCopy());
4597       std::ostringstream grpName; grpName << *grp << "_top";
4598       grpArr2->setName(grpName.str());
4599       grpArr2->applyLin(1,getNumberOfCellsAtLevel(levs.back()));
4600       outGrps.push_back(grpArr1); outGrps.push_back(grpArr2);
4601       outGrps2.push_back(grpArr1); outGrps2.push_back(grpArr2);
4602     }
4603   ret->setGroupsAtLevel(levs.back()-1,outGrps2);
4604   return ret.retn();
4605 }
4606
4607 /*!
4608  * This method converts all linear cells in \a this into quadratic cells (following the \a conversionType policy).
4609  * All the cells converted are put in the returned instance. This method applies all the groups and families in \a this to returned instance.
4610  * Groups on nodes and families on nodes are copied directly to the returned instance without transformation.
4611  *
4612  * \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
4613  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
4614  * \param [in] eps - detection threshold for coordinates.
4615  * \return A new instance that is the result of the conversion. The caller has the ownership of this returned instance.
4616  *
4617  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic , quadraticToLinear
4618  */
4619 MEDFileUMesh *MEDFileUMesh::linearToQuadratic(int conversionType, double eps) const
4620 {
4621   checkCartesian();
4622   MCAuto<MEDFileUMesh> ret(MEDFileUMesh::New());
4623   mcIdType initialNbNodes(getNumberOfNodes());
4624   MCAuto<MEDCouplingUMesh> m0Tmp(getMeshAtLevel(0));
4625   MCAuto<MEDCouplingUMesh> m0(dynamic_cast<MEDCouplingUMesh *>(m0Tmp->deepCopy()));
4626   {
4627     MCAuto<DataArrayIdType> notUsed(m0->convertLinearCellsToQuadratic(conversionType));
4628   }
4629   DataArrayDouble *zeCoords(m0->getCoords());
4630   ret->setMeshAtLevel(0,m0);
4631   std::vector<int> levs(getNonEmptyLevels());
4632   const DataArrayIdType *famField(getFamilyFieldAtLevel(0));
4633   if(famField)
4634     {
4635       MCAuto<DataArrayIdType> famFieldCpy(famField->deepCopy());
4636       ret->setFamilyFieldArr(0,famFieldCpy);
4637     }
4638   famField=getFamilyFieldAtLevel(1);
4639   if(famField)
4640     {
4641       MCAuto<DataArrayIdType> fam(DataArrayIdType::New()); fam->alloc(zeCoords->getNumberOfTuples(),1);
4642       fam->fillWithZero();
4643       fam->setPartOfValues1(famField,0,initialNbNodes,1,0,1,1);
4644       ret->setFamilyFieldArr(1,fam);
4645     }
4646   ret->copyFamGrpMapsFrom(*this);
4647   MCAuto<DataArrayDouble> partZeCoords(zeCoords->selectByTupleIdSafeSlice(initialNbNodes,zeCoords->getNumberOfTuples(),1));
4648   for(std::vector<int>::const_iterator lev=levs.begin();lev!=levs.end();lev++)
4649     {
4650       if(*lev==0)
4651         continue;
4652       MCAuto<MEDCouplingUMesh> m1Tmp(getMeshAtLevel(*lev));
4653       MCAuto<MEDCouplingUMesh> m1(dynamic_cast<MEDCouplingUMesh *>(m1Tmp->deepCopy()));
4654       if(m1->getMeshDimension()!=0)
4655         {
4656           {
4657             MCAuto<DataArrayIdType> notUsed(m1->convertLinearCellsToQuadratic(conversionType));
4658           }//kill unused notUsed var
4659           MCAuto<DataArrayDouble> m1Coords(m1->getCoords()->selectByTupleIdSafeSlice(initialNbNodes,m1->getNumberOfNodes(),1));
4660           DataArrayIdType *b(0);
4661           bool a(partZeCoords->areIncludedInMe(m1Coords,eps,b));
4662           MCAuto<DataArrayIdType> bSafe(b);
4663           if(!a)
4664             {
4665               std::ostringstream oss; oss << "MEDFileUMesh::linearCellsToQuadratic : for level " << *lev << " problem to identify nodes generated !";
4666               throw INTERP_KERNEL::Exception(oss.str().c_str());
4667             }
4668           b->applyLin(1,initialNbNodes);
4669           MCAuto<DataArrayIdType> l0(DataArrayIdType::New()); l0->alloc(initialNbNodes,1); l0->iota();
4670           std::vector<const DataArrayIdType *> v(2); v[0]=l0; v[1]=b;
4671           MCAuto<DataArrayIdType> renum(DataArrayIdType::Aggregate(v));
4672           m1->renumberNodesInConn(renum->begin());
4673         }
4674       m1->setCoords(zeCoords);
4675       ret->setMeshAtLevel(*lev,m1);
4676       famField=getFamilyFieldAtLevel(*lev);
4677       if(famField)
4678         {
4679           MCAuto<DataArrayIdType> famFieldCpy(famField->deepCopy());
4680           ret->setFamilyFieldArr(*lev,famFieldCpy);
4681         }
4682     }
4683   return ret.retn();
4684 }
4685
4686 /*!
4687  * This method converts all quadratic cells in \a this into linear cells.
4688  * All the cells converted are put in the returned instance. This method applies all the groups and families in \a this to returned instance.
4689  * Groups on nodes and families on nodes are copied directly to the returned instance without transformation.
4690  *
4691  * \param [in] eps - detection threshold for coordinates.
4692  * \return A new instance that is the result of the conversion. The caller has the ownership of this returned instance.
4693  *
4694  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic , linearToQuadratic
4695  */
4696 MEDFileUMesh *MEDFileUMesh::quadraticToLinear(double eps) const
4697 {
4698   checkCartesian();
4699   MCAuto<MEDFileUMesh> ret(MEDFileUMesh::New());
4700   MCAuto<MEDCouplingUMesh> m0Tmp(getMeshAtLevel(0));
4701   MCAuto<MEDCouplingUMesh> m0(dynamic_cast<MEDCouplingUMesh *>(m0Tmp->deepCopy()));
4702   m0->convertQuadraticCellsToLinear();
4703   m0->zipCoords();
4704   DataArrayDouble *zeCoords(m0->getCoords());
4705   ret->setMeshAtLevel(0,m0);
4706   std::vector<int> levs(getNonEmptyLevels());
4707   const DataArrayIdType *famField(getFamilyFieldAtLevel(0));
4708   if(famField)
4709     {
4710       MCAuto<DataArrayIdType> famFieldCpy(famField->deepCopy());
4711       ret->setFamilyFieldArr(0,famFieldCpy);
4712     }
4713   famField=getFamilyFieldAtLevel(1);
4714   if(famField)
4715     {
4716       MCAuto<DataArrayIdType> fam(famField->selectByTupleIdSafeSlice(0,zeCoords->getNumberOfTuples(),1));
4717       ret->setFamilyFieldArr(1,fam);
4718     }
4719   ret->copyFamGrpMapsFrom(*this);
4720   for(std::vector<int>::const_iterator lev=levs.begin();lev!=levs.end();lev++)
4721     {
4722       if(*lev==0)
4723         continue;
4724       MCAuto<MEDCouplingUMesh> m1Tmp(getMeshAtLevel(*lev));
4725       MCAuto<MEDCouplingUMesh> m1(dynamic_cast<MEDCouplingUMesh *>(m1Tmp->deepCopy()));
4726       m1->convertQuadraticCellsToLinear();
4727       m1->zipCoords();
4728       DataArrayIdType *b(0);
4729       bool a(zeCoords->areIncludedInMe(m1->getCoords(),eps,b));
4730       MCAuto<DataArrayIdType> bSafe(b);
4731       if(!a)
4732         {
4733           std::ostringstream oss; oss << "MEDFileUMesh::quadraticToLinear : for level " << *lev << " problem to identify nodes generated !";
4734           throw INTERP_KERNEL::Exception(oss.str().c_str());
4735         }
4736       m1->renumberNodesInConn(b->begin());
4737       m1->setCoords(zeCoords);
4738       ret->setMeshAtLevel(*lev,m1);
4739       famField=getFamilyFieldAtLevel(*lev);
4740       if(famField)
4741         {
4742           MCAuto<DataArrayIdType> famFieldCpy(famField->deepCopy());
4743           ret->setFamilyFieldArr(*lev,famFieldCpy);
4744         }
4745     }
4746   return ret.retn();
4747 }
4748
4749 /*!
4750  * Computes the symmetry of \a this.
4751  * \return a new object.
4752  */
4753 MCAuto<MEDFileUMesh> MEDFileUMesh::symmetry3DPlane(const double point[3], const double normalVector[3]) const
4754 {
4755   MCAuto<MEDFileUMesh> ret(deepCopy());
4756   DataArrayDouble *myCoo(getCoords());
4757   if(myCoo)
4758     {
4759       MCAuto<DataArrayDouble> newCoo(myCoo->symmetry3DPlane(point,normalVector));
4760       ret->setCoordsForced(newCoo);
4761     }
4762   return ret;
4763 }
4764
4765 /*!
4766  * Aggregate the given MEDFileUMesh objects into a single mesh. When groups are present, those are
4767  * merged in such a way that the final mesh contain all of them.
4768  * \return a new object.
4769  */
4770 MCAuto<MEDFileUMesh> MEDFileUMesh::Aggregate(const std::vector<const MEDFileUMesh *>& meshes)
4771 {
4772   if(meshes.empty())
4773     throw INTERP_KERNEL::Exception("MEDFileUMesh::Aggregate : empty input vector !");
4774   std::size_t sz(meshes.size()),i(0);
4775   std::vector<const DataArrayDouble *> coos(sz);
4776   std::vector<const DataArrayIdType *> fam_coos(sz),num_coos(sz);
4777   for(auto it=meshes.begin();it!=meshes.end();it++,i++)
4778     {
4779       if(!(*it))
4780         throw INTERP_KERNEL::Exception("MEDFileUMesh::Aggregate : presence of NULL pointer in input vector !");
4781       coos[i]=(*it)->getCoords();
4782       fam_coos[i]=(*it)->getFamilyFieldAtLevel(1);
4783       num_coos[i]=(*it)->getNumberFieldAtLevel(1);
4784     }
4785   const MEDFileUMesh *ref(meshes[0]);
4786   int spaceDim(ref->getSpaceDimension()),meshDim(ref->getMeshDimension());
4787   std::vector<int> levs(ref->getNonEmptyLevels());
4788   std::map<int, std::vector<const DataArrayIdType *> > m_fam,m_renum;
4789   std::map<int, std::vector< MCAuto< MEDCouplingUMesh > > > m_mesh2;
4790   std::map<int, std::vector<const MEDCouplingUMesh *> > m_mesh;
4791   std::map<std::string,mcIdType> famNumMap;
4792   std::map<mcIdType, std::string> famNumMap_rev;
4793   std::map<std::string, std::vector<std::string> > grpFamMap;
4794   std::set< MCAuto<DataArrayIdType> > mem_cleanup;   // Memory clean-up. At set deletion (end of method), arrays will be deallocated.
4795
4796   // Identify min family number used:
4797   mcIdType min_fam_num(0);
4798   for(const auto& msh : meshes)
4799     {
4800       const std::map<std::string,mcIdType>& locMap1(msh->getFamilyInfo());
4801       for(const auto& it3 : locMap1)
4802         if(it3.second < min_fam_num)
4803           min_fam_num = it3.second;
4804     }
4805
4806   for(const auto& msh : meshes)
4807     {
4808       if(msh->getSpaceDimension()!=spaceDim)
4809         throw INTERP_KERNEL::Exception("MEDFileUMesh::Aggregate : space dimension must be homogeneous !");
4810       if(msh->getMeshDimension()!=meshDim)
4811         throw INTERP_KERNEL::Exception("MEDFileUMesh::Aggregate : mesh dimension must be homogeneous !");
4812       if(msh->getNonEmptyLevels()!=levs)
4813         throw INTERP_KERNEL::Exception("MEDFileUMesh::Aggregate : levels must be the same for elements in input vector !");
4814
4815       const std::map<std::string,mcIdType>& locMap1(msh->getFamilyInfo());
4816       std::map<std::string, std::string> substitute;
4817       std::map<mcIdType, mcIdType> substituteN;
4818       bool fam_conflict(false);
4819       for(const auto& it3 : locMap1)
4820         {
4821           const std::string& famName = it3.first;
4822           mcIdType famNum = it3.second;
4823           if (famNumMap_rev.find(famNum) != famNumMap_rev.end()) // Family number is already used!
4824             {
4825               // Is it used by a group of the current mesh or a group from a previous mesh?
4826               // If not, this is OK (typically -1 familly).
4827               bool used = false;
4828               //    Current mesh
4829               const std::map<std::string, std::vector<std::string> >& locMap2(msh->getGroupInfo());
4830               for(const auto& it4 : locMap2)
4831                 {
4832                   const auto& famLst = it4.second;
4833                   if (std::find(famLst.begin(), famLst.end(), famName) != famLst.end())
4834                     { used = true; break; }
4835                 }
4836               //    Previous meshes ...
4837               if (!used)
4838                 for(const auto& it4 : grpFamMap)
4839                   {
4840                     const auto& famLst = it4.second;
4841                     if (std::find(famLst.begin(), famLst.end(), famName) != famLst.end())
4842                       { used = true; break; }
4843                   }
4844
4845               if(used)
4846                 { // Generate a new family name, and a new family number
4847                   fam_conflict = true;
4848                   std::ostringstream oss;
4849                   oss << "Family_" << --min_fam_num;  // New ID
4850                   std::string new_name(oss.str());
4851                   substitute[famName] = new_name;
4852                   substituteN[famNum] = min_fam_num;
4853                   famNumMap[new_name] = min_fam_num;
4854                   famNumMap_rev[min_fam_num] = new_name;
4855                 }
4856             }
4857           famNumMap[famName] = famNum;
4858           famNumMap_rev[famNum] = famName;
4859         }
4860
4861       for(const auto& level : levs)
4862         {
4863           MCAuto<MEDCouplingUMesh> locMesh(msh->getMeshAtLevel(level));
4864           m_mesh[level].push_back(locMesh); m_mesh2[level].push_back(locMesh);
4865           m_renum[level].push_back(msh->getNumberFieldAtLevel(level));
4866
4867           // Family field - substitute new family number if needed:
4868           if(fam_conflict)
4869             {
4870               DataArrayIdType* dai(msh->getFamilyFieldAtLevel(level)->deepCopy());  // Need a copy
4871               mem_cleanup.insert(MCAuto<DataArrayIdType>(dai));      // Make sure array will decrRef() at end of method
4872               for (const auto& subN : substituteN)
4873                 dai->changeValue(subN.first, subN.second);
4874               m_fam[level].push_back(dai);
4875             }
4876           else
4877             m_fam[level].push_back(msh->getFamilyFieldAtLevel(level));      // No copy needed
4878         }
4879
4880       const std::map<std::string, std::vector<std::string> >& locMap2(msh->getGroupInfo());
4881       for(const auto& grpItem : locMap2)
4882         {
4883           const std::string& grpName = grpItem.first;
4884           std::vector<std::string> famLst;
4885           // Substitute family name in group description if needed:
4886           if (fam_conflict)
4887             {
4888               famLst = grpItem.second;
4889               for (const auto& sub : substitute)
4890                 std::replace(famLst.begin(), famLst.end(), sub.first, sub.second);
4891             }
4892           else
4893             famLst = grpItem.second;
4894
4895           // Potentially merge groups (if same name):
4896           const auto& it = grpFamMap.find(grpName);
4897           if (it != grpFamMap.end())
4898             {
4899               // Group already exists, merge should be done. Normally we whould never
4900               // have twice the same family name in famLstCur and famLst since we dealt with family number
4901               // conflict just above ...
4902               std::vector<std::string>& famLstCur = (*it).second;
4903               famLstCur.insert(famLstCur.end(), famLst.begin(), famLst.end());
4904             }
4905           else
4906             grpFamMap[grpName] = famLst;
4907         }
4908     }
4909   // Easy part : nodes
4910   MCAuto<MEDFileUMesh> ret(MEDFileUMesh::New());
4911   MCAuto<DataArrayDouble> coo(DataArrayDouble::Aggregate(coos));
4912   ret->setCoords(coo);
4913   if(std::find(fam_coos.begin(),fam_coos.end(),(const DataArrayIdType *)0)==fam_coos.end())
4914     {
4915       MCAuto<DataArrayIdType> fam_coo(DataArrayIdType::Aggregate(fam_coos));
4916       ret->setFamilyFieldArr(1,fam_coo);
4917     }
4918   if(std::find(num_coos.begin(),num_coos.end(),(const DataArrayIdType *)0)==num_coos.end())
4919     {
4920       MCAuto<DataArrayIdType> num_coo(DataArrayIdType::Aggregate(num_coos));
4921       ret->setRenumFieldArr(1,num_coo);
4922     }
4923   // cells
4924   for(const auto& level : levs)
4925     {
4926       auto it2(m_mesh.find(level));
4927       if(it2==m_mesh.end())
4928         throw INTERP_KERNEL::Exception("MEDFileUMesh::Aggregate : internal error 1 !");
4929       MCAuto<MEDCouplingUMesh> mesh(MEDCouplingUMesh::MergeUMeshes((*it2).second));
4930       mesh->setCoords(coo); mesh->setName(ref->getName());
4931       MCAuto<DataArrayIdType> renum(mesh->sortCellsInMEDFileFrmt());
4932       ret->setMeshAtLevel(level,mesh);
4933       auto it3(m_fam.find(level)),it4(m_renum.find(level));
4934       if(it3==m_fam.end()) // Should never happen (all levels exist for all meshes)
4935         throw INTERP_KERNEL::Exception("MEDFileUMesh::Aggregate : internal error 2!");
4936       if(it4==m_renum.end())
4937         throw INTERP_KERNEL::Exception("MEDFileUMesh::Aggregate : internal error 3!");
4938       // Set new family field if it was defined for all input meshes
4939       const std::vector<const DataArrayIdType *>& fams((*it3).second);
4940       if(std::find(fams.begin(),fams.end(),(const DataArrayIdType *)0)==fams.end())
4941         {
4942           MCAuto<DataArrayIdType> famm(DataArrayIdType::Aggregate(fams));
4943           famm->renumberInPlace(renum->begin());
4944           ret->setFamilyFieldArr(level,famm);
4945         }
4946       // Set optional number field if defined for all input meshes:
4947       const std::vector<const DataArrayIdType *>& renums((*it4).second);
4948       if(std::find(renums.begin(),renums.end(),(const DataArrayIdType *)0)==renums.end())
4949         {
4950           MCAuto<DataArrayIdType> renumm(DataArrayIdType::Aggregate(renums));
4951           renumm->renumberInPlace(renum->begin());
4952           ret->setRenumFieldArr(level,renumm);
4953         }
4954     }
4955   //
4956   ret->setFamilyInfo(famNumMap);
4957   ret->setGroupInfo(grpFamMap);
4958   ret->setName(ref->getName());
4959   return ret;
4960 }
4961
4962 MEDCouplingMappedExtrudedMesh *MEDFileUMesh::convertToExtrudedMesh() const
4963 {
4964   if(getMeshDimension()!=3)
4965     throw INTERP_KERNEL::Exception("MEDFileUMesh::convertToExtrudedMesh : works only for 3D mesh !");
4966   MCAuto<MEDCouplingUMesh> m3D(getMeshAtLevel(0)),m2D(getMeshAtLevel(-1));
4967   if(m3D.isNull() || m2D.isNull())
4968     throw INTERP_KERNEL::Exception("MEDFileUMesh::convertToExtrudedMesh : this must be defined both at level 0 and level -1 !");
4969   mcIdType zeId(std::numeric_limits<med_int>::max()-getFamilyId(GetSpeStr4ExtMesh()));
4970   MCAuto<MEDCouplingMappedExtrudedMesh> ret(MEDCouplingMappedExtrudedMesh::New(m3D,m2D,zeId));
4971   return ret.retn();
4972 }
4973
4974 void MEDFileUMesh::serialize(std::vector<double>& tinyDouble, std::vector<mcIdType>& tinyInt, std::vector<std::string>& tinyStr, std::vector< MCAuto<DataArrayIdType> >& bigArraysI, MCAuto<DataArrayDouble>& bigArrayD)
4975 {
4976   clearNonDiscrAttributes();
4977   forceComputationOfParts();
4978   tinyDouble.clear(); tinyInt.clear(); tinyStr.clear(); bigArraysI.clear(); bigArrayD=0;
4979   std::vector<mcIdType> layer0;
4980   layer0.push_back(getAxisType());//0 i
4981   layer0.push_back(_order); //1 i
4982   layer0.push_back(_iteration);//2 i
4983   layer0.push_back(getSpaceDimension());//3 i
4984   tinyDouble.push_back(_time);//0 d
4985   tinyStr.push_back(_name);//0 s
4986   tinyStr.push_back(_desc_name);//1 s
4987   for(int i=0;i<getSpaceDimension();i++)
4988     tinyStr.push_back(_coords->getInfoOnComponent(i));
4989   layer0.push_back(ToIdType(_families.size()));//4 i <- key info aa layer#0
4990   for(std::map<std::string,mcIdType>::const_iterator it=_families.begin();it!=_families.end();it++)
4991     {
4992       tinyStr.push_back((*it).first);
4993       layer0.push_back((*it).second);
4994     }
4995   layer0.push_back((mcIdType)_groups.size());//4+aa i <- key info bb layer#0
4996   for(std::map<std::string, std::vector<std::string> >::const_iterator it0=_groups.begin();it0!=_groups.end();it0++)
4997     {
4998       layer0.push_back(ToIdType((*it0).second.size()));
4999       tinyStr.push_back((*it0).first);
5000       for(std::vector<std::string>::const_iterator it1=((*it0).second).begin();it1!=((*it0).second).end();it1++)
5001         tinyStr.push_back(*it1);
5002     }
5003   // sizeof(layer0)==4+aa+1+bb layer#0
5004   bigArrayD=_coords;// 0 bd
5005   bigArraysI.push_back(_fam_coords);// 0 bi
5006   bigArraysI.push_back(_num_coords);// 1 bi
5007   const PartDefinition *pd(_part_coords);
5008   if(!pd)
5009     layer0.push_back(-1);
5010   else
5011     {
5012       std::vector<mcIdType> tmp0;
5013       pd->serialize(tmp0,bigArraysI);
5014       tinyInt.push_back(ToIdType(tmp0.size()));
5015       tinyInt.insert(tinyInt.end(),tmp0.begin(),tmp0.end());
5016     }
5017   //
5018   std::vector<mcIdType> layer1;
5019   std::vector<int> levs(getNonEmptyLevels());
5020   layer1.push_back((mcIdType)levs.size());// 0 i <- key
5021   layer1.insert(layer1.end(),levs.begin(),levs.end());
5022   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
5023     {
5024       const MEDFileUMeshSplitL1 *lev(getMeshAtLevSafe(*it));
5025       lev->serialize(layer1,bigArraysI);
5026     }
5027   // put layers all together.
5028   tinyInt.push_back(ToIdType(layer0.size()));
5029   tinyInt.insert(tinyInt.end(),layer0.begin(),layer0.end());
5030   tinyInt.push_back(ToIdType(layer1.size()));
5031   tinyInt.insert(tinyInt.end(),layer1.begin(),layer1.end());
5032 }
5033
5034 void MEDFileUMesh::unserialize(std::vector<double>& tinyDouble, std::vector<mcIdType>& tinyInt, std::vector<std::string>& tinyStr,
5035                                std::vector< MCAuto<DataArrayIdType> >& bigArraysI, MCAuto<DataArrayDouble>& bigArrayD)
5036 {
5037   mcIdType sz0(tinyInt[0]);
5038   std::vector<mcIdType> layer0(tinyInt.begin()+1,tinyInt.begin()+1+sz0);
5039   mcIdType sz1(tinyInt[sz0+1]);
5040   std::vector<mcIdType> layer1(tinyInt.begin()+2+sz0,tinyInt.begin()+2+sz0+sz1);
5041   //
5042   std::reverse(layer0.begin(),layer0.end());
5043   std::reverse(layer1.begin(),layer1.end());
5044   std::reverse(tinyDouble.begin(),tinyDouble.end());
5045   std::reverse(tinyStr.begin(),tinyStr.end());
5046   std::reverse(bigArraysI.begin(),bigArraysI.end());
5047   //
5048   setAxisType((MEDCouplingAxisType)layer0.back()); layer0.pop_back();
5049   _order=FromIdType<int>(layer0.back()); layer0.pop_back();
5050   _iteration=FromIdType<int>(layer0.back()); layer0.pop_back();
5051   mcIdType spaceDim(layer0.back()); layer0.pop_back();
5052   _time=tinyDouble.back(); tinyDouble.pop_back();
5053   _name=tinyStr.back(); tinyStr.pop_back();
5054   _desc_name=tinyStr.back(); tinyStr.pop_back();
5055   _coords=bigArrayD; _coords->rearrange(spaceDim);
5056   for(int i=0;i<spaceDim;i++)
5057     {
5058       _coords->setInfoOnComponent(i,tinyStr.back());
5059       tinyStr.pop_back();
5060     }
5061   mcIdType nbOfFams(layer0.back()); layer0.pop_back();
5062   _families.clear();
5063   for(mcIdType i=0;i<nbOfFams;i++)
5064     {
5065       _families[tinyStr.back()]=layer0.back();
5066       tinyStr.pop_back(); layer0.pop_back();
5067     }
5068   mcIdType nbGroups(layer0.back()); layer0.pop_back();
5069   _groups.clear();
5070   for(mcIdType i=0;i<nbGroups;i++)
5071     {
5072       std::string grpName(tinyStr.back()); tinyStr.pop_back();
5073       mcIdType nbOfFamsOnGrp(layer0.back()); layer0.pop_back();
5074       std::vector<std::string> fams(nbOfFamsOnGrp);
5075       for(mcIdType j=0;j<nbOfFamsOnGrp;j++)
5076         {
5077           fams[j]=tinyStr.back(); tinyStr.pop_back();
5078         }
5079       _groups[grpName]=fams;
5080     }
5081   _fam_coords=bigArraysI.back(); bigArraysI.pop_back();
5082   _num_coords=bigArraysI.back(); bigArraysI.pop_back();
5083   _part_coords=0;
5084   mcIdType isPd(layer0.back()); layer0.pop_back();
5085   if(isPd!=-1)
5086     {
5087       std::vector<mcIdType> tmp0(layer0.begin(),layer0.begin()+isPd);
5088       layer0.erase(layer0.begin(),layer0.begin()+isPd);
5089       _part_coords=PartDefinition::Unserialize(tmp0,bigArraysI);
5090     }
5091   if(!layer0.empty())
5092     throw INTERP_KERNEL::Exception("MEDFileUMesh::unserialize : something wrong during unserialization #1 !");
5093   //
5094   mcIdType nbLevs(layer1.back()); layer1.pop_back();
5095   std::vector<mcIdType> levs(layer1.rbegin(),layer1.rbegin()+nbLevs); layer1.erase(layer1.end()-nbLevs,layer1.end());
5096   _ms.clear();
5097   mcIdType maxLev(-(*std::min_element(levs.begin(),levs.end())));
5098   _ms.resize(maxLev+1);
5099   for(mcIdType i=0;i<nbLevs;i++)
5100     {
5101       mcIdType lev(levs[i]);
5102       mcIdType pos(-lev);
5103       _ms[pos]=MEDFileUMeshSplitL1::Unserialize(_name,_coords,layer1,bigArraysI);
5104     }
5105 }
5106
5107 /*!
5108  * Adds a group of nodes to \a this mesh.
5109  *  \param [in] ids - a DataArrayIdType providing ids and a name of the group to add.
5110  *          The ids should be sorted and different each other (MED file norm).
5111  *
5112  *  \warning this method can alter default "FAMILLE_ZERO" family.
5113  *  For users sensitive to this a call to MEDFileMesh::rearrangeFamilies will be necessary after addGroup session.
5114  *
5115  *  \throw If the node coordinates array is not set.
5116  *  \throw If \a ids == \c NULL.
5117  *  \throw If \a ids->getName() == "".
5118  *  \throw If \a ids does not respect the MED file norm.
5119  *  \throw If a group with name \a ids->getName() already exists.
5120  */
5121 void MEDFileUMesh::addNodeGroup(const DataArrayIdType *ids)
5122 {
5123   const DataArrayDouble *coords(_coords);
5124   if(!coords)
5125     throw INTERP_KERNEL::Exception("MEDFileUMesh::addNodeGroup : no coords set !");
5126   mcIdType nbOfNodes(coords->getNumberOfTuples());
5127   if(_fam_coords.isNull())
5128     { _fam_coords=DataArrayIdType::New(); _fam_coords->alloc(nbOfNodes,1); _fam_coords->fillWithZero(); }
5129   //
5130   addGroupUnderground(true,ids,_fam_coords);
5131 }
5132
5133 /*!
5134  * Adds a group of nodes/cells/faces/edges to \a this mesh.
5135  *
5136  *  \param [in] ids - a DataArrayIdType providing ids and a name of the group to add.
5137  *          The ids should be sorted and different each other (MED file norm).
5138  *
5139  * \warning this method can alter default "FAMILLE_ZERO" family.
5140  * For users sensitive to this a call to MEDFileMesh::rearrangeFamilies will be necessary after addGroup session.
5141  *
5142  *  \throw If the node coordinates array is not set.
5143  *  \throw If \a ids == \c NULL.
5144  *  \throw If \a ids->getName() == "".
5145  *  \throw If \a ids does not respect the MED file norm.
5146  *  \throw If a group with name \a ids->getName() already exists.
5147  */
5148 void MEDFileUMesh::addGroup(int meshDimRelToMaxExt, const DataArrayIdType *ids)
5149 {
5150   std::vector<int> levs(getNonEmptyLevelsExt());
5151   if(std::find(levs.begin(),levs.end(),meshDimRelToMaxExt)==levs.end())
5152     { 
5153       std::ostringstream oss; oss << "MEDFileUMesh::addGroup : level " << meshDimRelToMaxExt << " not available ! Should be in ";
5154       std::copy(levs.begin(),levs.end(),std::ostream_iterator<int>(oss," ")); oss << " !"; throw INTERP_KERNEL::Exception(oss.str().c_str());
5155     }
5156   if(meshDimRelToMaxExt==1)
5157     { addNodeGroup(ids); return ; }
5158   MEDFileUMeshSplitL1 *lev(getMeshAtLevSafe(meshDimRelToMaxExt));
5159   DataArrayIdType *fam(lev->getOrCreateAndGetFamilyField());
5160   addGroupUnderground(false,ids,fam);
5161 }
5162
5163 /*!
5164  * Changes a name of a family specified by its id.
5165  *  \param [in] id - the id of the family of interest.
5166  *  \param [in] newFamName - the new family name.
5167  *  \throw If no family with the given \a id exists.
5168  */
5169 void MEDFileUMesh::setFamilyNameAttachedOnId(mcIdType id, const std::string& newFamName)
5170 {
5171   std::string oldName=getFamilyNameGivenId(id);
5172   _families.erase(oldName);
5173   _families[newFamName]=id;
5174 }
5175
5176 /*!
5177  * Removes a mesh of a given dimension.
5178  *  \param [in] meshDimRelToMax - the relative dimension of interest.
5179  *  \throw If there is no mesh at level \a meshDimRelToMax in \a this mesh.
5180  */
5181 void MEDFileUMesh::removeMeshAtLevel(int meshDimRelToMax)
5182 {
5183   std::vector<int> levSet=getNonEmptyLevels();
5184   std::vector<int>::const_iterator it=std::find(levSet.begin(),levSet.end(),meshDimRelToMax);
5185   if(it==levSet.end())
5186     throw INTERP_KERNEL::Exception("MEDFileUMesh::removeMeshAtLevel : the requested level is not existing !");
5187   int pos=(-meshDimRelToMax);
5188   _ms[pos]=0;
5189 }
5190
5191 /*!
5192  * Sets a new MEDCoupling1GTUMesh at a given level in \a this mesh.
5193  *  \param [in] meshDimRelToMax - a relative level to set the mesh at.
5194  *  \param [in] m - the new mesh to set.
5195  *  \throw If the name or the description of \a this mesh and \a m are not empty and are
5196  *         different. 
5197  *  \throw If the node coordinates array is set \a this in mesh and \a m refers to
5198  *         another node coordinates array.
5199  *  \throw If the mesh dimension of \a m does not correspond to \a meshDimRelToMax or
5200  *         to the existing meshes of other levels of \a this mesh.
5201  */
5202 void MEDFileUMesh::setMeshAtLevel(int meshDimRelToMax, MEDCoupling1GTUMesh *m)
5203 {
5204   MCAuto<MEDFileUMeshSplitL1> elt(new MEDFileUMeshSplitL1(m));
5205   checkAndGiveEntryInSplitL1(meshDimRelToMax,m)=elt;
5206 }
5207
5208 /*!
5209  * Sets a new MEDCouplingUMesh at a given level in \a this mesh.
5210  *  \param [in] meshDimRelToMax - a relative level to set the mesh at.
5211  *  \param [in] m - the new mesh to set.
5212  *  \param [in] newOrOld - if \c true, cells in \a m are sorted by type to be ready for 
5213  *         writing \a this mesh in a MED file.
5214  *  \throw If the name or the description of \a this mesh and \a m are not empty and are
5215  *         different. 
5216  *  \throw If the node coordinates array is set \a this in mesh and \a m refers to
5217  *         another node coordinates array.
5218  *  \throw If the mesh dimension of \a m does not correspond to \a meshDimRelToMax or
5219  *         to the existing meshes of other levels of \a this mesh.
5220  */
5221 void MEDFileUMesh::setMeshAtLevel(int meshDimRelToMax, MEDCouplingUMesh *m, bool newOrOld)
5222 {
5223   MCAuto<MEDFileUMeshSplitL1> elt(new MEDFileUMeshSplitL1(m,newOrOld));
5224   checkAndGiveEntryInSplitL1(meshDimRelToMax,m)=elt;
5225 }
5226
5227 MCAuto<MEDFileUMeshSplitL1>& MEDFileUMesh::checkAndGiveEntryInSplitL1(int meshDimRelToMax, MEDCouplingPointSet *m)
5228 {
5229   dealWithTinyInfo(m);
5230   std::vector<int> levSet=getNonEmptyLevels();
5231   if(std::find(levSet.begin(),levSet.end(),meshDimRelToMax)==levSet.end())
5232     {
5233       if((DataArrayDouble *)_coords==0)
5234         {
5235           DataArrayDouble *c=m->getCoords();
5236           if(c)
5237             c->incrRef();
5238           _coords=c;
5239         }
5240       if(m->getCoords()!=_coords)
5241         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshAtLevel : Invalid Given Mesh ! The coordinates are not the same ! try to use tryToShareSameCoords !");
5242       int sz=(-meshDimRelToMax)+1;
5243       if(sz>=(int)_ms.size())
5244         _ms.resize(sz);
5245       checkMeshDimCoherency(m->getMeshDimension(),meshDimRelToMax);
5246       return _ms[sz-1];
5247     }
5248   else
5249     return _ms[-meshDimRelToMax];
5250 }
5251
5252 /*!
5253  * This method allows to set at once the content of different levels in \a this.
5254  * This method is equivalent to a series of call to MEDFileUMesh::setMeshAtLevel.
5255  *
5256  * \param [in] ms - List of unstructured meshes lying on the same coordinates and having different mesh dimesnion.
5257  * \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.
5258  *                     If false, an exception is thrown. If true the mesh is reordered automatically. It is highly recommended to let this parameter to false.
5259  *
5260  * \throw If \a there is a null pointer in \a ms.
5261  * \sa MEDFileUMesh::setMeshAtLevel
5262  */
5263 void MEDFileUMesh::setMeshes(const std::vector<const MEDCouplingUMesh *>& ms, bool renum)
5264 {
5265   if(ms.empty())
5266     return ;
5267   const MEDCouplingUMesh *mRef=ms[0];
5268   if(!mRef)
5269     throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : null instance in the first element of input meshes !");
5270   std::string name(mRef->getName());
5271   const DataArrayDouble *coo(mRef->getCoords());
5272   std::set<int> s;
5273   int zeDim=-1;
5274   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
5275     {
5276       const MEDCouplingUMesh *cur(*it);
5277       if(!cur)
5278         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : null instance in input vector of meshes !");
5279       if(coo!=cur->getCoords())
5280         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : The input meshes do not share the same coordinates !");
5281       int mdim=cur->getMeshDimension();
5282       zeDim=std::max(zeDim,mdim);
5283       if(s.find(mdim)!=s.end())
5284         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : The input meshes must share the same coordinates pointer, and should have different mesh dimension each other !");
5285     }
5286   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
5287     {
5288       int mdim=(*it)->getMeshDimension();
5289       setName((*it)->getName());
5290       setMeshAtLevel(mdim-zeDim,const_cast<MEDCouplingUMesh *>(*it),renum);
5291     }
5292   setName(name);
5293 }
5294
5295 /*!
5296  * Creates one MEDCouplingUMesh at a given level in \a this mesh from a sequence of
5297  * meshes each representing a group, and creates corresponding groups in \a this mesh.
5298  * The given meshes must share the same node coordinates array.
5299  *  \param [in] meshDimRelToMax - the relative dimension to create the mesh and groups at.
5300  *  \param [in] ms - the sequence of meshes. Each mesh in \a ms represents a group to
5301  *          create in \a this mesh.
5302  *  \throw If \a ms is empty.
5303  *  \throw If dimension of meshes in \a ms does not correspond to \a meshDimRelToMax or
5304  *         to the existing meshes of other levels of \a this mesh.
5305  *  \throw If the meshes in \a ms do not share the same node coordinates array.
5306  *  \throw If the node coordinates array of \a this mesh (if any) is not the same as that
5307  *         of the given meshes.
5308  *  \throw If \a ms[ i ] is not well defined (MEDCouplingUMesh::checkConsistencyLight()).
5309  *  \throw If names of some meshes in \a ms are equal.
5310  *  \throw If \a ms includes a mesh with an empty name.
5311  */
5312 void MEDFileUMesh::setGroupsFromScratch(int meshDimRelToMax, const std::vector<const MEDCouplingUMesh *>& ms, bool renum)
5313 {
5314   if(ms.empty())
5315     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsFromScratch : expecting a non empty vector !");
5316   int sz=(-meshDimRelToMax)+1;
5317   if(sz>=(int)_ms.size())
5318     _ms.resize(sz);
5319   checkMeshDimCoherency(ms[0]->getMeshDimension(),meshDimRelToMax);
5320   DataArrayDouble *coo=checkMultiMesh(ms);
5321   if((DataArrayDouble *)_coords==0)
5322     {
5323       coo->incrRef();
5324       _coords=coo;
5325     }
5326   else
5327     if((DataArrayDouble *)_coords!=coo)
5328       throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsFromScratch : coordinates mismatches !");
5329   std::vector<DataArrayIdType *> corr;
5330   MCAuto<MEDCouplingUMesh> m=MEDCouplingUMesh::FuseUMeshesOnSameCoords(ms,_zipconn_pol,corr);
5331   std::vector< MCAuto<DataArrayIdType> > corr3(corr.begin(),corr.end());
5332   setMeshAtLevel(meshDimRelToMax,m,renum);
5333   std::vector<const DataArrayIdType *> corr2(corr.begin(),corr.end());
5334   setGroupsAtLevel(meshDimRelToMax,corr2,true);
5335 }
5336
5337 /*!
5338  * Creates groups at a given level in \a this mesh from a sequence of
5339  * meshes each representing a group.
5340  * The given meshes must share the same node coordinates array.
5341  *  \param [in] meshDimRelToMax - the relative dimension to create the groups at.
5342  *  \param [in] ms - the sequence of meshes. Each mesh in \a ms represents a group to
5343  *         create in \a this mesh.
5344  *  \param [in] renum - if \c true, then the optional numbers of entities are taken into
5345  *         account. 
5346  *  \throw If \a ms is empty.
5347  *  \throw If dimension of meshes in \a ms does not correspond to \a meshDimRelToMax or
5348  *         to the existing meshes of other levels of \a this mesh.
5349  *  \throw If the meshes in \a ms do not share the same node coordinates array.
5350  *  \throw If the node coordinates array of \a this mesh (if any) is not the same as that
5351  *         of the given meshes.
5352  *  \throw If \a ms[ i ] is not well defined (MEDCouplingUMesh::checkConsistencyLight()).
5353  *  \throw If names of some meshes in \a ms are equal.
5354  *  \throw If \a ms includes a mesh with an empty name.
5355  */
5356 void MEDFileUMesh::setGroupsOnSetMesh(int meshDimRelToMax, const std::vector<const MEDCouplingUMesh *>& ms, bool renum)
5357 {
5358   if(ms.empty())
5359     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsOnSetMesh : expecting a non empty vector !");
5360   int sz=(-meshDimRelToMax)+1;
5361   if(sz>=(int)_ms.size())
5362     _ms.resize(sz);
5363   checkMeshDimCoherency(ms[0]->getMeshDimension(),meshDimRelToMax);
5364   DataArrayDouble *coo=checkMultiMesh(ms);
5365   if((DataArrayDouble *)_coords==0)
5366     {
5367       coo->incrRef();
5368       _coords=coo;
5369     }
5370   else
5371     if((DataArrayDouble *)_coords!=coo)
5372       throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsOnSetMesh : coordinates mismatches !");
5373   MEDCouplingUMesh *m=getMeshAtLevel(meshDimRelToMax,renum);
5374   std::vector< MCAuto<DataArrayIdType> > corr(ms.size());
5375   int i=0;
5376   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++,i++)
5377     {
5378       DataArrayIdType *arr=0;
5379       bool test=m->areCellsIncludedIn(*it,_zipconn_pol,arr);
5380       corr[i]=arr;
5381       if(!test)
5382         {
5383           std::ostringstream oss; oss << "MEDFileUMesh::setGroupsOnSetMesh : mesh #" << i << " is not part of whole mesh !";
5384           throw INTERP_KERNEL::Exception(oss.str().c_str());
5385         }
5386     }
5387   std::vector<const DataArrayIdType *> corr2(corr.begin(),corr.end());
5388   setGroupsAtLevel(meshDimRelToMax,corr2,renum);
5389 }
5390
5391 DataArrayDouble *MEDFileUMesh::checkMultiMesh(const std::vector<const MEDCouplingUMesh *>& ms) const
5392 {
5393   const DataArrayDouble *ret=ms[0]->getCoords();
5394   int mdim=ms[0]->getMeshDimension();
5395   for(unsigned int i=1;i<ms.size();i++)
5396     {
5397       ms[i]->checkConsistencyLight();
5398       if(ms[i]->getCoords()!=ret)
5399         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMultiMesh : meshes must share the same coords !");
5400       if(ms[i]->getMeshDimension()!=mdim)
5401         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMultiMesh : meshes have not same mesh dimension !");
5402     }
5403   return const_cast<DataArrayDouble *>(ret);
5404 }
5405
5406 /*!
5407  * Sets the family field of a given relative dimension.
5408  *  \param [in] meshDimRelToMaxExt - the relative dimension of entities for which
5409  *          the family field is set.
5410  *  \param [in] famArr - the array of the family field.
5411  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5412  *  \throw If \a famArr has an invalid size.
5413  */
5414 void MEDFileUMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayIdType *famArr)
5415 {
5416   if(meshDimRelToMaxExt==1)
5417     {
5418       if(!famArr)
5419         {
5420           _fam_coords=0;
5421           return ;
5422         }
5423       DataArrayDouble *coo(_coords);
5424       if(!coo)
5425         throw INTERP_KERNEL::Exception("MEDFileUMesh::setFamilyFieldArr : the coordinates have not been set !");
5426       famArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),1,"MEDFileUMesh::setFamilyFieldArr : Problem in size of node family arr ! ");
5427       _fam_coords.takeRef(famArr);
5428       return ;
5429     }
5430   if(meshDimRelToMaxExt>1)
5431     throw INTERP_KERNEL::Exception("MEDFileUMesh::setFamilyFieldArr : Dimension request is invalid (>1) !");
5432   int traducedRk=-meshDimRelToMaxExt;
5433   if(traducedRk>=(int)_ms.size())
5434     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
5435   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
5436     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
5437   return _ms[traducedRk]->setFamilyArr(famArr);
5438 }
5439
5440 /*!
5441  * Sets the optional numbers of mesh entities of a given dimension.
5442  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5443  *  \param [in] renumArr - the array of the numbers.
5444  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5445  *  \throw If \a renumArr has an invalid size.
5446  */
5447 void MEDFileUMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayIdType *renumArr)
5448 {
5449   if(meshDimRelToMaxExt==1)
5450     {
5451       if(!renumArr)
5452         {
5453           _num_coords.nullify();
5454           _rev_num_coords.nullify();
5455           return ;
5456         }
5457       if(_coords.isNull())
5458         throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumFieldArr : the coordinates have not been set !");
5459       renumArr->checkNbOfTuplesAndComp(_coords->getNumberOfTuples(),1,"MEDFileUMesh::setRenumArr : Problem in size of node numbering arr ! ");
5460       _num_coords.takeRef(renumArr);
5461       computeRevNum();
5462       return ;
5463     }
5464   if(meshDimRelToMaxExt>1)
5465     throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumArr : Dimension request is invalid (>1) !");
5466   int traducedRk=-meshDimRelToMaxExt;
5467   if(traducedRk>=(int)_ms.size())
5468     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
5469   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
5470     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
5471   return _ms[traducedRk]->setRenumArr(renumArr);
5472 }
5473
5474 /*!
5475  * Sets the optional names of mesh entities of a given dimension.
5476  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5477  *  \param [in] nameArr - the array of the names.
5478  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5479  *  \throw If \a nameArr has an invalid size.
5480  */
5481 void MEDFileUMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr)
5482 {
5483   if(meshDimRelToMaxExt==1)
5484     {
5485       if(!nameArr)
5486         {
5487           _name_coords=0;
5488           return ;
5489         }
5490       DataArrayDouble *coo(_coords);
5491       if(!coo)
5492         throw INTERP_KERNEL::Exception("MEDFileUMesh::setNameFieldAtLevel : the coordinates have not been set !");
5493       nameArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),MED_SNAME_SIZE,"MEDFileUMesh::setNameFieldAtLevel : Problem in size of node numbering arr ! ");
5494       _name_coords.takeRef(nameArr);
5495       return ;
5496     }
5497   if(meshDimRelToMaxExt>1)
5498     throw INTERP_KERNEL::Exception("MEDFileUMesh::setNameFieldAtLevel : Dimension request is invalid (>1) !");
5499   int traducedRk=-meshDimRelToMaxExt;
5500   if(traducedRk>=(int)_ms.size())
5501     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
5502   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
5503     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
5504   return _ms[traducedRk]->setNameArr(nameArr);
5505 }
5506
5507 void MEDFileUMesh::setGlobalNumFieldAtLevel(int meshDimRelToMaxExt, DataArrayIdType *globalNumArr)
5508 {
5509   if(meshDimRelToMaxExt!=1)
5510     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGlobalNumFieldAtLevel : Only implemented for meshDimRelToMaxExt==1 for the moment !");
5511   if(globalNumArr)
5512     globalNumArr->checkNbOfTuplesAndComp(_coords->getNumberOfTuples(),1,"MEDFileUMesh::setGlobalNumFieldAtLevel : Problem in size of node global numbering arr ! ");
5513   _global_num_coords.takeRef(globalNumArr);
5514 }
5515
5516 void MEDFileUMesh::synchronizeTinyInfoOnLeaves() const
5517 {
5518   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
5519     if((const MEDFileUMeshSplitL1 *)(*it))
5520       (*it)->synchronizeTinyInfo(*this);
5521 }
5522
5523 /*!
5524  * This method is called by MEDFileMesh::changeFamilyId. It performs only one part of the family id modification.
5525  */
5526 void MEDFileUMesh::changeFamilyIdArr(mcIdType oldId, mcIdType newId)
5527 {
5528   DataArrayIdType *arr=_fam_coords;
5529   if(arr)
5530     arr->changeValue(oldId,newId);
5531   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
5532     {
5533       MEDFileUMeshSplitL1 *sp=(*it);
5534       if(sp)
5535         {
5536           sp->changeFamilyIdArr(oldId,newId);
5537         }
5538     }
5539 }
5540
5541 std::list< MCAuto<DataArrayIdType> > MEDFileUMesh::getAllNonNullFamilyIds() const
5542 {
5543   std::list< MCAuto<DataArrayIdType> > ret;
5544   const DataArrayIdType *da(_fam_coords);
5545   if(da)
5546     { da->incrRef(); ret.push_back(MCAuto<DataArrayIdType>(const_cast<DataArrayIdType *>(da))); }
5547   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
5548     {
5549       const MEDFileUMeshSplitL1 *elt(*it);
5550       if(elt)
5551         {
5552           da=elt->getFamilyField();
5553           if(da)
5554             { da->incrRef(); ret.push_back(MCAuto<DataArrayIdType>(const_cast<DataArrayIdType *>(da))); }
5555         }
5556     }
5557   return ret;
5558 }
5559
5560 void MEDFileUMesh::computeRevNum() const
5561 {
5562   if(_num_coords.isNotNull())
5563     {
5564       mcIdType pos;
5565       mcIdType maxValue=_num_coords->getMaxValue(pos);
5566       _rev_num_coords=_num_coords->invertArrayN2O2O2N(maxValue+1);
5567     }
5568 }
5569
5570 std::size_t MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren() const
5571 {
5572   return MEDFileMesh::getHeapMemorySizeWithoutChildren();
5573 }
5574
5575 std::vector<const BigMemoryObject *> MEDFileStructuredMesh::getDirectChildrenWithNull() const
5576 {
5577   std::vector<const BigMemoryObject *> ret(MEDFileMesh::getDirectChildrenWithNull());
5578   ret.push_back((const DataArrayIdType *)_fam_nodes);
5579   ret.push_back((const DataArrayIdType *)_num_nodes);
5580   ret.push_back((const DataArrayAsciiChar *)_names_nodes);
5581   ret.push_back((const DataArrayIdType *)_fam_cells);
5582   ret.push_back((const DataArrayIdType *)_num_cells);
5583   ret.push_back((const DataArrayAsciiChar *)_names_cells);
5584   ret.push_back((const DataArrayIdType *)_fam_faces);
5585   ret.push_back((const DataArrayIdType *)_num_faces);
5586   ret.push_back((const DataArrayIdType *)_rev_num_nodes);
5587   ret.push_back((const DataArrayAsciiChar *)_names_faces);
5588   ret.push_back((const DataArrayIdType *)_rev_num_cells);
5589   ret.push_back((const MEDCoupling1SGTUMesh*)_faces_if_necessary);
5590   return ret;
5591 }
5592
5593 mcIdType MEDFileStructuredMesh::getMaxAbsFamilyIdInArrays() const
5594 {
5595   mcIdType ret=-std::numeric_limits<mcIdType>::max(),tmp=-1;
5596   if((const DataArrayIdType *)_fam_nodes)
5597     {
5598       mcIdType val=_fam_nodes->getMaxValue(tmp);
5599       ret=std::max(ret,std::abs(val));
5600     }
5601   if((const DataArrayIdType *)_fam_cells)
5602     {
5603       mcIdType val=_fam_cells->getMaxValue(tmp);
5604       ret=std::max(ret,std::abs(val));
5605     }
5606   if((const DataArrayIdType *)_fam_faces)
5607     {
5608       mcIdType val=_fam_faces->getMaxValue(tmp);
5609       ret=std::max(ret,std::abs(val));
5610     }
5611   return ret;
5612 }
5613
5614 mcIdType MEDFileStructuredMesh::getMaxFamilyIdInArrays() const
5615 {
5616   mcIdType ret=-std::numeric_limits<mcIdType>::max(),tmp=-1;
5617   if((const DataArrayIdType *)_fam_nodes)
5618     {
5619       mcIdType val=_fam_nodes->getMaxValue(tmp);
5620       ret=std::max(ret,val);
5621     }
5622   if((const DataArrayIdType *)_fam_cells)
5623     {
5624       mcIdType val=_fam_cells->getMaxValue(tmp);
5625       ret=std::max(ret,val);
5626     }
5627   if((const DataArrayIdType *)_fam_faces)
5628     {
5629       mcIdType val=_fam_faces->getMaxValue(tmp);
5630       ret=std::max(ret,val);
5631     }
5632   return ret;
5633 }
5634
5635 mcIdType MEDFileStructuredMesh::getMinFamilyIdInArrays() const
5636 {
5637   mcIdType ret=std::numeric_limits<mcIdType>::max(),tmp=-1;
5638   if((const DataArrayIdType *)_fam_nodes)
5639     {
5640       mcIdType val=_fam_nodes->getMinValue(tmp);
5641       ret=std::min(ret,val);
5642     }
5643   if((const DataArrayIdType *)_fam_cells)
5644     {
5645       mcIdType val=_fam_cells->getMinValue(tmp);
5646       ret=std::min(ret,val);
5647     }
5648   if((const DataArrayIdType *)_fam_faces)
5649     {
5650       mcIdType val=_fam_faces->getMinValue(tmp);
5651       ret=std::min(ret,val);
5652     }
5653   return ret;
5654 }
5655
5656 bool MEDFileStructuredMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
5657 {
5658   if(!MEDFileMesh::isEqual(other,eps,what))
5659     return false;
5660   const MEDFileStructuredMesh *otherC=dynamic_cast<const  MEDFileStructuredMesh *>(other);
5661   if(!otherC)
5662     {
5663       what="Mesh types differ ! This is structured and other is NOT !";
5664       return false;
5665     }
5666   const DataArrayIdType *famc1=_fam_nodes;
5667   const DataArrayIdType *famc2=otherC->_fam_nodes;
5668   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
5669     {
5670       what="Mismatch of families arr on nodes ! One is defined and not other !";
5671       return false;
5672     }
5673   if(famc1)
5674     {
5675       bool ret=famc1->isEqual(*famc2);
5676       if(!ret)
5677         {
5678           what="Families arr on nodes differ !";
5679           return false;
5680         }
5681     }
5682   famc1=_fam_cells;
5683   famc2=otherC->_fam_cells;
5684   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
5685     {
5686       what="Mismatch of families arr on cells ! One is defined and not other !";
5687       return false;
5688     }
5689   if(famc1)
5690     {
5691       bool ret=famc1->isEqual(*famc2);
5692       if(!ret)
5693         {
5694           what="Families arr on cells differ !";
5695           return false;
5696         }
5697     }
5698   famc1=_fam_faces;
5699   famc2=otherC->_fam_faces;
5700   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
5701     {
5702       what="Mismatch of families arr on faces ! One is defined and not other !";
5703       return false;
5704     }
5705   if(famc1)
5706     {
5707       bool ret=famc1->isEqual(*famc2);
5708       if(!ret)
5709         {
5710           what="Families arr on faces differ !";
5711           return false;
5712         }
5713     }
5714   famc1=_num_nodes;
5715   famc2=otherC->_num_nodes;
5716   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
5717     {
5718       what="Mismatch of numbering arr on nodes ! One is defined and not other !";
5719       return false;
5720     }
5721   if(famc1)
5722     {
5723       bool ret=famc1->isEqual(*famc2);
5724       if(!ret)
5725         {
5726           what="Numbering arr on nodes differ !";
5727           return false;
5728         }
5729     }
5730   famc1=_num_cells;
5731   famc2=otherC->_num_cells;
5732   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
5733     {
5734       what="Mismatch of numbering arr on cells ! One is defined and not other !";
5735       return false;
5736     }
5737   if(famc1)
5738     {
5739       bool ret=famc1->isEqual(*famc2);
5740       if(!ret)
5741         {
5742           what="Numbering arr on cells differ !";
5743           return false;
5744         }
5745     }
5746   famc1=_num_faces;
5747   famc2=otherC->_num_faces;
5748   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
5749     {
5750       what="Mismatch of numbering arr on faces ! One is defined and not other !";
5751       return false;
5752     }
5753   if(famc1)
5754     {
5755       bool ret=famc1->isEqual(*famc2);
5756       if(!ret)
5757         {
5758           what="Numbering arr on faces differ !";
5759           return false;
5760         }
5761     }
5762   const DataArrayAsciiChar *d1=_names_cells;
5763   const DataArrayAsciiChar *d2=otherC->_names_cells;
5764   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
5765     {
5766       what="Mismatch of naming arr on cells ! One is defined and not other !";
5767       return false;
5768     }
5769   if(d1)
5770     {
5771       bool ret=d1->isEqual(*d2);
5772       if(!ret)
5773         {
5774           what="Naming arr on cells differ !";
5775           return false;
5776         }
5777     }
5778   d1=_names_faces;
5779   d2=otherC->_names_faces;
5780   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
5781     {
5782       what="Mismatch of naming arr on faces ! One is defined and not other !";
5783       return false;
5784     }
5785   if(d1)
5786     {
5787       bool ret=d1->isEqual(*d2);
5788       if(!ret)
5789         {
5790           what="Naming arr on faces differ !";
5791           return false;
5792         }
5793     }
5794   d1=_names_nodes;
5795   d2=otherC->_names_nodes;
5796   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
5797     {
5798       what="Mismatch of naming arr on nodes ! One is defined and not other !";
5799       return false;
5800     }
5801   if(d1)
5802     {
5803       bool ret=d1->isEqual(*d2);
5804       if(!ret)
5805         {
5806           what="Naming arr on nodes differ !";
5807           return false;
5808         }
5809     }
5810   return true;
5811 }
5812
5813 void MEDFileStructuredMesh::clearNonDiscrAttributes() const
5814 {
5815   MEDFileMesh::clearNonDiscrAttributes();
5816   const DataArrayIdType *tmp=_fam_nodes;
5817   if(tmp)
5818     (const_cast<DataArrayIdType *>(tmp))->setName("");
5819   tmp=_num_nodes;
5820   if(tmp)
5821     (const_cast<DataArrayIdType *>(tmp))->setName("");
5822   tmp=_fam_cells;
5823   if(tmp)
5824     (const_cast<DataArrayIdType *>(tmp))->setName("");
5825   tmp=_num_cells;
5826   if(tmp)
5827     (const_cast<DataArrayIdType *>(tmp))->setName("");
5828   tmp=_fam_faces;
5829   if(tmp)
5830     (const_cast<DataArrayIdType *>(tmp))->setName("");
5831   tmp=_num_faces;
5832   if(tmp)
5833     (const_cast<DataArrayIdType *>(tmp))->setName("");
5834 }
5835
5836 /*!
5837  * Returns ids of mesh entities contained in given families of a given dimension.
5838  *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
5839  *          are required.
5840  *  \param [in] fams - the names of the families of interest.
5841  *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
5842  *          returned instead of ids.
5843  *  \return DataArrayIdType * - a new instance of DataArrayIdType holding either ids or
5844  *          numbers, if available and required, of mesh entities of the families. The caller
5845  *          is to delete this array using decrRef() as it is no more needed. 
5846  *  \throw If the family field is missing for \a meshDimRelToMaxExt.
5847  */
5848 DataArrayIdType *MEDFileStructuredMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const
5849 {
5850   std::vector<mcIdType> famIds(getFamiliesIds(fams));
5851   switch(meshDimRelToMaxExt)
5852   {
5853     case 1:
5854       {
5855         if((const DataArrayIdType *)_fam_nodes)
5856           {
5857             MCAuto<DataArrayIdType> da;
5858             if(!famIds.empty())
5859               da=_fam_nodes->findIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
5860             else
5861               da=_fam_nodes->findIdsEqualList(0,0);
5862             if(renum)
5863               return MEDFileUMeshSplitL1::Renumber(_num_nodes,da);
5864             else
5865               return da.retn();
5866           }
5867         else
5868           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on nodes !");
5869         break;
5870       }
5871     case 0:
5872       {
5873         if((const DataArrayIdType *)_fam_cells)
5874           {
5875             MCAuto<DataArrayIdType> da;
5876             if(!famIds.empty())
5877               da=_fam_cells->findIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
5878             else
5879               da=_fam_cells->findIdsEqualList(0,0);
5880             if(renum)
5881               return MEDFileUMeshSplitL1::Renumber(_num_cells,da);
5882             else
5883               return da.retn();
5884           }
5885         else
5886           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on cells !");
5887         break;
5888       }
5889     case -1:
5890       {
5891         if((const DataArrayIdType *)_fam_faces)
5892           {
5893             MCAuto<DataArrayIdType> da;
5894             if(!famIds.empty())
5895               da=_fam_faces->findIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
5896             else
5897               da=_fam_faces->findIdsEqualList(0,0);
5898             if(renum)
5899               return MEDFileUMeshSplitL1::Renumber(_num_faces,da);
5900             else
5901               return da.retn();
5902           }
5903         else
5904           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on faces !");
5905         break;
5906       }
5907     default:
5908       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : input meshDimRelative must be in [0,1,-1] !");
5909   }
5910   throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : unmanaged case !");
5911 }
5912
5913 /*!
5914  * Sets the family field of a given relative dimension.
5915  *  \param [in] meshDimRelToMaxExt - the relative dimension of entities for which
5916  *          the family field is set.
5917  *  \param [in] famArr - the array of the family field.
5918  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5919  *  \throw If \a famArr has an invalid size.
5920  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1 and \a meshDimRelToMaxExt != -1.
5921  */
5922 void MEDFileStructuredMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayIdType *famArr)
5923 {
5924   const MEDCouplingStructuredMesh *mesh(getStructuredMesh());
5925   if(!mesh)
5926     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setFamilyFieldArr : no structured mesh specified ! Impossible to set family array !");
5927   switch(meshDimRelToMaxExt)
5928   {
5929     case 0:
5930       {
5931         mcIdType nbCells(mesh->getNumberOfCells());
5932         if(famArr)
5933           famArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of cells of mesh !");
5934         _fam_cells=famArr;
5935         break;
5936       }
5937     case 1:
5938       {
5939         mcIdType nbNodes(mesh->getNumberOfNodes());
5940         if(famArr)
5941           famArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !");
5942         _fam_nodes=famArr;
5943         break;
5944       }
5945     case -1:
5946       {
5947         mcIdType nbCells(mesh->getNumberOfCellsOfSubLevelMesh());
5948         if(famArr)
5949           famArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of faces of mesh !");
5950         _fam_faces=famArr;
5951         break;
5952       }
5953     default:
5954       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setFamilyFieldArr : Only available for levels 0 or 1 or -1 !");
5955   }
5956   if(famArr)
5957     famArr->incrRef();
5958 }
5959
5960 /*!
5961  * Sets the optional numbers of mesh entities of a given dimension.
5962  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
5963  *  \param [in] renumArr - the array of the numbers.
5964  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
5965  *  \throw If \a renumArr has an invalid size.
5966  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
5967  */
5968 void MEDFileStructuredMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayIdType *renumArr)
5969 {
5970   const MEDCouplingStructuredMesh *mesh=getStructuredMesh();
5971   if(!mesh)
5972     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : no structured mesh specified ! Impossible to set number array !");
5973   switch(meshDimRelToMaxExt)
5974   {
5975     case 0:
5976       {
5977         mcIdType nbCells=mesh->getNumberOfCells();
5978         renumArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Renum arr ! Mismatch with number of cells of mesh !");
5979         _num_cells=renumArr;
5980         break;
5981       }
5982     case 1:
5983       {
5984         mcIdType nbNodes=mesh->getNumberOfNodes();
5985         renumArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !");
5986         _num_nodes=renumArr;
5987         break;
5988       }
5989     case -1:
5990       {
5991         mcIdType nbCells=mesh->getNumberOfCellsOfSubLevelMesh();
5992         renumArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Renum arr ! Mismatch with number of faces of mesh !");
5993         _num_faces=renumArr;
5994         break;
5995       }
5996     default:
5997       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : Only available for levels 0 or 1 or -1 !");
5998   }
5999   if(renumArr)
6000     renumArr->incrRef();
6001 }
6002
6003 /*!
6004  * Sets the optional names of mesh entities of a given dimension.
6005  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
6006  *  \param [in] nameArr - the array of the names.
6007  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
6008  *  \throw If \a nameArr has an invalid size.
6009  */
6010 void MEDFileStructuredMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr)
6011 {
6012   const MEDCouplingStructuredMesh *mesh(getStructuredMesh());
6013   if(!mesh)
6014     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : no structured mesh specified ! Impossible to set names array !");
6015   switch(meshDimRelToMaxExt)
6016   {
6017     case 0:
6018       {
6019         mcIdType nbCells=mesh->getNumberOfCells();
6020         nameArr->checkNbOfTuplesAndComp(nbCells,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of cells of mesh !");
6021         _names_cells=nameArr;
6022         break;
6023       }
6024     case 1:
6025       {
6026         mcIdType nbNodes=mesh->getNumberOfNodes();
6027         nameArr->checkNbOfTuplesAndComp(nbNodes,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of nodes of mesh !");
6028         _names_nodes=nameArr;
6029         break;
6030       }
6031     case -1:
6032       {
6033         mcIdType nbCells=mesh->getNumberOfCellsOfSubLevelMesh();
6034         nameArr->checkNbOfTuplesAndComp(nbCells,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of faces of mesh !");
6035         _names_faces=nameArr;
6036       }
6037     default:
6038       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : Only available for levels 0 or 1 or -1 !");
6039   }
6040   if(nameArr)
6041     nameArr->incrRef();
6042 }
6043
6044 void MEDFileStructuredMesh::setGlobalNumFieldAtLevel(int meshDimRelToMaxExt, DataArrayIdType *globalNumArr)
6045 {
6046   throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setGlobalNumFieldAtLevel : not implemented yet !");
6047 }
6048
6049 /*!
6050  * Adds a group of nodes to \a this mesh.
6051  *  \param [in] ids - a DataArrayIdType providing ids and a name of the group to add.
6052  *          The ids should be sorted and different each other (MED file norm).
6053  *
6054  *  \warning this method can alter default "FAMILLE_ZERO" family.
6055  *  For users sensitive to this a call to MEDFileMesh::rearrangeFamilies will be necessary after addGroup session.
6056  *
6057  *  \throw If the node coordinates array is not set.
6058  *  \throw If \a ids == \c NULL.
6059  *  \throw If \a ids->getName() == "".
6060  *  \throw If \a ids does not respect the MED file norm.
6061  *  \throw If a group with name \a ids->getName() already exists.
6062  */
6063 void MEDFileStructuredMesh::addNodeGroup(const DataArrayIdType *ids)
6064 {
6065   addGroup(1,ids);
6066 }
6067
6068 /*!
6069  * Adds a group of nodes/cells/faces/edges to \a this mesh.
6070  *
6071  *  \param [in] ids - a DataArrayIdType providing ids and a name of the group to add.
6072  *          The ids should be sorted and different each other (MED file norm).
6073  *
6074  * \warning this method can alter default "FAMILLE_ZERO" family.
6075  * For users sensitive to this a call to MEDFileMesh::rearrangeFamilies will be necessary after addGroup session.
6076  *
6077  *  \throw If the node coordinates array is not set.
6078  *  \throw If \a ids == \c NULL.
6079  *  \throw If \a ids->getName() == "".
6080  *  \throw If \a ids does not respect the MED file norm.
6081  *  \throw If a group with name \a ids->getName() already exists.
6082  */
6083 void MEDFileStructuredMesh::addGroup(int meshDimRelToMaxExt, const DataArrayIdType *ids)
6084 {
6085   DataArrayIdType *fam(getOrCreateAndGetFamilyFieldAtLevel(meshDimRelToMaxExt));
6086   addGroupUnderground(false,ids,fam);
6087   return ;
6088 }
6089
6090 /*!
6091  * Returns the family field for mesh entities of a given dimension.
6092  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
6093  *  \return const DataArrayIdType * - the family field. It is an array of ids of families
6094  *          each mesh entity belongs to. It can be \c NULL.
6095  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
6096  */
6097 const DataArrayIdType *MEDFileStructuredMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) const
6098 {
6099   switch(meshDimRelToMaxExt)
6100   {
6101     case 0:
6102       return _fam_cells;
6103     case 1:
6104       return _fam_nodes;
6105     case -1:
6106       return _fam_faces;
6107     default:
6108       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamilyFieldAtLevel : Only available for levels 0 or 1 or -1 !");
6109   }
6110 }
6111
6112 /*!
6113  * Returns the family field for mesh entities of a given dimension.
6114  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
6115  *  \return const DataArrayIdType * - the family field. It is an array of ids of families
6116  *          each mesh entity belongs to. It can be \c NULL.
6117  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
6118  */
6119 DataArrayIdType *MEDFileStructuredMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt)
6120 {
6121   switch(meshDimRelToMaxExt)
6122   {
6123     case 0:
6124       return _fam_cells;
6125     case 1:
6126       return _fam_nodes;
6127     case -1:
6128       return _fam_faces;
6129     default:
6130       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamilyFieldAtLevel : Only available for levels 0 or 1 or -1 !");
6131   }
6132 }
6133
6134 /*!
6135  * Returns the optional numbers of mesh entities of a given dimension.
6136  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
6137  *  \return const DataArrayIdType * - the array of the entity numbers.
6138  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
6139  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
6140  */
6141 const DataArrayIdType *MEDFileStructuredMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) const
6142 {
6143   switch(meshDimRelToMaxExt)
6144   {
6145     case 0:
6146       return _num_cells;
6147     case 1:
6148       return _num_nodes;
6149     case -1:
6150       return _num_faces;
6151     default:
6152       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberFieldAtLevel : Only available for levels 0 or 1 or -1 !");
6153   }
6154 }
6155
6156 /*!
6157  * Returns the optional numbers of mesh entities of a given dimension transformed using
6158  * DataArrayIdType::invertArrayN2O2O2N().
6159  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
6160  *  \return const DataArrayIdType * - the array of the entity numbers transformed using
6161  *          DataArrayIdType::invertArrayN2O2O2N().
6162  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
6163  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
6164  */
6165 const DataArrayIdType *MEDFileStructuredMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxExt) const
6166 {
6167   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
6168     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getRevNumberFieldAtLevel : Only available for levels 0 or 1 !");
6169   if(meshDimRelToMaxExt==0)
6170     {
6171       if((const DataArrayIdType *)_num_cells)
6172         {
6173           mcIdType pos;
6174           mcIdType maxValue=_num_cells->getMaxValue(pos);
6175           _rev_num_cells=_num_cells->invertArrayN2O2O2N(maxValue+1);
6176           return _rev_num_cells;
6177         }
6178       else
6179         throw INTERP_KERNEL::Exception("MEDFileCMesh::getRevNumberFieldAtLevel : no cell renumbering for a request on reverse numbering !");
6180     }
6181   else
6182     {
6183       if((const DataArrayIdType *)_num_nodes)
6184         {
6185           mcIdType pos;
6186           mcIdType maxValue=_num_nodes->getMaxValue(pos);
6187           _rev_num_nodes=_num_nodes->invertArrayN2O2O2N(maxValue+1);
6188           return _rev_num_nodes;
6189         }
6190       else
6191         throw INTERP_KERNEL::Exception("MEDFileCMesh::getRevNumberFieldAtLevel : no node renumbering for a request on reverse numbering !");
6192     }
6193 }
6194
6195 const DataArrayAsciiChar *MEDFileStructuredMesh::getNameFieldAtLevel(int meshDimRelToMaxExt) const
6196 {
6197   switch(meshDimRelToMaxExt)
6198   {
6199     case 0:
6200       return _names_cells;
6201     case 1:
6202       return _names_nodes;
6203     case -1:
6204       return _names_faces;
6205     default:
6206       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNameFieldAtLevel : Only available for levels 0 or 1 or -1 !");
6207   }
6208 }
6209
6210 MCAuto<DataArrayIdType> MEDFileStructuredMesh::getGlobalNumFieldAtLevel(int meshDimRelToMaxExt) const
6211 {
6212   throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGlobalNumFieldAtLevel : not implemented yet for structured mesh !");
6213 }
6214
6215 /*!
6216  * Returns relative dimensions of mesh entities (excluding nodes) present in \a this mesh.
6217  *  \return std::vector<int> - a sequence of the relative dimensions: [0].
6218  */
6219 std::vector<int> MEDFileStructuredMesh::getNonEmptyLevels() const
6220 {
6221   std::vector<int> ret(1);
6222   return ret;
6223 }
6224
6225 /*!
6226  * Returns relative dimensions of mesh entities (including nodes) present in \a this mesh.
6227  *  \return std::vector<int> - a sequence of the relative dimensions: [1,0].
6228  */
6229 std::vector<int> MEDFileStructuredMesh::getNonEmptyLevelsExt() const
6230 {
6231   std::vector<int> ret(2);
6232   ret[0]=1;
6233   return ret;
6234 }
6235
6236 /*!
6237  * Returns the set of extensive levels (nodes included) where not NULL family arr are defined.
6238  */
6239 std::vector<int> MEDFileStructuredMesh::getFamArrNonEmptyLevelsExt() const
6240 {
6241   std::vector<int> ret;
6242   const DataArrayIdType *famNodes(_fam_nodes),*famCells(_fam_cells),*famFaces(_fam_faces);
6243   if(famNodes)
6244     ret.push_back(1);
6245   if(famCells)
6246     ret.push_back(0);
6247   if(famFaces)
6248     ret.push_back(-1);
6249   return ret;
6250 }
6251
6252 /*!
6253  * Returns the set of extensive levels (nodes included) where not NULL numbering arr are defined.
6254  */
6255 std::vector<int> MEDFileStructuredMesh::getNumArrNonEmptyLevelsExt() const
6256 {
6257   std::vector<int> ret;
6258   const DataArrayIdType *numNodes(_num_nodes),*numCells(_num_cells),*numFaces(_num_faces);
6259   if(numNodes)
6260     ret.push_back(1);
6261   if(numCells)
6262     ret.push_back(0);
6263   if(numFaces)
6264     ret.push_back(-1);
6265   return ret;
6266 }
6267
6268 /*!
6269  * Returns the set of extensive levels (nodes included) where not NULL naming arr are defined.
6270  */
6271 std::vector<int> MEDFileStructuredMesh::getNameArrNonEmptyLevelsExt() const
6272 {
6273   std::vector<int> ret;
6274   const DataArrayAsciiChar *namesNodes(_names_nodes),*namesCells(_names_cells),*namesFaces(_names_faces);
6275   if(namesNodes)
6276     ret.push_back(1);
6277   if(namesCells)
6278     ret.push_back(0);
6279   if(namesFaces)
6280     ret.push_back(-1);
6281   return ret;
6282 }
6283
6284 /*!
6285  * no implementation here, it is not a bug, but intresically no polyhedra in \a this.
6286  */
6287 bool MEDFileStructuredMesh::unPolyze(std::vector<mcIdType>& oldCode, std::vector<mcIdType>& newCode, DataArrayIdType *& o2nRenumCell)
6288 {
6289   oldCode.clear(); newCode.clear(); o2nRenumCell=0;
6290   return false;
6291 }
6292
6293 void MEDFileStructuredMesh::changeFamilyIdArr(mcIdType oldId, mcIdType newId)
6294 {
6295   DataArrayIdType *arr=_fam_nodes;
6296   if(arr)
6297     arr->changeValue(oldId,newId);
6298   arr=_fam_cells;
6299   if(arr)
6300     arr->changeValue(oldId,newId);
6301   arr=_fam_faces;
6302   if(arr)
6303     arr->changeValue(oldId,newId);
6304 }
6305
6306 std::list< MCAuto<DataArrayIdType> > MEDFileStructuredMesh::getAllNonNullFamilyIds() const
6307 {
6308   std::list< MCAuto<DataArrayIdType> > ret;
6309   const DataArrayIdType *da(_fam_nodes);
6310   if(da)
6311     { da->incrRef(); ret.push_back(MCAuto<DataArrayIdType>(const_cast<DataArrayIdType *>(da))); }
6312   da=_fam_cells;
6313   if(da)
6314     { da->incrRef(); ret.push_back(MCAuto<DataArrayIdType>(const_cast<DataArrayIdType *>(da))); }
6315   da=_fam_faces;
6316   if(da)
6317     { da->incrRef(); ret.push_back(MCAuto<DataArrayIdType>(const_cast<DataArrayIdType *>(da))); }
6318   return ret;
6319 }
6320
6321 void MEDFileStructuredMesh::deepCpyAttributes()
6322 {
6323   if((const DataArrayIdType*)_fam_nodes)
6324     _fam_nodes=_fam_nodes->deepCopy();
6325   if((const DataArrayIdType*)_num_nodes)
6326     _num_nodes=_num_nodes->deepCopy();
6327   if((const DataArrayAsciiChar*)_names_nodes)
6328     _names_nodes=_names_nodes->deepCopy();
6329   if((const DataArrayIdType*)_fam_cells)
6330     _fam_cells=_fam_cells->deepCopy();
6331   if((const DataArrayIdType*)_num_cells)
6332     _num_cells=_num_cells->deepCopy();
6333   if((const DataArrayAsciiChar*)_names_cells)
6334     _names_cells=_names_cells->deepCopy();
6335   if((const DataArrayIdType*)_fam_faces)
6336     _fam_faces=_fam_faces->deepCopy();
6337   if((const DataArrayIdType*)_num_faces)
6338     _num_faces=_num_faces->deepCopy();
6339   if((const DataArrayAsciiChar*)_names_faces)
6340     _names_faces=_names_faces->deepCopy();
6341   if((const DataArrayIdType*)_rev_num_nodes)
6342     _rev_num_nodes=_rev_num_nodes->deepCopy();
6343   if((const DataArrayIdType*)_rev_num_cells)
6344     _rev_num_cells=_rev_num_cells->deepCopy();
6345 }
6346
6347 /*!
6348  * Returns a pointer to mesh at the specified level (here 0 is compulsory for cartesian mesh).
6349  * 
6350  * \return a pointer to cartesian mesh that need to be managed by the caller.
6351  * \warning the returned pointer has to be managed by the caller.
6352  */
6353
6354 /*!
6355  * Returns a pointer to MEDCouplingStructuredMesh held by \a this. 
6356  *  \param [in] meshDimRelToMax - it must be \c 0 or \c -1.
6357  *  \param [in] renum - it must be \c false.
6358  *  \return MEDCouplingMesh * - a pointer to MEDCouplingMesh that the caller is to
6359  *          delete using decrRef() as it is no more needed. 
6360  */
6361 MEDCouplingMesh *MEDFileStructuredMesh::getMeshAtLevel(int meshDimRelToMax, bool renum) const
6362 {
6363   checkCartesian();
6364   if(renum)
6365     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support renumbering ! To do it perform request of renum array directly !");
6366   const MEDCouplingStructuredMesh *m(getStructuredMesh());
6367   switch(meshDimRelToMax)
6368   {
6369     case 0:
6370       {
6371         if(m)
6372           m->incrRef();
6373         return const_cast<MEDCouplingStructuredMesh *>(m);
6374       }
6375     case -1:
6376       {
6377         if(!m)
6378           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getMeshAtLevel : level -1 requested must be non empty to be able to compute unstructured sub mesh !");
6379         buildMinusOneImplicitPartIfNeeded();
6380         MEDCoupling1SGTUMesh *ret(_faces_if_necessary);
6381         if(ret)
6382           ret->incrRef();
6383         return ret;
6384       }
6385     default:
6386       throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support multi level for mesh 0 expected as input !");
6387   }
6388 }
6389
6390 std::vector<mcIdType> MEDFileStructuredMesh::getFamsNonEmptyLevels(const std::vector<std::string>& fams) const
6391 {
6392   std::vector<mcIdType> ret;
6393   const DataArrayIdType *famCells(_fam_cells),*famFaces(_fam_faces);
6394   if(famCells && famCells->presenceOfValue(ret))
6395     ret.push_back(0);
6396   if(famFaces && famFaces->presenceOfValue(ret))
6397     ret.push_back(-1);
6398   return ret;  
6399 }
6400
6401 std::vector<mcIdType> MEDFileStructuredMesh::getFamsNonEmptyLevelsExt(const std::vector<std::string>& fams) const
6402 {
6403   std::vector<mcIdType> ret(getFamsNonEmptyLevels(fams));
6404   const DataArrayIdType *famNodes(_fam_nodes);
6405   if(famNodes && famNodes->presenceOfValue(ret))
6406     ret.push_back(1);
6407   return ret;  
6408 }
6409
6410 /*!
6411  * Returns number of mesh entities of a given relative dimension in \a this mesh.
6412  *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
6413  *  \return mcIdType - the number of entities.
6414  *  \throw If no mesh entities of dimension \a meshDimRelToMaxExt are available in \a this mesh.
6415  */
6416 mcIdType MEDFileStructuredMesh::getSizeAtLevel(int meshDimRelToMaxExt) const
6417 {
6418   const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
6419   if(!cmesh)
6420     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : No structured mesh set !");
6421   switch(meshDimRelToMaxExt)
6422   {
6423     case 0:
6424       return cmesh->getNumberOfCells();
6425     case 1:
6426       return cmesh->getNumberOfNodes();
6427     case -1:
6428       return cmesh->getNumberOfCellsOfSubLevelMesh();
6429     default:
6430       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : Only available for levels 0 or 1 or -1 !");
6431   }
6432 }
6433
6434 mcIdType MEDFileStructuredMesh::getNumberOfNodes() const
6435 {
6436   const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
6437   if(!cmesh)
6438     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberOfNodes : no cartesian mesh set !");
6439   return cmesh->getNumberOfNodes();
6440 }
6441
6442 mcIdType MEDFileStructuredMesh::getNumberOfCellsAtLevel(int meshDimRelToMaxExt) const
6443 {
6444   const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
6445   if(!cmesh)
6446     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberOfNodes : no cartesian mesh set !");
6447   switch(meshDimRelToMaxExt)
6448   {
6449     case 0:
6450       return cmesh->getNumberOfCells();
6451     case -1:
6452       return cmesh->getNumberOfCellsOfSubLevelMesh();
6453     default:
6454       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberOfNodes : only meshDimRelToMax=0 and meshDimRelToMax=-1 supported !");
6455     }
6456 }
6457
6458 bool MEDFileStructuredMesh::hasImplicitPart() const
6459 {
6460   return true;
6461 }
6462
6463 /*!
6464  * \sa MEDFileStructuredMesh::getImplicitFaceMesh
6465  */
6466 mcIdType MEDFileStructuredMesh::buildImplicitPartIfAny(INTERP_KERNEL::NormalizedCellType gt) const
6467 {
6468   static const char MSG[]="MEDFileStructuredMesh::buildImplicitPartIfAny : the given geo type is not manageable by a structured mesh !";
6469   const MEDCoupling1SGTUMesh *zeFaceMesh(_faces_if_necessary);
6470   if(!zeFaceMesh)
6471     {
6472       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(getMeshDimension())));
6473       if(cm.getReverseExtrudedType()!=gt)
6474         throw INTERP_KERNEL::Exception(MSG);
6475       buildImplicitPart();
6476       return getStructuredMesh()->getNumberOfCellsOfSubLevelMesh();
6477     }
6478   else
6479     {
6480       if(gt!=zeFaceMesh->getCellModelEnum())
6481         throw INTERP_KERNEL::Exception(MSG);
6482       return zeFaceMesh->getNumberOfCells();
6483     }
6484 }
6485
6486 void MEDFileStructuredMesh::buildMinusOneImplicitPartIfNeeded() const
6487 {
6488   const MEDCoupling1SGTUMesh *zeFaceMesh(_faces_if_necessary);
6489   if(!zeFaceMesh)
6490     buildImplicitPart();
6491 }
6492
6493 void MEDFileStructuredMesh::buildImplicitPart() const
6494 {
6495   const MEDCouplingStructuredMesh *mcmesh(getStructuredMesh());
6496   if(!mcmesh)
6497     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::buildImplicitPart : Unable to build the implicit part of structured mesh because no structured mesh at level 0 defined !");
6498   _faces_if_necessary=mcmesh->build1SGTSubLevelMesh();
6499 }
6500
6501 void MEDFileStructuredMesh::releaseImplicitPartIfAny() const
6502 {
6503   _faces_if_necessary=0;
6504 }
6505
6506 /*!
6507  * Retrieves the internal pointer (no decrRef requested) of the implicit face mesh if any.
6508  * To force to build it you can invoke MEDFileStructuredMesh::buildImplicitPartIfAny method.
6509  * 
6510  * \sa MEDFileStructuredMesh::buildImplicitPartIfAny
6511  */
6512 MEDCoupling1SGTUMesh *MEDFileStructuredMesh::getImplicitFaceMesh() const
6513 {
6514   checkCartesian();
6515   return _faces_if_necessary;
6516 }
6517
6518 std::vector<INTERP_KERNEL::NormalizedCellType> MEDFileStructuredMesh::getGeoTypesAtLevel(int meshDimRelToMax) const
6519 {
6520   const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
6521   if(!cmesh)
6522     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGeoTypesAtLevel : No structured mesh set !");
6523   switch(meshDimRelToMax)
6524   {
6525     case 0:
6526       {
6527         std::vector<INTERP_KERNEL::NormalizedCellType> ret(1,cmesh->getTypeOfCell(0));
6528         return ret;
6529       }
6530     case -1:
6531       {
6532         int mdim(cmesh->getMeshDimension());
6533         if(mdim<1)
6534           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGeoTypesAtLevel : only one level available for structured meshes ! Input 0 is mandatory or 0D mesh !");
6535         std::vector<INTERP_KERNEL::NormalizedCellType> ret(1,MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(mdim-1));
6536         return ret;
6537       }
6538     default:
6539       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGeoTypesAtLevel : only 2 levels available at most : 0 and -1 !");
6540   }
6541 }
6542
6543 mcIdType MEDFileStructuredMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType ct) const
6544 {
6545   if(ct!=MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(getMeshDimension()))
6546     return 0;
6547   else
6548     return getNumberOfCellsAtLevel(0);
6549 }
6550
6551 void MEDFileStructuredMesh::whichAreNodesFetched(const MEDFileField1TSStructItem& st, const MEDFileFieldGlobsReal *globs, std::vector<bool>& nodesFetched) const
6552 {
6553   if(st.getNumberOfItems()!=1)
6554     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 !");
6555   if(st[0].getGeo()!=MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(getMeshDimension()))
6556     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : The sturture of field is not lying on expected geo type !");
6557   if(getNumberOfNodes()!=(mcIdType)nodesFetched.size())
6558     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : invalid size of array !");
6559   if(st[0].getPflName().empty())
6560     {
6561       std::fill(nodesFetched.begin(),nodesFetched.end(),true);
6562       return ;
6563     }
6564   const DataArrayIdType *arr(globs->getProfile(st[0].getPflName()));
6565   const MEDCouplingStructuredMesh *cmesh=getStructuredMesh();//cmesh not null because getNumberOfNodes called before
6566   mcIdType sz(ToIdType(nodesFetched.size()));
6567   for(const mcIdType *work=arr->begin();work!=arr->end();work++)
6568     {
6569       std::vector<mcIdType> conn;
6570       cmesh->getNodeIdsOfCell(*work,conn);
6571       for(std::vector<mcIdType>::const_iterator it=conn.begin();it!=conn.end();it++)
6572         if(*it>=0 && *it<sz)
6573           nodesFetched[*it]=true;
6574         else
6575           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : internal error !");
6576     }
6577 }
6578
6579 med_geometry_type MEDFileStructuredMesh::GetGeoTypeFromMeshDim(int meshDim)
6580 {
6581   INTERP_KERNEL::NormalizedCellType ct(MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(meshDim));
6582   return typmai3[ct];
6583 }
6584
6585 void MEDFileStructuredMesh::LoadStrMeshDAFromFile(med_idt fid, int meshDim, int dt, int it, const std::string& mName, MEDFileMeshReadSelector *mrs,
6586                                                   MCAuto<DataArrayIdType>& famCells, MCAuto<DataArrayIdType>& numCells, MCAuto<DataArrayAsciiChar>& namesCells)
6587 {
6588   med_bool chgt=MED_FALSE,trsf=MED_FALSE;
6589   med_geometry_type geoTypeReq=MEDFileStructuredMesh::GetGeoTypeFromMeshDim(meshDim);
6590   mcIdType nbOfElt(0);
6591   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf);
6592   if(nbOfElt>0)
6593     {
6594       if(!mrs || mrs->isCellFamilyFieldReading())
6595         {
6596           MCAuto<DataArrayMedInt> miFamCells=DataArrayMedInt::New();
6597           miFamCells->alloc(nbOfElt,1);
6598           MEDFILESAFECALLERRD0(MEDmeshEntityFamilyNumberRd,(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,miFamCells->getPointer()));
6599           famCells = FromMedIntArray<mcIdType>( miFamCells );
6600         }
6601     }
6602   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,MED_NUMBER,MED_NODAL,&chgt,&trsf);
6603   if(nbOfElt>0)
6604     {
6605       if(!mrs || mrs->isCellNumFieldReading())
6606         {
6607           MCAuto<DataArrayMedInt> miNumCells=DataArrayMedInt::New();
6608           miNumCells->alloc(nbOfElt,1);
6609           MEDFILESAFECALLERRD0(MEDmeshEntityNumberRd,(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,miNumCells->getPointer()));
6610           numCells = FromMedIntArray<mcIdType>( miNumCells );
6611         }
6612     }
6613   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,MED_NAME,MED_NODAL,&chgt,&trsf);
6614   if(nbOfElt>0)
6615     {
6616       if(!mrs || mrs->isCellNameFieldReading())
6617         {
6618           namesCells=DataArrayAsciiChar::New();
6619           namesCells->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end
6620           MEDFILESAFECALLERRD0(MEDmeshEntityNameRd,(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,namesCells->getPointer()));
6621           namesCells->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end
6622         }
6623     }
6624 }
6625
6626 void MEDFileStructuredMesh::loadStrMeshFromFile(MEDFileStrMeshL2 *strm, med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6627 {
6628   setName(strm->getName());
6629   setDescription(strm->getDescription());
6630   setUnivName(strm->getUnivName());
6631   setIteration(strm->getIteration());
6632   setOrder(strm->getOrder());
6633   setTimeValue(strm->getTime());
6634   setTimeUnit(strm->getTimeUnit());
6635   MEDFileMeshL2::ReadFamiliesAndGrps(fid,mName,_families,_groups,mrs);
6636   med_bool chgt=MED_FALSE,trsf=MED_FALSE;
6637   mcIdType nbOfElt(MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf));
6638   if(nbOfElt>0)
6639     {
6640       if(!mrs || mrs->isNodeFamilyFieldReading())
6641         {
6642           mcIdType nbNodes(getNumberOfNodes());
6643           if(nbOfElt>nbNodes)
6644             throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::loadStrMeshFromFile : invalid size of family node array regarding number of nodes in this ! File seems to be corrupted !");
6645           MCAuto<DataArrayMedInt> miFamNodes=DataArrayMedInt::New();
6646           miFamNodes->alloc(nbNodes,1);//yes nbNodes and not nbOfElt see next line.
6647           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...
6648             miFamNodes->fillWithZero();
6649           MEDFILESAFECALLERRD0(MEDmeshEntityFamilyNumberRd,(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,miFamNodes->getPointer()));
6650           _fam_nodes = FromMedIntArray<mcIdType>( miFamNodes );
6651         }
6652     }
6653   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_NUMBER,MED_NODAL,&chgt,&trsf);
6654   if(nbOfElt>0)
6655     {
6656       if(!mrs || mrs->isNodeNumFieldReading())
6657         {
6658           MCAuto<DataArrayMedInt> miNumNodes=DataArrayMedInt::New();
6659           miNumNodes->alloc(nbOfElt,1);
6660           MEDFILESAFECALLERRD0(MEDmeshEntityNumberRd,(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,miNumNodes->getPointer()));
6661           _num_nodes = FromMedIntArray<mcIdType>( miNumNodes );
6662         }
6663     }
6664   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_NAME,MED_NODAL,&chgt,&trsf);
6665   if(nbOfElt>0)
6666     {
6667       if(!mrs || mrs->isNodeNameFieldReading())
6668         {
6669           _names_nodes=DataArrayAsciiChar::New();
6670           _names_nodes->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end
6671           MEDFILESAFECALLERRD0(MEDmeshEntityNameRd,(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,_names_nodes->getPointer()));
6672           _names_nodes->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end
6673         }
6674     }
6675   int meshDim(getStructuredMesh()->getMeshDimension());
6676   LoadStrMeshDAFromFile(fid,meshDim,dt,it,mName,mrs,_fam_cells,_num_cells,_names_cells);
6677   if(meshDim>=1)
6678     LoadStrMeshDAFromFile(fid,meshDim-1,dt,it,mName,mrs,_fam_faces,_num_faces,_names_faces);
6679 }
6680
6681 void MEDFileStructuredMesh::writeStructuredLL(med_idt fid, const std::string& maa) const
6682 {
6683   int meshDim(getStructuredMesh()->getMeshDimension());
6684   med_geometry_type geoTypeReq(GetGeoTypeFromMeshDim(meshDim)),geoTypeReq2(GetGeoTypeFromMeshDim(meshDim-1));
6685   //
6686   if((const DataArrayIdType *)_fam_cells)
6687     MEDFILESAFECALLERWR0(MEDmeshEntityFamilyNumberWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq,ToMedInt(_fam_cells->getNumberOfTuples()),ToMedIntArray(_fam_cells)->getConstPointer()));
6688   if((const DataArrayIdType *)_fam_faces)
6689     MEDFILESAFECALLERWR0(MEDmeshEntityFamilyNumberWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq2,ToMedInt(_fam_faces->getNumberOfTuples()),ToMedIntArray(_fam_faces)->getConstPointer()));
6690   if((const DataArrayIdType *)_fam_nodes)
6691     MEDFILESAFECALLERWR0(MEDmeshEntityFamilyNumberWr,(fid,maa.c_str(),_iteration,_order,MED_NODE,MED_NONE,ToMedInt(_fam_nodes->getNumberOfTuples()),ToMedIntArray(_fam_nodes)->getConstPointer()));
6692   if((const DataArrayIdType *)_num_cells)
6693     MEDFILESAFECALLERWR0(MEDmeshEntityNumberWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq,ToMedInt(_num_cells->getNumberOfTuples()),ToMedIntArray(_num_cells)->getConstPointer()));
6694   if((const DataArrayIdType *)_num_faces)
6695     MEDFILESAFECALLERWR0(MEDmeshEntityNumberWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq2,ToMedInt(_num_faces->getNumberOfTuples()),ToMedIntArray(_num_faces)->getConstPointer()));
6696   if((const DataArrayIdType *)_num_nodes)
6697     MEDFILESAFECALLERWR0(MEDmeshEntityNumberWr,(fid,maa.c_str(),_iteration,_order,MED_NODE,MED_NONE,ToMedInt(_num_nodes->getNumberOfTuples()),ToMedIntArray(_num_nodes)->getConstPointer()));
6698   if((const DataArrayAsciiChar *)_names_cells)
6699     {
6700       if(_names_cells->getNumberOfComponents()!=MED_SNAME_SIZE)
6701         {
6702           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on cells with number of components set to " << MED_SNAME_SIZE;
6703           oss << " ! The array has " << _names_cells->getNumberOfComponents() << " components !";
6704           throw INTERP_KERNEL::Exception(oss.str().c_str());
6705         }
6706       MEDFILESAFECALLERWR0(MEDmeshEntityNameWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq,ToMedInt(_names_cells->getNumberOfTuples()),_names_cells->getConstPointer()));
6707     }
6708   if((const DataArrayAsciiChar *)_names_faces)
6709     {
6710       if(_names_faces->getNumberOfComponents()!=MED_SNAME_SIZE)
6711         {
6712           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on faces with number of components set to " << MED_SNAME_SIZE;
6713           oss << " ! The array has " << _names_faces->getNumberOfComponents() << " components !";
6714           throw INTERP_KERNEL::Exception(oss.str().c_str());
6715         }
6716       MEDFILESAFECALLERWR0(MEDmeshEntityNameWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq2,ToMedInt(_names_faces->getNumberOfTuples()),_names_faces->getConstPointer()));
6717     }
6718   if((const DataArrayAsciiChar *)_names_nodes)
6719     {
6720       if(_names_nodes->getNumberOfComponents()!=MED_SNAME_SIZE)
6721         {
6722           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on nodes with number of components set to " << MED_SNAME_SIZE;
6723           oss << " ! The array has " << _names_cells->getNumberOfComponents() << " components !";
6724           throw INTERP_KERNEL::Exception(oss.str().c_str());
6725         }
6726       MEDFILESAFECALLERWR0(MEDmeshEntityNameWr,(fid,maa.c_str(),_iteration,_order,MED_NODE,MED_NONE,ToMedInt(_names_nodes->getNumberOfTuples()),_names_nodes->getConstPointer()));
6727     }
6728   //
6729   MEDFileUMeshL2::WriteFamiliesAndGrps(fid,maa.c_str(),_families,_groups,_too_long_str);
6730 }
6731
6732 /*!
6733  * Returns an empty instance of MEDFileCMesh.
6734  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
6735  *          mesh using decrRef() as it is no more needed. 
6736  */
6737 MEDFileCMesh *MEDFileCMesh::New()
6738 {
6739   return new MEDFileCMesh;
6740 }
6741
6742 /*!
6743  * Returns a new MEDFileCMesh holding the mesh data that has been read from a given MED
6744  * file. The first mesh in the file is loaded.
6745  *  \param [in] fileName - the name of MED file to read.
6746  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
6747  *          mesh using decrRef() as it is no more needed. 
6748  *  \throw If the file is not readable.
6749  *  \throw If there is no meshes in the file.
6750  *  \throw If the mesh in the file is not a Cartesian one.
6751  */
6752 MEDFileCMesh *MEDFileCMesh::New(const std::string& fileName, MEDFileMeshReadSelector *mrs)
6753 {
6754   MEDFileUtilities::AutoFid fid(OpenMEDFileForRead(fileName));
6755   return New(fid,mrs);
6756 }
6757
6758 MEDFileCMesh *MEDFileCMesh::New(med_idt fid, MEDFileMeshReadSelector *mrs)
6759 {
6760   return NewForTheFirstMeshInFile<MEDFileCMesh>(fid,mrs);
6761 }
6762
6763 /*!
6764  * Returns a new MEDFileCMesh holding the mesh data that has been read from a given MED
6765  * file. The mesh to load is specified by its name and numbers of a time step and an
6766  * iteration.
6767  *  \param [in] fileName - the name of MED file to read.
6768  *  \param [in] mName - the name of the mesh to read.
6769  *  \param [in] dt - the number of a time step.
6770  *  \param [in] it - the number of an iteration.
6771  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
6772  *          mesh using decrRef() as it is no more needed. 
6773  *  \throw If the file is not readable.
6774  *  \throw If there is no mesh with given attributes in the file.
6775  *  \throw If the mesh in the file is not a Cartesian one.
6776  */
6777 MEDFileCMesh *MEDFileCMesh::New(const std::string& fileName, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6778 {
6779   MEDFileUtilities::AutoFid fid(OpenMEDFileForRead(fileName));
6780   return New(fid,mName,dt,it,mrs);
6781 }
6782
6783 MEDFileCMesh *MEDFileCMesh::New(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6784 {
6785   return new MEDFileCMesh(fid,mName,dt,it,mrs);
6786 }
6787
6788 std::size_t MEDFileCMesh::getHeapMemorySizeWithoutChildren() const
6789 {
6790   return MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren();
6791 }
6792
6793 std::vector<const BigMemoryObject *> MEDFileCMesh::getDirectChildrenWithNull() const
6794 {
6795   std::vector<const BigMemoryObject *> ret(MEDFileStructuredMesh::getDirectChildrenWithNull());
6796   ret.push_back((const MEDCouplingCMesh *)_cmesh);
6797   return ret;
6798 }
6799
6800 /*!
6801  * Returns the dimension on cells in \a this mesh.
6802  *  \return int - the mesh dimension.
6803  *  \throw If there are no cells in this mesh.
6804  */
6805 int MEDFileCMesh::getMeshDimension() const
6806 {
6807   if(!((const MEDCouplingCMesh*)_cmesh))
6808     throw INTERP_KERNEL::Exception("MEDFileCMesh::getMeshDimension : unable to get meshdimension because no mesh set !");
6809   return _cmesh->getMeshDimension();
6810 }
6811
6812 /*!
6813  * Returns the dimension on nodes in \a this mesh.
6814  *  \return int - the space dimension.
6815  *  \throw If there are no cells in this mesh.
6816  */
6817 int MEDFileCMesh::getSpaceDimension() const
6818 {
6819   if(!((const MEDCouplingCMesh*)_cmesh))
6820     throw INTERP_KERNEL::Exception("MEDFileCMesh::getSpaceDimension : unable to get spacedimension because no mesh set !");
6821   return _cmesh->getSpaceDimension();
6822 }
6823
6824 /*!
6825  * Returns a string describing \a this mesh.
6826  *  \return std::string - the mesh information string.
6827  */
6828 std::string MEDFileCMesh::simpleRepr() const
6829 {
6830   return MEDFileStructuredMesh::simpleRepr();
6831 }
6832
6833 /*!
6834  * Returns a full textual description of \a this mesh.
6835  *  \return std::string - the string holding the mesh description.
6836  */
6837 std::string MEDFileCMesh::advancedRepr() const
6838 {
6839   return simpleRepr();
6840 }
6841
6842 MEDFileCMesh *MEDFileCMesh::shallowCpy() const
6843 {
6844   MCAuto<MEDFileCMesh> ret(new MEDFileCMesh(*this));
6845   return ret.retn();
6846 }
6847
6848 MEDFileMesh *MEDFileCMesh::createNewEmpty() const
6849 {
6850   return new MEDFileCMesh;
6851 }
6852
6853 MEDFileCMesh *MEDFileCMesh::deepCopy() const
6854 {
6855   MCAuto<MEDFileCMesh> ret(new MEDFileCMesh(*this));
6856   ret->deepCpyEquivalences(*this);
6857   if((const MEDCouplingCMesh*)_cmesh)
6858     ret->_cmesh=static_cast<MEDCouplingCMesh*>(_cmesh->deepCopy());
6859   ret->deepCpyAttributes();
6860   return ret.retn();
6861 }
6862
6863 /*!
6864  * Checks if \a this and another mesh are equal.
6865  *  \param [in] other - the mesh to compare with.
6866  *  \param [in] eps - a precision used to compare real values.
6867  *  \param [in,out] what - the string returning description of unequal data.
6868  *  \return bool - \c true if the meshes are equal, \c false, else.
6869  */
6870 bool MEDFileCMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
6871 {
6872   if(!MEDFileStructuredMesh::isEqual(other,eps,what))
6873     return false;
6874   const MEDFileCMesh *otherC=dynamic_cast<const MEDFileCMesh *>(other);
6875   if(!otherC)
6876     {
6877       what="Mesh types differ ! This is cartesian and other is NOT !";
6878       return false;
6879     }
6880   clearNonDiscrAttributes();
6881   otherC->clearNonDiscrAttributes();
6882   const MEDCouplingCMesh *coo1=_cmesh;
6883   const MEDCouplingCMesh *coo2=otherC->_cmesh;
6884   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
6885     {
6886       what="Mismatch of cartesian meshes ! One is defined and not other !";
6887       return false;
6888     }
6889   if(coo1)
6890     {
6891       bool ret=coo1->isEqual(coo2,eps);
6892       if(!ret)
6893         {
6894           what="cartesian meshes differ !";
6895           return false;
6896         }
6897     }
6898   return true;
6899 }
6900
6901 /*!
6902  * Clears redundant attributes of incorporated data arrays.
6903  */
6904 void MEDFileCMesh::clearNonDiscrAttributes() const
6905 {
6906   MEDFileStructuredMesh::clearNonDiscrAttributes();
6907   MEDFileUMeshSplitL1::ClearNonDiscrAttributes(_cmesh);//to it is not a bug umeshsplit have already the method implemented
6908 }
6909
6910 MEDFileCMesh::MEDFileCMesh()
6911 {
6912 }
6913
6914 MEDFileCMesh::MEDFileCMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6915 try
6916 {
6917     loadLLWithAdditionalItems(fid,mName,dt,it,mrs);
6918 }
6919 catch(INTERP_KERNEL::Exception& e)
6920 {
6921     throw e;
6922 }
6923
6924 void MEDFileCMesh::loadLL(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
6925 {
6926   MEDCoupling::MEDCouplingMeshType meshType;
6927   int dummy0,dummy1;
6928   std::string dtunit;
6929   MEDCoupling::MEDCouplingAxisType axType;
6930   INTERP_KERNEL::AutoCppPtr<MeshOrStructMeshCls> mid(MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,axType,dummy0,dummy1,dtunit));
6931   if(meshType!=CARTESIAN)
6932     {
6933       std::ostringstream oss; oss << "Trying to load as cartesian an existing mesh with name '" << mName << "' that is NOT cartesian !";
6934       throw INTERP_KERNEL::Exception(oss.str().c_str());
6935     }
6936   MEDFileCMeshL2 loaderl2;
6937   loaderl2.loadAll(fid,mid,mName,dt,it);
6938   setAxisType(axType);
6939   MEDCouplingCMesh *mesh=loaderl2.getMesh();
6940   mesh->incrRef();
6941   _cmesh=mesh;
6942   loadStrMeshFromFile(&loaderl2,fid,mName,dt,it,mrs);
6943 }
6944
6945 /*!
6946  * Returns a const pointer to MEDCouplingCMesh held by \a this mesh.
6947  *  \return const MEDCouplingCMesh * - a pointer to the held MEDCouplingCMesh.
6948  */
6949 const MEDCouplingCMesh *MEDFileCMesh::getMesh() const
6950 {
6951   synchronizeTinyInfoOnLeaves();
6952   return _cmesh;
6953 }
6954
6955 const MEDCouplingStructuredMesh *MEDFileCMesh::getStructuredMesh() const
6956 {
6957   synchronizeTinyInfoOnLeaves();
6958   return _cmesh;
6959 }
6960
6961 /*!
6962  * Sets the MEDCouplingCMesh holding the data of \a this mesh.
6963  *  \param [in] m - the new MEDCouplingCMesh to refer to.
6964  *  \throw If the name or the description of \a this mesh and \a m are not empty and are
6965  *         different. 
6966  */
6967 void MEDFileCMesh::setMesh(MEDCouplingCMesh *m)
6968 {
6969   dealWithTinyInfo(m);
6970   if(m)
6971     m->incrRef();
6972   _cmesh=m;
6973 }
6974
6975 MEDFileMesh *MEDFileCMesh::cartesianize() const
6976 {
6977   if(getAxisType()==AX_CART)
6978     {
6979       incrRef();
6980       return const_cast<MEDFileCMesh *>(this);
6981     }
6982   else
6983     {
6984       const MEDCouplingCMesh *cmesh(getMesh());
6985       if(!cmesh)
6986         throw INTERP_KERNEL::Exception("MEDFileCMesh::cartesianize : impossible to turn into cartesian because the mesh is null !");
6987       MCAuto<MEDCouplingCurveLinearMesh> clmesh(cmesh->buildCurveLinear());
6988       MCAuto<DataArrayDouble> coords(clmesh->getCoords()->cartesianize(getAxisType()));
6989       clmesh->setCoords(coords);
6990       MCAuto<MEDFileCurveLinearMesh> ret(MEDFileCurveLinearMesh::New());
6991       ret->MEDFileStructuredMesh::operator=(*this);
6992       ret->setMesh(clmesh);
6993       ret->setAxisType(AX_CART);
6994       return ret.retn();
6995     }
6996 }
6997
6998 void MEDFileCMesh::writeMeshLL(med_idt fid) const
6999 {
7000   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
7001   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
7002   INTERP_KERNEL::AutoPtr<char> dtunit=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE);
7003   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
7004   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
7005   MEDLoaderBase::safeStrCpy(_dt_unit.c_str(),MED_LNAME_SIZE,dtunit,_too_long_str);
7006   int spaceDim(_cmesh->getSpaceDimension());
7007   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
7008   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
7009   for(int i=0;i<spaceDim;i++)
7010     {
7011       std::string info(_cmesh->getCoordsAt(i)->getInfoOnComponent(0));
7012       std::string c,u;
7013       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
7014       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
7015       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
7016     }
7017   MEDFILESAFECALLERWR0(MEDmeshCr,(fid,maa,spaceDim,spaceDim,MED_STRUCTURED_MESH,desc,dtunit,MED_SORT_DTIT,MEDFileMeshL2::TraduceAxisTypeRev(getAxisType()),comp,unit));
7018   if(_univ_wr_status)
7019     MEDFILESAFECALLERWR0(MEDmeshUniversalNameWr,(fid,maa));
7020   MEDFILESAFECALLERWR0(MEDmeshGridTypeWr,(fid,maa,MEDFileMeshL2::TraduceAxisTypeRevStruct(getAxisType())));
7021   for(int i=0;i<spaceDim;i++)
7022     {
7023       const DataArrayDouble *da=_cmesh->getCoordsAt(i);
7024       MEDFILESAFECALLERWR0(MEDmeshGridIndexCoordinateWr,(fid,maa,_iteration,_order,_time,i+1,ToMedInt(da->getNumberOfTuples()),da->getConstPointer()));
7025     }
7026   //
7027   std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE));
7028   MEDFileStructuredMesh::writeStructuredLL(fid,meshName);
7029 }
7030
7031 void MEDFileCMesh::synchronizeTinyInfoOnLeaves() const
7032 {
7033   const MEDCouplingCMesh *cmesh=_cmesh;
7034   if(!cmesh)
7035     return;
7036   (const_cast<MEDCouplingCMesh *>(cmesh))->setName(_name);
7037   (const_cast<MEDCouplingCMesh *>(cmesh))->setDescription(_desc_name);
7038   (const_cast<MEDCouplingCMesh *>(cmesh))->setTime(_time,_iteration,_order);
7039   (const_cast<MEDCouplingCMesh *>(cmesh))->setTimeUnit(_dt_unit);
7040 }
7041
7042 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New()
7043 {
7044   return new MEDFileCurveLinearMesh;
7045 }
7046
7047 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(med_idt fid, MEDFileMeshReadSelector *mrs)
7048 {
7049   return NewForTheFirstMeshInFile<MEDFileCurveLinearMesh>(fid,mrs);
7050 }
7051
7052 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const std::string& fileName, MEDFileMeshReadSelector *mrs)
7053 {
7054   MEDFileUtilities::AutoFid fid(OpenMEDFileForRead(fileName));
7055   return New(fid,mrs);
7056 }
7057
7058 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const std::string& fileName, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
7059 {
7060   MEDFileUtilities::AutoFid fid(OpenMEDFileForRead(fileName));
7061   return New(fid,mName,dt,it,mrs);
7062 }
7063
7064 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
7065 {
7066   return new MEDFileCurveLinearMesh(fid,mName,dt,it,mrs);
7067 }
7068
7069 std::size_t MEDFileCurveLinearMesh::getHeapMemorySizeWithoutChildren() const
7070 {
7071   return MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren();
7072 }
7073
7074 std::vector<const BigMemoryObject *> MEDFileCurveLinearMesh::getDirectChildrenWithNull() const
7075 {
7076   std::vector<const BigMemoryObject *> ret(MEDFileStructuredMesh::getDirectChildrenWithNull());
7077   ret.push_back((const MEDCouplingCurveLinearMesh *)_clmesh);
7078   return ret;
7079 }
7080
7081 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::shallowCpy() const
7082 {
7083   MCAuto<MEDFileCurveLinearMesh> ret(new MEDFileCurveLinearMesh(*this));
7084   return ret.retn();
7085 }
7086
7087 MEDFileMesh *MEDFileCurveLinearMesh::createNewEmpty() const
7088 {
7089   return new MEDFileCurveLinearMesh;
7090 }
7091
7092 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::deepCopy() const
7093 {
7094   MCAuto<MEDFileCurveLinearMesh> ret(new MEDFileCurveLinearMesh(*this));
7095   ret->deepCpyEquivalences(*this);
7096   if((const MEDCouplingCurveLinearMesh*)_clmesh)
7097     ret->_clmesh=static_cast<MEDCouplingCurveLinearMesh*>(_clmesh->deepCopy());
7098   ret->deepCpyAttributes();
7099   return ret.retn();
7100 }
7101
7102 int MEDFileCurveLinearMesh::getMeshDimension() const
7103 {
7104   if(!((const MEDCouplingCurveLinearMesh*)_clmesh))
7105     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::getMeshDimension : unable to get meshdimension because no mesh set !");
7106   return _clmesh->getMeshDimension();
7107 }
7108
7109 std::string MEDFileCurveLinearMesh::simpleRepr() const
7110 {
7111   return MEDFileStructuredMesh::simpleRepr();
7112 }
7113
7114 std::string MEDFileCurveLinearMesh::advancedRepr() const
7115 {
7116   return simpleRepr();
7117 }
7118
7119 bool MEDFileCurveLinearMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
7120 {
7121   if(!MEDFileStructuredMesh::isEqual(other,eps,what))
7122     return false;
7123   const MEDFileCurveLinearMesh *otherC=dynamic_cast<const MEDFileCurveLinearMesh *>(other);
7124   if(!otherC)
7125     {
7126       what="Mesh types differ ! This is curve linear and other is NOT !";
7127       return false;
7128     }
7129   clearNonDiscrAttributes();
7130   otherC->clearNonDiscrAttributes();
7131   const MEDCouplingCurveLinearMesh *coo1=_clmesh;
7132   const MEDCouplingCurveLinearMesh *coo2=otherC->_clmesh;
7133   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
7134     {
7135       what="Mismatch of curve linear meshes ! One is defined and not other !";
7136       return false;
7137     }
7138   if(coo1)
7139     {
7140       bool ret=coo1->isEqual(coo2,eps);
7141       if(!ret)
7142         {
7143           what="curve linear meshes differ !";
7144           return false;
7145         }
7146     }
7147   return true;
7148 }
7149
7150 void MEDFileCurveLinearMesh::clearNonDiscrAttributes() const
7151 {
7152   MEDFileStructuredMesh::clearNonDiscrAttributes();
7153   MEDFileUMeshSplitL1::ClearNonDiscrAttributes(_clmesh);//to it is not a bug umeshsplit have already the method implemented
7154 }
7155
7156 void MEDFileCurveLinearMesh::synchronizeTinyInfoOnLeaves() const
7157 {
7158   const MEDCouplingCurveLinearMesh *clmesh=_clmesh;
7159   if(!clmesh)
7160     return;
7161   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setName(_name);
7162   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setDescription(_desc_name);
7163   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setTime(_time,_iteration,_order);
7164   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setTimeUnit(_dt_unit);
7165 }
7166
7167 const MEDCouplingCurveLinearMesh *MEDFileCurveLinearMesh::getMesh() const
7168 {
7169   synchronizeTinyInfoOnLeaves();
7170   return _clmesh;
7171 }
7172
7173 void MEDFileCurveLinearMesh::setMesh(MEDCouplingCurveLinearMesh *m)
7174 {
7175   dealWithTinyInfo(m);
7176   if(m)
7177     m->incrRef();
7178   _clmesh=m;
7179 }
7180
7181 MEDFileMesh *MEDFileCurveLinearMesh::cartesianize() const
7182 {
7183   if(getAxisType()==AX_CART)
7184     {
7185       incrRef();
7186       return const_cast<MEDFileCurveLinearMesh *>(this);
7187     }
7188   else
7189     {
7190       const MEDCouplingCurveLinearMesh *mesh(getMesh());
7191       if(!mesh)
7192         throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::cartesianize : impossible to turn into cartesian because the mesh is null !");
7193       const DataArrayDouble *coords(mesh->getCoords());
7194       if(!coords)
7195         throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::cartesianize : coordinate pointer in mesh is null !");
7196       MCAuto<MEDFileCurveLinearMesh> ret(new MEDFileCurveLinearMesh(*this));
7197       MCAuto<MEDCouplingCurveLinearMesh> mesh2(mesh->clone(false));
7198       MCAuto<DataArrayDouble> coordsCart(coords->cartesianize(getAxisType()));
7199       mesh2->setCoords(coordsCart);
7200       ret->setMesh(mesh2);
7201       ret->setAxisType(AX_CART);
7202       return ret.retn();
7203     }
7204 }
7205
7206 const MEDCouplingStructuredMesh *MEDFileCurveLinearMesh::getStructuredMesh() const
7207 {
7208   synchronizeTinyInfoOnLeaves();
7209   return _clmesh;
7210 }
7211
7212 MEDFileCurveLinearMesh::MEDFileCurveLinearMesh()
7213 {
7214 }
7215
7216 MEDFileCurveLinearMesh::MEDFileCurveLinearMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
7217 try
7218 {
7219     loadLLWithAdditionalItems(fid,mName,dt,it,mrs);
7220 }
7221 catch(INTERP_KERNEL::Exception& e)
7222 {
7223     throw e;
7224 }
7225
7226 void MEDFileCurveLinearMesh::writeMeshLL(med_idt fid) const
7227 {
7228   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
7229   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
7230   INTERP_KERNEL::AutoPtr<char> dtunit=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE);
7231   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
7232   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
7233   MEDLoaderBase::safeStrCpy(_dt_unit.c_str(),MED_LNAME_SIZE,dtunit,_too_long_str);
7234   int spaceDim=_clmesh->getSpaceDimension();
7235   int meshDim=_clmesh->getMeshDimension();
7236   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
7237   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
7238   const DataArrayDouble *coords=_clmesh->getCoords();
7239   if(!coords)
7240     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::writeMeshLL : no coordinates set !");
7241   for(int i=0;i<spaceDim;i++)
7242     {
7243       std::string info(_clmesh->getCoords()->getInfoOnComponent(i));
7244       std::string c,u;
7245       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
7246       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
7247       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
7248     }
7249   MEDFILESAFECALLERWR0(MEDmeshCr,(fid,maa,spaceDim,meshDim,MED_STRUCTURED_MESH,desc,dtunit,MED_SORT_DTIT,MEDFileMeshL2::TraduceAxisTypeRev(getAxisType()),comp,unit));
7250   if(_univ_wr_status)
7251     MEDFILESAFECALLERWR0(MEDmeshUniversalNameWr,(fid,maa));
7252   MEDFILESAFECALLERWR0(MEDmeshGridTypeWr,(fid,maa,MED_CURVILINEAR_GRID));
7253   std::vector<mcIdType> nodeGridSt=_clmesh->getNodeGridStructure();
7254   MEDFILESAFECALLERWR0(MEDmeshGridStructWr,(fid,maa,_iteration,_order,_time,ToMedIntArray(nodeGridSt)->getConstPointer()));
7255
7256   MEDFILESAFECALLERWR0(MEDmeshNodeCoordinateWr,(fid,maa,_iteration,_order,_time,MED_FULL_INTERLACE,ToMedInt(coords->getNumberOfTuples()),coords->begin()));
7257   //
7258   std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE));
7259   MEDFileStructuredMesh::writeStructuredLL(fid,meshName);
7260 }
7261
7262 void MEDFileCurveLinearMesh::loadLL(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
7263 {
7264   MEDCoupling::MEDCouplingMeshType meshType;
7265   int dummy0,dummy1;
7266   std::string dtunit;
7267   MEDCoupling::MEDCouplingAxisType axType;
7268   INTERP_KERNEL::AutoCppPtr<MeshOrStructMeshCls> mid(MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,axType,dummy0,dummy1,dtunit));
7269   setAxisType(axType);
7270   if(meshType!=CURVE_LINEAR)
7271     {
7272       std::ostringstream oss; oss << "Trying to load as curve linear an existing mesh with name '" << mName << "' that is NOT curve linear !";
7273       throw INTERP_KERNEL::Exception(oss.str().c_str());
7274     }
7275   MEDFileCLMeshL2 loaderl2;
7276   loaderl2.loadAll(fid,mid,mName,dt,it);
7277   MEDCouplingCurveLinearMesh *mesh=loaderl2.getMesh();
7278   mesh->incrRef();
7279   _clmesh=mesh;
7280   loadStrMeshFromFile(&loaderl2,fid,mName,dt,it,mrs);
7281 }
7282
7283 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New()
7284 {
7285   return new MEDFileMeshMultiTS;
7286 }
7287
7288 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(med_idt fid)
7289 {
7290   return new MEDFileMeshMultiTS(fid);
7291 }
7292
7293 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(const std::string& fileName)
7294 {
7295   MEDFileUtilities::AutoFid fid(OpenMEDFileForRead(fileName));
7296   return New(fid);
7297 }
7298
7299 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(med_idt fid, const std::string& mName)
7300 {
7301   return new MEDFileMeshMultiTS(fid,mName);
7302 }
7303
7304 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(const std::string& fileName, const std::string& mName)
7305 {
7306   MEDFileUtilities::AutoFid fid(OpenMEDFileForRead(fileName));
7307   return New(fid,mName);
7308 }
7309
7310 MEDFileMeshMultiTS *MEDFileMeshMultiTS::deepCopy() const
7311 {
7312   MCAuto<MEDFileMeshMultiTS> ret(MEDFileMeshMultiTS::New());
7313   std::vector< MCAuto<MEDFileMesh> > meshOneTs(_mesh_one_ts.size());
7314   std::size_t i(0);
7315   for(std::vector< MCAuto<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++,i++)
7316     if((const MEDFileMesh *)*it)
7317       meshOneTs[i]=(*it)->deepCopy();
7318   ret->_mesh_one_ts=meshOneTs;
7319   return ret.retn();
7320 }
7321
7322 std::size_t MEDFileMeshMultiTS::getHeapMemorySizeWithoutChildren() const
7323 {
7324   return _mesh_one_ts.capacity()*sizeof(MCAuto<MEDFileMesh>);
7325 }
7326
7327 std::vector<const BigMemoryObject *> MEDFileMeshMultiTS::getDirectChildrenWithNull() const
7328 {
7329   std::vector<const BigMemoryObject *> ret;
7330   for(std::vector< MCAuto<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
7331     ret.push_back((const MEDFileMesh *)*it);
7332   return ret;
7333 }
7334
7335 std::string MEDFileMeshMultiTS::getName() const
7336 {
7337   if(_mesh_one_ts.empty())
7338     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::getName : no time steps set !");
7339   return _mesh_one_ts[0]->getName();
7340 }
7341
7342 void MEDFileMeshMultiTS::setName(const std::string& newMeshName)
7343 {
7344   std::string oldName(getName());
7345   std::vector< std::pair<std::string,std::string> > v(1);
7346   v[0].first=oldName; v[0].second=newMeshName;
7347   changeNames(v);
7348 }
7349
7350 bool MEDFileMeshMultiTS::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab)
7351 {
7352   bool ret=false;
7353   for(std::vector< MCAuto<MEDFileMesh> >::iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
7354     {
7355       MEDFileMesh *cur(*it);
7356       if(cur)
7357         ret=cur->changeNames(modifTab) || ret;
7358     }
7359   return ret;
7360 }
7361
7362 void MEDFileMeshMultiTS::cartesianizeMe()
7363 {
7364   for(std::vector< MCAuto<MEDFileMesh> >::iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
7365     {
7366       MEDFileMesh *cur(*it);
7367       if(cur)
7368         {
7369           MCAuto<MEDFileMesh> ccur(cur->cartesianize());// Attention ! Do not wrap these two lines because memory leak !
7370           *it=ccur;
7371         }
7372     }
7373 }
7374
7375 MEDFileMesh *MEDFileMeshMultiTS::getOneTimeStep() const
7376 {
7377   if(_mesh_one_ts.empty())
7378     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::getOneTimeStep : empty time step set !");
7379   return const_cast<MEDFileMesh *>(static_cast<const MEDFileMesh *>(_mesh_one_ts[0]));
7380 }
7381
7382 void MEDFileMeshMultiTS::setOneTimeStep(MEDFileMesh *mesh1TimeStep)
7383 {
7384   if(!mesh1TimeStep)
7385     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::setOneTimeStep : input pointer should be different from 0 !");
7386   _mesh_one_ts.resize(1);
7387   mesh1TimeStep->incrRef();
7388   //MCAuto<MEDFileMesh> toto=mesh1TimeStep;
7389   _mesh_one_ts[0]=mesh1TimeStep;
7390 }
7391
7392 MEDFileJoints * MEDFileMeshMultiTS::getJoints() const
7393 {
7394   if ( MEDFileMesh* m = getOneTimeStep() )
7395     return m->getJoints();
7396   return 0;
7397 }
7398
7399 /*!
7400  * \brief Set Joints that are common to all time-stamps
7401  */
7402 void MEDFileMeshMultiTS::setJoints( MEDFileJoints* joints )
7403 {
7404   for(std::vector< MCAuto<MEDFileMesh> >::iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
7405     {
7406       (*it)->setJoints( joints );
7407     }
7408 }
7409
7410 bool MEDFileMeshMultiTS::presenceOfStructureElements() const
7411 {
7412   for(std::vector< MCAuto<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
7413     if((*it).isNotNull())
7414       if((*it)->presenceOfStructureElements())
7415         return true;
7416   return false;
7417 }
7418
7419 void MEDFileMeshMultiTS::killStructureElements()
7420 {
7421   for(std::vector< MCAuto<MEDFileMesh> >::iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
7422     if((*it).isNotNull())
7423       (*it)->killStructureElements();
7424 }
7425
7426 void MEDFileMeshMultiTS::writeLL(med_idt fid) const
7427 {
7428   MEDFileJoints *joints(getJoints());
7429   bool jointsWritten(false);
7430
7431   for(std::vector< MCAuto<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
7432     {
7433       if ( jointsWritten )
7434         const_cast<MEDFileMesh&>(**it).setJoints( 0 );
7435       else
7436         jointsWritten = true;
7437
7438       (*it)->copyOptionsFrom(*this);
7439       (*it)->writeLL(fid);
7440     }
7441
7442   (const_cast<MEDFileMeshMultiTS*>(this))->setJoints( joints ); // restore joints
7443 }
7444
7445 void MEDFileMeshMultiTS::loadFromFile(med_idt fid, const std::string& mName)
7446 {
7447   MEDFileJoints *joints(0);
7448   if ( !_mesh_one_ts.empty() && getOneTimeStep() )
7449     {
7450       // joints of mName already read, pass them to MEDFileMesh::New() to prevent repeated reading
7451       joints = getOneTimeStep()->getJoints();
7452     }
7453   _mesh_one_ts.clear();  //for the moment to be improved
7454   _mesh_one_ts.push_back( MEDFileMesh::New(fid,mName,-1,-1,0, joints ));
7455 }
7456
7457 MEDFileMeshMultiTS::MEDFileMeshMultiTS()
7458 {
7459 }
7460
7461 MEDFileMeshMultiTS::MEDFileMeshMultiTS(med_idt fid)
7462 try
7463 {
7464   std::vector<std::string> ms(MEDLoaderNS::getMeshNamesFid(fid));
7465     if(ms.empty())
7466       {
7467         std::ostringstream oss; oss << "MEDFileMeshMultiTS : no meshes in file \"" << FileNameFromFID(fid) << "\" !";
7468         throw INTERP_KERNEL::Exception(oss.str().c_str());
7469       }
7470     int dt,it;
7471     MEDCoupling::MEDCouplingMeshType meshType;
7472     std::string dummy2;
7473     MEDCoupling::MEDCouplingAxisType dummy3;
7474     MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dummy3,dt,it,dummy2);
7475     loadFromFile(fid,ms.front());
7476 }
7477 catch(INTERP_KERNEL::Exception& e)
7478 {
7479     throw e;
7480 }
7481
7482 MEDFileMeshMultiTS::MEDFileMeshMultiTS(med_idt fid, const std::string& mName)
7483 try
7484 {
7485     loadFromFile(fid,mName);
7486 }
7487 catch(INTERP_KERNEL::Exception& e)
7488 {
7489     throw e;
7490 }
7491
7492 MEDFileMeshes *MEDFileMeshes::New()
7493 {
7494   return new MEDFileMeshes;
7495 }
7496
7497 MEDFileMeshes *MEDFileMeshes::New(med_idt fid)
7498 {
7499   return new MEDFileMeshes(fid);
7500 }
7501
7502 MEDFileMeshes *MEDFileMeshes::New(const std::string& fileName)
7503 {
7504   MEDFileUtilities::AutoFid fid(OpenMEDFileForRead(fileName));
7505   return New(fid);
7506 }
7507
7508 void MEDFileMeshes::writeLL(med_idt fid) const
7509 {
7510   checkConsistencyLight();
7511   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++)
7512     {
7513       (*it)->copyOptionsFrom(*this);
7514       (*it)->writeLL(fid);
7515     }
7516 }
7517
7518 //  MEDFileMeshes::writ checkConsistencyLight();
7519
7520 int MEDFileMeshes::getNumberOfMeshes() const
7521 {
7522   return (int)_meshes.size();
7523 }
7524
7525 MEDFileMeshesIterator *MEDFileMeshes::iterator()
7526 {
7527   return new MEDFileMeshesIterator(this);
7528 }
7529
7530 /** Return a borrowed reference (caller is not responsible) */
7531 MEDFileMesh *MEDFileMeshes::getMeshAtPos(int i) const
7532 {
7533   if(i<0 || i>=(int)_meshes.size())
7534     {
7535       std::ostringstream oss; oss << "MEDFileMeshes::getMeshAtPos : invalid mesh id given in parameter ! Should be in [0;" << _meshes.size() << ") !";
7536       throw INTERP_KERNEL::Exception(oss.str().c_str());
7537     }
7538   return _meshes[i]->getOneTimeStep();
7539 }
7540
7541 /** Return a borrowed reference (caller is not responsible) */
7542 MEDFileMesh *MEDFileMeshes::getMeshWithName(const std::string& mname) const
7543 {
7544   std::vector<std::string> ms=getMeshesNames();
7545   std::vector<std::string>::iterator it=std::find(ms.begin(),ms.end(),mname);
7546   if(it==ms.end())
7547     {
7548       std::ostringstream oss; oss << "MEDFileMeshes::getMeshWithName : Mesh  \"" << mname << "\" does not exist in this ! Existing are : ";
7549       std::copy(ms.begin(),ms.end(),std::ostream_iterator<std::string>(oss," "));
7550       throw INTERP_KERNEL::Exception(oss.str().c_str());
7551     }
7552   return getMeshAtPos((int)std::distance(ms.begin(),it));
7553 }
7554
7555 std::vector<std::string> MEDFileMeshes::getMeshesNames() const
7556 {
7557   std::vector<std::string> ret(_meshes.size());
7558   int i=0;
7559   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
7560     {
7561       const MEDFileMeshMultiTS *f=(*it);
7562       if(f)
7563         {
7564           ret[i]=f->getName();
7565         }
7566       else
7567         {
7568           std::ostringstream oss; oss << "MEDFileMeshes::getMeshesNames : At rank #" << i << " mesh is not defined !";
7569           throw INTERP_KERNEL::Exception(oss.str().c_str());
7570         }
7571     }
7572   return ret;
7573 }
7574
7575 bool MEDFileMeshes::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab)
7576 {
7577   bool ret=false;
7578   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::iterator it=_meshes.begin();it!=_meshes.end();it++)
7579     {
7580       MEDFileMeshMultiTS *cur(*it);
7581       if(cur)
7582         ret=cur->changeNames(modifTab) || ret;
7583     }
7584   return ret;
7585 }
7586
7587 void MEDFileMeshes::cartesianizeMe()
7588 {
7589   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::iterator it=_meshes.begin();it!=_meshes.end();it++)
7590     {
7591       MEDFileMeshMultiTS *cur(*it);
7592       if(cur)
7593         cur->cartesianizeMe();
7594     }
7595 }
7596
7597 void MEDFileMeshes::resize(int newSize)
7598 {
7599   _meshes.resize(newSize);
7600 }
7601
7602 void MEDFileMeshes::pushMesh(MEDFileMesh *mesh)
7603 {
7604   if(!mesh)
7605     throw INTERP_KERNEL::Exception("MEDFileMeshes::pushMesh : invalid input pointer ! should be different from 0 !");
7606   MEDFileMeshMultiTS *elt=MEDFileMeshMultiTS::New();
7607   elt->setOneTimeStep(mesh);
7608   _meshes.push_back(elt);
7609 }
7610
7611 void MEDFileMeshes::setMeshAtPos(int i, MEDFileMesh *mesh)
7612 {
7613   if(!mesh)
7614     throw INTERP_KERNEL::Exception("MEDFileMeshes::setMeshAtPos : invalid input pointer ! should be different from 0 !");
7615   if(i>=(int)_meshes.size())
7616     _meshes.resize(i+1);
7617   MEDFileMeshMultiTS *elt=MEDFileMeshMultiTS::New();
7618   elt->setOneTimeStep(mesh);
7619   _meshes[i]=elt;
7620 }
7621
7622 void MEDFileMeshes::destroyMeshAtPos(int i)
7623 {
7624   if(i<0 || i>=(int)_meshes.size())
7625     {
7626       std::ostringstream oss; oss << "MEDFileMeshes::destroyMeshAtPos : Invalid given id in input (" << i << ") should be in [0," << _meshes.size() << ") !";
7627       throw INTERP_KERNEL::Exception(oss.str().c_str());
7628     }
7629   _meshes.erase(_meshes.begin()+i);
7630 }
7631
7632 void MEDFileMeshes::loadFromFile(med_idt fid)
7633 {
7634   std::vector<std::string> ms(MEDLoaderNS::getMeshNamesFid(fid));
7635   int i=0;
7636   _meshes.resize(ms.size());
7637   for(std::vector<std::string>::const_iterator it=ms.begin();it!=ms.end();it++,i++)
7638     _meshes[i]=MEDFileMeshMultiTS::New(fid,(*it));
7639 }
7640
7641 MEDFileMeshes::MEDFileMeshes()
7642 {
7643 }
7644
7645 MEDFileMeshes::MEDFileMeshes(med_idt fid)
7646 try
7647 {
7648     loadFromFile(fid);
7649 }
7650 catch(INTERP_KERNEL::Exception& /*e*/)
7651 {
7652 }
7653
7654 MEDFileMeshes *MEDFileMeshes::deepCopy() const
7655 {
7656   std::vector< MCAuto<MEDFileMeshMultiTS> > meshes(_meshes.size());
7657   std::size_t i=0;
7658   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
7659     if((const MEDFileMeshMultiTS *)*it)
7660       meshes[i]=(*it)->deepCopy();
7661   MCAuto<MEDFileMeshes> ret(MEDFileMeshes::New());
7662   ret->_meshes=meshes;
7663   return ret.retn();
7664 }
7665
7666 std::size_t MEDFileMeshes::getHeapMemorySizeWithoutChildren() const
7667 {
7668   return _meshes.capacity()*(sizeof(MCAuto<MEDFileMeshMultiTS>));
7669 }
7670
7671 std::vector<const BigMemoryObject *> MEDFileMeshes::getDirectChildrenWithNull() const
7672 {
7673   std::vector<const BigMemoryObject *> ret;
7674   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++)
7675     ret.push_back((const MEDFileMeshMultiTS *)*it);
7676   return ret;
7677 }
7678
7679 std::string MEDFileMeshes::simpleRepr() const
7680 {
7681   std::ostringstream oss;
7682   oss << "(*****************)\n(* MEDFileMeshes *)\n(*****************)\n\n";
7683   simpleReprWithoutHeader(oss);
7684   return oss.str();
7685 }
7686
7687 void MEDFileMeshes::simpleReprWithoutHeader(std::ostream& oss) const
7688 {
7689   int nbOfMeshes=getNumberOfMeshes();
7690   oss << "There are " << nbOfMeshes << " meshes with the following names : \n";
7691   std::vector<std::string> mns=getMeshesNames();
7692   for(int i=0;i<nbOfMeshes;i++)
7693     oss << "  - #" << i << " \"" << mns[i] << "\"\n";
7694 }
7695
7696 void MEDFileMeshes::checkConsistencyLight() const
7697 {
7698   static const char MSG[]="MEDFileMeshes::checkConsistencyLight : mesh at rank ";
7699   int i=0;
7700   std::set<std::string> s;
7701   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
7702     {
7703       const MEDFileMeshMultiTS *elt=(*it);
7704       if(!elt)
7705         {
7706           std::ostringstream oss; oss << MSG << i << "/" << _meshes.size() << " is empty !";
7707           throw INTERP_KERNEL::Exception(oss.str().c_str());
7708         }
7709       std::size_t sz=s.size();
7710       s.insert(std::string((*it)->getName()));
7711       if(s.size()==sz)
7712         {
7713           std::ostringstream oss; oss << MSG << i << " has a name (\"" << (*it)->getName() << "\") already used by an another mesh in list !";
7714           throw INTERP_KERNEL::Exception(oss.str().c_str());
7715         }
7716     }
7717 }
7718
7719 bool MEDFileMeshes::presenceOfStructureElements() const
7720 {
7721   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++)
7722     if((*it).isNotNull())
7723       if((*it)->presenceOfStructureElements())
7724         return true;
7725   return false;
7726 }
7727
7728 void MEDFileMeshes::killStructureElements()
7729 {
7730   for(std::vector< MCAuto<MEDFileMeshMultiTS> >::iterator it=_meshes.begin();it!=_meshes.end();it++)
7731     if((*it).isNotNull())
7732       (*it)->killStructureElements();
7733 }
7734
7735 MEDFileMeshesIterator::MEDFileMeshesIterator(MEDFileMeshes *ms):_ms(ms),_iter_id(0),_nb_iter(0)
7736 {
7737   if(ms)
7738     {
7739       ms->incrRef();
7740       _nb_iter=ms->getNumberOfMeshes();
7741     }
7742 }
7743
7744 MEDFileMeshesIterator::~MEDFileMeshesIterator()
7745 {
7746 }
7747
7748 MEDFileMesh *MEDFileMeshesIterator::nextt()
7749 {
7750   if(_iter_id<_nb_iter)
7751     {
7752       MEDFileMeshes *ms(_ms);
7753       if(ms)
7754         return ms->getMeshAtPos(_iter_id++);
7755       else
7756         return 0;
7757     }
7758   else
7759     return 0;
7760 }
7761
7762 INTERP_KERNEL::NormalizedCellType MEDFileMesh::ConvertFromMEDFileGeoType(med_geometry_type geoType)
7763 {
7764   med_geometry_type *pos(std::find(typmai,typmai+MED_N_CELL_FIXED_GEO,geoType));
7765   if(pos==typmai+MED_N_CELL_FIXED_GEO)
7766     {
7767       if(geoType==MED_NO_GEOTYPE)
7768         return INTERP_KERNEL::NORM_ERROR;
7769       std::ostringstream oss; oss << "MEDFileMesh::ConvertFromMEDFileGeoType : no entry with " << geoType << " !"; 
7770       throw INTERP_KERNEL::Exception(oss.str());
7771     }
7772   return typmai2[std::distance(typmai,pos)];
7773 }
7774
7775 TypeOfField MEDFileMesh::ConvertFromMEDFileEntity(med_entity_type etype)
7776 {
7777   switch(etype)
7778     {
7779     case MED_NODE:
7780       return ON_NODES;
7781     case MED_CELL:
7782       return ON_CELLS;
7783     case MED_NODE_ELEMENT:
7784       return ON_GAUSS_NE;
7785     default:
7786       {
7787         std::ostringstream oss; oss << "MEDFileMesh::ConvertFromMEDFileEntity : not recognized entity " << etype << " !";
7788         throw INTERP_KERNEL::Exception(oss.str());
7789       }
7790     }
7791 }
7792
7793