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