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