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