Salome HOME
On the road of ParaMEDReader for fields.
[tools/medcoupling.git] / src / MEDLoader / MEDFileMesh.cxx
index 08af32e717a543d318abee61e71fbd284ff4c1d2..f07c99ce462ffef190cbeb2cc11b1382b6b3d0d0 100644 (file)
@@ -56,7 +56,7 @@ std::size_t MEDFileMesh::getHeapMemorySizeWithoutChildren() const
   return ret;
 }
 
-std::vector<const BigMemoryObject *> MEDFileMesh::getDirectChildren() const
+std::vector<const BigMemoryObject *> MEDFileMesh::getDirectChildrenWithNull() const
 {
   return std::vector<const BigMemoryObject *>();
 }
@@ -86,7 +86,7 @@ MEDFileMesh *MEDFileMesh::New(const std::string& fileName, MEDFileMeshReadSelect
   std::string dummy2;
   MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dt,it,dummy2);
   switch(meshType)
-    {
+  {
     case UNSTRUCTURED:
       {
         MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret=MEDFileUMesh::New();
@@ -110,7 +110,7 @@ MEDFileMesh *MEDFileMesh::New(const std::string& fileName, MEDFileMeshReadSelect
         std::ostringstream oss; oss << "MEDFileMesh::New : MED file exists and has mesh '" << ms.front() << "' exists but unsupported type yet !";
         throw INTERP_KERNEL::Exception(oss.str().c_str());
       }
-    }
+  }
 }
 
 /*!
@@ -136,7 +136,7 @@ MEDFileMesh *MEDFileMesh::New(const std::string& fileName, const std::string& mN
   std::string dummy2;
   MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dummy2);
   switch(meshType)
-    {
+  {
     case UNSTRUCTURED:
       {
         MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret=MEDFileUMesh::New();
@@ -160,7 +160,7 @@ MEDFileMesh *MEDFileMesh::New(const std::string& fileName, const std::string& mN
         std::ostringstream oss; oss << "MEDFileMesh::New : MED file exists and has mesh '" << mName << "' exists but unsupported type yet !";
         throw INTERP_KERNEL::Exception(oss.str().c_str());
       }
-    }
+  }
 }
 
 /*!
@@ -255,7 +255,7 @@ void MEDFileMesh::setName(const std::string& name)
  */
 void MEDFileMesh::clearNonDiscrAttributes() const
 {
-  
+
 }
 
 bool MEDFileMesh::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab)
@@ -815,7 +815,7 @@ bool MEDFileMesh::areGrpsEqual(const MEDFileMesh *other, std::string& what) cons
         {
           oss << " Group \"" << (*it).first << "\" on following families :\n";
           for(std::vector<std::string>::const_iterator it2=(*it).second.begin();it2!=(*it).second.end();it2++)
-        oss << "    \"" << *it2 << "\n";
+            oss << "    \"" << *it2 << "\n";
         }
       oss << "Second group description :\n";
       for(std::map<std::string, std::vector<std::string> >::const_iterator it=other->_groups.begin();it!=other->_groups.end();it++)
@@ -902,14 +902,14 @@ void MEDFileMesh::addFamily(const std::string& familyName, int famId)
   std::map<std::string,int>::const_iterator it=_families.find(fname);
   if(it==_families.end())
     {
-       for(std::map<std::string,int>::const_iterator it2=_families.begin();it2!=_families.end();it2++)
-         if((*it2).second==famId)
-           {
-             std::ostringstream oss;
-             oss << "MEDFileMesh::addFamily : Family \"" << (*it2).first << "\" already exists with specified id : " << famId << " !";
-             throw INTERP_KERNEL::Exception(oss.str().c_str());
-           }
-       _families[fname]=famId;
+      for(std::map<std::string,int>::const_iterator it2=_families.begin();it2!=_families.end();it2++)
+        if((*it2).second==famId)
+          {
+            std::ostringstream oss;
+            oss << "MEDFileMesh::addFamily : Family \"" << (*it2).first << "\" already exists with specified id : " << famId << " !";
+            throw INTERP_KERNEL::Exception(oss.str().c_str());
+          }
+      _families[fname]=famId;
     }
   else
     {
@@ -1983,6 +1983,40 @@ MEDFileUMesh *MEDFileUMesh::New()
   return new MEDFileUMesh;
 }
 
