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