Salome HOME
Management of lev -1 even for cell fields on structured meshes
[tools/medcoupling.git] / src / MEDLoader / MEDFileFieldOverView.cxx
index 2d42a00fbed6e9b030114aa48439fb309f66b439..5493d88cd6783d7b35ab1d5a17c33fcec0dbd470 100644 (file)
@@ -1,9 +1,9 @@
-// Copyright (C) 2007-2013  CEA/DEN, EDF R&D
+// Copyright (C) 2007-2014  CEA/DEN, EDF R&D
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 // License as published by the Free Software Foundation; either
-// version 2.1 of the License.
+// version 2.1 of the License, or (at your option) any later version.
 //
 // This library is distributed in the hope that it will be useful,
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -29,6 +29,8 @@ using namespace ParaMEDMEM;
 const unsigned char MEDMeshMultiLev::PARAMEDMEM_2_VTKTYPE[MEDMeshMultiLev::PARAMEDMEM_2_VTKTYPE_LGTH]=
   {1,3,21,5,9,7,22,34,23,28,255,255,255,255,10,14,13,255,12,255,24,255,16,27,255,26,255,29,255,255,25,42,36,4};
 
+const unsigned char MEDMeshMultiLev::HEXA27_PERM_ARRAY[27]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,24,22,21,23,20,25,26};
+
 const char MEDFileField1TSStructItem2::NEWLY_CREATED_PFL_NAME[]="???";
 
 MEDFileMeshStruct *MEDFileMeshStruct::New(const MEDFileMesh *mesh)
@@ -52,12 +54,15 @@ std::vector<const BigMemoryObject *> MEDFileMeshStruct::getDirectChildren() cons
 
 MEDFileMeshStruct::MEDFileMeshStruct(const MEDFileMesh *mesh):_mesh(mesh)
 {
-  std::vector<int> levs=mesh->getNonEmptyLevels();
+  std::vector<int> levs(mesh->getNonEmptyLevels());
   _name=mesh->getName();
   _nb_nodes=mesh->getNumberOfNodes();
-  _geo_types_distrib.resize(levs.size());
-  for(std::vector<int>::const_iterator lev=levs.begin();lev!=levs.end();lev++)
-    _geo_types_distrib[-(*lev)]=mesh->getDistributionOfTypes(*lev);
+  if(!levs.empty())
+    {
+      _geo_types_distrib.resize(-(*std::min_element(levs.begin(),levs.end()))+1);
+      for(std::vector<int>::const_iterator lev=levs.begin();lev!=levs.end();lev++)
+        _geo_types_distrib[-(*lev)]=mesh->getDistributionOfTypes(*lev);
+    }
 }
 
 int MEDFileMeshStruct::getLevelOfGeoType(INTERP_KERNEL::NormalizedCellType t) const
@@ -76,6 +81,9 @@ int MEDFileMeshStruct::getLevelOfGeoType(INTERP_KERNEL::NormalizedCellType t) co
   throw INTERP_KERNEL::Exception("MEDFileMeshStruct::getLevelOfGeoType : The specified geometric type is not present in the mesh structure !");
 }
 
