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