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