+/*!
+ * This method loads from file with name \a fileName the mesh called \a mName as New does. The difference is that
+ * here only a part of cells contained in the file will be loaded. The selection of cell is specified using the two consecutive parameters
+ * \a types and \a slicPerTyp. This method allows to load from a mesh (typically huge) in a MED file a part of cells of that mesh.
+ * The part of cells is specified using triplet (start,stop,step) for each geometric type. Only nodes lying on selected cells will be loaded to reduce
+ * at most the memory consumtion.
+ *
+ * \param [in] fileName - the name of the file.
+ * \param [in] mName - the name of the mesh to be read.
+ * \param [in] types - the list of the geo types of which some part will be taken. A geometric type in \a types must appear only once at most.
+ * \param [in] slicPerType - an array of size 3 times larger than \a types that specifies for each type in \a types (in the same order) resp the start, the stop and the step.
+ * \param [in] dt - the iteration, that is to say the first element of the pair that locates the asked time step.
+ * \param [in] it - the order, that is to say the second element of the pair that locates the asked time step.
+ * \param [in] mrs - the request for what to be loaded.
+ * \return MEDFileUMesh * - a new instance of MEDFileUMesh. The caller is to delete this mesh using decrRef() as it is no more needed.
+ */
+MEDFileUMesh *MEDFileUMesh::LoadPartOf(const std::string& fileName, const std::string& mName, const std::vector<INTERP_KERNEL::NormalizedCellType>& types, const std::vector<int>& slicPerTyp, int dt, int it, MEDFileMeshReadSelector *mrs)
+{
+  MEDFileUtilities::CheckFileForRead(fileName);
+  MEDFileUtilities::AutoFid fid(MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY));
+  return MEDFileUMesh::LoadPartOf(fid,mName,types,slicPerTyp,dt,it,mrs);
+}
+
+/*!
+ * Please refer to the other MEDFileUMesh::LoadPartOf method that has the same semantic and the same parameter (excepted the first).
+ * This method is \b NOT wrapped into python.
+ */
+MEDFileUMesh *MEDFileUMesh::LoadPartOf(med_idt fid, const std::string& mName, const std::vector<INTERP_KERNEL::NormalizedCellType>& types, const std::vector<int>& slicPerTyp, int dt, int it, MEDFileMeshReadSelector *mrs)
+{
+  MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret(MEDFileUMesh::New());
+  ret->loadPartUMeshFromFile(fid,mName,types,slicPerTyp,dt,it,mrs);
+  return ret.retn();
+}
+
 std::size_t MEDFileUMesh::getHeapMemorySizeWithoutChildren() const
 {
   std::size_t ret(MEDFileMesh::getHeapMemorySizeWithoutChildren());
@@ -1990,22 +2024,17 @@ std::size_t MEDFileUMesh::getHeapMemorySizeWithoutChildren() const
   return ret;
 }
 
-std::vector<const BigMemoryObject *> MEDFileUMesh::getDirectChildren() const
+std::vector<const BigMemoryObject *> MEDFileUMesh::getDirectChildrenWithNull() const
 {
-  std::vector<const BigMemoryObject *> ret(MEDFileMesh::getDirectChildren());
-  if((const DataArrayDouble*)_coords)
-    ret.push_back((const DataArrayDouble*)_coords);
-  if((const DataArrayInt *)_fam_coords)
-    ret.push_back((const DataArrayInt *)_fam_coords);
-  if((const DataArrayInt *)_num_coords)
-    ret.push_back((const DataArrayInt *)_num_coords);
-  if((const DataArrayInt *)_rev_num_coords)
-    ret.push_back((const DataArrayInt *)_rev_num_coords);
-  if((const DataArrayAsciiChar *)_name_coords)
-    ret.push_back((const DataArrayAsciiChar *)_name_coords);
+  std::vector<const BigMemoryObject *> ret(MEDFileMesh::getDirectChildrenWithNull());
+  ret.push_back((const DataArrayDouble*)_coords);
+  ret.push_back((const DataArrayInt *)_fam_coords);
+  ret.push_back((const DataArrayInt *)_num_coords);
+  ret.push_back((const DataArrayInt *)_rev_num_coords);
+  ret.push_back((const DataArrayAsciiChar *)_name_coords);
+  ret.push_back((const PartDefinition *)_part_coords);
   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
-    if((const MEDFileUMeshSplitL1*) *it)
-      ret.push_back((const MEDFileUMeshSplitL1*) *it);
+    ret.push_back((const MEDFileUMeshSplitL1*) *it);
   return ret;
 }
 
@@ -2190,27 +2219,60 @@ MEDFileUMesh::MEDFileUMesh()
 
 MEDFileUMesh::MEDFileUMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
 try
