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