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