-  {
+{
     loadUMeshFromFile(fid,mName,dt,it,mrs);
-  }
+}
 catch(INTERP_KERNEL::Exception& e)
-  {
+{
     throw e;
-  }
+}
 
+/*!
+ * This method loads only a part of specified cells (given by range of cell ID per geometric type)
+ * See MEDFileUMesh::LoadPartOf for detailed description.
+ *
+ * \sa loadUMeshFromFile
+ */
+void MEDFileUMesh::loadPartUMeshFromFile(med_idt fid, const std::string& mName, const std::vector<INTERP_KERNEL::NormalizedCellType>& types, const std::vector<int>& slicPerTyp, int dt, int it, MEDFileMeshReadSelector *mrs)
+{
+  MEDFileUMeshL2 loaderl2;
+  ParaMEDMEM::MEDCouplingMeshType meshType;
+  int dummy0,dummy1;
+  std::string dummy2;
+  int mid(MEDFileUMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dummy2));
+  if(meshType!=UNSTRUCTURED)
+    {
+      std::ostringstream oss; oss << "loadPartUMeshFromFile : Trying to load as unstructured an existing mesh with name '" << mName << "' !";
+      throw INTERP_KERNEL::Exception(oss.str().c_str());
+    }
+  loaderl2.loadPart(fid,mid,mName,types,slicPerTyp,dt,it,mrs);
+  dispatchLoadedPart(fid,loaderl2,mName,mrs);
+}
+
+/*!
+ * This method loads \b all \b the \b mesh \a mName in the file with \a fid descriptor.
+ *
+ * \sa loadPartUMeshFromFile
+ */
 void MEDFileUMesh::loadUMeshFromFile(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
 {
   MEDFileUMeshL2 loaderl2;
   ParaMEDMEM::MEDCouplingMeshType meshType;
   int dummy0,dummy1;
   std::string dummy2;
-  int mid=MEDFileUMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dummy2);
+  int mid(MEDFileUMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dummy2));
   if(meshType!=UNSTRUCTURED)
     {
       std::ostringstream oss; oss << "Trying to load as unstructured an existing mesh with name '" << mName << "' !";
       throw INTERP_KERNEL::Exception(oss.str().c_str());
     }
   loaderl2.loadAll(fid,mid,mName,dt,it,mrs);
+  dispatchLoadedPart(fid,loaderl2,mName,mrs);
+
+}
+
+void MEDFileUMesh::dispatchLoadedPart(med_idt fid, const MEDFileUMeshL2& loaderl2, const std::string& mName, MEDFileMeshReadSelector *mrs)
+{
   int lev=loaderl2.getNumberOfLevels();
   _ms.resize(lev);
   for(int i=0;i<lev;i++)
@@ -2236,6 +2298,7 @@ void MEDFileUMesh::loadUMeshFromFile(med_idt fid, const std::string& mName, int
     _num_coords=loaderl2.getCoordsNum();
   if(!mrs || mrs->isNodeNameFieldReading())
     _name_coords=loaderl2.getCoordsName();
+  _part_coords=loaderl2.getPartDefOfCoo();
   computeRevNum();
 }
 
@@ -2694,6 +2757,21 @@ const DataArrayAsciiChar *MEDFileUMesh::getNameFieldAtLevel(int meshDimRelToMaxE
   return l1->getNameField();
 }
 
+/*!
+ * This method returns for a specified relative level \a meshDimRelToMaxExt the part effectively read (if the instance is the result of the read of a file).
+ *
+ * \param [in] meshDimRelToMaxExt - the extended relative level for which the part definition is requested.
+ * \param [in] gt - The input geometric type for which the part definition is requested.
+ * \return the part definition owned by \a this. So no need to deallocate the returned instance.
+ */
+const PartDefinition *MEDFileUMesh::getPartDefAtLevel(int meshDimRelToMaxExt, INTERP_KERNEL::NormalizedCellType gt) const
+{
+  if(meshDimRelToMaxExt==1)
+    return _part_coords;
+  const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMaxExt));
+  return l1->getPartDef(gt);
+}
+
 int MEDFileUMesh::getNumberOfNodes() const
 {
   const DataArrayDouble *coo=_coords;
@@ -2702,6 +2780,20 @@ int MEDFileUMesh::getNumberOfNodes() const
   return coo->getNumberOfTuples();
 }
 
