Salome HOME
Merge branch 'master' of ssh://git.salome-platform.org/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::getDirectChildren() 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::getDirectChildren() const
1994 {
1995   std::vector<const BigMemoryObject *> ret(MEDFileMesh::getDirectChildren());
1996   if((const DataArrayDouble*)_coords)
1997     ret.push_back((const DataArrayDouble*)_coords);
1998   if((const DataArrayInt *)_fam_coords)
1999     ret.push_back((const DataArrayInt *)_fam_coords);
2000   if((const DataArrayInt *)_num_coords)
2001     ret.push_back((const DataArrayInt *)_num_coords);
2002   if((const DataArrayInt *)_rev_num_coords)
2003     ret.push_back((const DataArrayInt *)_rev_num_coords);
2004   if((const DataArrayAsciiChar *)_name_coords)
2005     ret.push_back((const DataArrayAsciiChar *)_name_coords);
2006   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2007     if((const MEDFileUMeshSplitL1*) *it)
2008       ret.push_back((const MEDFileUMeshSplitL1*) *it);
2009   return ret;
2010 }
2011
2012 MEDFileMesh *MEDFileUMesh::shallowCpy() const
2013 {
2014   MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret=new MEDFileUMesh(*this);
2015   return ret.retn();
2016 }
2017
2018 MEDFileMesh *MEDFileUMesh::createNewEmpty() const
2019 {
2020   return new MEDFileUMesh;
2021 }
2022
2023 MEDFileMesh *MEDFileUMesh::deepCpy() const
2024 {
2025   MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret=new MEDFileUMesh(*this);
2026   if((const DataArrayDouble*)_coords)
2027     ret->_coords=_coords->deepCpy();
2028   if((const DataArrayInt*)_fam_coords)
2029     ret->_fam_coords=_fam_coords->deepCpy();
2030   if((const DataArrayInt*)_num_coords)
2031     ret->_num_coords=_num_coords->deepCpy();
2032   if((const DataArrayInt*)_rev_num_coords)
2033     ret->_rev_num_coords=_rev_num_coords->deepCpy();
2034   if((const DataArrayAsciiChar*)_name_coords)
2035     ret->_name_coords=_name_coords->deepCpy();
2036   std::size_t i=0;
2037   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,i++)
2038     {
2039       if((const MEDFileUMeshSplitL1 *)(*it))
2040         ret->_ms[i]=(*it)->deepCpy(ret->_coords);
2041     }
2042   return ret.retn();
2043 }
2044
2045 /*!
2046  * Checks if \a this and another mesh are equal.
2047  *  \param [in] other - the mesh to compare with.
2048  *  \param [in] eps - a precision used to compare real values.
2049  *  \param [in,out] what - the string returning description of unequal data.
2050  *  \return bool - \c true if the meshes are equal, \c false, else.
2051  */
2052 bool MEDFileUMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
2053 {
2054   if(!MEDFileMesh::isEqual(other,eps,what))
2055     return false;
2056   const MEDFileUMesh *otherC=dynamic_cast<const MEDFileUMesh *>(other);
2057   if(!otherC)
2058     {
2059       what="Mesh types differ ! This is unstructured and other is NOT !";
2060       return false;
2061     }
2062   clearNonDiscrAttributes();
2063   otherC->clearNonDiscrAttributes();
2064   const DataArrayDouble *coo1=_coords;
2065   const DataArrayDouble *coo2=otherC->_coords;
2066   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
2067     {
2068       what="Mismatch of coordinates ! One is defined and not other !";
2069       return false;
2070     }
2071   if(coo1)
2072     {
2073       bool ret=coo1->isEqual(*coo2,eps);
2074       if(!ret)
2075         {
2076           what="Coords differ !";
2077           return false;
2078         }
2079     }
2080   const DataArrayInt *famc1=_fam_coords;
2081   const DataArrayInt *famc2=otherC->_fam_coords;
2082   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
2083     {
2084       what="Mismatch of families arr on nodes ! One is defined and not other !";
2085       return false;
2086     }
2087   if(famc1)
2088     {
2089       bool ret=famc1->isEqual(*famc2);
2090       if(!ret)
2091         {
2092           what="Families arr on node differ !";
2093           return false;
2094         }
2095     }
2096   const DataArrayInt *numc1=_num_coords;
2097   const DataArrayInt *numc2=otherC->_num_coords;
2098   if((numc1==0 && numc2!=0) || (numc1!=0 && numc2==0))
2099     {
2100       what="Mismatch of numbering arr on nodes ! One is defined and not other !";
2101       return false;
2102     }
2103   if(numc1)
2104     {
2105       bool ret=numc1->isEqual(*numc2);
2106       if(!ret)
2107         {
2108           what="Numbering arr on node differ !";
2109           return false;
2110         }
2111     }
2112   const DataArrayAsciiChar *namec1=_name_coords;
2113   const DataArrayAsciiChar *namec2=otherC->_name_coords;
2114   if((namec1==0 && namec2!=0) || (namec1!=0 && namec2==0))
2115     {
2116       what="Mismatch of naming arr on nodes ! One is defined and not other !";
2117       return false;
2118     }
2119   if(namec1)
2120     {
2121       bool ret=namec1->isEqual(*namec2);
2122       if(!ret)
2123         {
2124           what="Names arr on node differ !";
2125           return false;
2126         }
2127     }
2128   if(_ms.size()!=otherC->_ms.size())
2129     {
2130       what="Number of levels differs !";
2131       return false;
2132     }
2133   std::size_t sz=_ms.size();
2134   for(std::size_t i=0;i<sz;i++)
2135     {
2136       const MEDFileUMeshSplitL1 *s1=_ms[i];
2137       const MEDFileUMeshSplitL1 *s2=otherC->_ms[i];
2138       if((s1==0 && s2!=0) || (s1!=0 && s2==0))
2139         {
2140           what="Mismatch of presence of sub levels !";
2141           return false;
2142         }
2143       if(s1)
2144         {
2145           bool ret=s1->isEqual(s2,eps,what);
2146           if(!ret)
2147             return false;
2148         }
2149     }
2150   return true;
2151 }
2152
2153 /*!
2154  * Clears redundant attributes of incorporated data arrays.
2155  */
2156 void MEDFileUMesh::clearNonDiscrAttributes() const
2157 {
2158   MEDFileMesh::clearNonDiscrAttributes();
2159   const DataArrayDouble *coo1=_coords;
2160   if(coo1)
2161     (const_cast<DataArrayDouble *>(coo1))->setName("");//This parameter is not discriminant for comparison
2162   const DataArrayInt *famc1=_fam_coords;
2163   if(famc1)
2164     (const_cast<DataArrayInt *>(famc1))->setName("");//This parameter is not discriminant for comparison
2165   const DataArrayInt *numc1=_num_coords;
2166   if(numc1)
2167     (const_cast<DataArrayInt *>(numc1))->setName("");//This parameter is not discriminant for comparison
2168   const DataArrayAsciiChar *namc1=_name_coords;
2169   if(namc1)
2170     (const_cast<DataArrayAsciiChar *>(namc1))->setName("");//This parameter is not discriminant for comparison
2171   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2172     {
2173       const MEDFileUMeshSplitL1 *tmp=(*it);
2174       if(tmp)
2175         tmp->clearNonDiscrAttributes();
2176     }
2177 }
2178
2179 void MEDFileUMesh::setName(const std::string& name)
2180 {
2181   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
2182     if((MEDFileUMeshSplitL1 *)(*it)!=0)
2183       (*it)->setName(name);
2184   MEDFileMesh::setName(name);
2185 }
2186
2187 MEDFileUMesh::MEDFileUMesh()
2188 {
2189 }
2190
2191 MEDFileUMesh::MEDFileUMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
2192 try
2193 {
2194     loadUMeshFromFile(fid,mName,dt,it,mrs);
2195 }
2196 catch(INTERP_KERNEL::Exception& e)
2197 {
2198     throw e;
2199 }
2200
2201 void MEDFileUMesh::loadUMeshFromFile(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
2202 {
2203   MEDFileUMeshL2 loaderl2;
2204   ParaMEDMEM::MEDCouplingMeshType meshType;
2205   int dummy0,dummy1;
2206   std::string dummy2;
2207   int mid=MEDFileUMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dummy2);
2208   if(meshType!=UNSTRUCTURED)
2209     {
2210       std::ostringstream oss; oss << "Trying to load as unstructured an existing mesh with name '" << mName << "' !";
2211       throw INTERP_KERNEL::Exception(oss.str().c_str());
2212     }
2213   loaderl2.loadAll(fid,mid,mName,dt,it,mrs);
2214   int lev=loaderl2.getNumberOfLevels();
2215   _ms.resize(lev);
2216   for(int i=0;i<lev;i++)
2217     {
2218       if(!loaderl2.emptyLev(i))
2219         _ms[i]=new MEDFileUMeshSplitL1(loaderl2,mName,i);
2220       else
2221         _ms[i]=0;
2222     }
2223   MEDFileMeshL2::ReadFamiliesAndGrps(fid,mName,_families,_groups,mrs);
2224   //
2225   setName(loaderl2.getName());
2226   setDescription(loaderl2.getDescription());
2227   setUnivName(loaderl2.getUnivName());
2228   setIteration(loaderl2.getIteration());
2229   setOrder(loaderl2.getOrder());
2230   setTimeValue(loaderl2.getTime());
2231   setTimeUnit(loaderl2.getTimeUnit());
2232   _coords=loaderl2.getCoords();
2233   if(!mrs || mrs->isNodeFamilyFieldReading())
2234     _fam_coords=loaderl2.getCoordsFamily();
2235   if(!mrs || mrs->isNodeNumFieldReading())
2236     _num_coords=loaderl2.getCoordsNum();
2237   if(!mrs || mrs->isNodeNameFieldReading())
2238     _name_coords=loaderl2.getCoordsName();
2239   computeRevNum();
2240 }
2241
2242 MEDFileUMesh::~MEDFileUMesh()
2243 {
2244 }
2245
2246 void MEDFileUMesh::writeLL(med_idt fid) const
2247 {
2248   const DataArrayDouble *coo=_coords;
2249   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
2250   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
2251   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
2252   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
2253   int spaceDim=coo?coo->getNumberOfComponents():0;
2254   int mdim=getMeshDimension();
2255   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
2256   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
2257   for(int i=0;i<spaceDim;i++)
2258     {
2259       std::string info=coo->getInfoOnComponent(i);
2260       std::string c,u;
2261       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
2262       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
2263       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
2264     }
2265   MEDmeshCr(fid,maa,spaceDim,mdim,MED_UNSTRUCTURED_MESH,desc,"",MED_SORT_DTIT,MED_CARTESIAN,comp,unit);
2266   MEDmeshUniversalNameWr(fid,maa);
2267   std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE));
2268   MEDFileUMeshL2::WriteCoords(fid,meshName,_iteration,_order,_time,_coords,_fam_coords,_num_coords,_name_coords);
2269   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2270     if((const MEDFileUMeshSplitL1 *)(*it)!=0)
2271       (*it)->write(fid,meshName,mdim);
2272   MEDFileUMeshL2::WriteFamiliesAndGrps(fid,meshName,_families,_groups,_too_long_str);
2273 }
2274
2275 /*!
2276  * Returns relative dimensions of mesh entities (excluding nodes) present in \a this mesh.
2277  *  \return std::vector<int> - a sequence of the relative dimensions.
2278  */
2279 std::vector<int> MEDFileUMesh::getNonEmptyLevels() const
2280 {
2281   std::vector<int> ret;
2282   int lev=0;
2283   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
2284     if((const MEDFileUMeshSplitL1 *)(*it)!=0)
2285       if(!(*it)->empty())
2286         ret.push_back(lev);
2287   return ret;
2288 }
2289
2290 /*!
2291  * Returns relative dimensions of mesh entities (including nodes) present in \a this mesh.
2292  *  \return std::vector<int> - a sequence of the relative dimensions.
2293  */
2294 std::vector<int> MEDFileUMesh::getNonEmptyLevelsExt() const
2295 {
2296   std::vector<int> ret0=getNonEmptyLevels();
2297   if((const DataArrayDouble *) _coords)
2298     {
2299       std::vector<int> ret(ret0.size()+1);
2300       ret[0]=1;
2301       std::copy(ret0.begin(),ret0.end(),ret.begin()+1);
2302       return ret;
2303     }
2304   return ret0;
2305 }
2306
2307 std::vector<int> MEDFileUMesh::getFamArrNonEmptyLevelsExt() const
2308 {
2309   std::vector<int> ret;
2310   const DataArrayInt *famCoo(_fam_coords);
2311   if(famCoo)
2312     ret.push_back(1);
2313   int lev=0;
2314   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
2315     {
2316       const MEDFileUMeshSplitL1 *cur(*it);
2317       if(cur)
2318         if(cur->getFamilyField())
2319           ret.push_back(lev);
2320     }
2321   return ret;
2322 }
2323
2324 std::vector<int> MEDFileUMesh::getNumArrNonEmptyLevelsExt() const
2325 {
2326   std::vector<int> ret;
2327   const DataArrayInt *numCoo(_num_coords);
2328   if(numCoo)
2329     ret.push_back(1);
2330   int lev=0;
2331   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
2332     {
2333       const MEDFileUMeshSplitL1 *cur(*it);
2334       if(cur)
2335         if(cur->getNumberField())
2336           ret.push_back(lev);
2337     }
2338   return ret;
2339 }
2340
2341 std::vector<int> MEDFileUMesh::getNameArrNonEmptyLevelsExt() const
2342 {
2343   std::vector<int> ret;
2344   const DataArrayAsciiChar *nameCoo(_name_coords);
2345   if(nameCoo)
2346     ret.push_back(1);
2347   int lev=0;
2348   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
2349     {
2350       const MEDFileUMeshSplitL1 *cur(*it);
2351       if(cur)
2352         if(cur->getNameField())
2353           ret.push_back(lev);
2354     }
2355   return ret;
2356 }
2357
2358 /*!
2359  * Returns all relative mesh levels (**excluding nodes**) where a given group is defined.
2360  * To include nodes, call getGrpNonEmptyLevelsExt() method.
2361  *  \param [in] grp - the name of the group of interest.
2362  *  \return std::vector<int> - a sequence of the relative dimensions.
2363  */
2364 std::vector<int> MEDFileUMesh::getGrpNonEmptyLevels(const std::string& grp) const
2365 {
2366   std::vector<std::string> fams=getFamiliesOnGroup(grp);
2367   return getFamsNonEmptyLevels(fams);
2368 }
2369
2370 /*!
2371  * Returns all relative mesh levels (including nodes) where a given group is defined.
2372  *  \param [in] grp - the name of the group of interest.
2373  *  \return std::vector<int> - a sequence of the relative dimensions.
2374  */
2375 std::vector<int> MEDFileUMesh::getGrpNonEmptyLevelsExt(const std::string& grp) const
2376 {
2377   std::vector<std::string> fams=getFamiliesOnGroup(grp);
2378   return getFamsNonEmptyLevelsExt(fams);
2379 }
2380
2381 /*!
2382  * Returns all relative mesh levels (**excluding nodes**) where a given family is defined.
2383  * To include nodes, call getFamNonEmptyLevelsExt() method.
2384  *  \param [in] fam - the name of the family of interest.
2385  *  \return std::vector<int> - a sequence of the relative dimensions.
2386  */
2387 std::vector<int> MEDFileUMesh::getFamNonEmptyLevels(const std::string& fam) const
2388 {
2389   std::vector<std::string> fams(1,std::string(fam));
2390   return getFamsNonEmptyLevels(fams);
2391 }
2392
2393 /*!
2394  * Returns all relative mesh levels (including nodes) where a given family is defined.
2395  *  \param [in] fam - the name of the family of interest.
2396  *  \return std::vector<int> - a sequence of the relative dimensions.
2397  */
2398 std::vector<int> MEDFileUMesh::getFamNonEmptyLevelsExt(const std::string& fam) const
2399 {
2400   std::vector<std::string> fams(1,std::string(fam));
2401   return getFamsNonEmptyLevelsExt(fams);
2402 }
2403
2404 /*!
2405  * Returns all relative mesh levels (**excluding nodes**) where given groups are defined.
2406  * To include nodes, call getGrpsNonEmptyLevelsExt() method.
2407  *  \param [in] grps - a sequence of names of the groups of interest.
2408  *  \return std::vector<int> - a sequence of the relative dimensions.
2409  */
2410 std::vector<int> MEDFileUMesh::getGrpsNonEmptyLevels(const std::vector<std::string>& grps) const
2411 {
2412   std::vector<std::string> fams=getFamiliesOnGroups(grps);
2413   return getFamsNonEmptyLevels(fams);
2414 }
2415
2416 /*!
2417  * Returns all relative mesh levels (including nodes) where given groups are defined.
2418  *  \param [in] grps - a sequence of names of the groups of interest.
2419  *  \return std::vector<int> - a sequence of the relative dimensions.
2420  */
2421 std::vector<int> MEDFileUMesh::getGrpsNonEmptyLevelsExt(const std::vector<std::string>& grps) const
2422 {
2423   std::vector<std::string> fams=getFamiliesOnGroups(grps);
2424   return getFamsNonEmptyLevelsExt(fams);
2425 }
2426
2427 /*!
2428  * Returns all relative mesh levels (**excluding nodes**) where given families are defined.
2429  * To include nodes, call getFamsNonEmptyLevelsExt() method.
2430  *  \param [in] fams - the name of the family of interest.
2431  *  \return std::vector<int> - a sequence of the relative dimensions.
2432  */
2433 std::vector<int> MEDFileUMesh::getFamsNonEmptyLevels(const std::vector<std::string>& fams) const
2434 {
2435   std::vector<int> ret;
2436   std::vector<int> levs=getNonEmptyLevels();
2437   std::vector<int> famIds=getFamiliesIds(fams);
2438   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
2439     if(_ms[-(*it)]->presenceOfOneFams(famIds))
2440       ret.push_back(*it);
2441   return ret;
2442 }
2443
2444 /*!
2445  * Returns all relative mesh levels (including nodes) where given families are defined.
2446  *  \param [in] fams - the names of the families of interest.
2447  *  \return std::vector<int> - a sequence of the relative dimensions.
2448  */
2449 std::vector<int> MEDFileUMesh::getFamsNonEmptyLevelsExt(const std::vector<std::string>& fams) const
2450 {
2451   std::vector<int> ret0=getFamsNonEmptyLevels(fams);
2452   const DataArrayInt *famCoords=_fam_coords;
2453   if(!famCoords)
2454     return ret0;
2455   std::vector<int> famIds=getFamiliesIds(fams);
2456   if(famCoords->presenceOfValue(famIds))
2457     {
2458       std::vector<int> ret(ret0.size()+1);
2459       ret[0]=1;
2460       std::copy(ret0.begin(),ret0.end(),ret.begin()+1);
2461       return ret;
2462     }
2463   else
2464     return ret0;
2465 }
2466
2467 /*!
2468  * Returns names of groups that partly or fully appear on the level \a meshDimRelToMaxExt.
2469  *  \param [in] meshDimRelToMaxExt - a relative dimension of interest.
2470  *  \return std::vector<std::string> - a sequence of group names at \a meshDimRelToMaxExt
2471  *          level. 
2472  */
2473 std::vector<std::string> MEDFileUMesh::getGroupsOnSpecifiedLev(int meshDimRelToMaxExt) const
2474 {
2475   std::vector<std::string> ret;
2476   std::vector<std::string> allGrps=getGroupsNames();
2477   for(std::vector<std::string>::const_iterator it=allGrps.begin();it!=allGrps.end();it++)
2478     {
2479       std::vector<int> levs=getGrpNonEmptyLevelsExt((*it));
2480       if(std::find(levs.begin(),levs.end(),meshDimRelToMaxExt)!=levs.end())
2481         ret.push_back(*it);
2482     }
2483   return ret;
2484 }
2485
2486 int MEDFileUMesh::getMaxAbsFamilyIdInArrays() const
2487 {
2488   int ret=-std::numeric_limits<int>::max(),tmp=-1;
2489   if((const DataArrayInt *)_fam_coords)
2490     {
2491       int val=_fam_coords->getMaxValue(tmp);
2492       ret=std::max(ret,std::abs(val));
2493     }
2494   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2495     {
2496       if((const MEDFileUMeshSplitL1 *)(*it))
2497         {
2498           const DataArrayInt *da=(*it)->getFamilyField();
2499           if(da)
2500             {
2501               int val=da->getMaxValue(tmp);
2502               ret=std::max(ret,std::abs(val));
2503             }
2504         }
2505     }
2506   return ret;
2507 }
2508
2509 int MEDFileUMesh::getMaxFamilyIdInArrays() const
2510 {
2511   int ret=-std::numeric_limits<int>::max(),tmp=-1;
2512   if((const DataArrayInt *)_fam_coords)
2513     {
2514       int val=_fam_coords->getMaxValue(tmp);
2515       ret=std::max(ret,val);
2516     }
2517   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2518     {
2519       if((const MEDFileUMeshSplitL1 *)(*it))
2520         {
2521           const DataArrayInt *da=(*it)->getFamilyField();
2522           if(da)
2523             {
2524               int val=da->getMaxValue(tmp);
2525               ret=std::max(ret,val);
2526             }
2527         }
2528     }
2529   return ret;
2530 }
2531
2532 int MEDFileUMesh::getMinFamilyIdInArrays() const
2533 {
2534   int ret=std::numeric_limits<int>::max(),tmp=-1;
2535   if((const DataArrayInt *)_fam_coords)
2536     {
2537       int val=_fam_coords->getMinValue(tmp);
2538       ret=std::min(ret,val);
2539     }
2540   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2541     {
2542       if((const MEDFileUMeshSplitL1 *)(*it))
2543         {
2544           const DataArrayInt *da=(*it)->getFamilyField();
2545           if(da)
2546             {
2547               int val=da->getMinValue(tmp);
2548               ret=std::min(ret,val);
2549             }
2550         }
2551     }
2552   return ret;
2553 }
2554
2555 /*!
2556  * Returns the dimension on cells in \a this mesh.
2557  *  \return int - the mesh dimension.
2558  *  \throw If there are no cells in this mesh.
2559  */
2560 int MEDFileUMesh::getMeshDimension() const
2561 {
2562   int lev=0;
2563   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev++)
2564     if((const MEDFileUMeshSplitL1 *)(*it)!=0)
2565       return (*it)->getMeshDimension()+lev;
2566   throw INTERP_KERNEL::Exception("MEDFileUMesh::getMeshDimension : impossible to find a mesh dimension !");
2567 }
2568
2569 /*!
2570  * Returns the space dimension of \a this mesh that is equal to number of components in
2571  * the node coordinates array.
2572  *  \return int - the space dimension of \a this mesh.
2573  *  \throw If the node coordinates array is not available.
2574  */
2575 int MEDFileUMesh::getSpaceDimension() const
2576 {
2577   const DataArrayDouble *coo=_coords;
2578   if(!coo)
2579     throw INTERP_KERNEL::Exception(" MEDFileUMesh::getSpaceDimension : no coords set !");
2580   return coo->getNumberOfComponents();
2581 }
2582
2583 /*!
2584  * Returns a string describing \a this mesh.
2585  *  \return std::string - the mesh information string.
2586  */
2587 std::string MEDFileUMesh::simpleRepr() const
2588 {
2589   std::ostringstream oss;
2590   oss << MEDFileMesh::simpleRepr();
2591   const DataArrayDouble *coo=_coords;
2592   oss << "- The dimension of the space is ";
2593   static const char MSG1[]= "*** NO COORDS SET ***";
2594   static const char MSG2[]= "*** NO CONNECTIVITY SET FOR THIS LEVEL***";
2595   if(coo)
2596     oss << _coords->getNumberOfComponents() << std::endl;
2597   else
2598     oss << MSG1 << std::endl;
2599   oss << "- Type of the mesh : UNSTRUCTURED\n";
2600   oss << "- Number of nodes : ";
2601   if(coo)
2602     oss << _coords->getNumberOfTuples() << std::endl;
2603   else
2604     oss << MSG1 << std::endl;
2605   std::size_t nbOfLev=_ms.size();
2606   oss << "- Number of levels allocated : " << nbOfLev << std::endl;
2607   for(std::size_t i=0;i<nbOfLev;i++)
2608     {
2609       const MEDFileUMeshSplitL1 *lev=_ms[i];
2610       oss << "  - Level #" << -((int) i) << " has dimension : ";
2611       if(lev)
2612         {
2613           oss << lev->getMeshDimension() << std::endl;
2614           lev->simpleRepr(oss);
2615         }
2616       else
2617         oss << MSG2 << std::endl;
2618     }
2619   oss << "- Number of families : " << _families.size() << std::endl << std::endl;
2620   if(coo)
2621     {
2622       oss << "(***********************)\n(* NODES OF THE MESH : *)\n(***********************)\n";
2623       oss << "- Names of coordinates :" << std::endl;
2624       std::vector<std::string> vars=coo->getVarsOnComponent();
2625       std::copy(vars.begin(),vars.end(),std::ostream_iterator<std::string>(oss," "));
2626       oss << std::endl << "- Units of coordinates : " << std::endl;
2627       std::vector<std::string> units=coo->getUnitsOnComponent();
2628       std::copy(units.begin(),units.end(),std::ostream_iterator<std::string>(oss," "));
2629     }
2630   oss << std::endl << std::endl;
2631   getFamilyRepr(oss);
2632   return oss.str();
2633 }
2634
2635 /*!
2636  * Returns a full textual description of \a this mesh.
2637  *  \return std::string - the string holding the mesh description.
2638  */
2639 std::string MEDFileUMesh::advancedRepr() const
2640 {
2641   return simpleRepr();
2642 }
2643
2644 /*!
2645  * Returns number of mesh entities of a given relative dimension in \a this mesh.
2646  *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
2647  *  \return int - the number of entities.
2648  *  \throw If no mesh entities of dimension \a meshDimRelToMaxExt are available in \a this mesh.
2649  */
2650 int MEDFileUMesh::getSizeAtLevel(int meshDimRelToMaxExt) const
2651 {
2652   if(meshDimRelToMaxExt==1)
2653     {
2654       if(!((const DataArrayDouble *)_coords))
2655         throw INTERP_KERNEL::Exception("MEDFileUMesh::getSizeAtLevel : no coordinates specified !");
2656       return _coords->getNumberOfTuples();
2657     }
2658   return getMeshAtLevSafe(meshDimRelToMaxExt)->getSize();
2659 }
2660
2661 /*!
2662  * Returns the family field for mesh entities of a given dimension.
2663  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
2664  *  \return const DataArrayInt * - the family field. It is an array of ids of families
2665  *          each mesh entity belongs to. It can be \c NULL.
2666  */
2667 const DataArrayInt *MEDFileUMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) const
2668 {
2669   if(meshDimRelToMaxExt==1)
2670     return _fam_coords;
2671   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2672   return l1->getFamilyField();
2673 }
2674
2675 /*!
2676  * Returns the optional numbers of mesh entities of a given dimension.
2677  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
2678  *  \return const DataArrayInt * - the array of the entity numbers.
2679  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2680  */
2681 const DataArrayInt *MEDFileUMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) const
2682 {
2683   if(meshDimRelToMaxExt==1)
2684     return _num_coords;
2685   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2686   return l1->getNumberField();
2687 }
2688
2689 const DataArrayAsciiChar *MEDFileUMesh::getNameFieldAtLevel(int meshDimRelToMaxExt) const
2690 {
2691   if(meshDimRelToMaxExt==1)
2692     return _name_coords;
2693   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2694   return l1->getNameField();
2695 }
2696
2697 int MEDFileUMesh::getNumberOfNodes() const
2698 {
2699   const DataArrayDouble *coo=_coords;
2700   if(!coo)
2701     throw INTERP_KERNEL::Exception(" MEDFileUMesh::getNumberOfNodes : no coords set !");
2702   return coo->getNumberOfTuples();
2703 }
2704
2705 bool MEDFileUMesh::hasImplicitPart() const
2706 {
2707   return false;
2708 }
2709
2710 int MEDFileUMesh::buildImplicitPartIfAny(INTERP_KERNEL::NormalizedCellType gt) const
2711 {
2712   throw INTERP_KERNEL::Exception("MEDFileUMesh::buildImplicitPartIfAny : unstructured meshes do not have implicit part !");
2713 }
2714
2715 void MEDFileUMesh::releaseImplicitPartIfAny() const
2716 {
2717 }
2718
2719 void MEDFileUMesh::whichAreNodesFetched(const MEDFileField1TSStructItem& st, const MEDFileFieldGlobsReal *globs, std::vector<bool>& nodesFetched) const
2720 {
2721   std::size_t sz(st.getNumberOfItems());
2722   for(std::size_t i=0;i<sz;i++)
2723     {
2724       INTERP_KERNEL::NormalizedCellType curGt(st[i].getGeo());
2725       const MEDCoupling1GTUMesh *m(getDirectUndergroundSingleGeoTypeMesh(curGt));
2726       if(st[i].getPflName().empty())
2727         m->computeNodeIdsAlg(nodesFetched);
2728       else
2729         {
2730           const DataArrayInt *arr(globs->getProfile(st[i].getPflName()));
2731           MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> m2(dynamic_cast<MEDCoupling1GTUMesh *>(m->buildPartOfMySelf(arr->begin(),arr->end(),true)));
2732           m2->computeNodeIdsAlg(nodesFetched);
2733         }
2734     }
2735 }
2736
2737 /*!
2738  * Returns the optional numbers of mesh entities of a given dimension transformed using
2739  * DataArrayInt::invertArrayN2O2O2N().
2740  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
2741  *  \return const DataArrayInt * - the array of the entity numbers transformed using
2742  *          DataArrayInt::invertArrayN2O2O2N().
2743  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2744  */
2745 const DataArrayInt *MEDFileUMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxExt) const
2746 {
2747   if(meshDimRelToMaxExt==1)
2748     {
2749       if(!((const DataArrayInt *)_num_coords))
2750         throw INTERP_KERNEL::Exception("MEDFileUMesh::getRevNumberFieldAtLevel : no coordinates renum specified !");
2751       return _rev_num_coords;
2752     }
2753   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2754   return l1->getRevNumberField();
2755 }
2756
2757 /*!
2758  * Returns a pointer to the node coordinates array of \a this mesh \b without
2759  * incrementing its reference counter, thus there is no need to decrRef() it by the caller.
2760  */
2761 DataArrayDouble *MEDFileUMesh::getCoords() const
2762 {
2763   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp(_coords);
2764   if((DataArrayDouble *)tmp)
2765     {
2766       return tmp;
2767     }
2768   return 0;
2769 }
2770
2771 /*!
2772  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in a given
2773  * group of \a this mesh. Only mesh entities of a given dimension are included in the
2774  * new mesh.
2775  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
2776  *  \param [in] grp - the name of the group whose mesh entities are included in the
2777  *          new mesh.
2778  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
2779  *          according to the optional numbers of entities, if available.
2780  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
2781  *          delete this mesh using decrRef() as it is no more needed.
2782  *  \throw If the name of a nonexistent group is specified.
2783  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2784  */
2785 MEDCouplingUMesh *MEDFileUMesh::getGroup(int meshDimRelToMaxExt, const std::string& grp, bool renum) const
2786 {
2787   synchronizeTinyInfoOnLeaves();
2788   std::vector<std::string> tmp(1);
2789   tmp[0]=grp;
2790   return getGroups(meshDimRelToMaxExt,tmp,renum);
2791 }
2792
2793 /*!
2794  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in given
2795  * groups of \a this mesh. Only mesh entities of a given dimension are included in the
2796  * new mesh.
2797  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
2798  *  \param [in] grps - a sequence of group names whose mesh entities are included in the
2799  *          new mesh.
2800  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
2801  *          according to the optional numbers of entities, if available.
2802  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
2803  *          delete this mesh using decrRef() as it is no more needed.
2804  *  \throw If a name of a nonexistent group is present in \a grps.
2805  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2806  */
2807 MEDCouplingUMesh *MEDFileUMesh::getGroups(int meshDimRelToMaxExt, const std::vector<std::string>& grps, bool renum) const
2808 {
2809   synchronizeTinyInfoOnLeaves();
2810   std::vector<std::string> fams2=getFamiliesOnGroups(grps);
2811   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> zeRet=getFamilies(meshDimRelToMaxExt,fams2,renum);
2812   if(grps.size()==1 && ((MEDCouplingUMesh *)zeRet))
2813     zeRet->setName(grps[0]);
2814   return zeRet.retn();
2815 }
2816
2817 /*!
2818  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in a given
2819  * family of \a this mesh. Only mesh entities of a given dimension are included in the
2820  * new mesh.
2821  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
2822  *  \param [in] fam - the name of the family whose mesh entities are included in the
2823  *          new mesh.
2824  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
2825  *          according to the optional numbers of entities, if available.
2826  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
2827  *          delete this mesh using decrRef() as it is no more needed.
2828  *  \throw If a name of a nonexistent family is present in \a grps.
2829  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2830  */
2831 MEDCouplingUMesh *MEDFileUMesh::getFamily(int meshDimRelToMaxExt, const std::string& fam, bool renum) const
2832 {
2833   synchronizeTinyInfoOnLeaves();
2834   std::vector<std::string> tmp(1);
2835   tmp[0]=fam;
2836   return getFamilies(meshDimRelToMaxExt,tmp,renum);
2837 }
2838
2839 /*!
2840  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in given
2841  * families of \a this mesh. Only mesh entities of a given dimension are included in the
2842  * new mesh.
2843  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
2844  *  \param [in] fams - a sequence of family names whose mesh entities are included in the
2845  *          new mesh.
2846  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
2847  *          according to the optional numbers of entities, if available.
2848  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
2849  *          delete this mesh using decrRef() as it is no more needed.
2850  *  \throw If a name of a nonexistent family is present in \a fams.
2851  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2852  */
2853 MEDCouplingUMesh *MEDFileUMesh::getFamilies(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const
2854 {
2855   synchronizeTinyInfoOnLeaves();
2856   if(meshDimRelToMaxExt==1)
2857     {
2858       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr=getFamiliesArr(1,fams,renum);
2859       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
2860       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> c=_coords->selectByTupleId(arr->getConstPointer(),arr->getConstPointer()+arr->getNbOfElems());
2861       ret->setCoords(c);
2862       return ret.retn();
2863     }
2864   std::vector<int> famIds=getFamiliesIds(fams);
2865   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2866   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> zeRet;
2867   if(!famIds.empty())
2868     zeRet=l1->getFamilyPart(&famIds[0],&famIds[0]+famIds.size(),renum);
2869   else
2870     zeRet=l1->getFamilyPart(0,0,renum);
2871   if(fams.size()==1 && ((MEDCouplingUMesh *)zeRet))
2872     zeRet->setName(fams[0]);
2873   return zeRet.retn();
2874 }
2875
2876 /*!
2877  * Returns ids of mesh entities contained in given families of a given dimension.
2878  *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
2879  *          are required.
2880  *  \param [in] fams - the names of the families of interest.
2881  *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
2882  *          returned instead of ids.
2883  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
2884  *          numbers, if available and required, of mesh entities of the families. The caller
2885  *          is to delete this array using decrRef() as it is no more needed. 
2886  *  \throw If the family field is missing for \a meshDimRelToMaxExt.
2887  */
2888 DataArrayInt *MEDFileUMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const
2889 {
2890   std::vector<int> famIds=getFamiliesIds(fams);
2891   if(meshDimRelToMaxExt==1)
2892     {
2893       if((const DataArrayInt *)_fam_coords)
2894         {
2895           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
2896           if(!famIds.empty())
2897             da=_fam_coords->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
2898           else
2899             da=_fam_coords->getIdsEqualList(0,0);
2900           if(renum)
2901             return MEDFileUMeshSplitL1::Renumber(_num_coords,da);
2902           else
2903             return da.retn();
2904         }
2905       else
2906         throw INTERP_KERNEL::Exception("MEDFileUMesh::getFamiliesArr : no family array specified on nodes !");
2907     }
2908   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2909   if(!famIds.empty())
2910     return l1->getFamilyPartArr(&famIds[0],&famIds[0]+famIds.size(),renum);
2911   else
2912     return l1->getFamilyPartArr(0,0,renum);
2913 }
2914
2915 /*!
2916  * Returns a MEDCouplingUMesh of a given relative dimension.
2917  * \warning If \a meshDimRelToMaxExt == 1 (which means nodes), the returned mesh **is not
2918  * valid**. This is a feature, because MEDLoader does not create cells that do not exist! 
2919  * To build a valid MEDCouplingUMesh from the returned one in this case,
2920  * call MEDCouplingUMesh::Build0DMeshFromCoords().
2921  *  \param [in] meshDimRelToMax - the relative dimension of interest.
2922  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
2923  *          optional numbers of mesh entities.
2924  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
2925  *          delete using decrRef() as it is no more needed. 
2926  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2927  * \sa getGenMeshAtLevel()
2928  */
2929 MEDCouplingUMesh *MEDFileUMesh::getMeshAtLevel(int meshDimRelToMaxExt, bool renum) const
2930 {
2931   synchronizeTinyInfoOnLeaves();
2932   if(meshDimRelToMaxExt==1)
2933     {
2934       if(!renum)
2935         {
2936           MEDCouplingUMesh *umesh=MEDCouplingUMesh::New();
2937           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> cc=_coords->deepCpy();
2938           umesh->setCoords(cc);
2939           MEDFileUMeshSplitL1::ClearNonDiscrAttributes(umesh);
2940           umesh->setName(getName());
2941           return umesh;
2942         }
2943     }
2944   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2945   return l1->getWholeMesh(renum);
2946 }
2947
2948 /*!
2949  * Returns a MEDCouplingUMesh of a given relative dimension.
2950  * \warning If \a meshDimRelToMaxExt == 1 (which means nodes), the returned mesh **is not
2951  * valid**. This is a feature, because MEDLoader does not create cells that do not exist! 
2952  * To build a valid MEDCouplingUMesh from the returned one in this case,
2953  * call MEDCouplingUMesh::Build0DMeshFromCoords().
2954  *  \param [in] meshDimRelToMax - the relative dimension of interest.
2955  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
2956  *          optional numbers of mesh entities.
2957  *  \return MEDCouplingMesh * - a pointer to MEDCouplingUMesh that the caller is to
2958  *          delete using decrRef() as it is no more needed. 
2959  *  \throw If there are no mesh entities of \a meshDimRelToMax dimension in \a this mesh.
2960  * \sa getMeshAtLevel()
2961  */
2962 MEDCouplingMesh *MEDFileUMesh::getGenMeshAtLevel(int meshDimRelToMax, bool renum) const
2963 {
2964   return getMeshAtLevel(meshDimRelToMax,renum);
2965 }
2966
2967 std::vector<int> MEDFileUMesh::getDistributionOfTypes(int meshDimRelToMax) const
2968 {
2969   const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMax));
2970   return l1->getDistributionOfTypes();
2971 }
2972
2973 /*!
2974  * Returns a MEDCouplingUMesh of a relative dimension == 0.
2975  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
2976  *          optional numbers of mesh entities.
2977  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
2978  *          delete using decrRef() as it is no more needed. 
2979  *  \throw If there are no mesh entities of the relative dimension == 0 in \a this mesh.
2980  */
2981 MEDCouplingUMesh *MEDFileUMesh::getLevel0Mesh(bool renum) const
2982 {
2983   return getMeshAtLevel(0,renum);
2984 }
2985
2986 /*!
2987  * Returns a MEDCouplingUMesh of a relative dimension == -1.
2988  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
2989  *          optional numbers of mesh entities.
2990  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
2991  *          delete using decrRef() as it is no more needed. 
2992  *  \throw If there are no mesh entities of the relative dimension == -1 in \a this mesh.
2993  */
2994 MEDCouplingUMesh *MEDFileUMesh::getLevelM1Mesh(bool renum) const
2995 {
2996   return getMeshAtLevel(-1,renum);
2997 }
2998
2999 /*!
3000  * Returns a MEDCouplingUMesh of a relative dimension == -2.
3001  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3002  *          optional numbers of mesh entities.
3003  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
3004  *          delete using decrRef() as it is no more needed. 
3005  *  \throw If there are no mesh entities of the relative dimension == -2 in \a this mesh.
3006  */
3007 MEDCouplingUMesh *MEDFileUMesh::getLevelM2Mesh(bool renum) const
3008 {
3009   return getMeshAtLevel(-2,renum);
3010 }
3011
3012 /*!
3013  * Returns a MEDCouplingUMesh of a relative dimension == -3.
3014  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
3015  *          optional numbers of mesh entities.
3016  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
3017  *          delete using decrRef() as it is no more needed. 
3018  *  \throw If there are no mesh entities of the relative dimension == -3 in \a this mesh.
3019  */
3020 MEDCouplingUMesh *MEDFileUMesh::getLevelM3Mesh(bool renum) const
3021 {
3022   return getMeshAtLevel(-3,renum);
3023 }
3024
3025 /*!
3026  * This method is for advanced users. There is two storing strategy of mesh in \a this.
3027  * Either MEDCouplingUMesh, or vector of MEDCoupling1GTUMesh instances.
3028  * When assignement is done the first one is done, which is not optimal in write mode for MED file.
3029  * This method allows to switch from MEDCouplingUMesh mode to MEDCoupling1GTUMesh mode.
3030  */
3031 void MEDFileUMesh::forceComputationOfParts() const
3032 {
3033   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
3034     {
3035       const MEDFileUMeshSplitL1 *elt(*it);
3036       if(elt)
3037         elt->forceComputationOfParts();
3038     }
3039 }
3040
3041 /*!
3042  * This method returns a vector of mesh parts containing each exactly one geometric type.
3043  * This method will never launch an automatic computation of split by type (an INTERP_KERNEL::Exception will be then thrown).
3044  * This method is only for memory aware users.
3045  * The returned pointers are **NOT** new object pointer. No need to mange them.
3046  */
3047 std::vector<MEDCoupling1GTUMesh *> MEDFileUMesh::getDirectUndergroundSingleGeoTypeMeshes(int meshDimRelToMax) const
3048 {
3049   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(meshDimRelToMax));
3050   return sp->getDirectUndergroundSingleGeoTypeMeshes();
3051 }
3052
3053 /*!
3054  * This method returns the part of \a this having the geometric type \a gt.
3055  * If such part is not existing an exception will be thrown.
3056  * The returned pointer is **NOT** new object pointer. No need to mange it.
3057  */
3058 MEDCoupling1GTUMesh *MEDFileUMesh::getDirectUndergroundSingleGeoTypeMesh(INTERP_KERNEL::NormalizedCellType gt) const
3059 {
3060   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
3061   int lev=(int)cm.getDimension()-getMeshDimension();
3062   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(lev));
3063   return sp->getDirectUndergroundSingleGeoTypeMesh(gt);
3064 }
3065
3066 /*!
3067  * Given a relative level \a meshDimRelToMax it returns the sorted vector of geometric types present in \a this.
3068  * \throw if the reqsuested \a meshDimRelToMax does not exist.
3069  */
3070 std::vector<INTERP_KERNEL::NormalizedCellType> MEDFileUMesh::getGeoTypesAtLevel(int meshDimRelToMax) const
3071 {
3072   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(meshDimRelToMax));
3073   return sp->getGeoTypes();
3074 }
3075
3076 /*!
3077  * This method extracts from whole family field ids the part relative to the input parameter \a gt.
3078  * \param [in] gt - the geometric type for which the family field is asked.
3079  * \return DataArrayInt * - a pointer to DataArrayInt that the caller is to
3080  *          delete using decrRef() as it is no more needed.
3081  * \sa MEDFileUMesh::extractNumberFieldOnGeoType
3082  */
3083 DataArrayInt *MEDFileUMesh::extractFamilyFieldOnGeoType(INTERP_KERNEL::NormalizedCellType gt) const
3084 {
3085   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
3086   int lev=(int)cm.getDimension()-getMeshDimension();
3087   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(lev));
3088   return sp->extractFamilyFieldOnGeoType(gt);
3089 }
3090
3091 /*!
3092  * This method extracts from whole number field ids the part relative to the input parameter \a gt.
3093  * \param [in] gt - the geometric type for which the number field is asked.
3094  * \return DataArrayInt * - a pointer to DataArrayInt that the caller is to
3095  *          delete using decrRef() as it is no more needed.
3096  * \sa MEDFileUMesh::extractFamilyFieldOnGeoType
3097  */
3098 DataArrayInt *MEDFileUMesh::extractNumberFieldOnGeoType(INTERP_KERNEL::NormalizedCellType gt) const
3099 {
3100   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
3101   int lev=(int)cm.getDimension()-getMeshDimension();
3102   const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(lev));
3103   return sp->extractNumberFieldOnGeoType(gt);
3104 }
3105
3106 const MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt) const
3107 {
3108   if(meshDimRelToMaxExt==1)
3109     throw INTERP_KERNEL::Exception("Dimension request is invalid : asking for node level (1) !");
3110   if(meshDimRelToMaxExt>1)
3111     throw INTERP_KERNEL::Exception("Dimension request is invalid (>1) !");
3112   int tracucedRk=-meshDimRelToMaxExt;
3113   if(tracucedRk>=(int)_ms.size())
3114     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
3115   if((const MEDFileUMeshSplitL1 *)_ms[tracucedRk]==0)
3116     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3117   return _ms[tracucedRk];
3118 }
3119
3120 MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt)
3121 {
3122   if(meshDimRelToMaxExt==1)
3123     throw INTERP_KERNEL::Exception("Dimension request is invalid : asking for node level (1) !");
3124   if(meshDimRelToMaxExt>1)
3125     throw INTERP_KERNEL::Exception("Dimension request is invalid (>1) !");
3126   int tracucedRk=-meshDimRelToMaxExt;
3127   if(tracucedRk>=(int)_ms.size())
3128     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
3129   if((const MEDFileUMeshSplitL1 *)_ms[tracucedRk]==0)
3130     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3131   return _ms[tracucedRk];
3132 }
3133
3134 void MEDFileUMesh::checkMeshDimCoherency(int meshDim, int meshDimRelToMax) const
3135 {
3136   if(-meshDimRelToMax>=(int)_ms.size())
3137     throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMeshDimCoherency : The meshdim of mesh is not managed by 'this' !");
3138   int i=0;
3139   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,i++)
3140     {
3141       if(((const MEDFileUMeshSplitL1*) (*it))!=0)
3142         {
3143           int ref=(*it)->getMeshDimension();
3144           if(ref+i!=meshDim-meshDimRelToMax)
3145             throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMeshDimCoherency : no coherency between levels !");
3146         }
3147     }
3148 }
3149
3150 /*!
3151  * Sets the node coordinates array of \a this mesh.
3152  *  \param [in] coords - the new node coordinates array.
3153  *  \throw If \a coords == \c NULL.
3154  */
3155 void MEDFileUMesh::setCoords(DataArrayDouble *coords)
3156 {
3157   if(!coords)
3158     throw INTERP_KERNEL::Exception("MEDFileUMesh::setCoords : null pointer in input !");
3159   coords->checkAllocated();
3160   int nbOfTuples=coords->getNumberOfTuples();
3161   _coords=coords;
3162   coords->incrRef();
3163   _fam_coords=DataArrayInt::New();
3164   _fam_coords->alloc(nbOfTuples,1);
3165   _fam_coords->fillWithZero();
3166   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
3167     if((MEDFileUMeshSplitL1 *)(*it))
3168       (*it)->setCoords(coords);
3169 }
3170
3171 /*!
3172  * Removes all groups of a given dimension in \a this mesh.
3173  *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
3174  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3175  */
3176 void MEDFileUMesh::eraseGroupsAtLevel(int meshDimRelToMaxExt)
3177 {
3178   if(meshDimRelToMaxExt==1)
3179     {
3180       if((DataArrayInt *)_fam_coords)
3181         _fam_coords->fillWithZero();
3182       return ;
3183     }
3184   MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
3185   l1->eraseFamilyField();
3186   optimizeFamilies();
3187 }
3188
3189 /*!
3190  * Removes all families with ids not present in the family fields of \a this mesh.
3191  */
3192 void MEDFileUMesh::optimizeFamilies()
3193 {
3194   std::vector<int> levs=getNonEmptyLevelsExt();
3195   std::set<int> allFamsIds;
3196   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
3197     {
3198       const DataArrayInt *ffield=getFamilyFieldAtLevel(*it);
3199       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=ffield->getDifferentValues();
3200       std::set<int> res;
3201       std::set_union(ids->begin(),ids->end(),allFamsIds.begin(),allFamsIds.end(),std::inserter(res,res.begin()));
3202       allFamsIds=res;
3203     }
3204   std::set<std::string> famNamesToKill;
3205   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
3206     {
3207       if(allFamsIds.find((*it).second)!=allFamsIds.end())
3208         famNamesToKill.insert((*it).first);
3209     }
3210   for(std::set<std::string>::const_iterator it=famNamesToKill.begin();it!=famNamesToKill.end();it++)
3211     _families.erase(*it);
3212   std::vector<std::string> grpNamesToKill;
3213   for(std::map<std::string, std::vector<std::string> >::iterator it=_groups.begin();it!=_groups.end();it++)
3214     {
3215       std::vector<std::string> tmp;
3216       for(std::vector<std::string>::const_iterator it2=(*it).second.begin();it2!=(*it).second.end();it2++)
3217         {
3218           if(famNamesToKill.find(*it2)==famNamesToKill.end())
3219             tmp.push_back(*it2);
3220         }
3221       if(!tmp.empty())
3222         (*it).second=tmp;
3223       else
3224         tmp.push_back((*it).first);
3225     }
3226   for(std::vector<std::string>::const_iterator it=grpNamesToKill.begin();it!=grpNamesToKill.end();it++)
3227     _groups.erase(*it);
3228 }
3229
3230 void MEDFileUMesh::duplicateNodesOnM1Group(const std::string& grpNameM1, DataArrayInt *&nodesDuplicated, DataArrayInt *&cellsModified, DataArrayInt *&cellsNotModified)
3231 {
3232   std::vector<int> levs=getNonEmptyLevels();
3233   if(std::find(levs.begin(),levs.end(),0)==levs.end() || std::find(levs.begin(),levs.end(),-1)==levs.end())
3234     throw INTERP_KERNEL::Exception("MEDFileUMesh::duplicateNodesOnM1Group : This method works only for mesh definied on level 0 and -1 !");
3235   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0=getMeshAtLevel(0);
3236   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1=getMeshAtLevel(-1);
3237   int nbNodes=m0->getNumberOfNodes();
3238   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m11=getGroup(-1,grpNameM1);
3239   DataArrayInt *tmp00=0,*tmp11=0,*tmp22=0;
3240   m0->findNodesToDuplicate(*m11,tmp00,tmp11,tmp22);
3241   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodeIdsToDuplicate(tmp00);
3242   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0(tmp11);
3243   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1(tmp22);
3244   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp0=static_cast<MEDCouplingUMesh *>(m0->buildPartOfMySelf(cellsToModifyConn0->begin(),cellsToModifyConn0->end(),true));
3245   // node renumbering of cells in m1 impacted by duplication of node but not in group 'grpNameM1' on level -1
3246   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descTmp0=DataArrayInt::New(),descITmp0=DataArrayInt::New(),revDescTmp0=DataArrayInt::New(),revDescITmp0=DataArrayInt::New();
3247   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp0Desc=tmp0->buildDescendingConnectivity(descTmp0,descITmp0,revDescTmp0,revDescITmp0);
3248   descTmp0=0; descITmp0=0; revDescTmp0=0; revDescITmp0=0;
3249   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsInM1ToRenumW2=tmp0Desc->getCellIdsLyingOnNodes(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),false);
3250   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cellsInM1ToRenumW3=static_cast<MEDCouplingUMesh *>(tmp0Desc->buildPartOfMySelf(cellsInM1ToRenumW2->begin(),cellsInM1ToRenumW2->end(),true));
3251   DataArrayInt *cellsInM1ToRenumW4Tmp=0;
3252   m1->areCellsIncludedIn(cellsInM1ToRenumW3,2,cellsInM1ToRenumW4Tmp);
3253   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsInM1ToRenumW4(cellsInM1ToRenumW4Tmp);
3254   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsInM1ToRenumW5=cellsInM1ToRenumW4->getIdsInRange(0,m1->getNumberOfCells());
3255   cellsInM1ToRenumW5->transformWithIndArr(cellsInM1ToRenumW4->begin(),cellsInM1ToRenumW4->end());
3256   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> grpIds=getGroupArr(-1,grpNameM1);
3257   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsInM1ToRenum=cellsInM1ToRenumW5->buildSubstraction(grpIds);
3258   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Part=static_cast<MEDCouplingUMesh *>(m1->buildPartOfMySelf(cellsInM1ToRenum->begin(),cellsInM1ToRenum->end(),true));
3259   m1Part->duplicateNodesInConn(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),nbNodes);
3260   m1->setPartOfMySelf(cellsInM1ToRenum->begin(),cellsInM1ToRenum->end(),*m1Part);
3261   // end of node renumbering of cells in m1 impacted by duplication of node but not in group of level -1 'grpNameM1'
3262   tmp0->duplicateNodes(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end());
3263   m0->setCoords(tmp0->getCoords());
3264   m0->setPartOfMySelf(cellsToModifyConn0->begin(),cellsToModifyConn0->end(),*tmp0);
3265   m1->setCoords(m0->getCoords());
3266   _coords=m0->getCoords(); _coords->incrRef();
3267   // duplication of cells in group 'grpNameM1' on level -1
3268   m11->duplicateNodesInConn(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),nbNodes); m11->setCoords(m0->getCoords());
3269   std::vector<const MEDCouplingUMesh *> v(2); v[0]=m1; v[1]=m11;
3270   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> newm1=MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(v,tmp00,tmp11);
3271   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> szOfCellGrpOfSameType(tmp00);
3272   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idInMsOfCellGrpOfSameType(tmp11);
3273   //
3274   newm1->setName(getName());
3275   const DataArrayInt *fam=getFamilyFieldAtLevel(-1);
3276   if(!fam)
3277     throw INTERP_KERNEL::Exception("MEDFileUMesh::duplicateNodesOnM1Group : internal problem !");
3278   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newFam=DataArrayInt::New();
3279   newFam->alloc(newm1->getNumberOfCells(),1);
3280   int idd=getMaxFamilyId()+1;
3281   int globStart=0,start=0,end,globEnd;
3282   int nbOfChunks=szOfCellGrpOfSameType->getNumberOfTuples();
3283   for(int i=0;i<nbOfChunks;i++)
3284     {
3285       globEnd=globStart+szOfCellGrpOfSameType->getIJ(i,0);
3286       if(idInMsOfCellGrpOfSameType->getIJ(i,0)==0)
3287         {
3288           end=start+szOfCellGrpOfSameType->getIJ(i,0);
3289           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=fam->selectByTupleId2(start,end,1);
3290           newFam->setPartOfValues1(part,globStart,globEnd,1,0,1,1,true);
3291           start=end;
3292         }
3293       else
3294         {
3295           newFam->setPartOfValuesSimple1(idd,globStart,globEnd,1,0,1,1);
3296         }
3297       globStart=globEnd;
3298     }
3299   newm1->setCoords(getCoords());
3300   setMeshAtLevel(-1,newm1);
3301   setFamilyFieldArr(-1,newFam);
3302   std::string grpName2(grpNameM1); grpName2+="_dup";
3303   addFamily(grpName2,idd);
3304   addFamilyOnGrp(grpName2,grpName2);
3305   //
3306   fam=_fam_coords;
3307   if(fam)
3308     {
3309       int newNbOfNodes=getCoords()->getNumberOfTuples();
3310       newFam=DataArrayInt::New(); newFam->alloc(newNbOfNodes,1);
3311       newFam->setPartOfValues1(fam,0,nbNodes,1,0,1,1,true);
3312       newFam->setPartOfValuesSimple1(0,nbNodes,newNbOfNodes,1,0,1,1);
3313       _fam_coords=newFam;
3314     }
3315   nodesDuplicated=nodeIdsToDuplicate.retn();
3316   cellsModified=cellsToModifyConn0.retn();
3317   cellsNotModified=cellsToModifyConn1.retn();
3318 }
3319
3320 /*!
3321  * \param [out] oldCode retrieves the distribution of types before the call if true is returned
3322  * \param [out] newCode etrieves the distribution of types after the call if true is returned
3323  * \param [out] o2nRenumCell tells for **all levels** the old 2 new renumbering of cells.
3324  * 
3325  * \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.
3326  * 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.
3327  */
3328 bool MEDFileUMesh::unPolyze(std::vector<int>& oldCode, std::vector<int>& newCode, DataArrayInt *& o2nRenumCell)
3329 {
3330   o2nRenumCell=0; oldCode.clear(); newCode.clear();
3331   std::vector<int> levs=getNonEmptyLevels();
3332   bool ret=false;
3333   std::vector< const DataArrayInt* > renumCellsSplited;//same than memorySaverIfThrow
3334   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > memorySaverIfThrow;//same than renumCellsSplited only in case of throw
3335   int start=0;
3336   int end=0;
3337   for(std::vector<int>::reverse_iterator it=levs.rbegin();it!=levs.rend();it++)
3338     {
3339       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=getMeshAtLevel(*it);
3340       std::vector<int> code1=m->getDistributionOfTypes();
3341       end=PutInThirdComponentOfCodeOffset(code1,start);
3342       oldCode.insert(oldCode.end(),code1.begin(),code1.end());
3343       bool hasChanged=m->unPolyze();
3344       DataArrayInt *fake=0;
3345       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nCellsPart=m->getLevArrPerCellTypes(MEDCouplingUMesh::MEDMEM_ORDER,
3346           MEDCouplingUMesh::MEDMEM_ORDER+MEDCouplingUMesh::N_MEDMEM_ORDER,fake);
3347       fake->decrRef();
3348       renumCellsSplited.push_back(o2nCellsPart); memorySaverIfThrow.push_back(o2nCellsPart);
3349       if(hasChanged)
3350         {
3351           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nCellsPart2=o2nCellsPart->buildPermArrPerLevel();
3352           m->renumberCells(o2nCellsPart2->getConstPointer(),false);
3353           ret=true;
3354           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famField2,numField2;
3355           const DataArrayInt *famField=getFamilyFieldAtLevel(*it); if(famField) { famField->incrRef(); famField2=const_cast<DataArrayInt *>(famField); }
3356           const DataArrayInt *numField=getNumberFieldAtLevel(*it); if(numField) { numField->incrRef(); numField2=const_cast<DataArrayInt *>(numField); }
3357           setMeshAtLevel(*it,m);
3358           std::vector<int> code2=m->getDistributionOfTypes();
3359           end=PutInThirdComponentOfCodeOffset(code2,start);
3360           newCode.insert(newCode.end(),code2.begin(),code2.end());
3361           //
3362           if(o2nCellsPart2->isIdentity())
3363             continue;
3364           if(famField)
3365             {
3366               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newFamField=famField->renumber(o2nCellsPart2->getConstPointer());
3367               setFamilyFieldArr(*it,newFamField);
3368             }
3369           if(numField)
3370             {
3371               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newNumField=numField->renumber(o2nCellsPart2->getConstPointer());
3372               setRenumFieldArr(*it,newNumField);
3373             }
3374         }
3375       else
3376         {
3377           newCode.insert(newCode.end(),code1.begin(),code1.end());
3378         }
3379       start=end;
3380     }
3381   if(ret)
3382     {
3383       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renumCells=DataArrayInt::Aggregate(renumCellsSplited);
3384       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRenumCellRet=renumCells->buildPermArrPerLevel();
3385       o2nRenumCell=o2nRenumCellRet.retn();
3386     }
3387   return ret;
3388 }
3389
3390 struct MEDLoaderAccVisit1
3391 {
3392   MEDLoaderAccVisit1():_new_nb_of_nodes(0) { }
3393   int operator()(bool val) { return val?_new_nb_of_nodes++:-1; }
3394   int _new_nb_of_nodes;
3395 };
3396
3397 /*!
3398  * 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.
3399  * The maximum value stored in returned array is the number of nodes of \a this minus 1 after call of this method.
3400  * The size of returned array is the number of nodes of the old (previous to the call of this method) number of nodes.
3401  * -1 values in returned array means that the corresponding old node is no more used.
3402  *
3403  * \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
3404  *         is modified in \a this.
3405  * \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
3406  *  set coordinates.
3407  */
3408 DataArrayInt *MEDFileUMesh::zipCoords()
3409 {
3410   const DataArrayDouble *coo=getCoords();
3411   if(!coo)
3412     throw INTERP_KERNEL::Exception("MEDFileUMesh::zipCoords : no coordinates set in this !");
3413   int nbOfNodes=coo->getNumberOfTuples();
3414   std::vector<bool> nodeIdsInUse(nbOfNodes,false);
3415   std::vector<int> neLevs=getNonEmptyLevels();
3416   for(std::vector<int>::const_iterator lev=neLevs.begin();lev!=neLevs.end();lev++)
3417     {
3418       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=getMeshAtLevel(*lev);
3419       m->computeNodeIdsAlg(nodeIdsInUse);
3420     }
3421   int nbrOfNodesInUse=(int)std::count(nodeIdsInUse.begin(),nodeIdsInUse.end(),true);
3422   if(nbrOfNodesInUse==nbOfNodes)
3423     return 0;
3424   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodes,1);
3425   std::transform(nodeIdsInUse.begin(),nodeIdsInUse.end(),ret->getPointer(),MEDLoaderAccVisit1());
3426   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2=ret->invertArrayO2N2N2OBis(nbrOfNodesInUse);
3427   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->selectByTupleIdSafe(ret2->begin(),ret2->end());
3428   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newFamCoords;
3429   MEDCouplingAutoRefCountObjectPtr<DataArrayAsciiChar> newNameCoords;
3430   if((const DataArrayInt *)_fam_coords)
3431     newFamCoords=_fam_coords->selectByTupleIdSafe(ret2->begin(),ret2->end());
3432   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newNumCoords;
3433   if((const DataArrayInt *)_num_coords)
3434     newNumCoords=_num_coords->selectByTupleIdSafe(ret2->begin(),ret2->end());
3435   if((const DataArrayAsciiChar *)_name_coords)
3436     newNameCoords=static_cast<DataArrayAsciiChar *>(_name_coords->selectByTupleIdSafe(ret2->begin(),ret2->end()));
3437   _coords=newCoords; _fam_coords=newFamCoords; _num_coords=newNumCoords; _name_coords=newNameCoords; _rev_num_coords=0;
3438   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
3439     {
3440       if((MEDFileUMeshSplitL1*)*it)
3441         (*it)->renumberNodesInConn(ret->begin());
3442     }
3443   return ret.retn();
3444 }
3445
3446 /*!
3447  * Adds a group of nodes to \a this mesh.
3448  *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
3449  *          The ids should be sorted and different each other (MED file norm).
3450  *  \throw If the node coordinates array is not set.
3451  *  \throw If \a ids == \c NULL.
3452  *  \throw If \a ids->getName() == "".
3453  *  \throw If \a ids does not respect the MED file norm.
3454  *  \throw If a group with name \a ids->getName() already exists.
3455  */
3456 void MEDFileUMesh::addNodeGroup(const DataArrayInt *ids)
3457 {
3458   const DataArrayDouble *coords=_coords;
3459   if(!coords)
3460     throw INTERP_KERNEL::Exception("MEDFileUMesh::addNodeGroup : no coords set !");
3461   int nbOfNodes=coords->getNumberOfTuples();
3462   if(!((DataArrayInt *)_fam_coords))
3463     { _fam_coords=DataArrayInt::New(); _fam_coords->alloc(nbOfNodes,1); _fam_coords->fillWithZero(); }
3464   //
3465   addGroupUnderground(true,ids,_fam_coords);
3466 }
3467
3468 /*!
3469  * Adds a group of nodes/cells/faces/edges to \a this mesh.
3470  *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
3471  *          The ids should be sorted and different each other (MED file norm).
3472  *  \throw If the node coordinates array is not set.
3473  *  \throw If \a ids == \c NULL.
3474  *  \throw If \a ids->getName() == "".
3475  *  \throw If \a ids does not respect the MED file norm.
3476  *  \throw If a group with name \a ids->getName() already exists.
3477  */
3478 void MEDFileUMesh::addGroup(int meshDimRelToMaxExt, const DataArrayInt *ids)
3479 {
3480   std::vector<int> levs=getNonEmptyLevelsExt();
3481   if(std::find(levs.begin(),levs.end(),meshDimRelToMaxExt)==levs.end())
3482     { 
3483       std::ostringstream oss; oss << "MEDFileUMesh::addGroup : level " << meshDimRelToMaxExt << " not available ! Should be in ";
3484       std::copy(levs.begin(),levs.end(),std::ostream_iterator<int>(oss," ")); oss << " !"; throw INTERP_KERNEL::Exception(oss.str().c_str());
3485     }
3486   if(meshDimRelToMaxExt==1)
3487     { addNodeGroup(ids); return ; }
3488   MEDFileUMeshSplitL1 *lev=getMeshAtLevSafe(meshDimRelToMaxExt);
3489   DataArrayInt *fam=lev->getOrCreateAndGetFamilyField();
3490   addGroupUnderground(false,ids,fam);
3491 }
3492
3493 /*!
3494  * \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).
3495  * \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)
3496  */
3497 void MEDFileUMesh::addGroupUnderground(bool isNodeGroup, const DataArrayInt *ids, DataArrayInt *famArr)
3498 {
3499   if(!ids)
3500     throw INTERP_KERNEL::Exception("MEDFileUMesh::addGroup : NULL pointer in input !");
3501   std::string grpName(ids->getName());
3502   if(grpName.empty())
3503     throw INTERP_KERNEL::Exception("MEDFileUMesh::addGroup : empty group name ! MED file format do not accept empty group name !");
3504   ids->checkStrictlyMonotonic(true);
3505   famArr->incrRef(); MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famArrTmp(famArr);
3506   std::vector<std::string> grpsNames=getGroupsNames();
3507   if(std::find(grpsNames.begin(),grpsNames.end(),grpName)!=grpsNames.end())
3508     {
3509       std::ostringstream oss; oss << "MEDFileUMesh::addGroup : Group with name \"" << grpName << "\" already exists ! Destroy it before calling this method !";
3510       throw INTERP_KERNEL::Exception(oss.str().c_str());
3511     }
3512   std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > allFamIds=getAllNonNullFamilyIds();
3513   allFamIds.erase(std::find(allFamIds.begin(),allFamIds.end(),famArrTmp));
3514   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famIds=famArr->selectByTupleIdSafe(ids->begin(),ids->end());
3515   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffFamIds=famIds->getDifferentValues();
3516   std::vector<int> familyIds;
3517   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerfamiliyIds;
3518   int maxVal=getTheMaxAbsFamilyId()+1;
3519   std::map<std::string,int> families(_families);
3520   std::map<std::string, std::vector<std::string> > groups(_groups);
3521   std::vector<std::string> fams;
3522   bool created(false);
3523   for(const int *famId=diffFamIds->begin();famId!=diffFamIds->end();famId++)
3524     {
3525       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2Tmp=famIds->getIdsEqual(*famId);
3526       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=ids->selectByTupleId(ids2Tmp->begin(),ids2Tmp->end());
3527       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids1=famArr->getIdsEqual(*famId);
3528       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(ids1->buildSubstractionOptimized(ids2));
3529       if(ret0->empty())
3530         {
3531           bool isFamPresent=false;
3532           for(std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::const_iterator itl=allFamIds.begin();itl!=allFamIds.end() && !isFamPresent;itl++)
3533             isFamPresent=(*itl)->presenceOfValue(*famId);
3534           if(!isFamPresent)
3535             { familyIds.push_back(*famId); idsPerfamiliyIds.push_back(ret0); fams.push_back(FindOrCreateAndGiveFamilyWithId(families,*famId,created)); } // adding *famId in grp
3536           else
3537             {
3538               familyIds.push_back(isNodeGroup?maxVal:-maxVal); idsPerfamiliyIds.push_back(ids2);
3539               std::string locFamName=FindOrCreateAndGiveFamilyWithId(families,isNodeGroup?maxVal:-maxVal,created);
3540               fams.push_back(locFamName);
3541               if(existsFamily(*famId))
3542                 {
3543                   std::string locFamName2=getFamilyNameGivenId(*famId); std::vector<std::string> v(2); v[0]=locFamName2; v[1]=locFamName;
3544                   ChangeAllGroupsContainingFamily(groups,getFamilyNameGivenId(*famId),v);
3545                 }
3546               maxVal++;
3547             } // modifying all other groups on *famId to lie on maxVal and lie the grp on maxVal
3548         }
3549       else
3550         {
3551           familyIds.push_back(isNodeGroup?maxVal:-maxVal); idsPerfamiliyIds.push_back(ret0); // modifying all other groups on *famId to lie on maxVal and on maxVal+1
3552           familyIds.push_back(isNodeGroup?maxVal+1:-maxVal-1); idsPerfamiliyIds.push_back(ids2);//grp lie only on maxVal+1
3553           std::string n2(FindOrCreateAndGiveFamilyWithId(families,isNodeGroup?maxVal+1:-maxVal-1,created)); fams.push_back(n2);
3554           if(existsFamily(*famId))
3555             {
3556               std::string n1(FindOrCreateAndGiveFamilyWithId(families,isNodeGroup?maxVal:-maxVal,created)); std::vector<std::string> v(2); v[0]=n1; v[1]=n2;
3557               ChangeAllGroupsContainingFamily(groups,getFamilyNameGivenId(*famId),v);
3558             }
3559           maxVal+=2;
3560         }
3561     }
3562   for(std::size_t i=0;i<familyIds.size();i++)
3563     {
3564       DataArrayInt *da=idsPerfamiliyIds[i];
3565       famArr->setPartOfValuesSimple3(familyIds[i],da->begin(),da->end(),0,1,1);
3566     }
3567   _families=families;
3568   _groups=groups;
3569   _groups[grpName]=fams;
3570 }
3571
3572 /*!
3573  * Changes a name of a family specified by its id.
3574  *  \param [in] id - the id of the family of interest.
3575  *  \param [in] newFamName - the new family name.
3576  *  \throw If no family with the given \a id exists.
3577  */
3578 void MEDFileUMesh::setFamilyNameAttachedOnId(int id, const std::string& newFamName)
3579 {
3580   std::string oldName=getFamilyNameGivenId(id);
3581   _families.erase(oldName);
3582   _families[newFamName]=id;
3583 }
3584
3585 /*!
3586  * Removes a mesh of a given dimension.
3587  *  \param [in] meshDimRelToMax - the relative dimension of interest.
3588  *  \throw If there is no mesh at level \a meshDimRelToMax in \a this mesh.
3589  */
3590 void MEDFileUMesh::removeMeshAtLevel(int meshDimRelToMax)
3591 {
3592   std::vector<int> levSet=getNonEmptyLevels();
3593   std::vector<int>::const_iterator it=std::find(levSet.begin(),levSet.end(),meshDimRelToMax);
3594   if(it==levSet.end())
3595     throw INTERP_KERNEL::Exception("MEDFileUMesh::removeMeshAtLevel : the requested level is not existing !");
3596   int pos=(-meshDimRelToMax);
3597   _ms[pos]=0;
3598 }
3599
3600 /*!
3601  * Sets a new MEDCoupling1GTUMesh at a given level in \a this mesh.
3602  *  \param [in] meshDimRelToMax - a relative level to set the mesh at.
3603  *  \param [in] m - the new mesh to set.
3604  *  \throw If the name or the description of \a this mesh and \a m are not empty and are
3605  *         different. 
3606  *  \throw If the node coordinates array is set \a this in mesh and \a m refers to
3607  *         another node coordinates array.
3608  *  \throw If the mesh dimension of \a m does not correspond to \a meshDimRelToMax or
3609  *         to the existing meshes of other levels of \a this mesh.
3610  */
3611 void MEDFileUMesh::setMeshAtLevel(int meshDimRelToMax, MEDCoupling1GTUMesh *m)
3612 {
3613   MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> elt(new MEDFileUMeshSplitL1(m));
3614   checkAndGiveEntryInSplitL1(meshDimRelToMax,m)=elt;
3615 }
3616
3617 /*!
3618  * Sets a new MEDCouplingUMesh at a given level in \a this mesh.
3619  *  \param [in] meshDimRelToMax - a relative level to set the mesh at.
3620  *  \param [in] m - the new mesh to set.
3621  *  \param [in] newOrOld - if \c true, cells in \a m are sorted by type to be ready for 
3622  *         writing \a this mesh in a MED file.
3623  *  \throw If the name or the description of \a this mesh and \a m are not empty and are
3624  *         different. 
3625  *  \throw If the node coordinates array is set \a this in mesh and \a m refers to
3626  *         another node coordinates array.
3627  *  \throw If the mesh dimension of \a m does not correspond to \a meshDimRelToMax or
3628  *         to the existing meshes of other levels of \a this mesh.
3629  */
3630 void MEDFileUMesh::setMeshAtLevel(int meshDimRelToMax, MEDCouplingUMesh *m, bool newOrOld)
3631 {
3632   MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> elt(new MEDFileUMeshSplitL1(m,newOrOld));
3633   checkAndGiveEntryInSplitL1(meshDimRelToMax,m)=elt;
3634 }
3635
3636 MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1>& MEDFileUMesh::checkAndGiveEntryInSplitL1(int meshDimRelToMax, MEDCouplingPointSet *m)
3637 {
3638   dealWithTinyInfo(m);
3639   std::vector<int> levSet=getNonEmptyLevels();
3640   if(std::find(levSet.begin(),levSet.end(),meshDimRelToMax)==levSet.end())
3641     {
3642       if((DataArrayDouble *)_coords==0)
3643         {
3644           DataArrayDouble *c=m->getCoords();
3645           if(c)
3646             c->incrRef();
3647           _coords=c;
3648         }
3649       if(m->getCoords()!=_coords)
3650         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshAtLevel : Invalid Given Mesh ! The coordinates are not the same ! try to use tryToShareSameCoords !");
3651       int sz=(-meshDimRelToMax)+1;
3652       if(sz>=(int)_ms.size())
3653         _ms.resize(sz);
3654       checkMeshDimCoherency(m->getMeshDimension(),meshDimRelToMax);
3655       return _ms[sz-1];
3656     }
3657   else
3658     return _ms[-meshDimRelToMax];
3659 }
3660
3661 /*!
3662  * This method allows to set at once the content of different levels in \a this.
3663  * This method is equivalent to a series of call to MEDFileUMesh::setMeshAtLevel.
3664  *
3665  * \param [in] ms - List of unstructured meshes lying on the same coordinates and having different mesh dimesnion.
3666  * \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.
3667  *                     If false, an exception ois thrown. If true the mesh is reordered automatically. It is highly recommanded to let this parameter to false.
3668  *
3669  * \throw If \a there is a null pointer in \a ms.
3670  * \sa MEDFileUMesh::setMeshAtLevel
3671  */
3672 void MEDFileUMesh::setMeshes(const std::vector<const MEDCouplingUMesh *>& ms, bool renum)
3673 {
3674   if(ms.empty())
3675     return ;
3676   const MEDCouplingUMesh *mRef=ms[0];
3677   if(!mRef)
3678     throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : null instance in the first element of input meshes !");
3679   std::string name(mRef->getName());
3680   const DataArrayDouble *coo(mRef->getCoords());
3681   std::set<int> s;
3682   int zeDim=-1;
3683   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
3684     {
3685       const MEDCouplingUMesh *cur(*it);
3686       if(!cur)
3687         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : null instance in input vector of meshes !");
3688       if(coo!=cur->getCoords())
3689         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : The input meshes do not share the same coordinates !");
3690       int mdim=cur->getMeshDimension();
3691       zeDim=std::max(zeDim,mdim);
3692       if(s.find(mdim)!=s.end())
3693         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : The input meshes must share the same coordinates pointer, and should have different mesh dimension each other !");
3694     }
3695   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
3696     {
3697       int mdim=(*it)->getMeshDimension();
3698       setName((*it)->getName());
3699       setMeshAtLevel(mdim-zeDim,const_cast<MEDCouplingUMesh *>(*it),renum);
3700     }
3701   setName(name);
3702 }
3703
3704 /*!
3705  * Creates one MEDCouplingUMesh at a given level in \a this mesh from a sequence of
3706  * meshes each representing a group, and creates corresponding groups in \a this mesh.
3707  * The given meshes must share the same node coordinates array.
3708  *  \param [in] meshDimRelToMax - the relative dimension to create the mesh and groups at.
3709  *  \param [in] ms - the sequence of meshes. Each mesh in \a ms represents a group to
3710  *          create in \a this mesh.
3711  *  \throw If \a ms is empty.
3712  *  \throw If dimension of meshes in \a ms does not correspond to \a meshDimRelToMax or
3713  *         to the existing meshes of other levels of \a this mesh.
3714  *  \throw If the meshes in \a ms do not share the same node coordinates array.
3715  *  \throw If the node coordinates array of \a this mesh (if any) is not the same as that
3716  *         of the given meshes.
3717  *  \throw If \a ms[ i ] is not well defined (MEDCouplingUMesh::checkCoherency()).
3718  *  \throw If names of some meshes in \a ms are equal.
3719  *  \throw If \a ms includes a mesh with an empty name.
3720  */
3721 void MEDFileUMesh::setGroupsFromScratch(int meshDimRelToMax, const std::vector<const MEDCouplingUMesh *>& ms, bool renum)
3722 {
3723   if(ms.empty())
3724     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsFromScratch : expecting a non empty vector !");
3725   int sz=(-meshDimRelToMax)+1;
3726   if(sz>=(int)_ms.size())
3727     _ms.resize(sz);
3728   checkMeshDimCoherency(ms[0]->getMeshDimension(),meshDimRelToMax);
3729   DataArrayDouble *coo=checkMultiMesh(ms);
3730   if((DataArrayDouble *)_coords==0)
3731     {
3732       coo->incrRef();
3733       _coords=coo;
3734     }
3735   else
3736     if((DataArrayDouble *)_coords!=coo)
3737       throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsFromScratch : coordinates mismatches !");
3738   std::vector<DataArrayInt *> corr;
3739   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MEDCouplingUMesh::FuseUMeshesOnSameCoords(ms,_zipconn_pol,corr);
3740   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > corr3(corr.begin(),corr.end());
3741   setMeshAtLevel(meshDimRelToMax,m,renum);
3742   std::vector<const DataArrayInt *> corr2(corr.begin(),corr.end());
3743   setGroupsAtLevel(meshDimRelToMax,corr2,true);
3744 }
3745
3746 /*!
3747  * Creates groups at a given level in \a this mesh from a sequence of
3748  * meshes each representing a group.
3749  * The given meshes must share the same node coordinates array.
3750  *  \param [in] meshDimRelToMax - the relative dimension to create the groups at.
3751  *  \param [in] ms - the sequence of meshes. Each mesh in \a ms represents a group to
3752  *         create in \a this mesh.
3753  *  \param [in] renum - if \c true, then the optional numbers of entities are taken into
3754  *         account. 
3755  *  \throw If \a ms is empty.
3756  *  \throw If dimension of meshes in \a ms does not correspond to \a meshDimRelToMax or
3757  *         to the existing meshes of other levels of \a this mesh.
3758  *  \throw If the meshes in \a ms do not share the same node coordinates array.
3759  *  \throw If the node coordinates array of \a this mesh (if any) is not the same as that
3760  *         of the given meshes.
3761  *  \throw If \a ms[ i ] is not well defined (MEDCouplingUMesh::checkCoherency()).
3762  *  \throw If names of some meshes in \a ms are equal.
3763  *  \throw If \a ms includes a mesh with an empty name.
3764  */
3765 void MEDFileUMesh::setGroupsOnSetMesh(int meshDimRelToMax, const std::vector<const MEDCouplingUMesh *>& ms, bool renum)
3766 {
3767   if(ms.empty())
3768     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsOnSetMesh : expecting a non empty vector !");
3769   int sz=(-meshDimRelToMax)+1;
3770   if(sz>=(int)_ms.size())
3771     _ms.resize(sz);
3772   checkMeshDimCoherency(ms[0]->getMeshDimension(),meshDimRelToMax);
3773   DataArrayDouble *coo=checkMultiMesh(ms);
3774   if((DataArrayDouble *)_coords==0)
3775     {
3776       coo->incrRef();
3777       _coords=coo;
3778     }
3779   else
3780     if((DataArrayDouble *)_coords!=coo)
3781       throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsOnSetMesh : coordinates mismatches !");
3782   MEDCouplingUMesh *m=getMeshAtLevel(meshDimRelToMax,renum);
3783   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > corr(ms.size());
3784   int i=0;
3785   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++,i++)
3786     {
3787       DataArrayInt *arr=0;
3788       bool test=m->areCellsIncludedIn(*it,_zipconn_pol,arr);
3789       corr[i]=arr;
3790       if(!test)
3791         {
3792           std::ostringstream oss; oss << "MEDFileUMesh::setGroupsOnSetMesh : mesh #" << i << " is not part of whole mesh !";
3793           throw INTERP_KERNEL::Exception(oss.str().c_str());
3794         }
3795     }
3796   std::vector<const DataArrayInt *> corr2(corr.begin(),corr.end());
3797   setGroupsAtLevel(meshDimRelToMax,corr2,renum);
3798 }
3799
3800 DataArrayDouble *MEDFileUMesh::checkMultiMesh(const std::vector<const MEDCouplingUMesh *>& ms) const
3801 {
3802   const DataArrayDouble *ret=ms[0]->getCoords();
3803   int mdim=ms[0]->getMeshDimension();
3804   for(unsigned int i=1;i<ms.size();i++)
3805     {
3806       ms[i]->checkCoherency();
3807       if(ms[i]->getCoords()!=ret)
3808         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMultiMesh : meshes must share the same coords !");
3809       if(ms[i]->getMeshDimension()!=mdim)
3810         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMultiMesh : meshes have not same mesh dimension !");
3811     }
3812   return const_cast<DataArrayDouble *>(ret);
3813 }
3814
3815 /*!
3816  * Sets the family field of a given relative dimension.
3817  *  \param [in] meshDimRelToMaxExt - the relative dimension of entities for which
3818  *          the family field is set.
3819  *  \param [in] famArr - the array of the family field.
3820  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3821  *  \throw If \a famArr has an invalid size.
3822  */
3823 void MEDFileUMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr)
3824 {
3825   if(meshDimRelToMaxExt==1)
3826     {
3827       if(!famArr)
3828         {
3829           _fam_coords=0;
3830           return ;
3831         }
3832       DataArrayDouble *coo(_coords);
3833       if(!coo)
3834         throw INTERP_KERNEL::Exception("MEDFileUMesh::setFamilyFieldArr : the coordinates have not been set !");
3835       famArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),1,"MEDFileUMesh::setFamilyFieldArr : Problem in size of node family arr ! ");
3836       famArr->incrRef();
3837       _fam_coords=famArr;
3838       return ;
3839     }
3840   if(meshDimRelToMaxExt>1)
3841     throw INTERP_KERNEL::Exception("MEDFileUMesh::setFamilyFieldArr : Dimension request is invalid (>1) !");
3842   int traducedRk=-meshDimRelToMaxExt;
3843   if(traducedRk>=(int)_ms.size())
3844     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
3845   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
3846     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3847   return _ms[traducedRk]->setFamilyArr(famArr);
3848 }
3849
3850 /*!
3851  * Sets the optional numbers of mesh entities of a given dimension.
3852  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
3853  *  \param [in] renumArr - the array of the numbers.
3854  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3855  *  \throw If \a renumArr has an invalid size.
3856  */
3857 void MEDFileUMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr)
3858 {
3859   if(meshDimRelToMaxExt==1)
3860     {
3861       if(!renumArr)
3862         {
3863           _num_coords=0;
3864           _rev_num_coords=0;
3865           return ;
3866         }
3867       DataArrayDouble *coo(_coords);
3868       if(!coo)
3869         throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumFieldArr : the coordinates have not been set !");
3870       renumArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),1,"MEDFileUMesh::setRenumArr : Problem in size of node numbering arr ! ");
3871       renumArr->incrRef();
3872       _num_coords=renumArr;
3873       computeRevNum();
3874       return ;
3875     }
3876   if(meshDimRelToMaxExt>1)
3877     throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumArr : Dimension request is invalid (>1) !");
3878   int traducedRk=-meshDimRelToMaxExt;
3879   if(traducedRk>=(int)_ms.size())
3880     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
3881   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
3882     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3883   return _ms[traducedRk]->setRenumArr(renumArr);
3884 }
3885
3886 /*!
3887  * Sets the optional names of mesh entities of a given dimension.
3888  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
3889  *  \param [in] nameArr - the array of the names.
3890  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3891  *  \throw If \a nameArr has an invalid size.
3892  */
3893 void MEDFileUMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr)
3894 {
3895   if(meshDimRelToMaxExt==1)
3896     {
3897       if(!nameArr)
3898         {
3899           _name_coords=0;
3900           return ;
3901         }
3902       DataArrayDouble *coo(_coords);
3903       if(!coo)
3904         throw INTERP_KERNEL::Exception("MEDFileUMesh::setNameFieldAtLevel : the coordinates have not been set !");
3905       nameArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),MED_SNAME_SIZE,"MEDFileUMesh::setNameFieldAtLevel : Problem in size of node numbering arr ! ");
3906       nameArr->incrRef();
3907       _name_coords=nameArr;
3908       return ;
3909     }
3910   if(meshDimRelToMaxExt>1)
3911     throw INTERP_KERNEL::Exception("MEDFileUMesh::setNameFieldAtLevel : Dimension request is invalid (>1) !");
3912   int traducedRk=-meshDimRelToMaxExt;
3913   if(traducedRk>=(int)_ms.size())
3914     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
3915   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
3916     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3917   return _ms[traducedRk]->setNameArr(nameArr);
3918 }
3919
3920 void MEDFileUMesh::synchronizeTinyInfoOnLeaves() const
3921 {
3922   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
3923     if((const MEDFileUMeshSplitL1 *)(*it))
3924       (*it)->synchronizeTinyInfo(*this);
3925 }
3926
3927 /*!
3928  * This method is called by MEDFileMesh::changeFamilyId. It performs only one part of the family id modification.
3929  */
3930 void MEDFileUMesh::changeFamilyIdArr(int oldId, int newId)
3931 {
3932   DataArrayInt *arr=_fam_coords;
3933   if(arr)
3934     arr->changeValue(oldId,newId);
3935   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
3936     {
3937       MEDFileUMeshSplitL1 *sp=(*it);
3938       if(sp)
3939         {
3940           sp->changeFamilyIdArr(oldId,newId);
3941         }
3942     }
3943 }
3944
3945 std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > MEDFileUMesh::getAllNonNullFamilyIds() const
3946 {
3947   std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret;
3948   const DataArrayInt *da(_fam_coords);
3949   if(da)
3950     { da->incrRef(); ret.push_back(MEDCouplingAutoRefCountObjectPtr<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
3951   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
3952     {
3953       const MEDFileUMeshSplitL1 *elt(*it);
3954       if(elt)
3955         {
3956           da=elt->getFamilyField();
3957           if(da)
3958             { da->incrRef(); ret.push_back(MEDCouplingAutoRefCountObjectPtr<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
3959         }
3960     }
3961   return ret;
3962 }
3963
3964 void MEDFileUMesh::computeRevNum() const
3965 {
3966   if((const DataArrayInt *)_num_coords)
3967     {
3968       int pos;
3969       int maxValue=_num_coords->getMaxValue(pos);
3970       _rev_num_coords=_num_coords->invertArrayN2O2O2N(maxValue+1);
3971     }
3972 }
3973
3974 std::size_t MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren() const
3975 {
3976   return MEDFileMesh::getHeapMemorySizeWithoutChildren();
3977 }
3978
3979 std::vector<const BigMemoryObject *> MEDFileStructuredMesh::getDirectChildren() const
3980 {
3981   std::vector<const BigMemoryObject *> ret(MEDFileMesh::getDirectChildren());
3982   if((const DataArrayInt *)_fam_nodes)
3983     ret.push_back((const DataArrayInt *)_fam_nodes);
3984   if((const DataArrayInt *)_num_nodes)
3985     ret.push_back((const DataArrayInt *)_num_nodes);
3986   if((const DataArrayAsciiChar *)_names_nodes)
3987     ret.push_back((const DataArrayAsciiChar *)_names_nodes);
3988   if((const DataArrayInt *)_fam_cells)
3989     ret.push_back((const DataArrayInt *)_fam_cells);
3990   if((const DataArrayInt *)_num_cells)
3991     ret.push_back((const DataArrayInt *)_num_cells);
3992   if((const DataArrayAsciiChar *)_names_cells)
3993     ret.push_back((const DataArrayAsciiChar *)_names_cells);
3994   if((const DataArrayInt *)_fam_faces)
3995     ret.push_back((const DataArrayInt *)_fam_faces);
3996   if((const DataArrayInt *)_num_faces)
3997     ret.push_back((const DataArrayInt *)_num_faces);
3998   if((const DataArrayInt *)_rev_num_nodes)
3999     ret.push_back((const DataArrayInt *)_rev_num_nodes);
4000   if((const DataArrayAsciiChar *)_names_faces)
4001     ret.push_back((const DataArrayAsciiChar *)_names_faces);
4002   if((const DataArrayInt *)_rev_num_cells)
4003     ret.push_back((const DataArrayInt *)_rev_num_cells);
4004   return ret;
4005 }
4006
4007 int MEDFileStructuredMesh::getMaxAbsFamilyIdInArrays() const
4008 {
4009   int ret=-std::numeric_limits<int>::max(),tmp=-1;
4010   if((const DataArrayInt *)_fam_nodes)
4011     {
4012       int val=_fam_nodes->getMaxValue(tmp);
4013       ret=std::max(ret,std::abs(val));
4014     }
4015   if((const DataArrayInt *)_fam_cells)
4016     {
4017       int val=_fam_cells->getMaxValue(tmp);
4018       ret=std::max(ret,std::abs(val));
4019     }
4020   if((const DataArrayInt *)_fam_faces)
4021     {
4022       int val=_fam_faces->getMaxValue(tmp);
4023       ret=std::max(ret,std::abs(val));
4024     }
4025   return ret;
4026 }
4027
4028 int MEDFileStructuredMesh::getMaxFamilyIdInArrays() const
4029 {
4030   int ret=-std::numeric_limits<int>::max(),tmp=-1;
4031   if((const DataArrayInt *)_fam_nodes)
4032     {
4033       int val=_fam_nodes->getMaxValue(tmp);
4034       ret=std::max(ret,val);
4035     }
4036   if((const DataArrayInt *)_fam_cells)
4037     {
4038       int val=_fam_cells->getMaxValue(tmp);
4039       ret=std::max(ret,val);
4040     }
4041   if((const DataArrayInt *)_fam_faces)
4042     {
4043       int val=_fam_faces->getMaxValue(tmp);
4044       ret=std::max(ret,val);
4045     }
4046   return ret;
4047 }
4048
4049 int MEDFileStructuredMesh::getMinFamilyIdInArrays() const
4050 {
4051   int ret=std::numeric_limits<int>::max(),tmp=-1;
4052   if((const DataArrayInt *)_fam_nodes)
4053     {
4054       int val=_fam_nodes->getMinValue(tmp);
4055       ret=std::min(ret,val);
4056     }
4057   if((const DataArrayInt *)_fam_cells)
4058     {
4059       int val=_fam_cells->getMinValue(tmp);
4060       ret=std::min(ret,val);
4061     }
4062   if((const DataArrayInt *)_fam_faces)
4063     {
4064       int val=_fam_faces->getMinValue(tmp);
4065       ret=std::min(ret,val);
4066     }
4067   return ret;
4068 }
4069
4070 bool MEDFileStructuredMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
4071 {
4072   if(!MEDFileMesh::isEqual(other,eps,what))
4073     return false;
4074   const MEDFileStructuredMesh *otherC=dynamic_cast<const  MEDFileStructuredMesh *>(other);
4075   if(!otherC)
4076     {
4077       what="Mesh types differ ! This is structured and other is NOT !";
4078       return false;
4079     }
4080   const DataArrayInt *famc1=_fam_nodes;
4081   const DataArrayInt *famc2=otherC->_fam_nodes;
4082   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
4083     {
4084       what="Mismatch of families arr on nodes ! 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 nodes differ !";
4093           return false;
4094         }
4095     }
4096   famc1=_fam_cells;
4097   famc2=otherC->_fam_cells;
4098   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
4099     {
4100       what="Mismatch of families arr on cells ! 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 cells differ !";
4109           return false;
4110         }
4111     }
4112   famc1=_fam_faces;
4113   famc2=otherC->_fam_faces;
4114   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
4115     {
4116       what="Mismatch of families arr on faces ! 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="Families arr on faces differ !";
4125           return false;
4126         }
4127     }
4128   famc1=_num_nodes;
4129   famc2=otherC->_num_nodes;
4130   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
4131     {
4132       what="Mismatch of numbering arr on nodes ! 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 nodes differ !";
4141           return false;
4142         }
4143     }
4144   famc1=_num_cells;
4145   famc2=otherC->_num_cells;
4146   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
4147     {
4148       what="Mismatch of numbering arr on cells ! 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 cells differ !";
4157           return false;
4158         }
4159     }
4160   famc1=_num_faces;
4161   famc2=otherC->_num_faces;
4162   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
4163     {
4164       what="Mismatch of numbering arr on faces ! One is defined and not other !";
4165       return false;
4166     }
4167   if(famc1)
4168     {
4169       bool ret=famc1->isEqual(*famc2);
4170       if(!ret)
4171         {
4172           what="Numbering arr on faces differ !";
4173           return false;
4174         }
4175     }
4176   const DataArrayAsciiChar *d1=_names_cells;
4177   const DataArrayAsciiChar *d2=otherC->_names_cells;
4178   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
4179     {
4180       what="Mismatch of naming arr on cells ! 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 cells differ !";
4189           return false;
4190         }
4191     }
4192   d1=_names_faces;
4193   d2=otherC->_names_faces;
4194   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
4195     {
4196       what="Mismatch of naming arr on faces ! 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 faces differ !";
4205           return false;
4206         }
4207     }
4208   d1=_names_nodes;
4209   d2=otherC->_names_nodes;
4210   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
4211     {
4212       what="Mismatch of naming arr on nodes ! One is defined and not other !";
4213       return false;
4214     }
4215   if(d1)
4216     {
4217       bool ret=d1->isEqual(*d2);
4218       if(!ret)
4219         {
4220           what="Naming arr on nodes differ !";
4221           return false;
4222         }
4223     }
4224   return true;
4225 }
4226
4227 void MEDFileStructuredMesh::clearNonDiscrAttributes() const
4228 {
4229   MEDFileMesh::clearNonDiscrAttributes();
4230   const DataArrayInt *tmp=_fam_nodes;
4231   if(tmp)
4232     (const_cast<DataArrayInt *>(tmp))->setName("");
4233   tmp=_num_nodes;
4234   if(tmp)
4235     (const_cast<DataArrayInt *>(tmp))->setName("");
4236   tmp=_fam_cells;
4237   if(tmp)
4238     (const_cast<DataArrayInt *>(tmp))->setName("");
4239   tmp=_num_cells;
4240   if(tmp)
4241     (const_cast<DataArrayInt *>(tmp))->setName("");
4242   tmp=_fam_faces;
4243   if(tmp)
4244     (const_cast<DataArrayInt *>(tmp))->setName("");
4245   tmp=_num_faces;
4246   if(tmp)
4247     (const_cast<DataArrayInt *>(tmp))->setName("");
4248 }
4249
4250 /*!
4251  * Returns ids of mesh entities contained in given families of a given dimension.
4252  *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
4253  *          are required.
4254  *  \param [in] fams - the names of the families of interest.
4255  *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
4256  *          returned instead of ids.
4257  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
4258  *          numbers, if available and required, of mesh entities of the families. The caller
4259  *          is to delete this array using decrRef() as it is no more needed. 
4260  *  \throw If the family field is missing for \a meshDimRelToMaxExt.
4261  */
4262 DataArrayInt *MEDFileStructuredMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const
4263 {
4264   std::vector<int> famIds(getFamiliesIds(fams));
4265   switch(meshDimRelToMaxExt)
4266   {
4267     case 1:
4268       {
4269         if((const DataArrayInt *)_fam_nodes)
4270           {
4271             MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
4272             if(!famIds.empty())
4273               da=_fam_nodes->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
4274             else
4275               da=_fam_nodes->getIdsEqualList(0,0);
4276             if(renum)
4277               return MEDFileUMeshSplitL1::Renumber(_num_nodes,da);
4278             else
4279               return da.retn();
4280           }
4281         else
4282           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on nodes !");
4283         break;
4284       }
4285     case 0:
4286       {
4287         if((const DataArrayInt *)_fam_cells)
4288           {
4289             MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
4290             if(!famIds.empty())
4291               da=_fam_cells->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
4292             else
4293               da=_fam_cells->getIdsEqualList(0,0);
4294             if(renum)
4295               return MEDFileUMeshSplitL1::Renumber(_num_cells,da);
4296             else
4297               return da.retn();
4298           }
4299         else
4300           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on cells !");
4301         break;
4302       }
4303     case -1:
4304       {
4305         if((const DataArrayInt *)_fam_faces)
4306           {
4307             MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
4308             if(!famIds.empty())
4309               da=_fam_faces->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
4310             else
4311               da=_fam_faces->getIdsEqualList(0,0);
4312             if(renum)
4313               return MEDFileUMeshSplitL1::Renumber(_num_faces,da);
4314             else
4315               return da.retn();
4316           }
4317         else
4318           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on faces !");
4319         break;
4320       }
4321     default:
4322       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : input meshDimRelative must be in [0,1,-1] !");
4323   }
4324   throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : unmanaged case !");
4325 }
4326
4327 /*!
4328  * Sets the family field of a given relative dimension.
4329  *  \param [in] meshDimRelToMaxExt - the relative dimension of entities for which
4330  *          the family field is set.
4331  *  \param [in] famArr - the array of the family field.
4332  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4333  *  \throw If \a famArr has an invalid size.
4334  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1 and \a meshDimRelToMaxExt != -1.
4335  */
4336 void MEDFileStructuredMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr)
4337 {
4338   const MEDCouplingStructuredMesh *mesh(getStructuredMesh());
4339   if(!mesh)
4340     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setFamilyFieldArr : no structured mesh specified ! Impossible to set family array !");
4341   switch(meshDimRelToMaxExt)
4342   {
4343     case 0:
4344       {
4345         int nbCells=mesh->getNumberOfCells();
4346         famArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of cells of mesh !");
4347         _fam_cells=famArr;
4348         break;
4349       }
4350     case 1:
4351       {
4352         int nbNodes=mesh->getNumberOfNodes();
4353         famArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !");
4354         _fam_nodes=famArr;
4355         break;
4356       }
4357     case -1:
4358       {
4359         int nbCells=mesh->getNumberOfCellsOfSubLevelMesh();
4360         famArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of faces of mesh !");
4361         _fam_faces=famArr;
4362         break;
4363       }
4364     default:
4365       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setFamilyFieldArr : Only available for levels 0 or 1 or -1 !");
4366   }
4367   if(famArr)
4368     famArr->incrRef();
4369 }
4370
4371 /*!
4372  * Sets the optional numbers of mesh entities of a given dimension.
4373  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4374  *  \param [in] renumArr - the array of the numbers.
4375  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4376  *  \throw If \a renumArr has an invalid size.
4377  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
4378  */
4379 void MEDFileStructuredMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr)
4380 {
4381   const MEDCouplingStructuredMesh *mesh=getStructuredMesh();
4382   if(!mesh)
4383     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : no structured mesh specified ! Impossible to set number array !");
4384   switch(meshDimRelToMaxExt)
4385   {
4386     case 0:
4387       {
4388         int nbCells=mesh->getNumberOfCells();
4389         renumArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Renum arr ! Mismatch with number of cells of mesh !");
4390         _num_cells=renumArr;
4391         break;
4392       }
4393     case 1:
4394       {
4395         int nbNodes=mesh->getNumberOfNodes();
4396         renumArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !");
4397         _num_nodes=renumArr;
4398         break;
4399       }
4400     case -1:
4401       {
4402         int nbCells=mesh->getNumberOfCellsOfSubLevelMesh();
4403         renumArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Renum arr ! Mismatch with number of faces of mesh !");
4404         _num_faces=renumArr;
4405         break;
4406       }
4407     default:
4408       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : Only available for levels 0 or 1 or -1 !");
4409   }
4410   if(renumArr)
4411     renumArr->incrRef();
4412 }
4413
4414 /*!
4415  * Sets the optional names of mesh entities of a given dimension.
4416  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4417  *  \param [in] nameArr - the array of the names.
4418  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4419  *  \throw If \a nameArr has an invalid size.
4420  */
4421 void MEDFileStructuredMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr)
4422 {
4423   const MEDCouplingStructuredMesh *mesh(getStructuredMesh());
4424   if(!mesh)
4425     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : no structured mesh specified ! Impossible to set names array !");
4426   switch(meshDimRelToMaxExt)
4427   {
4428     case 0:
4429       {
4430         int nbCells=mesh->getNumberOfCells();
4431         nameArr->checkNbOfTuplesAndComp(nbCells,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of cells of mesh !");
4432         _names_cells=nameArr;
4433         break;
4434       }
4435     case 1:
4436       {
4437         int nbNodes=mesh->getNumberOfNodes();
4438         nameArr->checkNbOfTuplesAndComp(nbNodes,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of nodes of mesh !");
4439         _names_nodes=nameArr;
4440         break;
4441       }
4442     case -1:
4443       {
4444         int nbCells=mesh->getNumberOfCellsOfSubLevelMesh();
4445         nameArr->checkNbOfTuplesAndComp(nbCells,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of faces of mesh !");
4446         _names_cells=nameArr;
4447       }
4448     default:
4449       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : Only available for levels 0 or 1 or -1 !");
4450   }
4451   if(nameArr)
4452     nameArr->incrRef();
4453 }
4454
4455 /*!
4456  * Returns the family field for mesh entities of a given dimension.
4457  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4458  *  \return const DataArrayInt * - the family field. It is an array of ids of families
4459  *          each mesh entity belongs to. It can be \c NULL.
4460  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
4461  */
4462 const DataArrayInt *MEDFileStructuredMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) const
4463 {
4464   switch(meshDimRelToMaxExt)
4465   {
4466     case 0:
4467       return _fam_cells;
4468     case 1:
4469       return _fam_nodes;
4470     case -1:
4471       return _fam_faces;
4472     default:
4473       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamilyFieldAtLevel : Only available for levels 0 or 1 or -1 !");
4474   }
4475 }
4476
4477 /*!
4478  * Returns the optional numbers of mesh entities of a given dimension.
4479  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4480  *  \return const DataArrayInt * - the array of the entity numbers.
4481  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4482  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
4483  */
4484 const DataArrayInt *MEDFileStructuredMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) const
4485 {
4486   switch(meshDimRelToMaxExt)
4487   {
4488     case 0:
4489       return _num_cells;
4490     case 1:
4491       return _num_nodes;
4492     case -1:
4493       return _num_faces;
4494     default:
4495       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberFieldAtLevel : Only available for levels 0 or 1 or -1 !");
4496   }
4497 }
4498
4499 /*!
4500  * Returns the optional numbers of mesh entities of a given dimension transformed using
4501  * DataArrayInt::invertArrayN2O2O2N().
4502  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4503  *  \return const DataArrayInt * - the array of the entity numbers transformed using
4504  *          DataArrayInt::invertArrayN2O2O2N().
4505  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
4506  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4507  */
4508 const DataArrayInt *MEDFileStructuredMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxExt) const
4509 {
4510   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4511     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getRevNumberFieldAtLevel : Only available for levels 0 or 1 !");
4512   if(meshDimRelToMaxExt==0)
4513     {
4514       if((const DataArrayInt *)_num_cells)
4515         {
4516           int pos;
4517           int maxValue=_num_cells->getMaxValue(pos);
4518           _rev_num_cells=_num_cells->invertArrayN2O2O2N(maxValue+1);
4519           return _rev_num_cells;
4520         }
4521       else
4522         throw INTERP_KERNEL::Exception("MEDFileCMesh::getRevNumberFieldAtLevel : no cell renumbering for a request on reverse numbering !");
4523     }
4524   else
4525     {
4526       if((const DataArrayInt *)_num_nodes)
4527         {
4528           int pos;
4529           int maxValue=_num_nodes->getMaxValue(pos);
4530           _rev_num_nodes=_num_nodes->invertArrayN2O2O2N(maxValue+1);
4531           return _rev_num_nodes;
4532         }
4533       else
4534         throw INTERP_KERNEL::Exception("MEDFileCMesh::getRevNumberFieldAtLevel : no node renumbering for a request on reverse numbering !");
4535     }
4536 }
4537
4538 const DataArrayAsciiChar *MEDFileStructuredMesh::getNameFieldAtLevel(int meshDimRelToMaxExt) const
4539 {
4540   switch(meshDimRelToMaxExt)
4541   {
4542     case 0:
4543       return _names_cells;
4544     case 1:
4545       return _names_nodes;
4546     case -1:
4547       return _names_faces;
4548     default:
4549       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNameFieldAtLevel : Only available for levels 0 or 1 or -1 !");
4550   }
4551 }
4552
4553 /*!
4554  * Returns relative dimensions of mesh entities (excluding nodes) present in \a this mesh.
4555  *  \return std::vector<int> - a sequence of the relative dimensions: [0].
4556  */
4557 std::vector<int> MEDFileStructuredMesh::getNonEmptyLevels() const
4558 {
4559   std::vector<int> ret(1);
4560   return ret;
4561 }
4562
4563 /*!
4564  * Returns relative dimensions of mesh entities (including nodes) present in \a this mesh.
4565  *  \return std::vector<int> - a sequence of the relative dimensions: [1,0].
4566  */
4567 std::vector<int> MEDFileStructuredMesh::getNonEmptyLevelsExt() const
4568 {
4569   std::vector<int> ret(2);
4570   ret[0]=1;
4571   return ret;
4572 }
4573
4574 /*!
4575  * Returns the set of extensive levels (nodes included) where not NULL family arr are defined.
4576  */
4577 std::vector<int> MEDFileStructuredMesh::getFamArrNonEmptyLevelsExt() const
4578 {
4579   std::vector<int> ret;
4580   const DataArrayInt *famNodes(_fam_nodes),*famCells(_fam_cells),*famFaces(_fam_faces);
4581   if(famNodes)
4582     ret.push_back(1);
4583   if(famCells)
4584     ret.push_back(0);
4585   if(famFaces)
4586     ret.push_back(-1);
4587   return ret;
4588 }
4589
4590 /*!
4591  * Returns the set of extensive levels (nodes included) where not NULL numbering arr are defined.
4592  */
4593 std::vector<int> MEDFileStructuredMesh::getNumArrNonEmptyLevelsExt() const
4594 {
4595   std::vector<int> ret;
4596   const DataArrayInt *numNodes(_num_nodes),*numCells(_num_cells),*numFaces(_num_faces);
4597   if(numNodes)
4598     ret.push_back(1);
4599   if(numCells)
4600     ret.push_back(0);
4601   if(numFaces)
4602     ret.push_back(-1);
4603   return ret;
4604 }
4605
4606 /*!
4607  * Returns the set of extensive levels (nodes included) where not NULL naming arr are defined.
4608  */
4609 std::vector<int> MEDFileStructuredMesh::getNameArrNonEmptyLevelsExt() const
4610 {
4611   std::vector<int> ret;
4612   const DataArrayAsciiChar *namesNodes(_names_nodes),*namesCells(_names_cells),*namesFaces(_names_faces);
4613   if(namesNodes)
4614     ret.push_back(1);
4615   if(namesCells)
4616     ret.push_back(0);
4617   if(namesFaces)
4618     ret.push_back(-1);
4619   return ret;
4620 }
4621
4622 /*!
4623  * no implementation here, it is not a bug, but intresically no polyhedra in \a this.
4624  */
4625 bool MEDFileStructuredMesh::unPolyze(std::vector<int>& oldCode, std::vector<int>& newCode, DataArrayInt *& o2nRenumCell)
4626 {
4627   oldCode.clear(); newCode.clear(); o2nRenumCell=0;
4628   return false;
4629 }
4630
4631 void MEDFileStructuredMesh::changeFamilyIdArr(int oldId, int newId)
4632 {
4633   DataArrayInt *arr=_fam_nodes;
4634   if(arr)
4635     arr->changeValue(oldId,newId);
4636   arr=_fam_cells;
4637   if(arr)
4638     arr->changeValue(oldId,newId);
4639   arr=_fam_faces;
4640   if(arr)
4641     arr->changeValue(oldId,newId);
4642 }
4643
4644 void MEDFileStructuredMesh::deepCpyAttributes()
4645 {
4646   if((const DataArrayInt*)_fam_nodes)
4647     _fam_nodes=_fam_nodes->deepCpy();
4648   if((const DataArrayInt*)_num_nodes)
4649     _num_nodes=_num_nodes->deepCpy();
4650   if((const DataArrayAsciiChar*)_names_nodes)
4651     _names_nodes=_names_nodes->deepCpy();
4652   if((const DataArrayInt*)_fam_cells)
4653     _fam_cells=_fam_cells->deepCpy();
4654   if((const DataArrayInt*)_num_cells)
4655     _num_cells=_num_cells->deepCpy();
4656   if((const DataArrayAsciiChar*)_names_cells)
4657     _names_cells=_names_cells->deepCpy();
4658   if((const DataArrayInt*)_fam_faces)
4659     _fam_faces=_fam_faces->deepCpy();
4660   if((const DataArrayInt*)_num_faces)
4661     _num_faces=_num_faces->deepCpy();
4662   if((const DataArrayAsciiChar*)_names_faces)
4663     _names_faces=_names_faces->deepCpy();
4664   if((const DataArrayInt*)_rev_num_nodes)
4665     _rev_num_nodes=_rev_num_nodes->deepCpy();
4666   if((const DataArrayInt*)_rev_num_cells)
4667     _rev_num_cells=_rev_num_cells->deepCpy();
4668 }
4669
4670 /*!
4671  * Returns a pointer to mesh at the specified level (here 0 is compulsary for cartesian mesh).
4672  * 
4673  * \return a pointer to cartesian mesh that need to be managed by the caller.
4674  * \warning the returned pointer has to be managed by the caller.
4675  */
4676
4677 /*!
4678  * Returns a pointer to MEDCouplingStructuredMesh held by \a this. 
4679  *  \param [in] meshDimRelToMax - it must be \c 0 or \c -1.
4680  *  \param [in] renum - it must be \c false.
4681  *  \return MEDCouplingMesh * - a pointer to MEDCouplingMesh that the caller is to
4682  *          delete using decrRef() as it is no more needed. 
4683  */
4684 MEDCouplingMesh *MEDFileStructuredMesh::getGenMeshAtLevel(int meshDimRelToMax, bool renum) const
4685 {
4686   if(renum)
4687     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support renumbering ! To do it perform request of renum array directly !");
4688   const MEDCouplingStructuredMesh *m(getStructuredMesh());
4689   switch(meshDimRelToMax)
4690   {
4691     case 0:
4692       {
4693         if(m)
4694           m->incrRef();
4695         return const_cast<MEDCouplingStructuredMesh *>(m);
4696       }
4697     case -1:
4698       {
4699         if(!m)
4700           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGenMeshAtLevel : level -1 requested must be non empty to be able to compute unstructured sub mesh !");
4701         return _faces_if_necessary;
4702       }
4703     default:
4704       throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support multi level for mesh 0 expected as input !");
4705   }
4706 }
4707
4708 /*!
4709  * Returns number of mesh entities of a given relative dimension in \a this mesh.
4710  *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
4711  *  \return int - the number of entities.
4712  *  \throw If no mesh entities of dimension \a meshDimRelToMaxExt are available in \a this mesh.
4713  */
4714 int MEDFileStructuredMesh::getSizeAtLevel(int meshDimRelToMaxExt) const
4715 {
4716   const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
4717   if(!cmesh)
4718     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : No structured mesh set !");
4719   switch(meshDimRelToMaxExt)
4720   {
4721     case 0:
4722       return cmesh->getNumberOfCells();
4723     case 1:
4724       return cmesh->getNumberOfNodes();
4725     case -1:
4726       return cmesh->getNumberOfCellsOfSubLevelMesh();
4727     default:
4728       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : Only available for levels 0 or 1 or -1 !");
4729   }
4730 }
4731
4732 int MEDFileStructuredMesh::getNumberOfNodes() const
4733 {
4734   const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
4735   if(!cmesh)
4736     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberOfNodes : no cartesian mesh set !");
4737   return cmesh->getNumberOfNodes();
4738 }
4739
4740 bool MEDFileStructuredMesh::hasImplicitPart() const
4741 {
4742   return true;
4743 }
4744
4745 /*!
4746  * \sa MEDFileStructuredMesh::getImplicitFaceMesh
4747  */
4748 int MEDFileStructuredMesh::buildImplicitPartIfAny(INTERP_KERNEL::NormalizedCellType gt) const
4749 {
4750   static const char MSG[]="MEDFileStructuredMesh::buildImplicitPartIfAny : the given geo type is not manageable by a structured mesh !";
4751   const MEDCoupling1SGTUMesh *zeFaceMesh(_faces_if_necessary);
4752   if(!zeFaceMesh)
4753     {
4754       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(getMeshDimension())));
4755       if(cm.getReverseExtrudedType()!=gt)
4756         throw INTERP_KERNEL::Exception(MSG);
4757       const MEDCouplingStructuredMesh *mcmesh(getStructuredMesh());
4758       _faces_if_necessary=mcmesh->build1SGTSubLevelMesh();
4759       return mcmesh->getNumberOfCellsOfSubLevelMesh();
4760     }
4761   else
4762     {
4763       if(gt!=zeFaceMesh->getCellModelEnum())
4764         throw INTERP_KERNEL::Exception(MSG);
4765       return zeFaceMesh->getNumberOfCells();
4766     }
4767 }
4768
4769 void MEDFileStructuredMesh::releaseImplicitPartIfAny() const
4770 {
4771   _faces_if_necessary=0;
4772 }
4773
4774 /*!
4775  * Retrieves the internal pointer (no decrRef requested) of the implicit face mesh if any.
4776  * To force to build it you can invoke MEDFileStructuredMesh::buildImplicitPartIfAny method.
4777  * 
4778  * \sa MEDFileStructuredMesh::buildImplicitPartIfAny
4779  */
4780 MEDCoupling1SGTUMesh *MEDFileStructuredMesh::getImplicitFaceMesh() const
4781 {
4782   return _faces_if_necessary;
4783 }
4784
4785 std::vector<INTERP_KERNEL::NormalizedCellType> MEDFileStructuredMesh::getGeoTypesAtLevel(int meshDimRelToMax) const
4786 {
4787   const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
4788   if(!cmesh)
4789     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGeoTypesAtLevel : No structured mesh set !");
4790   switch(meshDimRelToMax)
4791   {
4792     case 0:
4793       {
4794         std::vector<INTERP_KERNEL::NormalizedCellType> ret(1,cmesh->getTypeOfCell(0));
4795         return ret;
4796       }
4797     case -1:
4798       {
4799         int mdim(cmesh->getMeshDimension());
4800         if(mdim<1)
4801           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGeoTypesAtLevel : only one level available for structured meshes ! Input 0 is mandatory or 0D mesh !");
4802         std::vector<INTERP_KERNEL::NormalizedCellType> ret(1,MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(mdim-1));
4803         return ret;
4804       }
4805     default:
4806       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGeoTypesAtLevel : only 2 levels available at most : 0 and -1 !");
4807   }
4808 }
4809
4810 void MEDFileStructuredMesh::whichAreNodesFetched(const MEDFileField1TSStructItem& st, const MEDFileFieldGlobsReal *globs, std::vector<bool>& nodesFetched) const
4811 {
4812   if(st.getNumberOfItems()!=1)
4813     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 !");
4814   if(st[0].getGeo()!=MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(getMeshDimension()))
4815     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : The sturture of field is not lying on expected geo type !");
4816   if(getNumberOfNodes()!=(int)nodesFetched.size())
4817     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : invalid size of array !");
4818   if(st[0].getPflName().empty())
4819     {
4820       std::fill(nodesFetched.begin(),nodesFetched.end(),true);
4821       return ;
4822     }
4823   const DataArrayInt *arr(globs->getProfile(st[0].getPflName()));
4824   const MEDCouplingStructuredMesh *cmesh=getStructuredMesh();//cmesh not null because getNumberOfNodes called before
4825   int sz(nodesFetched.size());
4826   for(const int *work=arr->begin();work!=arr->end();work++)
4827     {
4828       std::vector<int> conn;
4829       cmesh->getNodeIdsOfCell(*work,conn);
4830       for(std::vector<int>::const_iterator it=conn.begin();it!=conn.end();it++)
4831         if(*it>=0 && *it<sz)
4832           nodesFetched[*it]=true;
4833         else
4834           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : internal error !");
4835     }
4836 }
4837
4838 med_geometry_type MEDFileStructuredMesh::GetGeoTypeFromMeshDim(int meshDim)
4839 {
4840   INTERP_KERNEL::NormalizedCellType ct(MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(meshDim));
4841   return typmai3[ct];
4842 }
4843
4844 void MEDFileStructuredMesh::LoadStrMeshDAFromFile(med_idt fid, int meshDim, int dt, int it, const std::string& mName, MEDFileMeshReadSelector *mrs,
4845                                                   MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& famCells, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& numCells, MEDCouplingAutoRefCountObjectPtr<DataArrayAsciiChar>& namesCells)
4846 {
4847   med_bool chgt=MED_FALSE,trsf=MED_FALSE;
4848   med_geometry_type geoTypeReq=MEDFileStructuredMesh::GetGeoTypeFromMeshDim(meshDim);
4849   int nbOfElt(0);
4850   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf);
4851   if(nbOfElt>0)
4852     {
4853       if(!mrs || mrs->isCellFamilyFieldReading())
4854         {
4855           famCells=DataArrayInt::New();
4856           famCells->alloc(nbOfElt,1);
4857           MEDmeshEntityFamilyNumberRd(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,famCells->getPointer());
4858         }
4859     }
4860   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,MED_NUMBER,MED_NODAL,&chgt,&trsf);
4861   if(nbOfElt>0)
4862     {
4863       if(!mrs || mrs->isCellNumFieldReading())
4864         {
4865           numCells=DataArrayInt::New();
4866           numCells->alloc(nbOfElt,1);
4867           MEDmeshEntityNumberRd(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,numCells->getPointer());
4868         }
4869     }
4870   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,MED_NAME,MED_NODAL,&chgt,&trsf);
4871   if(nbOfElt>0)
4872     {
4873       if(!mrs || mrs->isCellNameFieldReading())
4874         {
4875           namesCells=DataArrayAsciiChar::New();
4876           namesCells->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end
4877           MEDmeshEntityNameRd(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,namesCells->getPointer());
4878           namesCells->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end
4879         }
4880     }
4881 }
4882
4883 void MEDFileStructuredMesh::loadStrMeshFromFile(MEDFileStrMeshL2 *strm, med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
4884 {
4885   setName(strm->getName());
4886   setDescription(strm->getDescription());
4887   setUnivName(strm->getUnivName());
4888   setIteration(strm->getIteration());
4889   setOrder(strm->getOrder());
4890   setTimeValue(strm->getTime());
4891   setTimeUnit(strm->getTimeUnit());
4892   MEDFileMeshL2::ReadFamiliesAndGrps(fid,mName,_families,_groups,mrs);
4893   med_bool chgt=MED_FALSE,trsf=MED_FALSE;
4894   int nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf);
4895   if(nbOfElt>0)
4896     {
4897       if(!mrs || mrs->isNodeFamilyFieldReading())
4898         {
4899           int nbNodes(getNumberOfNodes());
4900           if(nbOfElt>nbNodes)
4901             throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::loadStrMeshFromFile : invalid size of family node array regarding number of nodes in this ! File seems to be corrupted !");
4902           _fam_nodes=DataArrayInt::New();
4903           _fam_nodes->alloc(nbNodes,1);//yes nbNodes and not nbOfElt see next line.
4904           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...
4905             _fam_nodes->fillWithZero();
4906           MEDmeshEntityFamilyNumberRd(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,_fam_nodes->getPointer());
4907         }
4908     }
4909   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_NUMBER,MED_NODAL,&chgt,&trsf);
4910   if(nbOfElt>0)
4911     {
4912       if(!mrs || mrs->isNodeNumFieldReading())
4913         {
4914           _num_nodes=DataArrayInt::New();
4915           _num_nodes->alloc(nbOfElt,1);
4916           MEDmeshEntityNumberRd(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,_num_nodes->getPointer());
4917         }
4918     }
4919   nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_NAME,MED_NODAL,&chgt,&trsf);
4920   if(nbOfElt>0)
4921     {
4922       if(!mrs || mrs->isNodeNameFieldReading())
4923         {
4924           _names_nodes=DataArrayAsciiChar::New();
4925           _names_nodes->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end
4926           MEDmeshEntityNameRd(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,_names_nodes->getPointer());
4927           _names_nodes->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end
4928         }
4929     }
4930   int meshDim(getStructuredMesh()->getMeshDimension());
4931   LoadStrMeshDAFromFile(fid,meshDim,dt,it,mName,mrs,_fam_cells,_num_cells,_names_cells);
4932   if(meshDim>=1)
4933     LoadStrMeshDAFromFile(fid,meshDim-1,dt,it,mName,mrs,_fam_faces,_num_faces,_names_faces);
4934 }
4935
4936 void MEDFileStructuredMesh::writeStructuredLL(med_idt fid, const std::string& maa) const
4937 {
4938   int meshDim(getStructuredMesh()->getMeshDimension());
4939   med_geometry_type geoTypeReq(GetGeoTypeFromMeshDim(meshDim)),geoTypeReq2(GetGeoTypeFromMeshDim(meshDim-1));
4940   //
4941   if((const DataArrayInt *)_fam_cells)
4942     MEDmeshEntityFamilyNumberWr(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq,_fam_cells->getNumberOfTuples(),_fam_cells->getConstPointer());
4943   if((const DataArrayInt *)_fam_faces)
4944     MEDmeshEntityFamilyNumberWr(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq2,_fam_faces->getNumberOfTuples(),_fam_faces->getConstPointer());
4945   if((const DataArrayInt *)_fam_nodes)
4946     MEDmeshEntityFamilyNumberWr(fid,maa.c_str(),_iteration,_order,MED_NODE,MED_NONE,_fam_nodes->getNumberOfTuples(),_fam_nodes->getConstPointer());
4947   if((const DataArrayInt *)_num_cells)
4948     MEDmeshEntityNumberWr(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq,_num_cells->getNumberOfTuples(),_num_cells->getConstPointer());
4949   if((const DataArrayInt *)_num_faces)
4950     MEDmeshEntityNumberWr(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq2,_num_faces->getNumberOfTuples(),_num_faces->getConstPointer());
4951   if((const DataArrayInt *)_num_nodes)
4952     MEDmeshEntityNumberWr(fid,maa.c_str(),_iteration,_order,MED_NODE,MED_NONE,_num_nodes->getNumberOfTuples(),_num_nodes->getConstPointer());
4953   if((const DataArrayAsciiChar *)_names_cells)
4954     {
4955       if(_names_cells->getNumberOfComponents()!=MED_SNAME_SIZE)
4956         {
4957           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on cells with number of components set to " << MED_SNAME_SIZE;
4958           oss << " ! The array has " << _names_cells->getNumberOfComponents() << " components !";
4959           throw INTERP_KERNEL::Exception(oss.str().c_str());
4960         }
4961       MEDmeshEntityNameWr(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq,_names_cells->getNumberOfTuples(),_names_cells->getConstPointer());
4962     }
4963   if((const DataArrayAsciiChar *)_names_faces)
4964     {
4965       if(_names_faces->getNumberOfComponents()!=MED_SNAME_SIZE)
4966         {
4967           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on faces with number of components set to " << MED_SNAME_SIZE;
4968           oss << " ! The array has " << _names_faces->getNumberOfComponents() << " components !";
4969           throw INTERP_KERNEL::Exception(oss.str().c_str());
4970         }
4971       MEDmeshEntityNameWr(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq2,_names_faces->getNumberOfTuples(),_names_faces->getConstPointer());
4972     }
4973   if((const DataArrayAsciiChar *)_names_nodes)
4974     {
4975       if(_names_nodes->getNumberOfComponents()!=MED_SNAME_SIZE)
4976         {
4977           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on nodes with number of components set to " << MED_SNAME_SIZE;
4978           oss << " ! The array has " << _names_cells->getNumberOfComponents() << " components !";
4979           throw INTERP_KERNEL::Exception(oss.str().c_str());
4980         }
4981       MEDmeshEntityNameWr(fid,maa.c_str(),_iteration,_order,MED_NODE,MED_NONE,_names_nodes->getNumberOfTuples(),_names_nodes->getConstPointer());
4982     }
4983   //
4984   MEDFileUMeshL2::WriteFamiliesAndGrps(fid,maa.c_str(),_families,_groups,_too_long_str);
4985 }
4986
4987 /*!
4988  * Returns an empty instance of MEDFileCMesh.
4989  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
4990  *          mesh using decrRef() as it is no more needed. 
4991  */
4992 MEDFileCMesh *MEDFileCMesh::New()
4993 {
4994   return new MEDFileCMesh;
4995 }
4996
4997 /*!
4998  * Returns a new MEDFileCMesh holding the mesh data that has been read from a given MED
4999  * file. The first mesh in the file is loaded.
5000  *  \param [in] fileName - the name of MED file to read.
5001  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
5002  *          mesh using decrRef() as it is no more needed. 
5003  *  \throw If the file is not readable.
5004  *  \throw If there is no meshes in the file.
5005  *  \throw If the mesh in the file is not a Cartesian one.
5006  */
5007 MEDFileCMesh *MEDFileCMesh::New(const std::string& fileName, MEDFileMeshReadSelector *mrs)
5008 {
5009   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
5010   if(ms.empty())
5011     {
5012       std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
5013       throw INTERP_KERNEL::Exception(oss.str().c_str());
5014     }
5015   MEDFileUtilities::CheckFileForRead(fileName);
5016   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
5017   int dt,it;
5018   ParaMEDMEM::MEDCouplingMeshType meshType;
5019   std::string dummy2;
5020   MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dt,it,dummy2);
5021   return new MEDFileCMesh(fid,ms.front(),dt,it,mrs);
5022 }
5023
5024 /*!
5025  * Returns a new MEDFileCMesh holding the mesh data that has been read from a given MED
5026  * file. The mesh to load is specified by its name and numbers of a time step and an
5027  * iteration.
5028  *  \param [in] fileName - the name of MED file to read.
5029  *  \param [in] mName - the name of the mesh to read.
5030  *  \param [in] dt - the number of a time step.
5031  *  \param [in] it - the number of an iteration.
5032  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
5033  *          mesh using decrRef() as it is no more needed. 
5034  *  \throw If the file is not readable.
5035  *  \throw If there is no mesh with given attributes in the file.
5036  *  \throw If the mesh in the file is not a Cartesian one.
5037  */
5038 MEDFileCMesh *MEDFileCMesh::New(const std::string& fileName, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
5039 {
5040   MEDFileUtilities::CheckFileForRead(fileName);
5041   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
5042   return new MEDFileCMesh(fid,mName,dt,it,mrs);
5043 }
5044
5045 std::size_t MEDFileCMesh::getHeapMemorySizeWithoutChildren() const
5046 {
5047   return MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren();
5048 }
5049
5050 std::vector<const BigMemoryObject *> MEDFileCMesh::getDirectChildren() const
5051 {
5052   std::vector<const BigMemoryObject *> ret(MEDFileStructuredMesh::getDirectChildren());
5053   if((const MEDCouplingCMesh *)_cmesh)
5054     ret.push_back((const MEDCouplingCMesh *)_cmesh);
5055   return ret;
5056 }
5057
5058 /*!
5059  * Returns the dimension on cells in \a this mesh.
5060  *  \return int - the mesh dimension.
5061  *  \throw If there are no cells in this mesh.
5062  */
5063 int MEDFileCMesh::getMeshDimension() const
5064 {
5065   if(!((const MEDCouplingCMesh*)_cmesh))
5066     throw INTERP_KERNEL::Exception("MEDFileCMesh::getMeshDimension : unable to get meshdimension because no mesh set !");
5067   return _cmesh->getMeshDimension();
5068 }
5069
5070 /*!
5071  * Returns the dimension on nodes in \a this mesh.
5072  *  \return int - the space dimension.
5073  *  \throw If there are no cells in this mesh.
5074  */
5075 int MEDFileCMesh::getSpaceDimension() const
5076 {
5077   if(!((const MEDCouplingCMesh*)_cmesh))
5078     throw INTERP_KERNEL::Exception("MEDFileCMesh::getSpaceDimension : unable to get spacedimension because no mesh set !");
5079   return _cmesh->getSpaceDimension();
5080 }
5081
5082 /*!
5083  * Returns a string describing \a this mesh.
5084  *  \return std::string - the mesh information string.
5085  */
5086 std::string MEDFileCMesh::simpleRepr() const
5087 {
5088   return MEDFileStructuredMesh::simpleRepr();
5089 }
5090
5091 /*!
5092  * Returns a full textual description of \a this mesh.
5093  *  \return std::string - the string holding the mesh description.
5094  */
5095 std::string MEDFileCMesh::advancedRepr() const
5096 {
5097   return simpleRepr();
5098 }
5099
5100 MEDFileMesh *MEDFileCMesh::shallowCpy() const
5101 {
5102   MEDCouplingAutoRefCountObjectPtr<MEDFileCMesh> ret=new MEDFileCMesh(*this);
5103   return ret.retn();
5104 }
5105
5106 MEDFileMesh *MEDFileCMesh::createNewEmpty() const
5107 {
5108   return new MEDFileCMesh;
5109 }
5110
5111 MEDFileMesh *MEDFileCMesh::deepCpy() const
5112 {
5113   MEDCouplingAutoRefCountObjectPtr<MEDFileCMesh> ret=new MEDFileCMesh(*this);
5114   if((const MEDCouplingCMesh*)_cmesh)
5115     ret->_cmesh=static_cast<MEDCouplingCMesh*>(_cmesh->deepCpy());
5116   ret->deepCpyAttributes();
5117   return ret.retn();
5118 }
5119
5120 /*!
5121  * Checks if \a this and another mesh are equal.
5122  *  \param [in] other - the mesh to compare with.
5123  *  \param [in] eps - a precision used to compare real values.
5124  *  \param [in,out] what - the string returning description of unequal data.
5125  *  \return bool - \c true if the meshes are equal, \c false, else.
5126  */
5127 bool MEDFileCMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
5128 {
5129   if(!MEDFileStructuredMesh::isEqual(other,eps,what))
5130     return false;
5131   const MEDFileCMesh *otherC=dynamic_cast<const MEDFileCMesh *>(other);
5132   if(!otherC)
5133     {
5134       what="Mesh types differ ! This is cartesian and other is NOT !";
5135       return false;
5136     }
5137   clearNonDiscrAttributes();
5138   otherC->clearNonDiscrAttributes();
5139   const MEDCouplingCMesh *coo1=_cmesh;
5140   const MEDCouplingCMesh *coo2=otherC->_cmesh;
5141   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
5142     {
5143       what="Mismatch of cartesian meshes ! One is defined and not other !";
5144       return false;
5145     }
5146   if(coo1)
5147     {
5148       bool ret=coo1->isEqual(coo2,eps);
5149       if(!ret)
5150         {
5151           what="cartesian meshes differ !";
5152           return false;
5153         }
5154     }
5155   return true;
5156 }
5157
5158 /*!
5159  * Clears redundant attributes of incorporated data arrays.
5160  */
5161 void MEDFileCMesh::clearNonDiscrAttributes() const
5162 {
5163   MEDFileStructuredMesh::clearNonDiscrAttributes();
5164   MEDFileUMeshSplitL1::ClearNonDiscrAttributes(_cmesh);//to it is not a bug umeshsplit have already the method implemented
5165 }
5166
5167 MEDFileCMesh::MEDFileCMesh()
5168 {
5169 }
5170
5171 MEDFileCMesh::MEDFileCMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
5172 try
5173 {
5174     loadCMeshFromFile(fid,mName,dt,it,mrs);
5175 }
5176 catch(INTERP_KERNEL::Exception& e)
5177 {
5178     throw e;
5179 }
5180
5181 void MEDFileCMesh::loadCMeshFromFile(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
5182 {
5183   ParaMEDMEM::MEDCouplingMeshType meshType;
5184   int dummy0,dummy1;
5185   std::string dtunit;
5186   int mid=MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dtunit);
5187   if(meshType!=CARTESIAN)
5188     {
5189       std::ostringstream oss; oss << "Trying to load as cartesian an existing mesh with name '" << mName << "' that is NOT cartesian !";
5190       throw INTERP_KERNEL::Exception(oss.str().c_str());
5191     }
5192   MEDFileCMeshL2 loaderl2;
5193   loaderl2.loadAll(fid,mid,mName,dt,it);
5194   MEDCouplingCMesh *mesh=loaderl2.getMesh();
5195   mesh->incrRef();
5196   _cmesh=mesh;
5197   loadStrMeshFromFile(&loaderl2,fid,mName,dt,it,mrs);
5198 }
5199
5200 /*!
5201  * Returns a const pointer to MEDCouplingCMesh held by \a this mesh.
5202  *  \return const MEDCouplingCMesh * - a pointer to the held MEDCouplingCMesh.
5203  */
5204 const MEDCouplingCMesh *MEDFileCMesh::getMesh() const
5205 {
5206   synchronizeTinyInfoOnLeaves();
5207   return _cmesh;
5208 }
5209
5210 const MEDCouplingStructuredMesh *MEDFileCMesh::getStructuredMesh() const
5211 {
5212   synchronizeTinyInfoOnLeaves();
5213   return _cmesh;
5214 }
5215
5216 /*!
5217  * Sets the MEDCouplingCMesh holding the data of \a this mesh.
5218  *  \param [in] m - the new MEDCouplingCMesh to refer to.
5219  *  \throw If the name or the description of \a this mesh and \a m are not empty and are
5220  *         different. 
5221  */
5222 void MEDFileCMesh::setMesh(MEDCouplingCMesh *m)
5223 {
5224   dealWithTinyInfo(m);
5225   if(m)
5226     m->incrRef();
5227   _cmesh=m;
5228 }
5229
5230 void MEDFileCMesh::writeLL(med_idt fid) const
5231 {
5232   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
5233   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
5234   INTERP_KERNEL::AutoPtr<char> dtunit=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE);
5235   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
5236   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
5237   MEDLoaderBase::safeStrCpy(_dt_unit.c_str(),MED_LNAME_SIZE,dtunit,_too_long_str);
5238   int spaceDim(_cmesh->getSpaceDimension());
5239   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
5240   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
5241   for(int i=0;i<spaceDim;i++)
5242     {
5243       std::string info(_cmesh->getCoordsAt(i)->getInfoOnComponent(0));
5244       std::string c,u;
5245       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
5246       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
5247       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
5248     }
5249   MEDmeshCr(fid,maa,spaceDim,spaceDim,MED_STRUCTURED_MESH,desc,dtunit,MED_SORT_DTIT,MED_CARTESIAN,comp,unit);
5250   MEDmeshUniversalNameWr(fid,maa);
5251   MEDmeshGridTypeWr(fid,maa,MED_CARTESIAN_GRID);
5252   for(int i=0;i<spaceDim;i++)
5253     {
5254       const DataArrayDouble *da=_cmesh->getCoordsAt(i);
5255       MEDmeshGridIndexCoordinateWr(fid,maa,_iteration,_order,_time,i+1,da->getNumberOfTuples(),da->getConstPointer());
5256     }
5257   //
5258   std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE));
5259   MEDFileStructuredMesh::writeStructuredLL(fid,meshName);
5260 }
5261
5262 void MEDFileCMesh::synchronizeTinyInfoOnLeaves() const
5263 {
5264   const MEDCouplingCMesh *cmesh=_cmesh;
5265   if(!cmesh)
5266     return;
5267   (const_cast<MEDCouplingCMesh *>(cmesh))->setName(_name);
5268   (const_cast<MEDCouplingCMesh *>(cmesh))->setDescription(_desc_name);
5269   (const_cast<MEDCouplingCMesh *>(cmesh))->setTime(_time,_iteration,_order);
5270   (const_cast<MEDCouplingCMesh *>(cmesh))->setTimeUnit(_dt_unit);
5271 }
5272
5273 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New()
5274 {
5275   return new MEDFileCurveLinearMesh;
5276 }
5277
5278 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const std::string& fileName, MEDFileMeshReadSelector *mrs)
5279 {
5280   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
5281   if(ms.empty())
5282     {
5283       std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
5284       throw INTERP_KERNEL::Exception(oss.str().c_str());
5285     }
5286   MEDFileUtilities::CheckFileForRead(fileName);
5287   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
5288   int dt,it;
5289   ParaMEDMEM::MEDCouplingMeshType meshType;
5290   std::string dummy2;
5291   MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dt,it,dummy2);
5292   return new MEDFileCurveLinearMesh(fid,ms.front(),dt,it,mrs);
5293 }
5294
5295 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const std::string& fileName, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
5296 {
5297   MEDFileUtilities::CheckFileForRead(fileName);
5298   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
5299   return new MEDFileCurveLinearMesh(fid,mName,dt,it,mrs);
5300 }
5301
5302 std::size_t MEDFileCurveLinearMesh::getHeapMemorySizeWithoutChildren() const
5303 {
5304   return MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren();
5305 }
5306
5307 std::vector<const BigMemoryObject *> MEDFileCurveLinearMesh::getDirectChildren() const
5308 {
5309   std::vector<const BigMemoryObject *> ret(MEDFileStructuredMesh::getDirectChildren());
5310   if((const MEDCouplingCurveLinearMesh *)_clmesh)
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::getDirectChildren() 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     {
5525       const MEDFileMesh *cur(*it);
5526       if(cur)
5527         ret.push_back(cur);
5528     }
5529   return ret;
5530 }
5531
5532 std::string MEDFileMeshMultiTS::getName() const
5533 {
5534   if(_mesh_one_ts.empty())
5535     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::getName : no time steps set !");
5536   return _mesh_one_ts[0]->getName();
5537 }
5538
5539 void MEDFileMeshMultiTS::setName(const std::string& newMeshName)
5540 {
5541   std::string oldName(getName());
5542   std::vector< std::pair<std::string,std::string> > v(1);
5543   v[0].first=oldName; v[0].second=newMeshName;
5544   changeNames(v);
5545 }
5546
5547 bool MEDFileMeshMultiTS::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab)
5548 {
5549   bool ret=false;
5550   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
5551     {
5552       MEDFileMesh *cur(*it);
5553       if(cur)
5554         ret=cur->changeNames(modifTab) || ret;
5555     }
5556   return ret;
5557 }
5558
5559 MEDFileMesh *MEDFileMeshMultiTS::getOneTimeStep() const
5560 {
5561   if(_mesh_one_ts.empty())
5562     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::getOneTimeStep : empty time step set !");
5563   return const_cast<MEDFileMesh *>(static_cast<const MEDFileMesh *>(_mesh_one_ts[0]));
5564 }
5565
5566 void MEDFileMeshMultiTS::setOneTimeStep(MEDFileMesh *mesh1TimeStep)
5567 {
5568   if(!mesh1TimeStep)
5569     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::setOneTimeStep : input pointer should be different from 0 !");
5570   _mesh_one_ts.resize(1);
5571   mesh1TimeStep->incrRef();
5572   //MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> toto=mesh1TimeStep;
5573   _mesh_one_ts[0]=mesh1TimeStep;
5574 }
5575
5576 void MEDFileMeshMultiTS::write(med_idt fid) const
5577 {
5578   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
5579     {
5580       (*it)->copyOptionsFrom(*this);
5581       (*it)->write(fid);
5582     }
5583 }
5584
5585 void MEDFileMeshMultiTS::write(const std::string& fileName, int mode) const
5586 {
5587   med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode);
5588   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),medmod);
5589   std::ostringstream oss; oss << "MEDFileMesh : error on attempt to write in file : \"" << fileName << "\""; 
5590   MEDFileUtilities::CheckMEDCode(fid,fid,oss.str());
5591   write(fid);
5592 }
5593
5594 void MEDFileMeshMultiTS::loadFromFile(const std::string& fileName, const std::string& mName)
5595 {//for the moment to be improved
5596   _mesh_one_ts.resize(1);
5597   _mesh_one_ts[0]=MEDFileMesh::New(fileName,mName,-1,-1);
5598 }
5599
5600 MEDFileMeshMultiTS::MEDFileMeshMultiTS()
5601 {
5602 }
5603
5604 MEDFileMeshMultiTS::MEDFileMeshMultiTS(const std::string& fileName)
5605 try
5606 {
5607     std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
5608     if(ms.empty())
5609       {
5610         std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
5611         throw INTERP_KERNEL::Exception(oss.str().c_str());
5612       }
5613     MEDFileUtilities::CheckFileForRead(fileName);
5614     MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
5615     int dt,it;
5616     ParaMEDMEM::MEDCouplingMeshType meshType;
5617     std::string dummy2;
5618     MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dt,it,dummy2);
5619     loadFromFile(fileName,ms.front());
5620 }
5621 catch(INTERP_KERNEL::Exception& e)
5622 {
5623     throw e;
5624 }
5625
5626 MEDFileMeshMultiTS::MEDFileMeshMultiTS(const std::string& fileName, const std::string& mName)
5627 try
5628 {
5629     loadFromFile(fileName,mName);
5630 }
5631 catch(INTERP_KERNEL::Exception& e)
5632 {
5633     throw e;
5634 }
5635
5636 MEDFileMeshes *MEDFileMeshes::New()
5637 {
5638   return new MEDFileMeshes;
5639 }
5640
5641 MEDFileMeshes *MEDFileMeshes::New(const std::string& fileName)
5642 {
5643   return new MEDFileMeshes(fileName);
5644 }
5645
5646 void MEDFileMeshes::write(med_idt fid) const
5647 {
5648   checkCoherency();
5649   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++)
5650     {
5651       (*it)->copyOptionsFrom(*this);
5652       (*it)->write(fid);
5653     }
5654 }
5655
5656 void MEDFileMeshes::write(const std::string& fileName, int mode) const
5657 {
5658   med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode);
5659   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),medmod);
5660   std::ostringstream oss; oss << "MEDFileMesh : error on attempt to write in file : \"" << fileName << "\""; 
5661   MEDFileUtilities::CheckMEDCode(fid,fid,oss.str());
5662   checkCoherency();
5663   write(fid);
5664 }
5665
5666 int MEDFileMeshes::getNumberOfMeshes() const
5667 {
5668   return _meshes.size();
5669 }
5670
5671 MEDFileMeshesIterator *MEDFileMeshes::iterator()
5672 {
5673   return new MEDFileMeshesIterator(this);
5674 }
5675
5676 /** Return a borrowed reference (caller is not responsible) */
5677 MEDFileMesh *MEDFileMeshes::getMeshAtPos(int i) const
5678 {
5679   if(i<0 || i>=(int)_meshes.size())
5680     {
5681       std::ostringstream oss; oss << "MEDFileMeshes::getMeshAtPos : invalid mesh id given in parameter ! Should be in [0;" << _meshes.size() << ") !";
5682       throw INTERP_KERNEL::Exception(oss.str().c_str());
5683     }
5684   return _meshes[i]->getOneTimeStep();
5685 }
5686
5687 /** Return a borrowed reference (caller is not responsible) */
5688 MEDFileMesh *MEDFileMeshes::getMeshWithName(const std::string& mname) const
5689 {
5690   std::vector<std::string> ms=getMeshesNames();
5691   std::vector<std::string>::iterator it=std::find(ms.begin(),ms.end(),mname);
5692   if(it==ms.end())
5693     {
5694       std::ostringstream oss; oss << "MEDFileMeshes::getMeshWithName : Mesh  \"" << mname << "\" does not exist in this ! Existing are : ";
5695       std::copy(ms.begin(),ms.end(),std::ostream_iterator<std::string>(oss," "));
5696       throw INTERP_KERNEL::Exception(oss.str().c_str());
5697     }
5698   return getMeshAtPos((int)std::distance(ms.begin(),it));
5699 }
5700
5701 std::vector<std::string> MEDFileMeshes::getMeshesNames() const
5702 {
5703   std::vector<std::string> ret(_meshes.size());
5704   int i=0;
5705   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
5706     {
5707       const MEDFileMeshMultiTS *f=(*it);
5708       if(f)
5709         {
5710           ret[i]=f->getName();
5711         }
5712       else
5713         {
5714           std::ostringstream oss; oss << "MEDFileMeshes::getMeshesNames : At rank #" << i << " mesh is not defined !";
5715           throw INTERP_KERNEL::Exception(oss.str().c_str());
5716         }
5717     }
5718   return ret;
5719 }
5720
5721 bool MEDFileMeshes::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab)
5722 {
5723   bool ret=false;
5724   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::iterator it=_meshes.begin();it!=_meshes.end();it++)
5725     {
5726       MEDFileMeshMultiTS *cur(*it);
5727       if(cur)
5728         ret=cur->changeNames(modifTab) || ret;
5729     }
5730   return ret;
5731 }
5732
5733 void MEDFileMeshes::resize(int newSize)
5734 {
5735   _meshes.resize(newSize);
5736 }
5737
5738 void MEDFileMeshes::pushMesh(MEDFileMesh *mesh)
5739 {
5740   if(!mesh)
5741     throw INTERP_KERNEL::Exception("MEDFileMeshes::pushMesh : invalid input pointer ! should be different from 0 !");
5742   MEDFileMeshMultiTS *elt=MEDFileMeshMultiTS::New();
5743   elt->setOneTimeStep(mesh);
5744   _meshes.push_back(elt);
5745 }
5746
5747 void MEDFileMeshes::setMeshAtPos(int i, MEDFileMesh *mesh)
5748 {
5749   if(!mesh)
5750     throw INTERP_KERNEL::Exception("MEDFileMeshes::setMeshAtPos : invalid input pointer ! should be different from 0 !");
5751   if(i>=(int)_meshes.size())
5752     _meshes.resize(i+1);
5753   MEDFileMeshMultiTS *elt=MEDFileMeshMultiTS::New();
5754   elt->setOneTimeStep(mesh);
5755   _meshes[i]=elt;
5756 }
5757
5758 void MEDFileMeshes::destroyMeshAtPos(int i)
5759 {
5760   if(i<0 || i>=(int)_meshes.size())
5761     {
5762       std::ostringstream oss; oss << "MEDFileMeshes::destroyMeshAtPos : Invalid given id in input (" << i << ") should be in [0," << _meshes.size() << ") !";
5763       throw INTERP_KERNEL::Exception(oss.str().c_str());
5764     }
5765   _meshes.erase(_meshes.begin()+i);
5766 }
5767
5768 void MEDFileMeshes::loadFromFile(const std::string& fileName)
5769 {
5770   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
5771   int i=0;
5772   _meshes.resize(ms.size());
5773   for(std::vector<std::string>::const_iterator it=ms.begin();it!=ms.end();it++,i++)
5774     _meshes[i]=MEDFileMeshMultiTS::New(fileName,(*it));
5775 }
5776
5777 MEDFileMeshes::MEDFileMeshes()
5778 {
5779 }
5780
5781 MEDFileMeshes::MEDFileMeshes(const std::string& fileName)
5782 try
5783 {
5784     loadFromFile(fileName);
5785 }
5786 catch(INTERP_KERNEL::Exception& /*e*/)
5787 {
5788 }
5789
5790 MEDFileMeshes *MEDFileMeshes::deepCpy() const
5791 {
5792   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> > meshes(_meshes.size());
5793   std::size_t i=0;
5794   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
5795     if((const MEDFileMeshMultiTS *)*it)
5796       meshes[i]=(*it)->deepCpy();
5797   MEDCouplingAutoRefCountObjectPtr<MEDFileMeshes> ret=MEDFileMeshes::New();
5798   ret->_meshes=meshes;
5799   return ret.retn();
5800 }
5801
5802 std::size_t MEDFileMeshes::getHeapMemorySizeWithoutChildren() const
5803 {
5804   return _meshes.capacity()*(sizeof(MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS>));
5805 }
5806
5807 std::vector<const BigMemoryObject *> MEDFileMeshes::getDirectChildren() const
5808 {
5809   std::vector<const BigMemoryObject *> ret;
5810   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++)
5811     {
5812       const MEDFileMeshMultiTS *cur(*it);
5813       if(cur)
5814         ret.push_back(cur);
5815     }
5816   return ret;
5817 }
5818
5819 std::string MEDFileMeshes::simpleRepr() const
5820 {
5821   std::ostringstream oss;
5822   oss << "(*****************)\n(* MEDFileMeshes *)\n(*****************)\n\n";
5823   simpleReprWithoutHeader(oss);
5824   return oss.str();
5825 }
5826
5827 void MEDFileMeshes::simpleReprWithoutHeader(std::ostream& oss) const
5828 {
5829   int nbOfMeshes=getNumberOfMeshes();
5830   oss << "There are " << nbOfMeshes << " meshes with the following names : \n";
5831   std::vector<std::string> mns=getMeshesNames();
5832   for(int i=0;i<nbOfMeshes;i++)
5833     oss << "  - #" << i << " \"" << mns[i] << "\"\n";
5834 }
5835
5836 void MEDFileMeshes::checkCoherency() const
5837 {
5838   static const char MSG[]="MEDFileMeshes::checkCoherency : mesh at rank ";
5839   int i=0;
5840   std::set<std::string> s;
5841   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
5842     {
5843       const MEDFileMeshMultiTS *elt=(*it);
5844       if(!elt)
5845         {
5846           std::ostringstream oss; oss << MSG << i << "/" << _meshes.size() << " is empty !";
5847           throw INTERP_KERNEL::Exception(oss.str().c_str());
5848         }
5849       std::size_t sz=s.size();
5850       s.insert(std::string((*it)->getName()));
5851       if(s.size()==sz)
5852         {
5853           std::ostringstream oss; oss << MSG << i << " has a name (\"" << (*it)->getName() << "\") already used by an another mesh in list !";
5854           throw INTERP_KERNEL::Exception(oss.str().c_str());
5855         }
5856     }
5857 }
5858
5859 MEDFileMeshesIterator::MEDFileMeshesIterator(MEDFileMeshes *ms):_ms(ms),_iter_id(0),_nb_iter(0)
5860 {
5861   if(ms)
5862     {
5863       ms->incrRef();
5864       _nb_iter=ms->getNumberOfMeshes();
5865     }
5866 }
5867
5868 MEDFileMeshesIterator::~MEDFileMeshesIterator()
5869 {
5870 }
5871
5872 MEDFileMesh *MEDFileMeshesIterator::nextt()
5873 {
5874   if(_iter_id<_nb_iter)
5875     {
5876       MEDFileMeshes *ms(_ms);
5877       if(ms)
5878         return ms->getMeshAtPos(_iter_id++);
5879       else
5880         return 0;
5881     }
5882   else
5883     return 0;
5884 }