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