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