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