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