Salome HOME
8626120f3729672109a6c8b1529eb2d7759f7361
[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.)
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 MEDFileMesh *MEDFileMesh::New(const char *fileName) throw(INTERP_KERNEL::Exception)
56 {
57   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
58   if(ms.empty())
59     {
60       std::ostringstream oss; oss << "MEDFileMesh::New : no meshes in file \"" << fileName << "\" !";
61       throw INTERP_KERNEL::Exception(oss.str().c_str());
62     }
63   MEDFileUtilities::CheckFileForRead(fileName);
64   ParaMEDMEM::MEDCouplingMeshType meshType;
65   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
66   int dt,it;
67   std::string dummy2;
68   MEDFileMeshL2::GetMeshIdFromName(fid,ms.front().c_str(),meshType,dt,it,dummy2);
69   switch(meshType)
70     {
71     case UNSTRUCTURED:
72       {
73         MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret=MEDFileUMesh::New();
74         ret->loadUMeshFromFile(fid,ms.front().c_str(),dt,it);
75         return (MEDFileUMesh *)ret.retn();
76       }
77     case CARTESIAN:
78       {
79         MEDCouplingAutoRefCountObjectPtr<MEDFileCMesh> ret=MEDFileCMesh::New();
80         ret->loadCMeshFromFile(fid,ms.front().c_str(),dt,it);
81         return (MEDFileCMesh *)ret.retn();
82       }
83     case CURVE_LINEAR:
84       {
85         MEDCouplingAutoRefCountObjectPtr<MEDFileCurveLinearMesh> ret=MEDFileCurveLinearMesh::New();
86         ret->loadCLMeshFromFile(fid,ms.front().c_str(),dt,it);
87         return (MEDFileCMesh *)ret.retn();
88       }
89     default:
90       {
91         std::ostringstream oss; oss << "MEDFileMesh::New : MED file exists and has mesh '" << ms.front() << "' exists but unsupported type yet !";
92         throw INTERP_KERNEL::Exception(oss.str().c_str());
93       }
94     }
95 }
96
97 MEDFileMesh *MEDFileMesh::New(const char *fileName, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
98 {
99   MEDFileUtilities::CheckFileForRead(fileName);
100   ParaMEDMEM::MEDCouplingMeshType meshType;
101   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
102   int dummy0,dummy1;
103   std::string dummy2;
104   MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dummy2);
105   switch(meshType)
106     {
107     case UNSTRUCTURED:
108       {
109         MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret=MEDFileUMesh::New();
110         ret->loadUMeshFromFile(fid,mName,dt,it);
111         return (MEDFileUMesh *)ret.retn();
112       }
113     case CARTESIAN:
114       {
115         MEDCouplingAutoRefCountObjectPtr<MEDFileCMesh> ret=MEDFileCMesh::New();
116         ret->loadCMeshFromFile(fid,mName,dt,it);
117         return (MEDFileCMesh *)ret.retn();
118       }
119     default:
120       {
121         std::ostringstream oss; oss << "MEDFileMesh::New : MED file exists and has mesh '" << mName << "' exists but unsupported type yet !";
122         throw INTERP_KERNEL::Exception(oss.str().c_str());
123       }
124     }
125 }
126
127 void MEDFileMesh::write(med_idt fid) const throw(INTERP_KERNEL::Exception)
128 {
129   if(!existsFamily(0))
130     const_cast<MEDFileMesh *>(this)->addFamily(DFT_FAM_NAME,0);
131   if(_name.empty())
132     throw INTERP_KERNEL::Exception("MEDFileMesh : name is empty. MED file ask for a NON EMPTY name !");
133   writeLL(fid);
134 }
135
136 void MEDFileMesh::write(const char *fileName, int mode) const throw(INTERP_KERNEL::Exception)
137 {
138   med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode);
139   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,medmod);
140   std::ostringstream oss; oss << "MEDFileMesh : error on attempt to write in file : \"" << fileName << "\""; 
141   MEDFileUtilities::CheckMEDCode(fid,fid,oss.str().c_str());
142   write(fid);
143 }
144
145 bool MEDFileMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
146 {
147   if(_order!=other->_order)
148     {
149       what="Orders differ !";
150       return false;
151     }
152   if(_iteration!=other->_iteration)
153     {
154       what="Iterations differ !";
155       return false;
156     }
157   if(fabs(_time-other->_time)>eps)
158     {
159       what="Time values differ !";
160       return false;
161     }
162   if(_dt_unit!=other->_dt_unit)
163     {
164       what="Time units differ !";
165       return false;
166     }
167   if(_name!=other->_name)
168     {
169       what="Names differ !";
170       return false;
171     }
172   if(_univ_name!=other->_univ_name)
173     {
174       what="Univ names differ !";
175       return false;
176     }
177   if(_desc_name!=other->_desc_name)
178     {
179       what="Description names differ !";
180       return false;
181     }
182   if(!areGrpsEqual(other,what))
183     return false;
184   if(!areFamsEqual(other,what))
185     return false;
186   return true;
187 }
188
189 void MEDFileMesh::clearNonDiscrAttributes() const
190 {
191   
192 }
193
194 bool MEDFileMesh::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab) throw(INTERP_KERNEL::Exception)
195 {
196   for(std::vector< std::pair<std::string,std::string> >::const_iterator it=modifTab.begin();it!=modifTab.end();it++)
197     {
198       if((*it).first==_name)
199         {
200           _name=(*it).second;
201           return true;
202         }
203     }
204   return false;
205 }
206
207 void MEDFileMesh::copyFamGrpMapsFrom(const MEDFileMesh& other)
208 {
209   _groups=other._groups;
210   _families=other._families;
211 }
212
213 std::vector<std::string> MEDFileMesh::getFamiliesOnGroup(const char *name) const throw(INTERP_KERNEL::Exception)
214 {
215   std::string oname(name);
216   std::map<std::string, std::vector<std::string> >::const_iterator it=_groups.find(oname);
217   std::vector<std::string> grps=getGroupsNames();
218   if(it==_groups.end())
219     {
220       std::ostringstream oss; oss << "No such groupname \"" << name << "\" !\nAvailable groups are :";
221       std::copy(grps.begin(),grps.end(),std::ostream_iterator<std::string>(oss," "));
222       throw INTERP_KERNEL::Exception(oss.str().c_str());
223     }
224   return (*it).second;
225 }
226
227 std::vector<std::string> MEDFileMesh::getFamiliesOnGroups(const std::vector<std::string>& grps) const throw(INTERP_KERNEL::Exception)
228 {
229   std::set<std::string> fams;
230   for(std::vector<std::string>::const_iterator it=grps.begin();it!=grps.end();it++)
231     {
232       std::map<std::string, std::vector<std::string> >::const_iterator it2=_groups.find(*it);
233       if(it2==_groups.end())
234         {
235           std::ostringstream oss; oss << "No such group in mesh \"" << _name << "\" : " << *it; 
236           std::vector<std::string> grps2=getGroupsNames(); oss << "\" !\nAvailable groups are :";
237           std::copy(grps2.begin(),grps2.end(),std::ostream_iterator<std::string>(oss," "));
238           throw INTERP_KERNEL::Exception(oss.str().c_str());
239         }
240       fams.insert((*it2).second.begin(),(*it2).second.end());
241     }
242   std::vector<std::string> fams2(fams.begin(),fams.end());
243   return fams2;
244 }
245
246 std::vector<int> MEDFileMesh::getFamiliesIdsOnGroup(const char *name) const throw(INTERP_KERNEL::Exception)
247 {
248   std::string oname(name);
249   std::map<std::string, std::vector<std::string> >::const_iterator it=_groups.find(oname);
250   std::vector<std::string> grps=getGroupsNames();
251   if(it==_groups.end())
252     {
253       std::ostringstream oss; oss << "No such groupname \"" << name << "\" !\nAvailable groups are :";
254       std::copy(grps.begin(),grps.end(),std::ostream_iterator<std::string>(oss," "));
255       throw INTERP_KERNEL::Exception(oss.str().c_str());
256     }
257   return getFamiliesIds((*it).second);
258 }
259
260 /*!
261  * This method sets families at a corresponding groups existing or not. If it existed, it is replaced by new 'fams'.
262  * Each entry in 'fams' is checked if it is not still existing default id 0 is set.
263  */
264 void MEDFileMesh::setFamiliesOnGroup(const char *name, const std::vector<std::string>& fams) throw(INTERP_KERNEL::Exception)
265 {
266   std::string oname(name);
267   _groups[oname]=fams;
268   for(std::vector<std::string>::const_iterator it1=fams.begin();it1!=fams.end();it1++)
269     {
270       std::map<std::string,int>::iterator it2=_families.find(*it1);
271       if(it2==_families.end())
272         _families[*it1]=0;
273     }
274 }
275
276 /*!
277  * Behaves as MEDFileMesh::setFamiliesOnGroup, except that if there is presence of a family id in 'famIds' not existing an exception is thrown.
278  * If several families have same id the first one in lexical order is taken into account.
279  */
280 void MEDFileMesh::setFamiliesIdsOnGroup(const char *name, const std::vector<int>& famIds) throw(INTERP_KERNEL::Exception)
281 {
282   std::string oname(name);
283   std::vector<std::string> fams(famIds.size());
284   int i=0;
285   for(std::vector<int>::const_iterator it1=famIds.begin();it1!=famIds.end();it1++,i++)
286     {
287       std::string name2=getFamilyNameGivenId(*it1);
288       fams[i]=name2;
289     }
290   _groups[oname]=fams;
291 }
292
293 std::vector<std::string> MEDFileMesh::getGroupsOnFamily(const char *name) const throw(INTERP_KERNEL::Exception)
294 {
295   std::vector<std::string> ret;
296   for(std::map<std::string, std::vector<std::string> >::const_iterator it1=_groups.begin();it1!=_groups.end();it1++)
297     {
298       for(std::vector<std::string>::const_iterator it2=(*it1).second.begin();it2!=(*it1).second.end();it2++)
299         if((*it2)==name)
300           {
301             ret.push_back((*it1).first);
302             break;
303           }
304     }
305   return ret;
306 }
307
308 /*!
309  * This method expects that family 'famName' is already existing. If not an exception will be thrown.
310  */
311 void MEDFileMesh::setGroupsOnFamily(const char *famName, const std::vector<std::string>& grps) throw(INTERP_KERNEL::Exception)
312 {
313   std::string fName(famName);
314   const std::map<std::string,int>::const_iterator it=_families.find(fName);
315   if(it==_families.end())
316     {
317       std::vector<std::string> fams=getFamiliesNames();
318       std::ostringstream oss; oss << "No such familyname \"" << fName << "\" !\nAvailable families are :";
319       std::copy(fams.begin(),fams.end(),std::ostream_iterator<std::string>(oss," "));
320       throw INTERP_KERNEL::Exception(oss.str().c_str());
321     }
322   for(std::vector<std::string>::const_iterator it3=grps.begin();it3!=grps.end();it3++)
323     {
324       std::map< std::string, std::vector<std::string> >::iterator it2=_groups.find(*it3);
325       if(it2!=_groups.end())
326         (*it2).second.push_back(fName);
327       else
328         {
329           std::vector<std::string> grps2(1,fName);
330           _groups[*it3]=grps2;
331         }
332     }
333 }
334
335 std::vector<std::string> MEDFileMesh::getGroupsNames() const
336 {
337   std::vector<std::string> ret(_groups.size());
338   int i=0;
339   for(std::map<std::string, std::vector<std::string> >::const_iterator it=_groups.begin();it!=_groups.end();it++,i++)
340     ret[i]=(*it).first;
341   return ret;
342 }
343
344 std::vector<std::string> MEDFileMesh::getFamiliesNames() const
345 {
346   std::vector<std::string> ret(_families.size());
347   int i=0;
348   for(std::map<std::string, int >::const_iterator it=_families.begin();it!=_families.end();it++,i++)
349     ret[i]=(*it).first;
350   return ret;
351 }
352
353 /*!
354  * This method scans every families and for each families shared by only one group, the corresponding family takes the same name than the group.
355  */
356 void MEDFileMesh::assignFamilyNameWithGroupName() throw(INTERP_KERNEL::Exception)
357 {
358   std::map<std::string, std::vector<std::string> > groups(_groups);
359   std::map<std::string,int> newFams;
360   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
361     {
362       std::vector<std::string> grps=getGroupsOnFamily((*it).first.c_str());
363       if(grps.size()==1 && groups[grps[0]].size()==1)
364         {
365           if(newFams.find(grps[0])!=newFams.end())
366             {
367               std::ostringstream oss; oss << "MEDFileMesh::assignFamilyNameWithGroupName : Family \"" << grps[0] << "\" already exists !";
368               throw INTERP_KERNEL::Exception(oss.str().c_str());
369             }
370           newFams[grps[0]]=(*it).second;
371           std::vector<std::string>& grps2=groups[grps[0]];
372           std::size_t pos=std::distance(grps2.begin(),std::find(grps2.begin(),grps2.end(),(*it).first));
373           grps2[pos]=grps[0];
374         }
375       else
376         {
377           if(newFams.find((*it).first)!=newFams.end())
378             {
379               std::ostringstream oss; oss << "MEDFileMesh::assignFamilyNameWithGroupName : Family \"" << (*it).first << "\" already exists !";
380               throw INTERP_KERNEL::Exception(oss.str().c_str());
381             }
382           newFams[(*it).first]=(*it).second;
383         }
384     }
385   _families=newFams;
386   _groups=groups;
387 }
388
389 void MEDFileMesh::removeGroup(const char *name) throw(INTERP_KERNEL::Exception)
390 {
391   std::string oname(name);
392   std::map<std::string, std::vector<std::string> >::iterator it=_groups.find(oname);
393   std::vector<std::string> grps=getGroupsNames();
394   if(it==_groups.end())
395     {
396       std::ostringstream oss; oss << "No such groupname \"" << name << "\" !\nAvailable groups are :";
397       std::copy(grps.begin(),grps.end(),std::ostream_iterator<std::string>(oss," "));
398       throw INTERP_KERNEL::Exception(oss.str().c_str());
399     }
400   _groups.erase(it);
401 }
402
403 void MEDFileMesh::removeFamily(const char *name) throw(INTERP_KERNEL::Exception)
404 {
405   std::string oname(name);
406   std::map<std::string, int >::iterator it=_families.find(oname);
407   std::vector<std::string> fams=getFamiliesNames();
408   if(it==_families.end())
409     {
410       std::ostringstream oss; oss << "No such familyname \"" << name << "\" !\nAvailable families are :";
411       std::copy(fams.begin(),fams.end(),std::ostream_iterator<std::string>(oss," "));
412       throw INTERP_KERNEL::Exception(oss.str().c_str());
413     }
414   _families.erase(it);
415   for(std::map<std::string, std::vector<std::string> >::iterator it3=_groups.begin();it3!=_groups.end();it3++)
416     {
417       std::vector<std::string>& v=(*it3).second;
418       std::vector<std::string>::iterator it4=std::find(v.begin(),v.end(),oname);
419       if(it4!=v.end())
420         v.erase(it4);
421     }
422 }
423
424 void MEDFileMesh::changeGroupName(const char *oldName, const char *newName) throw(INTERP_KERNEL::Exception)
425 {
426   std::string oname(oldName);
427   std::map<std::string, std::vector<std::string> >::iterator it=_groups.find(oname);
428   std::vector<std::string> grps=getGroupsNames();
429   if(it==_groups.end())
430     {
431       std::ostringstream oss; oss << "No such groupname \"" << oldName << "\" !\nAvailable groups are :";
432       std::copy(grps.begin(),grps.end(),std::ostream_iterator<std::string>(oss," "));
433       throw INTERP_KERNEL::Exception(oss.str().c_str());
434     }
435   std::string nname(newName);
436   it=_groups.find(nname);
437   if(it!=_groups.end())
438     {
439       std::ostringstream oss; oss << "Such groupname \"" << newName << "\" already exists ! Kill it before !";
440       throw INTERP_KERNEL::Exception(oss.str().c_str());
441     }
442   std::vector<std::string> cpy=(*it).second;
443   _groups.erase(it);
444   _groups[newName]=cpy;
445 }
446
447 /*!
448  * This method changes the family ids in 'this'. It leads to a modification into '_families' attributes \b and in
449  * ids stored in arrays. This method calls MEDFileMesh::changeFamilyIdArr method.
450  */
451 void MEDFileMesh::changeFamilyId(int oldId, int newId) throw(INTERP_KERNEL::Exception)
452 {
453   changeFamilyIdArr(oldId,newId);
454   std::map<std::string,int> fam2;
455   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
456     {
457       if((*it).second==oldId)
458         fam2[(*it).first]=newId;
459       else
460         fam2[(*it).first]=(*it).second;
461     }
462   _families=fam2;
463 }
464
465 void MEDFileMesh::changeFamilyName(const char *oldName, const char *newName) throw(INTERP_KERNEL::Exception)
466 {
467   std::string oname(oldName);
468   std::map<std::string, int >::iterator it=_families.find(oname);
469   std::vector<std::string> fams=getFamiliesNames();
470   if(it==_families.end())
471     {
472       std::ostringstream oss; oss << "No such familyname \"" << oldName << "\" !\nAvailable families are :";
473       std::copy(fams.begin(),fams.end(),std::ostream_iterator<std::string>(oss," "));
474       throw INTERP_KERNEL::Exception(oss.str().c_str());
475     }
476   std::string nname(newName);
477   std::map<std::string, int >::iterator it2=_families.find(nname);
478   if(it2!=_families.end())
479     {
480       std::ostringstream oss; oss << "Such familyname \"" << newName << " already exists ! Kill it before !";
481       throw INTERP_KERNEL::Exception(oss.str().c_str());
482     }
483   int cpy=(*it).second;
484   _families.erase(it);
485   _families[newName]=cpy;
486   for(std::map<std::string, std::vector<std::string> >::iterator it3=_groups.begin();it3!=_groups.end();it3++)
487     {
488       std::vector<std::string>& v=(*it3).second;
489       std::vector<std::string>::iterator it4=std::find(v.begin(),v.end(),oname);
490       if(it4!=v.end())
491         (*it4)=nname;
492     }
493 }
494
495 bool MEDFileMesh::areFamsEqual(const MEDFileMesh *other, std::string& what) const
496 {
497   if(_families==other->_families)
498     return true;
499   std::map<std::string,int> fam0;
500   std::map<std::string,int> fam1;
501   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
502     if((*it).second!=0)
503       fam0[(*it).first]=(*it).second;
504   for(std::map<std::string,int>::const_iterator it=other->_families.begin();it!=other->_families.end();it++)
505     if((*it).second!=0)
506       fam1[(*it).first]=(*it).second;
507   return fam0==fam1;
508 }
509
510 bool MEDFileMesh::areGrpsEqual(const MEDFileMesh *other, std::string& what) const
511 {
512   if(_groups==other->_groups)
513     return true;
514   bool ret=true;
515   std::size_t sz=_groups.size();
516   if(sz!=other->_groups.size())
517     {
518       what="Groups differ because not same number !\n";
519       ret=false;
520     }
521   if(ret)
522     {
523       std::map<std::string, std::vector<std::string> >::const_iterator it1=_groups.begin();
524       for(std::size_t i=0;i<sz && ret;i++,it1++)
525         {
526           std::map<std::string, std::vector<std::string> >::const_iterator it2=other->_groups.find((*it1).first);
527           if(it2!=other->_groups.end())
528             {
529               std::set<std::string> s1((*it1).second.begin(),(*it1).second.end());
530               std::set<std::string> s2((*it2).second.begin(),(*it2).second.end());
531               ret=(s1==s2);
532             }
533           else
534             {
535               ret=false;
536               what="A group in first mesh exists not in other !\n";
537             }
538         }
539     }
540   if(!ret)
541     {
542       std::ostringstream oss; oss << "Groups description differs :\n";
543       oss << "First group description :\n";
544       for(std::map<std::string, std::vector<std::string> >::const_iterator it=_groups.begin();it!=_groups.end();it++)
545         {
546           oss << " Group \"" << (*it).first << "\" on following families :\n";
547           for(std::vector<std::string>::const_iterator it2=(*it).second.begin();it2!=(*it).second.end();it2++)
548         oss << "    \"" << *it2 << "\n";
549         }
550       oss << "Second group description :\n";
551       for(std::map<std::string, std::vector<std::string> >::const_iterator it=other->_groups.begin();it!=other->_groups.end();it++)
552         {
553           oss << " Group \"" << (*it).first << "\" on following families :\n";
554           for(std::vector<std::string>::const_iterator it2=(*it).second.begin();it2!=(*it).second.end();it2++)
555             oss << "    \"" << *it2 << "\n";
556         }
557       what+=oss.str();
558     }
559   return ret;
560 }
561
562 bool MEDFileMesh::existsGroup(const char *groupName) const
563 {
564   std::string grpName(groupName);
565   return _groups.find(grpName)!=_groups.end();
566 }
567
568 bool MEDFileMesh::existsFamily(int famId) const
569 {
570   for(std::map<std::string,int>::const_iterator it2=_families.begin();it2!=_families.end();it2++)
571     if((*it2).second==famId)
572       return true;
573   return false;
574 }
575
576 bool MEDFileMesh::existsFamily(const char *familyName) const
577 {
578   std::string fname(familyName);
579   return _families.find(fname)!=_families.end();
580 }
581
582 void MEDFileMesh::setFamilyId(const char *familyName, int id)
583 {
584   std::string fname(familyName);
585   _families[fname]=id;
586 }
587
588 void MEDFileMesh::setFamilyIdUnique(const char *familyName, int id) throw(INTERP_KERNEL::Exception)
589 {
590   std::string fname(familyName);
591   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
592     if((*it).second==id)
593       {
594         if((*it).first!=familyName)
595           {
596             std::ostringstream oss; oss << "MEDFileMesh::setFamilyIdUnique : Family id #" << id << " is already belonging to family with name \"" << (*it).first << "\" !";
597             throw INTERP_KERNEL::Exception(oss.str().c_str());
598           }
599       }
600   _families[fname]=id;
601 }
602
603 /*!
604  * This method appends a new entry in _families attribute. An exception is thrown if either the famId is already
605  * kept by an another familyName. An exception is thrown if name 'familyName' is alreadyset with a different 'famId'.
606  */
607 void MEDFileMesh::addFamily(const char *familyName, int famId) throw(INTERP_KERNEL::Exception)
608 {
609   std::string fname(familyName);
610   std::map<std::string,int>::const_iterator it=_families.find(fname);
611   if(it==_families.end())
612     {
613        for(std::map<std::string,int>::const_iterator it2=_families.begin();it2!=_families.end();it2++)
614          if((*it2).second==famId)
615            {
616              std::ostringstream oss;
617              oss << "MEDFileMesh::addFamily : Family \"" << (*it2).first << "\" already exists with specified id : " << famId << " !";
618              throw INTERP_KERNEL::Exception(oss.str().c_str());
619            }
620        _families[fname]=famId;
621     }
622   else
623     {
624       if((*it).second!=famId)
625         {
626           std::ostringstream oss;
627           oss << "MEDFileMesh::addFamily : Family \"" << fname << "\" already exists but has id set to " << (*it).second << " different from asked famId " << famId << " !";
628           throw INTERP_KERNEL::Exception(oss.str().c_str());
629         }
630     }
631 }
632
633 /*!
634  * This method creates a new group called 'groupName' in 'this'. If it exists a group with the same name an INTERP_KERNEL::Exception will be thrown.
635  * If the 'meshDimRelToMaxExt' is not existing an INTERP_KERNEL::Exception will be thrown too.
636  * \b WARNING : This method does \b not garantee that 'groupName' lies only on a single level specified by 'meshDimRelToMaxExt'.
637  * in the case of a presence of one or more family id in family field at 'meshDimRelToMaxExt' level that appears in another level.
638  * If there is a risk of such case call MEDFileMesh::keepFamIdsOnlyOnLevs method \b before calling this method. 
639  * (call to MEDFileMesh::keepFamIdsOnlyOnLevs should be done with MEDFileMesh::getFamiliesIdsOnGroup('groupName' as first input ).
640  */
641 void MEDFileMesh::createGroupOnAll(int meshDimRelToMaxExt, const char *groupName) throw(INTERP_KERNEL::Exception)
642 {
643   std::string grpName(groupName);
644   std::vector<int> levs=getNonEmptyLevelsExt();
645   if(std::find(levs.begin(),levs.end(),meshDimRelToMaxExt)==levs.end())
646     {
647       std::ostringstream oss; oss << "MEDFileMesh::createGroupOnAll : The relative ext dimension " << meshDimRelToMaxExt << " is not available !" << std::endl;
648       oss << "Available relative ext levels are : ";
649       std::copy(levs.begin(),levs.end(),std::ostream_iterator<int>(oss," "));
650       throw INTERP_KERNEL::Exception(oss.str().c_str());
651     }
652   if(existsGroup(groupName))
653     {
654       std::ostringstream oss; oss << "MEDFileMesh::createGroupOnAll : The groups \"" << grpName << "\" already exists in this !" << std::endl;
655       oss << "Already existing groups are : ";
656       std::copy(levs.begin(),levs.end(),std::ostream_iterator<int>(oss," "));
657       oss << std::endl << "Please choose an another group name or call removeGroup(\"" << grpName << "\") method !";
658       throw INTERP_KERNEL::Exception(oss.str().c_str());
659     }
660   const DataArrayInt *fieldFamIds=getFamilyFieldAtLevel(meshDimRelToMaxExt);
661   if(fieldFamIds==0)
662     throw INTERP_KERNEL::Exception("MEDFileMesh::createGroupOnAll : Family field arr ids is not defined for this level !");
663   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famIds=fieldFamIds->getDifferentValues();
664   std::vector<std::string> familiesOnWholeGroup;
665   for(const int *it=famIds->begin();it!=famIds->end();it++)
666     {
667       bool tmp;
668       familiesOnWholeGroup.push_back(findOrCreateAndGiveFamilyWithId(*it,tmp));
669     }
670   _groups[grpName]=familiesOnWholeGroup;
671 }
672
673 /*!
674  * This method checks that family Ids in 'famIds' are not present in levels \b not in 'vMeshDimRelToMaxExt'.
675  * If it is the case true is returned and 'this' is not modified.
676  * If there is some levels not in 'vMeshDimRelToMaxExt' where one or more family ids in 'famIds' appear
677  * new families are created and groups are updated in consequence.
678  */
679 bool MEDFileMesh::keepFamIdsOnlyOnLevs(const std::vector<int>& famIds, const std::vector<int>& vMeshDimRelToMaxExt) throw(INTERP_KERNEL::Exception)
680 {
681   std::set<int> levsInput(vMeshDimRelToMaxExt.begin(),vMeshDimRelToMaxExt.end());
682   std::vector<int> levs=getNonEmptyLevelsExt();
683   std::set<int> levs2(levs.begin(),levs.end());
684   std::vector<int> levsToTest;
685   std::set_difference(levs2.begin(),levs2.end(),levsInput.begin(),levsInput.end(),std::back_insert_iterator< std::vector<int> >(levsToTest));
686   std::set<int> famIds2(famIds.begin(),famIds.end());
687   bool ret=true;
688   int maxFamId=1;
689   if(!_families.empty())
690     maxFamId=getMaxFamilyId()+1;
691   std::vector<std::string> allFams=getFamiliesNames();
692   for(std::vector<int>::const_iterator it=levsToTest.begin();it!=levsToTest.end();it++)
693     {
694       const DataArrayInt *fieldFamIds=getFamilyFieldAtLevel(*it);
695       if(fieldFamIds)
696         {
697           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famIds3=fieldFamIds->getDifferentValues();
698           std::vector<int> tmp;
699           std::set_intersection(famIds3->begin(),famIds3->end(),famIds2.begin(),famIds2.end(),std::back_insert_iterator< std::vector<int> >(tmp));
700           for(std::vector<int>::const_iterator it2=tmp.begin();it2!=tmp.end();it2++)
701             {
702               ret=false;
703               std::string famName=getFamilyNameGivenId(*it2);
704               std::ostringstream oss; oss << "Family_" << maxFamId;
705               std::string zeName=CreateNameNotIn(oss.str(),allFams);
706               addFamilyOnAllGroupsHaving(famName.c_str(),zeName.c_str());
707               _families[zeName]=maxFamId;
708               (const_cast<DataArrayInt *>(fieldFamIds))->changeValue(*it2,maxFamId);
709               maxFamId++;
710             }
711         }
712     }
713   return ret;
714 }
715
716 /*!
717  * This method add into the family list of a group 'grpName' the family with name 'famName'.
718  * If the group 'grpName' does not exist it is created and 'famName' is added to the list.
719  * If the group 'grpName' already exists, 'famName' will be added into family list of the existing group.
720  * This method throws an INTERP_KERNEL::Exception if 'famName' does not exit.
721  */
722 void MEDFileMesh::addFamilyOnGrp(const char *grpName, const char *famName) throw(INTERP_KERNEL::Exception)
723 {
724   std::string grpn(grpName);
725   std::string famn(famName);
726   if(grpn.empty() || famn.empty())
727     throw INTERP_KERNEL::Exception("MEDFileMesh::addFamilyOnGrp : input strings must be non null !");
728   std::vector<std::string> fams=getFamiliesNames();
729   if(std::find(fams.begin(),fams.end(),famn)==fams.end())
730     {
731       std::ostringstream oss; oss << "MEDFileMesh::addFamilyOnGrp : Family \"" << famn << "\" does not exist !" << std::endl;
732       oss << "Create this family or choose an existing one ! Existing fams are : ";
733       std::copy(fams.begin(),fams.end(),std::ostream_iterator<std::string>(oss," ")); oss << ".";
734       throw INTERP_KERNEL::Exception(oss.str().c_str());
735     }
736   std::map<std::string, std::vector<std::string> >::iterator it=_groups.find(grpn);
737   if(it==_groups.end())
738     {
739       _groups[grpn].push_back(famn);
740     }
741   else
742     {
743       std::vector<std::string>::iterator it2=std::find((*it).second.begin(),(*it).second.end(),famn);
744       if(it2==(*it).second.end())
745         (*it).second.push_back(famn);
746     }
747 }
748
749 /*!
750  * This method adds to all groups lying on family with name 'famName' the other family name 'otherFamName'.
751  * This method is quite underground because it can lead to unconsistency because family 'otherFamName' is \b not added into _families.
752  * This method is used by MEDFileMesh::keepFamIdsOnlyOnLevs method.
753  */
754 void MEDFileMesh::addFamilyOnAllGroupsHaving(const char *famName, const char *otherFamName) throw(INTERP_KERNEL::Exception)
755 {
756   std::string famNameCpp(famName);
757   std::string otherCpp(otherFamName);
758   for(std::map<std::string, std::vector<std::string> >::iterator it=_groups.begin();it!=_groups.end();it++)
759     {
760       std::vector<std::string>& v=(*it).second;
761       if(std::find(v.begin(),v.end(),famNameCpp)!=v.end())
762         {
763           v.push_back(otherCpp);
764         }
765     }
766 }
767
768 void MEDFileMesh::changeAllGroupsContainingFamily(const char *familyNameToChange, const std::vector<std::string>& newFamiliesNames) throw(INTERP_KERNEL::Exception)
769 {
770   ChangeAllGroupsContainingFamily(_groups,familyNameToChange,newFamiliesNames);
771 }
772
773 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)
774 {
775   std::string fam(familyNameToChange);
776   for(std::map<std::string, std::vector<std::string> >::iterator it=groups.begin();it!=groups.end();it++)
777     {
778       std::vector<std::string>& fams((*it).second);
779       std::vector<std::string>::iterator it2=std::find(fams.begin(),fams.end(),fam);
780       if(it2!=fams.end())
781         {
782           fams.erase(it2);
783           fams.insert(fams.end(),newFamiliesNames.begin(),newFamiliesNames.end());
784         }
785     }
786 }
787
788 /*!
789  * If it exists a family whose family id is equal to 'id' this method behaves as MEDFileMesh::getFamilyNameGivenId.
790  * In this case, 'this' internal states remains unchanged and 'created' out parameter will be set to false.
791  * If there is no family whose family id is equal to 'id' a family is created with a name different from those
792  * already existing. In this case 'created' will be returned with a value set to true, and internal state
793  * will be modified.
794  * This method will throws an exception if it is not possible to create a unique family name.
795  */
796 std::string MEDFileMesh::findOrCreateAndGiveFamilyWithId(int id, bool& created) throw(INTERP_KERNEL::Exception)
797 {
798   return FindOrCreateAndGiveFamilyWithId(_families,id,created);
799 }
800
801 /*!
802  * If it exists a family whose family id is equal to 'id' this method behaves as MEDFileMesh::getFamilyNameGivenId.
803  * In this case, 'this' internal states remains unchanged and 'created' out parameter will be set to false.
804  * If there is no family whose family id is equal to 'id' a family is created with a name different from those
805  * already existing. In this case 'created' will be returned with a value set to true, and internal state
806  * will be modified.
807  * This method will throws an exception if it is not possible to create a unique family name.
808  */
809 std::string MEDFileMesh::FindOrCreateAndGiveFamilyWithId(std::map<std::string,int>& families, int id, bool& created) throw(INTERP_KERNEL::Exception)
810 {
811   std::vector<std::string> famAlreadyExisting(families.size());
812   int ii=0;
813   for(std::map<std::string,int>::const_iterator it=families.begin();it!=families.end();it++,ii++)
814     {
815       if((*it).second!=id)
816         {
817           famAlreadyExisting[ii]=(*it).first;
818         }
819       else
820         {
821           created=false;
822           return (*it).first;
823         }
824     }
825   created=true;
826   std::ostringstream oss; oss << "Family_" << id;
827   std::string ret=CreateNameNotIn(oss.str(),famAlreadyExisting);
828   families[ret]=id;
829   return ret;
830 }
831
832 void MEDFileMesh::setFamilyInfo(const std::map<std::string,int>& info)
833 {
834   _families=info;
835 }
836
837 void MEDFileMesh::setGroupInfo(const std::map<std::string, std::vector<std::string> >&info)
838 {
839   _groups=info;
840 }
841
842 int MEDFileMesh::getFamilyId(const char *name) const throw(INTERP_KERNEL::Exception)
843 {
844   std::string oname(name);
845   std::map<std::string, int>::const_iterator it=_families.find(oname);
846   std::vector<std::string> fams=getFamiliesNames();
847   if(it==_families.end())
848     {
849       std::ostringstream oss; oss << "No such familyname \"" << name << "\" !\nAvailable families are :";
850       std::copy(fams.begin(),fams.end(),std::ostream_iterator<std::string>(oss," "));
851       throw INTERP_KERNEL::Exception(oss.str().c_str());
852     }
853   return (*it).second;
854 }
855
856 std::vector<int> MEDFileMesh::getFamiliesIds(const std::vector<std::string>& fams) const throw(INTERP_KERNEL::Exception)
857 {
858   std::vector<int> ret(fams.size());
859   int i=0;
860   for(std::vector<std::string>::const_iterator it=fams.begin();it!=fams.end();it++,i++)
861     {
862       std::map<std::string, int>::const_iterator it2=_families.find(*it);
863       if(it2==_families.end())
864         {
865           std::vector<std::string> fams2=getFamiliesNames();
866           std::ostringstream oss; oss << "No such familyname \"" << *it << "\" in input list !\nAvailable families are :";
867           std::copy(fams2.begin(),fams2.end(),std::ostream_iterator<std::string>(oss," "));
868           throw INTERP_KERNEL::Exception(oss.str().c_str());
869         }
870       ret[i]=(*it2).second;
871     }
872   return ret;
873 }
874
875 int MEDFileMesh::getMaxFamilyId() const throw(INTERP_KERNEL::Exception)
876 {
877   if(_families.empty())
878     throw INTERP_KERNEL::Exception("MEDFileUMesh::getMaxFamilyId : no families set !");
879   int ret=-std::numeric_limits<int>::max();
880   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
881     {
882       ret=std::max((*it).second,ret);
883     }
884   return ret;
885 }
886
887 int MEDFileMesh::getMinFamilyId() const throw(INTERP_KERNEL::Exception)
888 {
889   if(_families.empty())
890     throw INTERP_KERNEL::Exception("MEDFileUMesh::getMinFamilyId : no families set !");
891   int ret=std::numeric_limits<int>::max();
892   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
893     {
894       ret=std::min((*it).second,ret);
895     }
896   return ret;
897 }
898
899 int MEDFileMesh::getTheMaxFamilyId() const throw(INTERP_KERNEL::Exception)
900 {
901   int m1=-std::numeric_limits<int>::max();
902   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
903     m1=std::max((*it).second,m1);
904   int m2=getMaxFamilyIdInArrays();
905   return std::max(m1,m2);
906 }
907
908 int MEDFileMesh::getTheMinFamilyId() const throw(INTERP_KERNEL::Exception)
909 {
910   int m1=std::numeric_limits<int>::max();
911   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
912     m1=std::min((*it).second,m1);
913   int m2=getMinFamilyIdInArrays();
914   return std::min(m1,m2);
915 }
916
917 DataArrayInt *MEDFileMesh::getAllFamiliesIdsReferenced() const throw(INTERP_KERNEL::Exception)
918 {
919   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
920   std::set<int> v;
921   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
922     v.insert((*it).second);
923   ret->alloc((int)v.size(),1);
924   std::copy(v.begin(),v.end(),ret->getPointer());
925   return ret.retn();
926 }
927
928 /*!
929  * true is returned if no modification has been needed. false if family
930  * renumbering has been needed.       
931  */
932 bool MEDFileMesh::ensureDifferentFamIdsPerLevel() throw(INTERP_KERNEL::Exception)
933 {
934   std::vector<int> levs=getNonEmptyLevelsExt();
935   std::set<int> allFamIds;
936   int maxId=getMaxFamilyId()+1;
937   std::map<int,std::vector<int> > famIdsToRenum;
938   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
939     {
940       const DataArrayInt *fam=getFamilyFieldAtLevel(*it);
941       if(fam)
942         {
943           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=fam->getDifferentValues();
944           std::set<int> r2;
945           std::set_intersection(tmp->begin(),tmp->end(),allFamIds.begin(),allFamIds.end(),std::inserter(r2,r2.end()));
946           if(!r2.empty())
947             famIdsToRenum[*it].insert(famIdsToRenum[*it].end(),r2.begin(),r2.end());
948           std::set<int> r3;
949           std::set_union(tmp->begin(),tmp->end(),allFamIds.begin(),allFamIds.end(),std::inserter(r3,r3.end()));
950         }
951     }
952   if(famIdsToRenum.empty())
953     return true;
954   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> allIds=getAllFamiliesIdsReferenced();
955   for(std::map<int,std::vector<int> >::const_iterator it2=famIdsToRenum.begin();it2!=famIdsToRenum.end();it2++)
956     {
957       DataArrayInt *fam=const_cast<DataArrayInt *>(getFamilyFieldAtLevel((*it2).first));
958       int *famIdsToChange=fam->getPointer();
959       std::map<int,int> ren;
960       for(std::vector<int>::const_iterator it3=(*it2).second.begin();it3!=(*it2).second.end();it3++,maxId++)
961         {
962           if(allIds->presenceOfValue(*it3))
963             {
964               std::string famName=getFamilyNameGivenId(*it3);
965               std::vector<std::string> grps=getGroupsOnFamily(famName.c_str());
966               ren[*it3]=maxId;
967               bool dummy;
968               std::string newFam=findOrCreateAndGiveFamilyWithId(maxId,dummy);
969               for(std::vector<std::string>::const_iterator it4=grps.begin();it4!=grps.end();it4++)
970                 addFamilyOnGrp((*it4).c_str(),newFam.c_str());
971             }
972         }
973       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=fam->getIdsEqualList(&(*it2).second[0],&(*it2).second[0]+(*it2).second.size());
974       for(const int *id=ids->begin();id!=ids->end();id++)
975         famIdsToChange[*id]=ren[famIdsToChange[*id]];
976     }
977   return false;
978 }
979
980 /*!
981  * This method normalizes fam id with the policy explained underneath. This policy is close to those implemented in SMESH.
982  * Level #0 famids > 0, Level #-1 famids < 0, Level #-2 famids=0, Level #1 famids=0
983  * This policy is those used by SMESH and Trio and that is the opposite of those in MED file.
984  * This method will throw an exception if a same family id is detected in different level.
985  * \warning This policy is the opposite of those in MED file documentation ...
986  */
987 void MEDFileMesh::normalizeFamIdsTrio() throw(INTERP_KERNEL::Exception)
988 {
989   ensureDifferentFamIdsPerLevel();
990   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> allIds=getAllFamiliesIdsReferenced();
991   std::vector<int> levs=getNonEmptyLevelsExt();
992   std::set<int> levsS(levs.begin(),levs.end());
993   std::set<std::string> famsFetched;
994   std::map<std::string,int> families;
995   if(std::find(levs.begin(),levs.end(),0)!=levs.end())
996     {
997       levsS.erase(0);
998       const DataArrayInt *fam=getFamilyFieldAtLevel(0);
999       if(fam)
1000         {
1001           int refId=1;
1002           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=fam->getDifferentValues();
1003           std::map<int,int> ren;
1004           for(const int *it=tmp->begin();it!=tmp->end();it++,refId++)
1005             ren[*it]=refId;
1006           int nbOfTuples=fam->getNumberOfTuples();
1007           int *start=const_cast<DataArrayInt *>(fam)->getPointer();
1008           for(int *w=start;w!=start+nbOfTuples;w++)
1009             *w=ren[*w];
1010           for(const int *it=tmp->begin();it!=tmp->end();it++)
1011             {
1012               if(allIds->presenceOfValue(*it))
1013                 {
1014                   std::string famName=getFamilyNameGivenId(*it);
1015                   families[famName]=ren[*it];
1016                   famsFetched.insert(famName);
1017                 }
1018             }
1019         }
1020     }
1021   if(std::find(levs.begin(),levs.end(),-1)!=levs.end())
1022     {
1023       levsS.erase(-1);
1024       const DataArrayInt *fam=getFamilyFieldAtLevel(-1);
1025       if(fam)
1026         {
1027           int refId=-1;
1028           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=fam->getDifferentValues();
1029           std::map<int,int> ren;
1030           for(const int *it=tmp->begin();it!=tmp->end();it++,refId--)
1031             ren[*it]=refId;
1032           int nbOfTuples=fam->getNumberOfTuples();
1033           int *start=const_cast<DataArrayInt *>(fam)->getPointer();
1034           for(int *w=start;w!=start+nbOfTuples;w++)
1035             *w=ren[*w];
1036           for(const int *it=tmp->begin();it!=tmp->end();it++)
1037             {
1038               if(allIds->presenceOfValue(*it))
1039                 {
1040                   std::string famName=getFamilyNameGivenId(*it);
1041                   families[famName]=ren[*it];
1042                   famsFetched.insert(famName);
1043                 }
1044             }
1045         }
1046     }
1047   for(std::set<int>::const_iterator it2=levsS.begin();it2!=levsS.end();it2++)
1048     {
1049       DataArrayInt *fam=const_cast<DataArrayInt*>(getFamilyFieldAtLevel(*it2));
1050       if(fam)
1051         {
1052           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=fam->getDifferentValues();
1053           fam->fillWithZero();
1054           for(const int *it3=tmp->begin();it3!=tmp->end();it3++)
1055             if(allIds->presenceOfValue(*it3))
1056               {
1057                 std::string famName=getFamilyNameGivenId(*it3);
1058                 families[famName]=0;
1059                 famsFetched.insert(famName);
1060               }
1061         }
1062     }
1063   //
1064   std::vector<std::string> allFams=getFamiliesNames();
1065   std::set<std::string> allFamsS(allFams.begin(),allFams.end());
1066   std::set<std::string> unFetchedIds;
1067   std::set_difference(allFamsS.begin(),allFamsS.end(),famsFetched.begin(),famsFetched.end(),std::inserter(unFetchedIds,unFetchedIds.end()));
1068   for(std::set<std::string>::const_iterator it4=unFetchedIds.begin();it4!=unFetchedIds.end();it4++)
1069     families[*it4]=_families[*it4];
1070   _families=families;
1071 }
1072
1073 /*!
1074  * This method normalizes fam id with the following policy.
1075  * Level #0 famids < 0, Level #-1 famids < 0 and for Level #1 famids >= 0
1076  * This policy is those defined in the MED file format but is the opposite of those implemented in SMESH and Trio.
1077  * This method will throw an exception if a same family id is detected in different level.
1078  */
1079 void MEDFileMesh::normalizeFamIdsMEDFile() throw(INTERP_KERNEL::Exception)
1080 {
1081   ensureDifferentFamIdsPerLevel();
1082   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> allIds=getAllFamiliesIdsReferenced();
1083   std::vector<int> levs=getNonEmptyLevelsExt();
1084   std::set<int> levsS(levs.begin(),levs.end());
1085   std::set<std::string> famsFetched;
1086   std::map<std::string,int> families;
1087   int refId=1;
1088   if(std::find(levs.begin(),levs.end(),1)!=levs.end())
1089     {
1090       levsS.erase(1);
1091       const DataArrayInt *fam=getFamilyFieldAtLevel(1);
1092       if(fam)
1093         {
1094           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=fam->getDifferentValues();
1095           std::map<int,int> ren;
1096           for(const int *it=tmp->begin();it!=tmp->end();it++,refId++)
1097             ren[*it]=refId;
1098           int nbOfTuples=fam->getNumberOfTuples();
1099           int *start=const_cast<DataArrayInt *>(fam)->getPointer();
1100           for(int *w=start;w!=start+nbOfTuples;w++)
1101             *w=ren[*w];
1102           for(const int *it=tmp->begin();it!=tmp->end();it++)
1103             {
1104               if(allIds->presenceOfValue(*it))
1105                 {
1106                   std::string famName=getFamilyNameGivenId(*it);
1107                   families[famName]=ren[*it];
1108                   famsFetched.insert(famName);
1109                 }
1110             }
1111         }
1112     }
1113   refId=-1;
1114   for(std::set<int>::const_reverse_iterator it2=levsS.rbegin();it2!=levsS.rend();it2++)
1115     {
1116       const DataArrayInt *fam=getFamilyFieldAtLevel(1);
1117       if(fam)
1118         {
1119           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=fam->getDifferentValues();
1120           std::map<int,int> ren;
1121           for(const int *it=tmp->begin();it!=tmp->end();it++,refId--)
1122             ren[*it]=refId;
1123           int nbOfTuples=fam->getNumberOfTuples();
1124           int *start=const_cast<DataArrayInt *>(fam)->getPointer();
1125           for(int *w=start;w!=start+nbOfTuples;w++)
1126             *w=ren[*w];
1127           for(const int *it=tmp->begin();it!=tmp->end();it++)
1128             {
1129               if(allIds->presenceOfValue(*it))
1130                 {
1131                   std::string famName=getFamilyNameGivenId(*it);
1132                   families[famName]=ren[*it];
1133                   famsFetched.insert(famName);
1134                 }
1135             }
1136         }
1137     }
1138   //
1139   std::vector<std::string> allFams=getFamiliesNames();
1140   std::set<std::string> allFamsS(allFams.begin(),allFams.end());
1141   std::set<std::string> unFetchedIds;
1142   std::set_difference(allFamsS.begin(),allFamsS.end(),famsFetched.begin(),famsFetched.end(),std::inserter(unFetchedIds,unFetchedIds.end()));
1143   for(std::set<std::string>::const_iterator it4=unFetchedIds.begin();it4!=unFetchedIds.end();it4++)
1144     families[*it4]=_families[*it4];
1145   _families=families;
1146 }
1147
1148 /*!
1149  * Returns the first (in lexical order) family name having family id equal to 'id'.
1150  */
1151 std::string MEDFileMesh::getFamilyNameGivenId(int id) const throw(INTERP_KERNEL::Exception)
1152 {
1153   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
1154     if((*it).second==id)
1155       return (*it).first;
1156   std::ostringstream oss; oss << "MEDFileUMesh::getFamilyNameGivenId : no such family id : " << id;
1157   throw INTERP_KERNEL::Exception(oss.str().c_str());
1158 }
1159
1160 std::string MEDFileMesh::simpleRepr() const
1161 {
1162   std::ostringstream oss;
1163   oss << "(*************************************)\n(* GENERAL INFORMATION ON THE MESH : *)\n(*************************************)\n";
1164   oss << "- Name of the mesh : <<" << getName() << ">>\n";
1165   oss << "- Description associated to the mesh : " << getDescription() << std::endl;
1166   return oss.str();
1167 }
1168
1169 DataArrayInt *MEDFileMesh::getGroupArr(int meshDimRelToMaxExt, const char *grp, bool renum) const throw(INTERP_KERNEL::Exception)
1170 {
1171   std::vector<std::string> tmp(1);
1172   tmp[0]=grp;
1173   DataArrayInt *ret=getGroupsArr(meshDimRelToMaxExt,tmp,renum);
1174   ret->setName(grp);
1175   return ret;
1176 }
1177
1178 DataArrayInt *MEDFileMesh::getGroupsArr(int meshDimRelToMaxExt, const std::vector<std::string>& grps, bool renum) const throw(INTERP_KERNEL::Exception)
1179 {
1180   std::vector<std::string> fams2=getFamiliesOnGroups(grps);
1181   return getFamiliesArr(meshDimRelToMaxExt,fams2,renum);
1182 }
1183
1184 DataArrayInt *MEDFileMesh::getFamilyArr(int meshDimRelToMaxExt, const char *fam, bool renum) const throw(INTERP_KERNEL::Exception)
1185 {
1186   std::vector<std::string> tmp(1);
1187   tmp[0]=fam;
1188   DataArrayInt *ret=getFamiliesArr(meshDimRelToMaxExt,tmp,renum);
1189   ret->setName(fam);
1190   return ret;
1191 }
1192
1193 DataArrayInt *MEDFileMesh::getNodeGroupArr(const char *grp, bool renum) const throw(INTERP_KERNEL::Exception)
1194 {
1195   std::vector<std::string> tmp(1);
1196   tmp[0]=grp;
1197   DataArrayInt *ret=getNodeGroupsArr(tmp,renum);
1198   ret->setName(grp);
1199   return ret;
1200 }
1201
1202 DataArrayInt *MEDFileMesh::getNodeGroupsArr(const std::vector<std::string>& grps, bool renum) const throw(INTERP_KERNEL::Exception)
1203 {
1204   return getGroupsArr(1,grps,renum);
1205 }
1206
1207 DataArrayInt *MEDFileMesh::getNodeFamilyArr(const char *fam, bool renum) const throw(INTERP_KERNEL::Exception)
1208 {
1209   std::vector<std::string> tmp(1);
1210   tmp[0]=fam;
1211   DataArrayInt *ret=getNodeFamiliesArr(tmp,renum);
1212   ret->setName(fam);
1213   return ret;
1214 }
1215
1216 DataArrayInt *MEDFileMesh::getNodeFamiliesArr(const std::vector<std::string>& fams, bool renum) const throw(INTERP_KERNEL::Exception)
1217 {
1218   return getFamiliesArr(1,fams,renum);
1219 }
1220
1221 void MEDFileMesh::setGroupsAtLevel(int meshDimRelToMaxExt, const std::vector<const DataArrayInt *>& grps, bool renum) throw(INTERP_KERNEL::Exception)
1222 {
1223   if(grps.empty())
1224     return ;
1225   std::set<std::string> grpsName;
1226   std::vector<std::string> grpsName2(grps.size());
1227   int i=0;
1228
1229   for(std::vector<const DataArrayInt *>::const_iterator it=grps.begin();it!=grps.end();it++,i++)
1230     {
1231       grpsName.insert((*it)->getName());
1232       grpsName2[i]=(*it)->getName();
1233     }
1234   if(grpsName.size()!=grps.size())
1235     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsAtLevel : groups name must be different each other !");
1236   if(grpsName.find(std::string(""))!=grpsName.end())
1237     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsAtLevel : groups name must be different empty string !");
1238   int sz=getSizeAtLevel(meshDimRelToMaxExt);
1239   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fam;
1240   std::vector< std::vector<int> > fidsOfGroups;
1241   if(!renum)
1242     {
1243       fam=DataArrayInt::MakePartition(grps,sz,fidsOfGroups);
1244     }
1245   else
1246     {
1247       std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > grps2(grps.size());
1248       for(unsigned int ii=0;ii<grps.size();ii++)
1249         {
1250           grps2[ii]=MEDFileUMeshSplitL1::Renumber(getRevNumberFieldAtLevel(meshDimRelToMaxExt),grps[ii]);
1251           grps2[ii]->setName(grps[ii]->getName().c_str());
1252         }
1253       std::vector<const DataArrayInt *> grps3(grps2.begin(),grps2.end());
1254       fam=DataArrayInt::MakePartition(grps3,sz,fidsOfGroups);
1255     }
1256   int offset=1;
1257   if(!_families.empty())
1258     offset=getMaxFamilyId()+1;
1259   TranslateFamilyIds(offset,fam,fidsOfGroups);
1260   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=fam->getDifferentValues();
1261   appendFamilyEntries(ids,fidsOfGroups,grpsName2);
1262   setFamilyFieldArr(meshDimRelToMaxExt,fam);
1263 }
1264
1265 /*!
1266  * This method append into '_families' attribute the families whose ids are in 'famIds'. Warning 'famIds' are expected to be ids
1267  * not in '_families'. Groups information are given in parameters in order to give to families representative names.
1268  * For the moment, the two last input parameters are not taken into account.
1269  */
1270 void MEDFileMesh::appendFamilyEntries(const DataArrayInt *famIds, const std::vector< std::vector<int> >& fidsOfGrps, const std::vector<std::string>& grpNames)
1271 {
1272   std::map<int,std::string> famInv;
1273   for(const int *it=famIds->begin();it!=famIds->end();it++)
1274     {
1275       std::ostringstream oss;
1276       oss << "Family_" << (*it);
1277       _families[oss.str()]=(*it);
1278       famInv[*it]=oss.str();
1279     }
1280   int i=0;
1281   for(std::vector< std::vector<int> >::const_iterator it1=fidsOfGrps.begin();it1!=fidsOfGrps.end();it1++,i++)
1282     {
1283       for(std::vector<int>::const_iterator it2=(*it1).begin();it2!=(*it1).end();it2++)
1284         {
1285           _groups[grpNames[i]].push_back(famInv[*it2]);
1286         }
1287     }
1288 }
1289
1290 void MEDFileMesh::TranslateFamilyIds(int offset, DataArrayInt *famArr, std::vector< std::vector<int> >& famIdsPerGrp)
1291 {
1292   famArr->applyLin(1,offset,0);
1293   for(std::vector< std::vector<int> >::iterator it1=famIdsPerGrp.begin();it1!=famIdsPerGrp.end();it1++)
1294     std::transform((*it1).begin(),(*it1).end(),(*it1).begin(),std::bind2nd(std::plus<int>(),offset));
1295 }
1296
1297 /*!
1298  * Warning no check is done on 'nameTry' in parameter. It should be non empty.
1299  * This method returns a name close to 'nameTry' so that it is not already into 'namesToAvoid'.
1300  * If this method fails to find such a name it will throw an exception.
1301  */
1302 std::string MEDFileMesh::CreateNameNotIn(const std::string& nameTry, const std::vector<std::string>& namesToAvoid) throw(INTERP_KERNEL::Exception)
1303 {
1304   //attempt #0
1305   if(std::find(namesToAvoid.begin(),namesToAvoid.end(),nameTry)==namesToAvoid.end())
1306     return nameTry;
1307   //attempt #1
1308   std::size_t len=nameTry.length();
1309   for(std::size_t ii=1;ii<len;ii++)
1310     {
1311       std::string tmp=nameTry.substr(ii,len-ii);
1312       if(std::find(namesToAvoid.begin(),namesToAvoid.end(),tmp)==namesToAvoid.end())
1313         return tmp;
1314     }
1315   //attempt #2
1316   if(len>=1)
1317     {
1318       for(std::size_t i=1;i<30;i++)
1319         {
1320           std::string tmp1(nameTry.at(0),i);
1321           tmp1+=nameTry;
1322           if(std::find(namesToAvoid.begin(),namesToAvoid.end(),tmp1)==namesToAvoid.end())
1323             return tmp1;
1324         }
1325     }
1326   //attempt #3
1327   std::string tmp2;
1328   for(std::vector<std::string>::const_iterator it2=namesToAvoid.begin();it2!=namesToAvoid.end();it2++)
1329     tmp2+=(*it2);
1330   if(std::find(namesToAvoid.begin(),namesToAvoid.end(),tmp2)==namesToAvoid.end())
1331     return tmp2;
1332   throw INTERP_KERNEL::Exception("MEDFileMesh::CreateNameNotIn : impossible to find a not already used name !");
1333 }
1334
1335 int MEDFileMesh::PutInThirdComponentOfCodeOffset(std::vector<int>& code, int strt) throw(INTERP_KERNEL::Exception)
1336 {
1337   std::size_t nbOfChunks=code.size()/3;
1338   if(code.size()%3!=0)
1339     throw INTERP_KERNEL::Exception("MEDFileMesh::PutInThirdComponentOfCodeOffset : code has invalid size : should be of size 3*x !");
1340   int ret=strt;
1341   for(std::size_t i=0;i<nbOfChunks;i++)
1342     {
1343       code[3*i+2]=ret;
1344       ret+=code[3*i+1];
1345     }
1346   return ret;
1347 }
1348
1349 /*!
1350  * This method should be called by any set* method of subclasses to deal automatically with _name attribute.
1351  * If _name attribute is empty the name of 'm' if taken as _name attribute.
1352  * If _name is not empty and that 'm' has the same name nothing is done.
1353  * If _name is not emplt and that 'm' has \b NOT the same name an exception is thrown.
1354  */
1355 void MEDFileMesh::dealWithTinyInfo(const MEDCouplingMesh *m) throw(INTERP_KERNEL::Exception)
1356 {
1357   if(_name.empty())
1358     _name=m->getName();
1359   else
1360     {
1361       std::string name(m->getName());
1362       if(!name.empty())
1363         {
1364           if(_name!=name)
1365             {
1366               std::ostringstream oss; oss << "MEDFileMesh::dealWithTinyInfo : name of current MEDfile mesh is '" << _name << "' whereas name of input mesh is : '";
1367               oss << name << "' ! Names must match !";
1368               throw INTERP_KERNEL::Exception(oss.str().c_str());
1369             }
1370         }
1371     }
1372   if(_desc_name.empty())
1373     _desc_name=m->getDescription();
1374   else
1375     {
1376       std::string name(m->getDescription());
1377       if(!name.empty())
1378         {
1379           if(_desc_name!=name)
1380             {
1381               std::ostringstream oss; oss << "MEDFileMesh::dealWithTinyInfo : description of current MEDfile mesh is '" << _desc_name << "' whereas name of input mesh is : '";
1382               oss << name << "' ! Names must match !";
1383               throw INTERP_KERNEL::Exception(oss.str().c_str());
1384             }
1385         }
1386     }
1387 }
1388
1389 void MEDFileMesh::getFamilyRepr(std::ostream& oss) const
1390 {
1391   oss << "(**************************)\n(* FAMILIES OF THE MESH : *)\n(**************************)\n";
1392   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
1393     {
1394       oss << "- Family with name \"" << (*it).first << "\" with number " << (*it).second << std::endl;
1395       oss << "  - Groups lying on this family : ";
1396       std::vector<std::string> grps=getGroupsOnFamily((*it).first.c_str());
1397       std::copy(grps.begin(),grps.end(),std::ostream_iterator<std::string>(oss," "));
1398       oss << std::endl << std::endl;
1399     }
1400 }
1401
1402 MEDFileUMesh *MEDFileUMesh::New(const char *fileName, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
1403 {
1404   MEDFileUtilities::CheckFileForRead(fileName);
1405   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
1406   return new MEDFileUMesh(fid,mName,dt,it);
1407 }
1408
1409 MEDFileUMesh *MEDFileUMesh::New(const char *fileName) throw(INTERP_KERNEL::Exception)
1410 {
1411   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
1412   if(ms.empty())
1413     {
1414       std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
1415       throw INTERP_KERNEL::Exception(oss.str().c_str());
1416     }
1417   MEDFileUtilities::CheckFileForRead(fileName);
1418   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
1419   int dt,it;
1420   ParaMEDMEM::MEDCouplingMeshType meshType;
1421   std::string dummy2;
1422   MEDFileMeshL2::GetMeshIdFromName(fid,ms.front().c_str(),meshType,dt,it,dummy2);
1423   return new MEDFileUMesh(fid,ms.front().c_str(),dt,it);
1424 }
1425
1426 MEDFileUMesh *MEDFileUMesh::New()
1427 {
1428   return new MEDFileUMesh;
1429 }
1430
1431 std::size_t MEDFileUMesh::getHeapMemorySize() const
1432 {
1433   std::size_t ret=MEDFileMesh::getHeapMemorySize();
1434   if((const DataArrayDouble*)_coords)
1435     ret+=_coords->getHeapMemorySize();
1436   if((const DataArrayInt *)_fam_coords)
1437     ret+=_fam_coords->getHeapMemorySize();
1438   if((const DataArrayInt *)_num_coords)
1439     ret+=_num_coords->getHeapMemorySize();
1440   if((const DataArrayInt *)_rev_num_coords)
1441     ret+=_rev_num_coords->getHeapMemorySize();
1442   if((const DataArrayAsciiChar *)_name_coords)
1443     ret+=_name_coords->getHeapMemorySize();
1444   ret+=_ms.capacity()*(sizeof(MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1>));
1445   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
1446     if((const MEDFileUMeshSplitL1*) *it)
1447       ret+=(*it)->getHeapMemorySize();
1448   return ret;
1449 }
1450
1451 MEDFileMesh *MEDFileUMesh::shallowCpy() const throw(INTERP_KERNEL::Exception)
1452 {
1453   MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret=new MEDFileUMesh(*this);
1454   return ret.retn();
1455 }
1456
1457 MEDFileMesh *MEDFileUMesh::deepCpy() const throw(INTERP_KERNEL::Exception)
1458 {
1459   MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret=new MEDFileUMesh(*this);
1460   if((const DataArrayDouble*)_coords)
1461     ret->_coords=_coords->deepCpy();
1462   if((const DataArrayInt*)_fam_coords)
1463     ret->_fam_coords=_fam_coords->deepCpy();
1464   if((const DataArrayInt*)_num_coords)
1465     ret->_num_coords=_num_coords->deepCpy();
1466   if((const DataArrayInt*)_rev_num_coords)
1467     ret->_rev_num_coords=_rev_num_coords->deepCpy();
1468   if((const DataArrayAsciiChar*)_name_coords)
1469     ret->_name_coords=_name_coords->deepCpy();
1470   std::size_t i=0;
1471   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,i++)
1472     {
1473       if((const MEDFileUMeshSplitL1 *)(*it))
1474         ret->_ms[i]=(*it)->deepCpy();
1475     }
1476   return ret.retn();
1477 }
1478
1479 bool MEDFileUMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
1480 {
1481   if(!MEDFileMesh::isEqual(other,eps,what))
1482     return false;
1483   const MEDFileUMesh *otherC=dynamic_cast<const MEDFileUMesh *>(other);
1484   if(!otherC)
1485     {
1486       what="Mesh types differ ! This is unstructured and other is NOT !";
1487       return false;
1488     }
1489   clearNonDiscrAttributes();
1490   otherC->clearNonDiscrAttributes();
1491   const DataArrayDouble *coo1=_coords;
1492   const DataArrayDouble *coo2=otherC->_coords;
1493   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
1494     {
1495       what="Mismatch of coordinates ! One is defined and not other !";
1496       return false;
1497     }
1498   if(coo1)
1499     {
1500       bool ret=coo1->isEqual(*coo2,eps);
1501       if(!ret)
1502         {
1503           what="Coords differ !";
1504           return false;
1505         }
1506     }
1507   const DataArrayInt *famc1=_fam_coords;
1508   const DataArrayInt *famc2=otherC->_fam_coords;
1509   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
1510     {
1511       what="Mismatch of families arr on nodes ! One is defined and not other !";
1512       return false;
1513     }
1514   if(famc1)
1515     {
1516       bool ret=famc1->isEqual(*famc2);
1517       if(!ret)
1518         {
1519           what="Families arr on node differ !";
1520           return false;
1521         }
1522     }
1523   const DataArrayInt *numc1=_num_coords;
1524   const DataArrayInt *numc2=otherC->_num_coords;
1525   if((numc1==0 && numc2!=0) || (numc1!=0 && numc2==0))
1526     {
1527       what="Mismatch of numbering arr on nodes ! One is defined and not other !";
1528       return false;
1529     }
1530   if(numc1)
1531     {
1532       bool ret=numc1->isEqual(*numc2);
1533       if(!ret)
1534         {
1535           what="Numbering arr on node differ !";
1536           return false;
1537         }
1538     }
1539   const DataArrayAsciiChar *namec1=_name_coords;
1540   const DataArrayAsciiChar *namec2=otherC->_name_coords;
1541   if((namec1==0 && namec2!=0) || (namec1!=0 && namec2==0))
1542     {
1543       what="Mismatch of naming arr on nodes ! One is defined and not other !";
1544       return false;
1545     }
1546   if(namec1)
1547     {
1548       bool ret=namec1->isEqual(*namec2);
1549       if(!ret)
1550         {
1551           what="Names arr on node differ !";
1552           return false;
1553         }
1554     }
1555   if(_ms.size()!=otherC->_ms.size())
1556     {
1557       what="Number of levels differs !";
1558       return false;
1559     }
1560   std::size_t sz=_ms.size();
1561   for(std::size_t i=0;i<sz;i++)
1562     {
1563       const MEDFileUMeshSplitL1 *s1=_ms[i];
1564       const MEDFileUMeshSplitL1 *s2=otherC->_ms[i];
1565       if((s1==0 && s2!=0) || (s1!=0 && s2==0))
1566         {
1567           what="Mismatch of presence of sub levels !";
1568           return false;
1569         }
1570       if(s1)
1571         {
1572           bool ret=s1->isEqual(s2,eps,what);
1573           if(!ret)
1574             return false;
1575         }
1576     }
1577   return true;
1578 }
1579
1580 void MEDFileUMesh::clearNonDiscrAttributes() const
1581 {
1582   MEDFileMesh::clearNonDiscrAttributes();
1583   const DataArrayDouble *coo1=_coords;
1584   if(coo1)
1585     (const_cast<DataArrayDouble *>(coo1))->setName("");//This parameter is not discriminant for comparison
1586   const DataArrayInt *famc1=_fam_coords;
1587   if(famc1)
1588     (const_cast<DataArrayInt *>(famc1))->setName("");//This parameter is not discriminant for comparison
1589   const DataArrayInt *numc1=_num_coords;
1590   if(numc1)
1591     (const_cast<DataArrayInt *>(numc1))->setName("");//This parameter is not discriminant for comparison
1592   const DataArrayAsciiChar *namc1=_name_coords;
1593   if(namc1)
1594     (const_cast<DataArrayAsciiChar *>(namc1))->setName("");//This parameter is not discriminant for comparison
1595   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
1596     {
1597       const MEDFileUMeshSplitL1 *tmp=(*it);
1598       if(tmp)
1599         tmp->clearNonDiscrAttributes();
1600     }
1601 }
1602
1603 MEDFileUMesh::MEDFileUMesh()
1604 {
1605 }
1606
1607 MEDFileUMesh::MEDFileUMesh(med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
1608 try
1609   {
1610     loadUMeshFromFile(fid,mName,dt,it);
1611   }
1612 catch(INTERP_KERNEL::Exception& e)
1613   {
1614     throw e;
1615   }
1616
1617 void MEDFileUMesh::loadUMeshFromFile(med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
1618 {
1619   MEDFileUMeshL2 loaderl2;
1620   ParaMEDMEM::MEDCouplingMeshType meshType;
1621   int dummy0,dummy1;
1622   std::string dummy2;
1623   int mid=MEDFileUMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dummy2);
1624   if(meshType!=UNSTRUCTURED)
1625     {
1626       std::ostringstream oss; oss << "Trying to load as unstructured an existing mesh with name '" << mName << "' !";
1627       throw INTERP_KERNEL::Exception(oss.str().c_str());
1628     }
1629   loaderl2.loadAll(fid,mid,mName,dt,it);
1630   int lev=loaderl2.getNumberOfLevels();
1631   _ms.resize(lev);
1632   for(int i=0;i<lev;i++)
1633     {
1634       if(!loaderl2.emptyLev(i))
1635         _ms[i]=new MEDFileUMeshSplitL1(loaderl2,mName,i);
1636       else
1637         _ms[i]=0;
1638     }
1639   MEDFileMeshL2::ReadFamiliesAndGrps(fid,mName,_families,_groups);
1640   //
1641   setName(loaderl2.getName());
1642   setDescription(loaderl2.getDescription());
1643   setIteration(loaderl2.getIteration());
1644   setOrder(loaderl2.getOrder());
1645   setTimeValue(loaderl2.getTime());
1646   setTimeUnit(loaderl2.getTimeUnit());
1647   _coords=loaderl2.getCoords();
1648   _fam_coords=loaderl2.getCoordsFamily();
1649   _num_coords=loaderl2.getCoordsNum();
1650   _name_coords=loaderl2.getCoordsName();
1651   computeRevNum();
1652 }
1653
1654 MEDFileUMesh::~MEDFileUMesh()
1655 {
1656 }
1657
1658 void MEDFileUMesh::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception)
1659 {
1660   const DataArrayDouble *coo=_coords;
1661   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
1662   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
1663   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
1664   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
1665   int spaceDim=coo?coo->getNumberOfComponents():0;
1666   int mdim=getMeshDimension();
1667   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
1668   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
1669   for(int i=0;i<spaceDim;i++)
1670     {
1671       std::string info=coo->getInfoOnComponent(i);
1672       std::string c,u;
1673       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
1674       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
1675       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
1676     }
1677   MEDmeshCr(fid,maa,spaceDim,mdim,MED_UNSTRUCTURED_MESH,desc,"",MED_SORT_DTIT,MED_CARTESIAN,comp,unit);
1678   MEDFileUMeshL2::WriteCoords(fid,maa,_iteration,_order,_time,_coords,_fam_coords,_num_coords,_name_coords);
1679   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
1680     if((const MEDFileUMeshSplitL1 *)(*it)!=0)
1681       (*it)->write(fid,maa,mdim);
1682   MEDFileUMeshL2::WriteFamiliesAndGrps(fid,maa,_families,_groups,_too_long_str);
1683 }
1684
1685 std::vector<int> MEDFileUMesh::getNonEmptyLevels() const
1686 {
1687   std::vector<int> ret;
1688   int lev=0;
1689   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
1690     if((const MEDFileUMeshSplitL1 *)(*it)!=0)
1691       if(!(*it)->empty())
1692         ret.push_back(lev);
1693   return ret;
1694 }
1695
1696 std::vector<int> MEDFileUMesh::getNonEmptyLevelsExt() const
1697 {
1698   std::vector<int> ret0=getNonEmptyLevels();
1699   if((const DataArrayDouble *) _coords)
1700     {
1701       std::vector<int> ret(ret0.size()+1);
1702       ret[0]=1;
1703       std::copy(ret0.begin(),ret0.end(),ret.begin()+1);
1704       return ret;
1705     }
1706   return ret0;
1707 }
1708
1709 /*!
1710  * This methods returns all relative mesh levels where group 'grp' is defined \b excluded \b nodes.
1711  * To include nodes call MEDFileUMesh::getGrpNonEmptyLevelsExt method.
1712  */
1713 std::vector<int> MEDFileUMesh::getGrpNonEmptyLevels(const char *grp) const throw(INTERP_KERNEL::Exception)
1714 {
1715   std::vector<std::string> fams=getFamiliesOnGroup(grp);
1716   return getFamsNonEmptyLevels(fams);
1717 }
1718
1719 /*!
1720  * This method is a generalization of MEDFileUMesh::getGrpNonEmptyLevelsExt. It looks at the node level to state if the group 'grp' has a part lying on node.
1721  */
1722 std::vector<int> MEDFileUMesh::getGrpNonEmptyLevelsExt(const char *grp) const throw(INTERP_KERNEL::Exception)
1723 {
1724   std::vector<std::string> fams=getFamiliesOnGroup(grp);
1725   return getFamsNonEmptyLevelsExt(fams);
1726 }
1727
1728 /*!
1729  * This methods returns all relative mesh levels where family 'fam' is defined \b excluded \b nodes.
1730  * To include nodes call MEDFileUMesh::getFamNonEmptyLevelsExt method.
1731  */
1732 std::vector<int> MEDFileUMesh::getFamNonEmptyLevels(const char *fam) const throw(INTERP_KERNEL::Exception)
1733 {
1734   std::vector<std::string> fams(1,std::string(fam));
1735   return getFamsNonEmptyLevels(fams);
1736 }
1737
1738 /*!
1739  * This method is a generalization of MEDFileUMesh::getFamNonEmptyLevels. It looks at the node level to state if the family 'fam' has a part lying on node.
1740  */
1741 std::vector<int> MEDFileUMesh::getFamNonEmptyLevelsExt(const char *fam) const throw(INTERP_KERNEL::Exception)
1742 {
1743   std::vector<std::string> fams(1,std::string(fam));
1744   return getFamsNonEmptyLevelsExt(fams);
1745 }
1746
1747 /*!
1748  * This methods returns all relative mesh levels where groups 'grps' are defined \b excluded \b nodes.
1749  * To include nodes call MEDFileUMesh::getGrpsNonEmptyLevelsExt method.
1750  */
1751 std::vector<int> MEDFileUMesh::getGrpsNonEmptyLevels(const std::vector<std::string>& grps) const throw(INTERP_KERNEL::Exception)
1752 {
1753   std::vector<std::string> fams=getFamiliesOnGroups(grps);
1754   return getFamsNonEmptyLevels(fams);
1755 }
1756
1757 /*!
1758  * This method is a generalization of MEDFileUMesh::getGrpsNonEmptyLevels. It looks at the node level to state if the families 'fams' has a part lying on node.
1759  */
1760 std::vector<int> MEDFileUMesh::getGrpsNonEmptyLevelsExt(const std::vector<std::string>& grps) const throw(INTERP_KERNEL::Exception)
1761 {
1762   std::vector<std::string> fams=getFamiliesOnGroups(grps);
1763   return getFamsNonEmptyLevelsExt(fams);
1764 }
1765
1766 /*!
1767  * This methods returns all relative mesh levels where families 'fams' are defined \b excluded \b nodes.
1768  * To include nodes call MEDFileUMesh::getFamsNonEmptyLevelsExt method.
1769  */
1770 std::vector<int> MEDFileUMesh::getFamsNonEmptyLevels(const std::vector<std::string>& fams) const throw(INTERP_KERNEL::Exception)
1771 {
1772   std::vector<int> ret;
1773   std::vector<int> levs=getNonEmptyLevels();
1774   std::vector<int> famIds=getFamiliesIds(fams);
1775   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
1776     if(_ms[-(*it)]->presenceOfOneFams(famIds))
1777       ret.push_back(*it);
1778   return ret;
1779 }
1780
1781 /*!
1782  * This method is a generalization of MEDFileUMesh::getFamsNonEmptyLevels. It looks at the node level to state if the families 'fams' has a part lying on node.
1783  */
1784 std::vector<int> MEDFileUMesh::getFamsNonEmptyLevelsExt(const std::vector<std::string>& fams) const throw(INTERP_KERNEL::Exception)
1785 {
1786   std::vector<int> ret0=getFamsNonEmptyLevels(fams);
1787   const DataArrayInt *famCoords=_fam_coords;
1788   if(!famCoords)
1789     return ret0;
1790   std::vector<int> famIds=getFamiliesIds(fams);
1791   if(famCoords->presenceOfValue(famIds))
1792     {
1793       std::vector<int> ret(ret0.size()+1);
1794       ret[0]=1;
1795       std::copy(ret0.begin(),ret0.end(),ret.begin()+1);
1796       return ret;
1797     }
1798   else
1799     return ret0;
1800 }
1801
1802 /*!
1803  * This method retrives all groups that partly or fully appear on the level 'meshDimRelToMaxExt'.
1804  */
1805 std::vector<std::string> MEDFileUMesh::getGroupsOnSpecifiedLev(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
1806 {
1807   std::vector<std::string> ret;
1808   std::vector<std::string> allGrps=getGroupsNames();
1809   for(std::vector<std::string>::const_iterator it=allGrps.begin();it!=allGrps.end();it++)
1810     {
1811       std::vector<int> levs=getGrpNonEmptyLevelsExt((*it).c_str());
1812       if(std::find(levs.begin(),levs.end(),meshDimRelToMaxExt)!=levs.end())
1813         ret.push_back(*it);
1814     }
1815   return ret;
1816 }
1817
1818 int MEDFileUMesh::getMaxFamilyIdInArrays() const throw(INTERP_KERNEL::Exception)
1819 {
1820   int ret=-std::numeric_limits<int>::max(),tmp=-1;
1821   if((const DataArrayInt *)_fam_coords)
1822     {
1823       int val=_fam_coords->getMaxValue(tmp);
1824       ret=std::max(ret,val);
1825     }
1826   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
1827     {
1828       if((const MEDFileUMeshSplitL1 *)(*it))
1829         {
1830           const DataArrayInt *da=(*it)->getFamilyField();
1831           if(da)
1832             {
1833               int val=_fam_coords->getMaxValue(tmp);
1834               ret=std::max(ret,val);
1835             }
1836         }
1837     }
1838   return ret;
1839 }
1840
1841 int MEDFileUMesh::getMinFamilyIdInArrays() const throw(INTERP_KERNEL::Exception)
1842 {
1843   int ret=std::numeric_limits<int>::max(),tmp=-1;
1844   if((const DataArrayInt *)_fam_coords)
1845     {
1846       int val=_fam_coords->getMinValue(tmp);
1847       ret=std::min(ret,val);
1848     }
1849   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
1850     {
1851       if((const MEDFileUMeshSplitL1 *)(*it))
1852         {
1853           const DataArrayInt *da=(*it)->getFamilyField();
1854           if(da)
1855             {
1856               int val=_fam_coords->getMinValue(tmp);
1857               ret=std::min(ret,val);
1858             }
1859         }
1860     }
1861   return ret;
1862 }
1863
1864 int MEDFileUMesh::getMeshDimension() const throw(INTERP_KERNEL::Exception)
1865 {
1866   int lev=0;
1867   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev++)
1868     if((const MEDFileUMeshSplitL1 *)(*it)!=0)
1869       return (*it)->getMeshDimension()+lev;
1870   throw INTERP_KERNEL::Exception("MEDFileUMesh::getMeshDimension : impossible to find a mesh dimension !");
1871 }
1872
1873 int MEDFileUMesh::getSpaceDimension() const throw(INTERP_KERNEL::Exception)
1874 {
1875   const DataArrayDouble *coo=_coords;
1876   if(!coo)
1877     throw INTERP_KERNEL::Exception(" MEDFileUMesh::getSpaceDimension : no coords set !");
1878   return coo->getNumberOfComponents();
1879 }
1880
1881 std::string MEDFileUMesh::simpleRepr() const
1882 {
1883   std::ostringstream oss;
1884   oss << MEDFileMesh::simpleRepr();
1885   const DataArrayDouble *coo=_coords;
1886   oss << "- The dimension of the space is ";
1887   static const char MSG1[]= "*** NO COORDS SET ***";
1888   static const char MSG2[]= "*** NO CONNECTIVITY SET FOR THIS LEVEL***";
1889   if(coo)
1890     oss << _coords->getNumberOfComponents() << std::endl;
1891   else
1892     oss << MSG1 << std::endl;
1893   oss << "- Type of the mesh : UNSTRUCTURED\n";
1894   oss << "- Number of nodes : ";
1895   if(coo)
1896     oss << _coords->getNumberOfTuples() << std::endl;
1897   else
1898     oss << MSG1 << std::endl;
1899   std::size_t nbOfLev=_ms.size();
1900   oss << "- Number of levels allocated : " << nbOfLev << std::endl;
1901   for(std::size_t i=0;i<nbOfLev;i++)
1902     {
1903       const MEDFileUMeshSplitL1 *lev=_ms[i];
1904       oss << "  - Level #" << -((int) i) << " has dimension : ";
1905       if(lev)
1906         {
1907           oss << lev->getMeshDimension() << std::endl;
1908           lev->simpleRepr(oss);
1909         }
1910       else
1911         oss << MSG2 << std::endl;
1912     }
1913   oss << "- Number of families : " << _families.size() << std::endl << std::endl;
1914   if(coo)
1915     {
1916       oss << "(***********************)\n(* NODES OF THE MESH : *)\n(***********************)\n";
1917       oss << "- Names of coordinates :" << std::endl;
1918       std::vector<std::string> vars=coo->getVarsOnComponent();
1919       std::copy(vars.begin(),vars.end(),std::ostream_iterator<std::string>(oss," "));
1920       oss << std::endl << "- Units of coordinates : " << std::endl;
1921       std::vector<std::string> units=coo->getUnitsOnComponent();
1922       std::copy(units.begin(),units.end(),std::ostream_iterator<std::string>(oss," "));
1923     }
1924   oss << std::endl << std::endl;
1925   getFamilyRepr(oss);
1926   return oss.str();
1927 }
1928
1929 std::string MEDFileUMesh::advancedRepr() const
1930 {
1931   return simpleRepr();
1932 }
1933
1934 int MEDFileUMesh::getSizeAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
1935 {
1936   if(meshDimRelToMaxExt==1)
1937     {
1938       if(!((const DataArrayDouble *)_coords))
1939         throw INTERP_KERNEL::Exception("MEDFileUMesh::getSizeAtLevel : no coordinates specified !");
1940       return _coords->getNumberOfTuples();
1941     }
1942   return getMeshAtLevSafe(meshDimRelToMaxExt)->getSize();
1943 }
1944
1945 const DataArrayInt *MEDFileUMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
1946 {
1947   if(meshDimRelToMaxExt==1)
1948     return _fam_coords;
1949   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
1950   return l1->getFamilyField();
1951 }
1952
1953 const DataArrayInt *MEDFileUMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
1954 {
1955   if(meshDimRelToMaxExt==1)
1956     return _num_coords;
1957   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
1958   return l1->getNumberField();
1959 }
1960
1961 const DataArrayAsciiChar *MEDFileUMesh::getNameFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
1962 {
1963   if(meshDimRelToMaxExt==1)
1964     return _name_coords;
1965   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
1966   return l1->getNameField();
1967 }
1968
1969 int MEDFileUMesh::getNumberOfNodes() const throw(INTERP_KERNEL::Exception)
1970 {
1971   const DataArrayDouble *coo=_coords;
1972   if(!coo)
1973     throw INTERP_KERNEL::Exception(" MEDFileUMesh::getNumberOfNodes : no coords set !");
1974   return coo->getNumberOfTuples();
1975 }
1976
1977 const DataArrayInt *MEDFileUMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
1978 {
1979   if(meshDimRelToMaxExt==1)
1980     {
1981       if(!((const DataArrayInt *)_num_coords))
1982         throw INTERP_KERNEL::Exception("MEDFileUMesh::getRevNumberFieldAtLevel : no coordinates renum specified !");
1983       return _rev_num_coords;
1984     }
1985   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
1986   return l1->getRevNumberField();
1987 }
1988
1989 /*!
1990  * This method returns coordinates in 'this'. The returned array reference counter is \b not incremented by this method (as MEDCouplingPointSet::getCoords does).
1991  */
1992 DataArrayDouble *MEDFileUMesh::getCoords() const
1993 {
1994   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp(_coords);
1995   if((DataArrayDouble *)tmp)
1996     {
1997       return tmp;
1998     }
1999   return 0;
2000 }
2001
2002 MEDCouplingUMesh *MEDFileUMesh::getGroup(int meshDimRelToMaxExt, const char *grp, bool renum) const throw(INTERP_KERNEL::Exception)
2003 {
2004   synchronizeTinyInfoOnLeaves();
2005   std::vector<std::string> tmp(1);
2006   tmp[0]=grp;
2007   MEDCouplingUMesh *ret=getGroups(meshDimRelToMaxExt,tmp,renum);
2008   ret->setName(grp);
2009   return ret;
2010 }
2011
2012 MEDCouplingUMesh *MEDFileUMesh::getGroups(int meshDimRelToMaxExt, const std::vector<std::string>& grps, bool renum) const throw(INTERP_KERNEL::Exception)
2013 {
2014   synchronizeTinyInfoOnLeaves();
2015   std::vector<std::string> fams2=getFamiliesOnGroups(grps);
2016   return getFamilies(meshDimRelToMaxExt,fams2,renum);
2017 }
2018
2019 MEDCouplingUMesh *MEDFileUMesh::getFamily(int meshDimRelToMaxExt, const char *fam, bool renum) const throw(INTERP_KERNEL::Exception)
2020 {
2021   synchronizeTinyInfoOnLeaves();
2022   std::vector<std::string> tmp(1);
2023   tmp[0]=fam;
2024   MEDCouplingUMesh *ret=getFamilies(meshDimRelToMaxExt,tmp,renum);
2025   ret->setName(fam);
2026   return ret;
2027 }
2028
2029 MEDCouplingUMesh *MEDFileUMesh::getFamilies(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const throw(INTERP_KERNEL::Exception)
2030 {
2031   synchronizeTinyInfoOnLeaves();
2032   if(meshDimRelToMaxExt==1)
2033     {
2034       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr=getFamiliesArr(1,fams,renum);
2035       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
2036       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> c=_coords->selectByTupleId(arr->getConstPointer(),arr->getConstPointer()+arr->getNbOfElems());
2037       ret->setCoords(c);
2038       return ret.retn();
2039     }
2040   std::vector<int> famIds=getFamiliesIds(fams);
2041   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2042   if(!famIds.empty())
2043     return l1->getFamilyPart(&famIds[0],&famIds[0]+famIds.size(),renum);
2044   else
2045     return l1->getFamilyPart(0,0,renum);
2046 }
2047
2048 DataArrayInt *MEDFileUMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const throw(INTERP_KERNEL::Exception)
2049 {
2050   std::vector<int> famIds=getFamiliesIds(fams);
2051   if(meshDimRelToMaxExt==1)
2052     {
2053       if((const DataArrayInt *)_fam_coords)
2054         {
2055           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
2056           if(!famIds.empty())
2057             da=_fam_coords->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
2058           else
2059             da=_fam_coords->getIdsEqualList(0,0);
2060           if(renum)
2061             return MEDFileUMeshSplitL1::Renumber(_num_coords,da);
2062           else
2063             return da.retn();
2064         }
2065       else
2066         throw INTERP_KERNEL::Exception("MEDFileUMesh::getFamiliesArr : no family array specified on nodes !");
2067     }
2068   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2069   if(!famIds.empty())
2070     return l1->getFamilyPartArr(&famIds[0],&famIds[0]+famIds.size(),renum);
2071   else
2072     return l1->getFamilyPartArr(0,0,renum);
2073 }
2074
2075 /*!
2076  * Returns a pointer to mesh at the specified level.
2077  * 
2078  * \return a pointer to unstructured mesh that need to be managed by the caller.
2079  * \warning the returned pointer has to be managed by the caller.
2080  * \sa MEDFileUMesh::getGenMeshAtLevel
2081  */
2082 MEDCouplingUMesh *MEDFileUMesh::getMeshAtLevel(int meshDimRelToMaxExt, bool renum) const throw(INTERP_KERNEL::Exception)
2083 {
2084   synchronizeTinyInfoOnLeaves();
2085   if(meshDimRelToMaxExt==1)
2086     {
2087       if(!renum)
2088         {
2089           MEDCouplingUMesh *umesh=MEDCouplingUMesh::New();
2090           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> cc=_coords->deepCpy();
2091           umesh->setCoords(cc);
2092           MEDFileUMeshSplitL1::ClearNonDiscrAttributes(umesh);
2093           umesh->setName(getName());
2094           return umesh;
2095         }
2096     }
2097   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2098   return l1->getWholeMesh(renum);
2099 }
2100
2101 /*!
2102  * Returns a pointer to mesh at the specified level.
2103  * 
2104  * \return a pointer to unstructured mesh that need to be managed by the caller.
2105  * \warning the returned pointer has to be managed by the caller.
2106  * \sa MEDFileUMesh::getMeshAtLevel
2107  */
2108 MEDCouplingMesh *MEDFileUMesh::getGenMeshAtLevel(int meshDimRelToMax, bool renum) const throw(INTERP_KERNEL::Exception)
2109 {
2110   return getMeshAtLevel(meshDimRelToMax,renum);
2111 }
2112
2113 MEDCouplingUMesh *MEDFileUMesh::getLevel0Mesh(bool renum) const throw(INTERP_KERNEL::Exception)
2114 {
2115   return getMeshAtLevel(0,renum);
2116 }
2117
2118 MEDCouplingUMesh *MEDFileUMesh::getLevelM1Mesh(bool renum) const throw(INTERP_KERNEL::Exception)
2119 {
2120   return getMeshAtLevel(-1,renum);
2121 }
2122
2123 MEDCouplingUMesh *MEDFileUMesh::getLevelM2Mesh(bool renum) const throw(INTERP_KERNEL::Exception)
2124 {
2125   return getMeshAtLevel(-2,renum);
2126 }
2127
2128 MEDCouplingUMesh *MEDFileUMesh::getLevelM3Mesh(bool renum) const throw(INTERP_KERNEL::Exception)
2129 {
2130   return getMeshAtLevel(-3,renum);
2131 }
2132
2133 const MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
2134 {
2135   if(meshDimRelToMaxExt==1)
2136     throw INTERP_KERNEL::Exception("Dimension request is invalid : asking for node level (1) !");
2137   if(meshDimRelToMaxExt>1)
2138     throw INTERP_KERNEL::Exception("Dimension request is invalid (>1) !");
2139   int tracucedRk=-meshDimRelToMaxExt;
2140   if(tracucedRk>=(int)_ms.size())
2141     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
2142   if((const MEDFileUMeshSplitL1 *)_ms[tracucedRk]==0)
2143     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
2144   return _ms[tracucedRk];
2145 }
2146
2147 MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt) throw(INTERP_KERNEL::Exception)
2148 {
2149    if(meshDimRelToMaxExt==1)
2150     throw INTERP_KERNEL::Exception("Dimension request is invalid : asking for node level (1) !");
2151   if(meshDimRelToMaxExt>1)
2152     throw INTERP_KERNEL::Exception("Dimension request is invalid (>1) !");
2153   int tracucedRk=-meshDimRelToMaxExt;
2154   if(tracucedRk>=(int)_ms.size())
2155     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
2156   if((const MEDFileUMeshSplitL1 *)_ms[tracucedRk]==0)
2157     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
2158   return _ms[tracucedRk];
2159 }
2160
2161 void MEDFileUMesh::checkMeshDimCoherency(int meshDim, int meshDimRelToMax) const throw(INTERP_KERNEL::Exception)
2162 {
2163   if(-meshDimRelToMax>=(int)_ms.size())
2164     throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMeshDimCoherency : The meshdim of mesh is not managed by 'this' !");
2165   int i=0;
2166   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,i++)
2167     {
2168       if(((const MEDFileUMeshSplitL1*) (*it))!=0)
2169         {
2170           int ref=(*it)->getMeshDimension();
2171           if(ref+i!=meshDim-meshDimRelToMax)
2172             throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMeshDimCoherency : no coherency between levels !");
2173         }
2174     }
2175 }
2176
2177 void MEDFileUMesh::setCoords(DataArrayDouble *coords) throw(INTERP_KERNEL::Exception)
2178 {
2179   if(!coords)
2180     throw INTERP_KERNEL::Exception("MEDFileUMesh::setCoords : null pointer in input !");
2181   coords->checkAllocated();
2182   int nbOfTuples=coords->getNumberOfTuples();
2183   _coords=coords;
2184   coords->incrRef();
2185   _fam_coords=DataArrayInt::New();
2186   _fam_coords->alloc(nbOfTuples,1);
2187   _fam_coords->fillWithZero();
2188 }
2189
2190 void MEDFileUMesh::eraseGroupsAtLevel(int meshDimRelToMaxExt) throw(INTERP_KERNEL::Exception)
2191 {
2192   if(meshDimRelToMaxExt==1)
2193     {
2194       if((DataArrayInt *)_fam_coords)
2195         _fam_coords->fillWithZero();
2196       return ;
2197     }
2198   MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
2199   l1->eraseFamilyField();
2200   optimizeFamilies();
2201 }
2202
2203 void MEDFileUMesh::optimizeFamilies() throw(INTERP_KERNEL::Exception)
2204 {
2205   std::vector<int> levs=getNonEmptyLevelsExt();
2206   std::set<int> allFamsIds;
2207   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
2208     {
2209       const DataArrayInt *ffield=getFamilyFieldAtLevel(*it);
2210       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=ffield->getDifferentValues();
2211       std::set<int> res;
2212       std::set_union(ids->begin(),ids->end(),allFamsIds.begin(),allFamsIds.end(),std::inserter(res,res.begin()));
2213       allFamsIds=res;
2214     }
2215   std::set<std::string> famNamesToKill;
2216   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
2217     {
2218       if(allFamsIds.find((*it).second)!=allFamsIds.end())
2219         famNamesToKill.insert((*it).first);
2220     }
2221   for(std::set<std::string>::const_iterator it=famNamesToKill.begin();it!=famNamesToKill.end();it++)
2222     _families.erase(*it);
2223   std::vector<std::string> grpNamesToKill;
2224   for(std::map<std::string, std::vector<std::string> >::iterator it=_groups.begin();it!=_groups.end();it++)
2225     {
2226       std::vector<std::string> tmp;
2227       for(std::vector<std::string>::const_iterator it2=(*it).second.begin();it2!=(*it).second.end();it2++)
2228         {
2229           if(famNamesToKill.find(*it2)==famNamesToKill.end())
2230             tmp.push_back(*it2);
2231         }
2232       if(!tmp.empty())
2233         (*it).second=tmp;
2234       else
2235         tmp.push_back((*it).first);
2236     }
2237   for(std::vector<std::string>::const_iterator it=grpNamesToKill.begin();it!=grpNamesToKill.end();it++)
2238     _groups.erase(*it);
2239 }
2240
2241 void MEDFileUMesh::duplicateNodesOnM1Group(const char *grpNameM1, DataArrayInt *&nodesDuplicated, DataArrayInt *&cellsModified, DataArrayInt *&cellsNotModified) throw(INTERP_KERNEL::Exception)
2242 {
2243   std::vector<int> levs=getNonEmptyLevels();
2244   if(std::find(levs.begin(),levs.end(),0)==levs.end() || std::find(levs.begin(),levs.end(),-1)==levs.end())
2245     throw INTERP_KERNEL::Exception("MEDFileUMesh::duplicateNodesOnM1Group : This method works only for mesh definied on level 0 and -1 !");
2246   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0=getMeshAtLevel(0);
2247   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1=getMeshAtLevel(-1);
2248   int nbNodes=m0->getNumberOfNodes();
2249   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m11=getGroup(-1,grpNameM1);
2250   DataArrayInt *tmp00=0,*tmp11=0,*tmp22=0;
2251   m0->findNodesToDuplicate(*m11,tmp00,tmp11,tmp22);
2252   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodeIdsToDuplicate(tmp00);
2253   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0(tmp11);
2254   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1(tmp22);
2255   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp0=static_cast<MEDCouplingUMesh *>(m0->buildPartOfMySelf(cellsToModifyConn0->begin(),cellsToModifyConn0->end(),true));
2256   // node renumbering of cells in m1 impacted by duplication of node but not in group 'grpNameM1' on level -1
2257   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descTmp0=DataArrayInt::New(),descITmp0=DataArrayInt::New(),revDescTmp0=DataArrayInt::New(),revDescITmp0=DataArrayInt::New();
2258   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp0Desc=tmp0->buildDescendingConnectivity(descTmp0,descITmp0,revDescTmp0,revDescITmp0);
2259   descTmp0=0; descITmp0=0; revDescTmp0=0; revDescITmp0=0;
2260   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsInM1ToRenumW2=tmp0Desc->getCellIdsLyingOnNodes(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),false);
2261   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cellsInM1ToRenumW3=static_cast<MEDCouplingUMesh *>(tmp0Desc->buildPartOfMySelf(cellsInM1ToRenumW2->begin(),cellsInM1ToRenumW2->end(),true));
2262   DataArrayInt *cellsInM1ToRenumW4Tmp=0;
2263   m1->areCellsIncludedIn(cellsInM1ToRenumW3,2,cellsInM1ToRenumW4Tmp);
2264   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsInM1ToRenumW4(cellsInM1ToRenumW4Tmp);
2265   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsInM1ToRenumW5=cellsInM1ToRenumW4->getIdsInRange(0,m1->getNumberOfCells());
2266   cellsInM1ToRenumW5->transformWithIndArr(cellsInM1ToRenumW4->begin(),cellsInM1ToRenumW4->end());
2267   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> grpIds=getGroupArr(-1,grpNameM1);
2268   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsInM1ToRenum=cellsInM1ToRenumW5->buildSubstraction(grpIds);
2269   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Part=static_cast<MEDCouplingUMesh *>(m1->buildPartOfMySelf(cellsInM1ToRenum->begin(),cellsInM1ToRenum->end(),true));
2270   m1Part->duplicateNodesInConn(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),nbNodes);
2271   m1->setPartOfMySelf(cellsInM1ToRenum->begin(),cellsInM1ToRenum->end(),*m1Part);
2272   // end of node renumbering of cells in m1 impacted by duplication of node but not in group of level -1 'grpNameM1'
2273   tmp0->duplicateNodes(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end());
2274   m0->setCoords(tmp0->getCoords());
2275   m0->setPartOfMySelf(cellsToModifyConn0->begin(),cellsToModifyConn0->end(),*tmp0);
2276   m1->setCoords(m0->getCoords());
2277   _coords=m0->getCoords(); _coords->incrRef();
2278   // duplication of cells in group 'grpNameM1' on level -1
2279   m11->duplicateNodesInConn(nodeIdsToDuplicate->begin(),nodeIdsToDuplicate->end(),nbNodes); m11->setCoords(m0->getCoords());
2280   std::vector<const MEDCouplingUMesh *> v(2); v[0]=m1; v[1]=m11;
2281   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> newm1=MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(v,tmp00,tmp11);
2282   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> szOfCellGrpOfSameType(tmp00);
2283   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idInMsOfCellGrpOfSameType(tmp11);
2284   //
2285   newm1->setName(getName());
2286   const DataArrayInt *fam=getFamilyFieldAtLevel(-1);
2287   if(!fam)
2288     throw INTERP_KERNEL::Exception("MEDFileUMesh::duplicateNodesOnM1Group : internal problem !");
2289   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newFam=DataArrayInt::New();
2290   newFam->alloc(newm1->getNumberOfCells(),1);
2291   int idd=getMaxFamilyId()+1;
2292   int globStart=0,start=0,end,globEnd;
2293   int nbOfChunks=szOfCellGrpOfSameType->getNumberOfTuples();
2294   for(int i=0;i<nbOfChunks;i++)
2295     {
2296       globEnd=globStart+szOfCellGrpOfSameType->getIJ(i,0);
2297       if(idInMsOfCellGrpOfSameType->getIJ(i,0)==0)
2298         {
2299           end=start+szOfCellGrpOfSameType->getIJ(i,0);
2300           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=fam->selectByTupleId2(start,end,1);
2301           newFam->setPartOfValues1(part,globStart,globEnd,1,0,1,1,true);
2302           start=end;
2303         }
2304       else
2305         {
2306           newFam->setPartOfValuesSimple1(idd,globStart,globEnd,1,0,1,1);
2307         }
2308       globStart=globEnd;
2309     }
2310   newm1->setCoords(getCoords());
2311   setMeshAtLevel(-1,newm1);
2312   setFamilyFieldArr(-1,newFam);
2313   std::string grpName2(grpNameM1); grpName2+="_dup";
2314   addFamily(grpName2.c_str(),idd);
2315   addFamilyOnGrp(grpName2.c_str(),grpName2.c_str());
2316   //
2317   fam=_fam_coords;
2318   if(fam)
2319     {
2320       int newNbOfNodes=getCoords()->getNumberOfTuples();
2321       newFam=DataArrayInt::New(); newFam->alloc(newNbOfNodes,1);
2322       newFam->setPartOfValues1(fam,0,nbNodes,1,0,1,1,true);
2323       newFam->setPartOfValuesSimple1(0,nbNodes,newNbOfNodes,1,0,1,1);
2324       _fam_coords=newFam;
2325     }
2326   nodesDuplicated=nodeIdsToDuplicate.retn();
2327   cellsModified=cellsToModifyConn0.retn();
2328   cellsNotModified=cellsToModifyConn1.retn();
2329 }
2330
2331 /*!
2332  * \param [out] oldCode retrieves the distribution of types before the call if true is returned
2333  * \param [out] newCode etrieves the distribution of types after the call if true is returned
2334  * \param [out] o2nRenumCell tells for **all levels** the old 2 new renumbering of cells.
2335  * 
2336  * \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.
2337  * 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.
2338  */
2339 bool MEDFileUMesh::unPolyze(std::vector<int>& oldCode, std::vector<int>& newCode, DataArrayInt *& o2nRenumCell) throw(INTERP_KERNEL::Exception)
2340 {
2341   o2nRenumCell=0; oldCode.clear(); newCode.clear();
2342   std::vector<int> levs=getNonEmptyLevels();
2343   bool ret=false;
2344   std::vector< const DataArrayInt* > renumCellsSplited;//same than memorySaverIfThrow
2345   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > memorySaverIfThrow;//same than renumCellsSplited only in case of throw
2346   int start=0;
2347   int end=0;
2348   for(std::vector<int>::reverse_iterator it=levs.rbegin();it!=levs.rend();it++)
2349     {
2350       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=getMeshAtLevel(*it);
2351       std::vector<int> code1=m->getDistributionOfTypes();
2352       end=PutInThirdComponentOfCodeOffset(code1,start);
2353       oldCode.insert(oldCode.end(),code1.begin(),code1.end());
2354       bool hasChanged=m->unPolyze();
2355       DataArrayInt *fake=0;
2356       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nCellsPart=m->getLevArrPerCellTypes(MEDCouplingUMesh::MEDMEM_ORDER,
2357                                                                                            MEDCouplingUMesh::MEDMEM_ORDER+MEDCouplingUMesh::N_MEDMEM_ORDER,fake);
2358       fake->decrRef();
2359       renumCellsSplited.push_back(o2nCellsPart); memorySaverIfThrow.push_back(o2nCellsPart);
2360       if(hasChanged)
2361         {
2362           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nCellsPart2=o2nCellsPart->buildPermArrPerLevel();
2363           m->renumberCells(o2nCellsPart2->getConstPointer(),false);
2364           ret=true;
2365           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famField2,numField2;
2366           const DataArrayInt *famField=getFamilyFieldAtLevel(*it); if(famField) { famField->incrRef(); famField2=const_cast<DataArrayInt *>(famField); }
2367           const DataArrayInt *numField=getNumberFieldAtLevel(*it); if(numField) { numField->incrRef(); numField2=const_cast<DataArrayInt *>(numField); }
2368           setMeshAtLevel(*it,m);
2369           std::vector<int> code2=m->getDistributionOfTypes();
2370           end=PutInThirdComponentOfCodeOffset(code2,start);
2371           newCode.insert(newCode.end(),code2.begin(),code2.end());
2372           //
2373           if(o2nCellsPart2->isIdentity())
2374             continue;
2375           if(famField)
2376             {
2377               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newFamField=famField->renumber(o2nCellsPart2->getConstPointer());
2378               setFamilyFieldArr(*it,newFamField);
2379             }
2380           if(numField)
2381             {
2382               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newNumField=numField->renumber(o2nCellsPart2->getConstPointer());
2383               setRenumFieldArr(*it,newNumField);
2384             }
2385         }
2386       else
2387         {
2388           newCode.insert(newCode.end(),code1.begin(),code1.end());
2389         }
2390       start=end;
2391     }
2392   if(ret)
2393     {
2394       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renumCells=DataArrayInt::Aggregate(renumCellsSplited);
2395       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRenumCellRet=renumCells->buildPermArrPerLevel();
2396       o2nRenumCell=o2nRenumCellRet.retn();
2397     }
2398   return ret;
2399 }
2400
2401 struct MEDLoaderAccVisit1
2402 {
2403   MEDLoaderAccVisit1():_new_nb_of_nodes(0) { }
2404   int operator()(bool val) { return val?_new_nb_of_nodes++:-1; }
2405   int _new_nb_of_nodes;
2406 };
2407
2408 /*!
2409  * 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.
2410  * The maximum value stored in returned array is the number of nodes of \a this minus 1 after call of this method.
2411  * The size of returned array is the number of nodes of the old (previous to the call of this method) number of nodes.
2412  * -1 values in returned array means that the corresponding old node is no more used.
2413  *
2414  * \return newly allocated array containing correspondance in \b old \b to \b new format. If all nodes in \a this are fetched NULL pointer is returned and nothing
2415  *         is modified in \a this.
2416  * \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
2417  *  set coordinates.
2418  */
2419 DataArrayInt *MEDFileUMesh::zipCoords() throw(INTERP_KERNEL::Exception)
2420 {
2421   const DataArrayDouble *coo=getCoords();
2422   if(!coo)
2423     throw INTERP_KERNEL::Exception("MEDFileUMesh::zipCoords : no coordinates set in this !");
2424   int nbOfNodes=coo->getNumberOfTuples();
2425   std::vector<bool> nodeIdsInUse(nbOfNodes,false);
2426   std::vector<int> neLevs=getNonEmptyLevels();
2427   for(std::vector<int>::const_iterator lev=neLevs.begin();lev!=neLevs.end();lev++)
2428     {
2429       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=getMeshAtLevel(*lev);
2430       m->computeNodeIdsAlg(nodeIdsInUse);
2431     }
2432   int nbrOfNodesInUse=(int)std::count(nodeIdsInUse.begin(),nodeIdsInUse.end(),true);
2433   if(nbrOfNodesInUse==nbOfNodes)
2434     return 0;
2435   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodes,1);
2436   std::transform(nodeIdsInUse.begin(),nodeIdsInUse.end(),ret->getPointer(),MEDLoaderAccVisit1());
2437   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2=ret->invertArrayO2N2N2OBis(nbrOfNodesInUse);
2438   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->selectByTupleIdSafe(ret2->begin(),ret2->end());
2439   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newFamCoords;
2440   MEDCouplingAutoRefCountObjectPtr<DataArrayAsciiChar> newNameCoords;
2441   if((const DataArrayInt *)_fam_coords)
2442     newFamCoords=_fam_coords->selectByTupleIdSafe(ret2->begin(),ret2->end());
2443   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newNumCoords;
2444   if((const DataArrayInt *)_num_coords)
2445     newNumCoords=_num_coords->selectByTupleIdSafe(ret2->begin(),ret2->end());
2446   if((const DataArrayAsciiChar *)_name_coords)
2447     newNameCoords=static_cast<DataArrayAsciiChar *>(_name_coords->selectByTupleIdSafe(ret2->begin(),ret2->end()));
2448   _coords=newCoords; _fam_coords=newFamCoords; _num_coords=newNumCoords; _name_coords=newNameCoords; _rev_num_coords=0;
2449   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
2450     {
2451       if((MEDFileUMeshSplitL1*)*it)
2452         (*it)->renumberNodesInConn(ret->begin());
2453     }
2454   return ret.retn();
2455 }
2456
2457 /*!
2458  * This method is here only to add a group on node.
2459  * MEDFileUMesh::setGroupsAtLevel with 1 in the first parameter.
2460  *
2461  * \param [in] ids node ids and group name of the new group to add. The ids should be sorted and different each other (MED file norm).
2462  */
2463 void MEDFileUMesh::addNodeGroup(const DataArrayInt *ids) throw(INTERP_KERNEL::Exception)
2464 {
2465   const DataArrayDouble *coords=_coords;
2466   if(!coords)
2467     throw INTERP_KERNEL::Exception("MEDFileUMesh::addNodeGroup : no coords set !");
2468   int nbOfNodes=coords->getNumberOfTuples();
2469   if(!((DataArrayInt *)_fam_coords))
2470     { _fam_coords=DataArrayInt::New(); _fam_coords->alloc(nbOfNodes,1); _fam_coords->fillWithZero(); }
2471   //
2472   addGroupUnderground(ids,_fam_coords);
2473 }
2474
2475 void MEDFileUMesh::addGroup(int meshDimRelToMaxExt, const DataArrayInt *ids) throw(INTERP_KERNEL::Exception)
2476 {
2477   std::vector<int> levs=getNonEmptyLevelsExt();
2478   if(std::find(levs.begin(),levs.end(),meshDimRelToMaxExt)==levs.end())
2479     { 
2480       std::ostringstream oss; oss << "MEDFileUMesh::addGroup : level " << meshDimRelToMaxExt << " not available ! Should be in ";
2481       std::copy(levs.begin(),levs.end(),std::ostream_iterator<int>(oss," ")); oss << " !"; throw INTERP_KERNEL::Exception(oss.str().c_str());
2482     }
2483   if(meshDimRelToMaxExt==1)
2484     { addNodeGroup(ids); return ; }
2485   MEDFileUMeshSplitL1 *lev=getMeshAtLevSafe(meshDimRelToMaxExt);
2486   DataArrayInt *fam=lev->getOrCreateAndGetFamilyField();
2487   addGroupUnderground(ids,fam);
2488 }
2489
2490 /*!
2491  * \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).
2492  * \parma [in,out] famArr family array on level of interest to be renumbered. The input pointer should be not NULL (no check of that will be performed)
2493  */
2494 void MEDFileUMesh::addGroupUnderground(const DataArrayInt *ids, DataArrayInt *famArr) throw(INTERP_KERNEL::Exception)
2495 {
2496   if(!ids)
2497     throw INTERP_KERNEL::Exception("MEDFileUMesh::addGroup : NULL pointer in input !");
2498   std::string grpName(ids->getName());
2499   if(grpName.empty())
2500     throw INTERP_KERNEL::Exception("MEDFileUMesh::addGroup : empty group name ! MED file format do not accept empty group name !");
2501   ids->checkStrictlyMonotonic(true);
2502   famArr->incrRef(); MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famArrTmp(famArr);
2503   std::vector<std::string> grpsNames=getGroupsNames();
2504   if(std::find(grpsNames.begin(),grpsNames.end(),grpName)!=grpsNames.end())
2505     {
2506       std::ostringstream oss; oss << "MEDFileUMesh::addGroup : Group with name \"" << grpName << "\" already exists ! Destroy it before calling this method !";
2507       throw INTERP_KERNEL::Exception(oss.str().c_str());
2508     }
2509   std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > allFamIds=getAllNonNullFamilyIds();
2510   allFamIds.erase(std::find(allFamIds.begin(),allFamIds.end(),famArrTmp));
2511   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famIds=famArr->selectByTupleIdSafe(ids->begin(),ids->end());
2512   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffFamIds=famIds->getDifferentValues();
2513   std::vector<int> familyIds;
2514   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerfamiliyIds;
2515   int maxVal=getTheMaxFamilyId()+1;
2516   std::map<std::string,int> families(_families);
2517   std::map<std::string, std::vector<std::string> > groups(_groups);
2518   std::vector<std::string> fams;
2519   bool created(false);
2520   for(const int *famId=diffFamIds->begin();famId!=diffFamIds->end();famId++)
2521     {
2522       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2Tmp=famIds->getIdsEqual(*famId);
2523       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=ids->selectByTupleId(ids2Tmp->begin(),ids2Tmp->end());
2524       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids1=famArr->getIdsEqual(*famId);
2525       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(ids1->buildSubstractionOptimized(ids2));
2526       if(ret0->empty())
2527         {
2528           bool isFamPresent=false;
2529           for(std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::const_iterator itl=allFamIds.begin();itl!=allFamIds.end() && !isFamPresent;itl++)
2530             isFamPresent=(*itl)->presenceOfValue(*famId);
2531           if(!isFamPresent)
2532             { familyIds.push_back(*famId); idsPerfamiliyIds.push_back(ret0); fams.push_back(FindOrCreateAndGiveFamilyWithId(families,*famId,created)); } // adding *famId in grp
2533           else
2534             {
2535               familyIds.push_back(maxVal); idsPerfamiliyIds.push_back(ids2); std::string locFamName=FindOrCreateAndGiveFamilyWithId(families,maxVal,created);
2536               fams.push_back(locFamName);
2537               if(existsFamily(*famId))
2538                 {
2539                   std::string locFamName2=getFamilyNameGivenId(*famId); std::vector<std::string> v(2); v[0]=locFamName2; v[1]=locFamName;
2540                   ChangeAllGroupsContainingFamily(groups,getFamilyNameGivenId(*famId).c_str(),v);
2541                 }
2542               maxVal++;
2543             } // modifying all other groups on *famId to lie on maxVal and lie the grp on maxVal
2544         }
2545       else
2546         {
2547           familyIds.push_back(maxVal); idsPerfamiliyIds.push_back(ret0); // modifying all other groups on *famId to lie on maxVal and on maxVal+1
2548           familyIds.push_back(maxVal+1); idsPerfamiliyIds.push_back(ids2);//grp lie only on maxVal+1
2549           std::string n2(FindOrCreateAndGiveFamilyWithId(families,maxVal+1,created)); fams.push_back(n2);
2550           if(existsFamily(*famId))
2551             {
2552               std::string n1(FindOrCreateAndGiveFamilyWithId(families,maxVal,created)); std::vector<std::string> v(2); v[0]=n1; v[1]=n2;
2553               ChangeAllGroupsContainingFamily(groups,getFamilyNameGivenId(*famId).c_str(),v);
2554             }
2555           maxVal+=2;
2556         }
2557     }
2558   for(std::size_t i=0;i<familyIds.size();i++)
2559     {
2560       DataArrayInt *da=idsPerfamiliyIds[i];
2561       famArr->setPartOfValuesSimple3(familyIds[i],da->begin(),da->end(),0,1,1);
2562     }
2563   _families=families;
2564   _groups=groups;
2565   _groups[grpName]=fams;
2566 }
2567
2568 void MEDFileUMesh::setFamilyNameAttachedOnId(int id, const std::string& newFamName) throw(INTERP_KERNEL::Exception)
2569 {
2570   std::string oldName=getFamilyNameGivenId(id);
2571   _families.erase(oldName);
2572   _families[newFamName]=id;
2573 }
2574
2575 void MEDFileUMesh::removeMeshAtLevel(int meshDimRelToMax) throw(INTERP_KERNEL::Exception)
2576 {
2577   std::vector<int> levSet=getNonEmptyLevels();
2578   std::vector<int>::const_iterator it=std::find(levSet.begin(),levSet.end(),meshDimRelToMax);
2579   if(it==levSet.end())
2580     throw INTERP_KERNEL::Exception("MEDFileUMesh::removeMeshAtLevel : the requested level is not existing !");
2581   int pos=(-meshDimRelToMax);
2582   _ms[pos]=0;
2583 }
2584
2585 void MEDFileUMesh::setMeshAtLevel(int meshDimRelToMax, MEDCouplingUMesh *m, bool newOrOld) throw(INTERP_KERNEL::Exception)
2586 {
2587   setMeshAtLevelGen(meshDimRelToMax,m,newOrOld);
2588 }
2589
2590 void MEDFileUMesh::setMeshAtLevelGen(int meshDimRelToMax, MEDCouplingUMesh *m, bool newOrOld) throw(INTERP_KERNEL::Exception)
2591 {
2592   dealWithTinyInfo(m);
2593   std::vector<int> levSet=getNonEmptyLevels();
2594   if(std::find(levSet.begin(),levSet.end(),meshDimRelToMax)==levSet.end())
2595     {
2596       if((DataArrayDouble *)_coords==0)
2597         {
2598           DataArrayDouble *c=m->getCoords();
2599           if(c)
2600             c->incrRef();
2601           _coords=c;
2602         }
2603       if(m->getCoords()!=_coords)
2604         throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshAtLevel : Invalid Given Mesh ! The coordinates are not the same ! try to use tryToShareSameCoords !");
2605       int sz=(-meshDimRelToMax)+1;
2606       if(sz>=(int)_ms.size())
2607         _ms.resize(sz);
2608       checkMeshDimCoherency(m->getMeshDimension(),meshDimRelToMax);
2609       _ms[sz-1]=new MEDFileUMeshSplitL1(m,newOrOld);
2610     }
2611   else
2612     _ms[-meshDimRelToMax]=new MEDFileUMeshSplitL1(m,newOrOld);
2613 }
2614
2615 void MEDFileUMesh::setGroupsFromScratch(int meshDimRelToMax, const std::vector<const MEDCouplingUMesh *>& ms) throw(INTERP_KERNEL::Exception)
2616 {
2617   if(ms.empty())
2618     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsFromScratch : expecting a non empty vector !");
2619   int sz=(-meshDimRelToMax)+1;
2620   if(sz>=(int)_ms.size())
2621     _ms.resize(sz);
2622   checkMeshDimCoherency(ms[0]->getMeshDimension(),meshDimRelToMax);
2623   DataArrayDouble *coo=checkMultiMesh(ms);
2624   if((DataArrayDouble *)_coords==0)
2625     {
2626       coo->incrRef();
2627       _coords=coo;
2628     }
2629   else
2630     if((DataArrayDouble *)_coords!=coo)
2631       throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsFromScratch : coordinates mismatches !");
2632   std::vector<DataArrayInt *> corr;
2633   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MEDCouplingUMesh::FuseUMeshesOnSameCoords(ms,_zipconn_pol,corr);
2634   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > corr3(corr.begin(),corr.end());
2635   setMeshAtLevel(meshDimRelToMax,m);
2636   std::vector<const DataArrayInt *> corr2(corr.begin(),corr.end());
2637   setGroupsAtLevel(meshDimRelToMax,corr2,true);
2638 }
2639
2640 void MEDFileUMesh::setGroupsOnSetMesh(int meshDimRelToMax, const std::vector<const MEDCouplingUMesh *>& ms, bool renum) throw(INTERP_KERNEL::Exception)
2641 {
2642   if(ms.empty())
2643     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsOnSetMesh : expecting a non empty vector !");
2644   int sz=(-meshDimRelToMax)+1;
2645   if(sz>=(int)_ms.size())
2646     _ms.resize(sz);
2647   checkMeshDimCoherency(ms[0]->getMeshDimension(),meshDimRelToMax);
2648   DataArrayDouble *coo=checkMultiMesh(ms);
2649   if((DataArrayDouble *)_coords==0)
2650     {
2651       coo->incrRef();
2652       _coords=coo;
2653     }
2654   else
2655     if((DataArrayDouble *)_coords!=coo)
2656       throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsOnSetMesh : coordinates mismatches !");
2657   MEDCouplingUMesh *m=getMeshAtLevel(meshDimRelToMax,renum);
2658   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > corr(ms.size());
2659   int i=0;
2660   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++,i++)
2661     {
2662       DataArrayInt *arr=0;
2663       bool test=m->areCellsIncludedIn(*it,_zipconn_pol,arr);
2664       corr[i]=arr;
2665       if(!test)
2666         {
2667           std::ostringstream oss; oss << "MEDFileUMesh::setGroupsOnSetMesh : mesh #" << i << " is not part of whole mesh !";
2668           throw INTERP_KERNEL::Exception(oss.str().c_str());
2669         }
2670     }
2671   std::vector<const DataArrayInt *> corr2(corr.begin(),corr.end());
2672   setGroupsAtLevel(meshDimRelToMax,corr2,renum);
2673 }
2674
2675 DataArrayDouble *MEDFileUMesh::checkMultiMesh(const std::vector<const MEDCouplingUMesh *>& ms) const throw(INTERP_KERNEL::Exception)
2676 {
2677   const DataArrayDouble *ret=ms[0]->getCoords();
2678   int mdim=ms[0]->getMeshDimension();
2679   for(unsigned int i=1;i<ms.size();i++)
2680     {
2681       ms[i]->checkCoherency();
2682       if(ms[i]->getCoords()!=ret)
2683         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMultiMesh : meshes must share the same coords !");
2684       if(ms[i]->getMeshDimension()!=mdim)
2685         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMultiMesh : meshes have not same mesh dimension !");
2686     }
2687   return const_cast<DataArrayDouble *>(ret);
2688 }
2689
2690 void MEDFileUMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr) throw(INTERP_KERNEL::Exception)
2691 {
2692   if(meshDimRelToMaxExt==1)
2693     {
2694       if(!famArr)
2695         {
2696           _fam_coords=0;
2697           return ;
2698         }
2699       DataArrayDouble *coo(_coords);
2700       if(!coo)
2701         throw INTERP_KERNEL::Exception("MEDFileUMesh::setFamilyFieldArr : the coordinates have not been set !");
2702       famArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),1,"MEDFileUMesh::setFamilyFieldArr : Problem in size of node family arr ! ");
2703       famArr->incrRef();
2704       _fam_coords=famArr;
2705       return ;
2706     }
2707   if(meshDimRelToMaxExt>1)
2708     throw INTERP_KERNEL::Exception("MEDFileUMesh::setFamilyFieldArr : Dimension request is invalid (>1) !");
2709   int traducedRk=-meshDimRelToMaxExt;
2710   if(traducedRk>=(int)_ms.size())
2711     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
2712   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
2713     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
2714   return _ms[traducedRk]->setFamilyArr(famArr);
2715 }
2716
2717 void MEDFileUMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr) throw(INTERP_KERNEL::Exception)
2718 {
2719   if(meshDimRelToMaxExt==1)
2720     {
2721       if(!renumArr)
2722         {
2723           _num_coords=0;
2724           _rev_num_coords=0;
2725           return ;
2726         }
2727       DataArrayDouble *coo(_coords);
2728       if(!coo)
2729         throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumFieldArr : the coordinates have not been set !");
2730       renumArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),1,"MEDFileUMesh::setRenumArr : Problem in size of node numbering arr ! ");
2731       renumArr->incrRef();
2732       _num_coords=renumArr;
2733       computeRevNum();
2734       return ;
2735     }
2736   if(meshDimRelToMaxExt>1)
2737     throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumArr : Dimension request is invalid (>1) !");
2738   int traducedRk=-meshDimRelToMaxExt;
2739   if(traducedRk>=(int)_ms.size())
2740     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
2741   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
2742     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
2743   return _ms[traducedRk]->setRenumArr(renumArr);
2744 }
2745
2746 void MEDFileUMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr) throw(INTERP_KERNEL::Exception)
2747 {
2748   if(meshDimRelToMaxExt==1)
2749     {
2750       if(!nameArr)
2751         {
2752           _name_coords=0;
2753           return ;
2754         }
2755       DataArrayDouble *coo(_coords);
2756       if(!coo)
2757         throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumFieldArr : the coordinates have not been set !");
2758       nameArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),MED_SNAME_SIZE,"MEDFileUMesh::setRenumArr : Problem in size of node numbering arr ! ");
2759       nameArr->incrRef();
2760       _name_coords=nameArr;
2761       return ;
2762     }
2763   if(meshDimRelToMaxExt>1)
2764     throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumArr : Dimension request is invalid (>1) !");
2765   int traducedRk=-meshDimRelToMaxExt;
2766   if(traducedRk>=(int)_ms.size())
2767     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
2768   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
2769     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
2770   return _ms[traducedRk]->setNameArr(nameArr);
2771 }
2772
2773 void MEDFileUMesh::synchronizeTinyInfoOnLeaves() const
2774 {
2775   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2776     if((const MEDFileUMeshSplitL1 *)(*it))
2777       (*it)->synchronizeTinyInfo(*this);
2778 }
2779
2780 /*!
2781  * This method is called by MEDFileMesh::changeFamilyId. It performs only one part of the family id modification.
2782  */
2783 void MEDFileUMesh::changeFamilyIdArr(int oldId, int newId) throw(INTERP_KERNEL::Exception)
2784 {
2785   DataArrayInt *arr=_fam_coords;
2786   if(arr)
2787     arr->changeValue(oldId,newId);
2788   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
2789     {
2790       MEDFileUMeshSplitL1 *sp=(*it);
2791       if(sp)
2792         {
2793           sp->changeFamilyIdArr(oldId,newId);
2794         }
2795     }
2796 }
2797
2798 std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > MEDFileUMesh::getAllNonNullFamilyIds() const
2799 {
2800   std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret;
2801   const DataArrayInt *da(_fam_coords);
2802   if(da)
2803     { da->incrRef(); ret.push_back(MEDCouplingAutoRefCountObjectPtr<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
2804   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
2805     {
2806       const MEDFileUMeshSplitL1 *elt(*it);
2807       if(elt)
2808         {
2809           da=elt->getFamilyField();
2810           if(da)
2811             { da->incrRef(); ret.push_back(MEDCouplingAutoRefCountObjectPtr<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
2812         }
2813     }
2814   return ret;
2815 }
2816
2817 void MEDFileUMesh::computeRevNum() const
2818 {
2819   if((const DataArrayInt *)_num_coords)
2820     {
2821       int pos;
2822       int maxValue=_num_coords->getMaxValue(pos);
2823       _rev_num_coords=_num_coords->invertArrayN2O2O2N(maxValue+1);
2824     }
2825 }
2826
2827 std::size_t MEDFileStructuredMesh::getHeapMemorySize() const
2828 {
2829   std::size_t ret=MEDFileMesh::getHeapMemorySize();
2830   if((const DataArrayInt*)_fam_nodes)
2831     ret+=_fam_nodes->getHeapMemorySize();
2832   if((const DataArrayInt*)_num_nodes)
2833     ret+=_num_nodes->getHeapMemorySize();
2834   if((const DataArrayInt*)_fam_cells)
2835     ret+=_fam_cells->getHeapMemorySize();
2836   if((const DataArrayInt*)_num_cells)
2837     ret+=_num_cells->getHeapMemorySize();
2838   if((const DataArrayInt*)_rev_num_nodes)
2839     ret+=_rev_num_nodes->getHeapMemorySize();
2840   if((const DataArrayInt*)_rev_num_cells)
2841     ret+=_rev_num_cells->getHeapMemorySize();
2842   return ret;
2843 }
2844
2845 int MEDFileStructuredMesh::getMaxFamilyIdInArrays() const throw(INTERP_KERNEL::Exception)
2846 {
2847   int ret=-std::numeric_limits<int>::max(),tmp=-1;
2848   if((const DataArrayInt *)_fam_nodes)
2849     {
2850       int val=_fam_nodes->getMaxValue(tmp);
2851       ret=std::max(ret,val);
2852     }
2853   if((const DataArrayInt *)_fam_cells)
2854     {
2855       int val=_fam_cells->getMaxValue(tmp);
2856       ret=std::max(ret,val);
2857     }
2858   return ret;
2859 }
2860
2861 int MEDFileStructuredMesh::getMinFamilyIdInArrays() const throw(INTERP_KERNEL::Exception)
2862 {
2863   int ret=std::numeric_limits<int>::max(),tmp=-1;
2864   if((const DataArrayInt *)_fam_nodes)
2865     {
2866       int val=_fam_nodes->getMinValue(tmp);
2867       ret=std::min(ret,val);
2868     }
2869   if((const DataArrayInt *)_fam_cells)
2870     {
2871       int val=_fam_cells->getMinValue(tmp);
2872       ret=std::min(ret,val);
2873     }
2874   return ret;
2875 }
2876
2877 bool MEDFileStructuredMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
2878 {
2879   if(!MEDFileMesh::isEqual(other,eps,what))
2880     return false;
2881   const MEDFileStructuredMesh *otherC=dynamic_cast<const  MEDFileStructuredMesh *>(other);
2882   if(!otherC)
2883     {
2884       what="Mesh types differ ! This is structured and other is NOT !";
2885       return false;
2886     }
2887   const DataArrayInt *famc1=_fam_nodes;
2888   const DataArrayInt *famc2=otherC->_fam_nodes;
2889   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
2890     {
2891       what="Mismatch of families arr on nodes ! One is defined and not other !";
2892       return false;
2893     }
2894   if(famc1)
2895     {
2896       bool ret=famc1->isEqual(*famc2);
2897       if(!ret)
2898         {
2899           what="Families arr on nodes differ !";
2900           return false;
2901         }
2902     }
2903   famc1=_fam_cells;
2904   famc2=otherC->_fam_cells;
2905   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
2906     {
2907       what="Mismatch of families arr on cells ! One is defined and not other !";
2908       return false;
2909     }
2910   if(famc1)
2911     {
2912       bool ret=famc1->isEqual(*famc2);
2913       if(!ret)
2914         {
2915           what="Families arr on cells differ !";
2916           return false;
2917         }
2918     }
2919   famc1=_num_nodes;
2920   famc2=otherC->_num_nodes;
2921   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
2922     {
2923       what="Mismatch of numbering arr on nodes ! One is defined and not other !";
2924       return false;
2925     }
2926   if(famc1)
2927     {
2928       bool ret=famc1->isEqual(*famc2);
2929       if(!ret)
2930         {
2931           what="Numbering arr on nodes differ !";
2932           return false;
2933         }
2934     }
2935   famc1=_num_cells;
2936   famc2=otherC->_num_cells;
2937   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
2938     {
2939       what="Mismatch of numbering arr on cells ! One is defined and not other !";
2940       return false;
2941     }
2942   if(famc1)
2943     {
2944       bool ret=famc1->isEqual(*famc2);
2945       if(!ret)
2946         {
2947           what="Numbering arr on cells differ !";
2948           return false;
2949         }
2950     }
2951   const DataArrayAsciiChar *d1=_names_cells;
2952   const DataArrayAsciiChar *d2=otherC->_names_cells;
2953   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
2954     {
2955       what="Mismatch of naming arr on cells ! One is defined and not other !";
2956       return false;
2957     }
2958   if(d1)
2959     {
2960       bool ret=d1->isEqual(*d2);
2961       if(!ret)
2962         {
2963           what="Naming arr on cells differ !";
2964           return false;
2965         }
2966     }
2967   d1=_names_nodes;
2968   d2=otherC->_names_nodes;
2969   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
2970     {
2971       what="Mismatch of naming arr on nodes ! One is defined and not other !";
2972       return false;
2973     }
2974   if(d1)
2975     {
2976       bool ret=d1->isEqual(*d2);
2977       if(!ret)
2978         {
2979           what="Naming arr on nodes differ !";
2980           return false;
2981         }
2982     }
2983   return true;
2984 }
2985
2986 void MEDFileStructuredMesh::clearNonDiscrAttributes() const
2987 {
2988   MEDFileMesh::clearNonDiscrAttributes();
2989   const DataArrayInt *tmp=_fam_nodes;
2990   if(tmp)
2991     (const_cast<DataArrayInt *>(tmp))->setName("");
2992   tmp=_num_nodes;
2993   if(tmp)
2994     (const_cast<DataArrayInt *>(tmp))->setName("");
2995   tmp=_fam_cells;
2996   if(tmp)
2997     (const_cast<DataArrayInt *>(tmp))->setName("");
2998   tmp=_num_cells;
2999   if(tmp)
3000     (const_cast<DataArrayInt *>(tmp))->setName("");
3001 }
3002
3003 DataArrayInt *MEDFileStructuredMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const throw(INTERP_KERNEL::Exception)
3004 {
3005   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
3006     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : Only available for levels 0 or 1 !");
3007   std::vector<int> famIds=getFamiliesIds(fams);
3008   if(meshDimRelToMaxExt==1)
3009     {
3010       if((const DataArrayInt *)_fam_nodes)
3011         {
3012           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
3013           if(!famIds.empty())
3014             da=_fam_nodes->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
3015           else
3016             da=_fam_nodes->getIdsEqualList(0,0);
3017           if(renum)
3018             return MEDFileUMeshSplitL1::Renumber(_num_nodes,da);
3019           else
3020             return da.retn();
3021         }
3022       else
3023         throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on nodes !");
3024     }
3025   else
3026     {
3027       if((const DataArrayInt *)_fam_cells)
3028         {
3029           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
3030           if(!famIds.empty())
3031             da=_fam_cells->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
3032           else
3033             da=_fam_cells->getIdsEqualList(0,0);
3034           if(renum)
3035             return MEDFileUMeshSplitL1::Renumber(_num_cells,da);
3036           else
3037             return da.retn();
3038         }
3039       else
3040         throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on cells !");
3041     }
3042 }
3043
3044 void MEDFileStructuredMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr) throw(INTERP_KERNEL::Exception)
3045 {
3046   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
3047     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : Only available for levels 0 or 1 !");
3048   const MEDCouplingStructuredMesh *mesh=getStructuredMesh();
3049   if(!mesh)
3050     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setFamilyFieldArr : no structured mesh specified ! Impossible to set family array !");
3051   if(meshDimRelToMaxExt==0)
3052     {
3053       int nbCells=mesh->getNumberOfCells();
3054       famArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of cells of mesh !");
3055       _fam_cells=famArr;
3056     }
3057   else
3058     {
3059       int nbNodes=mesh->getNumberOfNodes();
3060       famArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !");
3061       _fam_nodes=famArr;
3062     }
3063   if(famArr)
3064     famArr->incrRef();
3065 }
3066
3067 void MEDFileStructuredMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr) throw(INTERP_KERNEL::Exception)
3068 {
3069   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
3070     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : Only available for levels 0 or 1 !");
3071   const MEDCouplingStructuredMesh *mesh=getStructuredMesh();
3072   if(!mesh)
3073     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : no structured mesh specified ! Impossible to set number array !");
3074   if(meshDimRelToMaxExt==0)
3075     {
3076       int nbCells=mesh->getNumberOfCells();
3077       renumArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Renum arr ! Mismatch with number of cells of mesh !");
3078       _num_cells=renumArr;
3079     }
3080   else
3081     {
3082       int nbNodes=mesh->getNumberOfNodes();
3083       renumArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !");
3084       _num_nodes=renumArr;
3085     }
3086   if(renumArr)
3087     renumArr->incrRef();
3088 }
3089
3090 void MEDFileStructuredMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr) throw(INTERP_KERNEL::Exception)
3091 {
3092   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
3093     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : Only available for levels 0 or 1 !");
3094   const MEDCouplingStructuredMesh *mesh=getStructuredMesh();
3095   if(!mesh)
3096     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : no structured mesh specified ! Impossible to set names array !");
3097   if(meshDimRelToMaxExt==0)
3098     {
3099       int nbCells=mesh->getNumberOfCells();
3100       nameArr->checkNbOfTuplesAndComp(nbCells,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of cells of mesh !");
3101       _names_cells=nameArr;
3102     }
3103   else
3104     {
3105       int nbNodes=mesh->getNumberOfNodes();
3106       nameArr->checkNbOfTuplesAndComp(nbNodes,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of nodes of mesh !");
3107       _names_nodes=nameArr;
3108     }
3109   if(nameArr)
3110     nameArr->incrRef();
3111 }
3112
3113 const DataArrayInt *MEDFileStructuredMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
3114 {
3115   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
3116     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamilyFieldAtLevel : Only available for levels 0 or 1 !");
3117   if(meshDimRelToMaxExt==0)
3118     return _fam_cells;
3119   else
3120     return _fam_nodes;
3121 }
3122
3123 const DataArrayInt *MEDFileStructuredMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
3124 {
3125   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
3126     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberFieldAtLevel : Only available for levels 0 or 1 !");
3127   if(meshDimRelToMaxExt==0)
3128     return _num_cells;
3129   else
3130     return _num_nodes;
3131 }
3132
3133 const DataArrayInt *MEDFileStructuredMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
3134 {
3135   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
3136     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getRevNumberFieldAtLevel : Only available for levels 0 or 1 !");
3137   if(meshDimRelToMaxExt==0)
3138     {
3139       if((const DataArrayInt *)_num_cells)
3140         {
3141           int pos;
3142           int maxValue=_num_cells->getMaxValue(pos);
3143           _rev_num_cells=_num_cells->invertArrayN2O2O2N(maxValue+1);
3144           return _rev_num_cells;
3145         }
3146       else
3147         throw INTERP_KERNEL::Exception("MEDFileCMesh::getRevNumberFieldAtLevel : no cell renumbering for a request on reverse numbering !");
3148     }
3149   else
3150     {
3151       if((const DataArrayInt *)_num_nodes)
3152         {
3153           int pos;
3154           int maxValue=_num_nodes->getMaxValue(pos);
3155           _rev_num_nodes=_num_nodes->invertArrayN2O2O2N(maxValue+1);
3156           return _rev_num_nodes;
3157         }
3158       else
3159         throw INTERP_KERNEL::Exception("MEDFileCMesh::getRevNumberFieldAtLevel : no node renumbering for a request on reverse numbering !");
3160     }
3161 }
3162
3163 const DataArrayAsciiChar *MEDFileStructuredMesh::getNameFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
3164 {
3165   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
3166     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNameFieldAtLevel : Only available for levels 0 or 1 !");
3167   if(meshDimRelToMaxExt==0)
3168     return _names_cells;
3169   else
3170     return _names_nodes;
3171 }
3172
3173 std::vector<int> MEDFileStructuredMesh::getNonEmptyLevels() const
3174 {
3175   std::vector<int> ret(1);
3176   return ret;
3177 }
3178
3179 std::vector<int> MEDFileStructuredMesh::getNonEmptyLevelsExt() const
3180 {
3181   std::vector<int> ret(2);
3182   ret[0]=1;
3183   return ret;
3184 }
3185
3186 /*!
3187  * no implementation here, it is not a bug, but intresically no polyhedra in \a this.
3188  */
3189 bool MEDFileStructuredMesh::unPolyze(std::vector<int>& oldCode, std::vector<int>& newCode, DataArrayInt *& o2nRenumCell) throw(INTERP_KERNEL::Exception)
3190 {
3191   oldCode.clear(); newCode.clear(); o2nRenumCell=0;
3192   return false;
3193 }
3194
3195 void MEDFileStructuredMesh::changeFamilyIdArr(int oldId, int newId) throw(INTERP_KERNEL::Exception)
3196 {
3197   DataArrayInt *arr=_fam_nodes;
3198   if(arr)
3199     arr->changeValue(oldId,newId);
3200   arr=_fam_cells;
3201   if(arr)
3202     arr->changeValue(oldId,newId);
3203 }
3204
3205 void MEDFileStructuredMesh::deepCpyAttributes() throw(INTERP_KERNEL::Exception)
3206 {
3207   if((const DataArrayInt*)_fam_nodes)
3208     _fam_nodes=_fam_nodes->deepCpy();
3209   if((const DataArrayInt*)_num_nodes)
3210     _num_nodes=_num_nodes->deepCpy();
3211   if((const DataArrayInt*)_fam_cells)
3212     _fam_cells=_fam_cells->deepCpy();
3213   if((const DataArrayInt*)_num_cells)
3214     _num_cells=_num_cells->deepCpy();
3215   if((const DataArrayInt*)_rev_num_nodes)
3216     _rev_num_nodes=_rev_num_nodes->deepCpy();
3217   if((const DataArrayInt*)_rev_num_cells)
3218     _rev_num_cells=_rev_num_cells->deepCpy();
3219 }
3220
3221 /*!
3222  * Returns a pointer to mesh at the specified level (here 0 is compulsary for cartesian mesh).
3223  * 
3224  * \return a pointer to cartesian mesh that need to be managed by the caller.
3225  * \warning the returned pointer has to be managed by the caller.
3226  */
3227 MEDCouplingMesh *MEDFileStructuredMesh::getGenMeshAtLevel(int meshDimRelToMax, bool renum) const throw(INTERP_KERNEL::Exception)
3228 {
3229   if(renum)
3230     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support renumbering ! To do it perform request of renum array directly !");
3231   if(meshDimRelToMax!=0)
3232     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support multi level for mesh 0 expected as input !");
3233   const MEDCouplingStructuredMesh *m=getStructuredMesh();
3234   if(m)
3235     m->incrRef();
3236   return const_cast<MEDCouplingStructuredMesh *>(m);
3237 }
3238
3239 int MEDFileStructuredMesh::getSizeAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
3240 {
3241   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
3242     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : Only available for levels 0 or 1 !");
3243   const MEDCouplingStructuredMesh *cmesh=getStructuredMesh();
3244   if(!cmesh)
3245     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : No structured mesh set !");
3246   if(meshDimRelToMaxExt==0)
3247     return cmesh->getNumberOfCells();
3248   else
3249     return cmesh->getNumberOfNodes();
3250 }
3251
3252 int MEDFileStructuredMesh::getNumberOfNodes() const throw(INTERP_KERNEL::Exception)
3253 {
3254   const MEDCouplingStructuredMesh *cmesh=getStructuredMesh();
3255   if(!cmesh)
3256     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberOfNodes : no cartesian mesh set !");
3257   return cmesh->getNumberOfNodes();
3258 }
3259
3260 med_geometry_type MEDFileStructuredMesh::GetGeoTypeFromMeshDim(int meshDim) throw(INTERP_KERNEL::Exception)
3261 {
3262   med_geometry_type geoTypeReq=MED_NONE;
3263   switch(meshDim)
3264     {
3265     case 3:
3266       geoTypeReq=MED_HEXA8;
3267       break;
3268     case 2:
3269       geoTypeReq=MED_QUAD4;
3270       break;
3271     case 1:
3272       geoTypeReq=MED_SEG2;
3273       break;
3274     case 0:
3275       geoTypeReq=MED_POINT1;
3276       break;
3277     default:
3278       throw INTERP_KERNEL::Exception("Invalid meshdim detected for structured mesh ! Must be in (1,2,3) !");
3279     }
3280   return geoTypeReq;
3281 }
3282
3283 void MEDFileStructuredMesh::loadStrMeshFromFile(MEDFileStrMeshL2 *strm, med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
3284 {
3285   setName(strm->getName());
3286   setDescription(strm->getDescription());
3287   setIteration(strm->getIteration());
3288   setOrder(strm->getOrder());
3289   setTimeValue(strm->getTime());
3290   setTimeUnit(strm->getTimeUnit());
3291   MEDFileMeshL2::ReadFamiliesAndGrps(fid,mName,_families,_groups);
3292   med_bool chgt=MED_FALSE,trsf=MED_FALSE;
3293   int nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_NODE,MED_NONE,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf);
3294   if(nbOfElt>0)
3295     {
3296       _fam_nodes=DataArrayInt::New();
3297       _fam_nodes->alloc(nbOfElt,1);
3298       MEDmeshEntityFamilyNumberRd(fid,mName,dt,it,MED_NODE,MED_NONE,_fam_nodes->getPointer());
3299     }
3300   nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_NODE,MED_NONE,MED_NUMBER,MED_NODAL,&chgt,&trsf);
3301   if(nbOfElt>0)
3302     {
3303       _num_nodes=DataArrayInt::New();
3304       _num_nodes->alloc(nbOfElt,1);
3305       MEDmeshEntityNumberRd(fid,mName,dt,it,MED_NODE,MED_NONE,_num_nodes->getPointer());
3306     }
3307   int meshDim=getStructuredMesh()->getMeshDimension();
3308   med_geometry_type geoTypeReq=GetGeoTypeFromMeshDim(meshDim);
3309   nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_CELL,geoTypeReq,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf);
3310   if(nbOfElt>0)
3311     {
3312       _fam_cells=DataArrayInt::New();
3313       _fam_cells->alloc(nbOfElt,1);
3314       MEDmeshEntityFamilyNumberRd(fid,mName,dt,it,MED_CELL,geoTypeReq,_fam_cells->getPointer());
3315     }
3316   nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_CELL,geoTypeReq,MED_NUMBER,MED_NODAL,&chgt,&trsf);
3317   if(nbOfElt>0)
3318     {
3319       _num_cells=DataArrayInt::New();
3320       _num_cells->alloc(nbOfElt,1);
3321       MEDmeshEntityNumberRd(fid,mName,dt,it,MED_CELL,geoTypeReq,_num_cells->getPointer());
3322     }
3323   nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_CELL,geoTypeReq,MED_NAME,MED_NODAL,&chgt,&trsf);
3324   if(nbOfElt>0)
3325     {
3326       _names_cells=DataArrayAsciiChar::New();
3327       _names_cells->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end
3328       MEDmeshEntityNameRd(fid,mName,dt,it,MED_CELL,geoTypeReq,_names_cells->getPointer());
3329       _names_cells->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end
3330     }
3331   nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_NODE,MED_NONE,MED_NAME,MED_NODAL,&chgt,&trsf);
3332   if(nbOfElt>0)
3333     {
3334       _names_nodes=DataArrayAsciiChar::New();
3335       _names_nodes->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end
3336       MEDmeshEntityNameRd(fid,mName,dt,it,MED_NODE,MED_NONE,_names_nodes->getPointer());
3337       _names_nodes->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end
3338     }
3339 }
3340
3341 void MEDFileStructuredMesh::writeStructuredLL(med_idt fid, const char *maa) const throw(INTERP_KERNEL::Exception)
3342 {
3343   int meshDim=getStructuredMesh()->getMeshDimension();
3344   med_geometry_type geoTypeReq=GetGeoTypeFromMeshDim(meshDim);
3345   //
3346   if((const DataArrayInt *)_fam_cells)
3347     MEDmeshEntityFamilyNumberWr(fid,maa,_iteration,_order,MED_CELL,geoTypeReq,_fam_cells->getNumberOfTuples(),_fam_cells->getConstPointer());
3348   if((const DataArrayInt *)_fam_nodes)
3349     MEDmeshEntityFamilyNumberWr(fid,maa,_iteration,_order,MED_NODE,MED_NONE,_fam_nodes->getNumberOfTuples(),_fam_nodes->getConstPointer());
3350   if((const DataArrayInt *)_num_cells)
3351     MEDmeshEntityNumberWr(fid,maa,_iteration,_order,MED_CELL,geoTypeReq,_num_cells->getNumberOfTuples(),_num_cells->getConstPointer());
3352   if((const DataArrayInt *)_num_nodes)
3353     MEDmeshEntityNumberWr(fid,maa,_iteration,_order,MED_NODE,MED_NONE,_num_nodes->getNumberOfTuples(),_num_nodes->getConstPointer());
3354   if((const DataArrayAsciiChar *)_names_cells)
3355     {
3356       if(_names_cells->getNumberOfComponents()!=MED_SNAME_SIZE)
3357         {
3358           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on cells with number of components set to " << MED_SNAME_SIZE;
3359           oss << " ! The array has " << _names_cells->getNumberOfComponents() << " components !";
3360           throw INTERP_KERNEL::Exception(oss.str().c_str());
3361         }
3362       MEDmeshEntityNameWr(fid,maa,_iteration,_order,MED_CELL,geoTypeReq,_names_cells->getNumberOfTuples(),_names_cells->getConstPointer());
3363     }
3364   if((const DataArrayAsciiChar *)_names_nodes)
3365     {
3366       if(_names_nodes->getNumberOfComponents()!=MED_SNAME_SIZE)
3367         {
3368           std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on nodes with number of components set to " << MED_SNAME_SIZE;
3369           oss << " ! The array has " << _names_cells->getNumberOfComponents() << " components !";
3370           throw INTERP_KERNEL::Exception(oss.str().c_str());
3371         }
3372       MEDmeshEntityNameWr(fid,maa,_iteration,_order,MED_NODE,MED_NONE,_names_nodes->getNumberOfTuples(),_names_nodes->getConstPointer());
3373     }
3374   //
3375   MEDFileUMeshL2::WriteFamiliesAndGrps(fid,maa,_families,_groups,_too_long_str);
3376 }
3377
3378 MEDFileCMesh *MEDFileCMesh::New()
3379 {
3380   return new MEDFileCMesh;
3381 }
3382
3383 MEDFileCMesh *MEDFileCMesh::New(const char *fileName) throw(INTERP_KERNEL::Exception)
3384 {
3385   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
3386   if(ms.empty())
3387     {
3388       std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
3389       throw INTERP_KERNEL::Exception(oss.str().c_str());
3390     }
3391   MEDFileUtilities::CheckFileForRead(fileName);
3392   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
3393   int dt,it;
3394   ParaMEDMEM::MEDCouplingMeshType meshType;
3395   std::string dummy2;
3396   MEDFileMeshL2::GetMeshIdFromName(fid,ms.front().c_str(),meshType,dt,it,dummy2);
3397   return new MEDFileCMesh(fid,ms.front().c_str(),dt,it);
3398 }
3399
3400 MEDFileCMesh *MEDFileCMesh::New(const char *fileName, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
3401 {
3402   MEDFileUtilities::CheckFileForRead(fileName);
3403   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
3404   return new MEDFileCMesh(fid,mName,dt,it);
3405 }
3406
3407 std::size_t MEDFileCMesh::getHeapMemorySize() const
3408 {
3409   std::size_t ret=MEDFileStructuredMesh::getHeapMemorySize();
3410   if((const MEDCouplingCMesh *)_cmesh)
3411     ret+=_cmesh->getHeapMemorySize();
3412   return ret;
3413 }
3414
3415 int MEDFileCMesh::getMeshDimension() const throw(INTERP_KERNEL::Exception)
3416 {
3417   if(!((const MEDCouplingCMesh*)_cmesh))
3418     throw INTERP_KERNEL::Exception("MEDFileCMesh::getMeshDimension : unable to get meshdimension because no mesh set !");
3419   return _cmesh->getMeshDimension();
3420 }
3421
3422 std::string MEDFileCMesh::simpleRepr() const
3423 {
3424   return MEDFileStructuredMesh::simpleRepr();
3425 }
3426
3427 std::string MEDFileCMesh::advancedRepr() const
3428 {
3429   return simpleRepr();
3430 }
3431
3432 MEDFileMesh *MEDFileCMesh::shallowCpy() const throw(INTERP_KERNEL::Exception)
3433 {
3434   MEDCouplingAutoRefCountObjectPtr<MEDFileCMesh> ret=new MEDFileCMesh(*this);
3435   return ret.retn();
3436 }
3437
3438 MEDFileMesh *MEDFileCMesh::deepCpy() const throw(INTERP_KERNEL::Exception)
3439 {
3440   MEDCouplingAutoRefCountObjectPtr<MEDFileCMesh> ret=new MEDFileCMesh(*this);
3441   if((const MEDCouplingCMesh*)_cmesh)
3442     ret->_cmesh=static_cast<MEDCouplingCMesh*>(_cmesh->deepCpy());
3443   ret->deepCpyAttributes();
3444   return ret.retn();
3445 }
3446
3447 bool MEDFileCMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
3448 {
3449   if(!MEDFileStructuredMesh::isEqual(other,eps,what))
3450     return false;
3451   const MEDFileCMesh *otherC=dynamic_cast<const MEDFileCMesh *>(other);
3452   if(!otherC)
3453     {
3454       what="Mesh types differ ! This is cartesian and other is NOT !";
3455       return false;
3456     }
3457   clearNonDiscrAttributes();
3458   otherC->clearNonDiscrAttributes();
3459   const MEDCouplingCMesh *coo1=_cmesh;
3460   const MEDCouplingCMesh *coo2=otherC->_cmesh;
3461   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
3462     {
3463       what="Mismatch of cartesian meshes ! One is defined and not other !";
3464       return false;
3465     }
3466   if(coo1)
3467     {
3468       bool ret=coo1->isEqual(coo2,eps);
3469       if(!ret)
3470         {
3471           what="cartesian meshes differ !";
3472           return false;
3473         }
3474     }
3475   return true;
3476 }
3477
3478 void MEDFileCMesh::clearNonDiscrAttributes() const
3479 {
3480   MEDFileStructuredMesh::clearNonDiscrAttributes();
3481   MEDFileUMeshSplitL1::ClearNonDiscrAttributes(_cmesh);//to it is not a bug umeshsplit have already the method implemented
3482 }
3483
3484 MEDFileCMesh::MEDFileCMesh()
3485 {
3486 }
3487
3488 MEDFileCMesh::MEDFileCMesh(med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
3489 try
3490   {
3491     loadCMeshFromFile(fid,mName,dt,it);
3492   }
3493 catch(INTERP_KERNEL::Exception& e)
3494   {
3495     throw e;
3496   }
3497
3498 void MEDFileCMesh::loadCMeshFromFile(med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
3499 {
3500   ParaMEDMEM::MEDCouplingMeshType meshType;
3501   int dummy0,dummy1;
3502   std::string dtunit;
3503   int mid=MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dtunit);
3504   if(meshType!=CARTESIAN)
3505     {
3506       std::ostringstream oss; oss << "Trying to load as cartesian an existing mesh with name '" << mName << "' that is NOT cartesian !";
3507       throw INTERP_KERNEL::Exception(oss.str().c_str());
3508     }
3509   MEDFileCMeshL2 loaderl2;
3510   loaderl2.loadAll(fid,mid,mName,dt,it);
3511   MEDCouplingCMesh *mesh=loaderl2.getMesh();
3512   mesh->incrRef();
3513   _cmesh=mesh;
3514   loadStrMeshFromFile(&loaderl2,fid,mName,dt,it);
3515 }
3516
3517 const MEDCouplingCMesh *MEDFileCMesh::getMesh() const
3518 {
3519   synchronizeTinyInfoOnLeaves();
3520   return _cmesh;
3521 }
3522
3523 const MEDCouplingStructuredMesh *MEDFileCMesh::getStructuredMesh() const
3524 {
3525   synchronizeTinyInfoOnLeaves();
3526   return _cmesh;
3527 }
3528
3529 void MEDFileCMesh::setMesh(MEDCouplingCMesh *m) throw(INTERP_KERNEL::Exception)
3530 {
3531   dealWithTinyInfo(m);
3532   if(m)
3533     m->incrRef();
3534   _cmesh=m;
3535 }
3536
3537 void MEDFileCMesh::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception)
3538 {
3539   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
3540   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
3541   INTERP_KERNEL::AutoPtr<char> dtunit=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE);
3542   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
3543   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
3544   MEDLoaderBase::safeStrCpy(_dt_unit.c_str(),MED_LNAME_SIZE,dtunit,_too_long_str);
3545   int spaceDim=_cmesh->getSpaceDimension();
3546   int meshDim=_cmesh->getMeshDimension();
3547   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
3548   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
3549   for(int i=0;i<spaceDim;i++)
3550     {
3551       std::string info(_cmesh->getCoordsAt(i)->getInfoOnComponent(0));
3552       std::string c,u;
3553       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
3554       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
3555       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
3556     }
3557   MEDmeshCr(fid,maa,spaceDim,meshDim,MED_STRUCTURED_MESH,desc,dtunit,MED_SORT_DTIT,MED_CARTESIAN,comp,unit);
3558   MEDmeshGridTypeWr(fid,maa,MED_CARTESIAN_GRID);
3559   for(int i=0;i<spaceDim;i++)
3560     {
3561       const DataArrayDouble *da=_cmesh->getCoordsAt(i);
3562       MEDmeshGridIndexCoordinateWr(fid,maa,_iteration,_order,_time,i+1,da->getNumberOfTuples(),da->getConstPointer());
3563     }
3564   //
3565   MEDFileStructuredMesh::writeStructuredLL(fid,maa);
3566 }
3567
3568 void MEDFileCMesh::synchronizeTinyInfoOnLeaves() const
3569 {
3570   const MEDCouplingCMesh *cmesh=_cmesh;
3571   if(!cmesh)
3572     return;
3573   (const_cast<MEDCouplingCMesh *>(cmesh))->setName(_name.c_str());
3574   (const_cast<MEDCouplingCMesh *>(cmesh))->setDescription(_desc_name.c_str());
3575   (const_cast<MEDCouplingCMesh *>(cmesh))->setTime(_time,_iteration,_order);
3576   (const_cast<MEDCouplingCMesh *>(cmesh))->setTimeUnit(_dt_unit.c_str());
3577 }
3578
3579 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New()
3580 {
3581   return new MEDFileCurveLinearMesh;
3582 }
3583
3584 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const char *fileName) throw(INTERP_KERNEL::Exception)
3585 {
3586   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
3587   if(ms.empty())
3588     {
3589       std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
3590       throw INTERP_KERNEL::Exception(oss.str().c_str());
3591     }
3592   MEDFileUtilities::CheckFileForRead(fileName);
3593   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
3594   int dt,it;
3595   ParaMEDMEM::MEDCouplingMeshType meshType;
3596   std::string dummy2;
3597   MEDFileMeshL2::GetMeshIdFromName(fid,ms.front().c_str(),meshType,dt,it,dummy2);
3598   return new MEDFileCurveLinearMesh(fid,ms.front().c_str(),dt,it);
3599 }
3600
3601 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const char *fileName, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
3602 {
3603   MEDFileUtilities::CheckFileForRead(fileName);
3604   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
3605   return new MEDFileCurveLinearMesh(fid,mName,dt,it);
3606 }
3607
3608 std::size_t MEDFileCurveLinearMesh::getHeapMemorySize() const
3609 {
3610   std::size_t ret=MEDFileStructuredMesh::getHeapMemorySize();
3611   if((const MEDCouplingCurveLinearMesh *)_clmesh)
3612     ret+=_clmesh->getHeapMemorySize();
3613   return ret;
3614 }
3615
3616 MEDFileMesh *MEDFileCurveLinearMesh::shallowCpy() const throw(INTERP_KERNEL::Exception)
3617 {
3618   MEDCouplingAutoRefCountObjectPtr<MEDFileCurveLinearMesh> ret=new MEDFileCurveLinearMesh(*this);
3619   return ret.retn();
3620 }
3621
3622 MEDFileMesh *MEDFileCurveLinearMesh::deepCpy() const throw(INTERP_KERNEL::Exception)
3623 {
3624   MEDCouplingAutoRefCountObjectPtr<MEDFileCurveLinearMesh> ret=new MEDFileCurveLinearMesh(*this);
3625   if((const MEDCouplingCurveLinearMesh*)_clmesh)
3626     ret->_clmesh=static_cast<MEDCouplingCurveLinearMesh*>(_clmesh->deepCpy());
3627   ret->deepCpyAttributes();
3628   return ret.retn();
3629 }
3630
3631 int MEDFileCurveLinearMesh::getMeshDimension() const throw(INTERP_KERNEL::Exception)
3632 {
3633   if(!((const MEDCouplingCurveLinearMesh*)_clmesh))
3634     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::getMeshDimension : unable to get meshdimension because no mesh set !");
3635   return _clmesh->getMeshDimension();
3636 }
3637
3638 std::string MEDFileCurveLinearMesh::simpleRepr() const
3639 {
3640   return MEDFileStructuredMesh::simpleRepr();
3641 }
3642
3643 std::string MEDFileCurveLinearMesh::advancedRepr() const
3644 {
3645   return simpleRepr();
3646 }
3647
3648 bool MEDFileCurveLinearMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
3649 {
3650   if(!MEDFileStructuredMesh::isEqual(other,eps,what))
3651     return false;
3652   const MEDFileCurveLinearMesh *otherC=dynamic_cast<const MEDFileCurveLinearMesh *>(other);
3653   if(!otherC)
3654     {
3655       what="Mesh types differ ! This is curve linear and other is NOT !";
3656       return false;
3657     }
3658   clearNonDiscrAttributes();
3659   otherC->clearNonDiscrAttributes();
3660   const MEDCouplingCurveLinearMesh *coo1=_clmesh;
3661   const MEDCouplingCurveLinearMesh *coo2=otherC->_clmesh;
3662   if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0))
3663     {
3664       what="Mismatch of curve linear meshes ! One is defined and not other !";
3665       return false;
3666     }
3667   if(coo1)
3668     {
3669       bool ret=coo1->isEqual(coo2,eps);
3670       if(!ret)
3671         {
3672           what="curve linear meshes differ !";
3673           return false;
3674         }
3675     }
3676   return true;
3677 }
3678
3679 void MEDFileCurveLinearMesh::clearNonDiscrAttributes() const
3680 {
3681   MEDFileStructuredMesh::clearNonDiscrAttributes();
3682   MEDFileUMeshSplitL1::ClearNonDiscrAttributes(_clmesh);//to it is not a bug umeshsplit have already the method implemented
3683 }
3684
3685 void MEDFileCurveLinearMesh::synchronizeTinyInfoOnLeaves() const
3686 {
3687   const MEDCouplingCurveLinearMesh *clmesh=_clmesh;
3688   if(!clmesh)
3689     return;
3690   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setName(_name.c_str());
3691   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setDescription(_desc_name.c_str());
3692   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setTime(_time,_iteration,_order);
3693   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setTimeUnit(_dt_unit.c_str());
3694 }
3695
3696 const MEDCouplingCurveLinearMesh *MEDFileCurveLinearMesh::getMesh() const
3697 {
3698   synchronizeTinyInfoOnLeaves();
3699   return _clmesh;
3700 }
3701
3702 void MEDFileCurveLinearMesh::setMesh(MEDCouplingCurveLinearMesh *m) throw(INTERP_KERNEL::Exception)
3703 {
3704   dealWithTinyInfo(m);
3705   if(m)
3706     m->incrRef();
3707   _clmesh=m;
3708 }
3709
3710 const MEDCouplingStructuredMesh *MEDFileCurveLinearMesh::getStructuredMesh() const
3711 {
3712   synchronizeTinyInfoOnLeaves();
3713   return _clmesh;
3714 }
3715
3716 MEDFileCurveLinearMesh::MEDFileCurveLinearMesh()
3717 {
3718 }
3719
3720 MEDFileCurveLinearMesh::MEDFileCurveLinearMesh(med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
3721 try
3722   {
3723     loadCLMeshFromFile(fid,mName,dt,it);
3724   }
3725 catch(INTERP_KERNEL::Exception& e)
3726   {
3727     throw e;
3728   }
3729
3730 void MEDFileCurveLinearMesh::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception)
3731 {
3732   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
3733   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
3734   INTERP_KERNEL::AutoPtr<char> dtunit=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE);
3735   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
3736   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
3737   MEDLoaderBase::safeStrCpy(_dt_unit.c_str(),MED_LNAME_SIZE,dtunit,_too_long_str);
3738   int spaceDim=_clmesh->getSpaceDimension();
3739   int meshDim=_clmesh->getMeshDimension();
3740   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
3741   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
3742   const DataArrayDouble *coords=_clmesh->getCoords();
3743   if(!coords)
3744     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::writeLL : no coordinates set !");
3745   for(int i=0;i<spaceDim;i++)
3746     {
3747       std::string info(_clmesh->getCoords()->getInfoOnComponent(i));
3748       std::string c,u;
3749       MEDLoaderBase::splitIntoNameAndUnit(info,c,u);
3750       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
3751       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
3752     }
3753   MEDmeshCr(fid,maa,spaceDim,meshDim,MED_STRUCTURED_MESH,desc,dtunit,MED_SORT_DTIT,MED_CARTESIAN,comp,unit);
3754   MEDmeshGridTypeWr(fid,maa,MED_CURVILINEAR_GRID);
3755   std::vector<int> nodeGridSt=_clmesh->getNodeGridStructure();
3756   MEDmeshGridStructWr(fid,maa,_iteration,_order,_time,&nodeGridSt[0]);
3757   
3758   MEDmeshNodeCoordinateWr(fid,maa,_iteration,_order,_time,MED_FULL_INTERLACE,coords->getNumberOfTuples(),coords->begin());
3759   //
3760   MEDFileStructuredMesh::writeStructuredLL(fid,maa);
3761 }
3762
3763 void MEDFileCurveLinearMesh::loadCLMeshFromFile(med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
3764 {
3765   ParaMEDMEM::MEDCouplingMeshType meshType;
3766   int dummy0,dummy1;
3767   std::string dtunit;
3768   int mid=MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dtunit);
3769   if(meshType!=CURVE_LINEAR)
3770     {
3771       std::ostringstream oss; oss << "Trying to load as curve linear an existing mesh with name '" << mName << "' that is NOT curve linear !";
3772       throw INTERP_KERNEL::Exception(oss.str().c_str());
3773     }
3774   MEDFileCLMeshL2 loaderl2;
3775   loaderl2.loadAll(fid,mid,mName,dt,it);
3776   MEDCouplingCurveLinearMesh *mesh=loaderl2.getMesh();
3777   mesh->incrRef();
3778   _clmesh=mesh;
3779   loadStrMeshFromFile(&loaderl2,fid,mName,dt,it);
3780 }
3781
3782 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New()
3783 {
3784   return new MEDFileMeshMultiTS;
3785 }
3786
3787 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(const char *fileName) throw(INTERP_KERNEL::Exception)
3788 {
3789   return new MEDFileMeshMultiTS(fileName);
3790 }
3791
3792 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(const char *fileName, const char *mName) throw(INTERP_KERNEL::Exception)
3793 {
3794   return new MEDFileMeshMultiTS(fileName,mName);
3795 }
3796
3797 MEDFileMeshMultiTS *MEDFileMeshMultiTS::deepCpy() const throw(INTERP_KERNEL::Exception)
3798 {
3799   MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> ret=MEDFileMeshMultiTS::New();
3800   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> > meshOneTs(_mesh_one_ts.size());
3801   std::size_t i=0;
3802   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++,i++)
3803     if((const MEDFileMesh *)*it)
3804       meshOneTs[i]=(*it)->deepCpy();
3805   ret->_mesh_one_ts=meshOneTs;
3806   return ret.retn();
3807 }
3808
3809 std::size_t MEDFileMeshMultiTS::getHeapMemorySize() const
3810 {
3811   std::size_t ret=_mesh_one_ts.capacity()*sizeof(MEDCouplingAutoRefCountObjectPtr<MEDFileMesh>);
3812   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
3813     ret+=(*it)->getHeapMemorySize();
3814   return ret;
3815 }
3816
3817 const char *MEDFileMeshMultiTS::getName() const throw(INTERP_KERNEL::Exception)
3818 {
3819   if(_mesh_one_ts.empty())
3820     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::getName : no time steps set !");
3821   return _mesh_one_ts[0]->getName();
3822 }
3823
3824 void MEDFileMeshMultiTS::setName(const char *newMeshName) throw(INTERP_KERNEL::Exception)
3825 {
3826   std::string oldName(getName());
3827   std::vector< std::pair<std::string,std::string> > v(1);
3828   v[0].first=oldName; v[0].second=newMeshName;
3829   changeNames(v);
3830 }
3831
3832 bool MEDFileMeshMultiTS::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab) throw(INTERP_KERNEL::Exception)
3833 {
3834   bool ret=false;
3835   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
3836     {
3837       MEDFileMesh *cur(*it);
3838       if(cur)
3839         ret=cur->changeNames(modifTab) || ret;
3840     }
3841   return ret;
3842 }
3843
3844 MEDFileMesh *MEDFileMeshMultiTS::getOneTimeStep() const throw(INTERP_KERNEL::Exception)
3845 {
3846   if(_mesh_one_ts.empty())
3847     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::getOneTimeStep : empty time step set !");
3848   return const_cast<MEDFileMesh *>(static_cast<const MEDFileMesh *>(_mesh_one_ts[0]));
3849 }
3850
3851 void MEDFileMeshMultiTS::setOneTimeStep(MEDFileMesh *mesh1TimeStep) throw(INTERP_KERNEL::Exception)
3852 {
3853   if(!mesh1TimeStep)
3854     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::setOneTimeStep : input pointer should be different from 0 !");
3855   _mesh_one_ts.resize(1);
3856   mesh1TimeStep->incrRef();
3857   //MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> toto=mesh1TimeStep;
3858   _mesh_one_ts[0]=mesh1TimeStep;
3859 }
3860
3861 void MEDFileMeshMultiTS::write(med_idt fid) const throw(INTERP_KERNEL::Exception)
3862 {
3863   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
3864     {
3865       (*it)->copyOptionsFrom(*this);
3866       (*it)->write(fid);
3867     }
3868 }
3869
3870 void MEDFileMeshMultiTS::write(const char *fileName, int mode) const throw(INTERP_KERNEL::Exception)
3871 {
3872   med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode);
3873   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,medmod);
3874   std::ostringstream oss; oss << "MEDFileMesh : error on attempt to write in file : \"" << fileName << "\""; 
3875   MEDFileUtilities::CheckMEDCode(fid,fid,oss.str().c_str());
3876   write(fid);
3877 }
3878
3879 void MEDFileMeshMultiTS::loadFromFile(const char *fileName, const char *mName) throw(INTERP_KERNEL::Exception)
3880 {//for the moment to be improved
3881   _mesh_one_ts.resize(1);
3882   _mesh_one_ts[0]=MEDFileMesh::New(fileName,mName,-1,-1);
3883 }
3884
3885 MEDFileMeshMultiTS::MEDFileMeshMultiTS()
3886 {
3887 }
3888
3889 MEDFileMeshMultiTS::MEDFileMeshMultiTS(const char *fileName) throw(INTERP_KERNEL::Exception)
3890 try
3891   {
3892     std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
3893     if(ms.empty())
3894     {
3895       std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
3896       throw INTERP_KERNEL::Exception(oss.str().c_str());
3897     }
3898     MEDFileUtilities::CheckFileForRead(fileName);
3899     MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
3900     int dt,it;
3901     ParaMEDMEM::MEDCouplingMeshType meshType;
3902     std::string dummy2;
3903     MEDFileMeshL2::GetMeshIdFromName(fid,ms.front().c_str(),meshType,dt,it,dummy2);
3904     loadFromFile(fileName,ms.front().c_str());
3905   }
3906 catch(INTERP_KERNEL::Exception& e)
3907   {
3908     throw e;
3909   }
3910
3911 MEDFileMeshMultiTS::MEDFileMeshMultiTS(const char *fileName, const char *mName) throw(INTERP_KERNEL::Exception)
3912 try
3913   {
3914     loadFromFile(fileName,mName);
3915   }
3916 catch(INTERP_KERNEL::Exception& e)
3917   {
3918     throw e;
3919   }
3920
3921 MEDFileMeshes *MEDFileMeshes::New()
3922 {
3923   return new MEDFileMeshes;
3924 }
3925
3926 MEDFileMeshes *MEDFileMeshes::New(const char *fileName) throw(INTERP_KERNEL::Exception)
3927 {
3928   return new MEDFileMeshes(fileName);
3929 }
3930
3931 void MEDFileMeshes::write(med_idt fid) const throw(INTERP_KERNEL::Exception)
3932 {
3933   checkCoherency();
3934   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++)
3935     {
3936       (*it)->copyOptionsFrom(*this);
3937       (*it)->write(fid);
3938     }
3939 }
3940
3941 void MEDFileMeshes::write(const char *fileName, int mode) const throw(INTERP_KERNEL::Exception)
3942 {
3943   med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode);
3944   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,medmod);
3945   std::ostringstream oss; oss << "MEDFileMesh : error on attempt to write in file : \"" << fileName << "\""; 
3946   MEDFileUtilities::CheckMEDCode(fid,fid,oss.str().c_str());
3947   checkCoherency();
3948   write(fid);
3949 }
3950
3951 int MEDFileMeshes::getNumberOfMeshes() const throw(INTERP_KERNEL::Exception)
3952 {
3953   return _meshes.size();
3954 }
3955
3956 MEDFileMeshesIterator *MEDFileMeshes::iterator() throw(INTERP_KERNEL::Exception)
3957 {
3958   return new MEDFileMeshesIterator(this);
3959 }
3960
3961 MEDFileMesh *MEDFileMeshes::getMeshAtPos(int i) const throw(INTERP_KERNEL::Exception)
3962 {
3963   if(i<0 || i>=(int)_meshes.size())
3964     {
3965       std::ostringstream oss; oss << "MEDFileMeshes::getMeshAtPos : invalid mesh id given in parameter ! Should be in [0;" << _meshes.size() << ") !";
3966       throw INTERP_KERNEL::Exception(oss.str().c_str());
3967     }
3968   return _meshes[i]->getOneTimeStep();
3969 }
3970
3971 MEDFileMesh *MEDFileMeshes::getMeshWithName(const char *mname) const throw(INTERP_KERNEL::Exception)
3972 {
3973   std::vector<std::string> ms=getMeshesNames();
3974   std::vector<std::string>::iterator it=std::find(ms.begin(),ms.end(),mname);
3975   if(it==ms.end())
3976     {
3977       std::ostringstream oss; oss << "MEDFileMeshes::getMeshWithName : Mesh  \"" << mname << "\" does not exist in this ! Existing are : ";
3978       std::copy(ms.begin(),ms.end(),std::ostream_iterator<std::string>(oss," "));
3979       throw INTERP_KERNEL::Exception(oss.str().c_str());
3980     }
3981   return getMeshAtPos((int)std::distance(ms.begin(),it));
3982 }
3983
3984 std::vector<std::string> MEDFileMeshes::getMeshesNames() const throw(INTERP_KERNEL::Exception)
3985 {
3986   std::vector<std::string> ret(_meshes.size());
3987   int i=0;
3988   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
3989     {
3990       const MEDFileMeshMultiTS *f=(*it);
3991       if(f)
3992         {
3993           ret[i]=f->getName();
3994         }
3995       else
3996         {
3997           std::ostringstream oss; oss << "MEDFileMeshes::getMeshesNames : At rank #" << i << " mesh is not defined !";
3998           throw INTERP_KERNEL::Exception(oss.str().c_str());
3999         }
4000     }
4001   return ret;
4002 }
4003
4004 bool MEDFileMeshes::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab) throw(INTERP_KERNEL::Exception)
4005 {
4006   bool ret=false;
4007   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::iterator it=_meshes.begin();it!=_meshes.end();it++)
4008     {
4009       MEDFileMeshMultiTS *cur(*it);
4010       if(cur)
4011         ret=cur->changeNames(modifTab) || ret;
4012     }
4013   return ret;
4014 }
4015
4016 void MEDFileMeshes::resize(int newSize) throw(INTERP_KERNEL::Exception)
4017 {
4018   _meshes.resize(newSize);
4019 }
4020
4021 void MEDFileMeshes::pushMesh(MEDFileMesh *mesh) throw(INTERP_KERNEL::Exception)
4022 {
4023   if(!mesh)
4024     throw INTERP_KERNEL::Exception("MEDFileMeshes::pushMesh : invalid input pointer ! should be different from 0 !");
4025   MEDFileMeshMultiTS *elt=MEDFileMeshMultiTS::New();
4026   elt->setOneTimeStep(mesh);
4027   _meshes.push_back(elt);
4028 }
4029
4030 void MEDFileMeshes::setMeshAtPos(int i, MEDFileMesh *mesh) throw(INTERP_KERNEL::Exception)
4031 {
4032   if(!mesh)
4033     throw INTERP_KERNEL::Exception("MEDFileMeshes::setMeshAtPos : invalid input pointer ! should be different from 0 !");
4034   if(i>=(int)_meshes.size())
4035     _meshes.resize(i+1);
4036   MEDFileMeshMultiTS *elt=MEDFileMeshMultiTS::New();
4037   elt->setOneTimeStep(mesh);
4038   _meshes[i]=elt;
4039 }
4040
4041 void MEDFileMeshes::destroyMeshAtPos(int i) throw(INTERP_KERNEL::Exception)
4042 {
4043   if(i<0 || i>=(int)_meshes.size())
4044     {
4045       std::ostringstream oss; oss << "MEDFileMeshes::destroyMeshAtPos : Invalid given id in input (" << i << ") should be in [0," << _meshes.size() << ") !";
4046       throw INTERP_KERNEL::Exception(oss.str().c_str());
4047     }
4048   _meshes.erase(_meshes.begin()+i);
4049 }
4050
4051 void MEDFileMeshes::loadFromFile(const char *fileName) throw(INTERP_KERNEL::Exception)
4052 {
4053   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
4054   int i=0;
4055   _meshes.resize(ms.size());
4056   for(std::vector<std::string>::const_iterator it=ms.begin();it!=ms.end();it++,i++)
4057     _meshes[i]=MEDFileMeshMultiTS::New(fileName,(*it).c_str());
4058 }
4059
4060 MEDFileMeshes::MEDFileMeshes()
4061 {
4062 }
4063
4064 MEDFileMeshes::MEDFileMeshes(const char *fileName) throw(INTERP_KERNEL::Exception)
4065 try
4066   {
4067     loadFromFile(fileName);
4068   }
4069 catch(INTERP_KERNEL::Exception& e)
4070   {
4071   }
4072
4073 MEDFileMeshes *MEDFileMeshes::deepCpy() const throw(INTERP_KERNEL::Exception)
4074 {
4075   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> > meshes(_meshes.size());
4076   std::size_t i=0;
4077   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
4078     if((const MEDFileMeshMultiTS *)*it)
4079       meshes[i]=(*it)->deepCpy();
4080   MEDCouplingAutoRefCountObjectPtr<MEDFileMeshes> ret=MEDFileMeshes::New();
4081   ret->_meshes=meshes;
4082   return ret.retn();
4083 }
4084
4085 std::size_t MEDFileMeshes::getHeapMemorySize() const
4086 {
4087   std::size_t ret=_meshes.capacity()*(sizeof(MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS>));
4088   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++)
4089     if((const MEDFileMeshMultiTS*)*it)
4090       ret+=(*it)->getHeapMemorySize();
4091   return ret; 
4092 }
4093
4094 std::string MEDFileMeshes::simpleRepr() const
4095 {
4096   std::ostringstream oss;
4097   oss << "(*****************)\n(* MEDFileMeshes *)\n(*****************)\n\n";
4098   simpleReprWithoutHeader(oss);
4099   return oss.str();
4100 }
4101
4102 void MEDFileMeshes::simpleReprWithoutHeader(std::ostream& oss) const
4103 {
4104   int nbOfMeshes=getNumberOfMeshes();
4105   oss << "There are " << nbOfMeshes << " meshes with the following names : \n";
4106   std::vector<std::string> mns=getMeshesNames();
4107   for(int i=0;i<nbOfMeshes;i++)
4108     oss << "  - #" << i << " \"" << mns[i] << "\"\n";
4109 }
4110
4111 void MEDFileMeshes::checkCoherency() const throw(INTERP_KERNEL::Exception)
4112 {
4113   static const char MSG[]="MEDFileMeshes::checkCoherency : mesh at rank ";
4114   int i=0;
4115   std::set<std::string> s;
4116   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++)
4117     {
4118       const MEDFileMeshMultiTS *elt=(*it);
4119       if(!elt)
4120         {
4121           std::ostringstream oss; oss << MSG << i << "/" << _meshes.size() << " is empty !";
4122           throw INTERP_KERNEL::Exception(oss.str().c_str());
4123         }
4124       std::size_t sz=s.size();
4125       s.insert(std::string((*it)->getName()));
4126       if(s.size()==sz)
4127         {
4128           std::ostringstream oss; oss << MSG << i << " has a name (\"" << (*it)->getName() << "\") already used by an another mesh in list !";
4129           throw INTERP_KERNEL::Exception(oss.str().c_str());
4130         }
4131     }
4132 }
4133
4134 MEDFileMeshesIterator::MEDFileMeshesIterator(MEDFileMeshes *ms):_ms(ms),_iter_id(0),_nb_iter(0)
4135 {
4136   if(ms)
4137     {
4138       ms->incrRef();
4139       _nb_iter=ms->getNumberOfMeshes();
4140     }
4141 }
4142
4143 MEDFileMeshesIterator::~MEDFileMeshesIterator()
4144 {
4145 }
4146
4147 MEDFileMesh *MEDFileMeshesIterator::nextt()
4148 {
4149   if(_iter_id<_nb_iter)
4150     {
4151       MEDFileMeshes *ms(_ms);
4152       if(ms)
4153         return ms->getMeshAtPos(_iter_id++);
4154       else
4155         return 0;
4156     }
4157   else
4158     return 0;
4159 }