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