+/*!
+ * \sa MEDFileMeshStruct::doesManageGeoType
+ */
 int MEDFileMeshStruct::getNumberOfElemsOfGeoType(INTERP_KERNEL::NormalizedCellType t) const
 {
   for(std::vector< std::vector<int> >::const_iterator it1=_geo_types_distrib.begin();it1!=_geo_types_distrib.end();it1++)
@@ -91,6 +99,42 @@ int MEDFileMeshStruct::getNumberOfElemsOfGeoType(INTERP_KERNEL::NormalizedCellTy
   throw INTERP_KERNEL::Exception("The specified geometric type is not present in the mesh structure !");
 }
 
+/*!
+ * \sa MEDFileMeshStruct::getNumberOfElemsOfGeoType
+ */
+bool MEDFileMeshStruct::doesManageGeoType(INTERP_KERNEL::NormalizedCellType t) const
+{
+  for(std::vector< std::vector<int> >::const_iterator it1=_geo_types_distrib.begin();it1!=_geo_types_distrib.end();it1++)
+    {
+      std::size_t sz=(*it1).size();
+      if(sz%3!=0)
+        throw INTERP_KERNEL::Exception("MEDFileMeshStruct::doesManageGeoType : internal error in code !");
+      std::size_t nbGeo=sz/3;
+      for(std::size_t i=0;i<nbGeo;i++)
+        if((*it1)[3*i]==(int)t)
+          return true;
+    }
+  return false;
+}
+
+void MEDFileMeshStruct::appendIfImplicitType(INTERP_KERNEL::NormalizedCellType t)
+{
+  if(!_mesh->hasImplicitPart())
+    throw INTERP_KERNEL::Exception("MEDFileMeshStruct::appendIfImplicitType : by default no implicit geo type can be appended !");
+  static const char MSG[]="MEDFileMeshStruct::appendIfImplicitType : the distribution does not looks like structured standard !";
+  if(_geo_types_distrib.size()!=1)
+    throw INTERP_KERNEL::Exception(MSG);
+  std::size_t sz(_geo_types_distrib[0].size());
+  if(sz%3!=0)
+    throw INTERP_KERNEL::Exception("MEDFileMeshStruct::appendIfImplicitType : internal error in code !");
+  std::size_t nbGeo(sz/3);
+  if(nbGeo!=1)
+    throw INTERP_KERNEL::Exception(MSG);
+  std::vector<int> arr(3); arr[0]=(int)t; arr[1]=_mesh->buildImplicitPartIfAny(t); arr[2]=-1;
+  _geo_types_distrib.push_back(arr);
+}
+
+
 int MEDFileMeshStruct::getNumberOfLevs() const
 {
   return (int)_geo_types_distrib.size();
@@ -176,6 +220,8 @@ bool MEDMeshMultiLev::isFastlyTheSameStruct(const MEDFileField1TSStructItem& fst
       const DataArrayInt *nr(_node_reduction);
       if(pflName.empty() && !nr)
         return true;
+      if(!pflName.empty() && !nr)
+        return false;
       if(pflName==nr->getName())
         return true;
       return false;
@@ -335,6 +381,11 @@ void MEDMeshMultiLev::retrieveNumberIdsOnNodes(DataArrayInt *& numIds, bool& isW
     }
 }
 
+std::vector< INTERP_KERNEL::NormalizedCellType > MEDMeshMultiLev::getGeoTypes() const
+{
+  return _geo_types;
+}
+
 void MEDMeshMultiLev::setFamilyIdsOnCells(DataArrayInt *famIds, bool isNoCopy)
 {
   _cell_fam_ids=famIds;
@@ -415,7 +466,7 @@ DataArray *MEDMeshMultiLev::constructDataArray(const MEDFileField1TSStructItem&
           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> p2(nr->deepCpy());
           p1->sort(true); p2->sort(true);
           if(!p1->isEqualWithoutConsideringStr(*p2))
-            throw INTERP_KERNEL::Exception("MEDMeshMultiLev::constructDataArray : unexpected situation for nodes 3 !");
+            throw INTERP_KERNEL::Exception("MEDMeshMultiLev::constructDataArray : it appears that a profile on nodes does not cover the cells correctly !");
           p1=DataArrayInt::FindPermutationFromFirstToSecond(globs->getProfile(pflName.c_str()),nr);
           MEDCouplingAutoRefCountObjectPtr<DataArray> ret(vals->deepCpy());
           ret->renumberInPlace(p1->begin());
@@ -543,11 +594,56 @@ DataArray *MEDMeshMultiLev::constructDataArray(const MEDFileField1TSStructItem&
     }
 }
 
-MEDMeshMultiLev::MEDMeshMultiLev():_nb_nodes(0),_cell_fam_ids_nocpy(false)
+/*!
+ * This method is called to add NORM_POINT1 cells in \a this so that orphan nodes in \a verticesToAdd will be fetched.
+ */
+void MEDMeshMultiLev::appendVertices(const DataArrayInt *verticesToAdd, DataArrayInt *nr)
+{
+  int nbOfVertices(verticesToAdd->getNumberOfTuples());
+  std::size_t sz(_pfls.size());
+  _pfls.resize(sz+1);
+  _geo_types.resize(sz+1,INTERP_KERNEL::NORM_POINT1);
+  _nb_entities.resize(sz+1,nbOfVertices);
+  _node_reduction=nr; nr->incrRef();
+  _nb_nodes+=nbOfVertices;
+  const DataArrayInt *cf(_cell_fam_ids),*cn(_cell_num_ids),*nf(_node_fam_ids),*nn(_node_num_ids);
+  if(cf)
+    {
+      MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp;
+      std::vector<const DataArrayInt *> a(2);
+      a[0]=cf;
+      if(nf)
+        tmp=nf->selectByTupleIdSafe(verticesToAdd->begin(),verticesToAdd->end());
+      else
+        {
+          tmp=DataArrayInt::New(); tmp->alloc(nbOfVertices,1); tmp->fillWithZero();
+        }
+      a[1]=tmp;
+      _cell_fam_ids=DataArrayInt::Aggregate(a);
+      _cell_fam_ids_nocpy=false;
+    }
+  if(cn)
+    {
+      MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp;
+      std::vector<const DataArrayInt *> a(2);
+      a[0]=cn;
+      if(nn)
+        tmp=nn->selectByTupleIdSafe(verticesToAdd->begin(),verticesToAdd->end());
+      else
+        {
+          tmp=DataArrayInt::New(); tmp->alloc(nbOfVertices,1); tmp->fillWithZero();
+        }
+      a[1]=tmp;
+      _cell_num_ids=DataArrayInt::Aggregate(a);
+      _cell_num_ids_nocpy=false;
+    }
+}
+
+MEDMeshMultiLev::MEDMeshMultiLev(const MEDFileMesh *mesh):_mesh(mesh),_nb_nodes(0),_cell_fam_ids_nocpy(false)
 {
 }
 
-MEDMeshMultiLev::MEDMeshMultiLev(int nbNodes, const std::vector<INTERP_KERNEL::NormalizedCellType>& gts, const std::vector<const DataArrayInt *>& pfls, const std::vector<int>& nbEntities):_geo_types(gts),_nb_entities(nbEntities),_nb_nodes(nbNodes),_cell_fam_ids_nocpy(false),_cell_num_ids_nocpy(false),_node_fam_ids_nocpy(false),_node_num_ids_nocpy(false)
+MEDMeshMultiLev::MEDMeshMultiLev(const MEDFileMesh *mesh, int nbNodes, const std::vector<INTERP_KERNEL::NormalizedCellType>& gts, const std::vector<const DataArrayInt *>& pfls, const std::vector<int>& nbEntities):_mesh(mesh),_geo_types(gts),_nb_entities(nbEntities),_nb_nodes(nbNodes),_cell_fam_ids_nocpy(false),_cell_num_ids_nocpy(false),_node_fam_ids_nocpy(false),_node_num_ids_nocpy(false)
 {
   std::size_t sz(_geo_types.size());
   if(sz!=pfls.size() || sz!=nbEntities.size())
@@ -561,7 +657,7 @@ MEDMeshMultiLev::MEDMeshMultiLev(int nbNodes, const std::vector<INTERP_KERNEL::N
     }
 }
 
-MEDMeshMultiLev::MEDMeshMultiLev(const MEDMeshMultiLev& other):RefCountObject(other),_pfls(other._pfls),_geo_types(other._geo_types),_nb_entities(other._nb_entities),_node_reduction(other._node_reduction),_nb_nodes(other._nb_nodes),_cell_fam_ids(other._cell_fam_ids),_cell_fam_ids_nocpy(other._cell_fam_ids_nocpy),_cell_num_ids(other._cell_num_ids),_cell_num_ids_nocpy(other._cell_num_ids_nocpy),_node_fam_ids(other._node_fam_ids),_node_fam_ids_nocpy(other._node_fam_ids_nocpy),_node_num_ids(other._node_num_ids),_node_num_ids_nocpy(other._node_num_ids_nocpy)
+MEDMeshMultiLev::MEDMeshMultiLev(const MEDMeshMultiLev& other):RefCountObject(other),_mesh(other._mesh),_pfls(other._pfls),_geo_types(other._geo_types),_nb_entities(other._nb_entities),_node_reduction(other._node_reduction),_nb_nodes(other._nb_nodes),_cell_fam_ids(other._cell_fam_ids),_cell_fam_ids_nocpy(other._cell_fam_ids_nocpy),_cell_num_ids(other._cell_num_ids),_cell_num_ids_nocpy(other._cell_num_ids_nocpy),_node_fam_ids(other._node_fam_ids),_node_fam_ids_nocpy(other._node_fam_ids_nocpy),_node_num_ids(other._node_num_ids),_node_num_ids_nocpy(other._node_num_ids_nocpy)
 {
 }
 
@@ -572,7 +668,7 @@ MEDUMeshMultiLev *MEDUMeshMultiLev::New(const MEDFileUMesh *m, const std::vector
   return new MEDUMeshMultiLev(m,levs);
 }
 
-MEDUMeshMultiLev::MEDUMeshMultiLev(const MEDFileUMesh *m, const std::vector<int>& levs)
+MEDUMeshMultiLev::MEDUMeshMultiLev(const MEDFileUMesh *m, const std::vector<int>& levs):MEDMeshMultiLev(m)
 {
   if(!m)
     throw INTERP_KERNEL::Exception("MEDUMeshMultiLev constructor : null input pointer !");
@@ -583,6 +679,10 @@ MEDUMeshMultiLev::MEDUMeshMultiLev(const MEDFileUMesh *m, const std::vector<int>
       v.insert(v.end(),vTmp.begin(),vTmp.end());
     }
   std::size_t sz(v.size());
+  if(v.empty())
+    {
+      _coords=m->getCoords(); _coords->incrRef();
+    }
   _parts.resize(sz);
   _pfls.resize(sz);
   _geo_types.resize(sz);
@@ -619,7 +719,7 @@ MEDUMeshMultiLev::MEDUMeshMultiLev(const MEDFileUMesh *m, const std::vector<int>
           if(!tmps[i])
             f=false;
         }
-      if(f)
+      if(f && !tmps.empty())
         _cell_fam_ids=DataArrayInt::Aggregate(tmps);
     }
   _cell_num_ids_nocpy=(levs.size()==1);
@@ -642,7 +742,7 @@ MEDUMeshMultiLev::MEDUMeshMultiLev(const MEDFileUMesh *m, const std::vector<int>
           if(!tmps[i])
             n=false;
         }
-      if(n)
+      if(n && !tmps.empty())
         _cell_num_ids=DataArrayInt::Aggregate(tmps);
     }
   // node part
@@ -671,7 +771,7 @@ MEDUMeshMultiLev *MEDUMeshMultiLev::New(const MEDFileUMesh *m, const std::vector
   return new MEDUMeshMultiLev(m,gts,pfls,nbEntities);
 }
 
-MEDUMeshMultiLev::MEDUMeshMultiLev(const MEDFileUMesh *m, const std::vector<INTERP_KERNEL::NormalizedCellType>& gts, const std::vector<const DataArrayInt *>& pfls, const std::vector<int>& nbEntities):MEDMeshMultiLev(m->getNumberOfNodes(),gts,pfls,nbEntities)
+MEDUMeshMultiLev::MEDUMeshMultiLev(const MEDFileUMesh *m, const std::vector<INTERP_KERNEL::NormalizedCellType>& gts, const std::vector<const DataArrayInt *>& pfls, const std::vector<int>& nbEntities):MEDMeshMultiLev(m,m->getNumberOfNodes(),gts,pfls,nbEntities)
 {
   std::size_t sz(gts.size());
   if(sz<1)
@@ -759,7 +859,6 @@ void MEDUMeshMultiLev::selectPartOfNodes(const DataArrayInt *pflNodes)
    std::vector< const DataArrayInt *> aa(sz);
    for(std::size_t i=0;i<sz;i++)
      {
-       
        const DataArrayInt *pfl(_pfls[i]);
        MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> m(_parts[i]);
        if(pfl)
@@ -776,9 +875,21 @@ void MEDUMeshMultiLev::selectPartOfNodes(const DataArrayInt *pflNodes)
        else
          _pfls[i]=cellIdsSafe;
      }
-   _node_reduction=DataArrayInt::Aggregate(aa);
+   if(!aa.empty())
+     _node_reduction=DataArrayInt::Aggregate(aa);//general case
+   else
+     _node_reduction=pflNodes->deepCpy();//case where no cells in read mesh.
    _node_reduction->sort(true);
    _node_reduction=_node_reduction->buildUnique();
+   if(_node_reduction->getNumberOfTuples()==pflNodes->getNumberOfTuples())
+     return ;//This is the classical case where the input node profile corresponds perfectly to a subset of cells in _parts
+   if(_node_reduction->getNumberOfTuples()>pflNodes->getNumberOfTuples())
+     throw INTERP_KERNEL::Exception("MEDUMeshMultiLev::selectPartOfNodes : internal error in MEDCoupling during cell select from a list of nodes !");
+   // Here the cells available in _parts is not enough to cover all the nodes in pflNodes. So adding vertices cells in _parts...
+   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> pflNodes2(pflNodes->deepCpy());
+   pflNodes2->sort(true);
+   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diff(pflNodes2->buildSubstractionOptimized(_node_reduction));
+   appendVertices(diff,pflNodes2);
 }
 
 MEDMeshMultiLev *MEDUMeshMultiLev::prepare() const
@@ -786,7 +897,7 @@ MEDMeshMultiLev *MEDUMeshMultiLev::prepare() const
   return new MEDUMeshMultiLev(*this);
 }
 
-MEDUMeshMultiLev::MEDUMeshMultiLev(const MEDUMeshMultiLev& other):MEDMeshMultiLev(other),_parts(other._parts)
+MEDUMeshMultiLev::MEDUMeshMultiLev(const MEDUMeshMultiLev& other):MEDMeshMultiLev(other),_parts(other._parts),_coords(other._coords)
 {
 }
 
@@ -805,11 +916,11 @@ MEDUMeshMultiLev::MEDUMeshMultiLev(const MEDStructuredMeshMultiLev& other, const
  */
 bool MEDUMeshMultiLev::buildVTUArrays(DataArrayDouble *& coords, DataArrayByte *&types, DataArrayInt *&cellLocations, DataArrayInt *& cells, DataArrayInt *&faceLocations, DataArrayInt *&faces) const
 {
+  const DataArrayDouble *tmp(0);
   if(_parts.empty())
-    throw INTERP_KERNEL::Exception("MEDUMeshMultiLev::getVTUArrays : empty array !");
-  if(!(const MEDCoupling1GTUMesh *)_parts[0])
-    throw INTERP_KERNEL::Exception("MEDUMeshMultiLev::getVTUArrays : first part is null !");
-  const DataArrayDouble *tmp(_parts[0]->getCoords());
+    tmp=_coords;
+  else
+    tmp=_parts[0]->getCoords();
   if(!tmp)
     throw INTERP_KERNEL::Exception("MEDUMeshMultiLev::getVTUArrays : the coordinates are null !");
   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> a(const_cast<DataArrayDouble *>(tmp)); tmp->incrRef();
@@ -875,12 +986,25 @@ bool MEDUMeshMultiLev::buildVTUArrays(DataArrayDouble *& coords, DataArrayByte *
         throw INTERP_KERNEL::Exception("MEDUMeshMultiLev::getVTUArrays : internal error !");
       if(scur)
         {
-          int nnpc(scur->getNumberOfNodesPerCell());
-          for(int i=0;i<curNbCells;i++,connPtr+=nnpc)
+          if(cur->getCellModelEnum()!=INTERP_KERNEL::NORM_HEXA27)
             {
-              *dPtr++=nnpc;
-              dPtr=std::copy(connPtr,connPtr+nnpc,dPtr);
-              *cPtr++=k; k+=nnpc+1;
+              int nnpc(scur->getNumberOfNodesPerCell());
+              for(int i=0;i<curNbCells;i++,connPtr+=nnpc)
+                {
+                  *dPtr++=nnpc;
+                  dPtr=std::copy(connPtr,connPtr+nnpc,dPtr);
+                  *cPtr++=k; k+=nnpc+1;
+                }
+            }
+          else
+            {
+              for(int i=0;i<curNbCells;i++,connPtr+=27)
+                {
+                  *dPtr++=27;
+                  for(int j=0;j<27;j++,dPtr++)
+                    *dPtr=connPtr[HEXA27_PERM_ARRAY[j]];
+                  *cPtr++=k; k+=28;
+                }
             }
           if(isPolyh)
             { std::fill(ePtr,ePtr+curNbCells,-1); ePtr+=curNbCells; }
@@ -952,6 +1076,11 @@ void MEDUMeshMultiLev::reorderNodesIfNecessary(MEDCouplingAutoRefCountObjectPtr<
   const DataArrayInt *nr(_node_reduction);
   if(!nr)
     return ;
+  if(nodalConnVTK->empty() && !polyhedNodalConnVTK)
+    {
+      coords=(coords->selectByTupleIdSafe(nr->begin(),nr->end()));
+      return ;
+    }
   int sz(coords->getNumberOfTuples());
   std::vector<bool> b(sz,false);
   const int *work(nodalConnVTK->begin()),*endW(nodalConnVTK->end());
@@ -1022,13 +1151,32 @@ void MEDUMeshMultiLev::reorderNodesIfNecessary(MEDCouplingAutoRefCountObjectPtr<
   coords=(coords->selectByTupleIdSafe(nr->begin(),nr->end()));
 }
 
+
+void MEDUMeshMultiLev::appendVertices(const DataArrayInt *verticesToAdd, DataArrayInt *nr)
+{
+  int nbOfCells(verticesToAdd->getNumberOfTuples());//it is not a bug cells are NORM_POINT1
+  MEDMeshMultiLev::appendVertices(verticesToAdd,nr);
+  MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> elt(MEDCoupling1SGTUMesh::New("",INTERP_KERNEL::NORM_POINT1));
+  elt->allocateCells(nbOfCells);
+  for(int i=0;i<nbOfCells;i++)
+    {
+      int pt(verticesToAdd->getIJ(i,0));
+      elt->insertNextCell(&pt,&pt+1);
+    }
+  if(_parts.empty())
+    throw INTERP_KERNEL::Exception("MEDUMeshMultiLev::appendVertices : parts are empty !");
+  elt->setCoords(_parts[0]->getCoords());
+  MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> elt2((MEDCoupling1SGTUMesh *)elt); elt2->incrRef();
+  _parts.push_back(elt2);
+}
+
 //=
 
-MEDStructuredMeshMultiLev::MEDStructuredMeshMultiLev()
+MEDStructuredMeshMultiLev::MEDStructuredMeshMultiLev(const MEDFileStructuredMesh *m):MEDMeshMultiLev(m),_is_internal(true)
 {
 }
 
-MEDStructuredMeshMultiLev::MEDStructuredMeshMultiLev(const MEDFileStructuredMesh *m, const std::vector<int>& lev)
+MEDStructuredMeshMultiLev::MEDStructuredMeshMultiLev(const MEDFileStructuredMesh *m, const std::vector<int>& lev):MEDMeshMultiLev(m),_is_internal(true)
 {
   // ids fields management
   _cell_fam_ids_nocpy=true; _cell_num_ids_nocpy=true;
@@ -1062,7 +1210,7 @@ MEDStructuredMeshMultiLev::MEDStructuredMeshMultiLev(const MEDFileStructuredMesh
     }
 }
 
-MEDStructuredMeshMultiLev::MEDStructuredMeshMultiLev(const MEDFileStructuredMesh *m, int nbOfNodes, const std::vector<INTERP_KERNEL::NormalizedCellType>& gts, const std::vector<const DataArrayInt *>& pfls, const std::vector<int>& nbEntities):MEDMeshMultiLev(nbOfNodes,gts,pfls,nbEntities)
+MEDStructuredMeshMultiLev::MEDStructuredMeshMultiLev(const MEDFileStructuredMesh *m, int nbOfNodes, const std::vector<INTERP_KERNEL::NormalizedCellType>& gts, const std::vector<const DataArrayInt *>& pfls, const std::vector<int>& nbEntities):MEDMeshMultiLev(m,nbOfNodes,gts,pfls,nbEntities),_is_internal(true)
 {
   // ids fields management
   _cell_fam_ids_nocpy=true; _cell_num_ids_nocpy=true;
@@ -1096,6 +1244,47 @@ MEDStructuredMeshMultiLev::MEDStructuredMeshMultiLev(const MEDFileStructuredMesh
     }
 }
 
+MEDStructuredMeshMultiLev::MEDStructuredMeshMultiLev(const MEDStructuredMeshMultiLev& other):MEDMeshMultiLev(other),_is_internal(true)
+{
+}
+
+bool MEDStructuredMeshMultiLev::prepareForImplicitUnstructuredMeshCase(MEDMeshMultiLev *&ret) const
+{
+  ret=0;
+  MEDCoupling1GTUMesh *facesIfPresent((static_cast<const MEDFileStructuredMesh *>(_mesh))->getImplicitFaceMesh());
+  if(!facesIfPresent)
+    return false;
+  const DataArrayInt *pfl(0),*nr(_node_reduction);
+  if(!_pfls.empty())
+    pfl=_pfls[0];
+  MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> facesIfPresent2(facesIfPresent); facesIfPresent->incrRef();
+  MEDCouplingAutoRefCountObjectPtr<MEDUMeshMultiLev> ret2(new MEDUMeshMultiLev(*this,facesIfPresent2));
+  if(pfl)
+    throw INTERP_KERNEL::Exception("MEDStructuredMeshMultiLev::prepareForImplicitUnstructuredMeshCase : case is not treated yet for profile on implicit unstructured mesh.");
+  if(nr)
+    throw INTERP_KERNEL::Exception("MEDStructuredMeshMultiLev::prepareForImplicitUnstructuredMeshCase : case is not treated yet for node reduction on implicit unstructured mesh.");
+  ret=ret2.retn();
+  return true;
+}
+
+void MEDStructuredMeshMultiLev::dealWithImplicitUnstructuredMesh(const MEDFileMesh *m)
+{
+  _cell_fam_ids_nocpy=true; _cell_num_ids_nocpy=true;
+  const DataArrayInt *tmp(0);
+  tmp=m->getFamilyFieldAtLevel(-1);
+  if(tmp)
+    {
+      tmp->incrRef();
+      _cell_fam_ids=const_cast<DataArrayInt *>(tmp);
+    }
+  tmp=m->getNumberFieldAtLevel(-1);
+  if(tmp)
+    {
+      tmp->incrRef();
+      _cell_num_ids=const_cast<DataArrayInt *>(tmp);
+    }
+}
+
 void MEDStructuredMeshMultiLev::selectPartOfNodes(const DataArrayInt *pflNodes)
 {
   if(!pflNodes || !pflNodes->isAllocated())
@@ -1121,10 +1310,6 @@ void MEDStructuredMeshMultiLev::selectPartOfNodes(const DataArrayInt *pflNodes)
     _pfls[0]=cellIdsSafe;
 }
 
-MEDStructuredMeshMultiLev::MEDStructuredMeshMultiLev(const MEDStructuredMeshMultiLev& other):MEDMeshMultiLev(other)
-{
-}
-
 //=
 
 MEDCMeshMultiLev *MEDCMeshMultiLev::New(const MEDFileCMesh *m, const std::vector<int>& levs)
@@ -1143,13 +1328,14 @@ MEDCMeshMultiLev::MEDCMeshMultiLev(const MEDFileCMesh *m, const std::vector<int>
     throw INTERP_KERNEL::Exception("MEDCMeshMultiLev constructor : null input pointer !");
   if(levs.size()!=1 || levs[0]!=0)
     throw INTERP_KERNEL::Exception("MEDCMeshMultiLev constructor : levels supported is 0 only !");
-  int mdim(MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(m->getMeshDimension()));
-  _coords.resize(mdim);
-  for(int i=0;i<mdim;i++)
+  int sdim(m->getSpaceDimension());
+  _coords.resize(sdim);
+  for(int i=0;i<sdim;i++)
     {
       DataArrayDouble *elt(const_cast<DataArrayDouble *>(m->getMesh()->getCoordsAt(i)));
       if(!elt)
         throw INTERP_KERNEL::Exception("MEDCMeshMultiLev constructor 2 : presence of null pointer for an vector of double along an axis !");
+      elt->incrRef();
       _coords[i]=elt;
     }
 }
@@ -1162,16 +1348,19 @@ MEDCMeshMultiLev::MEDCMeshMultiLev(const MEDFileCMesh *m, const std::vector<INTE
     throw INTERP_KERNEL::Exception("MEDCMeshMultiLev constructor 2 : lengthes of gts and pfls must be equal to one !");
   int mdim(m->getMeshDimension());
   INTERP_KERNEL::NormalizedCellType gt(MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(mdim));
-  if(gt!=gts[0])
-    throw INTERP_KERNEL::Exception("MEDCMeshMultiLev constructor 2 : the unique geo type is invalid regarding meshdim !");
-  _coords.resize(mdim);
-  for(int i=0;i<mdim;i++)
+  if(gt==gts[0])
     {
-      DataArrayDouble *elt(const_cast<DataArrayDouble *>(m->getMesh()->getCoordsAt(i)));
-      if(!elt)
-        throw INTERP_KERNEL::Exception("MEDCMeshMultiLev constructor 2 : presence of null pointer for an vector of double along an axis !");
-      _coords[i]=elt; _coords[i]->incrRef();
+      _coords.resize(mdim);
+      for(int i=0;i<mdim;i++)
+        {
+          DataArrayDouble *elt(const_cast<DataArrayDouble *>(m->getMesh()->getCoordsAt(i)));
+          if(!elt)
+            throw INTERP_KERNEL::Exception("MEDCMeshMultiLev constructor 2 : presence of null pointer for an vector of double along an axis !");
+          _coords[i]=elt; _coords[i]->incrRef();
+        }
     }
+  else
+    dealWithImplicitUnstructuredMesh(m);
 }
 
 MEDCMeshMultiLev::MEDCMeshMultiLev(const MEDCMeshMultiLev& other):MEDStructuredMeshMultiLev(other),_coords(other._coords)
@@ -1188,7 +1377,12 @@ std::vector<int> MEDCMeshMultiLev::getNodeGridStructure() const
 
 MEDMeshMultiLev *MEDCMeshMultiLev::prepare() const
 {
-  const DataArrayInt *pfl(_pfls[0]),*nr(_node_reduction);
+  MEDMeshMultiLev *retSpecific(0);
+  if(prepareForImplicitUnstructuredMeshCase(retSpecific))
+    return retSpecific;
+  const DataArrayInt *pfl(0),*nr(_node_reduction);
+  if(!_pfls.empty())
+    pfl=_pfls[0];
   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nnr;
   std::vector<int> cgs,ngs(getNodeGridStructure());
   cgs.resize(ngs.size());
@@ -1200,6 +1394,7 @@ MEDMeshMultiLev *MEDCMeshMultiLev::prepare() const
       if(MEDCouplingStructuredMesh::IsPartStructured(pfl->begin(),pfl->end(),cgs,cellParts))
         {
           MEDCouplingAutoRefCountObjectPtr<MEDCMeshMultiLev> ret(new MEDCMeshMultiLev(*this));
+          ret->_is_internal=false;
           if(nr)
             { nnr=nr->deepCpy(); nnr->sort(true); ret->setNodeReduction(nnr); }
           ret->_nb_entities[0]=pfl->getNumberOfTuples();
@@ -1245,8 +1440,12 @@ MEDMeshMultiLev *MEDCMeshMultiLev::prepare() const
     }
 }
 
-std::vector< DataArrayDouble * > MEDCMeshMultiLev::buildVTUArrays() const
+/*!
+ * \a param [out] isInternal if true the returned pointers are those in main data structure. If false those pointers have been built espacially for that method.
+ */
+std::vector< DataArrayDouble * > MEDCMeshMultiLev::buildVTUArrays(bool& isInternal) const
 {
+  isInternal=_is_internal;
   std::size_t sz(_coords.size());
   std::vector< DataArrayDouble * > ret(sz);
   for(std::size_t i=0;i<sz;i++)
@@ -1289,15 +1488,18 @@ MEDCurveLinearMeshMultiLev::MEDCurveLinearMeshMultiLev(const MEDFileCurveLinearM
     throw INTERP_KERNEL::Exception("MEDCurveLinearMeshMultiLev constructor 2 : null input pointer !");
   if(gts.size()!=1 || pfls.size()!=1)
     throw INTERP_KERNEL::Exception("MEDCurveLinearMeshMultiLev constructor 2 : lengthes of gts and pfls must be equal to one !");
-  int mdim(MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(m->getMeshDimension()));
-  if(mdim!=gts[0])
-    throw INTERP_KERNEL::Exception("MEDCurveLinearMeshMultiLev constructor 2 : the unique geo type is invalid regarding meshdim !");
-  DataArrayDouble *coords(const_cast<DataArrayDouble *>(m->getMesh()->getCoords()));
-  if(!coords)
-    throw INTERP_KERNEL::Exception("MEDCurveLinearMeshMultiLev constructor 2 : no coords set !");
-  coords->incrRef();
-  _coords=coords;
-  _structure=m->getMesh()->getNodeGridStructure();
+  INTERP_KERNEL::NormalizedCellType gt(MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(m->getMeshDimension()));
+  if(gt==gts[0])
+    {
+      DataArrayDouble *coords(const_cast<DataArrayDouble *>(m->getMesh()->getCoords()));
+      if(!coords)
+        throw INTERP_KERNEL::Exception("MEDCurveLinearMeshMultiLev constructor 2 : no coords set !");
+      coords->incrRef();
+      _coords=coords;
+      _structure=m->getMesh()->getNodeGridStructure();
+    }
+  else
+    dealWithImplicitUnstructuredMesh(m);
 }
 
 MEDCurveLinearMeshMultiLev::MEDCurveLinearMeshMultiLev(const MEDCurveLinearMeshMultiLev& other):MEDStructuredMeshMultiLev(other),_coords(other._coords),_structure(other._structure)
@@ -1311,7 +1513,12 @@ std::vector<int> MEDCurveLinearMeshMultiLev::getNodeGridStructure() const
 
 MEDMeshMultiLev *MEDCurveLinearMeshMultiLev::prepare() const
 {
-  const DataArrayInt *pfl(_pfls[0]),*nr(_node_reduction);
+  MEDMeshMultiLev *retSpecific(0);
+  if(prepareForImplicitUnstructuredMeshCase(retSpecific))
+    return retSpecific;
+  const DataArrayInt *pfl(0),*nr(_node_reduction);
+  if(!_pfls.empty())
+    pfl=_pfls[0];
   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nnr;
   std::vector<int> cgs,ngs(getNodeGridStructure());
   cgs.resize(ngs.size());
@@ -1331,6 +1538,7 @@ MEDMeshMultiLev *MEDCurveLinearMeshMultiLev::prepare() const
             }
           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> p(MEDCouplingStructuredMesh::BuildExplicitIdsFrom(ngs,nodeParts));
           MEDCouplingAutoRefCountObjectPtr<MEDCurveLinearMeshMultiLev> ret(new MEDCurveLinearMeshMultiLev(*this));
+          ret->_is_internal=false;
           if(nr)
             { nnr=nr->deepCpy(); nnr->sort(true); ret->setNodeReduction(nnr); }
           ret->_nb_entities[0]=pfl->getNumberOfTuples();
@@ -1372,8 +1580,9 @@ MEDMeshMultiLev *MEDCurveLinearMeshMultiLev::prepare() const
     }
 }
 
-void MEDCurveLinearMeshMultiLev::buildVTUArrays(DataArrayDouble *&coords, std::vector<int>& nodeStrct) const
+void MEDCurveLinearMeshMultiLev::buildVTUArrays(DataArrayDouble *&coords, std::vector<int>& nodeStrct, bool& isInternal) const
 {
+  isInternal=_is_internal;
   nodeStrct=_structure;
   const DataArrayDouble *coo(_coords);
   if(!coo)
@@ -1394,6 +1603,11 @@ MEDFileField1TSStructItem2::MEDFileField1TSStructItem2(INTERP_KERNEL::Normalized
 
 void MEDFileField1TSStructItem2::checkWithMeshStructForCells(const MEDFileMeshStruct *mst, const MEDFileFieldGlobsReal *globs)
 {
+  if(!mst->doesManageGeoType(_geo_type))
+    {
+      MEDFileMeshStruct *mstUnConstCasted(const_cast<MEDFileMeshStruct *>(mst));
+      mstUnConstCasted->appendIfImplicitType(_geo_type);
+    }
   int nbOfEnt=mst->getNumberOfElemsOfGeoType(_geo_type);
   checkInRange(nbOfEnt,1,globs);
 }
@@ -1474,7 +1688,7 @@ void MEDFileField1TSStructItem2::checkInRange(int nbOfEntity, int nip, const MED
     }
 }
 
-bool MEDFileField1TSStructItem2::isFastlyEqual(int& startExp, INTERP_KERNEL::NormalizedCellType gt, const char *pflName) const
+bool MEDFileField1TSStructItem2::isFastlyEqual(int& startExp, INTERP_KERNEL::NormalizedCellType gt, const std::string& pflName) const
 {
   if(startExp!=_start_end.first)
     return false;
@@ -1808,6 +2022,31 @@ MEDMeshMultiLev *MEDFileField1TSStructItem::buildFromScratchDataSetSupportOnCell
   return MEDMeshMultiLev::New(mst->getTheMesh(),a0,a1,a2);
 }
 
+std::vector<INTERP_KERNEL::NormalizedCellType> MEDFileField1TSStructItem::getGeoTypes(const MEDFileMesh *m) const
+{
+  std::vector<INTERP_KERNEL::NormalizedCellType> ret;
+  if(_type==ON_NODES)
+    {
+      if(!_items.empty() && _items[0].getPflName().empty())
+        {
+          if(m)
+            return m->getAllGeoTypes();
+          else
+            return ret;
+        }
+      else
+        return ret;
+    }
+  for(std::vector< MEDFileField1TSStructItem2 >::const_iterator it=_items.begin();it!=_items.end();it++)
+    {
+      INTERP_KERNEL::NormalizedCellType elt((*it).getGeo());
+      std::vector<INTERP_KERNEL::NormalizedCellType>::iterator it2(std::find(ret.begin(),ret.end(),elt));
+      if(it2==ret.end())
+        ret.push_back(elt);
+    }
+  return ret;
+}
+
 MEDFileField1TSStructItem MEDFileField1TSStructItem::BuildItemFrom(const MEDFileAnyTypeField1TS *ref, const MEDFileMeshStruct *meshSt)
 {
   TypeOfField atype;
@@ -1816,7 +2055,7 @@ MEDFileField1TSStructItem MEDFileField1TSStructItem::BuildItemFrom(const MEDFile
   std::vector< std::vector<std::string> > pfls,locs;
   std::vector< std::vector<TypeOfField> > typesF;
   std::vector<INTERP_KERNEL::NormalizedCellType> geoTypes;
-  std::vector< std::vector<std::pair<int,int> > > strtEnds=ref->getFieldSplitedByType(0,geoTypes,typesF,pfls,locs);
+  std::vector< std::vector<std::pair<int,int> > > strtEnds=ref->getFieldSplitedByType(std::string(),geoTypes,typesF,pfls,locs);
   std::size_t nbOfGeoTypes(geoTypes.size());
   if(nbOfGeoTypes==0)
     throw INTERP_KERNEL::Exception("MEDFileField1TSStruct : not null by empty ref  !");
@@ -1965,9 +2204,8 @@ MEDMeshMultiLev *MEDFileField1TSStruct::buildFromScratchDataSetSupport(const MED
   else
     {
       if(!presenceOfPartialNodeDiscr(pos1))
-        {//we have only all nodes, no cell definition info -> level 0;
-          std::vector<int> levs(1,0);
-          return MEDMeshMultiLev::New(mst->getTheMesh(),levs);
+        {//we have only all nodes, no cell definition info -> all existing levels !;
+          return MEDMeshMultiLev::New(mst->getTheMesh(),mst->getTheMesh()->getNonEmptyLevels());
         }
       else
         return MEDMeshMultiLev::NewOnlyOnNode(mst->getTheMesh(),_already_checked[pos1][0].getPfl(globs));
@@ -1991,6 +2229,24 @@ bool MEDFileField1TSStruct::isDataSetSupportFastlyEqualTo(const MEDFileField1TSS
   return true;
 }
 
+std::vector<INTERP_KERNEL::NormalizedCellType> MEDFileField1TSStruct::getGeoTypes(const MEDFileMesh *m) const
+{
+  std::vector<INTERP_KERNEL::NormalizedCellType> ret;
+  for(std::vector<MEDFileField1TSStructItem>::const_iterator it=_already_checked.begin();it!=_already_checked.end();it++)
+    {
+      std::vector<INTERP_KERNEL::NormalizedCellType> ret2((*it).getGeoTypes(m));
+      for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it2=ret2.begin();it2!=ret2.end();it2++)
+        {
+          if(*it2==INTERP_KERNEL::NORM_ERROR)
+            continue;
+          std::vector<INTERP_KERNEL::NormalizedCellType>::iterator it3(std::find(ret.begin(),ret.end(),*it2));
+          if(it3==ret.end())
+            ret.push_back(*it2);
+        }
+    }
+  return ret;
+}
+
 /*!
  * Returns true if presence in \a this of discretization ON_CELLS, ON_GAUSS_PT, ON_GAUSS_NE.
  * If true is returned the pos of the easiest is returned. The easiest is the first element in \a this having the less splitted subparts.
@@ -2144,3 +2400,24 @@ bool MEDFileFastCellSupportComparator::isDataSetSupportEqualToThePreviousOne(int
   const MEDFileField1TSStruct *objRef(_f1ts_cmps[timeStepId-1]);
   return objRef->isDataSetSupportFastlyEqualTo(*obj,globs);
 }
+
+int MEDFileFastCellSupportComparator::getNumberOfTS() const
+{
+  return _f1ts_cmps.size();
+}
+
+std::vector<INTERP_KERNEL::NormalizedCellType> MEDFileFastCellSupportComparator::getGeoTypesAt(int timeStepId, const MEDFileMesh *m) const
+{
+  if(timeStepId<0 || timeStepId>=(int)_f1ts_cmps.size())
+    {
+      std::ostringstream oss; oss << "MEDFileFastCellSupportComparator::getGeoTypesAt : requested time step id #" << timeStepId << " is not in [0," << _f1ts_cmps.size() << ") !";
+      throw INTERP_KERNEL::Exception(oss.str().c_str());
+    }
+  const MEDFileField1TSStruct *elt(_f1ts_cmps[timeStepId]);
+  if(!elt)
+    {
+      std::ostringstream oss; oss << "MEDFileFastCellSupportComparator::getGeoTypesAt : requested time step id #" << timeStepId << " points to a NULL pointer !";
+      throw INTERP_KERNEL::Exception(oss.str().c_str());
+    }
+  return elt->getGeoTypes(m);
+}