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