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