+bool MEDFileUMesh::hasImplicitPart() const
+{
+  return false;
+}
+
+int MEDFileUMesh::buildImplicitPartIfAny(INTERP_KERNEL::NormalizedCellType gt) const
+{
+  throw INTERP_KERNEL::Exception("MEDFileUMesh::buildImplicitPartIfAny : unstructured meshes do not have implicit part !");
+}
+
+void MEDFileUMesh::releaseImplicitPartIfAny() const
+{
+}
+
 void MEDFileUMesh::whichAreNodesFetched(const MEDFileField1TSStructItem& st, const MEDFileFieldGlobsReal *globs, std::vector<bool>& nodesFetched) const
 {
   std::size_t sz(st.getNumberOfItems());
@@ -3089,6 +3181,18 @@ DataArrayInt *MEDFileUMesh::extractNumberFieldOnGeoType(INTERP_KERNEL::Normalize
   return sp->extractNumberFieldOnGeoType(gt);
 }
 
+/*!
+ * This method returns for specified geometric type \a gt the relative level to \a this.
+ * If the relative level is empty an exception will be thrown.
+ */
+int MEDFileUMesh::getRelativeLevOnGeoType(INTERP_KERNEL::NormalizedCellType gt) const
+{
+  const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
+  int ret((int)cm.getDimension()-getMeshDimension());
+  getMeshAtLevSafe(ret);//To test that returned value corresponds to a valid level.
+  return ret;
+}
+
 const MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt) const
 {
   if(meshDimRelToMaxExt==1)
@@ -3105,7 +3209,7 @@ const MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt
 
 MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt)
 {
-   if(meshDimRelToMaxExt==1)
+  if(meshDimRelToMaxExt==1)
     throw INTERP_KERNEL::Exception("Dimension request is invalid : asking for node level (1) !");
   if(meshDimRelToMaxExt>1)
     throw INTERP_KERNEL::Exception("Dimension request is invalid (>1) !");
@@ -3329,7 +3433,7 @@ bool MEDFileUMesh::unPolyze(std::vector<int>& oldCode, std::vector<int>& newCode
       bool hasChanged=m->unPolyze();
       DataArrayInt *fake=0;
       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nCellsPart=m->getLevArrPerCellTypes(MEDCouplingUMesh::MEDMEM_ORDER,
-                                                                                           MEDCouplingUMesh::MEDMEM_ORDER+MEDCouplingUMesh::N_MEDMEM_ORDER,fake);
+          MEDCouplingUMesh::MEDMEM_ORDER+MEDCouplingUMesh::N_MEDMEM_ORDER,fake);
       fake->decrRef();
       renumCellsSplited.push_back(o2nCellsPart); memorySaverIfThrow.push_back(o2nCellsPart);
       if(hasChanged)
@@ -3962,31 +4066,21 @@ std::size_t MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren() const
   return MEDFileMesh::getHeapMemorySizeWithoutChildren();
 }
 
