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