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