-std::vector<const BigMemoryObject *> MEDFileStructuredMesh::getDirectChildren() const
-{
-  std::vector<const BigMemoryObject *> ret(MEDFileMesh::getDirectChildren());
-  if((const DataArrayInt *)_fam_nodes)
-    ret.push_back((const DataArrayInt *)_fam_nodes);
-  if((const DataArrayInt *)_num_nodes)
-    ret.push_back((const DataArrayInt *)_num_nodes);
-  if((const DataArrayAsciiChar *)_names_nodes)
-    ret.push_back((const DataArrayAsciiChar *)_names_nodes);
-  if((const DataArrayInt *)_fam_cells)
-    ret.push_back((const DataArrayInt *)_fam_cells);
-  if((const DataArrayInt *)_num_cells)
-    ret.push_back((const DataArrayInt *)_num_cells);
-  if((const DataArrayAsciiChar *)_names_cells)
-    ret.push_back((const DataArrayAsciiChar *)_names_cells);
-  if((const DataArrayInt *)_fam_faces)
-    ret.push_back((const DataArrayInt *)_fam_faces);
-  if((const DataArrayInt *)_num_faces)
-    ret.push_back((const DataArrayInt *)_num_faces);
-  if((const DataArrayInt *)_rev_num_nodes)
-    if((const DataArrayAsciiChar *)_names_faces)
-    ret.push_back((const DataArrayAsciiChar *)_names_faces);
-    ret.push_back((const DataArrayInt *)_rev_num_nodes);
-  if((const DataArrayInt *)_rev_num_cells)
-    ret.push_back((const DataArrayInt *)_rev_num_cells);
+std::vector<const BigMemoryObject *> MEDFileStructuredMesh::getDirectChildrenWithNull() const
+{
+  std::vector<const BigMemoryObject *> ret(MEDFileMesh::getDirectChildrenWithNull());
+  ret.push_back((const DataArrayInt *)_fam_nodes);
+  ret.push_back((const DataArrayInt *)_num_nodes);
+  ret.push_back((const DataArrayAsciiChar *)_names_nodes);
+  ret.push_back((const DataArrayInt *)_fam_cells);
+  ret.push_back((const DataArrayInt *)_num_cells);
+  ret.push_back((const DataArrayAsciiChar *)_names_cells);
+  ret.push_back((const DataArrayInt *)_fam_faces);
+  ret.push_back((const DataArrayInt *)_num_faces);
+  ret.push_back((const DataArrayInt *)_rev_num_nodes);
+  ret.push_back((const DataArrayAsciiChar *)_names_faces);
+  ret.push_back((const DataArrayInt *)_rev_num_cells);
+  ret.push_back((const MEDCoupling1SGTUMesh*)_faces_if_necessary);
   return ret;
 }
 
@@ -4249,7 +4343,7 @@ DataArrayInt *MEDFileStructuredMesh::getFamiliesArr(int meshDimRelToMaxExt, cons
 {
   std::vector<int> famIds(getFamiliesIds(fams));
   switch(meshDimRelToMaxExt)
-    {
+  {
     case 1:
       {
         if((const DataArrayInt *)_fam_nodes)
@@ -4306,7 +4400,8 @@ DataArrayInt *MEDFileStructuredMesh::getFamiliesArr(int meshDimRelToMaxExt, cons
       }
     default:
       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : input meshDimRelative must be in [0,1,-1] !");
-    }
+  }
+  throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : unmanaged case !");
 }
 
 /*!
@@ -4324,7 +4419,7 @@ void MEDFileStructuredMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayI
   if(!mesh)
     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setFamilyFieldArr : no structured mesh specified ! Impossible to set family array !");
   switch(meshDimRelToMaxExt)
-    {
+  {
     case 0:
       {
         int nbCells=mesh->getNumberOfCells();
@@ -4348,7 +4443,7 @@ void MEDFileStructuredMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayI
       }
     default:
       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setFamilyFieldArr : Only available for levels 0 or 1 or -1 !");
-    }
+  }
   if(famArr)
     famArr->incrRef();
 }
@@ -4367,7 +4462,7 @@ void MEDFileStructuredMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayIn
   if(!mesh)
     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : no structured mesh specified ! Impossible to set number array !");
   switch(meshDimRelToMaxExt)
-    {
+  {
     case 0:
       {
         int nbCells=mesh->getNumberOfCells();
@@ -4391,7 +4486,7 @@ void MEDFileStructuredMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayIn
       }
     default:
       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : Only available for levels 0 or 1 or -1 !");
-    }
+  }
   if(renumArr)
     renumArr->incrRef();
 }
@@ -4409,7 +4504,7 @@ void MEDFileStructuredMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArra
   if(!mesh)
     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : no structured mesh specified ! Impossible to set names array !");
   switch(meshDimRelToMaxExt)
-    {
+  {
     case 0:
       {
         int nbCells=mesh->getNumberOfCells();
@@ -4432,7 +4527,7 @@ void MEDFileStructuredMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArra
       }
     default:
       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : Only available for levels 0 or 1 or -1 !");
-    }
+  }
   if(nameArr)
     nameArr->incrRef();
 }
@@ -4447,7 +4542,7 @@ void MEDFileStructuredMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArra
 const DataArrayInt *MEDFileStructuredMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) const
 {
   switch(meshDimRelToMaxExt)
-    {
+  {
     case 0:
       return _fam_cells;
     case 1:
@@ -4456,7 +4551,7 @@ const DataArrayInt *MEDFileStructuredMesh::getFamilyFieldAtLevel(int meshDimRelT
       return _fam_faces;
     default:
       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamilyFieldAtLevel : Only available for levels 0 or 1 or -1 !");
-    }
+  }
 }
 
 /*!
@@ -4469,7 +4564,7 @@ const DataArrayInt *MEDFileStructuredMesh::getFamilyFieldAtLevel(int meshDimRelT
 const DataArrayInt *MEDFileStructuredMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) const
 {
   switch(meshDimRelToMaxExt)
-    {
+  {
     case 0:
       return _num_cells;
     case 1:
@@ -4478,7 +4573,7 @@ const DataArrayInt *MEDFileStructuredMesh::getNumberFieldAtLevel(int meshDimRelT
       return _num_faces;
     default:
       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberFieldAtLevel : Only available for levels 0 or 1 or -1 !");
-    }
+  }
 }
 
 /*!
@@ -4523,7 +4618,7 @@ const DataArrayInt *MEDFileStructuredMesh::getRevNumberFieldAtLevel(int meshDimR
 const DataArrayAsciiChar *MEDFileStructuredMesh::getNameFieldAtLevel(int meshDimRelToMaxExt) const
 {
   switch(meshDimRelToMaxExt)
-    {
+  {
     case 0:
       return _names_cells;
     case 1:
@@ -4532,7 +4627,7 @@ const DataArrayAsciiChar *MEDFileStructuredMesh::getNameFieldAtLevel(int meshDim
       return _names_faces;
     default:
       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNameFieldAtLevel : Only available for levels 0 or 1 or -1 !");
-    }
+  }
 }
 
 /*!
@@ -4672,7 +4767,7 @@ MEDCouplingMesh *MEDFileStructuredMesh::getGenMeshAtLevel(int meshDimRelToMax, b
     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support renumbering ! To do it perform request of renum array directly !");
   const MEDCouplingStructuredMesh *m(getStructuredMesh());
   switch(meshDimRelToMax)
-    {
+  {
     case 0:
       {
         if(m)
@@ -4683,11 +4778,15 @@ MEDCouplingMesh *MEDFileStructuredMesh::getGenMeshAtLevel(int meshDimRelToMax, b
       {
         if(!m)
           throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGenMeshAtLevel : level -1 requested must be non empty to be able to compute unstructured sub mesh !");
-        return m->build1SGTSubLevelMesh();
+        buildMinusOneImplicitPartIfNeeded();
+        MEDCouplingMesh *ret(_faces_if_necessary);
+        if(ret)
+          ret->incrRef();
+        return ret;
       }
     default:
       throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support multi level for mesh 0 expected as input !");
-    }
+  }
 }
 
 /*!
@@ -4702,7 +4801,7 @@ int MEDFileStructuredMesh::getSizeAtLevel(int meshDimRelToMaxExt) const
   if(!cmesh)
     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : No structured mesh set !");
   switch(meshDimRelToMaxExt)
-    {
+  {
     case 0:
       return cmesh->getNumberOfCells();
     case 1:
@@ -4711,7 +4810,7 @@ int MEDFileStructuredMesh::getSizeAtLevel(int meshDimRelToMaxExt) const
       return cmesh->getNumberOfCellsOfSubLevelMesh();
     default:
       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : Only available for levels 0 or 1 or -1 !");
-    }
+  }
 }
 
 int MEDFileStructuredMesh::getNumberOfNodes() const
@@ -4722,13 +4821,72 @@ int MEDFileStructuredMesh::getNumberOfNodes() const
   return cmesh->getNumberOfNodes();
 }
 
+bool MEDFileStructuredMesh::hasImplicitPart() const
+{
+  return true;
+}
+
+/*!
+ * \sa MEDFileStructuredMesh::getImplicitFaceMesh
+ */
+int MEDFileStructuredMesh::buildImplicitPartIfAny(INTERP_KERNEL::NormalizedCellType gt) const
+{
+  static const char MSG[]="MEDFileStructuredMesh::buildImplicitPartIfAny : the given geo type is not manageable by a structured mesh !";
+  const MEDCoupling1SGTUMesh *zeFaceMesh(_faces_if_necessary);
+  if(!zeFaceMesh)
+    {
+      const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(getMeshDimension())));
+      if(cm.getReverseExtrudedType()!=gt)
+        throw INTERP_KERNEL::Exception(MSG);
+      buildImplicitPart();
+      return getStructuredMesh()->getNumberOfCellsOfSubLevelMesh();
+    }
+  else
+    {
+      if(gt!=zeFaceMesh->getCellModelEnum())
+        throw INTERP_KERNEL::Exception(MSG);
+      return zeFaceMesh->getNumberOfCells();
+    }
+}
+
+void MEDFileStructuredMesh::buildMinusOneImplicitPartIfNeeded() const
+{
+  const MEDCoupling1SGTUMesh *zeFaceMesh(_faces_if_necessary);
+  if(!zeFaceMesh)
+    buildImplicitPart();
+}
+
+void MEDFileStructuredMesh::buildImplicitPart() const
+{
+  const MEDCouplingStructuredMesh *mcmesh(getStructuredMesh());
+  if(!mcmesh)
+    throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::buildImplicitPart : Unable to build the implicit part of structured mesh because no structured mesh at level 0 defined !");
+  _faces_if_necessary=mcmesh->build1SGTSubLevelMesh();
+}
+
+void MEDFileStructuredMesh::releaseImplicitPartIfAny() const
+{
+  _faces_if_necessary=0;
+}
+
+/*!
+ * Retrieves the internal pointer (no decrRef requested) of the implicit face mesh if any.
+ * To force to build it you can invoke MEDFileStructuredMesh::buildImplicitPartIfAny method.
+ * 
+ * \sa MEDFileStructuredMesh::buildImplicitPartIfAny
+ */
+MEDCoupling1SGTUMesh *MEDFileStructuredMesh::getImplicitFaceMesh() const
+{
+  return _faces_if_necessary;
+}
+
 std::vector<INTERP_KERNEL::NormalizedCellType> MEDFileStructuredMesh::getGeoTypesAtLevel(int meshDimRelToMax) const
 {
   const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
   if(!cmesh)
     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGeoTypesAtLevel : No structured mesh set !");
   switch(meshDimRelToMax)
-    {
+  {
     case 0:
       {
         std::vector<INTERP_KERNEL::NormalizedCellType> ret(1,cmesh->getTypeOfCell(0));
@@ -4744,7 +4902,7 @@ std::vector<INTERP_KERNEL::NormalizedCellType> MEDFileStructuredMesh::getGeoType
       }
     default:
       throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGeoTypesAtLevel : only 2 levels available at most : 0 and -1 !");
-    }
+  }
 }
 
 void MEDFileStructuredMesh::whichAreNodesFetched(const MEDFileField1TSStructItem& st, const MEDFileFieldGlobsReal *globs, std::vector<bool>& nodesFetched) const
@@ -4987,11 +5145,10 @@ std::size_t MEDFileCMesh::getHeapMemorySizeWithoutChildren() const
   return MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren();
 }
 
