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