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