-std::vector<const BigMemoryObject *> MEDFileCMesh::getDirectChildren() const
+std::vector<const BigMemoryObject *> MEDFileCMesh::getDirectChildrenWithNull() const
 {
-  std::vector<const BigMemoryObject *> ret(MEDFileStructuredMesh::getDirectChildren());
-  if((const MEDCouplingCMesh *)_cmesh)
-    ret.push_back((const MEDCouplingCMesh *)_cmesh);
+  std::vector<const BigMemoryObject *> ret(MEDFileStructuredMesh::getDirectChildrenWithNull());
+  ret.push_back((const MEDCouplingCMesh *)_cmesh);
   return ret;
 }
 
@@ -5110,13 +5267,13 @@ MEDFileCMesh::MEDFileCMesh()
 
 MEDFileCMesh::MEDFileCMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
 try
-  {
+{
     loadCMeshFromFile(fid,mName,dt,it,mrs);
-  }
+}
 catch(INTERP_KERNEL::Exception& e)
-  {
+{
     throw e;
-  }
+}
 
 void MEDFileCMesh::loadCMeshFromFile(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
 {
@@ -5244,11 +5401,10 @@ std::size_t MEDFileCurveLinearMesh::getHeapMemorySizeWithoutChildren() const
   return MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren();
 }
 
-std::vector<const BigMemoryObject *> MEDFileCurveLinearMesh::getDirectChildren() const
+std::vector<const BigMemoryObject *> MEDFileCurveLinearMesh::getDirectChildrenWithNull() const
 {
-  std::vector<const BigMemoryObject *> ret(MEDFileStructuredMesh::getDirectChildren());
-  if((const MEDCouplingCurveLinearMesh *)_clmesh)
-    ret.push_back((const MEDCouplingCurveLinearMesh *)_clmesh);
+  std::vector<const BigMemoryObject *> ret(MEDFileStructuredMesh::getDirectChildrenWithNull());
+  ret.push_back((const MEDCouplingCurveLinearMesh *)_clmesh);
   return ret;
 }
 
@@ -5363,13 +5519,13 @@ MEDFileCurveLinearMesh::MEDFileCurveLinearMesh()
 
 MEDFileCurveLinearMesh::MEDFileCurveLinearMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
 try
-  {
+{
     loadCLMeshFromFile(fid,mName,dt,it,mrs);
-  }
+}
 catch(INTERP_KERNEL::Exception& e)
-  {
+{
     throw e;
-  }
+}
 
 void MEDFileCurveLinearMesh::writeLL(med_idt fid) const
 {
@@ -5399,7 +5555,7 @@ void MEDFileCurveLinearMesh::writeLL(med_idt fid) const
   MEDmeshGridTypeWr(fid,maa,MED_CURVILINEAR_GRID);
   std::vector<int> nodeGridSt=_clmesh->getNodeGridStructure();
   MEDmeshGridStructWr(fid,maa,_iteration,_order,_time,&nodeGridSt[0]);
-  
+
   MEDmeshNodeCoordinateWr(fid,maa,_iteration,_order,_time,MED_FULL_INTERLACE,coords->getNumberOfTuples(),coords->begin());
   //
   std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE));
