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