Salome HOME
On the road of reimplementation of basic MEDLoader API with advanced one.
[modules/med.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  * This method allows to set at once the content of different levels in \a this.
3430  * This method is equivalent to a series of call to MEDFileUMesh::setMeshAtLevel.
3431  *
3432  * \param [in] ms - List of unstructured meshes lying on the same coordinates and having different mesh dimesnion.
3433  * \param [in] renum - the parameter (set to false by default) that tells the beheviour if there is a mesh on \a ms that is not geo type sorted.
3434  *                     If false, an exception ois thrown. If true the mesh is reordered automatically. It is highly recommanded to let this parameter to false.
3435  *
3436  * \throw If \a there is a null pointer in \a ms.
3437  * \sa MEDFileUMesh::setMeshAtLevel
3438  */
3439 void MEDFileUMesh::setMeshes(const std::vector<const MEDCouplingUMesh *>& ms, bool renum) throw(INTERP_KERNEL::Exception)
3440 {
3441   if(ms.empty())
3442     return ;
3443   const MEDCouplingUMesh *mRef=ms[0];
3444   if(!mRef)
3445     throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : null instance in the first element of input meshes !");
3446   std::string name(mRef->getName());
3447   const DataArrayDouble *coo(mRef->getCoords());
3448   std::set<int> s;
3449   int zeDim=-1;
3450   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
3451     {
3452       const MEDCouplingUMesh *cur(*it);
3453       if(!cur)
3454         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : null instance in input vector of meshes !");
3455       if(coo!=cur->getCoords())
3456         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : The input meshes do not share the same coordinates !");
3457       int mdim=cur->getMeshDimension();
3458       zeDim=std::max(zeDim,mdim);
3459       if(s.find(mdim)!=s.end())
3460         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : The input meshes must share the same coordinates pointer, and should have different mesh dimension each other !");
3461     }
3462   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
3463     {
3464       int mdim=(*it)->getMeshDimension();
3465       setName((*it)->getName());
3466       setMeshAtLevel(mdim-zeDim,const_cast<MEDCouplingUMesh *>(*it),renum);
3467     }
3468   setName(name.c_str());
3469 }
3470
3471 /*!
3472  * Creates one MEDCouplingUMesh at a given level in \a this mesh from a sequence of
3473  * meshes each representing a group, and creates corresponding groups in \a this mesh.
3474  * The given meshes must share the same node coordinates array.
3475  *  \param [in] meshDimRelToMax - the relative dimension to create the mesh and groups at.
3476  *  \param [in] ms - the sequence of meshes. Each mesh in \a ms represents a group to
3477  *          create in \a this mesh.
3478  *  \throw If \a ms is empty.
3479  *  \throw If dimension of meshes in \a ms does not correspond to \a meshDimRelToMax or
3480  *         to the existing meshes of other levels of \a this mesh.
3481  *  \throw If the meshes in \a ms do not share the same node coordinates array.
3482  *  \throw If the node coordinates array of \a this mesh (if any) is not the same as that
3483  *         of the given meshes.
3484  *  \throw If \a ms[ i ] is not well defined (MEDCouplingUMesh::checkCoherency()).
3485  *  \throw If names of some meshes in \a ms are equal.
3486  *  \throw If \a ms includes a mesh with an empty name.
3487  */
3488 void MEDFileUMesh::setGroupsFromScratch(int meshDimRelToMax, const std::vector<const MEDCouplingUMesh *>& ms, bool renum) throw(INTERP_KERNEL::Exception)
3489 {
3490   if(ms.empty())
3491     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsFromScratch : expecting a non empty vector !");
3492   int sz=(-meshDimRelToMax)+1;
3493   if(sz>=(int)_ms.size())
3494     _ms.resize(sz);
3495   checkMeshDimCoherency(ms[0]->getMeshDimension(),meshDimRelToMax);
3496   DataArrayDouble *coo=checkMultiMesh(ms);
3497   if((DataArrayDouble *)_coords==0)
3498     {
3499       coo->incrRef();
3500       _coords=coo;
3501     }
3502   else
3503     if((DataArrayDouble *)_coords!=coo)
3504       throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsFromScratch : coordinates mismatches !");
3505   std::vector<DataArrayInt *> corr;
3506   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MEDCouplingUMesh::FuseUMeshesOnSameCoords(ms,_zipconn_pol,corr);
3507   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > corr3(corr.begin(),corr.end());
3508   setMeshAtLevel(meshDimRelToMax,m,renum);
3509   std::vector<const DataArrayInt *> corr2(corr.begin(),corr.end());
3510   setGroupsAtLevel(meshDimRelToMax,corr2,true);
3511 }
3512
3513 /*!
3514  * Creates groups at a given level in \a this mesh from a sequence of
3515  * meshes each representing a group.
3516  * The given meshes must share the same node coordinates array.
3517  *  \param [in] meshDimRelToMax - the relative dimension to create the groups at.
3518  *  \param [in] ms - the sequence of meshes. Each mesh in \a ms represents a group to
3519  *         create in \a this mesh.
3520  *  \param [in] renum - if \c true, then the optional numbers of entities are taken into
3521  *         account. 
3522  *  \throw If \a ms is empty.
3523  *  \throw If dimension of meshes in \a ms does not correspond to \a meshDimRelToMax or
3524  *         to the existing meshes of other levels of \a this mesh.
3525  *  \throw If the meshes in \a ms do not share the same node coordinates array.
3526  *  \throw If the node coordinates array of \a this mesh (if any) is not the same as that
3527  *         of the given meshes.
3528  *  \throw If \a ms[ i ] is not well defined (MEDCouplingUMesh::checkCoherency()).
3529  *  \throw If names of some meshes in \a ms are equal.
3530  *  \throw If \a ms includes a mesh with an empty name.
3531  */
3532 void MEDFileUMesh::setGroupsOnSetMesh(int meshDimRelToMax, const std::vector<const MEDCouplingUMesh *>& ms, bool renum) throw(INTERP_KERNEL::Exception)
3533 {
3534   if(ms.empty())
3535     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsOnSetMesh : expecting a non empty vector !");
3536   int sz=(-meshDimRelToMax)+1;
3537   if(sz>=(int)_ms.size())
3538     _ms.resize(sz);
3539   checkMeshDimCoherency(ms[0]->getMeshDimension(),meshDimRelToMax);
3540   DataArrayDouble *coo=checkMultiMesh(ms);
3541   if((DataArrayDouble *)_coords==0)
3542     {
3543       coo->incrRef();
3544       _coords=coo;
3545     }
3546   else
3547     if((DataArrayDouble *)_coords!=coo)
3548       throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsOnSetMesh : coordinates mismatches !");
3549   MEDCouplingUMesh *m=getMeshAtLevel(meshDimRelToMax,renum);
3550   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > corr(ms.size());
3551   int i=0;
3552   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++,i++)
3553     {
3554       DataArrayInt *arr=0;
3555       bool test=m->areCellsIncludedIn(*it,_zipconn_pol,arr);
3556       corr[i]=arr;
3557       if(!test)
3558         {
3559           std::ostringstream oss; oss << "MEDFileUMesh::setGroupsOnSetMesh : mesh #" << i << " is not part of whole mesh !";
3560           throw INTERP_KERNEL::Exception(oss.str().c_str());
3561         }
3562     }
3563   std::vector<const DataArrayInt *> corr2(corr.begin(),corr.end());
3564   setGroupsAtLevel(meshDimRelToMax,corr2,renum);
3565 }
3566
3567 DataArrayDouble *MEDFileUMesh::checkMultiMesh(const std::vector<const MEDCouplingUMesh *>& ms) const throw(INTERP_KERNEL::Exception)
3568 {
3569   const DataArrayDouble *ret=ms[0]->getCoords();
3570   int mdim=ms[0]->getMeshDimension();
3571   for(unsigned int i=1;i<ms.size();i++)
3572     {
3573       ms[i]->checkCoherency();
3574       if(ms[i]->getCoords()!=ret)
3575         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMultiMesh : meshes must share the same coords !");
3576       if(ms[i]->getMeshDimension()!=mdim)
3577         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMultiMesh : meshes have not same mesh dimension !");
3578     }
3579   return const_cast<DataArrayDouble *>(ret);
3580 }
3581
3582 /*!
3583  * Sets the family field of a given relative dimension.
3584  *  \param [in] meshDimRelToMaxExt - the relative dimension of entities for which
3585  *          the family field is set.
3586  *  \param [in] famArr - the array of the family field.
3587  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3588  *  \throw If \a famArr has an invalid size.
3589  */
3590 void MEDFileUMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr) throw(INTERP_KERNEL::Exception)
3591 {
3592   if(meshDimRelToMaxExt==1)
3593     {
3594       if(!famArr)
3595         {
3596           _fam_coords=0;
3597           return ;
3598         }
3599       DataArrayDouble *coo(_coords);
3600       if(!coo)
3601         throw INTERP_KERNEL::Exception("MEDFileUMesh::setFamilyFieldArr : the coordinates have not been set !");
3602       famArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),1,"MEDFileUMesh::setFamilyFieldArr : Problem in size of node family arr ! ");
3603       famArr->incrRef();
3604       _fam_coords=famArr;
3605       return ;
3606     }
3607   if(meshDimRelToMaxExt>1)
3608     throw INTERP_KERNEL::Exception("MEDFileUMesh::setFamilyFieldArr : Dimension request is invalid (>1) !");
3609   int traducedRk=-meshDimRelToMaxExt;
3610   if(traducedRk>=(int)_ms.size())
3611     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
3612   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
3613     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3614   return _ms[traducedRk]->setFamilyArr(famArr);
3615 }
3616
3617 /*!
3618  * Sets the optional numbers of mesh entities of a given dimension.
3619  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
3620  *  \param [in] renumArr - the array of the numbers.
3621  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3622  *  \throw If \a renumArr has an invalid size.
3623  */
3624 void MEDFileUMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr) throw(INTERP_KERNEL::Exception)
3625 {
3626   if(meshDimRelToMaxExt==1)
3627     {
3628       if(!renumArr)
3629         {
3630           _num_coords=0;
3631           _rev_num_coords=0;
3632           return ;
3633         }
3634       DataArrayDouble *coo(_coords);
3635       if(!coo)
3636         throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumFieldArr : the coordinates have not been set !");
3637       renumArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),1,"MEDFileUMesh::setRenumArr : Problem in size of node numbering arr ! ");
3638       renumArr->incrRef();
3639       _num_coords=renumArr;
3640       computeRevNum();
3641       return ;
3642     }
3643   if(meshDimRelToMaxExt>1)
3644     throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumArr : Dimension request is invalid (>1) !");
3645   int traducedRk=-meshDimRelToMaxExt;
3646   if(traducedRk>=(int)_ms.size())
3647     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
3648   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
3649     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3650   return _ms[traducedRk]->setRenumArr(renumArr);
3651 }
3652
3653 /*!
3654  * Sets the optional names of mesh entities of a given dimension.
3655  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
3656  *  \param [in] nameArr - the array of the names.
3657  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3658  *  \throw If \a nameArr has an invalid size.
3659  */
3660 void MEDFileUMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr) throw(INTERP_KERNEL::Exception)
3661 {
3662   if(meshDimRelToMaxExt==1)
3663     {
3664       if(!nameArr)
3665         {
3666           _name_coords=0;
3667           return ;
3668         }
3669       DataArrayDouble *coo(_coords);
3670       if(!coo)
3671         throw INTERP_KERNEL::Exception("MEDFileUMesh::setNameFieldAtLevel : the coordinates have not been set !");
3672       nameArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),MED_SNAME_SIZE,"MEDFileUMesh::setNameFieldAtLevel : Problem in size of node numbering arr ! ");
3673       nameArr->incrRef();
3674       _name_coords=nameArr;
3675       return ;
3676     }
3677   if(meshDimRelToMaxExt>1)
3678     throw INTERP_KERNEL::Exception("MEDFileUMesh::setNameFieldAtLevel : Dimension request is invalid (>1) !");
3679   int traducedRk=-meshDimRelToMaxExt;
3680   if(traducedRk>=(int)_ms.size())
3681     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
3682   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
3683     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
3684   return _ms[traducedRk]->setNameArr(nameArr);
3685 }
3686
3687 void MEDFileUMesh::synchronizeTinyInfoOnLeaves() const
3688 {
3689   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
3690     if((const MEDFileUMeshSplitL1 *)(*it))
3691       (*it)->synchronizeTinyInfo(*this);
3692 }
3693
3694 /*!
3695  * This method is called by MEDFileMesh::changeFamilyId. It performs only one part of the family id modification.
3696  */
3697 void MEDFileUMesh::changeFamilyIdArr(int oldId, int newId) throw(INTERP_KERNEL::Exception)
3698 {
3699   DataArrayInt *arr=_fam_coords;
3700   if(arr)
3701     arr->changeValue(oldId,newId);
3702   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
3703     {
3704       MEDFileUMeshSplitL1 *sp=(*it);
3705       if(sp)
3706         {
3707           sp->changeFamilyIdArr(oldId,newId);
3708         }
3709     }
3710 }
3711
3712 std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > MEDFileUMesh::getAllNonNullFamilyIds() const
3713 {
3714   std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret;
3715   const DataArrayInt *da(_fam_coords);
3716   if(da)
3717     { da->incrRef(); ret.push_back(MEDCouplingAutoRefCountObjectPtr<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
3718   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
3719     {
3720       const MEDFileUMeshSplitL1 *elt(*it);
3721       if(elt)
3722         {
3723           da=elt->getFamilyField();
3724           if(da)
3725             { da->incrRef(); ret.push_back(MEDCouplingAutoRefCountObjectPtr<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
3726         }
3727     }
3728   return ret;
3729 }
3730
3731 void MEDFileUMesh::computeRevNum() const
3732 {
3733   if((const DataArrayInt *)_num_coords)
3734     {
3735       int pos;
3736       int maxValue=_num_coords->getMaxValue(pos);
3737       _rev_num_coords=_num_coords->invertArrayN2O2O2N(maxValue+1);
3738     }
3739 }
3740
3741 std::size_t MEDFileStructuredMesh::getHeapMemorySize() const
3742 {
3743   std::size_t ret=MEDFileMesh::getHeapMemorySize();
3744   if((const DataArrayInt*)_fam_nodes)
3745     ret+=_fam_nodes->getHeapMemorySize();
3746   if((const DataArrayInt*)_num_nodes)
3747     ret+=_num_nodes->getHeapMemorySize();
3748   if((const DataArrayInt*)_fam_cells)
3749     ret+=_fam_cells->getHeapMemorySize();
3750   if((const DataArrayInt*)_num_cells)
3751     ret+=_num_cells->getHeapMemorySize();
3752   if((const DataArrayInt*)_rev_num_nodes)
3753     ret+=_rev_num_nodes->getHeapMemorySize();
3754   if((const DataArrayInt*)_rev_num_cells)
3755     ret+=_rev_num_cells->getHeapMemorySize();
3756   return ret;
3757 }
3758
3759 int MEDFileStructuredMesh::getMaxAbsFamilyIdInArrays() const throw(INTERP_KERNEL::Exception)
3760 {
3761   int ret=-std::numeric_limits<int>::max(),tmp=-1;
3762   if((const DataArrayInt *)_fam_nodes)
3763     {
3764       int val=_fam_nodes->getMaxValue(tmp);
3765       ret=std::max(ret,std::abs(val));
3766     }
3767   if((const DataArrayInt *)_fam_cells)
3768     {
3769       int val=_fam_cells->getMaxValue(tmp);
3770       ret=std::max(ret,std::abs(val));
3771     }
3772   return ret;
3773 }
3774
3775 int MEDFileStructuredMesh::getMaxFamilyIdInArrays() const throw(INTERP_KERNEL::Exception)
3776 {
3777   int ret=-std::numeric_limits<int>::max(),tmp=-1;
3778   if((const DataArrayInt *)_fam_nodes)
3779     {
3780       int val=_fam_nodes->getMaxValue(tmp);
3781       ret=std::max(ret,val);
3782     }
3783   if((const DataArrayInt *)_fam_cells)
3784     {
3785       int val=_fam_cells->getMaxValue(tmp);
3786       ret=std::max(ret,val);
3787     }
3788   return ret;
3789 }
3790
3791 int MEDFileStructuredMesh::getMinFamilyIdInArrays() const throw(INTERP_KERNEL::Exception)
3792 {
3793   int ret=std::numeric_limits<int>::max(),tmp=-1;
3794   if((const DataArrayInt *)_fam_nodes)
3795     {
3796       int val=_fam_nodes->getMinValue(tmp);
3797       ret=std::min(ret,val);
3798     }
3799   if((const DataArrayInt *)_fam_cells)
3800     {
3801       int val=_fam_cells->getMinValue(tmp);
3802       ret=std::min(ret,val);
3803     }
3804   return ret;
3805 }
3806
3807 bool MEDFileStructuredMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
3808 {
3809   if(!MEDFileMesh::isEqual(other,eps,what))
3810     return false;
3811   const MEDFileStructuredMesh *otherC=dynamic_cast<const  MEDFileStructuredMesh *>(other);
3812   if(!otherC)
3813     {
3814       what="Mesh types differ ! This is structured and other is NOT !";
3815       return false;
3816     }
3817   const DataArrayInt *famc1=_fam_nodes;
3818   const DataArrayInt *famc2=otherC->_fam_nodes;
3819   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
3820     {
3821       what="Mismatch of families arr on nodes ! One is defined and not other !";
3822       return false;
3823     }
3824   if(famc1)
3825     {
3826       bool ret=famc1->isEqual(*famc2);
3827       if(!ret)
3828         {
3829           what="Families arr on nodes differ !";
3830           return false;
3831         }
3832     }
3833   famc1=_fam_cells;
3834   famc2=otherC->_fam_cells;
3835   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
3836     {
3837       what="Mismatch of families arr on cells ! One is defined and not other !";
3838       return false;
3839     }
3840   if(famc1)
3841     {
3842       bool ret=famc1->isEqual(*famc2);
3843       if(!ret)
3844         {
3845           what="Families arr on cells differ !";
3846           return false;
3847         }
3848     }
3849   famc1=_num_nodes;
3850   famc2=otherC->_num_nodes;
3851   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
3852     {
3853       what="Mismatch of numbering arr on nodes ! One is defined and not other !";
3854       return false;
3855     }
3856   if(famc1)
3857     {
3858       bool ret=famc1->isEqual(*famc2);
3859       if(!ret)
3860         {
3861           what="Numbering arr on nodes differ !";
3862           return false;
3863         }
3864     }
3865   famc1=_num_cells;
3866   famc2=otherC->_num_cells;
3867   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
3868     {
3869       what="Mismatch of numbering arr on cells ! One is defined and not other !";
3870       return false;
3871     }
3872   if(famc1)
3873     {
3874       bool ret=famc1->isEqual(*famc2);
3875       if(!ret)
3876         {
3877           what="Numbering arr on cells differ !";
3878           return false;
3879         }
3880     }
3881   const DataArrayAsciiChar *d1=_names_cells;
3882   const DataArrayAsciiChar *d2=otherC->_names_cells;
3883   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
3884     {
3885       what="Mismatch of naming arr on cells ! One is defined and not other !";
3886       return false;
3887     }
3888   if(d1)
3889     {
3890       bool ret=d1->isEqual(*d2);
3891       if(!ret)
3892         {
3893           what="Naming arr on cells differ !";
3894           return false;
3895         }
3896     }
3897   d1=_names_nodes;
3898   d2=otherC->_names_nodes;
3899   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
3900     {
3901       what="Mismatch of naming arr on nodes ! One is defined and not other !";
3902       return false;
3903     }
3904   if(d1)
3905     {
3906       bool ret=d1->isEqual(*d2);
3907       if(!ret)
3908         {
3909           what="Naming arr on nodes differ !";
3910           return false;
3911         }
3912     }
3913   return true;
3914 }
3915
3916 void MEDFileStructuredMesh::clearNonDiscrAttributes() const
3917 {
3918   MEDFileMesh::clearNonDiscrAttributes();
3919   const DataArrayInt *tmp=_fam_nodes;
3920   if(tmp)
3921     (const_cast<DataArrayInt *>(tmp))->setName("");
3922   tmp=_num_nodes;
3923   if(tmp)
3924     (const_cast<DataArrayInt *>(tmp))->setName("");
3925   tmp=_fam_cells;
3926   if(tmp)
3927     (const_cast<DataArrayInt *>(tmp))->setName("");
3928   tmp=_num_cells;
3929   if(tmp)
3930     (const_cast<DataArrayInt *>(tmp))->setName("");
3931 }
3932
3933 /*!
3934  * Returns ids of mesh entities contained in given families of a given dimension.
3935  *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
3936  *          are required.
3937  *  \param [in] fams - the names of the families of interest.
3938  *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
3939  *          returned instead of ids.
3940  *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
3941  *          numbers, if available and required, of mesh entities of the families. The caller
3942  *          is to delete this array using decrRef() as it is no more needed. 
3943  *  \throw If the family field is missing for \a meshDimRelToMaxExt.
3944  */
3945 DataArrayInt *MEDFileStructuredMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const throw(INTERP_KERNEL::Exception)
3946 {
3947   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
3948     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : Only available for levels 0 or 1 !");
3949   std::vector<int> famIds=getFamiliesIds(fams);
3950   if(meshDimRelToMaxExt==1)
3951     {
3952       if((const DataArrayInt *)_fam_nodes)
3953         {
3954           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
3955           if(!famIds.empty())
3956             da=_fam_nodes->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
3957           else
3958             da=_fam_nodes->getIdsEqualList(0,0);
3959           if(renum)
3960             return MEDFileUMeshSplitL1::Renumber(_num_nodes,da);
3961           else
3962             return da.retn();
3963         }
3964       else
3965         throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on nodes !");
3966     }
3967   else
3968     {
3969       if((const DataArrayInt *)_fam_cells)
3970         {
3971           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
3972           if(!famIds.empty())
3973             da=_fam_cells->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
3974           else
3975             da=_fam_cells->getIdsEqualList(0,0);
3976           if(renum)
3977             return MEDFileUMeshSplitL1::Renumber(_num_cells,da);
3978           else
3979             return da.retn();
3980         }
3981       else
3982         throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on cells !");
3983     }
3984 }
3985
3986 /*!
3987  * Sets the family field of a given relative dimension.
3988  *  \param [in] meshDimRelToMaxExt - the relative dimension of entities for which
3989  *          the family field is set.
3990  *  \param [in] famArr - the array of the family field.
3991  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
3992  *  \throw If \a famArr has an invalid size.
3993  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
3994  */
3995 void MEDFileStructuredMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr) throw(INTERP_KERNEL::Exception)
3996 {
3997   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
3998     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : Only available for levels 0 or 1 !");
3999   const MEDCouplingStructuredMesh *mesh=getStructuredMesh();
4000   if(!mesh)
4001     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setFamilyFieldArr : no structured mesh specified ! Impossible to set family array !");
4002   if(meshDimRelToMaxExt==0)
4003     {
4004       int nbCells=mesh->getNumberOfCells();
4005       famArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of cells of mesh !");
4006       _fam_cells=famArr;
4007     }
4008   else
4009     {
4010       int nbNodes=mesh->getNumberOfNodes();
4011       famArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !");
4012       _fam_nodes=famArr;
4013     }
4014   if(famArr)
4015     famArr->incrRef();
4016 }
4017
4018 /*!
4019  * Sets the optional numbers of mesh entities of a given dimension.
4020  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4021  *  \param [in] renumArr - the array of the numbers.
4022  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4023  *  \throw If \a renumArr has an invalid size.
4024  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
4025  */
4026 void MEDFileStructuredMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr) throw(INTERP_KERNEL::Exception)
4027 {
4028   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4029     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : Only available for levels 0 or 1 !");
4030   const MEDCouplingStructuredMesh *mesh=getStructuredMesh();
4031   if(!mesh)
4032     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : no structured mesh specified ! Impossible to set number array !");
4033   if(meshDimRelToMaxExt==0)
4034     {
4035       int nbCells=mesh->getNumberOfCells();
4036       renumArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Renum arr ! Mismatch with number of cells of mesh !");
4037       _num_cells=renumArr;
4038     }
4039   else
4040     {
4041       int nbNodes=mesh->getNumberOfNodes();
4042       renumArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !");
4043       _num_nodes=renumArr;
4044     }
4045   if(renumArr)
4046     renumArr->incrRef();
4047 }
4048
4049 /*!
4050  * Sets the optional names of mesh entities of a given dimension.
4051  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4052  *  \param [in] nameArr - the array of the names.
4053  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4054  *  \throw If \a nameArr has an invalid size.
4055  */
4056 void MEDFileStructuredMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr) throw(INTERP_KERNEL::Exception)
4057 {
4058   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4059     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : Only available for levels 0 or 1 !");
4060   const MEDCouplingStructuredMesh *mesh=getStructuredMesh();
4061   if(!mesh)
4062     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : no structured mesh specified ! Impossible to set names array !");
4063   if(meshDimRelToMaxExt==0)
4064     {
4065       int nbCells=mesh->getNumberOfCells();
4066       nameArr->checkNbOfTuplesAndComp(nbCells,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of cells of mesh !");
4067       _names_cells=nameArr;
4068     }
4069   else
4070     {
4071       int nbNodes=mesh->getNumberOfNodes();
4072       nameArr->checkNbOfTuplesAndComp(nbNodes,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of nodes of mesh !");
4073       _names_nodes=nameArr;
4074     }
4075   if(nameArr)
4076     nameArr->incrRef();
4077 }
4078
4079 /*!
4080  * Returns the family field for mesh entities of a given dimension.
4081  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4082  *  \return const DataArrayInt * - the family field. It is an array of ids of families
4083  *          each mesh entity belongs to. It can be \c NULL.
4084  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
4085  */
4086 const DataArrayInt *MEDFileStructuredMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
4087 {
4088   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4089     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamilyFieldAtLevel : Only available for levels 0 or 1 !");
4090   if(meshDimRelToMaxExt==0)
4091     return _fam_cells;
4092   else
4093     return _fam_nodes;
4094 }
4095
4096 /*!
4097  * Returns the optional numbers of mesh entities of a given dimension.
4098  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4099  *  \return const DataArrayInt * - the array of the entity numbers.
4100  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4101  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
4102  */
4103 const DataArrayInt *MEDFileStructuredMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
4104 {
4105   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4106     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberFieldAtLevel : Only available for levels 0 or 1 !");
4107   if(meshDimRelToMaxExt==0)
4108     return _num_cells;
4109   else
4110     return _num_nodes;
4111 }
4112
4113 /*!
4114  * Returns the optional numbers of mesh entities of a given dimension transformed using
4115  * DataArrayInt::invertArrayN2O2O2N().
4116  *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
4117  *  \return const DataArrayInt * - the array of the entity numbers transformed using
4118  *          DataArrayInt::invertArrayN2O2O2N().
4119  *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
4120  *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
4121  */
4122 const DataArrayInt *MEDFileStructuredMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
4123 {
4124   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4125     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getRevNumberFieldAtLevel : Only available for levels 0 or 1 !");
4126   if(meshDimRelToMaxExt==0)
4127     {
4128       if((const DataArrayInt *)_num_cells)
4129         {
4130           int pos;
4131           int maxValue=_num_cells->getMaxValue(pos);
4132           _rev_num_cells=_num_cells->invertArrayN2O2O2N(maxValue+1);
4133           return _rev_num_cells;
4134         }
4135       else
4136         throw INTERP_KERNEL::Exception("MEDFileCMesh::getRevNumberFieldAtLevel : no cell renumbering for a request on reverse numbering !");
4137     }
4138   else
4139     {
4140       if((const DataArrayInt *)_num_nodes)
4141         {
4142           int pos;
4143           int maxValue=_num_nodes->getMaxValue(pos);
4144           _rev_num_nodes=_num_nodes->invertArrayN2O2O2N(maxValue+1);
4145           return _rev_num_nodes;
4146         }
4147       else
4148         throw INTERP_KERNEL::Exception("MEDFileCMesh::getRevNumberFieldAtLevel : no node renumbering for a request on reverse numbering !");
4149     }
4150 }
4151
4152 const DataArrayAsciiChar *MEDFileStructuredMesh::getNameFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
4153 {
4154   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4155     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNameFieldAtLevel : Only available for levels 0 or 1 !");
4156   if(meshDimRelToMaxExt==0)
4157     return _names_cells;
4158   else
4159     return _names_nodes;
4160 }
4161
4162 /*!
4163  * Returns relative dimensions of mesh entities (excluding nodes) present in \a this mesh.
4164  *  \return std::vector<int> - a sequence of the relative dimensions: [0].
4165  */
4166 std::vector<int> MEDFileStructuredMesh::getNonEmptyLevels() const
4167 {
4168   std::vector<int> ret(1);
4169   return ret;
4170 }
4171
4172 /*!
4173  * Returns relative dimensions of mesh entities (including nodes) present in \a this mesh.
4174  *  \return std::vector<int> - a sequence of the relative dimensions: [1,0].
4175  */
4176 std::vector<int> MEDFileStructuredMesh::getNonEmptyLevelsExt() const
4177 {
4178   std::vector<int> ret(2);
4179   ret[0]=1;
4180   return ret;
4181 }
4182
4183 /*!
4184  * Returns the set of extensive levels (nodes included) where not NULL family arr are defined.
4185  */
4186 std::vector<int> MEDFileStructuredMesh::getFamArrNonEmptyLevelsExt() const
4187 {
4188   std::vector<int> ret;
4189   const DataArrayInt *famNodes(_fam_nodes),*famCells(_fam_cells);
4190   if(famNodes)
4191     ret.push_back(1);
4192   if(famCells)
4193     ret.push_back(0);
4194   return ret;
4195 }
4196
4197 /*!
4198  * Returns the set of extensive levels (nodes included) where not NULL numbering arr are defined.
4199  */
4200 std::vector<int> MEDFileStructuredMesh::getNumArrNonEmptyLevelsExt() const
4201 {
4202   std::vector<int> ret;
4203   const DataArrayInt *numNodes(_num_nodes),*numCells(_num_cells);
4204   if(numNodes)
4205     ret.push_back(1);
4206   if(numCells)
4207     ret.push_back(0);
4208   return ret;
4209 }
4210
4211 /*!
4212  * Returns the set of extensive levels (nodes included) where not NULL naming arr are defined.
4213  */
4214 std::vector<int> MEDFileStructuredMesh::getNameArrNonEmptyLevelsExt() const
4215 {
4216   std::vector<int> ret;
4217   const DataArrayAsciiChar *namesCells(_names_cells);
4218   if(namesCells)
4219     ret.push_back(0);
4220   return ret;
4221 }
4222
4223 /*!
4224  * no implementation here, it is not a bug, but intresically no polyhedra in \a this.
4225  */
4226 bool MEDFileStructuredMesh::unPolyze(std::vector<int>& oldCode, std::vector<int>& newCode, DataArrayInt *& o2nRenumCell) throw(INTERP_KERNEL::Exception)
4227 {
4228   oldCode.clear(); newCode.clear(); o2nRenumCell=0;
4229   return false;
4230 }
4231
4232 void MEDFileStructuredMesh::changeFamilyIdArr(int oldId, int newId) throw(INTERP_KERNEL::Exception)
4233 {
4234   DataArrayInt *arr=_fam_nodes;
4235   if(arr)
4236     arr->changeValue(oldId,newId);
4237   arr=_fam_cells;
4238   if(arr)
4239     arr->changeValue(oldId,newId);
4240 }
4241
4242 void MEDFileStructuredMesh::deepCpyAttributes() throw(INTERP_KERNEL::Exception)
4243 {
4244   if((const DataArrayInt*)_fam_nodes)
4245     _fam_nodes=_fam_nodes->deepCpy();
4246   if((const DataArrayInt*)_num_nodes)
4247     _num_nodes=_num_nodes->deepCpy();
4248   if((const DataArrayInt*)_fam_cells)
4249     _fam_cells=_fam_cells->deepCpy();
4250   if((const DataArrayInt*)_num_cells)
4251     _num_cells=_num_cells->deepCpy();
4252   if((const DataArrayInt*)_rev_num_nodes)
4253     _rev_num_nodes=_rev_num_nodes->deepCpy();
4254   if((const DataArrayInt*)_rev_num_cells)
4255     _rev_num_cells=_rev_num_cells->deepCpy();
4256 }
4257
4258 /*!
4259  * Returns a pointer to mesh at the specified level (here 0 is compulsary for cartesian mesh).
4260  * 
4261  * \return a pointer to cartesian mesh that need to be managed by the caller.
4262  * \warning the returned pointer has to be managed by the caller.
4263  */
4264
4265 /*!
4266  * Returns a pointer to MEDCouplingStructuredMesh held by \a this. 
4267  *  \param [in] meshDimRelToMax - it must be \c 0.
4268  *  \param [in] renum - it must be \c false.
4269  *  \return MEDCouplingMesh * - a pointer to MEDCouplingMesh that the caller is to
4270  *          delete using decrRef() as it is no more needed. 
4271  */
4272 MEDCouplingMesh *MEDFileStructuredMesh::getGenMeshAtLevel(int meshDimRelToMax, bool renum) const throw(INTERP_KERNEL::Exception)
4273 {
4274   if(renum)
4275     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support renumbering ! To do it perform request of renum array directly !");
4276   if(meshDimRelToMax!=0)
4277     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support multi level for mesh 0 expected as input !");
4278   const MEDCouplingStructuredMesh *m=getStructuredMesh();
4279   if(m)
4280     m->incrRef();
4281   return const_cast<MEDCouplingStructuredMesh *>(m);
4282 }
4283
4284 /*!
4285  * Returns number of mesh entities of a given relative dimension in \a this mesh.
4286  *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
4287  *  \return int - the number of entities.
4288  *  \throw If no mesh entities of dimension \a meshDimRelToMaxExt are available in \a this mesh.
4289  */
4290 int MEDFileStructuredMesh::getSizeAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
4291 {
4292   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
4293     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : Only available for levels 0 or 1 !");
4294   const MEDCouplingStructuredMesh *cmesh=getStructuredMesh();
4295   if(!cmesh)
4296     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : No structured mesh set !");
4297   if(meshDimRelToMaxExt==0)
4298     return cmesh->getNumberOfCells();
4299   else
4300     return cmesh->getNumberOfNodes();
4301 }
4302
4303 int MEDFileStructuredMesh::getNumberOfNodes() const throw(INTERP_KERNEL::Exception)
4304 {
4305   const MEDCouplingStructuredMesh *cmesh=getStructuredMesh();
4306   if(!cmesh)
4307     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberOfNodes : no cartesian mesh set !");
4308   return cmesh->getNumberOfNodes();
4309 }
4310
4311 med_geometry_type MEDFileStructuredMesh::GetGeoTypeFromMeshDim(int meshDim) throw(INTERP_KERNEL::Exception)
4312 {
4313   med_geometry_type geoTypeReq=MED_NONE;
4314   switch(meshDim)
4315     {
4316     case 3:
4317       geoTypeReq=MED_HEXA8;
4318       break;
4319     case 2:
4320       geoTypeReq=MED_QUAD4;
4321       break;
4322     case 1:
4323       geoTypeReq=MED_SEG2;
4324       break;
4325     case 0:
4326       geoTypeReq=MED_POINT1;
4327       break;
4328     default:
4329       throw INTERP_KERNEL::Exception("Invalid meshdim detected for structured mesh ! Must be in (1,2,3) !");
4330     }
4331   return geoTypeReq;
4332 }
4333
4334 void MEDFileStructuredMesh::loadStrMeshFromFile(MEDFileStrMeshL2 *strm, med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
4335 {
4336   setName(strm->getName());
4337   setDescription(strm->getDescription());
4338   setUnivName(strm->getUnivName());
4339   setIteration(strm->getIteration());
4340   setOrder(strm->getOrder());
4341   setTimeValue(strm->getTime());
4342   setTimeUnit(strm->getTimeUnit());
4343   MEDFileMeshL2::ReadFamiliesAndGrps(fid,mName,_families,_groups);
4344   med_bool chgt=MED_FALSE,trsf=MED_FALSE;
4345   int nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_NODE,MED_NONE,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf);
4346   if(nbOfElt>0)
4347     {
4348       _fam_nodes=DataArrayInt::New();
4349       _fam_nodes->alloc(nbOfElt,1);
4350       MEDmeshEntityFamilyNumberRd(fid,mName,dt,it,MED_NODE,MED_NONE,_fam_nodes->getPointer());
4351     }
4352   nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_NODE,MED_NONE,MED_NUMBER,MED_NODAL,&chgt,&trsf);
4353   if(nbOfElt>0)
4354     {
4355       _num_nodes=DataArrayInt::New();
4356       _num_nodes->alloc(nbOfElt,1);
4357       MEDmeshEntityNumberRd(fid,mName,dt,it,MED_NODE,MED_NONE,_num_nodes->getPointer());
4358     }
4359   int meshDim=getStructuredMesh()->getMeshDimension();
4360   med_geometry_type geoTypeReq=GetGeoTypeFromMeshDim(meshDim);
4361   nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_CELL,geoTypeReq,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf);
4362   if(nbOfElt>0)
4363     {
4364       _fam_cells=DataArrayInt::New();
4365       _fam_cells->alloc(nbOfElt,1);
4366       MEDmeshEntityFamilyNumberRd(fid,mName,dt,it,MED_CELL,geoTypeReq,_fam_cells->getPointer());
4367     }
4368   nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_CELL,geoTypeReq,MED_NUMBER,MED_NODAL,&chgt,&trsf);
4369   if(nbOfElt>0)
4370     {
4371       _num_cells=DataArrayInt::New();
4372       _num_cells->alloc(nbOfElt,1);
4373       MEDmeshEntityNumberRd(fid,mName,dt,it,MED_CELL,geoTypeReq,_num_cells->getPointer());
4374     }
4375   nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_CELL,geoTypeReq,MED_NAME,MED_NODAL,&chgt,&trsf);
4376   if(nbOfElt>0)
4377     {
4378       _names_cells=DataArrayAsciiChar::New();
4379       _names_cells->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end
4380       MEDmeshEntityNameRd(fid,mName,dt,it,MED_CELL,geoTypeReq,_names_cells->getPointer());
4381       _names_cells->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end
4382     }
4383   nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_NODE,MED_NONE,MED_NAME,MED_NODAL,&chgt,&trsf);
4384   if(nbOfElt>0)
4385     {
4386       _names_nodes=DataArrayAsciiChar::New();
4387       _names_nodes->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end
4388       MEDmeshEntityNameRd(fid,mName,dt,it,MED_NODE,MED_NONE,_names_nodes->getPointer());
4389       _names_nodes->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end
4390     }
4391 }
4392
4393 void MEDFileStructuredMesh::writeStructuredLL(med_idt fid, const char *maa) const throw(INTERP_KERNEL::Exception)
4394 {
4395   int meshDim=getStructuredMesh()->getMeshDimension();
4396   med_geometry_type geoTypeReq=GetGeoTypeFromMeshDim(meshDim);
4397   //
4398   if((const DataArrayInt *)_fam_cells)
4399     MEDmeshEntityFamilyNumberWr(fid,maa,_iteration,_order,MED_CELL,geoTypeReq,_fam_cells->getNumberOfTuples(),_fam_cells->getConstPointer());
4400   if((const DataArrayInt *)_fam_nodes)
4401     MEDmeshEntityFamilyNumberWr(fid,maa,_iteration,_order,MED_NODE,MED_NONE,_fam_nodes->getNumberOfTuples(),_fam_nodes->getConstPointer());
4402   if((const DataArrayInt *)_num_cells)
4403     MEDmeshEntityNumberWr(fid,maa,_iteration,_order,MED_CELL,geoTypeReq,_num_cells->getNumberOfTuples(),_num_cells->getConstPointer());
4404   if((const DataArrayInt *)_num_nodes)
4405     MEDmeshEntityNumberWr(fid,maa,_iteration,_order,MED_NODE,MED_NONE,_num_nodes->getNumberOfTuples(),_num_nodes->getConstPointer());
4406   if((const DataArrayAsciiChar *)_names_cells)
4407     {
4408       if(_names_cells->getNumberOfComponents()!=MED_SNAME_SIZE)
4409         {
4410           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on cells with number of components set to " << MED_SNAME_SIZE;
4411           oss << " ! The array has " << _names_cells->getNumberOfComponents() << " components !";
4412           throw INTERP_KERNEL::Exception(oss.str().c_str());
4413         }
4414       MEDmeshEntityNameWr(fid,maa,_iteration,_order,MED_CELL,geoTypeReq,_names_cells->getNumberOfTuples(),_names_cells->getConstPointer());
4415     }
4416   if((const DataArrayAsciiChar *)_names_nodes)
4417     {
4418       if(_names_nodes->getNumberOfComponents()!=MED_SNAME_SIZE)
4419         {
4420           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on nodes with number of components set to " << MED_SNAME_SIZE;
4421           oss << " ! The array has " << _names_cells->getNumberOfComponents() << " components !";
4422           throw INTERP_KERNEL::Exception(oss.str().c_str());
4423         }
4424       MEDmeshEntityNameWr(fid,maa,_iteration,_order,MED_NODE,MED_NONE,_names_nodes->getNumberOfTuples(),_names_nodes->getConstPointer());
4425     }
4426   //
4427   MEDFileUMeshL2::WriteFamiliesAndGrps(fid,maa,_families,_groups,_too_long_str);
4428 }
4429
4430 /*!
4431  * Returns an empty instance of MEDFileCMesh.
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  */
4435 MEDFileCMesh *MEDFileCMesh::New()
4436 {
4437   return new MEDFileCMesh;
4438 }
4439
4440 /*!
4441  * Returns a new MEDFileCMesh holding the mesh data that has been read from a given MED
4442  * file. The first mesh in the file is loaded.
4443  *  \param [in] fileName - the name of MED file to read.
4444  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
4445  *          mesh using decrRef() as it is no more needed. 
4446  *  \throw If the file is not readable.
4447  *  \throw If there is no meshes in the file.
4448  *  \throw If the mesh in the file is not a Cartesian one.
4449  */
4450 MEDFileCMesh *MEDFileCMesh::New(const char *fileName) throw(INTERP_KERNEL::Exception)
4451 {
4452   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
4453   if(ms.empty())
4454     {
4455       std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
4456       throw INTERP_KERNEL::Exception(oss.str().c_str());
4457     }
4458   MEDFileUtilities::CheckFileForRead(fileName);
4459   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
4460   int dt,it;
4461   ParaMEDMEM::MEDCouplingMeshType meshType;
4462   std::string dummy2;
4463   MEDFileMeshL2::GetMeshIdFromName(fid,ms.front().c_str(),meshType,dt,it,dummy2);
4464   return new MEDFileCMesh(fid,ms.front().c_str(),dt,it);
4465 }
4466
4467 /*!
4468  * Returns a new MEDFileCMesh holding the mesh data that has been read from a given MED
4469  * file. The mesh to load is specified by its name and numbers of a time step and an
4470  * iteration.
4471  *  \param [in] fileName - the name of MED file to read.
4472  *  \param [in] mName - the name of the mesh to read.
4473  *  \param [in] dt - the number of a time step.
4474  *  \param [in] it - the number of an iteration.
4475  *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
4476  *          mesh using decrRef() as it is no more needed. 
4477  *  \throw If the file is not readable.
4478  *  \throw If there is no mesh with given attributes in the file.
4479  *  \throw If the mesh in the file is not a Cartesian one.
4480  */
4481 MEDFileCMesh *MEDFileCMesh::New(const char *fileName, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
4482 {
4483   MEDFileUtilities::CheckFileForRead(fileName);
4484   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
4485   return new MEDFileCMesh(fid,mName,dt,it);
4486 }
4487
4488 std::size_t MEDFileCMesh::getHeapMemorySize() const
4489 {
4490   std::size_t ret=MEDFileStructuredMesh::getHeapMemorySize();
4491   if((const MEDCouplingCMesh *)_cmesh)
4492     ret+=_cmesh->getHeapMemorySize();
4493   return ret;
4494 }
4495
4496 /*!
4497  * Returns the dimension on cells in \a this mesh.
4498  *  \return int - the mesh dimension.
4499  *  \throw If there are no cells in this mesh.
4500  */
4501 int MEDFileCMesh::getMeshDimension() const throw(INTERP_KERNEL::Exception)
4502 {
4503   if(!((const MEDCouplingCMesh*)_cmesh))
4504     throw INTERP_KERNEL::Exception("MEDFileCMesh::getMeshDimension : unable to get meshdimension because no mesh set !");
4505   return _cmesh->getMeshDimension();
4506 }
4507
4508 /*!
4509  * Returns a string describing \a this mesh.
4510  *  \return std::string - the mesh information string.
4511  */
4512 std::string MEDFileCMesh::simpleRepr() const
4513 {
4514   return MEDFileStructuredMesh::simpleRepr();
4515 }
4516
4517 /*!
4518  * Returns a full textual description of \a this mesh.
4519  *  \return std::string - the string holding the mesh description.
4520  */
4521 std::string MEDFileCMesh::advancedRepr() const
4522 {
4523   return simpleRepr();
4524 }
4525
4526 MEDFileMesh *MEDFileCMesh::shallowCpy() const throw(INTERP_KERNEL::Exception)
4527 {
4528   MEDCouplingAutoRefCountObjectPtr<MEDFileCMesh> ret=new MEDFileCMesh(*this);
4529   return ret.retn();
4530 }
4531
4532 MEDFileMesh *MEDFileCMesh::createNewEmpty() const throw(INTERP_KERNEL::Exception)
4533 {
4534   return new MEDFileCMesh;
4535 }
4536
4537 MEDFileMesh *MEDFileCMesh::deepCpy() const throw(INTERP_KERNEL::Exception)
4538 {
4539   MEDCouplingAutoRefCountObjectPtr<MEDFileCMesh> ret=new MEDFileCMesh(*this);
4540   if((const MEDCouplingCMesh*)_cmesh)
4541     ret->_cmesh=static_cast<MEDCouplingCMesh*>(_cmesh->deepCpy());
4542   ret->deepCpyAttributes();
4543   return ret.retn();
4544 }
4545
4546 /*!
4547  * Checks if \a this and another mesh are equal.
4548  *  \param [in] other - the mesh to compare with.
4549  *  \param [in] eps - a precision used to compare real values.
4550  *  \param [in,out] what - the string returning description of unequal data.
4551  *  \return bool - \c true if the meshes are equal, \c false, else.
4552  */
4553 bool MEDFileCMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
4554 {
4555   if(!MEDFileStructuredMesh::isEqual(other,eps,what))
4556     return false;
4557   const MEDFileCMesh *otherC=dynamic_cast<const MEDFileCMesh *>(other);
4558   if(!otherC)
4559     {
4560       what="Mesh types differ ! This is cartesian and other is NOT !";
4561       return false;
4562     }
4563   clearNonDiscrAttributes();
4564   otherC->clearNonDiscrAttributes();
4565   const MEDCouplingCMesh *coo1=_cmesh;
4566   const MEDCouplingCMesh *coo2=otherC->_cmesh;
4567   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
4568     {
4569       what="Mismatch of cartesian meshes ! One is defined and not other !";
4570       return false;
4571     }
4572   if(coo1)
4573     {
4574       bool ret=coo1->isEqual(coo2,eps);
4575       if(!ret)
4576         {
4577           what="cartesian meshes differ !";
4578           return false;
4579         }
4580     }
4581   return true;
4582 }
4583
4584 /*!
4585  * Clears redundant attributes of incorporated data arrays.
4586  */
4587 void MEDFileCMesh::clearNonDiscrAttributes() const
4588 {
4589   MEDFileStructuredMesh::clearNonDiscrAttributes();
4590   MEDFileUMeshSplitL1::ClearNonDiscrAttributes(_cmesh);//to it is not a bug umeshsplit have already the method implemented
4591 }
4592
4593 MEDFileCMesh::MEDFileCMesh()
4594 {
4595 }
4596
4597 MEDFileCMesh::MEDFileCMesh(med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
4598 try
4599   {
4600     loadCMeshFromFile(fid,mName,dt,it);
4601   }
4602 catch(INTERP_KERNEL::Exception& e)
4603   {
4604     throw e;
4605   }
4606
4607 void MEDFileCMesh::loadCMeshFromFile(med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
4608 {
4609   ParaMEDMEM::MEDCouplingMeshType meshType;
4610   int dummy0,dummy1;
4611   std::string dtunit;
4612   int mid=MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dtunit);
4613   if(meshType!=CARTESIAN)
4614     {
4615       std::ostringstream oss; oss << "Trying to load as cartesian an existing mesh with name '" << mName << "' that is NOT cartesian !";
4616       throw INTERP_KERNEL::Exception(oss.str().c_str());
4617     }
4618   MEDFileCMeshL2 loaderl2;
4619   loaderl2.loadAll(fid,mid,mName,dt,it);
4620   MEDCouplingCMesh *mesh=loaderl2.getMesh();
4621   mesh->incrRef();
4622   _cmesh=mesh;
4623   loadStrMeshFromFile(&loaderl2,fid,mName,dt,it);
4624 }
4625
4626 /*!
4627  * Returns a const pointer to MEDCouplingCMesh held by \a this mesh.
4628  *  \return const MEDCouplingCMesh * - a pointer to the held MEDCouplingCMesh.
4629  */
4630 const MEDCouplingCMesh *MEDFileCMesh::getMesh() const
4631 {
4632   synchronizeTinyInfoOnLeaves();
4633   return _cmesh;
4634 }
4635
4636 const MEDCouplingStructuredMesh *MEDFileCMesh::getStructuredMesh() const
4637 {
4638   synchronizeTinyInfoOnLeaves();
4639   return _cmesh;
4640 }
4641
4642 /*!
4643  * Sets the MEDCouplingCMesh holding the data of \a this mesh.
4644  *  \param [in] m - the new MEDCouplingCMesh to refer to.
4645  *  \throw If the name or the description of \a this mesh and \a m are not empty and are
4646  *         different. 
4647  */
4648 void MEDFileCMesh::setMesh(MEDCouplingCMesh *m) throw(INTERP_KERNEL::Exception)
4649 {
4650   dealWithTinyInfo(m);
4651   if(m)
4652     m->incrRef();
4653   _cmesh=m;
4654 }
4655
4656 void MEDFileCMesh::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception)
4657 {
4658   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
4659   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
4660   INTERP_KERNEL::AutoPtr<char> dtunit=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE);
4661   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
4662   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
4663   MEDLoaderBase::safeStrCpy(_dt_unit.c_str(),MED_LNAME_SIZE,dtunit,_too_long_str);
4664   int spaceDim=_cmesh->getSpaceDimension();
4665   int meshDim=_cmesh->getMeshDimension();
4666   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
4667   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
4668   for(int i=0;i<spaceDim;i++)
4669     {
4670       std::string info(_cmesh->getCoordsAt(i)->getInfoOnComponent(0));
4671       std::string c,u;
4672       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
4673       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
4674       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
4675     }
4676   MEDmeshCr(fid,maa,spaceDim,meshDim,MED_STRUCTURED_MESH,desc,dtunit,MED_SORT_DTIT,MED_CARTESIAN,comp,unit);
4677   MEDmeshUniversalNameWr(fid,maa);
4678   MEDmeshGridTypeWr(fid,maa,MED_CARTESIAN_GRID);
4679   for(int i=0;i<spaceDim;i++)
4680     {
4681       const DataArrayDouble *da=_cmesh->getCoordsAt(i);
4682       MEDmeshGridIndexCoordinateWr(fid,maa,_iteration,_order,_time,i+1,da->getNumberOfTuples(),da->getConstPointer());
4683     }
4684   //
4685   MEDFileStructuredMesh::writeStructuredLL(fid,maa);
4686 }
4687
4688 void MEDFileCMesh::synchronizeTinyInfoOnLeaves() const
4689 {
4690   const MEDCouplingCMesh *cmesh=_cmesh;
4691   if(!cmesh)
4692     return;
4693   (const_cast<MEDCouplingCMesh *>(cmesh))->setName(_name.c_str());
4694   (const_cast<MEDCouplingCMesh *>(cmesh))->setDescription(_desc_name.c_str());
4695   (const_cast<MEDCouplingCMesh *>(cmesh))->setTime(_time,_iteration,_order);
4696   (const_cast<MEDCouplingCMesh *>(cmesh))->setTimeUnit(_dt_unit.c_str());
4697 }
4698
4699 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New()
4700 {
4701   return new MEDFileCurveLinearMesh;
4702 }
4703
4704 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const char *fileName) throw(INTERP_KERNEL::Exception)
4705 {
4706   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
4707   if(ms.empty())
4708     {
4709       std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
4710       throw INTERP_KERNEL::Exception(oss.str().c_str());
4711     }
4712   MEDFileUtilities::CheckFileForRead(fileName);
4713   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
4714   int dt,it;
4715   ParaMEDMEM::MEDCouplingMeshType meshType;
4716   std::string dummy2;
4717   MEDFileMeshL2::GetMeshIdFromName(fid,ms.front().c_str(),meshType,dt,it,dummy2);
4718   return new MEDFileCurveLinearMesh(fid,ms.front().c_str(),dt,it);
4719 }
4720
4721 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const char *fileName, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
4722 {
4723   MEDFileUtilities::CheckFileForRead(fileName);
4724   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
4725   return new MEDFileCurveLinearMesh(fid,mName,dt,it);
4726 }
4727
4728 std::size_t MEDFileCurveLinearMesh::getHeapMemorySize() const
4729 {
4730   std::size_t ret=MEDFileStructuredMesh::getHeapMemorySize();
4731   if((const MEDCouplingCurveLinearMesh *)_clmesh)
4732     ret+=_clmesh->getHeapMemorySize();
4733   return ret;
4734 }
4735
4736 MEDFileMesh *MEDFileCurveLinearMesh::shallowCpy() const throw(INTERP_KERNEL::Exception)
4737 {
4738   MEDCouplingAutoRefCountObjectPtr<MEDFileCurveLinearMesh> ret=new MEDFileCurveLinearMesh(*this);
4739   return ret.retn();
4740 }
4741
4742 MEDFileMesh *MEDFileCurveLinearMesh::createNewEmpty() const throw(INTERP_KERNEL::Exception)
4743 {
4744   return new MEDFileCurveLinearMesh;
4745 }
4746
4747 MEDFileMesh *MEDFileCurveLinearMesh::deepCpy() const throw(INTERP_KERNEL::Exception)
4748 {
4749   MEDCouplingAutoRefCountObjectPtr<MEDFileCurveLinearMesh> ret=new MEDFileCurveLinearMesh(*this);
4750   if((const MEDCouplingCurveLinearMesh*)_clmesh)
4751     ret->_clmesh=static_cast<MEDCouplingCurveLinearMesh*>(_clmesh->deepCpy());
4752   ret->deepCpyAttributes();
4753   return ret.retn();
4754 }
4755
4756 int MEDFileCurveLinearMesh::getMeshDimension() const throw(INTERP_KERNEL::Exception)
4757 {
4758   if(!((const MEDCouplingCurveLinearMesh*)_clmesh))
4759     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::getMeshDimension : unable to get meshdimension because no mesh set !");
4760   return _clmesh->getMeshDimension();
4761 }
4762
4763 std::string MEDFileCurveLinearMesh::simpleRepr() const
4764 {
4765   return MEDFileStructuredMesh::simpleRepr();
4766 }
4767
4768 std::string MEDFileCurveLinearMesh::advancedRepr() const
4769 {
4770   return simpleRepr();
4771 }
4772
4773 bool MEDFileCurveLinearMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
4774 {
4775   if(!MEDFileStructuredMesh::isEqual(other,eps,what))
4776     return false;
4777   const MEDFileCurveLinearMesh *otherC=dynamic_cast<const MEDFileCurveLinearMesh *>(other);
4778   if(!otherC)
4779     {
4780       what="Mesh types differ ! This is curve linear and other is NOT !";
4781       return false;
4782     }
4783   clearNonDiscrAttributes();
4784   otherC->clearNonDiscrAttributes();
4785   const MEDCouplingCurveLinearMesh *coo1=_clmesh;
4786   const MEDCouplingCurveLinearMesh *coo2=otherC->_clmesh;
4787   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
4788     {
4789       what="Mismatch of curve linear meshes ! One is defined and not other !";
4790       return false;
4791     }
4792   if(coo1)
4793     {
4794       bool ret=coo1->isEqual(coo2,eps);
4795       if(!ret)
4796         {
4797           what="curve linear meshes differ !";
4798           return false;
4799         }
4800     }
4801   return true;
4802 }
4803
4804 void MEDFileCurveLinearMesh::clearNonDiscrAttributes() const
4805 {
4806   MEDFileStructuredMesh::clearNonDiscrAttributes();
4807   MEDFileUMeshSplitL1::ClearNonDiscrAttributes(_clmesh);//to it is not a bug umeshsplit have already the method implemented
4808 }
4809
4810 void MEDFileCurveLinearMesh::synchronizeTinyInfoOnLeaves() const
4811 {
4812   const MEDCouplingCurveLinearMesh *clmesh=_clmesh;
4813   if(!clmesh)
4814     return;
4815   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setName(_name.c_str());
4816   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setDescription(_desc_name.c_str());
4817   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setTime(_time,_iteration,_order);
4818   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setTimeUnit(_dt_unit.c_str());
4819 }
4820
4821 const MEDCouplingCurveLinearMesh *MEDFileCurveLinearMesh::getMesh() const
4822 {
4823   synchronizeTinyInfoOnLeaves();
4824   return _clmesh;
4825 }
4826
4827 void MEDFileCurveLinearMesh::setMesh(MEDCouplingCurveLinearMesh *m) throw(INTERP_KERNEL::Exception)
4828 {
4829   dealWithTinyInfo(m);
4830   if(m)
4831     m->incrRef();
4832   _clmesh=m;
4833 }
4834
4835 const MEDCouplingStructuredMesh *MEDFileCurveLinearMesh::getStructuredMesh() const
4836 {
4837   synchronizeTinyInfoOnLeaves();
4838   return _clmesh;
4839 }
4840
4841 MEDFileCurveLinearMesh::MEDFileCurveLinearMesh()
4842 {
4843 }
4844
4845 MEDFileCurveLinearMesh::MEDFileCurveLinearMesh(med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
4846 try
4847   {
4848     loadCLMeshFromFile(fid,mName,dt,it);
4849   }
4850 catch(INTERP_KERNEL::Exception& e)
4851   {
4852     throw e;
4853   }
4854
4855 void MEDFileCurveLinearMesh::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception)
4856 {
4857   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
4858   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
4859   INTERP_KERNEL::AutoPtr<char> dtunit=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE);
4860   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
4861   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
4862   MEDLoaderBase::safeStrCpy(_dt_unit.c_str(),MED_LNAME_SIZE,dtunit,_too_long_str);
4863   int spaceDim=_clmesh->getSpaceDimension();
4864   int meshDim=_clmesh->getMeshDimension();
4865   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
4866   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
4867   const DataArrayDouble *coords=_clmesh->getCoords();
4868   if(!coords)
4869     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::writeLL : no coordinates set !");
4870   for(int i=0;i<spaceDim;i++)
4871     {
4872       std::string info(_clmesh->getCoords()->getInfoOnComponent(i));
4873       std::string c,u;
4874       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
4875       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
4876       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
4877     }
4878   MEDmeshCr(fid,maa,spaceDim,meshDim,MED_STRUCTURED_MESH,desc,dtunit,MED_SORT_DTIT,MED_CARTESIAN,comp,unit);
4879   MEDmeshUniversalNameWr(fid,maa);
4880   MEDmeshGridTypeWr(fid,maa,MED_CURVILINEAR_GRID);
4881   std::vector<int> nodeGridSt=_clmesh->getNodeGridStructure();
4882   MEDmeshGridStructWr(fid,maa,_iteration,_order,_time,&nodeGridSt[0]);
4883   
4884   MEDmeshNodeCoordinateWr(fid,maa,_iteration,_order,_time,MED_FULL_INTERLACE,coords->getNumberOfTuples(),coords->begin());
4885   //
4886   MEDFileStructuredMesh::writeStructuredLL(fid,maa);
4887 }
4888
4889 void MEDFileCurveLinearMesh::loadCLMeshFromFile(med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
4890 {
4891   ParaMEDMEM::MEDCouplingMeshType meshType;
4892   int dummy0,dummy1;
4893   std::string dtunit;
4894   int mid=MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dtunit);
4895   if(meshType!=CURVE_LINEAR)
4896     {
4897       std::ostringstream oss; oss << "Trying to load as curve linear an existing mesh with name '" << mName << "' that is NOT curve linear !";
4898       throw INTERP_KERNEL::Exception(oss.str().c_str());
4899     }
4900   MEDFileCLMeshL2 loaderl2;
4901   loaderl2.loadAll(fid,mid,mName,dt,it);
4902   MEDCouplingCurveLinearMesh *mesh=loaderl2.getMesh();
4903   mesh->incrRef();
4904   _clmesh=mesh;
4905   loadStrMeshFromFile(&loaderl2,fid,mName,dt,it);
4906 }
4907
4908 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New()
4909 {
4910   return new MEDFileMeshMultiTS;
4911 }
4912
4913 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(const char *fileName) throw(INTERP_KERNEL::Exception)
4914 {
4915   return new MEDFileMeshMultiTS(fileName);
4916 }
4917
4918 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(const char *fileName, const char *mName) throw(INTERP_KERNEL::Exception)
4919 {
4920   return new MEDFileMeshMultiTS(fileName,mName);
4921 }
4922
4923 MEDFileMeshMultiTS *MEDFileMeshMultiTS::deepCpy() const throw(INTERP_KERNEL::Exception)
4924 {
4925   MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> ret=MEDFileMeshMultiTS::New();
4926   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> > meshOneTs(_mesh_one_ts.size());
4927   std::size_t i=0;
4928   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++,i++)
4929     if((const MEDFileMesh *)*it)
4930       meshOneTs[i]=(*it)->deepCpy();
4931   ret->_mesh_one_ts=meshOneTs;
4932   return ret.retn();
4933 }
4934
4935 std::size_t MEDFileMeshMultiTS::getHeapMemorySize() const
4936 {
4937   std::size_t ret=_mesh_one_ts.capacity()*sizeof(MEDCouplingAutoRefCountObjectPtr<MEDFileMesh>);
4938   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
4939     ret+=(*it)->getHeapMemorySize();
4940   return ret;
4941 }
4942
4943 const char *MEDFileMeshMultiTS::getName() const throw(INTERP_KERNEL::Exception)
4944 {
4945   if(_mesh_one_ts.empty())
4946     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::getName : no time steps set !");
4947   return _mesh_one_ts[0]->getName();
4948 }
4949
4950 void MEDFileMeshMultiTS::setName(const char *newMeshName) throw(INTERP_KERNEL::Exception)
4951 {
4952   std::string oldName(getName());
4953   std::vector< std::pair<std::string,std::string> > v(1);
4954   v[0].first=oldName; v[0].second=newMeshName;
4955   changeNames(v);
4956 }
4957
4958 bool MEDFileMeshMultiTS::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab) throw(INTERP_KERNEL::Exception)
4959 {
4960   bool ret=false;
4961   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
4962     {
4963       MEDFileMesh *cur(*it);
4964       if(cur)
4965         ret=cur->changeNames(modifTab) || ret;
4966     }
4967   return ret;
4968 }
4969
4970 MEDFileMesh *MEDFileMeshMultiTS::getOneTimeStep() const throw(INTERP_KERNEL::Exception)
4971 {
4972   if(_mesh_one_ts.empty())
4973     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::getOneTimeStep : empty time step set !");
4974   return const_cast<MEDFileMesh *>(static_cast<const MEDFileMesh *>(_mesh_one_ts[0]));
4975 }
4976
4977 void MEDFileMeshMultiTS::setOneTimeStep(MEDFileMesh *mesh1TimeStep) throw(INTERP_KERNEL::Exception)
4978 {
4979   if(!mesh1TimeStep)
4980     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::setOneTimeStep : input pointer should be different from 0 !");
4981   _mesh_one_ts.resize(1);
4982   mesh1TimeStep->incrRef();
4983   //MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> toto=mesh1TimeStep;
4984   _mesh_one_ts[0]=mesh1TimeStep;
4985 }
4986
4987 void MEDFileMeshMultiTS::write(med_idt fid) const throw(INTERP_KERNEL::Exception)
4988 {
4989   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
4990     {
4991       (*it)->copyOptionsFrom(*this);
4992       (*it)->write(fid);
4993     }
4994 }
4995
4996 void MEDFileMeshMultiTS::write(const char *fileName, int mode) const throw(INTERP_KERNEL::Exception)
4997 {
4998   med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode);
4999   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,medmod);
5000   std::ostringstream oss; oss << "MEDFileMesh : error on attempt to write in file : \"" << fileName << "\""; 
5001   MEDFileUtilities::CheckMEDCode(fid,fid,oss.str().c_str());
5002   write(fid);
5003 }
5004
5005 void MEDFileMeshMultiTS::loadFromFile(const char *fileName, const char *mName) throw(INTERP_KERNEL::Exception)
5006 {//for the moment to be improved
5007   _mesh_one_ts.resize(1);
5008   _mesh_one_ts[0]=MEDFileMesh::New(fileName,mName,-1,-1);
5009 }
5010
5011 MEDFileMeshMultiTS::MEDFileMeshMultiTS()
5012 {
5013 }
5014
5015 MEDFileMeshMultiTS::MEDFileMeshMultiTS(const char *fileName) throw(INTERP_KERNEL::Exception)
5016 try
5017   {
5018     std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
5019     if(ms.empty())
5020     {
5021       std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
5022       throw INTERP_KERNEL::Exception(oss.str().c_str());
5023     }
5024     MEDFileUtilities::CheckFileForRead(fileName);
5025     MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
5026     int dt,it;
5027     ParaMEDMEM::MEDCouplingMeshType meshType;
5028     std::string dummy2;
5029     MEDFileMeshL2::GetMeshIdFromName(fid,ms.front().c_str(),meshType,dt,it,dummy2);
5030     loadFromFile(fileName,ms.front().c_str());
5031   }
5032 catch(INTERP_KERNEL::Exception& e)
5033   {
5034     throw e;
5035   }
5036
5037 MEDFileMeshMultiTS::MEDFileMeshMultiTS(const char *fileName, const char *mName) throw(INTERP_KERNEL::Exception)
5038 try
5039   {
5040     loadFromFile(fileName,mName);
5041   }
5042 catch(INTERP_KERNEL::Exception& e)
5043   {
5044     throw e;
5045   }
5046
5047 MEDFileMeshes *MEDFileMeshes::New()
5048 {
5049   return new MEDFileMeshes;
5050 }
5051
5052 MEDFileMeshes *MEDFileMeshes::New(const char *fileName) throw(INTERP_KERNEL::Exception)
5053 {
5054   return new MEDFileMeshes(fileName);
5055 }
5056
5057 void MEDFileMeshes::write(med_idt fid) const throw(INTERP_KERNEL::Exception)
5058 {
5059   checkCoherency();
5060   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++)
5061     {
5062       (*it)->copyOptionsFrom(*this);
5063       (*it)->write(fid);
5064     }
5065 }
5066
5067 void MEDFileMeshes::write(const char *fileName, int mode) const throw(INTERP_KERNEL::Exception)
5068 {
5069   med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode);
5070   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,medmod);
5071   std::ostringstream oss; oss << "MEDFileMesh : error on attempt to write in file : \"" << fileName << "\""; 
5072   MEDFileUtilities::CheckMEDCode(fid,fid,oss.str().c_str());
5073   checkCoherency();
5074   write(fid);
5075 }
5076
5077 int MEDFileMeshes::getNumberOfMeshes() const throw(INTERP_KERNEL::Exception)
5078 {
5079   return _meshes.size();
5080 }
5081
5082 MEDFileMeshesIterator *MEDFileMeshes::iterator() throw(INTERP_KERNEL::Exception)
5083 {
5084   return new MEDFileMeshesIterator(this);
5085 }
5086
5087 MEDFileMesh *MEDFileMeshes::getMeshAtPos(int i) const throw(INTERP_KERNEL::Exception)
5088 {
5089   if(i<0 || i>=(int)_meshes.size())
5090     {
5091       std::ostringstream oss; oss << "MEDFileMeshes::getMeshAtPos : invalid mesh id given in parameter ! Should be in [0;" << _meshes.size() << ") !";
5092       throw INTERP_KERNEL::Exception(oss.str().c_str());
5093     }
5094   return _meshes[i]->getOneTimeStep();
5095 }
5096
5097 MEDFileMesh *MEDFileMeshes::getMeshWithName(const char *mname) const throw(INTERP_KERNEL::Exception)
5098 {
5099   std::vector<std::string> ms=getMeshesNames();
5100   std::vector<std::string>::iterator it=std::find(ms.begin(),ms.end(),mname);
5101   if(it==ms.end())
5102     {
5103       std::ostringstream oss; oss << "MEDFileMeshes::getMeshWithName : Mesh  \"" << mname << "\" does not exist in this ! Existing are : ";
5104       std::copy(ms.begin(),ms.end(),std::ostream_iterator<std::string>(oss," "));
5105       throw INTERP_KERNEL::Exception(oss.str().c_str());
5106     }
5107   return getMeshAtPos((int)std::distance(ms.begin(),it));
5108 }
5109
5110 std::vector<std::string> MEDFileMeshes::getMeshesNames() const throw(INTERP_KERNEL::Exception)
5111 {
5112   std::vector<std::string> ret(_meshes.size());
5113   int i=0;
5114   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
5115     {
5116       const MEDFileMeshMultiTS *f=(*it);
5117       if(f)
5118         {
5119           ret[i]=f->getName();
5120         }
5121       else
5122         {
5123           std::ostringstream oss; oss << "MEDFileMeshes::getMeshesNames : At rank #" << i << " mesh is not defined !";
5124           throw INTERP_KERNEL::Exception(oss.str().c_str());
5125         }
5126     }
5127   return ret;
5128 }
5129
5130 bool MEDFileMeshes::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab) throw(INTERP_KERNEL::Exception)
5131 {
5132   bool ret=false;
5133   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::iterator it=_meshes.begin();it!=_meshes.end();it++)
5134     {
5135       MEDFileMeshMultiTS *cur(*it);
5136       if(cur)
5137         ret=cur->changeNames(modifTab) || ret;
5138     }
5139   return ret;
5140 }
5141
5142 void MEDFileMeshes::resize(int newSize) throw(INTERP_KERNEL::Exception)
5143 {
5144   _meshes.resize(newSize);
5145 }
5146
5147 void MEDFileMeshes::pushMesh(MEDFileMesh *mesh) throw(INTERP_KERNEL::Exception)
5148 {
5149   if(!mesh)
5150     throw INTERP_KERNEL::Exception("MEDFileMeshes::pushMesh : invalid input pointer ! should be different from 0 !");
5151   MEDFileMeshMultiTS *elt=MEDFileMeshMultiTS::New();
5152   elt->setOneTimeStep(mesh);
5153   _meshes.push_back(elt);
5154 }
5155
5156 void MEDFileMeshes::setMeshAtPos(int i, MEDFileMesh *mesh) throw(INTERP_KERNEL::Exception)
5157 {
5158   if(!mesh)
5159     throw INTERP_KERNEL::Exception("MEDFileMeshes::setMeshAtPos : invalid input pointer ! should be different from 0 !");
5160   if(i>=(int)_meshes.size())
5161     _meshes.resize(i+1);
5162   MEDFileMeshMultiTS *elt=MEDFileMeshMultiTS::New();
5163   elt->setOneTimeStep(mesh);
5164   _meshes[i]=elt;
5165 }
5166
5167 void MEDFileMeshes::destroyMeshAtPos(int i) throw(INTERP_KERNEL::Exception)
5168 {
5169   if(i<0 || i>=(int)_meshes.size())
5170     {
5171       std::ostringstream oss; oss << "MEDFileMeshes::destroyMeshAtPos : Invalid given id in input (" << i << ") should be in [0," << _meshes.size() << ") !";
5172       throw INTERP_KERNEL::Exception(oss.str().c_str());
5173     }
5174   _meshes.erase(_meshes.begin()+i);
5175 }
5176
5177 void MEDFileMeshes::loadFromFile(const char *fileName) throw(INTERP_KERNEL::Exception)
5178 {
5179   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
5180   int i=0;
5181   _meshes.resize(ms.size());
5182   for(std::vector<std::string>::const_iterator it=ms.begin();it!=ms.end();it++,i++)
5183     _meshes[i]=MEDFileMeshMultiTS::New(fileName,(*it).c_str());
5184 }
5185
5186 MEDFileMeshes::MEDFileMeshes()
5187 {
5188 }
5189
5190 MEDFileMeshes::MEDFileMeshes(const char *fileName) throw(INTERP_KERNEL::Exception)
5191 try
5192   {
5193     loadFromFile(fileName);
5194   }
5195 catch(INTERP_KERNEL::Exception& e)
5196   {
5197   }
5198
5199 MEDFileMeshes *MEDFileMeshes::deepCpy() const throw(INTERP_KERNEL::Exception)
5200 {
5201   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> > meshes(_meshes.size());
5202   std::size_t i=0;
5203   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
5204     if((const MEDFileMeshMultiTS *)*it)
5205       meshes[i]=(*it)->deepCpy();
5206   MEDCouplingAutoRefCountObjectPtr<MEDFileMeshes> ret=MEDFileMeshes::New();
5207   ret->_meshes=meshes;
5208   return ret.retn();
5209 }
5210
5211 std::size_t MEDFileMeshes::getHeapMemorySize() const
5212 {
5213   std::size_t ret=_meshes.capacity()*(sizeof(MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS>));
5214   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++)
5215     if((const MEDFileMeshMultiTS*)*it)
5216       ret+=(*it)->getHeapMemorySize();
5217   return ret; 
5218 }
5219
5220 std::string MEDFileMeshes::simpleRepr() const
5221 {
5222   std::ostringstream oss;
5223   oss << "(*****************)\n(* MEDFileMeshes *)\n(*****************)\n\n";
5224   simpleReprWithoutHeader(oss);
5225   return oss.str();
5226 }
5227
5228 void MEDFileMeshes::simpleReprWithoutHeader(std::ostream& oss) const
5229 {
5230   int nbOfMeshes=getNumberOfMeshes();
5231   oss << "There are " << nbOfMeshes << " meshes with the following names : \n";
5232   std::vector<std::string> mns=getMeshesNames();
5233   for(int i=0;i<nbOfMeshes;i++)
5234     oss << "  - #" << i << " \"" << mns[i] << "\"\n";
5235 }
5236
5237 void MEDFileMeshes::checkCoherency() const throw(INTERP_KERNEL::Exception)
5238 {
5239   static const char MSG[]="MEDFileMeshes::checkCoherency : mesh at rank ";
5240   int i=0;
5241   std::set<std::string> s;
5242   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
5243     {
5244       const MEDFileMeshMultiTS *elt=(*it);
5245       if(!elt)
5246         {
5247           std::ostringstream oss; oss << MSG << i << "/" << _meshes.size() << " is empty !";
5248           throw INTERP_KERNEL::Exception(oss.str().c_str());
5249         }
5250       std::size_t sz=s.size();
5251       s.insert(std::string((*it)->getName()));
5252       if(s.size()==sz)
5253         {
5254           std::ostringstream oss; oss << MSG << i << " has a name (\"" << (*it)->getName() << "\") already used by an another mesh in list !";
5255           throw INTERP_KERNEL::Exception(oss.str().c_str());
5256         }
5257     }
5258 }
5259
5260 MEDFileMeshesIterator::MEDFileMeshesIterator(MEDFileMeshes *ms):_ms(ms),_iter_id(0),_nb_iter(0)
5261 {
5262   if(ms)
5263     {
5264       ms->incrRef();
5265       _nb_iter=ms->getNumberOfMeshes();
5266     }
5267 }
5268
5269 MEDFileMeshesIterator::~MEDFileMeshesIterator()
5270 {
5271 }
5272
5273 MEDFileMesh *MEDFileMeshesIterator::nextt()
5274 {
5275   if(_iter_id<_nb_iter)
5276     {
5277       MEDFileMeshes *ms(_ms);
5278       if(ms)
5279         return ms->getMeshAtPos(_iter_id++);
5280       else
5281         return 0;
5282     }
5283   else
5284     return 0;
5285 }