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