@@ -5457,15 +5613,11 @@ std::size_t MEDFileMeshMultiTS::getHeapMemorySizeWithoutChildren() const
   return _mesh_one_ts.capacity()*sizeof(MEDCouplingAutoRefCountObjectPtr<MEDFileMesh>);
 }
 
-std::vector<const BigMemoryObject *> MEDFileMeshMultiTS::getDirectChildren() const
+std::vector<const BigMemoryObject *> MEDFileMeshMultiTS::getDirectChildrenWithNull() const
 {
   std::vector<const BigMemoryObject *> ret;
   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
-    {
-      const MEDFileMesh *cur(*it);
-      if(cur)
-        ret.push_back(cur);
-    }
+    ret.push_back((const MEDFileMesh *)*it);
   return ret;
 }
 
@@ -5543,13 +5695,13 @@ MEDFileMeshMultiTS::MEDFileMeshMultiTS()
 
 MEDFileMeshMultiTS::MEDFileMeshMultiTS(const std::string& fileName)
 try
-  {
+{
     std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
     if(ms.empty())
-    {
-      std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
-      throw INTERP_KERNEL::Exception(oss.str().c_str());
-    }
+      {
+        std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
+        throw INTERP_KERNEL::Exception(oss.str().c_str());
+      }
     MEDFileUtilities::CheckFileForRead(fileName);
     MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
     int dt,it;
@@ -5557,21 +5709,21 @@ try
     std::string dummy2;
     MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dt,it,dummy2);
     loadFromFile(fileName,ms.front());
-  }
+}
 catch(INTERP_KERNEL::Exception& e)
