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