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