-  {
+{
     throw e;
-  }
+}
 
 MEDFileMeshMultiTS::MEDFileMeshMultiTS(const std::string& fileName, const std::string& mName)
 try
-  {
+{
     loadFromFile(fileName,mName);
-  }
+}
 catch(INTERP_KERNEL::Exception& e)
-  {
+{
     throw e;
-  }
+}
 
 MEDFileMeshes *MEDFileMeshes::New()
 {
@@ -5613,6 +5765,7 @@ MEDFileMeshesIterator *MEDFileMeshes::iterator()
   return new MEDFileMeshesIterator(this);
 }
 
+/** Return a borrowed reference (caller is not responsible) */
 MEDFileMesh *MEDFileMeshes::getMeshAtPos(int i) const
 {
   if(i<0 || i>=(int)_meshes.size())
@@ -5623,6 +5776,7 @@ MEDFileMesh *MEDFileMeshes::getMeshAtPos(int i) const
   return _meshes[i]->getOneTimeStep();
 }
 
+/** Return a borrowed reference (caller is not responsible) */
 MEDFileMesh *MEDFileMeshes::getMeshWithName(const std::string& mname) const
 {
   std::vector<std::string> ms=getMeshesNames();
@@ -5718,12 +5872,12 @@ MEDFileMeshes::MEDFileMeshes()
 
 MEDFileMeshes::MEDFileMeshes(const std::string& fileName)
 try
-  {
+{
     loadFromFile(fileName);
-  }
+}
 catch(INTERP_KERNEL::Exception& /*e*/)
-  {
-  }
+{
+}
 
 MEDFileMeshes *MEDFileMeshes::deepCpy() const
 {
@@ -5742,15 +5896,11 @@ std::size_t MEDFileMeshes::getHeapMemorySizeWithoutChildren() const
   return _meshes.capacity()*(sizeof(MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS>));
 }
 
-std::vector<const BigMemoryObject *> MEDFileMeshes::getDirectChildren() const
+std::vector<const BigMemoryObject *> MEDFileMeshes::getDirectChildrenWithNull() const
 {
   std::vector<const BigMemoryObject *> ret;
   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++)
-    {
-      const MEDFileMeshMultiTS *cur(*it);
-      if(cur)
-        ret.push_back(cur);
-    }
+    ret.push_back((const MEDFileMeshMultiTS *)*it);
   return ret;
 }