Salome HOME
On the road of reimplementation of basic MEDLoader API with advanced one.
[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   return getGroups(meshDimRelToMaxExt,tmp,renum);
2670 }
2671
2672 /*!
2673  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in given
2674  * groups of \a this mesh. Only mesh entities of a given dimension are included in the
2675  * new mesh.
2676  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
2677  *  \param [in] grps - a sequence of group names whose mesh entities are included in the
2678  *          new mesh.
2679  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
2680  *          according to the optional numbers of entities, if available.
2681  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
2682  *          delete this mesh using decrRef() as it is no more needed.
2683  *  \throw If a name of a nonexistent group is present in \a grps.
2684  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2685  */
2686 MEDCouplingUMesh *MEDFileUMesh::getGroups(int meshDimRelToMaxExt, const std::vector<std::string>& grps, bool renum) const throw(INTERP_KERNEL::Exception)
2687 {
2688   synchronizeTinyInfoOnLeaves();
2689   std::vector<std::string> fams2=getFamiliesOnGroups(grps);
2690   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> zeRet=getFamilies(meshDimRelToMaxExt,fams2,renum);
2691   if(grps.size()==1 && ((MEDCouplingUMesh *)zeRet))
2692     zeRet->setName(grps[0].c_str());
2693   return zeRet.retn();
2694 }
2695
2696 /*!
2697  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in a given
2698  * family of \a this mesh. Only mesh entities of a given dimension are included in the
2699  * new mesh.
2700  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
2701  *  \param [in] fam - the name of the family whose mesh entities are included in the
2702  *          new mesh.
2703  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
2704  *          according to the optional numbers of entities, if available.
2705  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
2706  *          delete this mesh using decrRef() as it is no more needed.
2707  *  \throw If a name of a nonexistent family is present in \a grps.
2708  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2709  */
2710 MEDCouplingUMesh *MEDFileUMesh::getFamily(int meshDimRelToMaxExt, const char *fam, bool renum) const throw(INTERP_KERNEL::Exception)
2711 {
2712   synchronizeTinyInfoOnLeaves();
2713   std::vector<std::string> tmp(1);
2714   tmp[0]=fam;
2715   return getFamilies(meshDimRelToMaxExt,tmp,renum);
2716 }
2717
2718 /*!
2719  * Returns a new MEDCouplingUMesh corresponding to mesh entities included in given
2720  * families of \a this mesh. Only mesh entities of a given dimension are included in the
2721  * new mesh.
2722  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
2723  *  \param [in] fams - a sequence of family names whose mesh entities are included in the
2724  *          new mesh.
2725  *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
2726  *          according to the optional numbers of entities, if available.
2727  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
2728  *          delete this mesh using decrRef() as it is no more needed.
2729  *  \throw If a name of a nonexistent family is present in \a fams.
2730  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2731  */
2732 MEDCouplingUMesh *MEDFileUMesh::getFamilies(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const throw(INTERP_KERNEL::Exception)
2733 {
2734   synchronizeTinyInfoOnLeaves();
2735   if(meshDimRelToMaxExt==1)
2736     {
2737       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr=getFamiliesArr(1,fams,renum);
2738       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
2739       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> c=_coords->selectByTupleId(arr->getConstPointer(),arr->getConstPointer()+arr->getNbOfElems());
2740       ret->setCoords(c);
2741       return ret.retn();
2742     }
2743   std::vector<int> famIds=getFamiliesIds(fams);
2744   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2745   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> zeRet;
2746   if(!famIds.empty())
2747     zeRet=l1->getFamilyPart(&famIds[0],&famIds[0]+famIds.size(),renum);
2748   else
2749     zeRet=l1->getFamilyPart(0,0,renum);
2750   if(fams.size()==1 && ((MEDCouplingUMesh *)zeRet))
2751     zeRet->setName(fams[0].c_str());
2752   return zeRet.retn();
2753 }
2754
2755 /*!
2756  * Returns ids of mesh entities contained in given families of a given dimension.
2757  *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
2758  *          are required.
2759  *  \param [in] fams - the names of the families of interest.
2760  *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
2761  *          returned instead of ids.
2762  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
2763  *          numbers, if available and required, of mesh entities of the families. The caller
2764  *          is to delete this array using decrRef() as it is no more needed. 
2765  *  \throw If the family field is missing for \a meshDimRelToMaxExt.
2766  */
2767 DataArrayInt *MEDFileUMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const throw(INTERP_KERNEL::Exception)
2768 {
2769   std::vector<int> famIds=getFamiliesIds(fams);
2770   if(meshDimRelToMaxExt==1)
2771     {
2772       if((const DataArrayInt *)_fam_coords)
2773         {
2774           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
2775           if(!famIds.empty())
2776             da=_fam_coords->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
2777           else
2778             da=_fam_coords->getIdsEqualList(0,0);
2779           if(renum)
2780             return MEDFileUMeshSplitL1::Renumber(_num_coords,da);
2781           else
2782             return da.retn();
2783         }
2784       else
2785         throw INTERP_KERNEL::Exception("MEDFileUMesh::getFamiliesArr : no family array specified on nodes !");
2786     }
2787   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2788   if(!famIds.empty())
2789     return l1->getFamilyPartArr(&famIds[0],&famIds[0]+famIds.size(),renum);
2790   else
2791     return l1->getFamilyPartArr(0,0,renum);
2792 }
2793
2794 /*!
2795  * Returns a MEDCouplingUMesh of a given relative dimension.
2796  * \warning If \a meshDimRelToMaxExt == 1 (which means nodes), the returned mesh **is not
2797  * valid**. This is a feature, because MEDLoader does not create cells that do not exist! 
2798  * To build a valid MEDCouplingUMesh from the returned one in this case,
2799  * call MEDCouplingUMesh::Build0DMeshFromCoords().
2800  *  \param [in] meshDimRelToMax - the relative dimension of interest.
2801  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
2802  *          optional numbers of mesh entities.
2803  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
2804  *          delete using decrRef() as it is no more needed. 
2805  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2806  * \sa getGenMeshAtLevel()
2807  */
2808 MEDCouplingUMesh *MEDFileUMesh::getMeshAtLevel(int meshDimRelToMaxExt, bool renum) const throw(INTERP_KERNEL::Exception)
2809 {
2810   synchronizeTinyInfoOnLeaves();
2811   if(meshDimRelToMaxExt==1)
2812     {
2813       if(!renum)
2814         {
2815           MEDCouplingUMesh *umesh=MEDCouplingUMesh::New();
2816           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> cc=_coords->deepCpy();
2817           umesh->setCoords(cc);
2818           MEDFileUMeshSplitL1::ClearNonDiscrAttributes(umesh);
2819           umesh->setName(getName());
2820           return umesh;
2821         }
2822     }
2823   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2824   return l1->getWholeMesh(renum);
2825 }
2826
2827 /*!
2828  * Returns a MEDCouplingUMesh of a given relative dimension.
2829  * \warning If \a meshDimRelToMaxExt == 1 (which means nodes), the returned mesh **is not
2830  * valid**. This is a feature, because MEDLoader does not create cells that do not exist! 
2831  * To build a valid MEDCouplingUMesh from the returned one in this case,
2832  * call MEDCouplingUMesh::Build0DMeshFromCoords().
2833  *  \param [in] meshDimRelToMax - the relative dimension of interest.
2834  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
2835  *          optional numbers of mesh entities.
2836  *  \return MEDCouplingMesh * - a pointer to MEDCouplingUMesh that the caller is to
2837  *          delete using decrRef() as it is no more needed. 
2838  *  \throw If there are no mesh entities of \a meshDimRelToMax dimension in \a this mesh.
2839  * \sa getMeshAtLevel()
2840  */
2841 MEDCouplingMesh *MEDFileUMesh::getGenMeshAtLevel(int meshDimRelToMax, bool renum) const throw(INTERP_KERNEL::Exception)
2842 {
2843   return getMeshAtLevel(meshDimRelToMax,renum);
2844 }
2845
2846 /*!
2847  * Returns a MEDCouplingUMesh of a relative dimension == 0.
2848  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
2849  *          optional numbers of mesh entities.
2850  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
2851  *          delete using decrRef() as it is no more needed. 
2852  *  \throw If there are no mesh entities of the relative dimension == 0 in \a this mesh.
2853  */
2854 MEDCouplingUMesh *MEDFileUMesh::getLevel0Mesh(bool renum) const throw(INTERP_KERNEL::Exception)
2855 {
2856   return getMeshAtLevel(0,renum);
2857 }
2858
2859 /*!
2860  * Returns a MEDCouplingUMesh of a relative dimension == -1.
2861  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
2862  *          optional numbers of mesh entities.
2863  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
2864  *          delete using decrRef() as it is no more needed. 
2865  *  \throw If there are no mesh entities of the relative dimension == -1 in \a this mesh.
2866  */
2867 MEDCouplingUMesh *MEDFileUMesh::getLevelM1Mesh(bool renum) const throw(INTERP_KERNEL::Exception)
2868 {
2869   return getMeshAtLevel(-1,renum);
2870 }
2871
2872 /*!
2873  * Returns a MEDCouplingUMesh of a relative dimension == -2.
2874  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
2875  *          optional numbers of mesh entities.
2876  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
2877  *          delete using decrRef() as it is no more needed. 
2878  *  \throw If there are no mesh entities of the relative dimension == -2 in \a this mesh.
2879  */
2880 MEDCouplingUMesh *MEDFileUMesh::getLevelM2Mesh(bool renum) const throw(INTERP_KERNEL::Exception)
2881 {
2882   return getMeshAtLevel(-2,renum);
2883 }
2884
2885 /*!
2886  * Returns a MEDCouplingUMesh of a relative dimension == -3.
2887  *  \param [in] renum - if \c true, the returned mesh is permuted according to the
2888  *          optional numbers of mesh entities.
2889  *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
2890  *          delete using decrRef() as it is no more needed. 
2891  *  \throw If there are no mesh entities of the relative dimension == -3 in \a this mesh.
2892  */
2893 MEDCouplingUMesh *MEDFileUMesh::getLevelM3Mesh(bool renum) const throw(INTERP_KERNEL::Exception)
2894 {
2895   return getMeshAtLevel(-3,renum);
2896 }
2897
2898 const MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
2899 {
2900   if(meshDimRelToMaxExt==1)
2901     throw INTERP_KERNEL::Exception("Dimension request is invalid : asking for node level (1) !");
2902   if(meshDimRelToMaxExt>1)
2903     throw INTERP_KERNEL::Exception("Dimension request is invalid (>1) !");
2904   int tracucedRk=-meshDimRelToMaxExt;
2905   if(tracucedRk>=(int)_ms.size())
2906     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
2907   if((const MEDFileUMeshSplitL1 *)_ms[tracucedRk]==0)
2908     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
2909   return _ms[tracucedRk];
2910 }
2911
2912 MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt) throw(INTERP_KERNEL::Exception)
2913 {
2914    if(meshDimRelToMaxExt==1)
2915     throw INTERP_KERNEL::Exception("Dimension request is invalid : asking for node level (1) !");
2916   if(meshDimRelToMaxExt>1)
2917     throw INTERP_KERNEL::Exception("Dimension request is invalid (>1) !");
2918   int tracucedRk=-meshDimRelToMaxExt;
2919   if(tracucedRk>=(int)_ms.size())
2920     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
2921   if((const MEDFileUMeshSplitL1 *)_ms[tracucedRk]==0)
2922     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
2923   return _ms[tracucedRk];
2924 }
2925
2926 void MEDFileUMesh::checkMeshDimCoherency(int meshDim, int meshDimRelToMax) const throw(INTERP_KERNEL::Exception)
2927 {
2928   if(-meshDimRelToMax>=(int)_ms.size())
2929     throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMeshDimCoherency : The meshdim of mesh is not managed by 'this' !");
2930   int i=0;
2931   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,i++)
2932     {
2933       if(((const MEDFileUMeshSplitL1*) (*it))!=0)
2934         {
2935           int ref=(*it)->getMeshDimension();
2936           if(ref+i!=meshDim-meshDimRelToMax)
2937             throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMeshDimCoherency : no coherency between levels !");
2938         }
2939     }
2940 }
2941
2942 /*!
2943  * Sets the node coordinates array of \a this mesh.
2944  *  \param [in] coords - the new node coordinates array.
2945  *  \throw If \a coords == \c NULL.
2946  */
2947
2948 void MEDFileUMesh::setCoords(DataArrayDouble *coords) throw(INTERP_KERNEL::Exception)
2949 {
2950   if(!coords)
2951     throw INTERP_KERNEL::Exception("MEDFileUMesh::setCoords : null pointer in input !");
2952   coords->checkAllocated();
2953   int nbOfTuples=coords->getNumberOfTuples();
2954   _coords=coords;
2955   coords->incrRef();
2956   _fam_coords=DataArrayInt::New();
2957   _fam_coords->alloc(nbOfTuples,1);
2958   _fam_coords->fillWithZero();
2959 }
2960
2961 /*!
2962  * Removes all groups of a given dimension in \a this mesh.
2963  *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
2964  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
2965  */
2966 void MEDFileUMesh::eraseGroupsAtLevel(int meshDimRelToMaxExt) throw(INTERP_KERNEL::Exception)
2967 {
2968   if(meshDimRelToMaxExt==1)
2969     {
2970       if((DataArrayInt *)_fam_coords)
2971         _fam_coords->fillWithZero();
2972       return ;
2973     }
2974   MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2975   l1->eraseFamilyField();
2976   optimizeFamilies();
2977 }
2978
2979 /*!
2980  * Removes all families with ids not present in the family fields of \a this mesh.
2981  */
2982 void MEDFileUMesh::optimizeFamilies() throw(INTERP_KERNEL::Exception)
2983 {
2984   std::vector<int> levs=getNonEmptyLevelsExt();
2985   std::set<int> allFamsIds;
2986   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
2987     {
2988       const DataArrayInt *ffield=getFamilyFieldAtLevel(*it);
2989       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=ffield->getDifferentValues();
2990       std::set<int> res;
2991       std::set_union(ids->begin(),ids->end(),allFamsIds.begin(),allFamsIds.end(),std::inserter(res,res.begin()));
2992       allFamsIds=res;
2993     }
2994   std::set<std::string> famNamesToKill;
2995   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
2996     {
2997       if(allFamsIds.find((*it).second)!=allFamsIds.end())
2998         famNamesToKill.insert((*it).first);
2999     }
3000   for(std::set<std::string>::const_iterator it=famNamesToKill.begin();it!=famNamesToKill.end();it++)
3001     _families.erase(*it);
3002   std::vector<std::string> grpNamesToKill;
3003   for(std::map<std::string, std::vector<std::string> >::iterator it=_groups.begin();it!=_groups.end();it++)
3004     {
3005       std::vector<std::string> tmp;
3006       for(std::vector<std::string>::const_iterator it2=(*it).second.begin();it2!=(*it).second.end();it2++)
3007         {
3008           if(famNamesToKill.find(*it2)==famNamesToKill.end())
3009             tmp.push_back(*it2);
3010         }
3011       if(!tmp.empty())
3012         (*it).second=tmp;
3013       else
3014         tmp.push_back((*it).first);
3015     }
3016   for(std::vector<std::string>::const_iterator it=grpNamesToKill.begin();it!=grpNamesToKill.end();it++)
3017     _groups.erase(*it);
3018 }
3019
3020 void MEDFileUMesh::duplicateNodesOnM1Group(const char *grpNameM1, DataArrayInt *&nodesDuplicated, DataArrayInt *&cellsModified, DataArrayInt *&cellsNotModified) throw(INTERP_KERNEL::Exception)
3021 {
3022   std::vector<int> levs=getNonEmptyLevels();
3023   if(std::find(levs.begin(),levs.end(),0)==levs.end() || std::find(levs.begin(),levs.end(),-1)==levs.end())
3024     throw INTERP_KERNEL::Exception("MEDFileUMesh::duplicateNodesOnM1Group : This method works only for mesh definied on level 0 and -1 !");
3025   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0=getMeshAtLevel(0);
3026   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1=getMeshAtLevel(-1);
3027   int nbNodes=m0->getNumberOfNodes();
3028   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m11=getGroup(-1,grpNameM1);
3029   DataArrayInt *tmp00=0,*tmp11=0,*tmp22=0;
3030   m0->findNodesToDuplicate(*m11,tmp00,tmp11,tmp22);
3031   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodeIdsToDuplicate(tmp00);
3032   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0(tmp11);
3033   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1(tmp22);
3034   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp0=static_cast<MEDCouplingUMesh *>(m0->buildPartOfMySelf(cellsToModifyConn0->begin(),cellsToModifyConn0->end(),true));
3035   // node renumbering of cells in m1 impacted by duplication of node but not in group 'grpNameM1' on level -1
3036   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descTmp0=DataArrayInt::New(),descITmp0=DataArrayInt::New(),revDescTmp0=DataArrayInt::New(),revDescITmp0=DataArrayInt::New();
3037   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp0Desc=tmp0->buildDescendingConnectivity(descTmp0,descITmp0,revDescTmp0,revDescITmp0);
3038   descTmp0=0; descITmp0=0; revDescTmp0=0; revDescITmp0=0;
3039   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsInM1ToRenumW2=tmp0Desc->getCellIdsLyingOnNodes(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),false);
3040   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cellsInM1ToRenumW3=static_cast<MEDCouplingUMesh *>(tmp0Desc->buildPartOfMySelf(cellsInM1ToRenumW2->begin(),cellsInM1ToRenumW2->end(),true));
3041   DataArrayInt *cellsInM1ToRenumW4Tmp=0;
3042   m1->areCellsIncludedIn(cellsInM1ToRenumW3,2,cellsInM1ToRenumW4Tmp);
3043   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsInM1ToRenumW4(cellsInM1ToRenumW4Tmp);
3044   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsInM1ToRenumW5=cellsInM1ToRenumW4->getIdsInRange(0,m1->getNumberOfCells());
3045   cellsInM1ToRenumW5->transformWithIndArr(cellsInM1ToRenumW4->begin(),cellsInM1ToRenumW4->end());
3046   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> grpIds=getGroupArr(-1,grpNameM1);
3047   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsInM1ToRenum=cellsInM1ToRenumW5->buildSubstraction(grpIds);
3048   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Part=static_cast<MEDCouplingUMesh *>(m1->buildPartOfMySelf(cellsInM1ToRenum->begin(),cellsInM1ToRenum->end(),true));
3049   m1Part->duplicateNodesInConn(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),nbNodes);
3050   m1->setPartOfMySelf(cellsInM1ToRenum->begin(),cellsInM1ToRenum->end(),*m1Part);
3051   // end of node renumbering of cells in m1 impacted by duplication of node but not in group of level -1 'grpNameM1'
3052   tmp0->duplicateNodes(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end());
3053   m0->setCoords(tmp0->getCoords());
3054   m0->setPartOfMySelf(cellsToModifyConn0->begin(),cellsToModifyConn0->end(),*tmp0);
3055   m1->setCoords(m0->getCoords());
3056   _coords=m0->getCoords(); _coords->incrRef();
3057   // duplication of cells in group 'grpNameM1' on level -1
3058   m11->duplicateNodesInConn(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),nbNodes); m11->setCoords(m0->getCoords());
3059   std::vector<const MEDCouplingUMesh *> v(2); v[0]=m1; v[1]=m11;
3060   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> newm1=MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(v,tmp00,tmp11);
3061   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> szOfCellGrpOfSameType(tmp00);
3062   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idInMsOfCellGrpOfSameType(tmp11);
3063   //
3064   newm1->setName(getName());
3065   const DataArrayInt *fam=getFamilyFieldAtLevel(-1);
3066   if(!fam)
3067     throw INTERP_KERNEL::Exception("MEDFileUMesh::duplicateNodesOnM1Group : internal problem !");
3068   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newFam=DataArrayInt::New();
3069   newFam->alloc(newm1->getNumberOfCells(),1);
3070   int idd=getMaxFamilyId()+1;
3071   int globStart=0,start=0,end,globEnd;
3072   int nbOfChunks=szOfCellGrpOfSameType->getNumberOfTuples();
3073   for(int i=0;i<nbOfChunks;i++)
3074     {
3075       globEnd=globStart+szOfCellGrpOfSameType->getIJ(i,0);
3076       if(idInMsOfCellGrpOfSameType->getIJ(i,0)==0)
3077         {
3078           end=start+szOfCellGrpOfSameType->getIJ(i,0);
3079           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=fam->selectByTupleId2(start,end,1);
3080           newFam->setPartOfValues1(part,globStart,globEnd,1,0,1,1,true);
3081           start=end;
3082         }
3083       else
3084         {
3085           newFam->setPartOfValuesSimple1(idd,globStart,globEnd,1,0,1,1);
3086         }
3087       globStart=globEnd;
3088     }
3089   newm1->setCoords(getCoords());
3090   setMeshAtLevel(-1,newm1);
3091   setFamilyFieldArr(-1,newFam);
3092   std::string grpName2(grpNameM1); grpName2+="_dup";
3093   addFamily(grpName2.c_str(),idd);
3094   addFamilyOnGrp(grpName2.c_str(),grpName2.c_str());
3095   //
3096   fam=_fam_coords;
3097   if(fam)
3098     {
3099       int newNbOfNodes=getCoords()->getNumberOfTuples();
3100       newFam=DataArrayInt::New(); newFam->alloc(newNbOfNodes,1);
3101       newFam->setPartOfValues1(fam,0,nbNodes,1,0,1,1,true);
3102       newFam->setPartOfValuesSimple1(0,nbNodes,newNbOfNodes,1,0,1,1);
3103       _fam_coords=newFam;
3104     }
3105   nodesDuplicated=nodeIdsToDuplicate.retn();
3106   cellsModified=cellsToModifyConn0.retn();
3107   cellsNotModified=cellsToModifyConn1.retn();
3108 }
3109
3110 /*!
3111  * \param [out] oldCode retrieves the distribution of types before the call if true is returned
3112  * \param [out] newCode etrieves the distribution of types after the call if true is returned
3113  * \param [out] o2nRenumCell tells for **all levels** the old 2 new renumbering of cells.
3114  * 
3115  * \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.
3116  * 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.
3117  */
3118 bool MEDFileUMesh::unPolyze(std::vector<int>& oldCode, std::vector<int>& newCode, DataArrayInt *& o2nRenumCell) throw(INTERP_KERNEL::Exception)
3119 {
3120   o2nRenumCell=0; oldCode.clear(); newCode.clear();
3121   std::vector<int> levs=getNonEmptyLevels();
3122   bool ret=false;
3123   std::vector< const DataArrayInt* > renumCellsSplited;//same than memorySaverIfThrow
3124   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > memorySaverIfThrow;//same than renumCellsSplited only in case of throw
3125   int start=0;
3126   int end=0;
3127   for(std::vector<int>::reverse_iterator it=levs.rbegin();it!=levs.rend();it++)
3128     {
3129       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=getMeshAtLevel(*it);
3130       std::vector<int> code1=m->getDistributionOfTypes();
3131       end=PutInThirdComponentOfCodeOffset(code1,start);
3132       oldCode.insert(oldCode.end(),code1.begin(),code1.end());
3133       bool hasChanged=m->unPolyze();
3134       DataArrayInt *fake=0;
3135       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nCellsPart=m->getLevArrPerCellTypes(MEDCouplingUMesh::MEDMEM_ORDER,
3136                                                                                            MEDCouplingUMesh::MEDMEM_ORDER+MEDCouplingUMesh::N_MEDMEM_ORDER,fake);
3137       fake->decrRef();
3138       renumCellsSplited.push_back(o2nCellsPart); memorySaverIfThrow.push_back(o2nCellsPart);
3139       if(hasChanged)
3140         {
3141           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nCellsPart2=o2nCellsPart->buildPermArrPerLevel();
3142           m->renumberCells(o2nCellsPart2->getConstPointer(),false);
3143           ret=true;
3144           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famField2,numField2;
3145           const DataArrayInt *famField=getFamilyFieldAtLevel(*it); if(famField) { famField->incrRef(); famField2=const_cast<DataArrayInt *>(famField); }
3146           const DataArrayInt *numField=getNumberFieldAtLevel(*it); if(numField) { numField->incrRef(); numField2=const_cast<DataArrayInt *>(numField); }
3147           setMeshAtLevel(*it,m);
3148           std::vector<int> code2=m->getDistributionOfTypes();
3149           end=PutInThirdComponentOfCodeOffset(code2,start);
3150           newCode.insert(newCode.end(),code2.begin(),code2.end());
3151           //
3152           if(o2nCellsPart2->isIdentity())
3153             continue;
3154           if(famField)
3155             {
3156               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newFamField=famField->renumber(o2nCellsPart2->getConstPointer());
3157               setFamilyFieldArr(*it,newFamField);
3158             }
3159           if(numField)
3160             {
3161               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newNumField=numField->renumber(o2nCellsPart2->getConstPointer());
3162               setRenumFieldArr(*it,newNumField);
3163             }
3164         }
3165       else
3166         {
3167           newCode.insert(newCode.end(),code1.begin(),code1.end());
3168         }
3169       start=end;
3170     }
3171   if(ret)
3172     {
3173       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renumCells=DataArrayInt::Aggregate(renumCellsSplited);
3174       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRenumCellRet=renumCells->buildPermArrPerLevel();
3175       o2nRenumCell=o2nRenumCellRet.retn();
3176     }
3177   return ret;
3178 }
3179
3180 struct MEDLoaderAccVisit1
3181 {
3182   MEDLoaderAccVisit1():_new_nb_of_nodes(0) { }
3183   int operator()(bool val) { return val?_new_nb_of_nodes++:-1; }
3184   int _new_nb_of_nodes;
3185 };
3186
3187 /*!
3188  * 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.
3189  * The maximum value stored in returned array is the number of nodes of \a this minus 1 after call of this method.
3190  * The size of returned array is the number of nodes of the old (previous to the call of this method) number of nodes.
3191  * -1 values in returned array means that the corresponding old node is no more used.
3192  *
3193  * \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
3194  *         is modified in \a this.
3195  * \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
3196  *  set coordinates.
3197  */
3198 DataArrayInt *MEDFileUMesh::zipCoords() throw(INTERP_KERNEL::Exception)
3199 {
3200   const DataArrayDouble *coo=getCoords();
3201   if(!coo)
3202     throw INTERP_KERNEL::Exception("MEDFileUMesh::zipCoords : no coordinates set in this !");
3203   int nbOfNodes=coo->getNumberOfTuples();
3204   std::vector<bool> nodeIdsInUse(nbOfNodes,false);
3205   std::vector<int> neLevs=getNonEmptyLevels();
3206   for(std::vector<int>::const_iterator lev=neLevs.begin();lev!=neLevs.end();lev++)
3207     {
3208       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=getMeshAtLevel(*lev);
3209       m->computeNodeIdsAlg(nodeIdsInUse);
3210     }
3211   int nbrOfNodesInUse=(int)std::count(nodeIdsInUse.begin(),nodeIdsInUse.end(),true);
3212   if(nbrOfNodesInUse==nbOfNodes)
3213     return 0;
3214   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodes,1);
3215   std::transform(nodeIdsInUse.begin(),nodeIdsInUse.end(),ret->getPointer(),MEDLoaderAccVisit1());
3216   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2=ret->invertArrayO2N2N2OBis(nbrOfNodesInUse);
3217   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->selectByTupleIdSafe(ret2->begin(),ret2->end());
3218   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newFamCoords;
3219   MEDCouplingAutoRefCountObjectPtr<DataArrayAsciiChar> newNameCoords;
3220   if((const DataArrayInt *)_fam_coords)
3221     newFamCoords=_fam_coords->selectByTupleIdSafe(ret2->begin(),ret2->end());
3222   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newNumCoords;
3223   if((const DataArrayInt *)_num_coords)
3224     newNumCoords=_num_coords->selectByTupleIdSafe(ret2->begin(),ret2->end());
3225   if((const DataArrayAsciiChar *)_name_coords)
3226     newNameCoords=static_cast<DataArrayAsciiChar *>(_name_coords->selectByTupleIdSafe(ret2->begin(),ret2->end()));
3227   _coords=newCoords; _fam_coords=newFamCoords; _num_coords=newNumCoords; _name_coords=newNameCoords; _rev_num_coords=0;
3228   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
3229     {
3230       if((MEDFileUMeshSplitL1*)*it)
3231         (*it)->renumberNodesInConn(ret->begin());
3232     }
3233   return ret.retn();
3234 }
3235
3236 /*!
3237  * Adds a group of nodes to \a this mesh.
3238  *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
3239  *          The ids should be sorted and different each other (MED file norm).
3240  *  \throw If the node coordinates array is not set.
3241  *  \throw If \a ids == \c NULL.
3242  *  \throw If \a ids->getName() == "".
3243  *  \throw If \a ids does not respect the MED file norm.
3244  *  \throw If a group with name \a ids->getName() already exists.
3245  */
3246 void MEDFileUMesh::addNodeGroup(const DataArrayInt *ids) throw(INTERP_KERNEL::Exception)
3247 {
3248   const DataArrayDouble *coords=_coords;
3249   if(!coords)
3250     throw INTERP_KERNEL::Exception("MEDFileUMesh::addNodeGroup : no coords set !");
3251   int nbOfNodes=coords->getNumberOfTuples();
3252   if(!((DataArrayInt *)_fam_coords))
3253     { _fam_coords=DataArrayInt::New(); _fam_coords->alloc(nbOfNodes,1); _fam_coords->fillWithZero(); }
3254   //
3255   addGroupUnderground(true,ids,_fam_coords);
3256 }
3257
3258 /*!
3259  * Adds a group of nodes/cells/faces/edges to \a this mesh.
3260  *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
3261  *          The ids should be sorted and different each other (MED file norm).
3262  *  \throw If the node coordinates array is not set.
3263  *  \throw If \a ids == \c NULL.
3264  *  \throw If \a ids->getName() == "".
3265  *  \throw If \a ids does not respect the MED file norm.
3266  *  \throw If a group with name \a ids->getName() already exists.
3267  */
3268 void MEDFileUMesh::addGroup(int meshDimRelToMaxExt, const DataArrayInt *ids) throw(INTERP_KERNEL::Exception)
3269 {
3270   std::vector<int> levs=getNonEmptyLevelsExt();
3271   if(std::find(levs.begin(),levs.end(),meshDimRelToMaxExt)==levs.end())
3272     { 
3273       std::ostringstream oss; oss << "MEDFileUMesh::addGroup : level " << meshDimRelToMaxExt << " not available ! Should be in ";
3274       std::copy(levs.begin(),levs.end(),std::ostream_iterator<int>(oss," ")); oss << " !"; throw INTERP_KERNEL::Exception(oss.str().c_str());
3275     }
3276   if(meshDimRelToMaxExt==1)
3277     { addNodeGroup(ids); return ; }
3278   MEDFileUMeshSplitL1 *lev=getMeshAtLevSafe(meshDimRelToMaxExt);
3279   DataArrayInt *fam=lev->getOrCreateAndGetFamilyField();
3280   addGroupUnderground(false,ids,fam);
3281 }
3282
3283 /*!
3284  * \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).
3285  * \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)
3286  */
3287 void MEDFileUMesh::addGroupUnderground(bool isNodeGroup, const DataArrayInt *ids, DataArrayInt *famArr) throw(INTERP_KERNEL::Exception)
3288 {
3289   if(!ids)
3290     throw INTERP_KERNEL::Exception("MEDFileUMesh::addGroup : NULL pointer in input !");
3291   std::string grpName(ids->getName());
3292   if(grpName.empty())
3293     throw INTERP_KERNEL::Exception("MEDFileUMesh::addGroup : empty group name ! MED file format do not accept empty group name !");
3294   ids->checkStrictlyMonotonic(true);
3295   famArr->incrRef(); MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famArrTmp(famArr);
3296   std::vector<std::string> grpsNames=getGroupsNames();
3297   if(std::find(grpsNames.begin(),grpsNames.end(),grpName)!=grpsNames.end())
3298     {
3299       std::ostringstream oss; oss << "MEDFileUMesh::addGroup : Group with name \"" << grpName << "\" already exists ! Destroy it before calling this method !";
3300       throw INTERP_KERNEL::Exception(oss.str().c_str());
3301     }
3302   std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > allFamIds=getAllNonNullFamilyIds();
3303   allFamIds.erase(std::find(allFamIds.begin(),allFamIds.end(),famArrTmp));
3304   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famIds=famArr->selectByTupleIdSafe(ids->begin(),ids->end());
3305   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffFamIds=famIds->getDifferentValues();
3306   std::vector<int> familyIds;
3307   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerfamiliyIds;
3308   int maxVal=getTheMaxAbsFamilyId()+1;
3309   std::map<std::string,int> families(_families);
3310   std::map<std::string, std::vector<std::string> > groups(_groups);
3311   std::vector<std::string> fams;
3312   bool created(false);
3313   for(const int *famId=diffFamIds->begin();famId!=diffFamIds->end();famId++)
3314     {
3315       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2Tmp=famIds->getIdsEqual(*famId);
3316       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=ids->selectByTupleId(ids2Tmp->begin(),ids2Tmp->end());
3317       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids1=famArr->getIdsEqual(*famId);
3318       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(ids1->buildSubstractionOptimized(ids2));
3319       if(ret0->empty())
3320         {
3321           bool isFamPresent=false;
3322           for(std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::const_iterator itl=allFamIds.begin();itl!=allFamIds.end() && !isFamPresent;itl++)
3323             isFamPresent=(*itl)->presenceOfValue(*famId);
3324           if(!isFamPresent)
3325             { familyIds.push_back(*famId); idsPerfamiliyIds.push_back(ret0); fams.push_back(FindOrCreateAndGiveFamilyWithId(families,*famId,created)); } // adding *famId in grp
3326           else
3327             {
3328               familyIds.push_back(isNodeGroup?maxVal:-maxVal); idsPerfamiliyIds.push_back(ids2);
3329               std::string locFamName=FindOrCreateAndGiveFamilyWithId(families,isNodeGroup?maxVal:-maxVal,created);
3330               fams.push_back(locFamName);
3331               if(existsFamily(*famId))
3332                 {
3333                   std::string locFamName2=getFamilyNameGivenId(*famId); std::vector<std::string> v(2); v[0]=locFamName2; v[1]=locFamName;
3334                   ChangeAllGroupsContainingFamily(groups,getFamilyNameGivenId(*famId).c_str(),v);
3335                 }
3336               maxVal++;
3337             } // modifying all other groups on *famId to lie on maxVal and lie the grp on maxVal
3338         }
3339       else
3340         {
3341           familyIds.push_back(isNodeGroup?maxVal:-maxVal); idsPerfamiliyIds.push_back(ret0); // modifying all other groups on *famId to lie on maxVal and on maxVal+1
3342           familyIds.push_back(isNodeGroup?maxVal+1:-maxVal-1); idsPerfamiliyIds.push_back(ids2);//grp lie only on maxVal+1
3343           std::string n2(FindOrCreateAndGiveFamilyWithId(families,isNodeGroup?maxVal+1:-maxVal-1,created)); fams.push_back(n2);
3344           if(existsFamily(*famId))
3345             {
3346               std::string n1(FindOrCreateAndGiveFamilyWithId(families,isNodeGroup?maxVal:-maxVal,created)); std::vector<std::string> v(2); v[0]=n1; v[1]=n2;
3347               ChangeAllGroupsContainingFamily(groups,getFamilyNameGivenId(*famId).c_str(),v);
3348             }
3349           maxVal+=2;
3350         }
3351     }
3352   for(std::size_t i=0;i<familyIds.size();i++)
3353     {
3354       DataArrayInt *da=idsPerfamiliyIds[i];
3355       famArr->setPartOfValuesSimple3(familyIds[i],da->begin(),da->end(),0,1,1);
3356     }
3357   _families=families;
3358   _groups=groups;
3359   _groups[grpName]=fams;
3360 }
3361
3362 /*!
3363  * Changes a name of a family specified by its id.
3364  *  \param [in] id - the id of the family of interest.
3365  *  \param [in] newFamName - the new family name.
3366  *  \throw If no family with the given \a id exists.
3367  */
3368 void MEDFileUMesh::setFamilyNameAttachedOnId(int id, const std::string& newFamName) throw(INTERP_KERNEL::Exception)
3369 {
3370   std::string oldName=getFamilyNameGivenId(id);
3371   _families.erase(oldName);
3372   _families[newFamName]=id;
3373 }
3374
3375 /*!
3376  * Removes a mesh of a given dimension.
3377  *  \param [in] meshDimRelToMax - the relative dimension of interest.
3378  *  \throw If there is no mesh at level \a meshDimRelToMax in \a this mesh.
3379  */
3380 void MEDFileUMesh::removeMeshAtLevel(int meshDimRelToMax) throw(INTERP_KERNEL::Exception)
3381 {
3382   std::vector<int> levSet=getNonEmptyLevels();
3383   std::vector<int>::const_iterator it=std::find(levSet.begin(),levSet.end(),meshDimRelToMax);
3384   if(it==levSet.end())
3385     throw INTERP_KERNEL::Exception("MEDFileUMesh::removeMeshAtLevel : the requested level is not existing !");
3386   int pos=(-meshDimRelToMax);
3387   _ms[pos]=0;
3388 }
3389
3390 /*!
3391  * Sets a new MEDCouplingUMesh at a given level in \a this mesh.
3392  *  \param [in] meshDimRelToMax - a relative level to set the mesh at.
3393  *  \param [in] m - the new mesh to set.
3394  *  \param [in] newOrOld - if \c true, cells in \a m are sorted by type to be ready for 
3395  *         writing \a this mesh in a MED file.
3396  *  \throw If the name or the description of \a this mesh and \a m are not empty and are
3397  *         different. 
3398  *  \throw If the node coordinates array is set \a this in mesh and \a m refers to
3399  *         another node coordinates array.
3400  *  \throw If the mesh dimension of \a m does not correspond to \a meshDimRelToMax or
3401  *         to the existing meshes of other levels of \a this mesh.
3402  */
3403 void MEDFileUMesh::setMeshAtLevel(int meshDimRelToMax, MEDCouplingUMesh *m, bool newOrOld) throw(INTERP_KERNEL::Exception)
3404 {
3405   dealWithTinyInfo(m);
3406   std::vector<int> levSet=getNonEmptyLevels();
3407   if(std::find(levSet.begin(),levSet.end(),meshDimRelToMax)==levSet.end())
3408     {
3409       if((DataArrayDouble *)_coords==0)
3410         {
3411           DataArrayDouble *c=m->getCoords();
3412           if(c)
3413             c->incrRef();
3414           _coords=c;
3415         }
3416       if(m->getCoords()!=_coords)
3417         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshAtLevel : Invalid Given Mesh ! The coordinates are not the same ! try to use tryToShareSameCoords !");
3418       int sz=(-meshDimRelToMax)+1;
3419       if(sz>=(int)_ms.size())
3420         _ms.resize(sz);
3421       checkMeshDimCoherency(m->getMeshDimension(),meshDimRelToMax);
3422       _ms[sz-1]=new MEDFileUMeshSplitL1(m,newOrOld);
3423     }
3424   else
3425     _ms[-meshDimRelToMax]=new MEDFileUMeshSplitL1(m,newOrOld);
3426 }
3427
3428 /*!
3429  * Creates one MEDCouplingUMesh at a given level in \a this mesh from a sequence of
3430  * meshes each representing a group, and creates corresponding groups in \a this mesh.
3431  * The given meshes must share the same node coordinates array.
3432  *  \param [in] meshDimRelToMax - the relative dimension to create the mesh and groups at.
3433  *  \param [in] ms - the sequence of meshes. Each mesh in \a ms represents a group to
3434  *          create in \a this mesh.
3435  *  \throw If \a ms is empty.
3436  *  \throw If dimension of meshes in \a ms does not correspond to \a meshDimRelToMax or
3437  *         to the existing meshes of other levels of \a this mesh.
3438  *  \throw If the meshes in \a ms do not share the same node coordinates array.
3439  *  \throw If the node coordinates array of \a this mesh (if any) is not the same as that
3440  *         of the given meshes.
3441  *  \throw If \a ms[ i ] is not well defined (MEDCouplingUMesh::checkCoherency()).
3442  *  \throw If names of some meshes in \a ms are equal.
3443  *  \throw If \a ms includes a mesh with an empty name.
3444  */
3445 void MEDFileUMesh::setGroupsFromScratch(int meshDimRelToMax, const std::vector<const MEDCouplingUMesh *>& ms, bool renum) throw(INTERP_KERNEL::Exception)
3446 {
3447   if(ms.empty())
3448     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsFromScratch : expecting a non empty vector !");
3449   int sz=(-meshDimRelToMax)+1;
3450   if(sz>=(int)_ms.size())
3451     _ms.resize(sz);
3452   checkMeshDimCoherency(ms[0]->getMeshDimension(),meshDimRelToMax);
3453   DataArrayDouble *coo=checkMultiMesh(ms);
3454   if((DataArrayDouble *)_coords==0)
3455     {
3456       coo->incrRef();
3457       _coords=coo;
3458     }
3459   else
3460     if((DataArrayDouble *)_coords!=coo)
3461       throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsFromScratch : coordinates mismatches !");
3462   std::vector<DataArrayInt *> corr;
3463   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MEDCouplingUMesh::FuseUMeshesOnSameCoords(ms,_zipconn_pol,corr);
3464   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > corr3(corr.begin(),corr.end());
3465   setMeshAtLevel(meshDimRelToMax,m,renum);
3466   std::vector<const DataArrayInt *> corr2(corr.begin(),corr.end());
3467   setGroupsAtLevel(meshDimRelToMax,corr2,true);
3468 }
3469
3470 /*!
3471  * Creates groups at a given level in \a this mesh from a sequence of
3472  * meshes each representing a group.
3473  * The given meshes must share the same node coordinates array.
3474  *  \param [in] meshDimRelToMax - the relative dimension to create the groups at.
3475  *  \param [in] ms - the sequence of meshes. Each mesh in \a ms represents a group to
3476  *         create in \a this mesh.
3477  *  \param [in] renum - if \c true, then the optional numbers of entities are taken into
3478  *         account. 
3479  *  \throw If \a ms is empty.
3480  *  \throw If dimension of meshes in \a ms does not correspond to \a meshDimRelToMax or
3481  *         to the existing meshes of other levels of \a this mesh.
3482  *  \throw If the meshes in \a ms do not share the same node coordinates array.
3483  *  \throw If the node coordinates array of \a this mesh (if any) is not the same as that
3484  *         of the given meshes.
3485  *  \throw If \a ms[ i ] is not well defined (MEDCouplingUMesh::checkCoherency()).
3486  *  \throw If names of some meshes in \a ms are equal.
3487  *  \throw If \a ms includes a mesh with an empty name.
3488  */
3489 void MEDFileUMesh::setGroupsOnSetMesh(int meshDimRelToMax, const std::vector<const MEDCouplingUMesh *>& ms, bool renum) throw(INTERP_KERNEL::Exception)
3490 {
3491   if(ms.empty())
3492     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsOnSetMesh : expecting a non empty vector !");
3493   int sz=(-meshDimRelToMax)+1;
3494   if(sz>=(int)_ms.size())
3495     _ms.resize(sz);
3496   checkMeshDimCoherency(ms[0]->getMeshDimension(),meshDimRelToMax);
3497   DataArrayDouble *coo=checkMultiMesh(ms);
3498   if((DataArrayDouble *)_coords==0)
3499     {
3500       coo->incrRef();
3501       _coords=coo;
3502     }
3503   else
3504     if((DataArrayDouble *)_coords!=coo)
3505       throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsOnSetMesh : coordinates mismatches !");
3506   MEDCouplingUMesh *m=getMeshAtLevel(meshDimRelToMax,renum);
3507   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > corr(ms.size());
3508   int i=0;
3509   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++,i++)
3510     {
3511       DataArrayInt *arr=0;
3512       bool test=m->areCellsIncludedIn(*it,_zipconn_pol,arr);
3513       corr[i]=arr;
3514       if(!test)
3515         {
3516           std::ostringstream oss; oss << "MEDFileUMesh::setGroupsOnSetMesh : mesh #" << i << " is not part of whole mesh !";
3517           throw INTERP_KERNEL::Exception(oss.str().c_str());
3518         }
3519     }
3520   std::vector<const DataArrayInt *> corr2(corr.begin(),corr.end());
3521   setGroupsAtLevel(meshDimRelToMax,corr2,renum);
3522 }
3523
3524 DataArrayDouble *MEDFileUMesh::checkMultiMesh(const std::vector<const MEDCouplingUMesh *>& ms) const throw(INTERP_KERNEL::Exception)
3525 {
3526   const DataArrayDouble *ret=ms[0]->getCoords();
3527   int mdim=ms[0]->getMeshDimension();
3528   for(unsigned int i=1;i<ms.size();i++)
3529     {
3530       ms[i]->checkCoherency();
3531       if(ms[i]->getCoords()!=ret)
3532         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMultiMesh : meshes must share the same coords !");
3533       if(ms[i]->getMeshDimension()!=mdim)
3534         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMultiMesh : meshes have not same mesh dimension !");
3535     }
3536   return const_cast<DataArrayDouble *>(ret);
3537 }
3538
3539 /*!
3540  * Sets the family field of a given relative dimension.
3541  *  \param [in] meshDimRelToMaxExt - the relative dimension of entities for which
3542  *          the family field is set.
3543  *  \param [in] famArr - the array of the family field.
3544  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3545  *  \throw If \a famArr has an invalid size.
3546  */
3547 void MEDFileUMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr) throw(INTERP_KERNEL::Exception)
3548 {
3549   if(meshDimRelToMaxExt==1)
3550     {
3551       if(!famArr)
3552         {
3553           _fam_coords=0;
3554           return ;
3555         }
3556       DataArrayDouble *coo(_coords);
3557       if(!coo)
3558         throw INTERP_KERNEL::Exception("MEDFileUMesh::setFamilyFieldArr : the coordinates have not been set !");
3559       famArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),1,"MEDFileUMesh::setFamilyFieldArr : Problem in size of node family arr ! ");
3560       famArr->incrRef();
3561       _fam_coords=famArr;
3562       return ;
3563     }
3564   if(meshDimRelToMaxExt>1)
3565     throw INTERP_KERNEL::Exception("MEDFileUMesh::setFamilyFieldArr : Dimension request is invalid (>1) !");
3566   int traducedRk=-meshDimRelToMaxExt;
3567   if(traducedRk>=(int)_ms.size())
3568     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
3569   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
3570     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3571   return _ms[traducedRk]->setFamilyArr(famArr);
3572 }
3573
3574 /*!
3575  * Sets the optional numbers of mesh entities of a given dimension.
3576  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
3577  *  \param [in] renumArr - the array of the numbers.
3578  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3579  *  \throw If \a renumArr has an invalid size.
3580  */
3581 void MEDFileUMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr) throw(INTERP_KERNEL::Exception)
3582 {
3583   if(meshDimRelToMaxExt==1)
3584     {
3585       if(!renumArr)
3586         {
3587           _num_coords=0;
3588           _rev_num_coords=0;
3589           return ;
3590         }
3591       DataArrayDouble *coo(_coords);
3592       if(!coo)
3593         throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumFieldArr : the coordinates have not been set !");
3594       renumArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),1,"MEDFileUMesh::setRenumArr : Problem in size of node numbering arr ! ");
3595       renumArr->incrRef();
3596       _num_coords=renumArr;
3597       computeRevNum();
3598       return ;
3599     }
3600   if(meshDimRelToMaxExt>1)
3601     throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumArr : Dimension request is invalid (>1) !");
3602   int traducedRk=-meshDimRelToMaxExt;
3603   if(traducedRk>=(int)_ms.size())
3604     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
3605   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
3606     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3607   return _ms[traducedRk]->setRenumArr(renumArr);
3608 }
3609
3610 /*!
3611  * Sets the optional names of mesh entities of a given dimension.
3612  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
3613  *  \param [in] nameArr - the array of the names.
3614  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3615  *  \throw If \a nameArr has an invalid size.
3616  */
3617 void MEDFileUMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr) throw(INTERP_KERNEL::Exception)
3618 {
3619   if(meshDimRelToMaxExt==1)
3620     {
3621       if(!nameArr)
3622         {
3623           _name_coords=0;
3624           return ;
3625         }
3626       DataArrayDouble *coo(_coords);
3627       if(!coo)
3628         throw INTERP_KERNEL::Exception("MEDFileUMesh::setNameFieldAtLevel : the coordinates have not been set !");
3629       nameArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),MED_SNAME_SIZE,"MEDFileUMesh::setNameFieldAtLevel : Problem in size of node numbering arr ! ");
3630       nameArr->incrRef();
3631       _name_coords=nameArr;
3632       return ;
3633     }
3634   if(meshDimRelToMaxExt>1)
3635     throw INTERP_KERNEL::Exception("MEDFileUMesh::setNameFieldAtLevel : Dimension request is invalid (>1) !");
3636   int traducedRk=-meshDimRelToMaxExt;
3637   if(traducedRk>=(int)_ms.size())
3638     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
3639   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
3640     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3641   return _ms[traducedRk]->setNameArr(nameArr);
3642 }
3643
3644 void MEDFileUMesh::synchronizeTinyInfoOnLeaves() const
3645 {
3646   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
3647     if((const MEDFileUMeshSplitL1 *)(*it))
3648       (*it)->synchronizeTinyInfo(*this);
3649 }
3650
3651 /*!
3652  * This method is called by MEDFileMesh::changeFamilyId. It performs only one part of the family id modification.
3653  */
3654 void MEDFileUMesh::changeFamilyIdArr(int oldId, int newId) throw(INTERP_KERNEL::Exception)
3655 {
3656   DataArrayInt *arr=_fam_coords;
3657   if(arr)
3658     arr->changeValue(oldId,newId);
3659   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
3660     {
3661       MEDFileUMeshSplitL1 *sp=(*it);
3662       if(sp)
3663         {
3664           sp->changeFamilyIdArr(oldId,newId);
3665         }
3666     }
3667 }
3668
3669 std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > MEDFileUMesh::getAllNonNullFamilyIds() const
3670 {
3671   std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret;
3672   const DataArrayInt *da(_fam_coords);
3673   if(da)
3674     { da->incrRef(); ret.push_back(MEDCouplingAutoRefCountObjectPtr<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
3675   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
3676     {
3677       const MEDFileUMeshSplitL1 *elt(*it);
3678       if(elt)
3679         {
3680           da=elt->getFamilyField();
3681           if(da)
3682             { da->incrRef(); ret.push_back(MEDCouplingAutoRefCountObjectPtr<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
3683         }
3684     }
3685   return ret;
3686 }
3687
3688 void MEDFileUMesh::computeRevNum() const
3689 {
3690   if((const DataArrayInt *)_num_coords)
3691     {
3692       int pos;
3693       int maxValue=_num_coords->getMaxValue(pos);
3694       _rev_num_coords=_num_coords->invertArrayN2O2O2N(maxValue+1);
3695     }
3696 }
3697
3698 std::size_t MEDFileStructuredMesh::getHeapMemorySize() const
3699 {
3700   std::size_t ret=MEDFileMesh::getHeapMemorySize();
3701   if((const DataArrayInt*)_fam_nodes)
3702     ret+=_fam_nodes->getHeapMemorySize();
3703   if((const DataArrayInt*)_num_nodes)
3704     ret+=_num_nodes->getHeapMemorySize();
3705   if((const DataArrayInt*)_fam_cells)
3706     ret+=_fam_cells->getHeapMemorySize();
3707   if((const DataArrayInt*)_num_cells)
3708     ret+=_num_cells->getHeapMemorySize();
3709   if((const DataArrayInt*)_rev_num_nodes)
3710     ret+=_rev_num_nodes->getHeapMemorySize();
3711   if((const DataArrayInt*)_rev_num_cells)
3712     ret+=_rev_num_cells->getHeapMemorySize();
3713   return ret;
3714 }
3715
3716 int MEDFileStructuredMesh::getMaxAbsFamilyIdInArrays() const throw(INTERP_KERNEL::Exception)
3717 {
3718   int ret=-std::numeric_limits<int>::max(),tmp=-1;
3719   if((const DataArrayInt *)_fam_nodes)
3720     {
3721       int val=_fam_nodes->getMaxValue(tmp);
3722       ret=std::max(ret,std::abs(val));
3723     }
3724   if((const DataArrayInt *)_fam_cells)
3725     {
3726       int val=_fam_cells->getMaxValue(tmp);
3727       ret=std::max(ret,std::abs(val));
3728     }
3729   return ret;
3730 }
3731
3732 int MEDFileStructuredMesh::getMaxFamilyIdInArrays() const throw(INTERP_KERNEL::Exception)
3733 {
3734   int ret=-std::numeric_limits<int>::max(),tmp=-1;
3735   if((const DataArrayInt *)_fam_nodes)
3736     {
3737       int val=_fam_nodes->getMaxValue(tmp);
3738       ret=std::max(ret,val);
3739     }
3740   if((const DataArrayInt *)_fam_cells)
3741     {
3742       int val=_fam_cells->getMaxValue(tmp);
3743       ret=std::max(ret,val);
3744     }
3745   return ret;
3746 }
3747
3748 int MEDFileStructuredMesh::getMinFamilyIdInArrays() const throw(INTERP_KERNEL::Exception)
3749 {
3750   int ret=std::numeric_limits<int>::max(),tmp=-1;
3751   if((const DataArrayInt *)_fam_nodes)
3752     {
3753       int val=_fam_nodes->getMinValue(tmp);
3754       ret=std::min(ret,val);
3755     }
3756   if((const DataArrayInt *)_fam_cells)
3757     {
3758       int val=_fam_cells->getMinValue(tmp);
3759       ret=std::min(ret,val);
3760     }
3761   return ret;
3762 }
3763
3764 bool MEDFileStructuredMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
3765 {
3766   if(!MEDFileMesh::isEqual(other,eps,what))
3767     return false;
3768   const MEDFileStructuredMesh *otherC=dynamic_cast<const  MEDFileStructuredMesh *>(other);
3769   if(!otherC)
3770     {
3771       what="Mesh types differ ! This is structured and other is NOT !";
3772       return false;
3773     }
3774   const DataArrayInt *famc1=_fam_nodes;
3775   const DataArrayInt *famc2=otherC->_fam_nodes;
3776   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
3777     {
3778       what="Mismatch of families arr on nodes ! One is defined and not other !";
3779       return false;
3780     }
3781   if(famc1)
3782     {
3783       bool ret=famc1->isEqual(*famc2);
3784       if(!ret)
3785         {
3786           what="Families arr on nodes differ !";
3787           return false;
3788         }
3789     }
3790   famc1=_fam_cells;
3791   famc2=otherC->_fam_cells;
3792   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
3793     {
3794       what="Mismatch of families arr on cells ! One is defined and not other !";
3795       return false;
3796     }
3797   if(famc1)
3798     {
3799       bool ret=famc1->isEqual(*famc2);
3800       if(!ret)
3801         {
3802           what="Families arr on cells differ !";
3803           return false;
3804         }
3805     }
3806   famc1=_num_nodes;
3807   famc2=otherC->_num_nodes;
3808   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
3809     {
3810       what="Mismatch of numbering arr on nodes ! One is defined and not other !";
3811       return false;
3812     }
3813   if(famc1)
3814     {
3815       bool ret=famc1->isEqual(*famc2);
3816       if(!ret)
3817         {
3818           what="Numbering arr on nodes differ !";
3819           return false;
3820         }
3821     }
3822   famc1=_num_cells;
3823   famc2=otherC->_num_cells;
3824   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
3825     {
3826       what="Mismatch of numbering arr on cells ! One is defined and not other !";
3827       return false;
3828     }
3829   if(famc1)
3830     {
3831       bool ret=famc1->isEqual(*famc2);
3832       if(!ret)
3833         {
3834           what="Numbering arr on cells differ !";
3835           return false;
3836         }
3837     }
3838   const DataArrayAsciiChar *d1=_names_cells;
3839   const DataArrayAsciiChar *d2=otherC->_names_cells;
3840   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
3841     {
3842       what="Mismatch of naming arr on cells ! One is defined and not other !";
3843       return false;
3844     }
3845   if(d1)
3846     {
3847       bool ret=d1->isEqual(*d2);
3848       if(!ret)
3849         {
3850           what="Naming arr on cells differ !";
3851           return false;
3852         }
3853     }
3854   d1=_names_nodes;
3855   d2=otherC->_names_nodes;
3856   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
3857     {
3858       what="Mismatch of naming arr on nodes ! One is defined and not other !";
3859       return false;
3860     }
3861   if(d1)
3862     {
3863       bool ret=d1->isEqual(*d2);
3864       if(!ret)
3865         {
3866           what="Naming arr on nodes differ !";
3867           return false;
3868         }
3869     }
3870   return true;
3871 }
3872
3873 void MEDFileStructuredMesh::clearNonDiscrAttributes() const
3874 {
3875   MEDFileMesh::clearNonDiscrAttributes();
3876   const DataArrayInt *tmp=_fam_nodes;
3877   if(tmp)
3878     (const_cast<DataArrayInt *>(tmp))->setName("");
3879   tmp=_num_nodes;
3880   if(tmp)
3881     (const_cast<DataArrayInt *>(tmp))->setName("");
3882   tmp=_fam_cells;
3883   if(tmp)
3884     (const_cast<DataArrayInt *>(tmp))->setName("");
3885   tmp=_num_cells;
3886   if(tmp)
3887     (const_cast<DataArrayInt *>(tmp))->setName("");
3888 }
3889
3890 /*!
3891  * Returns ids of mesh entities contained in given families of a given dimension.
3892  *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
3893  *          are required.
3894  *  \param [in] fams - the names of the families of interest.
3895  *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
3896  *          returned instead of ids.
3897  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
3898  *          numbers, if available and required, of mesh entities of the families. The caller
3899  *          is to delete this array using decrRef() as it is no more needed. 
3900  *  \throw If the family field is missing for \a meshDimRelToMaxExt.
3901  */
3902 DataArrayInt *MEDFileStructuredMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const throw(INTERP_KERNEL::Exception)
3903 {
3904   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
3905     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : Only available for levels 0 or 1 !");
3906   std::vector<int> famIds=getFamiliesIds(fams);
3907   if(meshDimRelToMaxExt==1)
3908     {
3909       if((const DataArrayInt *)_fam_nodes)
3910         {
3911           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
3912           if(!famIds.empty())
3913             da=_fam_nodes->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
3914           else
3915             da=_fam_nodes->getIdsEqualList(0,0);
3916           if(renum)
3917             return MEDFileUMeshSplitL1::Renumber(_num_nodes,da);
3918           else
3919             return da.retn();
3920         }
3921       else
3922         throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on nodes !");
3923     }
3924   else
3925     {
3926       if((const DataArrayInt *)_fam_cells)
3927         {
3928           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
3929           if(!famIds.empty())
3930             da=_fam_cells->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
3931           else
3932             da=_fam_cells->getIdsEqualList(0,0);
3933           if(renum)
3934             return MEDFileUMeshSplitL1::Renumber(_num_cells,da);
3935           else
3936             return da.retn();
3937         }
3938       else
3939         throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on cells !");
3940     }
3941 }
3942
3943 /*!
3944  * Sets the family field of a given relative dimension.
3945  *  \param [in] meshDimRelToMaxExt - the relative dimension of entities for which
3946  *          the family field is set.
3947  *  \param [in] famArr - the array of the family field.
3948  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3949  *  \throw If \a famArr has an invalid size.
3950  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
3951  */
3952 void MEDFileStructuredMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr) throw(INTERP_KERNEL::Exception)
3953 {
3954   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
3955     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : Only available for levels 0 or 1 !");
3956   const MEDCouplingStructuredMesh *mesh=getStructuredMesh();
3957   if(!mesh)
3958     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setFamilyFieldArr : no structured mesh specified ! Impossible to set family array !");
3959   if(meshDimRelToMaxExt==0)
3960     {
3961       int nbCells=mesh->getNumberOfCells();
3962       famArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of cells of mesh !");
3963       _fam_cells=famArr;
3964     }
3965   else
3966     {
3967       int nbNodes=mesh->getNumberOfNodes();
3968       famArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !");
3969       _fam_nodes=famArr;
3970     }
3971   if(famArr)
3972     famArr->incrRef();
3973 }
3974
3975 /*!
3976  * Sets the optional numbers of mesh entities of a given dimension.
3977  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
3978  *  \param [in] renumArr - the array of the numbers.
3979  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3980  *  \throw If \a renumArr has an invalid size.
3981  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
3982  */
3983 void MEDFileStructuredMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr) throw(INTERP_KERNEL::Exception)
3984 {
3985   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
3986     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : Only available for levels 0 or 1 !");
3987   const MEDCouplingStructuredMesh *mesh=getStructuredMesh();
3988   if(!mesh)
3989     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : no structured mesh specified ! Impossible to set number array !");
3990   if(meshDimRelToMaxExt==0)
3991     {
3992       int nbCells=mesh->getNumberOfCells();
3993       renumArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Renum arr ! Mismatch with number of cells of mesh !");
3994       _num_cells=renumArr;
3995     }
3996   else
3997     {
3998       int nbNodes=mesh->getNumberOfNodes();
3999       renumArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !");
4000       _num_nodes=renumArr;
4001     }
4002   if(renumArr)
4003     renumArr->incrRef();
4004 }
4005
4006 /*!
4007  * Sets the optional names of mesh entities of a given dimension.
4008  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4009  *  \param [in] nameArr - the array of the names.
4010  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4011  *  \throw If \a nameArr has an invalid size.
4012  */
4013 void MEDFileStructuredMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr) throw(INTERP_KERNEL::Exception)
4014 {
4015   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4016     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : Only available for levels 0 or 1 !");
4017   const MEDCouplingStructuredMesh *mesh=getStructuredMesh();
4018   if(!mesh)
4019     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : no structured mesh specified ! Impossible to set names array !");
4020   if(meshDimRelToMaxExt==0)
4021     {
4022       int nbCells=mesh->getNumberOfCells();
4023       nameArr->checkNbOfTuplesAndComp(nbCells,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of cells of mesh !");
4024       _names_cells=nameArr;
4025     }
4026   else
4027     {
4028       int nbNodes=mesh->getNumberOfNodes();
4029       nameArr->checkNbOfTuplesAndComp(nbNodes,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of nodes of mesh !");
4030       _names_nodes=nameArr;
4031     }
4032   if(nameArr)
4033     nameArr->incrRef();
4034 }
4035
4036 /*!
4037  * Returns the family field for mesh entities of a given dimension.
4038  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4039  *  \return const DataArrayInt * - the family field. It is an array of ids of families
4040  *          each mesh entity belongs to. It can be \c NULL.
4041  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
4042  */
4043 const DataArrayInt *MEDFileStructuredMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
4044 {
4045   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4046     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamilyFieldAtLevel : Only available for levels 0 or 1 !");
4047   if(meshDimRelToMaxExt==0)
4048     return _fam_cells;
4049   else
4050     return _fam_nodes;
4051 }
4052
4053 /*!
4054  * Returns the optional numbers of mesh entities of a given dimension.
4055  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4056  *  \return const DataArrayInt * - the array of the entity numbers.
4057  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4058  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
4059  */
4060 const DataArrayInt *MEDFileStructuredMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
4061 {
4062   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4063     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberFieldAtLevel : Only available for levels 0 or 1 !");
4064   if(meshDimRelToMaxExt==0)
4065     return _num_cells;
4066   else
4067     return _num_nodes;
4068 }
4069
4070 /*!
4071  * Returns the optional numbers of mesh entities of a given dimension transformed using
4072  * DataArrayInt::invertArrayN2O2O2N().
4073  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4074  *  \return const DataArrayInt * - the array of the entity numbers transformed using
4075  *          DataArrayInt::invertArrayN2O2O2N().
4076  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
4077  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4078  */
4079 const DataArrayInt *MEDFileStructuredMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
4080 {
4081   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4082     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getRevNumberFieldAtLevel : Only available for levels 0 or 1 !");
4083   if(meshDimRelToMaxExt==0)
4084     {
4085       if((const DataArrayInt *)_num_cells)
4086         {
4087           int pos;
4088           int maxValue=_num_cells->getMaxValue(pos);
4089           _rev_num_cells=_num_cells->invertArrayN2O2O2N(maxValue+1);
4090           return _rev_num_cells;
4091         }
4092       else
4093         throw INTERP_KERNEL::Exception("MEDFileCMesh::getRevNumberFieldAtLevel : no cell renumbering for a request on reverse numbering !");
4094     }
4095   else
4096     {
4097       if((const DataArrayInt *)_num_nodes)
4098         {
4099           int pos;
4100           int maxValue=_num_nodes->getMaxValue(pos);
4101           _rev_num_nodes=_num_nodes->invertArrayN2O2O2N(maxValue+1);
4102           return _rev_num_nodes;
4103         }
4104       else
4105         throw INTERP_KERNEL::Exception("MEDFileCMesh::getRevNumberFieldAtLevel : no node renumbering for a request on reverse numbering !");
4106     }
4107 }
4108
4109 const DataArrayAsciiChar *MEDFileStructuredMesh::getNameFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
4110 {
4111   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4112     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNameFieldAtLevel : Only available for levels 0 or 1 !");
4113   if(meshDimRelToMaxExt==0)
4114     return _names_cells;
4115   else
4116     return _names_nodes;
4117 }
4118
4119 /*!
4120  * Returns relative dimensions of mesh entities (excluding nodes) present in \a this mesh.
4121  *  \return std::vector<int> - a sequence of the relative dimensions: [0].
4122  */
4123 std::vector<int> MEDFileStructuredMesh::getNonEmptyLevels() const
4124 {
4125   std::vector<int> ret(1);
4126   return ret;
4127 }
4128
4129 /*!
4130  * Returns relative dimensions of mesh entities (including nodes) present in \a this mesh.
4131  *  \return std::vector<int> - a sequence of the relative dimensions: [1,0].
4132  */
4133 std::vector<int> MEDFileStructuredMesh::getNonEmptyLevelsExt() const
4134 {
4135   std::vector<int> ret(2);
4136   ret[0]=1;
4137   return ret;
4138 }
4139
4140 /*!
4141  * Returns the set of extensive levels (nodes included) where not NULL family arr are defined.
4142  */
4143 std::vector<int> MEDFileStructuredMesh::getFamArrNonEmptyLevelsExt() const
4144 {
4145   std::vector<int> ret;
4146   const DataArrayInt *famNodes(_fam_nodes),*famCells(_fam_cells);
4147   if(famNodes)
4148     ret.push_back(1);
4149   if(famCells)
4150     ret.push_back(0);
4151   return ret;
4152 }
4153
4154 /*!
4155  * Returns the set of extensive levels (nodes included) where not NULL numbering arr are defined.
4156  */
4157 std::vector<int> MEDFileStructuredMesh::getNumArrNonEmptyLevelsExt() const
4158 {
4159   std::vector<int> ret;
4160   const DataArrayInt *numNodes(_num_nodes),*numCells(_num_cells);
4161   if(numNodes)
4162     ret.push_back(1);
4163   if(numCells)
4164     ret.push_back(0);
4165   return ret;
4166 }
4167
4168 /*!
4169  * Returns the set of extensive levels (nodes included) where not NULL naming arr are defined.
4170  */
4171 std::vector<int> MEDFileStructuredMesh::getNameArrNonEmptyLevelsExt() const
4172 {
4173   std::vector<int> ret;
4174   const DataArrayAsciiChar *namesCells(_names_cells);
4175   if(namesCells)
4176     ret.push_back(0);
4177   return ret;
4178 }
4179
4180 /*!
4181  * no implementation here, it is not a bug, but intresically no polyhedra in \a this.
4182  */
4183 bool MEDFileStructuredMesh::unPolyze(std::vector<int>& oldCode, std::vector<int>& newCode, DataArrayInt *& o2nRenumCell) throw(INTERP_KERNEL::Exception)
4184 {
4185   oldCode.clear(); newCode.clear(); o2nRenumCell=0;
4186   return false;
4187 }
4188
4189 void MEDFileStructuredMesh::changeFamilyIdArr(int oldId, int newId) throw(INTERP_KERNEL::Exception)
4190 {
4191   DataArrayInt *arr=_fam_nodes;
4192   if(arr)
4193     arr->changeValue(oldId,newId);
4194   arr=_fam_cells;
4195   if(arr)
4196     arr->changeValue(oldId,newId);
4197 }
4198
4199 void MEDFileStructuredMesh::deepCpyAttributes() throw(INTERP_KERNEL::Exception)
4200 {
4201   if((const DataArrayInt*)_fam_nodes)
4202     _fam_nodes=_fam_nodes->deepCpy();
4203   if((const DataArrayInt*)_num_nodes)
4204     _num_nodes=_num_nodes->deepCpy();
4205   if((const DataArrayInt*)_fam_cells)
4206     _fam_cells=_fam_cells->deepCpy();
4207   if((const DataArrayInt*)_num_cells)
4208     _num_cells=_num_cells->deepCpy();
4209   if((const DataArrayInt*)_rev_num_nodes)
4210     _rev_num_nodes=_rev_num_nodes->deepCpy();
4211   if((const DataArrayInt*)_rev_num_cells)
4212     _rev_num_cells=_rev_num_cells->deepCpy();
4213 }
4214
4215 /*!
4216  * Returns a pointer to mesh at the specified level (here 0 is compulsary for cartesian mesh).
4217  * 
4218  * \return a pointer to cartesian mesh that need to be managed by the caller.
4219  * \warning the returned pointer has to be managed by the caller.
4220  */
4221
4222 /*!
4223  * Returns a pointer to MEDCouplingStructuredMesh held by \a this. 
4224  *  \param [in] meshDimRelToMax - it must be \c 0.
4225  *  \param [in] renum - it must be \c false.
4226  *  \return MEDCouplingMesh * - a pointer to MEDCouplingMesh that the caller is to
4227  *          delete using decrRef() as it is no more needed. 
4228  */
4229 MEDCouplingMesh *MEDFileStructuredMesh::getGenMeshAtLevel(int meshDimRelToMax, bool renum) const throw(INTERP_KERNEL::Exception)
4230 {
4231   if(renum)
4232     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support renumbering ! To do it perform request of renum array directly !");
4233   if(meshDimRelToMax!=0)
4234     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support multi level for mesh 0 expected as input !");
4235   const MEDCouplingStructuredMesh *m=getStructuredMesh();
4236   if(m)
4237     m->incrRef();
4238   return const_cast<MEDCouplingStructuredMesh *>(m);
4239 }
4240
4241 /*!
4242  * Returns number of mesh entities of a given relative dimension in \a this mesh.
4243  *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
4244  *  \return int - the number of entities.
4245  *  \throw If no mesh entities of dimension \a meshDimRelToMaxExt are available in \a this mesh.
4246  */
4247 int MEDFileStructuredMesh::getSizeAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
4248 {
4249   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4250     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : Only available for levels 0 or 1 !");
4251   const MEDCouplingStructuredMesh *cmesh=getStructuredMesh();
4252   if(!cmesh)
4253     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : No structured mesh set !");
4254   if(meshDimRelToMaxExt==0)
4255     return cmesh->getNumberOfCells();
4256   else
4257     return cmesh->getNumberOfNodes();
4258 }
4259
4260 int MEDFileStructuredMesh::getNumberOfNodes() const throw(INTERP_KERNEL::Exception)
4261 {
4262   const MEDCouplingStructuredMesh *cmesh=getStructuredMesh();
4263   if(!cmesh)
4264     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberOfNodes : no cartesian mesh set !");
4265   return cmesh->getNumberOfNodes();
4266 }
4267
4268 med_geometry_type MEDFileStructuredMesh::GetGeoTypeFromMeshDim(int meshDim) throw(INTERP_KERNEL::Exception)
4269 {
4270   med_geometry_type geoTypeReq=MED_NONE;
4271   switch(meshDim)
4272     {
4273     case 3:
4274       geoTypeReq=MED_HEXA8;
4275       break;
4276     case 2:
4277       geoTypeReq=MED_QUAD4;
4278       break;
4279     case 1:
4280       geoTypeReq=MED_SEG2;
4281       break;
4282     case 0:
4283       geoTypeReq=MED_POINT1;
4284       break;
4285     default:
4286       throw INTERP_KERNEL::Exception("Invalid meshdim detected for structured mesh ! Must be in (1,2,3) !");
4287     }
4288   return geoTypeReq;
4289 }
4290
4291 void MEDFileStructuredMesh::loadStrMeshFromFile(MEDFileStrMeshL2 *strm, med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
4292 {
4293   setName(strm->getName());
4294   setDescription(strm->getDescription());
4295   setUnivName(strm->getUnivName());
4296   setIteration(strm->getIteration());
4297   setOrder(strm->getOrder());
4298   setTimeValue(strm->getTime());
4299   setTimeUnit(strm->getTimeUnit());
4300   MEDFileMeshL2::ReadFamiliesAndGrps(fid,mName,_families,_groups);
4301   med_bool chgt=MED_FALSE,trsf=MED_FALSE;
4302   int nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_NODE,MED_NONE,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf);
4303   if(nbOfElt>0)
4304     {
4305       _fam_nodes=DataArrayInt::New();
4306       _fam_nodes->alloc(nbOfElt,1);
4307       MEDmeshEntityFamilyNumberRd(fid,mName,dt,it,MED_NODE,MED_NONE,_fam_nodes->getPointer());
4308     }
4309   nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_NODE,MED_NONE,MED_NUMBER,MED_NODAL,&chgt,&trsf);
4310   if(nbOfElt>0)
4311     {
4312       _num_nodes=DataArrayInt::New();
4313       _num_nodes->alloc(nbOfElt,1);
4314       MEDmeshEntityNumberRd(fid,mName,dt,it,MED_NODE,MED_NONE,_num_nodes->getPointer());
4315     }
4316   int meshDim=getStructuredMesh()->getMeshDimension();
4317   med_geometry_type geoTypeReq=GetGeoTypeFromMeshDim(meshDim);
4318   nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_CELL,geoTypeReq,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf);
4319   if(nbOfElt>0)
4320     {
4321       _fam_cells=DataArrayInt::New();
4322       _fam_cells->alloc(nbOfElt,1);
4323       MEDmeshEntityFamilyNumberRd(fid,mName,dt,it,MED_CELL,geoTypeReq,_fam_cells->getPointer());
4324     }
4325   nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_CELL,geoTypeReq,MED_NUMBER,MED_NODAL,&chgt,&trsf);
4326   if(nbOfElt>0)
4327     {
4328       _num_cells=DataArrayInt::New();
4329       _num_cells->alloc(nbOfElt,1);
4330       MEDmeshEntityNumberRd(fid,mName,dt,it,MED_CELL,geoTypeReq,_num_cells->getPointer());
4331     }
4332   nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_CELL,geoTypeReq,MED_NAME,MED_NODAL,&chgt,&trsf);
4333   if(nbOfElt>0)
4334     {
4335       _names_cells=DataArrayAsciiChar::New();
4336       _names_cells->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end
4337       MEDmeshEntityNameRd(fid,mName,dt,it,MED_CELL,geoTypeReq,_names_cells->getPointer());
4338       _names_cells->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end
4339     }
4340   nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_NODE,MED_NONE,MED_NAME,MED_NODAL,&chgt,&trsf);
4341   if(nbOfElt>0)
4342     {
4343       _names_nodes=DataArrayAsciiChar::New();
4344       _names_nodes->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end
4345       MEDmeshEntityNameRd(fid,mName,dt,it,MED_NODE,MED_NONE,_names_nodes->getPointer());
4346       _names_nodes->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end
4347     }
4348 }
4349
4350 void MEDFileStructuredMesh::writeStructuredLL(med_idt fid, const char *maa) const throw(INTERP_KERNEL::Exception)
4351 {
4352   int meshDim=getStructuredMesh()->getMeshDimension();
4353   med_geometry_type geoTypeReq=GetGeoTypeFromMeshDim(meshDim);
4354   //
4355   if((const DataArrayInt *)_fam_cells)
4356     MEDmeshEntityFamilyNumberWr(fid,maa,_iteration,_order,MED_CELL,geoTypeReq,_fam_cells->getNumberOfTuples(),_fam_cells->getConstPointer());
4357   if((const DataArrayInt *)_fam_nodes)
4358     MEDmeshEntityFamilyNumberWr(fid,maa,_iteration,_order,MED_NODE,MED_NONE,_fam_nodes->getNumberOfTuples(),_fam_nodes->getConstPointer());
4359   if((const DataArrayInt *)_num_cells)
4360     MEDmeshEntityNumberWr(fid,maa,_iteration,_order,MED_CELL,geoTypeReq,_num_cells->getNumberOfTuples(),_num_cells->getConstPointer());
4361   if((const DataArrayInt *)_num_nodes)
4362     MEDmeshEntityNumberWr(fid,maa,_iteration,_order,MED_NODE,MED_NONE,_num_nodes->getNumberOfTuples(),_num_nodes->getConstPointer());
4363   if((const DataArrayAsciiChar *)_names_cells)
4364     {
4365       if(_names_cells->getNumberOfComponents()!=MED_SNAME_SIZE)
4366         {
4367           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on cells with number of components set to " << MED_SNAME_SIZE;
4368           oss << " ! The array has " << _names_cells->getNumberOfComponents() << " components !";
4369           throw INTERP_KERNEL::Exception(oss.str().c_str());
4370         }
4371       MEDmeshEntityNameWr(fid,maa,_iteration,_order,MED_CELL,geoTypeReq,_names_cells->getNumberOfTuples(),_names_cells->getConstPointer());
4372     }
4373   if((const DataArrayAsciiChar *)_names_nodes)
4374     {
4375       if(_names_nodes->getNumberOfComponents()!=MED_SNAME_SIZE)
4376         {
4377           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on nodes with number of components set to " << MED_SNAME_SIZE;
4378           oss << " ! The array has " << _names_cells->getNumberOfComponents() << " components !";
4379           throw INTERP_KERNEL::Exception(oss.str().c_str());
4380         }
4381       MEDmeshEntityNameWr(fid,maa,_iteration,_order,MED_NODE,MED_NONE,_names_nodes->getNumberOfTuples(),_names_nodes->getConstPointer());
4382     }
4383   //
4384   MEDFileUMeshL2::WriteFamiliesAndGrps(fid,maa,_families,_groups,_too_long_str);
4385 }
4386
4387 /*!
4388  * Returns an empty instance of MEDFileCMesh.
4389  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
4390  *          mesh using decrRef() as it is no more needed. 
4391  */
4392 MEDFileCMesh *MEDFileCMesh::New()
4393 {
4394   return new MEDFileCMesh;
4395 }
4396
4397 /*!
4398  * Returns a new MEDFileCMesh holding the mesh data that has been read from a given MED
4399  * file. The first mesh in the file is loaded.
4400  *  \param [in] fileName - the name of MED file to read.
4401  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
4402  *          mesh using decrRef() as it is no more needed. 
4403  *  \throw If the file is not readable.
4404  *  \throw If there is no meshes in the file.
4405  *  \throw If the mesh in the file is not a Cartesian one.
4406  */
4407 MEDFileCMesh *MEDFileCMesh::New(const char *fileName) throw(INTERP_KERNEL::Exception)
4408 {
4409   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
4410   if(ms.empty())
4411     {
4412       std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
4413       throw INTERP_KERNEL::Exception(oss.str().c_str());
4414     }
4415   MEDFileUtilities::CheckFileForRead(fileName);
4416   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
4417   int dt,it;
4418   ParaMEDMEM::MEDCouplingMeshType meshType;
4419   std::string dummy2;
4420   MEDFileMeshL2::GetMeshIdFromName(fid,ms.front().c_str(),meshType,dt,it,dummy2);
4421   return new MEDFileCMesh(fid,ms.front().c_str(),dt,it);
4422 }
4423
4424 /*!
4425  * Returns a new MEDFileCMesh holding the mesh data that has been read from a given MED
4426  * file. The mesh to load is specified by its name and numbers of a time step and an
4427  * iteration.
4428  *  \param [in] fileName - the name of MED file to read.
4429  *  \param [in] mName - the name of the mesh to read.
4430  *  \param [in] dt - the number of a time step.
4431  *  \param [in] it - the number of an iteration.
4432  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
4433  *          mesh using decrRef() as it is no more needed. 
4434  *  \throw If the file is not readable.
4435  *  \throw If there is no mesh with given attributes in the file.
4436  *  \throw If the mesh in the file is not a Cartesian one.
4437  */
4438 MEDFileCMesh *MEDFileCMesh::New(const char *fileName, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
4439 {
4440   MEDFileUtilities::CheckFileForRead(fileName);
4441   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
4442   return new MEDFileCMesh(fid,mName,dt,it);
4443 }
4444
4445 std::size_t MEDFileCMesh::getHeapMemorySize() const
4446 {
4447   std::size_t ret=MEDFileStructuredMesh::getHeapMemorySize();
4448   if((const MEDCouplingCMesh *)_cmesh)
4449     ret+=_cmesh->getHeapMemorySize();
4450   return ret;
4451 }
4452
4453 /*!
4454  * Returns the dimension on cells in \a this mesh.
4455  *  \return int - the mesh dimension.
4456  *  \throw If there are no cells in this mesh.
4457  */
4458 int MEDFileCMesh::getMeshDimension() const throw(INTERP_KERNEL::Exception)
4459 {
4460   if(!((const MEDCouplingCMesh*)_cmesh))
4461     throw INTERP_KERNEL::Exception("MEDFileCMesh::getMeshDimension : unable to get meshdimension because no mesh set !");
4462   return _cmesh->getMeshDimension();
4463 }
4464
4465 /*!
4466  * Returns a string describing \a this mesh.
4467  *  \return std::string - the mesh information string.
4468  */
4469 std::string MEDFileCMesh::simpleRepr() const
4470 {
4471   return MEDFileStructuredMesh::simpleRepr();
4472 }
4473
4474 /*!
4475  * Returns a full textual description of \a this mesh.
4476  *  \return std::string - the string holding the mesh description.
4477  */
4478 std::string MEDFileCMesh::advancedRepr() const
4479 {
4480   return simpleRepr();
4481 }
4482
4483 MEDFileMesh *MEDFileCMesh::shallowCpy() const throw(INTERP_KERNEL::Exception)
4484 {
4485   MEDCouplingAutoRefCountObjectPtr<MEDFileCMesh> ret=new MEDFileCMesh(*this);
4486   return ret.retn();
4487 }
4488
4489 MEDFileMesh *MEDFileCMesh::createNewEmpty() const throw(INTERP_KERNEL::Exception)
4490 {
4491   return new MEDFileCMesh;
4492 }
4493
4494 MEDFileMesh *MEDFileCMesh::deepCpy() const throw(INTERP_KERNEL::Exception)
4495 {
4496   MEDCouplingAutoRefCountObjectPtr<MEDFileCMesh> ret=new MEDFileCMesh(*this);
4497   if((const MEDCouplingCMesh*)_cmesh)
4498     ret->_cmesh=static_cast<MEDCouplingCMesh*>(_cmesh->deepCpy());
4499   ret->deepCpyAttributes();
4500   return ret.retn();
4501 }
4502
4503 /*!
4504  * Checks if \a this and another mesh are equal.
4505  *  \param [in] other - the mesh to compare with.
4506  *  \param [in] eps - a precision used to compare real values.
4507  *  \param [in,out] what - the string returning description of unequal data.
4508  *  \return bool - \c true if the meshes are equal, \c false, else.
4509  */
4510 bool MEDFileCMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
4511 {
4512   if(!MEDFileStructuredMesh::isEqual(other,eps,what))
4513     return false;
4514   const MEDFileCMesh *otherC=dynamic_cast<const MEDFileCMesh *>(other);
4515   if(!otherC)
4516     {
4517       what="Mesh types differ ! This is cartesian and other is NOT !";
4518       return false;
4519     }
4520   clearNonDiscrAttributes();
4521   otherC->clearNonDiscrAttributes();
4522   const MEDCouplingCMesh *coo1=_cmesh;
4523   const MEDCouplingCMesh *coo2=otherC->_cmesh;
4524   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
4525     {
4526       what="Mismatch of cartesian meshes ! One is defined and not other !";
4527       return false;
4528     }
4529   if(coo1)
4530     {
4531       bool ret=coo1->isEqual(coo2,eps);
4532       if(!ret)
4533         {
4534           what="cartesian meshes differ !";
4535           return false;
4536         }
4537     }
4538   return true;
4539 }
4540
4541 /*!
4542  * Clears redundant attributes of incorporated data arrays.
4543  */
4544 void MEDFileCMesh::clearNonDiscrAttributes() const
4545 {
4546   MEDFileStructuredMesh::clearNonDiscrAttributes();
4547   MEDFileUMeshSplitL1::ClearNonDiscrAttributes(_cmesh);//to it is not a bug umeshsplit have already the method implemented
4548 }
4549
4550 MEDFileCMesh::MEDFileCMesh()
4551 {
4552 }
4553
4554 MEDFileCMesh::MEDFileCMesh(med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
4555 try
4556   {
4557     loadCMeshFromFile(fid,mName,dt,it);
4558   }
4559 catch(INTERP_KERNEL::Exception& e)
4560   {
4561     throw e;
4562   }
4563
4564 void MEDFileCMesh::loadCMeshFromFile(med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
4565 {
4566   ParaMEDMEM::MEDCouplingMeshType meshType;
4567   int dummy0,dummy1;
4568   std::string dtunit;
4569   int mid=MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dtunit);
4570   if(meshType!=CARTESIAN)
4571     {
4572       std::ostringstream oss; oss << "Trying to load as cartesian an existing mesh with name '" << mName << "' that is NOT cartesian !";
4573       throw INTERP_KERNEL::Exception(oss.str().c_str());
4574     }
4575   MEDFileCMeshL2 loaderl2;
4576   loaderl2.loadAll(fid,mid,mName,dt,it);
4577   MEDCouplingCMesh *mesh=loaderl2.getMesh();
4578   mesh->incrRef();
4579   _cmesh=mesh;
4580   loadStrMeshFromFile(&loaderl2,fid,mName,dt,it);
4581 }
4582
4583 /*!
4584  * Returns a const pointer to MEDCouplingCMesh held by \a this mesh.
4585  *  \return const MEDCouplingCMesh * - a pointer to the held MEDCouplingCMesh.
4586  */
4587 const MEDCouplingCMesh *MEDFileCMesh::getMesh() const
4588 {
4589   synchronizeTinyInfoOnLeaves();
4590   return _cmesh;
4591 }
4592
4593 const MEDCouplingStructuredMesh *MEDFileCMesh::getStructuredMesh() const
4594 {
4595   synchronizeTinyInfoOnLeaves();
4596   return _cmesh;
4597 }
4598
4599 /*!
4600  * Sets the MEDCouplingCMesh holding the data of \a this mesh.
4601  *  \param [in] m - the new MEDCouplingCMesh to refer to.
4602  *  \throw If the name or the description of \a this mesh and \a m are not empty and are
4603  *         different. 
4604  */
4605 void MEDFileCMesh::setMesh(MEDCouplingCMesh *m) throw(INTERP_KERNEL::Exception)
4606 {
4607   dealWithTinyInfo(m);
4608   if(m)
4609     m->incrRef();
4610   _cmesh=m;
4611 }
4612
4613 void MEDFileCMesh::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception)
4614 {
4615   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
4616   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
4617   INTERP_KERNEL::AutoPtr<char> dtunit=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE);
4618   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
4619   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
4620   MEDLoaderBase::safeStrCpy(_dt_unit.c_str(),MED_LNAME_SIZE,dtunit,_too_long_str);
4621   int spaceDim=_cmesh->getSpaceDimension();
4622   int meshDim=_cmesh->getMeshDimension();
4623   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
4624   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
4625   for(int i=0;i<spaceDim;i++)
4626     {
4627       std::string info(_cmesh->getCoordsAt(i)->getInfoOnComponent(0));
4628       std::string c,u;
4629       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
4630       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
4631       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
4632     }
4633   MEDmeshCr(fid,maa,spaceDim,meshDim,MED_STRUCTURED_MESH,desc,dtunit,MED_SORT_DTIT,MED_CARTESIAN,comp,unit);
4634   MEDmeshUniversalNameWr(fid,maa);
4635   MEDmeshGridTypeWr(fid,maa,MED_CARTESIAN_GRID);
4636   for(int i=0;i<spaceDim;i++)
4637     {
4638       const DataArrayDouble *da=_cmesh->getCoordsAt(i);
4639       MEDmeshGridIndexCoordinateWr(fid,maa,_iteration,_order,_time,i+1,da->getNumberOfTuples(),da->getConstPointer());
4640     }
4641   //
4642   MEDFileStructuredMesh::writeStructuredLL(fid,maa);
4643 }
4644
4645 void MEDFileCMesh::synchronizeTinyInfoOnLeaves() const
4646 {
4647   const MEDCouplingCMesh *cmesh=_cmesh;
4648   if(!cmesh)
4649     return;
4650   (const_cast<MEDCouplingCMesh *>(cmesh))->setName(_name.c_str());
4651   (const_cast<MEDCouplingCMesh *>(cmesh))->setDescription(_desc_name.c_str());
4652   (const_cast<MEDCouplingCMesh *>(cmesh))->setTime(_time,_iteration,_order);
4653   (const_cast<MEDCouplingCMesh *>(cmesh))->setTimeUnit(_dt_unit.c_str());
4654 }
4655
4656 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New()
4657 {
4658   return new MEDFileCurveLinearMesh;
4659 }
4660
4661 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const char *fileName) throw(INTERP_KERNEL::Exception)
4662 {
4663   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
4664   if(ms.empty())
4665     {
4666       std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
4667       throw INTERP_KERNEL::Exception(oss.str().c_str());
4668     }
4669   MEDFileUtilities::CheckFileForRead(fileName);
4670   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
4671   int dt,it;
4672   ParaMEDMEM::MEDCouplingMeshType meshType;
4673   std::string dummy2;
4674   MEDFileMeshL2::GetMeshIdFromName(fid,ms.front().c_str(),meshType,dt,it,dummy2);
4675   return new MEDFileCurveLinearMesh(fid,ms.front().c_str(),dt,it);
4676 }
4677
4678 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const char *fileName, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
4679 {
4680   MEDFileUtilities::CheckFileForRead(fileName);
4681   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
4682   return new MEDFileCurveLinearMesh(fid,mName,dt,it);
4683 }
4684
4685 std::size_t MEDFileCurveLinearMesh::getHeapMemorySize() const
4686 {
4687   std::size_t ret=MEDFileStructuredMesh::getHeapMemorySize();
4688   if((const MEDCouplingCurveLinearMesh *)_clmesh)
4689     ret+=_clmesh->getHeapMemorySize();
4690   return ret;
4691 }
4692
4693 MEDFileMesh *MEDFileCurveLinearMesh::shallowCpy() const throw(INTERP_KERNEL::Exception)
4694 {
4695   MEDCouplingAutoRefCountObjectPtr<MEDFileCurveLinearMesh> ret=new MEDFileCurveLinearMesh(*this);
4696   return ret.retn();
4697 }
4698
4699 MEDFileMesh *MEDFileCurveLinearMesh::createNewEmpty() const throw(INTERP_KERNEL::Exception)
4700 {
4701   return new MEDFileCurveLinearMesh;
4702 }
4703
4704 MEDFileMesh *MEDFileCurveLinearMesh::deepCpy() const throw(INTERP_KERNEL::Exception)
4705 {
4706   MEDCouplingAutoRefCountObjectPtr<MEDFileCurveLinearMesh> ret=new MEDFileCurveLinearMesh(*this);
4707   if((const MEDCouplingCurveLinearMesh*)_clmesh)
4708     ret->_clmesh=static_cast<MEDCouplingCurveLinearMesh*>(_clmesh->deepCpy());
4709   ret->deepCpyAttributes();
4710   return ret.retn();
4711 }
4712
4713 int MEDFileCurveLinearMesh::getMeshDimension() const throw(INTERP_KERNEL::Exception)
4714 {
4715   if(!((const MEDCouplingCurveLinearMesh*)_clmesh))
4716     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::getMeshDimension : unable to get meshdimension because no mesh set !");
4717   return _clmesh->getMeshDimension();
4718 }
4719
4720 std::string MEDFileCurveLinearMesh::simpleRepr() const
4721 {
4722   return MEDFileStructuredMesh::simpleRepr();
4723 }
4724
4725 std::string MEDFileCurveLinearMesh::advancedRepr() const
4726 {
4727   return simpleRepr();
4728 }
4729
4730 bool MEDFileCurveLinearMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
4731 {
4732   if(!MEDFileStructuredMesh::isEqual(other,eps,what))
4733     return false;
4734   const MEDFileCurveLinearMesh *otherC=dynamic_cast<const MEDFileCurveLinearMesh *>(other);
4735   if(!otherC)
4736     {
4737       what="Mesh types differ ! This is curve linear and other is NOT !";
4738       return false;
4739     }
4740   clearNonDiscrAttributes();
4741   otherC->clearNonDiscrAttributes();
4742   const MEDCouplingCurveLinearMesh *coo1=_clmesh;
4743   const MEDCouplingCurveLinearMesh *coo2=otherC->_clmesh;
4744   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
4745     {
4746       what="Mismatch of curve linear meshes ! One is defined and not other !";
4747       return false;
4748     }
4749   if(coo1)
4750     {
4751       bool ret=coo1->isEqual(coo2,eps);
4752       if(!ret)
4753         {
4754           what="curve linear meshes differ !";
4755           return false;
4756         }
4757     }
4758   return true;
4759 }
4760
4761 void MEDFileCurveLinearMesh::clearNonDiscrAttributes() const
4762 {
4763   MEDFileStructuredMesh::clearNonDiscrAttributes();
4764   MEDFileUMeshSplitL1::ClearNonDiscrAttributes(_clmesh);//to it is not a bug umeshsplit have already the method implemented
4765 }
4766
4767 void MEDFileCurveLinearMesh::synchronizeTinyInfoOnLeaves() const
4768 {
4769   const MEDCouplingCurveLinearMesh *clmesh=_clmesh;
4770   if(!clmesh)
4771     return;
4772   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setName(_name.c_str());
4773   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setDescription(_desc_name.c_str());
4774   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setTime(_time,_iteration,_order);
4775   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setTimeUnit(_dt_unit.c_str());
4776 }
4777
4778 const MEDCouplingCurveLinearMesh *MEDFileCurveLinearMesh::getMesh() const
4779 {
4780   synchronizeTinyInfoOnLeaves();
4781   return _clmesh;
4782 }
4783
4784 void MEDFileCurveLinearMesh::setMesh(MEDCouplingCurveLinearMesh *m) throw(INTERP_KERNEL::Exception)
4785 {
4786   dealWithTinyInfo(m);
4787   if(m)
4788     m->incrRef();
4789   _clmesh=m;
4790 }
4791
4792 const MEDCouplingStructuredMesh *MEDFileCurveLinearMesh::getStructuredMesh() const
4793 {
4794   synchronizeTinyInfoOnLeaves();
4795   return _clmesh;
4796 }
4797
4798 MEDFileCurveLinearMesh::MEDFileCurveLinearMesh()
4799 {
4800 }
4801
4802 MEDFileCurveLinearMesh::MEDFileCurveLinearMesh(med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
4803 try
4804   {
4805     loadCLMeshFromFile(fid,mName,dt,it);
4806   }
4807 catch(INTERP_KERNEL::Exception& e)
4808   {
4809     throw e;
4810   }
4811
4812 void MEDFileCurveLinearMesh::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception)
4813 {
4814   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
4815   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
4816   INTERP_KERNEL::AutoPtr<char> dtunit=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE);
4817   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
4818   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
4819   MEDLoaderBase::safeStrCpy(_dt_unit.c_str(),MED_LNAME_SIZE,dtunit,_too_long_str);
4820   int spaceDim=_clmesh->getSpaceDimension();
4821   int meshDim=_clmesh->getMeshDimension();
4822   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
4823   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
4824   const DataArrayDouble *coords=_clmesh->getCoords();
4825   if(!coords)
4826     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::writeLL : no coordinates set !");
4827   for(int i=0;i<spaceDim;i++)
4828     {
4829       std::string info(_clmesh->getCoords()->getInfoOnComponent(i));
4830       std::string c,u;
4831       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
4832       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
4833       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
4834     }
4835   MEDmeshCr(fid,maa,spaceDim,meshDim,MED_STRUCTURED_MESH,desc,dtunit,MED_SORT_DTIT,MED_CARTESIAN,comp,unit);
4836   MEDmeshUniversalNameWr(fid,maa);
4837   MEDmeshGridTypeWr(fid,maa,MED_CURVILINEAR_GRID);
4838   std::vector<int> nodeGridSt=_clmesh->getNodeGridStructure();
4839   MEDmeshGridStructWr(fid,maa,_iteration,_order,_time,&nodeGridSt[0]);
4840   
4841   MEDmeshNodeCoordinateWr(fid,maa,_iteration,_order,_time,MED_FULL_INTERLACE,coords->getNumberOfTuples(),coords->begin());
4842   //
4843   MEDFileStructuredMesh::writeStructuredLL(fid,maa);
4844 }
4845
4846 void MEDFileCurveLinearMesh::loadCLMeshFromFile(med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
4847 {
4848   ParaMEDMEM::MEDCouplingMeshType meshType;
4849   int dummy0,dummy1;
4850   std::string dtunit;
4851   int mid=MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dtunit);
4852   if(meshType!=CURVE_LINEAR)
4853     {
4854       std::ostringstream oss; oss << "Trying to load as curve linear an existing mesh with name '" << mName << "' that is NOT curve linear !";
4855       throw INTERP_KERNEL::Exception(oss.str().c_str());
4856     }
4857   MEDFileCLMeshL2 loaderl2;
4858   loaderl2.loadAll(fid,mid,mName,dt,it);
4859   MEDCouplingCurveLinearMesh *mesh=loaderl2.getMesh();
4860   mesh->incrRef();
4861   _clmesh=mesh;
4862   loadStrMeshFromFile(&loaderl2,fid,mName,dt,it);
4863 }
4864
4865 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New()
4866 {
4867   return new MEDFileMeshMultiTS;
4868 }
4869
4870 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(const char *fileName) throw(INTERP_KERNEL::Exception)
4871 {
4872   return new MEDFileMeshMultiTS(fileName);
4873 }
4874
4875 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(const char *fileName, const char *mName) throw(INTERP_KERNEL::Exception)
4876 {
4877   return new MEDFileMeshMultiTS(fileName,mName);
4878 }
4879
4880 MEDFileMeshMultiTS *MEDFileMeshMultiTS::deepCpy() const throw(INTERP_KERNEL::Exception)
4881 {
4882   MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> ret=MEDFileMeshMultiTS::New();
4883   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> > meshOneTs(_mesh_one_ts.size());
4884   std::size_t i=0;
4885   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++,i++)
4886     if((const MEDFileMesh *)*it)
4887       meshOneTs[i]=(*it)->deepCpy();
4888   ret->_mesh_one_ts=meshOneTs;
4889   return ret.retn();
4890 }
4891
4892 std::size_t MEDFileMeshMultiTS::getHeapMemorySize() const
4893 {
4894   std::size_t ret=_mesh_one_ts.capacity()*sizeof(MEDCouplingAutoRefCountObjectPtr<MEDFileMesh>);
4895   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
4896     ret+=(*it)->getHeapMemorySize();
4897   return ret;
4898 }
4899
4900 const char *MEDFileMeshMultiTS::getName() const throw(INTERP_KERNEL::Exception)
4901 {
4902   if(_mesh_one_ts.empty())
4903     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::getName : no time steps set !");
4904   return _mesh_one_ts[0]->getName();
4905 }
4906
4907 void MEDFileMeshMultiTS::setName(const char *newMeshName) throw(INTERP_KERNEL::Exception)
4908 {
4909   std::string oldName(getName());
4910   std::vector< std::pair<std::string,std::string> > v(1);
4911   v[0].first=oldName; v[0].second=newMeshName;
4912   changeNames(v);
4913 }
4914
4915 bool MEDFileMeshMultiTS::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab) throw(INTERP_KERNEL::Exception)
4916 {
4917   bool ret=false;
4918   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
4919     {
4920       MEDFileMesh *cur(*it);
4921       if(cur)
4922         ret=cur->changeNames(modifTab) || ret;
4923     }
4924   return ret;
4925 }
4926
4927 MEDFileMesh *MEDFileMeshMultiTS::getOneTimeStep() const throw(INTERP_KERNEL::Exception)
4928 {
4929   if(_mesh_one_ts.empty())
4930     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::getOneTimeStep : empty time step set !");
4931   return const_cast<MEDFileMesh *>(static_cast<const MEDFileMesh *>(_mesh_one_ts[0]));
4932 }
4933
4934 void MEDFileMeshMultiTS::setOneTimeStep(MEDFileMesh *mesh1TimeStep) throw(INTERP_KERNEL::Exception)
4935 {
4936   if(!mesh1TimeStep)
4937     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::setOneTimeStep : input pointer should be different from 0 !");
4938   _mesh_one_ts.resize(1);
4939   mesh1TimeStep->incrRef();
4940   //MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> toto=mesh1TimeStep;
4941   _mesh_one_ts[0]=mesh1TimeStep;
4942 }
4943
4944 void MEDFileMeshMultiTS::write(med_idt fid) const throw(INTERP_KERNEL::Exception)
4945 {
4946   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
4947     {
4948       (*it)->copyOptionsFrom(*this);
4949       (*it)->write(fid);
4950     }
4951 }
4952
4953 void MEDFileMeshMultiTS::write(const char *fileName, int mode) const throw(INTERP_KERNEL::Exception)
4954 {
4955   med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode);
4956   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,medmod);
4957   std::ostringstream oss; oss << "MEDFileMesh : error on attempt to write in file : \"" << fileName << "\""; 
4958   MEDFileUtilities::CheckMEDCode(fid,fid,oss.str().c_str());
4959   write(fid);
4960 }
4961
4962 void MEDFileMeshMultiTS::loadFromFile(const char *fileName, const char *mName) throw(INTERP_KERNEL::Exception)
4963 {//for the moment to be improved
4964   _mesh_one_ts.resize(1);
4965   _mesh_one_ts[0]=MEDFileMesh::New(fileName,mName,-1,-1);
4966 }
4967
4968 MEDFileMeshMultiTS::MEDFileMeshMultiTS()
4969 {
4970 }
4971
4972 MEDFileMeshMultiTS::MEDFileMeshMultiTS(const char *fileName) throw(INTERP_KERNEL::Exception)
4973 try
4974   {
4975     std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
4976     if(ms.empty())
4977     {
4978       std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
4979       throw INTERP_KERNEL::Exception(oss.str().c_str());
4980     }
4981     MEDFileUtilities::CheckFileForRead(fileName);
4982     MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
4983     int dt,it;
4984     ParaMEDMEM::MEDCouplingMeshType meshType;
4985     std::string dummy2;
4986     MEDFileMeshL2::GetMeshIdFromName(fid,ms.front().c_str(),meshType,dt,it,dummy2);
4987     loadFromFile(fileName,ms.front().c_str());
4988   }
4989 catch(INTERP_KERNEL::Exception& e)
4990   {
4991     throw e;
4992   }
4993
4994 MEDFileMeshMultiTS::MEDFileMeshMultiTS(const char *fileName, const char *mName) throw(INTERP_KERNEL::Exception)
4995 try
4996   {
4997     loadFromFile(fileName,mName);
4998   }
4999 catch(INTERP_KERNEL::Exception& e)
5000   {
5001     throw e;
5002   }
5003
5004 MEDFileMeshes *MEDFileMeshes::New()
5005 {
5006   return new MEDFileMeshes;
5007 }
5008
5009 MEDFileMeshes *MEDFileMeshes::New(const char *fileName) throw(INTERP_KERNEL::Exception)
5010 {
5011   return new MEDFileMeshes(fileName);
5012 }
5013
5014 void MEDFileMeshes::write(med_idt fid) const throw(INTERP_KERNEL::Exception)
5015 {
5016   checkCoherency();
5017   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++)
5018     {
5019       (*it)->copyOptionsFrom(*this);
5020       (*it)->write(fid);
5021     }
5022 }
5023
5024 void MEDFileMeshes::write(const char *fileName, int mode) const throw(INTERP_KERNEL::Exception)
5025 {
5026   med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode);
5027   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,medmod);
5028   std::ostringstream oss; oss << "MEDFileMesh : error on attempt to write in file : \"" << fileName << "\""; 
5029   MEDFileUtilities::CheckMEDCode(fid,fid,oss.str().c_str());
5030   checkCoherency();
5031   write(fid);
5032 }
5033
5034 int MEDFileMeshes::getNumberOfMeshes() const throw(INTERP_KERNEL::Exception)
5035 {
5036   return _meshes.size();
5037 }
5038
5039 MEDFileMeshesIterator *MEDFileMeshes::iterator() throw(INTERP_KERNEL::Exception)
5040 {
5041   return new MEDFileMeshesIterator(this);
5042 }
5043
5044 MEDFileMesh *MEDFileMeshes::getMeshAtPos(int i) const throw(INTERP_KERNEL::Exception)
5045 {
5046   if(i<0 || i>=(int)_meshes.size())
5047     {
5048       std::ostringstream oss; oss << "MEDFileMeshes::getMeshAtPos : invalid mesh id given in parameter ! Should be in [0;" << _meshes.size() << ") !";
5049       throw INTERP_KERNEL::Exception(oss.str().c_str());
5050     }
5051   return _meshes[i]->getOneTimeStep();
5052 }
5053
5054 MEDFileMesh *MEDFileMeshes::getMeshWithName(const char *mname) const throw(INTERP_KERNEL::Exception)
5055 {
5056   std::vector<std::string> ms=getMeshesNames();
5057   std::vector<std::string>::iterator it=std::find(ms.begin(),ms.end(),mname);
5058   if(it==ms.end())
5059     {
5060       std::ostringstream oss; oss << "MEDFileMeshes::getMeshWithName : Mesh  \"" << mname << "\" does not exist in this ! Existing are : ";
5061       std::copy(ms.begin(),ms.end(),std::ostream_iterator<std::string>(oss," "));
5062       throw INTERP_KERNEL::Exception(oss.str().c_str());
5063     }
5064   return getMeshAtPos((int)std::distance(ms.begin(),it));
5065 }
5066
5067 std::vector<std::string> MEDFileMeshes::getMeshesNames() const throw(INTERP_KERNEL::Exception)
5068 {
5069   std::vector<std::string> ret(_meshes.size());
5070   int i=0;
5071   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
5072     {
5073       const MEDFileMeshMultiTS *f=(*it);
5074       if(f)
5075         {
5076           ret[i]=f->getName();
5077         }
5078       else
5079         {
5080           std::ostringstream oss; oss << "MEDFileMeshes::getMeshesNames : At rank #" << i << " mesh is not defined !";
5081           throw INTERP_KERNEL::Exception(oss.str().c_str());
5082         }
5083     }
5084   return ret;
5085 }
5086
5087 bool MEDFileMeshes::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab) throw(INTERP_KERNEL::Exception)
5088 {
5089   bool ret=false;
5090   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::iterator it=_meshes.begin();it!=_meshes.end();it++)
5091     {
5092       MEDFileMeshMultiTS *cur(*it);
5093       if(cur)
5094         ret=cur->changeNames(modifTab) || ret;
5095     }
5096   return ret;
5097 }
5098
5099 void MEDFileMeshes::resize(int newSize) throw(INTERP_KERNEL::Exception)
5100 {
5101   _meshes.resize(newSize);
5102 }
5103
5104 void MEDFileMeshes::pushMesh(MEDFileMesh *mesh) throw(INTERP_KERNEL::Exception)
5105 {
5106   if(!mesh)
5107     throw INTERP_KERNEL::Exception("MEDFileMeshes::pushMesh : invalid input pointer ! should be different from 0 !");
5108   MEDFileMeshMultiTS *elt=MEDFileMeshMultiTS::New();
5109   elt->setOneTimeStep(mesh);
5110   _meshes.push_back(elt);
5111 }
5112
5113 void MEDFileMeshes::setMeshAtPos(int i, MEDFileMesh *mesh) throw(INTERP_KERNEL::Exception)
5114 {
5115   if(!mesh)
5116     throw INTERP_KERNEL::Exception("MEDFileMeshes::setMeshAtPos : invalid input pointer ! should be different from 0 !");
5117   if(i>=(int)_meshes.size())
5118     _meshes.resize(i+1);
5119   MEDFileMeshMultiTS *elt=MEDFileMeshMultiTS::New();
5120   elt->setOneTimeStep(mesh);
5121   _meshes[i]=elt;
5122 }
5123
5124 void MEDFileMeshes::destroyMeshAtPos(int i) throw(INTERP_KERNEL::Exception)
5125 {
5126   if(i<0 || i>=(int)_meshes.size())
5127     {
5128       std::ostringstream oss; oss << "MEDFileMeshes::destroyMeshAtPos : Invalid given id in input (" << i << ") should be in [0," << _meshes.size() << ") !";
5129       throw INTERP_KERNEL::Exception(oss.str().c_str());
5130     }
5131   _meshes.erase(_meshes.begin()+i);
5132 }
5133
5134 void MEDFileMeshes::loadFromFile(const char *fileName) throw(INTERP_KERNEL::Exception)
5135 {
5136   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
5137   int i=0;
5138   _meshes.resize(ms.size());
5139   for(std::vector<std::string>::const_iterator it=ms.begin();it!=ms.end();it++,i++)
5140     _meshes[i]=MEDFileMeshMultiTS::New(fileName,(*it).c_str());
5141 }
5142
5143 MEDFileMeshes::MEDFileMeshes()
5144 {
5145 }
5146
5147 MEDFileMeshes::MEDFileMeshes(const char *fileName) throw(INTERP_KERNEL::Exception)
5148 try
5149   {
5150     loadFromFile(fileName);
5151   }
5152 catch(INTERP_KERNEL::Exception& e)
5153   {
5154   }
5155
5156 MEDFileMeshes *MEDFileMeshes::deepCpy() const throw(INTERP_KERNEL::Exception)
5157 {
5158   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> > meshes(_meshes.size());
5159   std::size_t i=0;
5160   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
5161     if((const MEDFileMeshMultiTS *)*it)
5162       meshes[i]=(*it)->deepCpy();
5163   MEDCouplingAutoRefCountObjectPtr<MEDFileMeshes> ret=MEDFileMeshes::New();
5164   ret->_meshes=meshes;
5165   return ret.retn();
5166 }
5167
5168 std::size_t MEDFileMeshes::getHeapMemorySize() const
5169 {
5170   std::size_t ret=_meshes.capacity()*(sizeof(MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS>));
5171   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++)
5172     if((const MEDFileMeshMultiTS*)*it)
5173       ret+=(*it)->getHeapMemorySize();
5174   return ret; 
5175 }
5176
5177 std::string MEDFileMeshes::simpleRepr() const
5178 {
5179   std::ostringstream oss;
5180   oss << "(*****************)\n(* MEDFileMeshes *)\n(*****************)\n\n";
5181   simpleReprWithoutHeader(oss);
5182   return oss.str();
5183 }
5184
5185 void MEDFileMeshes::simpleReprWithoutHeader(std::ostream& oss) const
5186 {
5187   int nbOfMeshes=getNumberOfMeshes();
5188   oss << "There are " << nbOfMeshes << " meshes with the following names : \n";
5189   std::vector<std::string> mns=getMeshesNames();
5190   for(int i=0;i<nbOfMeshes;i++)
5191     oss << "  - #" << i << " \"" << mns[i] << "\"\n";
5192 }
5193
5194 void MEDFileMeshes::checkCoherency() const throw(INTERP_KERNEL::Exception)
5195 {
5196   static const char MSG[]="MEDFileMeshes::checkCoherency : mesh at rank ";
5197   int i=0;
5198   std::set<std::string> s;
5199   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
5200     {
5201       const MEDFileMeshMultiTS *elt=(*it);
5202       if(!elt)
5203         {
5204           std::ostringstream oss; oss << MSG << i << "/" << _meshes.size() << " is empty !";
5205           throw INTERP_KERNEL::Exception(oss.str().c_str());
5206         }
5207       std::size_t sz=s.size();
5208       s.insert(std::string((*it)->getName()));
5209       if(s.size()==sz)
5210         {
5211           std::ostringstream oss; oss << MSG << i << " has a name (\"" << (*it)->getName() << "\") already used by an another mesh in list !";
5212           throw INTERP_KERNEL::Exception(oss.str().c_str());
5213         }
5214     }
5215 }
5216
5217 MEDFileMeshesIterator::MEDFileMeshesIterator(MEDFileMeshes *ms):_ms(ms),_iter_id(0),_nb_iter(0)
5218 {
5219   if(ms)
5220     {
5221       ms->incrRef();
5222       _nb_iter=ms->getNumberOfMeshes();
5223     }
5224 }
5225
5226 MEDFileMeshesIterator::~MEDFileMeshesIterator()
5227 {
5228 }
5229
5230 MEDFileMesh *MEDFileMeshesIterator::nextt()
5231 {
5232   if(_iter_id<_nb_iter)
5233     {
5234       MEDFileMeshes *ms(_ms);
5235       if(ms)
5236         return ms->getMeshAtPos(_iter_id++);
5237       else
5238         return 0;
5239     }
5240   else
5241     return 0;
5242 }