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