Salome HOME
83bdb7d9c4086020b94deca8d78f713ac9a58d1d
[tools/medcoupling.git] / src / MEDLoader / MEDFileMeshLL.cxx
1 // Copyright (C) 2007-2015  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, or (at your option) any later version.
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 #include "MEDFileSafeCaller.txx"
25 #include "MEDFileMeshReadSelector.hxx"
26
27 #include "MEDCouplingUMesh.hxx"
28
29 #include "InterpKernelAutoPtr.hxx"
30 #include "CellModel.hxx"
31
32 #include <set>
33 #include <iomanip>
34
35 extern med_geometry_type typmai[MED_N_CELL_FIXED_GEO];
36 extern INTERP_KERNEL::NormalizedCellType typmai2[MED_N_CELL_FIXED_GEO];
37 extern med_geometry_type typmainoeud[1];
38
39 using namespace MEDCoupling;
40
41 const char MEDFileMeshL2::ZE_SEP_FOR_FAMILY_KILLERS[]="!/__\\!";//important start by - because ord('!')==33 the smallest (!=' ') to preserve orders at most.
42
43 int MEDFileMeshL2::ZE_SEP2_FOR_FAMILY_KILLERS=4;
44
45 MEDFileMeshL2::MEDFileMeshL2():_name(MED_NAME_SIZE),_description(MED_COMMENT_SIZE),_univ_name(MED_LNAME_SIZE),_dt_unit(MED_LNAME_SIZE)
46 {
47 }
48
49 std::size_t MEDFileMeshL2::getHeapMemorySizeWithoutChildren() const
50 {
51   return 0;
52 }
53
54 std::vector<const BigMemoryObject *> MEDFileMeshL2::getDirectChildrenWithNull() const
55 {
56   return std::vector<const BigMemoryObject *>();
57 }
58
59 int MEDFileMeshL2::GetMeshIdFromName(med_idt fid, const std::string& mname, MEDCoupling::MEDCouplingMeshType& meshType, MEDCoupling::MEDCouplingAxisType& axType, int& dt, int& it, std::string& dtunit1)
60 {
61   med_mesh_type type_maillage;
62   char maillage_description[MED_COMMENT_SIZE+1];
63   char dtunit[MED_LNAME_SIZE+1];
64   med_int spaceDim,dim;
65   char nommaa[MED_NAME_SIZE+1];
66   med_int n=MEDnMesh(fid);
67   bool found=false;
68   int ret=-1;
69   med_sorting_type stype;
70   std::vector<std::string> ms;
71   int nstep;
72   med_axis_type axistype;
73   for(int i=0;i<n && !found;i++)
74     {
75       int naxis(MEDmeshnAxis(fid,i+1));
76       INTERP_KERNEL::AutoPtr<char> axisname=MEDLoaderBase::buildEmptyString(naxis*MED_SNAME_SIZE);
77       INTERP_KERNEL::AutoPtr<char> axisunit=MEDLoaderBase::buildEmptyString(naxis*MED_SNAME_SIZE);
78       MEDFILESAFECALLERRD0(MEDmeshInfo,(fid,i+1,nommaa,&spaceDim,&dim,&type_maillage,maillage_description,dtunit,&stype,&nstep,&axistype,axisname,axisunit));      
79       dtunit1=MEDLoaderBase::buildStringFromFortran(dtunit,sizeof(dtunit));
80       std::string cur=MEDLoaderBase::buildStringFromFortran(nommaa,sizeof(nommaa));
81       ms.push_back(cur);
82       if(cur==mname)
83         {
84           found=true;
85           ret=i+1;
86         }
87     }
88   if(!found)
89     {
90       std::ostringstream oss;
91       oss << "No such meshname (" << mname <<  ") in file ! Must be in : ";
92       std::copy(ms.begin(),ms.end(),std::ostream_iterator<std::string>(oss,", "));
93       throw INTERP_KERNEL::Exception(oss.str().c_str());
94     }
95   axType=TraduceAxisType(axistype);
96   switch(type_maillage)
97   {
98     case MED_UNSTRUCTURED_MESH:
99       meshType=UNSTRUCTURED;
100       break;
101     case MED_STRUCTURED_MESH:
102       {
103         med_grid_type gt;
104         MEDFILESAFECALLERRD0(MEDmeshGridTypeRd,(fid,mname.c_str(),&gt));
105         switch(gt)
106         {
107           case MED_CARTESIAN_GRID:
108             meshType=CARTESIAN;
109             break;
110           case MED_CURVILINEAR_GRID:
111             meshType=CURVE_LINEAR;
112             break;
113           case MED_POLAR_GRID:// this is not a bug. A MED file POLAR_GRID is deal by CARTESIAN MEDLoader
114             meshType=CARTESIAN;
115             break;
116           default:
117             throw INTERP_KERNEL::Exception("MEDFileMeshL2::getMeshIdFromName : unrecognized structured mesh type ! Supported are :\n - cartesian\n - curve linear\n");
118         }
119         break;
120       }
121     default:
122       throw INTERP_KERNEL::Exception("MEDFileMeshL2::getMeshIdFromName : unrecognized mesh type !");
123   }
124   med_int numdt,numit;
125   med_float dtt;
126   MEDFILESAFECALLERRD0(MEDmeshComputationStepInfo,(fid,mname.c_str(),1,&numdt,&numit,&dtt));
127   dt=numdt; it=numit;
128   return ret;
129 }
130
131 double MEDFileMeshL2::CheckMeshTimeStep(med_idt fid, const std::string& mName, int nstep, int dt, int it)
132 {
133   bool found=false;
134   med_int numdt,numit;
135   med_float dtt;
136   std::vector< std::pair<int,int> > p(nstep);
137   for(int i=0;i<nstep;i++)
138     {
139       MEDFILESAFECALLERRD0(MEDmeshComputationStepInfo,(fid,mName.c_str(),i+1,&numdt,&numit,&dtt));
140       p[i]=std::make_pair(numdt,numit);
141       found=(numdt==dt) && (numit==numit);
142     }
143   if(!found)
144     {
145       std::ostringstream oss; oss << "No such iteration=" << dt << ",order=" << it << " numbers found for mesh '" << mName << "' ! ";
146       oss << "Possibilities are : ";
147       for(int i=0;i<nstep;i++)
148         oss << "(" << p[i].first << "," << p[i].second << "), ";
149       throw INTERP_KERNEL::Exception(oss.str().c_str());
150     }
151   return dtt;
152 }
153
154 /*!
155  * non static and non const method because _description, _dt_unit... are set in this method.
156  */
157 std::vector<std::string> MEDFileMeshL2::getAxisInfoOnMesh(med_idt fid, int mId, const std::string& mName, MEDCoupling::MEDCouplingMeshType& meshType, MEDCoupling::MEDCouplingAxisType& axType, int& nstep, int& Mdim)
158 {
159   med_mesh_type type_maillage;
160   med_int spaceDim;
161   med_sorting_type stype;
162   med_axis_type axistype;
163   int naxis(MEDmeshnAxis(fid,mId));
164   INTERP_KERNEL::AutoPtr<char> nameTmp=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
165   INTERP_KERNEL::AutoPtr<char> axisname=MEDLoaderBase::buildEmptyString(naxis*MED_SNAME_SIZE);
166   INTERP_KERNEL::AutoPtr<char> axisunit=MEDLoaderBase::buildEmptyString(naxis*MED_SNAME_SIZE);
167   INTERP_KERNEL::AutoPtr<char> univTmp=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE);
168   if(MEDmeshInfo(fid,mId,nameTmp,&spaceDim,&Mdim,&type_maillage,_description.getPointer(),_dt_unit.getPointer(),
169       &stype,&nstep,&axistype,axisname,axisunit)!=0)
170     throw INTERP_KERNEL::Exception("A problem has been detected when trying to get info on mesh !");
171   MEDmeshUniversalNameRd(fid,nameTmp,_univ_name.getPointer());// do not protect  MEDFILESAFECALLERRD0 call : Thanks to fra.med.
172   axType=TraduceAxisType(axistype);
173   switch(type_maillage)
174   {
175     case MED_UNSTRUCTURED_MESH:
176       meshType=UNSTRUCTURED;
177       break;
178     case MED_STRUCTURED_MESH:
179       {
180         med_grid_type gt;
181         MEDFILESAFECALLERRD0(MEDmeshGridTypeRd,(fid,mName.c_str(),&gt));
182         switch(gt)
183         {
184           case MED_CARTESIAN_GRID:
185             meshType=CARTESIAN;
186             break;
187           case MED_CURVILINEAR_GRID:
188             meshType=CURVE_LINEAR;
189             break;
190         case MED_POLAR_GRID:// this is not a bug. A MED file POLAR_GRID is deal by CARTESIAN MEDLoader
191             meshType=CARTESIAN;
192             break;
193           default:
194             throw INTERP_KERNEL::Exception("MEDFileMeshL2::getAxisInfoOnMesh : unrecognized structured mesh type ! Supported are :\n - cartesian\n - curve linear\n");
195         }
196         break;
197       }
198     default:
199       throw INTERP_KERNEL::Exception("MEDFileMeshL2::getMeshIdFromName : unrecognized mesh type !");
200   }
201   //
202   std::vector<std::string> infosOnComp(naxis);
203   for(int i=0;i<naxis;i++)
204     {
205       std::string info=MEDLoaderBase::buildUnionUnit(((char *)axisname)+i*MED_SNAME_SIZE,MED_SNAME_SIZE,((char *)axisunit)+i*MED_SNAME_SIZE,MED_SNAME_SIZE);
206       infosOnComp[i]=info;
207     }
208   return infosOnComp;
209 }
210
211 void MEDFileMeshL2::ReadFamiliesAndGrps(med_idt fid, const std::string& meshName, std::map<std::string,int>& fams, std::map<std::string, std::vector<std::string> >& grps, MEDFileMeshReadSelector *mrs)
212 {
213   if(mrs && !(mrs->isCellFamilyFieldReading() || mrs->isNodeFamilyFieldReading()))
214     return ;
215   char nomfam[MED_NAME_SIZE+1];
216   med_int numfam;
217   int nfam=MEDnFamily(fid,meshName.c_str());
218   std::vector< std::pair<std::string,std::pair<int,std::vector<std::string> > > > crudeFams(nfam);
219   for(int i=0;i<nfam;i++)
220     {
221       int ngro=MEDnFamilyGroup(fid,meshName.c_str(),i+1);
222       med_int natt=MEDnFamily23Attribute(fid,meshName.c_str(),i+1);
223       INTERP_KERNEL::AutoPtr<med_int> attide=new med_int[natt];
224       INTERP_KERNEL::AutoPtr<med_int> attval=new med_int[natt];
225       INTERP_KERNEL::AutoPtr<char> attdes=new char[MED_COMMENT_SIZE*natt+1];
226       INTERP_KERNEL::AutoPtr<char> gro=new char[MED_LNAME_SIZE*ngro+1];
227       MEDfamily23Info(fid,meshName.c_str(),i+1,nomfam,attide,attval,attdes,&numfam,gro);
228       std::string famName(MEDLoaderBase::buildStringFromFortran(nomfam,MED_NAME_SIZE));
229       std::vector<std::string> grps(ngro);
230       for(int j=0;j<ngro;j++)
231         grps[j]=MEDLoaderBase::buildStringFromFortran(gro+j*MED_LNAME_SIZE,MED_LNAME_SIZE);
232       crudeFams[i]=std::pair<std::string,std::pair<int,std::vector<std::string> > >(famName,std::pair<int,std::vector<std::string> >(numfam,grps));
233     }
234   RenameFamiliesFromFileToMemInternal(crudeFams);
235   for(std::vector< std::pair<std::string,std::pair<int,std::vector<std::string> > > >::const_iterator it0=crudeFams.begin();it0!=crudeFams.end();it0++)
236     {
237       fams[(*it0).first]=(*it0).second.first;
238       for(std::vector<std::string>::const_iterator it1=(*it0).second.second.begin();it1!=(*it0).second.second.end();it1++)
239         grps[*it1].push_back((*it0).first);
240     }
241 }
242
243 void MEDFileMeshL2::WriteFamiliesAndGrps(med_idt fid, const std::string& mname, const std::map<std::string,int>& fams, const std::map<std::string, std::vector<std::string> >& grps, int tooLongStrPol)
244 {
245   std::vector< std::pair<std::string,std::pair<int,std::vector<std::string> > > > crudeFams(fams.size());
246   std::size_t ii(0);
247   for(std::map<std::string,int>::const_iterator it=fams.begin();it!=fams.end();it++,ii++)
248     {
249       std::vector<std::string> grpsOfFam;
250       for(std::map<std::string, std::vector<std::string> >::const_iterator it1=grps.begin();it1!=grps.end();it1++)
251         {
252           if(std::find((*it1).second.begin(),(*it1).second.end(),(*it).first)!=(*it1).second.end())
253             grpsOfFam.push_back((*it1).first);
254         }
255       crudeFams[ii]=std::pair<std::string,std::pair<int,std::vector<std::string> > >((*it).first,std::pair<int,std::vector<std::string> >((*it).second,grpsOfFam));
256     }
257   RenameFamiliesFromMemToFileInternal(crudeFams);
258   for(std::vector< std::pair<std::string,std::pair<int,std::vector<std::string> > > >::const_iterator it=crudeFams.begin();it!=crudeFams.end();it++)
259     {
260       int ngro((*it).second.second.size());
261       INTERP_KERNEL::AutoPtr<char> groName=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE*ngro);
262       int i=0;
263       for(std::vector<std::string>::const_iterator it2=(*it).second.second.begin();it2!=(*it).second.second.end();it2++,i++)
264         MEDLoaderBase::safeStrCpy2((*it2).c_str(),MED_LNAME_SIZE-1,groName+i*MED_LNAME_SIZE,tooLongStrPol);
265       INTERP_KERNEL::AutoPtr<char> famName=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
266       MEDLoaderBase::safeStrCpy((*it).first.c_str(),MED_NAME_SIZE,famName,tooLongStrPol);
267       int ret=MEDfamilyCr(fid,mname.c_str(),famName,(*it).second.first,ngro,groName);
268       ret++;
269     }
270 }
271
272 void MEDFileMeshL2::RenameFamiliesPatternInternal(std::vector< std::pair<std::string,std::pair<int,std::vector<std::string> > > >& crudeFams, RenameFamiliesPatternFunc func)
273 {
274   std::size_t ii(0);
275   std::vector<std::string> fams(crudeFams.size());
276   for(std::vector< std::pair<std::string,std::pair<int,std::vector<std::string> > > >::const_iterator it=crudeFams.begin();it!=crudeFams.end();it++,ii++)
277     fams[ii]=(*it).first;
278   if(!func(fams))
279     return ;
280   ii=0;
281   for(std::vector< std::pair<std::string,std::pair<int,std::vector<std::string> > > >::iterator it=crudeFams.begin();it!=crudeFams.end();it++,ii++)
282     (*it).first=fams[ii];
283 }
284
285 /*!
286  * This method is dedicated to the killers that use a same family name to store different family ids. MED file API authorizes it.
287  * So this method renames families (if needed generaly not !) in order to have a discriminant name for families.
288  */
289 void MEDFileMeshL2::RenameFamiliesFromFileToMemInternal(std::vector< std::pair<std::string,std::pair<int,std::vector<std::string> > > >& crudeFams)
290 {
291   RenameFamiliesPatternInternal(crudeFams,RenameFamiliesFromFileToMem);
292 }
293
294 bool MEDFileMeshL2::RenameFamiliesFromFileToMem(std::vector< std::string >& famNames)
295 {
296   std::map<std::string,int> m;
297   std::set<std::string> s;
298   for(std::vector< std::string >::const_iterator it=famNames.begin();it!=famNames.end();it++)
299     {
300       if(s.find(*it)!=s.end())
301         m[*it]=0;
302       s.insert(*it);
303     }
304   if(m.empty())
305     return false;// the general case !
306   for(std::vector< std::string >::iterator it=famNames.begin();it!=famNames.end();it++)
307     {
308       std::map<std::string,int>::iterator it2(m.find(*it));
309       if(it2!=m.end())
310         {
311           std::ostringstream oss; oss << *it << ZE_SEP_FOR_FAMILY_KILLERS << std::setfill('0') << std::setw(ZE_SEP2_FOR_FAMILY_KILLERS) << (*it2).second++;
312           *it=oss.str();
313         }
314     }
315   return true;
316 }
317
318 /*!
319  * This method is dedicated to the killers that use a same family name to store different family ids. MED file API authorizes it.
320  * So this method renames families (if needed generaly not !) in order to have a discriminant name for families.
321  */
322 void MEDFileMeshL2::RenameFamiliesFromMemToFileInternal(std::vector< std::pair<std::string,std::pair<int,std::vector<std::string> > > >& crudeFams)
323 {
324   RenameFamiliesPatternInternal(crudeFams,RenameFamiliesFromMemToFile);
325 }
326
327 bool MEDFileMeshL2::RenameFamiliesFromMemToFile(std::vector< std::string >& famNames)
328 {
329   bool isSmthingStrange(false);
330   for(std::vector< std::string >::const_iterator it=famNames.begin();it!=famNames.end();it++)
331     {
332       std::size_t found((*it).find(ZE_SEP_FOR_FAMILY_KILLERS));
333       if(found!=std::string::npos)
334         isSmthingStrange=true;
335     }
336   if(!isSmthingStrange)
337     return false;
338   // pattern matching
339   std::map< std::string, std::vector<std::string> > m;
340   for(std::vector< std::string >::const_iterator it=famNames.begin();it!=famNames.end();it++)
341     {
342       std::size_t found((*it).find(ZE_SEP_FOR_FAMILY_KILLERS));
343       if(found!=std::string::npos && found>=1)
344         {
345           std::string s1((*it).substr(found+sizeof(ZE_SEP_FOR_FAMILY_KILLERS)-1));
346           if(s1.size()!=ZE_SEP2_FOR_FAMILY_KILLERS)
347             continue;
348           int k(-1);
349           std::istringstream iss(s1);
350           iss >> k;
351           bool isOK((iss.rdstate() & ( std::istream::failbit | std::istream::eofbit)) == std::istream::eofbit);
352           if(isOK && k>=0)
353             {
354               std::string s0((*it).substr(0,found));
355               m[s0].push_back(*it);
356             }
357         }
358     }
359   if(m.empty())
360     return false;
361   // filtering
362   std::map<std::string,std::string> zeMap;
363   for(std::map< std::string, std::vector<std::string> >::const_iterator it=m.begin();it!=m.end();it++)
364     {
365       if((*it).second.size()==1)
366         continue;
367       for(std::vector<std::string>::const_iterator it1=(*it).second.begin();it1!=(*it).second.end();it1++)
368         zeMap[*it1]=(*it).first;
369     }
370   if(zeMap.empty())
371     return false;
372   // traduce
373   for(std::vector< std::string >::iterator it=famNames.begin();it!=famNames.end();it++)
374     {
375       std::map<std::string,std::string>::iterator it1(zeMap.find(*it));
376       if(it1!=zeMap.end())
377         *it=(*it1).second;
378     }    
379   return true;
380 }
381
382 MEDCoupling::MEDCouplingAxisType MEDFileMeshL2::TraduceAxisType(med_axis_type at)
383 {
384   switch(at)
385     {
386     case MED_CARTESIAN:
387       return AX_CART;
388     case MED_CYLINDRICAL:
389       return AX_CYL;
390     case MED_SPHERICAL:
391       return AX_SPHER;
392     case MED_UNDEF_AXIS_TYPE:
393       return AX_CART;
394     default:
395       throw INTERP_KERNEL::Exception("MEDFileMeshL2::TraduceAxisType : unrecognized axis type !");
396     }
397 }
398
399 MEDCoupling::MEDCouplingAxisType MEDFileMeshL2::TraduceAxisTypeStruct(med_grid_type gt)
400 {
401   switch(gt)
402     {
403     case MED_CARTESIAN_GRID:
404       return AX_CART;
405     case MED_POLAR_GRID:
406       return AX_CYL;
407     default:
408       throw INTERP_KERNEL::Exception("MEDFileMeshL2::TraduceAxisTypeStruct : only Cartesian and Cylindrical supported by MED file !");
409     }
410 }
411
412 med_axis_type MEDFileMeshL2::TraduceAxisTypeRev(MEDCoupling::MEDCouplingAxisType at)
413 {
414   switch(at)
415     {
416     case AX_CART:
417       return MED_CARTESIAN;
418     case AX_CYL:
419       return MED_CYLINDRICAL;
420     case AX_SPHER:
421       return MED_SPHERICAL;
422     default:
423       throw INTERP_KERNEL::Exception("MEDFileMeshL2::TraduceAxisTypeRev : unrecognized axis type !");
424     }
425 }
426
427 med_grid_type MEDFileMeshL2::TraduceAxisTypeRevStruct(MEDCoupling::MEDCouplingAxisType at)
428 {
429   switch(at)
430     {
431     case AX_CART:
432       return MED_CARTESIAN_GRID;
433     case AX_CYL:
434       return MED_POLAR_GRID;
435     case AX_SPHER:
436       return MED_POLAR_GRID;
437     default:
438       throw INTERP_KERNEL::Exception("MEDFileMeshL2::TraduceAxisTypeRevStruct : unrecognized axis type !");
439     }
440 }
441
442 MEDFileUMeshL2::MEDFileUMeshL2()
443 {
444 }
445
446 std::vector<std::string> MEDFileUMeshL2::loadCommonPart(med_idt fid, int mId, const std::string& mName, int dt, int it, int& Mdim)
447 {
448   Mdim=-3;
449   _name.set(mName.c_str());
450   int nstep;
451   MEDCoupling::MEDCouplingMeshType meshType;
452   MEDCoupling::MEDCouplingAxisType dummy3;
453   std::vector<std::string> ret(getAxisInfoOnMesh(fid,mId,mName.c_str(),meshType,dummy3,nstep,Mdim));
454   if(nstep==0)
455     {
456       Mdim=-4;
457       return std::vector<std::string>();
458     }
459   if(meshType!=UNSTRUCTURED)
460     throw INTERP_KERNEL::Exception("Invalid mesh type ! You are expected an unstructured one whereas in file it is not an unstructured !");
461   _time=CheckMeshTimeStep(fid,mName,nstep,dt,it);
462   _iteration=dt;
463   _order=it;
464   return ret;
465 }
466
467 void MEDFileUMeshL2::loadAll(med_idt fid, int mId, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
468 {
469   int Mdim;
470   std::vector<std::string> infosOnComp(loadCommonPart(fid,mId,mName,dt,it,Mdim));
471   if(Mdim==-4)
472     return ;
473   loadConnectivity(fid,Mdim,mName,dt,it,mrs);//to improve check (dt,it) coherency
474   loadCoords(fid,mId,infosOnComp,mName,dt,it);
475 }
476
477 void MEDFileUMeshL2::loadPart(med_idt fid, int mId, const std::string& mName, const std::vector<INTERP_KERNEL::NormalizedCellType>& types, const std::vector<int>& slicPerTyp, int dt, int it, MEDFileMeshReadSelector *mrs)
478 {
479   int Mdim;
480   std::vector<std::string> infosOnComp(loadCommonPart(fid,mId,mName,dt,it,Mdim));
481   if(Mdim==-4)
482     return ;
483   loadPartOfConnectivity(fid,Mdim,mName,types,slicPerTyp,dt,it,mrs);
484   med_bool changement,transformation;
485   int nCoords(MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_COORDINATE,MED_NO_CMODE,&changement,&transformation));
486   std::vector<bool> fetchedNodeIds(nCoords,false);
487   for(std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshPerType> > >::const_iterator it0=_per_type_mesh.begin();it0!=_per_type_mesh.end();it0++)
488     for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshPerType> >::const_iterator it1=(*it0).begin();it1!=(*it0).end();it1++)
489       (*it1)->getMesh()->computeNodeIdsAlg(fetchedNodeIds);
490   int nMin(std::distance(fetchedNodeIds.begin(),std::find(fetchedNodeIds.begin(),fetchedNodeIds.end(),true)));
491   int nMax(std::distance(fetchedNodeIds.rbegin(),std::find(fetchedNodeIds.rbegin(),fetchedNodeIds.rend(),true)));
492   nMax=nCoords-nMax;
493   for(std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshPerType> > >::const_iterator it0=_per_type_mesh.begin();it0!=_per_type_mesh.end();it0++)
494     for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshPerType> >::const_iterator it1=(*it0).begin();it1!=(*it0).end();it1++)
495       (*it1)->getMesh()->renumberNodesWithOffsetInConn(-nMin);
496   loadPartCoords(fid,mId,infosOnComp,mName,dt,it,nMin,nMax);
497 }
498
499 void MEDFileUMeshL2::loadConnectivity(med_idt fid, int mdim, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
500 {
501   _per_type_mesh.resize(1);
502   _per_type_mesh[0].clear();
503   for(int j=0;j<MED_N_CELL_FIXED_GEO;j++)
504     {
505       MEDFileUMeshPerType *tmp(MEDFileUMeshPerType::New(fid,mName.c_str(),dt,it,mdim,typmai[j],typmai2[j],mrs));
506       if(tmp)
507         _per_type_mesh[0].push_back(tmp);
508     }
509   sortTypes();
510 }
511
512 void MEDFileUMeshL2::loadPartOfConnectivity(med_idt fid, int mdim, const std::string& mName, const std::vector<INTERP_KERNEL::NormalizedCellType>& types, const std::vector<int>& slicPerTyp, int dt, int it, MEDFileMeshReadSelector *mrs)
513 {
514   std::size_t nbOfTypes(types.size());
515   if(slicPerTyp.size()!=3*nbOfTypes)
516     throw INTERP_KERNEL::Exception("MEDFileUMeshL2::loadPartOfConnectivity : The size of slicPerTyp array is expected to be equal to 3 times size of array types !");
517   std::set<INTERP_KERNEL::NormalizedCellType> types2(types.begin(),types.end());
518   if(types2.size()!=nbOfTypes)
519     throw INTERP_KERNEL::Exception("MEDFileUMeshL2::loadPartOfConnectivity : the geometric types in types array must appear once !");
520   _per_type_mesh.resize(1);
521   _per_type_mesh[0].clear();
522   for(std::size_t ii=0;ii<nbOfTypes;ii++)
523     {
524       int strt(slicPerTyp[3*ii+0]),stp(slicPerTyp[3*ii+1]),step(slicPerTyp[3*ii+2]);
525       MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshPerType> tmp(MEDFileUMeshPerType::NewPart(fid,mName.c_str(),dt,it,mdim,types[ii],strt,stp,step,mrs));
526       _per_type_mesh[0].push_back(tmp);
527     }
528   sortTypes();
529 }
530
531 void MEDFileUMeshL2::loadCoords(med_idt fid, int mId, const std::vector<std::string>& infosOnComp, const std::string& mName, int dt, int it)
532 {
533   int spaceDim((int)infosOnComp.size());
534   med_bool changement,transformation;
535   int nCoords(MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_COORDINATE,MED_NO_CMODE,&changement,&transformation));
536   _coords=DataArrayDouble::New();
537   _coords->alloc(nCoords,spaceDim);
538   double *coordsPtr(_coords->getPointer());
539   if (nCoords)
540     MEDFILESAFECALLERRD0(MEDmeshNodeCoordinateRd,(fid,mName.c_str(),dt,it,MED_FULL_INTERLACE,coordsPtr));
541   if(MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NO_GEOTYPE,MED_FAMILY_NUMBER,MED_NODAL,&changement,&transformation)>0)
542     {
543       _fam_coords=DataArrayInt::New();
544       _fam_coords->alloc(nCoords,1);
545       MEDFILESAFECALLERRD0(MEDmeshEntityFamilyNumberRd,(fid,mName.c_str(),dt,it,MED_NODE,MED_NO_GEOTYPE,_fam_coords->getPointer()));
546     }
547   else
548     _fam_coords=0;
549   if(MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NO_GEOTYPE,MED_NUMBER,MED_NODAL,&changement,&transformation)>0)
550     {
551       _num_coords=DataArrayInt::New();
552       _num_coords->alloc(nCoords,1);
553       MEDFILESAFECALLERRD0(MEDmeshEntityNumberRd,(fid,mName.c_str(),dt,it,MED_NODE,MED_NO_GEOTYPE,_num_coords->getPointer()));
554     }
555   else
556     _num_coords=0;
557   if(MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NO_GEOTYPE,MED_NAME,MED_NODAL,&changement,&transformation)>0)
558     {
559       _name_coords=DataArrayAsciiChar::New();
560       _name_coords->alloc(nCoords+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end
561       MEDFILESAFECALLERRD0(MEDmeshEntityNameRd,(fid,mName.c_str(),dt,it,MED_NODE,MED_NO_GEOTYPE,_name_coords->getPointer()));
562       _name_coords->reAlloc(nCoords);//not a bug to avoid the memory corruption due to last \0 at the end
563     }
564   else
565     _name_coords=0;
566   for(int i=0;i<spaceDim;i++)
567     _coords->setInfoOnComponent(i,infosOnComp[i]);
568 }
569
570 void MEDFileUMeshL2::loadPartCoords(med_idt fid, int mId, const std::vector<std::string>& infosOnComp, const std::string& mName, int dt, int it, int nMin, int nMax)
571 {
572   med_bool changement,transformation;
573   int spaceDim((int)infosOnComp.size()),nCoords(MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_COORDINATE,MED_NO_CMODE,&changement,&transformation));
574   _coords=DataArrayDouble::New();
575   int nbNodesToLoad(nMax-nMin);
576   _coords->alloc(nbNodesToLoad,spaceDim);
577   med_filter filter=MED_FILTER_INIT,filter2=MED_FILTER_INIT;
578   MEDfilterBlockOfEntityCr(fid,/*nentity*/nCoords,/*nvaluesperentity*/1,/*nconstituentpervalue*/spaceDim,
579                            MED_ALL_CONSTITUENT,MED_FULL_INTERLACE,MED_COMPACT_STMODE,MED_NO_PROFILE,
580                            /*start*/nMin+1,/*stride*/1,/*count*/1,/*blocksize*/nbNodesToLoad,
581                            /*lastblocksize=useless because count=1*/0,&filter);
582   MEDFILESAFECALLERRD0(MEDmeshNodeCoordinateAdvancedRd,(fid,mName.c_str(),dt,it,&filter,_coords->getPointer()));
583   _part_coords=PartDefinition::New(nMin,nMax,1);
584   MEDfilterClose(&filter);
585   MEDfilterBlockOfEntityCr(fid,nCoords,1,1,MED_ALL_CONSTITUENT,MED_FULL_INTERLACE,MED_COMPACT_STMODE,
586                            MED_NO_PROFILE,nMin+1,1,1,nbNodesToLoad,0,&filter2);
587   if(MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NO_GEOTYPE,MED_FAMILY_NUMBER,MED_NODAL,&changement,&transformation)>0)
588     {
589       _fam_coords=DataArrayInt::New();
590       _fam_coords->alloc(nbNodesToLoad,1);
591       MEDFILESAFECALLERRD0(MEDmeshEntityAttributeAdvancedRd,(fid,mName.c_str(),MED_FAMILY_NUMBER,dt,it,MED_NODE,MED_NO_GEOTYPE,&filter2,_fam_coords->getPointer()));
592     }
593   else
594     _fam_coords=0;
595   if(MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NO_GEOTYPE,MED_NUMBER,MED_NODAL,&changement,&transformation)>0)
596     {
597       _num_coords=DataArrayInt::New();
598       _num_coords->alloc(nbNodesToLoad,1);
599       MEDFILESAFECALLERRD0(MEDmeshEntityAttributeAdvancedRd,(fid,mName.c_str(),MED_NUMBER,dt,it,MED_NODE,MED_NO_GEOTYPE,&filter2,_num_coords->getPointer()));
600     }
601   else
602     _num_coords=0;
603   if(MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NO_GEOTYPE,MED_NAME,MED_NODAL,&changement,&transformation)>0)
604     {
605       _name_coords=DataArrayAsciiChar::New();
606       _name_coords->alloc(nbNodesToLoad+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end
607       MEDFILESAFECALLERRD0(MEDmeshEntityAttributeAdvancedRd,(fid,mName.c_str(),MED_NAME,dt,it,MED_NODE,MED_NO_GEOTYPE,&filter2,_name_coords->getPointer()));
608       _name_coords->reAlloc(nbNodesToLoad);//not a bug to avoid the memory corruption due to last \0 at the end
609     }
610   else
611     _name_coords=0;
612   MEDfilterClose(&filter2);
613   _coords->setInfoOnComponents(infosOnComp);
614 }
615
616 void MEDFileUMeshL2::sortTypes()
617 {
618   std::set<int> mdims;
619   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshPerType> > tmp(_per_type_mesh[0]);
620   _per_type_mesh.clear();
621   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshPerType> >::const_iterator it=tmp.begin();it!=tmp.end();it++)
622     mdims.insert((*it)->getDim());
623   if(mdims.empty())
624     return;
625   int mdim=*mdims.rbegin();
626   _per_type_mesh.resize(mdim+1);
627   for(int dim=mdim+1;dim!=0;dim--)
628     {
629       std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshPerType> >& elt=_per_type_mesh[mdim+1-dim];
630       for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshPerType> >::const_iterator it=tmp.begin();it!=tmp.end();it++)
631         if((*it)->getDim()==dim-1)
632           elt.push_back(*it);
633     }
634   // suppression of contiguous empty levels at the end of _per_type_mesh.
635   int nbOfUselessLev=0;
636   bool isFirst=true;
637   for(std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshPerType> > >::reverse_iterator it2=_per_type_mesh.rbegin();it2!=_per_type_mesh.rend();it2++)
638     {
639       if((*it2).empty() && isFirst)
640         {
641           nbOfUselessLev++;
642         }
643       else
644         isFirst=false;
645     }
646   _per_type_mesh.resize(_per_type_mesh.size()-nbOfUselessLev);
647 }
648
649 void MEDFileUMeshL2::WriteCoords(med_idt fid, const std::string& mname, int dt, int it, double time, const DataArrayDouble *coords, const DataArrayInt *famCoords, const DataArrayInt *numCoords, const DataArrayAsciiChar *nameCoords)
650 {
651   if(!coords)
652     return ;
653   MEDFILESAFECALLERWR0(MEDmeshNodeCoordinateWr,(fid,mname.c_str(),dt,it,time,MED_FULL_INTERLACE,coords->getNumberOfTuples(),coords->getConstPointer()));
654   if(famCoords)
655     MEDFILESAFECALLERWR0(MEDmeshEntityFamilyNumberWr,(fid,mname.c_str(),dt,it,MED_NODE,MED_NO_GEOTYPE,famCoords->getNumberOfTuples(),famCoords->getConstPointer()));
656   if(numCoords)
657     MEDFILESAFECALLERWR0(MEDmeshEntityNumberWr,(fid,mname.c_str(),dt,it,MED_NODE,MED_NO_GEOTYPE,numCoords->getNumberOfTuples(),numCoords->getConstPointer()));
658   if(nameCoords)
659     {
660       if(nameCoords->getNumberOfComponents()!=MED_SNAME_SIZE)
661         {
662           std::ostringstream oss; oss << " MEDFileUMeshL2::WriteCoords : expected a name field on nodes with number of components set to " << MED_SNAME_SIZE;
663           oss << " ! The array has " << nameCoords->getNumberOfComponents() << " components !";
664           throw INTERP_KERNEL::Exception(oss.str().c_str());
665         }
666       MEDFILESAFECALLERWR0(MEDmeshEntityNameWr,(fid,mname.c_str(),dt,it,MED_NODE,MED_NO_GEOTYPE,nameCoords->getNumberOfTuples(),nameCoords->getConstPointer()));
667     }
668 }
669
670 bool MEDFileUMeshL2::isFamDefinedOnLev(int levId) const
671 {
672   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshPerType> >::const_iterator it=_per_type_mesh[levId].begin();it!=_per_type_mesh[levId].end();it++)
673     if((*it)->getFam()==0)
674       return false;
675   return true;
676 }
677
678 bool MEDFileUMeshL2::isNumDefinedOnLev(int levId) const
679 {
680   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshPerType> >::const_iterator it=_per_type_mesh[levId].begin();it!=_per_type_mesh[levId].end();it++)
681     if((*it)->getNum()==0)
682       return false;
683   return true;
684 }
685
686 bool MEDFileUMeshL2::isNamesDefinedOnLev(int levId) const
687 {
688   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshPerType> >::const_iterator it=_per_type_mesh[levId].begin();it!=_per_type_mesh[levId].end();it++)
689     if((*it)->getNames()==0)
690       return false;
691   return true;
692 }
693
694 MEDFileCMeshL2::MEDFileCMeshL2():_ax_type(AX_CART)
695 {
696 }
697
698 void MEDFileCMeshL2::loadAll(med_idt fid, int mId, const std::string& mName, int dt, int it)
699 {
700   _name.set(mName.c_str());
701   int nstep;
702   int Mdim;
703   MEDCoupling::MEDCouplingMeshType meshType;
704   MEDCoupling::MEDCouplingAxisType dummy3;
705   std::vector<std::string> infosOnComp=getAxisInfoOnMesh(fid,mId,mName.c_str(),meshType,dummy3,nstep,Mdim);
706   if(meshType!=CARTESIAN)
707     throw INTERP_KERNEL::Exception("Invalid mesh type ! You are expected a structured one whereas in file it is not a structured !");
708   _time=CheckMeshTimeStep(fid,mName,nstep,dt,it);
709   _iteration=dt;
710   _order=it;
711   //
712   med_grid_type gridtype;
713   MEDFILESAFECALLERRD0(MEDmeshGridTypeRd,(fid,mName.c_str(),&gridtype));
714   if(gridtype!=MED_CARTESIAN_GRID && gridtype!=MED_POLAR_GRID)
715     throw INTERP_KERNEL::Exception("Invalid rectilinear mesh ! Only cartesian and polar are supported !");
716   _ax_type=TraduceAxisTypeStruct(gridtype);
717   _cmesh=MEDCouplingCMesh::New();
718   for(int i=0;i<Mdim;i++)
719     {
720       med_data_type dataTypeReq=GetDataTypeCorrespondingToSpaceId(i);
721       med_bool chgt=MED_FALSE,trsf=MED_FALSE;
722       int nbOfElt(MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,dataTypeReq,MED_NO_CMODE,&chgt,&trsf));
723       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> da=DataArrayDouble::New();
724       da->alloc(nbOfElt,1);
725       da->setInfoOnComponent(0,infosOnComp[i]);
726       MEDFILESAFECALLERRD0(MEDmeshGridIndexCoordinateRd,(fid,mName.c_str(),dt,it,i+1,da->getPointer()));
727       _cmesh->setCoordsAt(i,da);
728     }
729 }
730
731 med_data_type MEDFileCMeshL2::GetDataTypeCorrespondingToSpaceId(int id)
732 {
733   switch(id)
734   {
735     case 0:
736       return MED_COORDINATE_AXIS1;
737     case 1:
738       return MED_COORDINATE_AXIS2;
739     case 2:
740       return MED_COORDINATE_AXIS3;
741     default:
742       throw INTERP_KERNEL::Exception("Invalid meshdim detected in Cartesian Grid !");
743   }
744 }
745
746 MEDFileCLMeshL2::MEDFileCLMeshL2()
747 {
748 }
749
750 void MEDFileCLMeshL2::loadAll(med_idt fid, int mId, const std::string& mName, int dt, int it)
751 {
752   _name.set(mName.c_str());
753   int nstep;
754   int Mdim;
755   MEDCoupling::MEDCouplingMeshType meshType;
756   MEDCoupling::MEDCouplingAxisType dummy3;
757   std::vector<std::string> infosOnComp=getAxisInfoOnMesh(fid,mId,mName,meshType,dummy3,nstep,Mdim);
758   if(meshType!=CURVE_LINEAR)
759     throw INTERP_KERNEL::Exception("Invalid mesh type ! You are expected a structured one whereas in file it is not a structured !");
760   _time=CheckMeshTimeStep(fid,mName,nstep,dt,it);
761   _iteration=dt;
762   _order=it;
763   //
764   _clmesh=MEDCouplingCurveLinearMesh::New();
765   INTERP_KERNEL::AutoPtr<int> stGrid=new int[Mdim];
766   MEDFILESAFECALLERRD0(MEDmeshGridStructRd,(fid,mName.c_str(),dt,it,stGrid));
767   _clmesh->setNodeGridStructure(stGrid,((int *)stGrid)+Mdim);
768   med_bool chgt=MED_FALSE,trsf=MED_FALSE;
769   int nbNodes(MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_COORDINATE,MED_NO_CMODE,&chgt,&trsf));
770   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> da=DataArrayDouble::New();
771   da->alloc(nbNodes,infosOnComp.size());
772   da->setInfoOnComponents(infosOnComp);
773   MEDFILESAFECALLERRD0(MEDmeshNodeCoordinateRd,(fid,mName.c_str(),dt,it,MED_FULL_INTERLACE,da->getPointer()));
774   _clmesh->setCoords(da);
775 }
776
777 MEDFileUMeshPermCompute::MEDFileUMeshPermCompute(const MEDFileUMeshSplitL1* st):_st(st),_mpt_time(0),_num_time(0)
778 {
779 }
780
781 /*!
782  * Warning it returns an instance to deallocate !!!!
783  */
784 MEDFileUMeshPermCompute::operator MEDCouplingUMesh *() const
785 {
786   _st->_num->updateTime();
787   if((MEDCouplingUMesh *)_m==0)
788     {
789       updateTime();
790       _m=static_cast<MEDCouplingUMesh *>(_st->_m_by_types.getUmesh()->deepCpy());
791       _m->renumberCells(_st->_num->getConstPointer(),true);
792       return _m.retn();
793     }
794   else
795     {
796       if(_mpt_time==_st->_m_by_types.getTimeOfThis() && _num_time==_st->_num->getTimeOfThis())
797         return _m.retn();
798       else
799         {
800           updateTime();
801           _m=static_cast<MEDCouplingUMesh *>(_st->_m_by_types.getUmesh()->deepCpy());
802           _m->renumberCells(_st->_num->getConstPointer(),true);
803           return _m.retn();
804         }
805     }
806 }
807
808 void MEDFileUMeshPermCompute::operator=(MEDCouplingUMesh *m)
809 {
810   _m=m;
811 }
812
813 void MEDFileUMeshPermCompute::updateTime() const
814 {
815   _mpt_time=_st->_m_by_types.getTimeOfThis();
816   _num_time=_st->_num->getTimeOfThis();
817 }
818
819 std::vector<const BigMemoryObject *> MEDFileUMeshPermCompute::getDirectChildrenWithNull() const
820 {
821   std::vector<const BigMemoryObject *> ret;
822   ret.push_back((const MEDCouplingUMesh *)_m);
823   return ret;
824 }
825
826 std::size_t MEDFileUMeshPermCompute::getHeapMemorySizeWithoutChildren() const
827 {
828   return sizeof(MEDFileUMeshPermCompute);
829 }
830
831 MEDFileUMeshSplitL1::MEDFileUMeshSplitL1(const MEDFileUMeshSplitL1& other):RefCountObject(other),_m_by_types(other._m_by_types),_fam(other._fam),_num(other._num),_names(other._names),_rev_num(other._rev_num),_m(this)
832 {
833 }
834
835 MEDFileUMeshSplitL1::MEDFileUMeshSplitL1(const MEDFileUMeshL2& l2, const std::string& mName, int id):_m(this)
836 {
837   const std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshPerType> >& v=l2.getLev(id);
838   if(v.empty())
839     return;
840   int sz=v.size();
841   std::vector<const MEDCoupling1GTUMesh *> ms(sz);
842   std::vector<const DataArrayInt *> fams(sz),nums(sz);
843   std::vector<const DataArrayChar *> names(sz);
844   std::vector<const PartDefinition *> pds(sz);
845   for(int i=0;i<sz;i++)
846     {
847       MEDCoupling1GTUMesh *elt(v[i]->getMesh());
848       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=l2.getCoords();
849       elt->setCoords(tmp2);
850       ms[i]=elt;
851       pds[i]=v[i]->getPartDef();
852     }
853   _m_by_types.assignParts(ms);
854   _m_by_types.assignDefParts(pds);
855   if(l2.isFamDefinedOnLev(id))
856     {
857       for(int i=0;i<sz;i++)
858         fams[i]=v[i]->getFam();
859       if(sz!=1)
860         _fam=DataArrayInt::Aggregate(fams);
861       else
862         {
863           fams[0]->incrRef();
864           _fam=const_cast<DataArrayInt *>(fams[0]);
865         }
866     }
867   if(l2.isNumDefinedOnLev(id))
868     {
869       for(int i=0;i<sz;i++)
870         nums[i]=v[i]->getNum();
871       if(sz!=1)
872         _num=DataArrayInt::Aggregate(nums);
873       else
874         {
875           nums[0]->incrRef();
876           _num=const_cast<DataArrayInt *>(nums[0]);
877         }
878       computeRevNum();
879     }
880   if(l2.isNamesDefinedOnLev(id))
881     {
882       for(int i=0;i<sz;i++)
883         names[i]=v[i]->getNames();
884       _names=dynamic_cast<DataArrayAsciiChar *>(DataArrayChar::Aggregate(names));
885     }
886 }
887
888 MEDFileUMeshSplitL1::MEDFileUMeshSplitL1(MEDCoupling1GTUMesh *m):_m(this)
889 {
890   std::vector< const MEDCoupling1GTUMesh * > v(1);
891   v[0]=m;
892   assignParts(v);
893 }
894
895 MEDFileUMeshSplitL1::MEDFileUMeshSplitL1(MEDCouplingUMesh *m):_m(this)
896 {
897   assignMesh(m,true);
898 }
899
900 MEDFileUMeshSplitL1::MEDFileUMeshSplitL1(MEDCouplingUMesh *m, bool newOrOld):_m(this)
901 {
902   assignMesh(m,newOrOld);
903 }
904
905 void MEDFileUMeshSplitL1::setName(const std::string& name)
906 {
907   _m_by_types.setName(name);
908 }
909
910 std::size_t MEDFileUMeshSplitL1::getHeapMemorySizeWithoutChildren() const
911 {
912   return 0;
913 }
914
915 std::vector<const BigMemoryObject *> MEDFileUMeshSplitL1::getDirectChildrenWithNull() const
916 {
917   std::vector<const BigMemoryObject *> ret;
918   ret.push_back(&_m_by_types);
919   ret.push_back(&_m);
920   ret.push_back((const DataArrayInt*)_fam);
921   ret.push_back((const DataArrayInt*)_num);
922   ret.push_back((const DataArrayInt*)_rev_num);
923   ret.push_back((const DataArrayAsciiChar*)_names);
924   return ret;
925 }
926
927 MEDFileUMeshSplitL1 *MEDFileUMeshSplitL1::shallowCpyUsingCoords(DataArrayDouble *coords) const
928 {
929   MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> ret(new MEDFileUMeshSplitL1(*this));
930   ret->_m_by_types.shallowCpyMeshes();
931   ret->_m_by_types.setCoords(coords);
932   return ret.retn();
933 }
934
935 MEDFileUMeshSplitL1 *MEDFileUMeshSplitL1::deepCpy(DataArrayDouble *coords) const
936 {
937   MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> ret(new MEDFileUMeshSplitL1(*this));
938   ret->_m_by_types=_m_by_types.deepCpy(coords);
939   if((const DataArrayInt *)_fam)
940     ret->_fam=_fam->deepCpy();
941   if((const DataArrayInt *)_num)
942     ret->_num=_num->deepCpy();
943   if((const DataArrayInt *)_rev_num)
944     ret->_rev_num=_rev_num->deepCpy();
945   if((const DataArrayAsciiChar *)_names)
946     ret->_names=_names->deepCpy();
947   return ret.retn();
948 }
949
950 bool MEDFileUMeshSplitL1::isEqual(const MEDFileUMeshSplitL1 *other, double eps, std::string& what) const
951 {
952   if(!_m_by_types.isEqual(other->_m_by_types,eps,what))
953     return false;
954   const DataArrayInt *d1=_fam;
955   const DataArrayInt *d2=other->_fam;
956   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
957     {
958       what="Presence of family arr in one sublevel and not in other!";
959       return false;
960     }
961   if(d1)
962     if(!d1->isEqual(*d2))
963       {
964         what="family arr at a sublevel are not deeply equal !";
965         return false;
966       }
967   d1=_num;
968   d2=other->_num;
969   if((d1==0 && d2!=0) || (d1!=0 && d2==0))
970     {
971       what="Presence of cell numbering arr in one sublevel and not in other!";
972       return false;
973     }
974   if(d1)
975     if(!d1->isEqual(*d2))
976       {
977         what="Numbering cell arr at a sublevel are not deeply equal !";
978         return false;
979       }
980   const DataArrayAsciiChar *e1=_names;
981   const DataArrayAsciiChar *e2=other->_names;
982   if((e1==0 && e2!=0) || (e1!=0 && e2==0))
983     {
984       what="Presence of cell names arr in one sublevel and not in other!";
985       return false;
986     }
987   if(e1)
988     if(!e1->isEqual(*e2))
989       {
990         what="Name cell arr at a sublevel are not deeply equal !";
991         return false;
992       }
993   return true;
994 }
995
996 void MEDFileUMeshSplitL1::synchronizeTinyInfo(const MEDFileMesh& master) const
997 {
998   _m_by_types.synchronizeTinyInfo(master);
999 }
1000
1001 void MEDFileUMeshSplitL1::clearNonDiscrAttributes() const
1002 {
1003   _m_by_types.clearNonDiscrAttributes();
1004 }
1005
1006 void MEDFileUMeshSplitL1::ClearNonDiscrAttributes(const MEDCouplingMesh *tmp)
1007 {
1008   if(!tmp)
1009     return ;
1010   (const_cast<MEDCouplingMesh *>(tmp))->setName("");
1011   (const_cast<MEDCouplingMesh *>(tmp))->setDescription("");
1012   (const_cast<MEDCouplingMesh *>(tmp))->setTime(0.,-1,-1);
1013   (const_cast<MEDCouplingMesh *>(tmp))->setTimeUnit("");
1014 }
1015
1016 void MEDFileUMeshSplitL1::setCoords(DataArrayDouble *coords)
1017 {
1018   _m_by_types.setCoords(coords);
1019 }
1020
1021 void MEDFileUMeshSplitL1::assignMesh(MEDCouplingUMesh *m, bool newOrOld)
1022 {
1023   if(newOrOld)
1024     {
1025       m->incrRef();
1026       _m=m;
1027       _m_by_types.assignUMesh(dynamic_cast<MEDCouplingUMesh *>(m->deepCpy()));
1028       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=_m_by_types.getUmesh()->getRenumArrForConsecutiveCellTypesSpec(typmai2,typmai2+MED_N_CELL_FIXED_GEO);
1029       if(!da->isIdentity2(m->getNumberOfCells()))
1030         {
1031           _num=da->invertArrayO2N2N2O(m->getNumberOfCells());
1032           _m.updateTime();
1033           computeRevNum();
1034           _m_by_types.getUmesh()->renumberCells(da->getConstPointer(),false);
1035         }
1036     }
1037   else
1038     {
1039       if(!m->checkConsecutiveCellTypesAndOrder(typmai2,typmai2+MED_N_CELL_FIXED_GEO))
1040         throw INTERP_KERNEL::Exception("MEDFileUMeshSplitL1::assignMesh(): the mesh does not follow the MED file numbering convention! Invoke sortCellsInMEDFileFrmt() first!");
1041       m->incrRef();
1042       _m_by_types.assignUMesh(m);
1043     }
1044   assignCommonPart();
1045 }
1046
1047 void MEDFileUMeshSplitL1::forceComputationOfParts() const
1048 {
1049   _m_by_types.forceComputationOfPartsFromUMesh();
1050 }
1051
1052 void MEDFileUMeshSplitL1::assignParts(const std::vector< const MEDCoupling1GTUMesh * >& mParts)
1053 {
1054   _m_by_types.assignParts(mParts);
1055   assignCommonPart();
1056 }
1057
1058 MEDFileUMeshSplitL1::MEDFileUMeshSplitL1():_m(this)
1059 {
1060 }
1061
1062 void MEDFileUMeshSplitL1::assignCommonPart()
1063 {
1064   _fam=DataArrayInt::New();
1065   _fam->alloc(_m_by_types.getSize(),1);
1066   _fam->fillWithValue(0);
1067 }
1068
1069 bool MEDFileUMeshSplitL1::empty() const
1070 {
1071   return _m_by_types.empty();
1072 }
1073
1074 bool MEDFileUMeshSplitL1::presenceOfOneFams(const std::vector<int>& ids) const
1075 {
1076   const DataArrayInt *fam=_fam;
1077   if(!fam)
1078     return false;
1079   return fam->presenceOfValue(ids);
1080 }
1081
1082 int MEDFileUMeshSplitL1::getMeshDimension() const
1083 {
1084   return _m_by_types.getMeshDimension();
1085 }
1086
1087 void MEDFileUMeshSplitL1::simpleRepr(std::ostream& oss) const
1088 {
1089   std::vector<int> code=_m_by_types.getDistributionOfTypes();
1090   int nbOfTypes=code.size()/3;
1091   for(int i=0;i<nbOfTypes;i++)
1092     {
1093       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType) code[3*i];
1094       oss << "    - Number of cells with type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr() << " : " << code[3*i+1] << std::endl;
1095     }
1096 }
1097
1098 int MEDFileUMeshSplitL1::getSize() const
1099 {
1100   return _m_by_types.getSize();
1101 }
1102
1103 MEDCouplingUMesh *MEDFileUMeshSplitL1::getFamilyPart(const int *idsBg, const int *idsEnd, bool renum) const
1104 {
1105   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsToKeep=_fam->getIdsEqualList(idsBg,idsEnd);
1106   MEDCouplingUMesh *m=(MEDCouplingUMesh *)_m_by_types.getUmesh()->buildPartOfMySelf(eltsToKeep->getConstPointer(),eltsToKeep->getConstPointer()+eltsToKeep->getNumberOfTuples(),true);
1107   if(renum)
1108     return renumIfNeeded(m,eltsToKeep->getConstPointer());
1109   return m;
1110 }
1111
1112 DataArrayInt *MEDFileUMeshSplitL1::getFamilyPartArr(const int *idsBg, const int *idsEnd, bool renum) const
1113 {
1114   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=_fam->getIdsEqualList(idsBg,idsEnd);
1115   if(renum)
1116     return renumIfNeededArr(da);
1117   return da.retn();
1118 }
1119
1120 std::vector<INTERP_KERNEL::NormalizedCellType> MEDFileUMeshSplitL1::getGeoTypes() const
1121 {
1122   return _m_by_types.getGeoTypes();
1123 }
1124
1125 int MEDFileUMeshSplitL1::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType ct) const
1126 {
1127   return _m_by_types.getNumberOfCellsWithType(ct);
1128 }
1129
1130 MEDCouplingUMesh *MEDFileUMeshSplitL1::getWholeMesh(bool renum) const
1131 {
1132   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp;
1133   if(renum && ((const DataArrayInt *)_num))
1134     tmp=_m;
1135   else
1136     { tmp=_m_by_types.getUmesh(); if(tmp) tmp->incrRef(); }
1137   return tmp.retn();
1138 }
1139
1140 int MEDFileUMeshSplitL1::getNumberOfCells() const
1141 {
1142   return _m_by_types.getNumberOfCells();
1143 }
1144
1145 DataArrayInt *MEDFileUMeshSplitL1::extractFamilyFieldOnGeoType(INTERP_KERNEL::NormalizedCellType gt) const
1146 {
1147   const DataArrayInt *fam(_fam);
1148   if(!fam)
1149     return 0;
1150   int start(0),stop(0);
1151   _m_by_types.getStartStopOfGeoTypeWithoutComputation(gt,start,stop);
1152   return fam->selectByTupleId2(start,stop,1);
1153 }
1154
1155 DataArrayInt *MEDFileUMeshSplitL1::extractNumberFieldOnGeoType(INTERP_KERNEL::NormalizedCellType gt) const
1156 {
1157   const DataArrayInt *num(_num);
1158   if(!num)
1159     return 0;
1160   int start(0),stop(0);
1161   _m_by_types.getStartStopOfGeoTypeWithoutComputation(gt,start,stop);
1162   return num->selectByTupleId2(start,stop,1);
1163 }
1164
1165 DataArrayInt *MEDFileUMeshSplitL1::getOrCreateAndGetFamilyField()
1166 {
1167   if((DataArrayInt *)_fam)
1168     return _fam;
1169   int nbOfTuples=_m_by_types.getSize();
1170   _fam=DataArrayInt::New(); _fam->alloc(nbOfTuples,1); _fam->fillWithZero();
1171   return _fam;
1172 }
1173
1174 const DataArrayInt *MEDFileUMeshSplitL1::getFamilyField() const
1175 {
1176   return _fam;
1177 }
1178
1179 const DataArrayInt *MEDFileUMeshSplitL1::getNumberField() const
1180 {
1181   return _num;
1182 }
1183
1184 const DataArrayInt *MEDFileUMeshSplitL1::getRevNumberField() const
1185 {
1186   return _rev_num;
1187 }
1188
1189 const DataArrayAsciiChar *MEDFileUMeshSplitL1::getNameField() const
1190 {
1191   return _names;
1192 }
1193
1194 const PartDefinition *MEDFileUMeshSplitL1::getPartDef(INTERP_KERNEL::NormalizedCellType gt) const
1195 {
1196   return _m_by_types.getPartDefOfWithoutComputation(gt);
1197 }
1198
1199 void MEDFileUMeshSplitL1::eraseFamilyField()
1200 {
1201   _fam->fillWithZero();
1202 }
1203
1204 /*!
1205  * This method ignores _m and _m_by_types.
1206  */
1207 void MEDFileUMeshSplitL1::setGroupsFromScratch(const std::vector<const MEDCouplingUMesh *>& ms, std::map<std::string,int>& familyIds,
1208                                                std::map<std::string, std::vector<std::string> >& groups)
1209 {
1210   std::vector< DataArrayInt * > corr;
1211   _m=MEDCouplingUMesh::FuseUMeshesOnSameCoords(ms,0,corr);
1212   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > corrMSafe(corr.begin(),corr.end());
1213   std::vector< std::vector<int> > fidsOfGroups;
1214   std::vector< const DataArrayInt * > corr2(corr.begin(),corr.end());
1215   _fam=DataArrayInt::MakePartition(corr2,((MEDCouplingUMesh *)_m)->getNumberOfCells(),fidsOfGroups);
1216   int nbOfCells=((MEDCouplingUMesh *)_m)->getNumberOfCells();
1217   std::map<int,std::string> newfams;
1218   std::map<int,int> famIdTrad;
1219   TraduceFamilyNumber(fidsOfGroups,familyIds,famIdTrad,newfams);
1220   int *w=_fam->getPointer();
1221   for(int i=0;i<nbOfCells;i++,w++)
1222     *w=famIdTrad[*w];
1223 }
1224
1225 void MEDFileUMeshSplitL1::write(med_idt fid, const std::string& mName, int mdim) const
1226 {
1227   std::vector<MEDCoupling1GTUMesh *> ms(_m_by_types.getParts());
1228   int start=0;
1229   for(std::vector<MEDCoupling1GTUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
1230     {
1231       int nbCells=(*it)->getNumberOfCells();
1232       int end=start+nbCells;
1233       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fam,num;
1234       MEDCouplingAutoRefCountObjectPtr<DataArrayAsciiChar> names;
1235       if((const DataArrayInt *)_fam)
1236         fam=_fam->substr(start,end);
1237       if((const DataArrayInt *)_num)
1238         num=_num->substr(start,end);
1239       if((const DataArrayAsciiChar *)_names)
1240         names=static_cast<DataArrayAsciiChar *>(_names->substr(start,end));
1241       MEDFileUMeshPerType::Write(fid,mName,mdim,(*it),fam,num,names);
1242       start=end;
1243     }
1244 }
1245
1246 void MEDFileUMeshSplitL1::renumberNodesInConn(const int *newNodeNumbersO2N)
1247 {
1248   _m_by_types.renumberNodesInConnWithoutComputation(newNodeNumbersO2N);
1249 }
1250
1251 void MEDFileUMeshSplitL1::serialize(std::vector<int>& tinyInt, std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >& bigArraysI) const
1252 {
1253   bigArraysI.push_back(_fam);
1254   bigArraysI.push_back(_num);
1255   _m_by_types.serialize(tinyInt,bigArraysI);
1256 }
1257
1258 void MEDFileUMeshSplitL1::unserialize(const std::string& name, DataArrayDouble *coo, std::vector<int>& tinyInt, std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >& bigArraysI)
1259 {
1260   _fam=bigArraysI.back(); bigArraysI.pop_back();
1261   _num=bigArraysI.back(); bigArraysI.pop_back();
1262   _m_by_types.unserialize(name,coo,tinyInt,bigArraysI);
1263 }
1264
1265 void MEDFileUMeshSplitL1::changeFamilyIdArr(int oldId, int newId)
1266 {
1267   DataArrayInt *arr=_fam;
1268   if(arr)
1269     arr->changeValue(oldId,newId);
1270 }
1271
1272 void MEDFileUMeshSplitL1::setFamilyArr(DataArrayInt *famArr)
1273 {
1274   if(!famArr)
1275     {
1276       _fam=0;
1277       return ;
1278     }
1279   int sz(_m_by_types.getSize());
1280   famArr->checkNbOfTuplesAndComp(sz,1,"MEDFileUMeshSplitL1::setFamilyArr : Problem in size of Family arr ! ");
1281   famArr->incrRef();
1282   _fam=famArr;
1283 }
1284
1285 DataArrayInt *MEDFileUMeshSplitL1::getFamilyField()
1286 {
1287   return _fam;
1288 }
1289
1290 void MEDFileUMeshSplitL1::setRenumArr(DataArrayInt *renumArr)
1291 {
1292   if(!renumArr)
1293     {
1294       _num=0;
1295       _rev_num=0;
1296       return ;
1297     }
1298   int sz(_m_by_types.getSize());
1299   renumArr->checkNbOfTuplesAndComp(sz,1,"MEDFileUMeshSplitL1::setRenumArr : Problem in size of numbering arr ! ");
1300   renumArr->incrRef();
1301   _num=renumArr;
1302   computeRevNum();
1303 }
1304
1305 void MEDFileUMeshSplitL1::setNameArr(DataArrayAsciiChar *nameArr)
1306 {
1307   if(!nameArr)
1308     {
1309       _names=0;
1310       return ;
1311     }
1312   int sz(_m_by_types.getSize());
1313   nameArr->checkNbOfTuplesAndComp(sz,MED_SNAME_SIZE,"MEDFileUMeshSplitL1::setNameArr : Problem in size of name arr ! ");
1314   nameArr->incrRef();
1315   _names=nameArr;
1316 }
1317
1318 MEDCouplingUMesh *MEDFileUMeshSplitL1::Renumber2(const DataArrayInt *renum, MEDCouplingUMesh *m, const int *cellIds)
1319 {
1320   if(renum==0)
1321     return m;
1322   if(cellIds==0)
1323     m->renumberCells(renum->getConstPointer(),true);
1324   else
1325     {
1326       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> locnum=renum->selectByTupleId(cellIds,cellIds+m->getNumberOfCells());
1327       m->renumberCells(locnum->getConstPointer(),true);
1328     }
1329   return m;
1330 }
1331
1332 MEDFileUMeshSplitL1 *MEDFileUMeshSplitL1::Unserialize(const std::string& name, DataArrayDouble *coo, std::vector<int>& tinyInt, std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >& bigArraysI)
1333 {
1334   MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> ret(new MEDFileUMeshSplitL1);
1335   ret->unserialize(name,coo,tinyInt,bigArraysI);
1336   return ret.retn();
1337 }
1338
1339 MEDCouplingUMesh *MEDFileUMeshSplitL1::renumIfNeeded(MEDCouplingUMesh *m, const int *cellIds) const
1340 {
1341   return Renumber2(_num,m,cellIds);
1342 }
1343
1344 DataArrayInt *MEDFileUMeshSplitL1::Renumber(const DataArrayInt *renum, const DataArrayInt *da)
1345 {
1346   if((const DataArrayInt *)renum==0)
1347     {
1348       da->incrRef();
1349       return const_cast<DataArrayInt *>(da);
1350     }
1351   return renum->selectByTupleId(da->getConstPointer(),da->getConstPointer()+da->getNumberOfTuples());
1352 }
1353
1354 DataArrayInt *MEDFileUMeshSplitL1::renumIfNeededArr(const DataArrayInt *da) const
1355 {
1356   return Renumber(_num,da);
1357 }
1358
1359 std::vector<int> MEDFileUMeshSplitL1::GetNewFamiliesNumber(int nb, const std::map<std::string,int>& families)
1360 {
1361   int id=-1;
1362   for(std::map<std::string,int>::const_iterator it=families.begin();it!=families.end();it++)
1363     id=std::max(id,(*it).second);
1364   if(id==-1)
1365     id=0;
1366   std::vector<int> ret(nb);
1367   for(int i=1;i<=nb;i++)
1368     ret[i]=id+i;
1369   return ret;
1370 }
1371
1372 void MEDFileUMeshSplitL1::TraduceFamilyNumber(const std::vector< std::vector<int> >& fidsGrps, std::map<std::string,int>& familyIds,
1373                                               std::map<int,int>& famIdTrad, std::map<int,std::string>& newfams)
1374 {
1375   std::set<int> allfids;
1376   //tony
1377 }
1378
1379 void MEDFileUMeshSplitL1::computeRevNum() const
1380 {
1381   int pos;
1382   int maxValue=_num->getMaxValue(pos);
1383   _rev_num=_num->invertArrayN2O2O2N(maxValue+1);
1384 }
1385
1386 //=
1387
1388 MEDFileUMeshAggregateCompute::MEDFileUMeshAggregateCompute():_mp_time(0),_m_time(0)
1389 {
1390 }
1391
1392 void MEDFileUMeshAggregateCompute::setName(const std::string& name)
1393 {
1394   if(_m_time>=_mp_time)
1395     {
1396       MEDCouplingUMesh *um(_m);
1397       if(um)
1398         um->setName(name);
1399     }
1400   if(_mp_time>=_m_time)
1401     {
1402       for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> >::iterator it=_m_parts.begin();it!=_m_parts.end();it++)
1403         {
1404           MEDCoupling1GTUMesh *tmp(*it);
1405           if(tmp)
1406             tmp->setName(name);
1407         }
1408     }
1409 }
1410
1411 void MEDFileUMeshAggregateCompute::assignParts(const std::vector< const MEDCoupling1GTUMesh * >& mParts)
1412 {
1413   std::size_t sz(mParts.size());
1414   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> > ret(sz);
1415   for(std::size_t i=0;i<sz;i++)
1416     {
1417       const MEDCoupling1GTUMesh *elt(mParts[i]);
1418       if(!elt)
1419         throw INTERP_KERNEL::Exception("MEDFileUMeshAggregateCompute::assignParts : presence of null pointer !");
1420       ret[i]=const_cast<MEDCoupling1GTUMesh *>(elt); elt->incrRef();
1421     }
1422   _m_parts=ret;
1423   _part_def.clear(); _part_def.resize(sz);
1424   _mp_time=std::max(_mp_time,_m_time)+1;
1425   _m=0;
1426 }
1427
1428 void MEDFileUMeshAggregateCompute::assignDefParts(const std::vector<const PartDefinition *>& partDefs)
1429 {
1430   if(_mp_time<_m_time)
1431     throw INTERP_KERNEL::Exception("MEDFileUMeshAggregateCompute::assignDefParts : the parts require a computation !");
1432   std::size_t sz(partDefs.size());
1433   if(_part_def.size()!=partDefs.size() || _part_def.size()!=_m_parts.size())
1434     throw INTERP_KERNEL::Exception("MEDFileUMeshAggregateCompute::assignDefParts : sizes of vectors of part definition mismatch !");
1435   for(std::size_t i=0;i<sz;i++)
1436     {
1437       const PartDefinition *elt(partDefs[i]);
1438       if(elt)
1439         elt->incrRef();
1440       _part_def[i]=const_cast<PartDefinition*>(elt);
1441     }
1442 }
1443
1444 void MEDFileUMeshAggregateCompute::assignUMesh(MEDCouplingUMesh *m)
1445 {
1446   _m=m;
1447   _m_parts.clear();
1448   _m_time=std::max(_mp_time,_m_time)+1;
1449 }
1450
1451 MEDCouplingUMesh *MEDFileUMeshAggregateCompute::getUmesh() const
1452 {
1453   if(_mp_time<=_m_time)
1454     return _m;
1455   std::vector< const MEDCoupling1GTUMesh *> mp(_m_parts.size());
1456   std::copy(_m_parts.begin(),_m_parts.end(),mp.begin());
1457   _m=MEDCoupling1GTUMesh::AggregateOnSameCoordsToUMesh(mp);
1458   _m_parts.clear();//to avoid memory peak !
1459   _m_time=_mp_time+1;//+1 is important ! That is to say that only _m is OK not _m_parts because cleared !
1460   return _m;
1461 }
1462
1463 int MEDFileUMeshAggregateCompute::getNumberOfCells() const
1464 {
1465   if(_mp_time<=_m_time)
1466     return _m->getNumberOfCells();
1467   int ret(0);
1468   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> >::const_iterator it=_m_parts.begin();it!=_m_parts.end();it++)
1469     ret+=(*it)->getNumberOfCells();
1470   return ret;
1471 }
1472
1473 std::vector<INTERP_KERNEL::NormalizedCellType> MEDFileUMeshAggregateCompute::getGeoTypes() const
1474 {
1475   if(_mp_time>=_m_time)
1476     {
1477       std::size_t sz(_m_parts.size());
1478       std::vector<INTERP_KERNEL::NormalizedCellType> ret(sz);
1479       for(std::size_t i=0;i<sz;i++)
1480         ret[i]=_m_parts[i]->getCellModelEnum();
1481       return ret;
1482     }
1483   else
1484     return _m->getAllGeoTypesSorted();
1485 }
1486
1487 int MEDFileUMeshAggregateCompute::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType ct) const
1488 {
1489   if(_mp_time>=_m_time)
1490     {
1491       for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> >::const_iterator it=_m_parts.begin();it!=_m_parts.end();it++)
1492         {
1493           const MEDCoupling1GTUMesh *elt(*it);
1494           if(elt && elt->getCellModelEnum()==ct)
1495             return elt->getNumberOfCells();
1496         }
1497       return 0;
1498     }
1499   else
1500     return _m->getNumberOfCellsWithType(ct);
1501 }
1502
1503 std::vector<MEDCoupling1GTUMesh *> MEDFileUMeshAggregateCompute::retrievePartsWithoutComputation() const
1504 {
1505   if(_mp_time<_m_time)
1506     throw INTERP_KERNEL::Exception("MEDFileUMeshAggregateCompute::getPartsWithoutComputation : the parts require a computation !");
1507   //
1508   std::vector<MEDCoupling1GTUMesh *> ret(_m_parts.size());
1509   std::size_t i(0);
1510   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> >::const_iterator it=_m_parts.begin();it!=_m_parts.end();it++,i++)
1511     {
1512       const MEDCoupling1GTUMesh *elt(*it);
1513       ret[i]=const_cast<MEDCoupling1GTUMesh *>(elt);
1514     }
1515   return ret;
1516 }
1517
1518 std::vector<MEDCoupling1GTUMesh *> MEDFileUMeshAggregateCompute::getParts() const
1519 {
1520   if(_mp_time<_m_time)
1521     forceComputationOfPartsFromUMesh();
1522   return retrievePartsWithoutComputation();
1523 }
1524
1525 MEDCoupling1GTUMesh *MEDFileUMeshAggregateCompute::retrievePartWithoutComputation(INTERP_KERNEL::NormalizedCellType gt) const
1526 {
1527   std::vector<MEDCoupling1GTUMesh *> v(retrievePartsWithoutComputation());
1528   std::size_t sz(v.size());
1529   for(std::size_t i=0;i<sz;i++)
1530     {
1531       if(v[i])
1532         if(v[i]->getCellModelEnum()==gt)
1533           return v[i];
1534     }
1535   throw INTERP_KERNEL::Exception("MEDFileUMeshAggregateCompute::getPartWithoutComputation : the geometric type is not existing !");
1536 }
1537
1538 void MEDFileUMeshAggregateCompute::getStartStopOfGeoTypeWithoutComputation(INTERP_KERNEL::NormalizedCellType gt, int& start, int& stop) const
1539 {
1540   start=0; stop=0;
1541   std::vector<MEDCoupling1GTUMesh *> v(retrievePartsWithoutComputation());
1542   std::size_t sz(v.size());
1543   for(std::size_t i=0;i<sz;i++)
1544     {
1545       if(v[i])
1546         {
1547           if(v[i]->getCellModelEnum()==gt)
1548             {
1549               stop=start+v[i]->getNumberOfCells();
1550               return;
1551             }
1552           else
1553             start+=v[i]->getNumberOfCells();
1554         }
1555     }
1556   throw INTERP_KERNEL::Exception("MEDFileUMeshAggregateCompute::getStartStopOfGeoTypeWithoutComputation : the geometric type is not existing !");
1557 }
1558
1559 void MEDFileUMeshAggregateCompute::renumberNodesInConnWithoutComputation(const int *newNodeNumbersO2N)
1560 {
1561   if(_mp_time>_m_time)
1562     {
1563       for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> >::iterator it=_m_parts.begin();it!=_m_parts.end();it++)
1564         {
1565           MEDCoupling1GTUMesh *m(*it);
1566           if(m)
1567             m->renumberNodesInConn(newNodeNumbersO2N);
1568         }
1569     }
1570   else
1571     {
1572       MEDCouplingUMesh *m(getUmesh());
1573       if(!m)
1574         return;
1575       m->renumberNodesInConn(newNodeNumbersO2N);
1576     }
1577 }
1578
1579 void MEDFileUMeshAggregateCompute::forceComputationOfPartsFromUMesh() const
1580 {
1581   const MEDCouplingUMesh *m(_m);
1582   if(!m)
1583     {
1584       if(_m_parts.empty())
1585         throw INTERP_KERNEL::Exception("MEDFileUMeshAggregateCompute::forceComputationOfPartsFromUMesh : null UMesh !");
1586       else
1587         return ;// no needs to compte parts they are already here !
1588     }
1589   std::vector<MEDCouplingUMesh *> ms(m->splitByType());
1590   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > msMSafe(ms.begin(),ms.end());
1591   std::size_t sz(msMSafe.size());
1592   _m_parts.resize(sz);
1593   for(std::size_t i=0;i<sz;i++)
1594     _m_parts[i]=MEDCoupling1GTUMesh::New(ms[i]);
1595   _part_def.clear();
1596   _part_def.resize(_m_parts.size());
1597   _mp_time=std::max(_mp_time,_m_time);
1598 }
1599
1600 const PartDefinition *MEDFileUMeshAggregateCompute::getPartDefOfWithoutComputation(INTERP_KERNEL::NormalizedCellType gt) const
1601 {
1602   if(_mp_time<_m_time)
1603     throw INTERP_KERNEL::Exception("MEDFileUMeshAggregateCompute::getPartDefOfWithoutComputation : the parts require a computation !");
1604   if(_m_parts.size()!=_part_def.size())
1605     throw INTERP_KERNEL::Exception("MEDFileUMeshAggregateCompute::getPartDefOfWithoutComputation : size of arrays are expected to be the same !");
1606   std::size_t sz(_m_parts.size());
1607   for(std::size_t i=0;i<sz;i++)
1608     {
1609       const MEDCoupling1GTUMesh *mesh(_m_parts[i]);
1610       if(mesh)
1611         if(mesh->getCellModelEnum()==gt)
1612           return _part_def[i];
1613     }
1614   throw INTERP_KERNEL::Exception("MEDFileUMeshAggregateCompute::getPartDefOfWithoutComputation : The input geo type is not existing in this !");
1615 }
1616
1617 void MEDFileUMeshAggregateCompute::serialize(std::vector<int>& tinyInt, std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >& bigArraysI) const
1618 {
1619   if(_mp_time<_m_time)
1620     throw INTERP_KERNEL::Exception("MEDFileUMeshAggregateCompute::serialize : the parts require a computation !");
1621   std::size_t sz(_m_parts.size());
1622   tinyInt.push_back((int)sz);
1623   for(std::size_t i=0;i<sz;i++)
1624     {
1625       const MEDCoupling1GTUMesh *mesh(_m_parts[i]);
1626       if(!mesh)
1627         throw INTERP_KERNEL::Exception("MEDFileUMeshAggregateCompute::serialize : one part is empty !");
1628       tinyInt.push_back(mesh->getCellModelEnum());
1629       const MEDCoupling1SGTUMesh *mesh1(dynamic_cast<const MEDCoupling1SGTUMesh *>(mesh));
1630       const MEDCoupling1DGTUMesh *mesh2(dynamic_cast<const MEDCoupling1DGTUMesh *>(mesh));
1631       if(mesh1)
1632         {
1633           DataArrayInt *elt(mesh1->getNodalConnectivity());
1634           if(elt)
1635             elt->incrRef();
1636           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elt1(elt);
1637           bigArraysI.push_back(elt1);
1638         }
1639       else if(mesh2)
1640         {
1641           DataArrayInt *elt1(mesh2->getNodalConnectivity()),*elt2(mesh2->getNodalConnectivityIndex());
1642           if(elt1)
1643             elt1->incrRef();
1644           if(elt2)
1645             elt2->incrRef();
1646           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elt11(elt1),elt22(elt2);
1647           bigArraysI.push_back(elt11); bigArraysI.push_back(elt22);
1648         }
1649       else
1650         throw INTERP_KERNEL::Exception("MEDFileUMeshAggregateCompute::serialize : unrecognized single geo type mesh !");
1651       const PartDefinition *pd(_part_def[i]);
1652       if(!pd)
1653         tinyInt.push_back(-1);
1654       else
1655         {
1656           std::vector<int> tinyTmp;
1657           pd->serialize(tinyTmp,bigArraysI);
1658           tinyInt.push_back((int)tinyTmp.size());
1659           tinyInt.insert(tinyInt.end(),tinyTmp.begin(),tinyTmp.end());
1660         }
1661     }
1662 }
1663
1664 void MEDFileUMeshAggregateCompute::unserialize(const std::string& name, DataArrayDouble *coo, std::vector<int>& tinyInt, std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >& bigArraysI)
1665 {
1666   int nbParts(tinyInt.back()); tinyInt.pop_back();
1667   _part_def.clear(); _part_def.resize(nbParts);
1668   _m_parts.clear(); _m_parts.resize(nbParts);
1669   for(int i=0;i<nbParts;i++)
1670     {
1671       INTERP_KERNEL::NormalizedCellType tp((INTERP_KERNEL::NormalizedCellType) tinyInt.back()); tinyInt.pop_back();
1672       MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> mesh(MEDCoupling1GTUMesh::New(name,tp));
1673       mesh->setCoords(coo);
1674       MEDCoupling1SGTUMesh *mesh1(dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh *) mesh));
1675       MEDCoupling1DGTUMesh *mesh2(dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh *) mesh));
1676       if(mesh1)
1677         {
1678           mesh1->setNodalConnectivity(bigArraysI.back()); bigArraysI.pop_back();
1679         }
1680       else if(mesh2)
1681         {
1682           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elt0,elt1;
1683           elt0=bigArraysI.back(); bigArraysI.pop_back();
1684           elt1=bigArraysI.back(); bigArraysI.pop_back();
1685           mesh2->setNodalConnectivity(elt0,elt1);
1686         }
1687       else
1688         throw INTERP_KERNEL::Exception("MEDFileUMeshAggregateCompute::unserialize : unrecognized single geo type mesh !");
1689       _m_parts[i]=mesh;
1690       int pdid(tinyInt.back()); tinyInt.pop_back();
1691       if(pdid!=-1)
1692         _part_def[i]=PartDefinition::Unserialize(tinyInt,bigArraysI);
1693       _mp_time=std::max(_mp_time,_m_time)+1;
1694     }
1695 }
1696
1697 /*!
1698  * This method returns true if \a this is stored split by type false if stored in a merged unstructured mesh.
1699  */
1700 bool MEDFileUMeshAggregateCompute::isStoredSplitByType() const
1701 {
1702   return _mp_time>=_m_time;
1703 }
1704
1705 std::size_t MEDFileUMeshAggregateCompute::getTimeOfThis() const
1706 {
1707   if(_mp_time>_m_time)
1708     return getTimeOfParts();
1709   if(_m_time>_mp_time)
1710     return getTimeOfUMesh();
1711   return std::max(getTimeOfParts(),getTimeOfUMesh());
1712 }
1713
1714 std::size_t MEDFileUMeshAggregateCompute::getTimeOfParts() const
1715 {
1716   std::size_t ret(0);
1717   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> >::const_iterator it=_m_parts.begin();it!=_m_parts.end();it++)
1718     {
1719       const MEDCoupling1GTUMesh *elt(*it);
1720       if(!elt)
1721         throw INTERP_KERNEL::Exception("MEDFileUMeshAggregateCompute::getTimeOfParts : null obj in parts !");
1722       ret=std::max(ret,elt->getTimeOfThis());
1723     }
1724   if(ret==0)
1725     throw INTERP_KERNEL::Exception("MEDFileUMeshAggregateCompute::getTimeOfParts : parts is empty !");
1726   return ret;
1727 }
1728
1729 std::size_t MEDFileUMeshAggregateCompute::getTimeOfUMesh() const
1730 {
1731   const MEDCouplingUMesh *m(_m);
1732   if(!m)
1733     throw INTERP_KERNEL::Exception("MEDFileUMeshAggregateCompute::getTimeOfUMesh : unmesh is null !");
1734   return m->getTimeOfThis();
1735 }
1736
1737 std::size_t MEDFileUMeshAggregateCompute::getHeapMemorySizeWithoutChildren() const
1738 {
1739   std::size_t ret(_m_parts.size()*sizeof(MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh>));
1740   return ret;
1741 }
1742
1743 std::vector<const BigMemoryObject *> MEDFileUMeshAggregateCompute::getDirectChildrenWithNull() const
1744 {
1745   std::vector<const BigMemoryObject *> ret;
1746   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> >::const_iterator it=_m_parts.begin();it!=_m_parts.end();it++)
1747     ret.push_back((const MEDCoupling1GTUMesh *)*it);
1748   ret.push_back((const MEDCouplingUMesh *)_m);
1749   return ret;
1750 }
1751
1752 MEDFileUMeshAggregateCompute MEDFileUMeshAggregateCompute::deepCpy(DataArrayDouble *coords) const
1753 {
1754   MEDFileUMeshAggregateCompute ret;
1755   ret._m_parts.resize(_m_parts.size());
1756   for(std::size_t i=0;i<_m_parts.size();i++)
1757     {
1758       const MEDCoupling1GTUMesh *elt(_m_parts[i]);
1759       if(elt)
1760         {
1761           ret._m_parts[i]=static_cast<MEDCoupling::MEDCoupling1GTUMesh*>(elt->deepCpy());
1762           ret._m_parts[i]->setCoords(coords);
1763         }
1764     }
1765   ret._mp_time=_mp_time; ret._m_time=_m_time;
1766   if((const MEDCouplingUMesh *)_m)
1767     {
1768       ret._m=static_cast<MEDCoupling::MEDCouplingUMesh*>(_m->deepCpy());
1769       ret._m->setCoords(coords);
1770     }
1771   std::size_t sz(_part_def.size());
1772   ret._part_def.clear(); ret._part_def.resize(sz);
1773   for(std::size_t i=0;i<sz;i++)
1774     {
1775       const PartDefinition *elt(_part_def[i]);
1776       if(elt)
1777         ret._part_def[i]=elt->deepCpy();
1778     }
1779   return ret;
1780 }
1781
1782 void MEDFileUMeshAggregateCompute::shallowCpyMeshes()
1783 {
1784   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> >::iterator it=_m_parts.begin();it!=_m_parts.end();it++)
1785     {
1786       const MEDCoupling1GTUMesh *elt(*it);
1787       if(elt)
1788         {
1789           MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> elt2(elt->clone(false));
1790           *it=DynamicCastSafe<MEDCouplingMesh,MEDCoupling1GTUMesh>(elt2);
1791         }
1792     }
1793   const MEDCouplingUMesh *m(_m);
1794   if(m)
1795     _m=m->clone(false);
1796 }
1797
1798 bool MEDFileUMeshAggregateCompute::isEqual(const MEDFileUMeshAggregateCompute& other, double eps, std::string& what) const
1799 {
1800   const MEDCouplingUMesh *m1(getUmesh());
1801   const MEDCouplingUMesh *m2(other.getUmesh());
1802   if((m1==0 && m2!=0) || (m1!=0 && m2==0))
1803     {
1804       what="Presence of mesh in one sublevel and not in other!";
1805       return false;
1806     }
1807   if(m1)
1808     {
1809       std::string what2;
1810       if(!m1->isEqualIfNotWhy(m2,eps,what2))
1811         {
1812           what=std::string("meshes at a sublevel are not deeply equal (")+what2+std::string(")!");
1813           return false;
1814         }
1815     }
1816   std::size_t sz(_part_def.size());
1817   if(sz!=other._part_def.size())
1818     {
1819       what=std::string("number of subdivision per geo type for part definition is not the same !");
1820       return false;
1821     }
1822   for(std::size_t i=0;i<sz;i++)
1823     {
1824       const PartDefinition *pd0(_part_def[i]),*pd1(other._part_def[i]);
1825       if(!pd0 && !pd1)
1826         continue;
1827       if((!pd0 && pd1) || (pd0 && !pd1))
1828         {
1829           what=std::string("a cell part def is defined only for one among this or other !");
1830           return false;
1831         }
1832       bool ret(pd0->isEqual(pd1,what));
1833       if(!ret)
1834         return false;
1835     }
1836   return true;
1837 }
1838
1839 void MEDFileUMeshAggregateCompute::clearNonDiscrAttributes() const
1840 {
1841   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> >::const_iterator it=_m_parts.begin();it!=_m_parts.end();it++)
1842     MEDFileUMeshSplitL1::ClearNonDiscrAttributes(*it);
1843   MEDFileUMeshSplitL1::ClearNonDiscrAttributes(_m);
1844 }
1845
1846 void MEDFileUMeshAggregateCompute::synchronizeTinyInfo(const MEDFileMesh& master) const
1847 {
1848   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> >::const_iterator it=_m_parts.begin();it!=_m_parts.end();it++)
1849     {
1850       const MEDCoupling1GTUMesh *tmp(*it);
1851       if(tmp)
1852         {
1853           (const_cast<MEDCoupling1GTUMesh *>(tmp))->setName(master.getName().c_str());
1854           (const_cast<MEDCoupling1GTUMesh *>(tmp))->setDescription(master.getDescription().c_str());
1855           (const_cast<MEDCoupling1GTUMesh *>(tmp))->setTime(master.getTimeValue(),master.getIteration(),master.getOrder());
1856           (const_cast<MEDCoupling1GTUMesh *>(tmp))->setTimeUnit(master.getTimeUnit());
1857         }
1858     }
1859   const MEDCouplingUMesh *m(_m);
1860   if(m)
1861     {
1862       (const_cast<MEDCouplingUMesh *>(m))->setName(master.getName().c_str());
1863       (const_cast<MEDCouplingUMesh *>(m))->setDescription(master.getDescription().c_str());
1864       (const_cast<MEDCouplingUMesh *>(m))->setTime(master.getTimeValue(),master.getIteration(),master.getOrder());
1865       (const_cast<MEDCouplingUMesh *>(m))->setTimeUnit(master.getTimeUnit());
1866     }
1867 }
1868
1869 bool MEDFileUMeshAggregateCompute::empty() const
1870 {
1871   if(_mp_time<_m_time)
1872     return ((const MEDCouplingUMesh *)_m)==0;
1873   //else _mp_time>=_m_time)
1874   return _m_parts.empty();
1875 }
1876
1877 int MEDFileUMeshAggregateCompute::getMeshDimension() const
1878 {
1879   if(_mp_time<_m_time)
1880     {
1881       const MEDCouplingUMesh *m(_m);
1882       if(!m)
1883         throw INTERP_KERNEL::Exception("MEDFileUMeshAggregateCompute::getMeshDimension : no umesh in this !");
1884       return m->getMeshDimension();
1885     }
1886   else
1887     {
1888       if(_m_parts.empty())
1889         throw INTERP_KERNEL::Exception("MEDFileUMeshAggregateCompute::getMeshDimension : part mesh is empty !");
1890       const MEDCoupling1GTUMesh *m(_m_parts[0]);
1891       if(!m)
1892         throw INTERP_KERNEL::Exception("MEDFileUMeshAggregateCompute::getMeshDimension : part mesh contains null instance !");
1893       return m->getMeshDimension();
1894     }
1895 }
1896
1897 std::vector<int> MEDFileUMeshAggregateCompute::getDistributionOfTypes() const
1898 {
1899   if(_mp_time<_m_time)
1900     {
1901       const MEDCouplingUMesh *m(_m);
1902       if(!m)
1903         throw INTERP_KERNEL::Exception("MEDFileUMeshAggregateCompute::getDistributionOfTypes : no umesh in this !");
1904       return m->getDistributionOfTypes();
1905     }
1906   else
1907     {
1908       std::vector<int> ret;
1909       for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> >::const_iterator it=_m_parts.begin();it!=_m_parts.end();it++)
1910         {
1911           const MEDCoupling1GTUMesh *tmp(*it);
1912           if(!tmp)
1913             throw INTERP_KERNEL::Exception("MEDFileUMeshAggregateCompute::getDistributionOfTypes : part mesh contains null instance !");
1914           std::vector<int> ret0(tmp->getDistributionOfTypes());
1915           ret.insert(ret.end(),ret0.begin(),ret0.end());
1916         }
1917       return ret;
1918     }
1919 }
1920
1921 int MEDFileUMeshAggregateCompute::getSize() const
1922 {
1923   if(_mp_time<_m_time)
1924     {
1925       const MEDCouplingUMesh *m(_m);
1926       if(!m)
1927         throw INTERP_KERNEL::Exception("MEDFileUMeshAggregateCompute::getSize : no umesh in this !");
1928       return m->getNumberOfCells();
1929     }
1930   else
1931     {
1932       int ret=0;
1933       for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> >::const_iterator it=_m_parts.begin();it!=_m_parts.end();it++)
1934         {
1935           const MEDCoupling1GTUMesh *m(*it);
1936           if(!m)
1937             throw INTERP_KERNEL::Exception("MEDFileUMeshAggregateCompute::getSize : part mesh contains null instance !");
1938           ret+=m->getNumberOfCells();
1939         }
1940       return ret;
1941     }
1942 }
1943
1944 void MEDFileUMeshAggregateCompute::setCoords(DataArrayDouble *coords)
1945 {
1946   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> >::iterator it=_m_parts.begin();it!=_m_parts.end();it++)
1947     {
1948       MEDCoupling1GTUMesh *tmp(*it);
1949       if(tmp)
1950         (*it)->setCoords(coords);
1951     }
1952   MEDCouplingUMesh *m(_m);
1953   if(m)
1954     m->setCoords(coords);
1955 }