Salome HOME
Merge from V6_main 06/03/2013
[tools/medcoupling.git] / src / MEDLoader / MEDFileMeshLL.cxx
1 // Copyright (C) 2007-2012  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 "MEDFileMeshLL.hxx"
22 #include "MEDFileMesh.hxx"
23 #include "MEDLoaderBase.hxx"
24
25 #include "MEDCouplingUMesh.hxx"
26
27 #include "InterpKernelAutoPtr.hxx"
28 #include "CellModel.hxx"
29
30 #include <set>
31
32 extern med_geometry_type typmai[MED_N_CELL_FIXED_GEO];
33 extern INTERP_KERNEL::NormalizedCellType typmai2[MED_N_CELL_FIXED_GEO];
34 extern med_geometry_type typmainoeud[1];
35
36 using namespace ParaMEDMEM;
37
38 MEDFileMeshL2::MEDFileMeshL2():_name(MED_NAME_SIZE),_description(MED_COMMENT_SIZE),_dt_unit(MED_LNAME_SIZE)
39 {
40 }
41
42 int MEDFileMeshL2::GetMeshIdFromName(med_idt fid, const char *mname, ParaMEDMEM::MEDCouplingMeshType& meshType, int& dt, int& it, std::string& dtunit1) throw(INTERP_KERNEL::Exception)
43 {
44   med_mesh_type type_maillage;
45   char maillage_description[MED_COMMENT_SIZE+1];
46   char dtunit[MED_LNAME_SIZE+1];
47   med_int spaceDim,dim;
48   char nommaa[MED_NAME_SIZE+1];
49   med_int n=MEDnMesh(fid);
50   bool found=false;
51   int ret=-1;
52   med_sorting_type stype;
53   std::vector<std::string> ms;
54   int nstep;
55   med_axis_type axistype;
56   for(int i=0;i<n && !found;i++)
57     {
58       int naxis=MEDmeshnAxis(fid,i+1);
59       INTERP_KERNEL::AutoPtr<char> axisname=MEDLoaderBase::buildEmptyString(naxis*MED_SNAME_SIZE);
60       INTERP_KERNEL::AutoPtr<char> axisunit=MEDLoaderBase::buildEmptyString(naxis*MED_SNAME_SIZE);
61       MEDmeshInfo(fid,i+1,nommaa,&spaceDim,&dim,&type_maillage,maillage_description,dtunit,&stype,&nstep,&axistype,axisname,axisunit);
62       dtunit1=MEDLoaderBase::buildStringFromFortran(dtunit,sizeof(dtunit));
63       std::string cur=MEDLoaderBase::buildStringFromFortran(nommaa,sizeof(nommaa));
64       ms.push_back(cur);
65       if(cur==mname)
66         {
67           found=true;
68           ret=i+1;
69         }
70     }
71   if(!found)
72     {
73       std::ostringstream oss;
74       oss << "No such meshname (" << mname <<  ") in file ! Must be in :";
75       std::copy(ms.begin(),ms.end(),std::ostream_iterator<std::string>(oss,", "));
76       throw INTERP_KERNEL::Exception(oss.str().c_str());
77     }
78   switch(type_maillage)
79     {
80     case MED_UNSTRUCTURED_MESH:
81       meshType=UNSTRUCTURED;
82       break;
83     case MED_STRUCTURED_MESH:
84       {
85         med_grid_type gt;
86         MEDmeshGridTypeRd(fid,mname,&gt);
87         switch(gt)
88           {
89           case MED_CARTESIAN_GRID:
90             meshType=CARTESIAN;
91             break;
92           case MED_CURVILINEAR_GRID:
93             meshType=CURVE_LINEAR;
94             break;
95           default:
96             throw INTERP_KERNEL::Exception("MEDFileUMeshL2::getMeshIdFromName : unrecognized structured mesh type ! Supported are :\n - cartesian\n - curve linear\n");
97           }
98         break;
99       }
100     default:
101       throw INTERP_KERNEL::Exception("MEDFileUMeshL2::getMeshIdFromName : unrecognized mesh type !");
102     }
103   med_int numdt,numit;
104   med_float dtt;
105   MEDmeshComputationStepInfo(fid,mname,1,&numdt,&numit,&dtt);
106   dt=numdt; it=numit;
107   return ret;
108 }
109
110 double MEDFileMeshL2::CheckMeshTimeStep(med_idt fid, const char *mName, int nstep, int dt, int it) throw(INTERP_KERNEL::Exception)
111 {
112   bool found=false;
113   med_int numdt,numit;
114   med_float dtt;
115   std::vector< std::pair<int,int> > p(nstep);
116   for(int i=0;i<nstep;i++)
117     {
118       MEDmeshComputationStepInfo(fid,mName,i+1,&numdt,&numit,&dtt);
119       p[i]=std::make_pair<int,int>(numdt,numit);
120       found=(numdt==dt) && (numit==numit);
121     }
122   if(!found)
123     {
124       std::ostringstream oss; oss << "No such iteration=" << dt << ",order=" << it << " numbers found for mesh '" << mName << "' ! ";
125       oss << "Possibilities are : ";
126       for(int i=0;i<nstep;i++)
127         oss << "(" << p[i].first << "," << p[i].second << "), ";
128       throw INTERP_KERNEL::Exception(oss.str().c_str());
129     }
130   return dtt;
131 }
132
133 std::vector<std::string> MEDFileMeshL2::getAxisInfoOnMesh(med_idt fid, int mId, const char *mName, ParaMEDMEM::MEDCouplingMeshType& meshType, int& nstep, int& Mdim) throw(INTERP_KERNEL::Exception)
134 {
135   med_mesh_type type_maillage;
136   med_int spaceDim;
137   med_sorting_type stype;
138   med_axis_type axistype;
139   int naxis=MEDmeshnAxis(fid,mId);
140   INTERP_KERNEL::AutoPtr<char> nameTmp=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
141   INTERP_KERNEL::AutoPtr<char> axisname=MEDLoaderBase::buildEmptyString(naxis*MED_SNAME_SIZE);
142   INTERP_KERNEL::AutoPtr<char> axisunit=MEDLoaderBase::buildEmptyString(naxis*MED_SNAME_SIZE);
143   if(MEDmeshInfo(fid,mId,nameTmp,&spaceDim,&Mdim,&type_maillage,_description.getPointer(),_dt_unit.getPointer(),
144                  &stype,&nstep,&axistype,axisname,axisunit)!=0)
145     throw INTERP_KERNEL::Exception("A problem has been detected when trying to get info on mesh !");
146   switch(type_maillage)
147     {
148     case MED_UNSTRUCTURED_MESH:
149       meshType=UNSTRUCTURED;
150       break;
151     case MED_STRUCTURED_MESH:
152       {
153         med_grid_type gt;
154         MEDmeshGridTypeRd(fid,mName,&gt);
155         switch(gt)
156           {
157           case MED_CARTESIAN_GRID:
158             meshType=CARTESIAN;
159             break;
160           case MED_CURVILINEAR_GRID:
161             meshType=CURVE_LINEAR;
162             break;
163           default:
164             throw INTERP_KERNEL::Exception("MEDFileUMeshL2::getAxisInfoOnMesh : unrecognized structured mesh type ! Supported are :\n - cartesian\n - curve linear\n");
165           }
166         break;
167       }
168     default:
169       throw INTERP_KERNEL::Exception("MEDFileUMeshL2::getMeshIdFromName : unrecognized mesh type !");
170     }
171   //
172   std::vector<std::string> infosOnComp(naxis);
173   for(int i=0;i<naxis;i++)
174     {
175       std::string info=MEDLoaderBase::buildUnionUnit(((char *)axisname)+i*MED_SNAME_SIZE,MED_SNAME_SIZE,((char *)axisunit)+i*MED_SNAME_SIZE,MED_SNAME_SIZE);
176       infosOnComp[i]=info;
177     }
178   return infosOnComp;
179 }
180
181 void MEDFileMeshL2::ReadFamiliesAndGrps(med_idt fid, const char *meshName, std::map<std::string,int>& fams, std::map<std::string, std::vector<std::string> >& grps)
182 {
183   char nomfam[MED_NAME_SIZE+1];
184   med_int numfam;
185   int nfam=MEDnFamily(fid,meshName);
186   for(int i=0;i<nfam;i++)
187     {
188       int ngro=MEDnFamilyGroup(fid,meshName,i+1);
189       med_int natt=MEDnFamily23Attribute(fid,meshName,i+1);
190       INTERP_KERNEL::AutoPtr<med_int> attide=new med_int[natt];
191       INTERP_KERNEL::AutoPtr<med_int> attval=new med_int[natt];
192       INTERP_KERNEL::AutoPtr<char> attdes=new char[MED_COMMENT_SIZE*natt+1];
193       INTERP_KERNEL::AutoPtr<char> gro=new char[MED_LNAME_SIZE*ngro+1];
194       MEDfamily23Info(fid,meshName,i+1,nomfam,attide,attval,attdes,&numfam,gro);
195       std::string famName=MEDLoaderBase::buildStringFromFortran(nomfam,MED_NAME_SIZE);
196       fams[famName]=numfam;
197       for(int j=0;j<ngro;j++)
198         {
199           std::string groupname=MEDLoaderBase::buildStringFromFortran(gro+j*MED_LNAME_SIZE,MED_LNAME_SIZE);
200           grps[groupname].push_back(famName);
201         }
202     }
203 }
204
205 void MEDFileMeshL2::WriteFamiliesAndGrps(med_idt fid, const char *mname, const std::map<std::string,int>& fams, const std::map<std::string, std::vector<std::string> >& grps, int tooLongStrPol)
206 {
207   for(std::map<std::string,int>::const_iterator it=fams.begin();it!=fams.end();it++)
208     {
209       std::vector<std::string> grpsOfFam;
210       for(std::map<std::string, std::vector<std::string> >::const_iterator it1=grps.begin();it1!=grps.end();it1++)
211         {
212           if(std::find((*it1).second.begin(),(*it1).second.end(),(*it).first)!=(*it1).second.end())
213             grpsOfFam.push_back((*it1).first);
214         }
215       int ngro=grpsOfFam.size();
216       INTERP_KERNEL::AutoPtr<char> groName=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE*ngro);
217       int i=0;
218       for(std::vector<std::string>::const_iterator it2=grpsOfFam.begin();it2!=grpsOfFam.end();it2++,i++)
219         MEDLoaderBase::safeStrCpy2((*it2).c_str(),MED_LNAME_SIZE-1,groName+i*MED_LNAME_SIZE,tooLongStrPol);
220       INTERP_KERNEL::AutoPtr<char> famName=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
221       MEDLoaderBase::safeStrCpy((*it).first.c_str(),MED_NAME_SIZE,famName,tooLongStrPol);
222       int ret=MEDfamilyCr(fid,mname,famName,(*it).second,ngro,groName);
223       ret++;
224     }
225 }
226
227 MEDFileUMeshL2::MEDFileUMeshL2()
228 {
229 }
230
231 void MEDFileUMeshL2::loadAll(med_idt fid, int mId, const char *mName, int dt, int it)
232 {
233   _name.set(mName);
234   int nstep;
235   int Mdim;
236   ParaMEDMEM::MEDCouplingMeshType meshType;
237   std::vector<std::string> infosOnComp=getAxisInfoOnMesh(fid,mId,mName,meshType,nstep,Mdim);
238   if(meshType!=UNSTRUCTURED)
239     throw INTERP_KERNEL::Exception("Invalid mesh type ! You are expected an unstructured one whereas in file it is not an unstructured !");
240   _time=CheckMeshTimeStep(fid,mName,nstep,dt,it);
241   _iteration=dt;
242   _order=it;
243   loadConnectivity(fid,Mdim,mName,dt,it);//to improve check (dt,it) coherency
244   loadCoords(fid,mId,infosOnComp,mName,dt,it);
245 }
246
247 void MEDFileUMeshL2::loadConnectivity(med_idt fid, int mdim, const char *mName, int dt, int it)
248 {
249   _per_type_mesh.resize(1);
250   _per_type_mesh[0].clear();
251   for(int j=0;j<MED_N_CELL_FIXED_GEO;j++)
252     {
253       MEDFileUMeshPerType *tmp=MEDFileUMeshPerType::New(fid,mName,dt,it,mdim,typmai[j],typmai2[j]);
254       if(tmp)
255         _per_type_mesh[0].push_back(tmp);
256     }
257   sortTypes();
258 }
259
260 void MEDFileUMeshL2::loadCoords(med_idt fid, int mId, const std::vector<std::string>& infosOnComp, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
261 {
262   int spaceDim=infosOnComp.size();
263   med_bool changement,transformation;
264   int nCoords=MEDmeshnEntity(fid,mName,dt,it,MED_NODE,MED_NONE,MED_COORDINATE,MED_NO_CMODE,&changement,&transformation);
265   _coords=DataArrayDouble::New();
266   _coords->alloc(nCoords,spaceDim);
267   double *coordsPtr=_coords->getPointer();
268   MEDmeshNodeCoordinateRd(fid,mName,dt,it,MED_FULL_INTERLACE,coordsPtr);
269   _fam_coords=DataArrayInt::New();
270   _fam_coords->alloc(nCoords,1);
271   _num_coords=DataArrayInt::New();
272   _num_coords->alloc(nCoords,1);
273   if(MEDmeshnEntity(fid,mName,dt,it,MED_NODE,MED_NO_GEOTYPE,MED_FAMILY_NUMBER,MED_NODAL,&changement,&transformation)>0)
274     MEDmeshEntityFamilyNumberRd(fid,mName,dt,it,MED_NODE,MED_NO_GEOTYPE,_fam_coords->getPointer());
275   else
276     _fam_coords=0;
277   if(MEDmeshnEntity(fid,mName,dt,it,MED_NODE,MED_NO_GEOTYPE,MED_NUMBER,MED_NODAL,&changement,&transformation)>0)
278     MEDmeshEntityNumberRd(fid,mName,dt,it,MED_NODE,MED_NO_GEOTYPE,_num_coords->getPointer());
279   else
280     _num_coords=0;
281   for(int i=0;i<spaceDim;i++)
282     _coords->setInfoOnComponent(i,infosOnComp[i].c_str());
283 }
284
285 void MEDFileUMeshL2::sortTypes()
286 {
287   std::set<int> mdims;
288   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshPerType> > tmp(_per_type_mesh[0]);
289   _per_type_mesh.clear();
290   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshPerType> >::const_iterator it=tmp.begin();it!=tmp.end();it++)
291     mdims.insert((*it)->getDim());
292   if(mdims.empty())
293     return;
294   int mdim=*mdims.rbegin();
295   _per_type_mesh.resize(mdim+1);
296   for(int dim=mdim+1;dim!=0;dim--)
297     {
298       std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshPerType> >& elt=_per_type_mesh[mdim+1-dim];
299       for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshPerType> >::const_iterator it=tmp.begin();it!=tmp.end();it++)
300         if((*it)->getDim()==dim-1)
301           elt.push_back(*it);
302     }
303   // suppression of contiguous empty levels at the end of _per_type_mesh.
304   int nbOfUselessLev=0;
305   bool isFirst=true;
306   for(std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshPerType> > >::reverse_iterator it2=_per_type_mesh.rbegin();it2!=_per_type_mesh.rend();it2++)
307     {
308       if((*it2).empty() && isFirst)
309         {
310           nbOfUselessLev++;
311         }
312       else
313         isFirst=false;
314     }
315   _per_type_mesh.resize(_per_type_mesh.size()-nbOfUselessLev);
316 }
317
318 void MEDFileUMeshL2::WriteCoords(med_idt fid, const char *mname, int dt, int it, double time, const DataArrayDouble *coords, const DataArrayInt *famCoords, const DataArrayInt *numCoords)
319 {
320   if(!coords)
321     return ;
322   MEDmeshNodeCoordinateWr(fid,mname,dt,it,time,MED_FULL_INTERLACE,coords->getNumberOfTuples(),coords->getConstPointer());
323   if(famCoords)
324     MEDmeshEntityFamilyNumberWr(fid,mname,dt,it,MED_NODE,MED_NO_GEOTYPE,famCoords->getNumberOfTuples(),famCoords->getConstPointer());
325   if(numCoords)
326     MEDmeshEntityNumberWr(fid,mname,dt,it,MED_NODE,MED_NO_GEOTYPE,numCoords->getNumberOfTuples(),numCoords->getConstPointer());
327 }
328
329 bool MEDFileUMeshL2::isFamDefinedOnLev(int levId) const
330 {
331   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshPerType> >::const_iterator it=_per_type_mesh[levId].begin();it!=_per_type_mesh[levId].end();it++)
332     if((*it)->getFam()==0)
333       return false;
334   return true;
335 }
336
337 bool MEDFileUMeshL2::isNumDefinedOnLev(int levId) const
338 {
339   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshPerType> >::const_iterator it=_per_type_mesh[levId].begin();it!=_per_type_mesh[levId].end();it++)
340     if((*it)->getNum()==0)
341       return false;
342   return true;
343 }
344
345 MEDFileCMeshL2::MEDFileCMeshL2()
346 {
347 }
348
349 void MEDFileCMeshL2::loadAll(med_idt fid, int mId, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
350 {
351   _name.set(mName);
352   int nstep;
353   int Mdim;
354   ParaMEDMEM::MEDCouplingMeshType meshType;
355   std::vector<std::string> infosOnComp=getAxisInfoOnMesh(fid,mId,mName,meshType,nstep,Mdim);
356   if(meshType!=CARTESIAN)
357     throw INTERP_KERNEL::Exception("Invalid mesh type ! You are expected a structured one whereas in file it is not a structured !");
358   _time=CheckMeshTimeStep(fid,mName,nstep,dt,it);
359   _iteration=dt;
360   _order=it;
361   //
362   med_grid_type gridtype;
363   MEDmeshGridTypeRd(fid,mName,&gridtype);
364   if(gridtype!=MED_CARTESIAN_GRID)
365     throw INTERP_KERNEL::Exception("Invalid structured mesh ! Expected cartesian mesh type !");
366   _cmesh=MEDCouplingCMesh::New();
367   for(int i=0;i<Mdim;i++)
368     {
369       med_data_type dataTypeReq=GetDataTypeCorrespondingToSpaceId(i);
370       med_bool chgt=MED_FALSE,trsf=MED_FALSE;
371       int nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_NODE,MED_NONE,dataTypeReq,MED_NO_CMODE,&chgt,&trsf);
372       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> da=DataArrayDouble::New();
373       da->alloc(nbOfElt,1);
374       da->setInfoOnComponent(0,infosOnComp[i].c_str());
375       MEDmeshGridIndexCoordinateRd(fid,mName,dt,it,i+1,da->getPointer());
376       _cmesh->setCoordsAt(i,da);
377     }
378 }
379
380 med_data_type MEDFileCMeshL2::GetDataTypeCorrespondingToSpaceId(int id) throw(INTERP_KERNEL::Exception)
381 {
382   switch(id)
383     {
384     case 0:
385       return MED_COORDINATE_AXIS1;
386     case 1:
387       return MED_COORDINATE_AXIS2;
388     case 2:
389       return MED_COORDINATE_AXIS3;
390     default:
391       throw INTERP_KERNEL::Exception("Invalid meshdim detected in Cartesian Grid !");
392     }
393 }
394
395 MEDFileCLMeshL2::MEDFileCLMeshL2()
396 {
397 }
398
399 void MEDFileCLMeshL2::loadAll(med_idt fid, int mId, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
400 {
401   _name.set(mName);
402   int nstep;
403   int Mdim;
404   ParaMEDMEM::MEDCouplingMeshType meshType;
405   std::vector<std::string> infosOnComp=getAxisInfoOnMesh(fid,mId,mName,meshType,nstep,Mdim);
406   if(meshType!=CURVE_LINEAR)
407     throw INTERP_KERNEL::Exception("Invalid mesh type ! You are expected a structured one whereas in file it is not a structured !");
408   _time=CheckMeshTimeStep(fid,mName,nstep,dt,it);
409   _iteration=dt;
410   _order=it;
411   //
412   _clmesh=MEDCouplingCurveLinearMesh::New();
413   INTERP_KERNEL::AutoPtr<int> stGrid=new int[Mdim];
414   MEDmeshGridStructRd(fid,mName,dt,it,stGrid);
415   _clmesh->setNodeGridStructure(stGrid,((int *)stGrid)+Mdim);
416   med_bool chgt=MED_FALSE,trsf=MED_FALSE;
417   int nbNodes=MEDmeshnEntity(fid,mName,dt,it,MED_NODE,MED_NONE,MED_COORDINATE,MED_NO_CMODE,&chgt,&trsf);
418   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> da=DataArrayDouble::New();
419   da->alloc(nbNodes,infosOnComp.size());
420   da->setInfoOnComponents(infosOnComp);
421   MEDmeshNodeCoordinateRd(fid,mName,dt,it,MED_FULL_INTERLACE,da->getPointer());
422   _clmesh->setCoords(da);
423 }
424
425 MEDFileUMeshPermCompute::MEDFileUMeshPermCompute(const MEDFileUMeshSplitL1* st):_st(st),_mpt_time(0),_num_time(0)
426 {
427 }
428
429 /*!
430  * Warning it returns an instance to deallocate !!!!
431  */
432 MEDFileUMeshPermCompute::operator MEDCouplingUMesh *() const
433 {
434   _st->_m_by_types->updateTime();
435   _st->_num->updateTime();
436   if((MEDCouplingUMesh *)_m==0)
437     {
438       updateTime();
439       _m=static_cast<MEDCouplingUMesh *>(_st->_m_by_types->deepCpy());
440       _m->renumberCells(_st->_num->getConstPointer(),true);
441       return _m.retn();
442     }
443   else
444     {
445       if(_mpt_time==_st->_m_by_types->getTimeOfThis() && _num_time==_st->_num->getTimeOfThis())
446         return _m.retn();
447       else
448         {
449           updateTime();
450           _m=static_cast<MEDCouplingUMesh *>(_st->_m_by_types->deepCpy());
451           _m->renumberCells(_st->_num->getConstPointer(),true);
452           return _m.retn();
453         }
454     }
455 }
456
457 void MEDFileUMeshPermCompute::operator=(MEDCouplingUMesh *m)
458 {
459   _m=m;
460 }
461
462 void MEDFileUMeshPermCompute::updateTime() const
463 {
464   _mpt_time=_st->_m_by_types->getTimeOfThis();
465   _num_time=_st->_num->getTimeOfThis();
466 }
467
468 MEDFileUMeshSplitL1::MEDFileUMeshSplitL1(const MEDFileUMeshSplitL1& other):_m_by_types(other._m_by_types),_fam(other._fam),_num(other._num),_rev_num(other._rev_num),_m(this)
469 {
470 }
471
472 MEDFileUMeshSplitL1::MEDFileUMeshSplitL1(const MEDFileUMeshL2& l2, const char *mName, int id):_m(this)
473 {
474   const std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshPerType> >& v=l2.getLev(id);
475   if(v.empty())
476     return;
477   int sz=v.size();
478   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > msMSafe(sz);
479   std::vector<const MEDCouplingUMesh *> ms(sz);
480   for(int i=0;i<sz;i++)
481     {
482       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New("",v[i]->getDim());
483       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=l2.getCoords();
484       tmp->setCoords(tmp2);
485       tmp->setConnectivity(const_cast<DataArrayInt *>(v[i]->getNodal()),const_cast<DataArrayInt *>(v[i]->getNodalIndex()));
486       ms[i]=tmp; msMSafe[i]=tmp;
487     }
488   _m_by_types=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms);
489   _m_by_types->setName(mName);
490   if(l2.isFamDefinedOnLev(id))
491     {
492       int nbOfCells=_m_by_types->getNumberOfCells();
493       _fam=DataArrayInt::New();
494       _fam->alloc(nbOfCells,1);
495       int *w=_fam->getPointer();
496       for(int i=0;i<sz;i++)
497         w=std::copy(v[i]->getFam()->getConstPointer(),v[i]->getFam()->getConstPointer()+v[i]->getFam()->getNumberOfTuples(),w);
498     }
499   if(l2.isNumDefinedOnLev(id))
500     {
501       int nbOfCells=_m_by_types->getNumberOfCells();
502       _num=DataArrayInt::New();
503       _num->alloc(nbOfCells,1);
504       int *w=_num->getPointer();
505       for(int i=0;i<sz;i++)
506         w=std::copy(v[i]->getNum()->getConstPointer(),v[i]->getNum()->getConstPointer()+v[i]->getNum()->getNumberOfTuples(),w);
507       computeRevNum();
508     }
509 }
510
511 MEDFileUMeshSplitL1::MEDFileUMeshSplitL1(MEDCouplingUMesh *m):_m(this)
512 {
513   assignMesh(m,true);
514 }
515
516 MEDFileUMeshSplitL1::MEDFileUMeshSplitL1(MEDCouplingUMesh *m, bool newOrOld):_m(this)
517 {
518   assignMesh(m,newOrOld);
519 }
520
521 std::size_t MEDFileUMeshSplitL1::getHeapMemorySize() const
522 {
523   std::size_t ret=0;
524   if((const MEDCouplingUMesh *)_m_by_types)
525     {
526       ret+=_m_by_types->getHeapMemorySize();
527       if((const DataArrayDouble *)_m_by_types->getCoords())
528         ret-=_m_by_types->getCoords()->getHeapMemorySize();
529     }
530   if((const  DataArrayInt*)_fam)
531     ret+=_fam->getHeapMemorySize();
532   if((const  DataArrayInt*)_num)
533     ret+=_num->getHeapMemorySize();
534   if((const  DataArrayInt*)_rev_num)
535     ret+=_rev_num->getHeapMemorySize();
536   return ret;
537 }
538
539 MEDFileUMeshSplitL1 *MEDFileUMeshSplitL1::deepCpy() const
540 {
541   MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> ret=new MEDFileUMeshSplitL1(*this);
542   if((const MEDCouplingUMesh*)_m_by_types)
543     ret->_m_by_types=static_cast<MEDCouplingUMesh*>(_m_by_types->deepCpy());
544   if((const DataArrayInt *)_fam)
545     ret->_fam=_fam->deepCpy();
546   if((const DataArrayInt *)_num)
547     ret->_num=_num->deepCpy();
548   if((const DataArrayInt *)_rev_num)
549     ret->_rev_num=_rev_num->deepCpy();
550   return ret.retn();
551 }
552
553 bool MEDFileUMeshSplitL1::isEqual(const MEDFileUMeshSplitL1 *other, double eps, std::string& what) const
554 {
555   const MEDCouplingUMesh *m1=_m_by_types;
556   const MEDCouplingUMesh *m2=other->_m_by_types;
557   if((m1==0 && m2!=0) || (m1!=0 && m2==0))
558     {
559       what="Presence of mesh in one sublevel and not in other!";
560       return false;
561     }
562   if(m1)
563     if(!m1->isEqual(m2,eps))
564       {
565         what="meshes at a sublevel are not deeply equal !";
566         return false;
567       }
568   const DataArrayInt *d1=_fam;
569   const DataArrayInt *d2=other->_fam;
570   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
571     {
572       what="Presence of family arr in one sublevel and not in other!";
573       return false;
574     }
575   if(d1)
576     if(!d1->isEqual(*d2))
577       {
578         what="family arr at a sublevel are not deeply equal !";
579         return false;
580       }
581   d1=_num;
582   d2=other->_num;
583   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
584     {
585       what="Presence of cell numbering arr in one sublevel and not in other!";
586       return false;
587     }
588   if(d1)
589     if(!d1->isEqual(*d2))
590       {
591         what="Numbering cell arr at a sublevel are not deeply equal !";
592         return false;
593       }
594   return true;
595 }
596
597 void MEDFileUMeshSplitL1::synchronizeTinyInfo(const MEDFileMesh& master) const
598 {
599   const MEDCouplingUMesh *tmp=_m_by_types;
600   if(!tmp)
601     return ;
602   (const_cast<MEDCouplingUMesh *>(tmp))->setName(master.getName());
603   (const_cast<MEDCouplingUMesh *>(tmp))->setDescription(master.getDescription());
604   (const_cast<MEDCouplingUMesh *>(tmp))->setTime(master.getTimeValue(),master.getIteration(),master.getOrder());
605   (const_cast<MEDCouplingUMesh *>(tmp))->setTimeUnit(master.getTimeUnit());
606 }
607
608 void MEDFileUMeshSplitL1::clearNonDiscrAttributes() const
609 {
610   ClearNonDiscrAttributes(_m_by_types);
611 }
612
613 void MEDFileUMeshSplitL1::ClearNonDiscrAttributes(const MEDCouplingMesh *tmp)
614 {
615   if(!tmp)
616     return ;
617   (const_cast<MEDCouplingMesh *>(tmp))->setName("");
618   (const_cast<MEDCouplingMesh *>(tmp))->setDescription("");
619   (const_cast<MEDCouplingMesh *>(tmp))->setTime(0.,-1,-1);
620   (const_cast<MEDCouplingMesh *>(tmp))->setTimeUnit("");
621 }
622
623 void MEDFileUMeshSplitL1::assignMesh(MEDCouplingUMesh *m, bool newOrOld) throw(INTERP_KERNEL::Exception)
624 {
625   if(newOrOld)
626     {
627       m->incrRef();
628       _m=m;
629       _m_by_types=(MEDCouplingUMesh *)m->deepCpy();
630       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=_m_by_types->getRenumArrForConsecutiveCellTypesSpec(typmai2,typmai2+MED_N_CELL_FIXED_GEO);
631       if(!da->isIdentity())
632         {
633           _num=da->invertArrayO2N2N2O(m->getNumberOfCells());
634           _m.updateTime();
635           computeRevNum();
636           _m_by_types->renumberCells(da->getConstPointer(),false);
637         }
638     }
639   else
640     {
641       if(!m->checkConsecutiveCellTypesAndOrder(typmai2,typmai2+MED_N_CELL_FIXED_GEO))
642         throw INTERP_KERNEL::Exception("MEDFileUMeshSplitL1::assignMesh : the mode of mesh setting expects to follow the MED file numbering convention ! it is not the case !");
643       m->incrRef();
644       _m_by_types=m;
645     }
646   _fam=DataArrayInt::New();
647   _fam->alloc(m->getNumberOfCells(),1);
648   _fam->fillWithValue(0);
649 }
650
651 bool MEDFileUMeshSplitL1::empty() const
652 {
653   return ((const MEDCouplingUMesh *)_m_by_types)==0;
654 }
655
656 bool MEDFileUMeshSplitL1::presenceOfOneFams(const std::vector<int>& ids) const
657 {
658   const DataArrayInt *fam=_fam;
659   if(!fam)
660     return false;
661   return fam->presenceOfValue(ids);
662 }
663
664 int MEDFileUMeshSplitL1::getMeshDimension() const
665 {
666   return _m_by_types->getMeshDimension();
667 }
668
669 void MEDFileUMeshSplitL1::simpleRepr(std::ostream& oss) const
670 {
671   std::vector<int> code=_m_by_types->getDistributionOfTypes();
672   int nbOfTypes=code.size()/3;
673   for(int i=0;i<nbOfTypes;i++)
674     {
675       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType) code[3*i];
676       oss << "    - Number of cells with type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr() << " : " << code[3*i+1] << std::endl;
677     }
678 }
679
680 int MEDFileUMeshSplitL1::getSize() const throw(INTERP_KERNEL::Exception)
681 {
682   if((const MEDCouplingUMesh *)_m_by_types==0)
683     throw INTERP_KERNEL::Exception("MEDFileUMeshSplitL1::getSize : no mesh specified at level !");
684   return _m_by_types->getNumberOfCells();
685 }
686
687 MEDCouplingUMesh *MEDFileUMeshSplitL1::getFamilyPart(const int *idsBg, const int *idsEnd, bool renum) const
688 {
689   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsToKeep=_fam->getIdsEqualList(idsBg,idsEnd);
690   MEDCouplingUMesh *m=(MEDCouplingUMesh *)_m_by_types->buildPartOfMySelf(eltsToKeep->getConstPointer(),eltsToKeep->getConstPointer()+eltsToKeep->getNumberOfTuples(),true);
691   if(renum)
692     return renumIfNeeded(m,eltsToKeep->getConstPointer());
693   return m;
694 }
695
696 DataArrayInt *MEDFileUMeshSplitL1::getFamilyPartArr(const int *idsBg, const int *idsEnd, bool renum) const
697 {
698   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=_fam->getIdsEqualList(idsBg,idsEnd);
699   if(renum)
700     return renumIfNeededArr(da);
701   return da.retn();
702 }
703
704 MEDCouplingUMesh *MEDFileUMeshSplitL1::getWholeMesh(bool renum) const
705 {
706   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp;
707   if(renum)
708     tmp=_m;
709   else
710     tmp=_m_by_types;
711   return tmp.retn();
712 }
713
714 DataArrayInt *MEDFileUMeshSplitL1::getOrCreateAndGetFamilyField() throw(INTERP_KERNEL::Exception)
715 {
716   if((DataArrayInt *)_fam)
717     return _fam;
718   MEDCouplingUMesh *m(_m_by_types);
719   if(!m)
720     throw INTERP_KERNEL::Exception("MEDFileUMeshSplitL1::getOrCreateAndGetFamilyField : impossible to create a family field array because no mesh specified on this level !");
721   int nbOfTuples=m->getNumberOfCells();
722   _fam=DataArrayInt::New(); _fam->alloc(nbOfTuples,1); _fam->fillWithZero();
723   return _fam;
724 }
725
726 const DataArrayInt *MEDFileUMeshSplitL1::getFamilyField() const
727 {
728   return _fam;
729 }
730
731 const DataArrayInt *MEDFileUMeshSplitL1::getNumberField() const
732 {
733   return _num;
734 }
735
736 const DataArrayInt *MEDFileUMeshSplitL1::getRevNumberField() const
737 {
738   return _rev_num;
739 }
740
741 void MEDFileUMeshSplitL1::eraseFamilyField()
742 {
743   _fam->fillWithZero();
744 }
745
746 /*!
747  * This method ignores _m and _m_by_types.
748  */
749 void MEDFileUMeshSplitL1::setGroupsFromScratch(const std::vector<const MEDCouplingUMesh *>& ms, std::map<std::string,int>& familyIds,
750                                                std::map<std::string, std::vector<std::string> >& groups) throw(INTERP_KERNEL::Exception)
751 {
752   std::vector< DataArrayInt * > corr;
753   _m=MEDCouplingUMesh::FuseUMeshesOnSameCoords(ms,0,corr);
754   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > corrMSafe(corr.begin(),corr.end());
755   std::vector< std::vector<int> > fidsOfGroups;
756   std::vector< const DataArrayInt * > corr2(corr.begin(),corr.end());
757   _fam=DataArrayInt::MakePartition(corr2,((MEDCouplingUMesh *)_m)->getNumberOfCells(),fidsOfGroups);
758   int nbOfCells=((MEDCouplingUMesh *)_m)->getNumberOfCells();
759   std::map<int,std::string> newfams;
760   std::map<int,int> famIdTrad;
761   TraduceFamilyNumber(fidsOfGroups,familyIds,famIdTrad,newfams);
762   int *w=_fam->getPointer();
763   for(int i=0;i<nbOfCells;i++,w++)
764     *w=famIdTrad[*w];
765 }
766
767 void MEDFileUMeshSplitL1::write(med_idt fid, const char *mName, int mdim) const
768 {
769   std::vector<MEDCouplingUMesh *> ms=_m_by_types->splitByType();
770   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > msMSafe(ms.begin(),ms.end());
771   int start=0;
772   for(std::vector<MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
773     {
774       int nbCells=(*it)->getNumberOfCells();
775       int end=start+nbCells;
776       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fam,num;
777       if((const DataArrayInt *)_fam)
778         fam=_fam->substr(start,end);
779       if((const DataArrayInt *)_num)
780         num=_num->substr(start,end);
781       MEDFileUMeshPerType::write(fid,mName,mdim,(*it),fam,num);
782       start=end;
783     }
784 }
785
786 void MEDFileUMeshSplitL1::renumberNodesInConn(const int *newNodeNumbersO2N) throw(INTERP_KERNEL::Exception)
787 {
788   MEDCouplingUMesh *m(_m_by_types);
789   if(!m)
790     return;
791   m->renumberNodesInConn(newNodeNumbersO2N);
792 }
793
794 void MEDFileUMeshSplitL1::changeFamilyIdArr(int oldId, int newId) throw(INTERP_KERNEL::Exception)
795 {
796   DataArrayInt *arr=_fam;
797   if(arr)
798     arr->changeValue(oldId,newId);
799 }
800
801 void MEDFileUMeshSplitL1::setFamilyArr(DataArrayInt *famArr)
802 {
803   if(!famArr)
804     {
805       _fam=0;
806       return ;
807     }
808   MEDCouplingUMesh *mbt(_m_by_types);
809   if(!mbt)
810     throw INTERP_KERNEL::Exception("MEDFileUMeshSplitL1::setFamilyArr : no mesh defined on this level !");
811   famArr->checkNbOfTuplesAndComp(mbt->getNumberOfCells(),1,"MEDFileUMeshSplitL1::setFamilyArr : Problem in size of Family arr ! ");
812   famArr->incrRef();
813   _fam=famArr;
814 }
815
816 void MEDFileUMeshSplitL1::setRenumArr(DataArrayInt *renumArr)
817 {
818   if(!renumArr)
819     {
820       _num=0;
821       _rev_num=0;
822       return ;
823     }
824   MEDCouplingUMesh *mbt(_m_by_types);
825   if(!mbt)
826     throw INTERP_KERNEL::Exception("MEDFileUMeshSplitL1::setRenumArr : no mesh defined on this level !");
827   renumArr->checkNbOfTuplesAndComp(mbt->getNumberOfCells(),1,"MEDFileUMeshSplitL1::setRenumArr : Problem in size of numbering arr ! ");
828   renumArr->incrRef();
829   _num=renumArr;
830   computeRevNum();
831 }
832
833 MEDCouplingUMesh *MEDFileUMeshSplitL1::Renumber2(const DataArrayInt *renum, MEDCouplingUMesh *m, const int *cellIds)
834 {
835   if(renum==0)
836     return m;
837   if(cellIds==0)
838     m->renumberCells(renum->getConstPointer(),true);
839   else
840     {
841       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> locnum=renum->selectByTupleId(cellIds,cellIds+m->getNumberOfCells());
842       m->renumberCells(locnum->getConstPointer(),true);
843     }
844   return m;
845 }
846
847 MEDCouplingUMesh *MEDFileUMeshSplitL1::renumIfNeeded(MEDCouplingUMesh *m, const int *cellIds) const
848 {
849   return Renumber2(_num,m,cellIds);
850 }
851
852 DataArrayInt *MEDFileUMeshSplitL1::Renumber(const DataArrayInt *renum, const DataArrayInt *da)
853 {
854   if((const DataArrayInt *)renum==0)
855     {
856       da->incrRef();
857       return const_cast<DataArrayInt *>(da);
858     }
859   return renum->selectByTupleId(da->getConstPointer(),da->getConstPointer()+da->getNumberOfTuples());
860 }
861
862 DataArrayInt *MEDFileUMeshSplitL1::renumIfNeededArr(const DataArrayInt *da) const
863 {
864   return Renumber(_num,da);
865 }
866
867 std::vector<int> MEDFileUMeshSplitL1::GetNewFamiliesNumber(int nb, const std::map<std::string,int>& families)
868 {
869   int id=-1;
870   for(std::map<std::string,int>::const_iterator it=families.begin();it!=families.end();it++)
871     id=std::max(id,(*it).second);
872   if(id==-1)
873     id=0;
874   std::vector<int> ret(nb);
875   for(int i=1;i<=nb;i++)
876     ret[i]=id+i;
877   return ret;
878 }
879
880 void MEDFileUMeshSplitL1::TraduceFamilyNumber(const std::vector< std::vector<int> >& fidsGrps, std::map<std::string,int>& familyIds,
881                                               std::map<int,int>& famIdTrad, std::map<int,std::string>& newfams)
882 {
883   std::set<int> allfids;
884   
885 }
886
887 void MEDFileUMeshSplitL1::computeRevNum() const
888 {
889   int pos;
890   int maxValue=_num->getMaxValue(pos);
891   _rev_num=_num->invertArrayN2O2O2N(maxValue+1);
892 }