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