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