Salome HOME
On the highway to MEDReader
authorageay <ageay>
Mon, 22 Jul 2013 11:01:19 +0000 (11:01 +0000)
committerageay <ageay>
Mon, 22 Jul 2013 11:01:19 +0000 (11:01 +0000)
src/MEDLoader/MEDFileField.cxx
src/MEDLoader/MEDFileFieldOverView.cxx
src/MEDLoader/MEDFileFieldOverView.hxx
src/MEDLoader/MEDFileMesh.cxx
src/MEDLoader/MEDFileMesh.hxx
src/MEDLoader/MEDFileMeshLL.cxx
src/MEDLoader/MEDFileMeshLL.hxx
src/MEDLoader/Swig/MEDLoaderCommon.i

index 00dbb7b36da4ff76c344082c2da13a2be9e3343f..8ee6fde59dcbc2692b545a262642cae21c0f4af7 100644 (file)
@@ -8327,7 +8327,8 @@ std::vector< std::vector<MEDFileAnyTypeFieldMultiTS *> > MEDFileAnyTypeFieldMult
       MEDFileAnyTypeFieldMultiTS *ref(*it);
       std::vector<MEDFileAnyTypeFieldMultiTS *> elt;
       elt.push_back(ref); it=lstFMTS.erase(it);
-      MEDCouplingAutoRefCountObjectPtr<MEDFileFastCellSupportComparator> cmp(MEDFileFastCellSupportComparator::New(mesh,ref));
+      MEDCouplingAutoRefCountObjectPtr<MEDFileMeshStruct> mst(MEDFileMeshStruct::New(mesh));
+      MEDCouplingAutoRefCountObjectPtr<MEDFileFastCellSupportComparator> cmp(MEDFileFastCellSupportComparator::New(mst,ref));
       while(it!=lstFMTS.end())
         {
           MEDFileAnyTypeFieldMultiTS *curIt(*it);
index f619e410c7034665aa551c44a4b6992a377ce41a..379556249dfc37c98be2b8dc106128920aa053e4 100644 (file)
@@ -26,6 +26,8 @@
 
 using namespace ParaMEDMEM;
 
+const char MEDFileField1TSStructItem2::NEWLY_CREATED_PFL_NAME[]="???";
+
 MEDFileMeshStruct *MEDFileMeshStruct::New(const MEDFileMesh *mesh)
 {
   return new MEDFileMeshStruct(mesh);
@@ -140,6 +142,19 @@ std::string MEDFileField1TSStructItem2::getPflName() const
   return _pfl->getName();
 }
 
+const DataArrayInt *MEDFileField1TSStructItem2::getPfl(const MEDFileFieldGlobsReal *globs) const
+{
+  if(!_pfl->isAllocated())
+    {
+      if(_pfl->getName().empty())
+        return 0;
+      else
+        return globs->getProfile(_pfl->getName().c_str());
+    }
+  else
+    return _pfl;
+}
+
 /*!
  * \param [in] nbOfEntity - number of entity that can be either cells or nodes. Not other possiblity.
  * \param [in] nip - number of integration points. 1 for ON_CELLS and NO_NODES
@@ -171,7 +186,7 @@ bool MEDFileField1TSStructItem2::operator==(const MEDFileField1TSStructItem2& ot
   return _geo_type==other._geo_type && _start_end==other._start_end && _pfl->getName()==other._pfl->getName();
 }
 
-bool MEDFileField1TSStructItem2::isCellSupportEqual(const MEDFileField1TSStructItem2& other) const throw(INTERP_KERNEL::Exception)
+bool MEDFileField1TSStructItem2::isCellSupportEqual(const MEDFileField1TSStructItem2& other, const MEDFileFieldGlobsReal *globs) const throw(INTERP_KERNEL::Exception)
 {
   if(_geo_type!=other._geo_type)
     return false;
@@ -181,7 +196,13 @@ bool MEDFileField1TSStructItem2::isCellSupportEqual(const MEDFileField1TSStructI
     return false;
   if(_pfl->getName().empty() && other._pfl->getName().empty())
     return true;
-  return _pfl->isEqualWithoutConsideringStr(*other._pfl);
+  const DataArrayInt *pfl1(getPfl(globs)),*pfl2(other.getPfl(globs));
+  return pfl1->isEqualWithoutConsideringStr(*pfl2);
+}
+
+bool MEDFileField1TSStructItem2::isNodeSupportEqual(const MEDFileField1TSStructItem2& other, const MEDFileFieldGlobsReal *globs) const throw(INTERP_KERNEL::Exception)
+{
+  return isCellSupportEqual(other,globs);
 }
 
 /*!
@@ -224,7 +245,7 @@ MEDFileField1TSStructItem2 MEDFileField1TSStructItem2::BuildAggregationOf(const
     }
   else
     {
-      arr->setName("???");
+      arr->setName(NEWLY_CREATED_PFL_NAME);
       std::pair<int,int> p(0,oldNbTuples);
       std::string a,b;
       MEDFileField1TSStructItem2 ret(gt,p,a,b);
@@ -297,14 +318,26 @@ bool MEDFileField1TSStructItem::operator==(const MEDFileField1TSStructItem& othe
   return true;
 }
 
-bool MEDFileField1TSStructItem::isCellSupportEqual(const MEDFileField1TSStructItem& other) const throw(INTERP_KERNEL::Exception)
+bool MEDFileField1TSStructItem::isCellSupportEqual(const MEDFileField1TSStructItem& other, const MEDFileFieldGlobsReal *globs) const throw(INTERP_KERNEL::Exception)
+{
+  if(_type!=other._type)
+    return false;
+  if(_items.size()!=other._items.size())
+    return false;
+  for(std::size_t i=0;i<_items.size();i++)
+    if(!(_items[i].isCellSupportEqual(other._items[i],globs)))
+      return false;
+  return true;
+}
+
+bool MEDFileField1TSStructItem::isNodeSupportEqual(const MEDFileField1TSStructItem& other, const MEDFileFieldGlobsReal *globs) const throw(INTERP_KERNEL::Exception)
 {
   if(_type!=other._type)
     return false;
   if(_items.size()!=other._items.size())
     return false;
   for(std::size_t i=0;i<_items.size();i++)
-    if(!(_items[i].isCellSupportEqual(other._items[i])))
+    if(!(_items[i].isNodeSupportEqual(other._items[i],globs)))
       return false;
   return true;
 }
@@ -443,9 +476,19 @@ std::size_t MEDFileField1TSStructItem::getHeapMemorySize() const
   return ret;
 }
 
-MEDCouplingMesh *MEDFileField1TSStructItem::buildFromScratchDataSetSupportOnCells(const MEDFileMeshStruct *mst, const MEDFileFieldGlobsReal *globs) const throw(INTERP_KERNEL::Exception)
+MEDMeshMultiLev *MEDFileField1TSStructItem::buildFromScratchDataSetSupportOnCells(const MEDFileMeshStruct *mst, const MEDFileFieldGlobsReal *globs) const throw(INTERP_KERNEL::Exception)
 {
-  return 0;//tony
+  std::vector<INTERP_KERNEL::NormalizedCellType> a0;
+  std::vector<const DataArrayInt *> a1;
+  std::vector<int> a2;
+  std::size_t i(0);
+  for(std::vector< MEDFileField1TSStructItem2 >::const_iterator it=_items.begin();it!=_items.end();it++,i++)
+    {
+      a0[i]=(*it).getGeo();
+      a1[i]=(*it).getPfl(globs);
+      a2[i]=mst->getNumberOfElemsOfGeoType((*it).getGeo());
+    }
+  return MEDMeshMultiLev::New(mst->getTheMesh(),a0,a1,a2);
 }
 
 //=
@@ -497,12 +540,12 @@ bool MEDFileField1TSStruct::isSupportSameAs(const MEDFileAnyTypeField1TS *other,
   if(found==-1)
     {
       MEDFileField1TSStructItem this1(_already_checked[0].simplifyMeOnCellEntity(other->contentNotNull()));
-      ret=this1.isCellSupportEqual(other1);
+      ret=this1.isCellSupportEqual(other1,other);
       if(ret)
         _already_checked.push_back(this1);
     }
   else
-    ret=_already_checked[found].isCellSupportEqual(other1);
+    ret=_already_checked[found].isCellSupportEqual(other1,other);
   if(ret)
     _already_checked.push_back(b);
   return ret;
@@ -580,27 +623,45 @@ MEDFileField1TSStructItem MEDFileField1TSStruct::BuildItemFrom(const MEDFileAnyT
   return ret;
 }
 
-MEDCouplingMesh *MEDFileField1TSStruct::buildFromScratchDataSetSupport(const MEDFileMeshStruct *mst, const MEDFileFieldGlobsReal *globs) const throw(INTERP_KERNEL::Exception)
+MEDMeshMultiLev *MEDFileField1TSStruct::buildFromScratchDataSetSupport(const MEDFileMeshStruct *mst, const MEDFileFieldGlobsReal *globs) const throw(INTERP_KERNEL::Exception)
 {
   if(_already_checked.empty())
     throw INTERP_KERNEL::Exception("MEDFileField1TSStruct::buildFromScratchDataSetSupport : No outline structure in this !");
   int pos0(-1),pos1(-1);
   if(presenceOfCellDiscr(pos0))
     {
-      if(!presenceOfPartialNodeDiscr(pos1))
-        return _already_checked[pos0].buildFromScratchDataSetSupportOnCells(mst,globs);
-      else
-        throw INTERP_KERNEL::Exception("MEDFileField1TSStruct::buildFromScratchDataSetSupport : tony do it very soon !");
+      MEDCouplingAutoRefCountObjectPtr<MEDMeshMultiLev> ret(_already_checked[pos0].buildFromScratchDataSetSupportOnCells(mst,globs));
+      if(presenceOfPartialNodeDiscr(pos1))
+        ret->setNodeReduction(_already_checked[pos1][0].getPfl(globs));
+      return ret.retn();
     }
   else
     {
       if(!presenceOfPartialNodeDiscr(pos1))
         {//we have only all nodes, no cell definition info -> level 0;
-          return mst->getTheMesh()->getGenMeshAtLevel(0);
+          std::vector<int> levs(1,0);
+          return MEDMeshMultiLev::New(mst->getTheMesh(),levs);
         }
     }
 }
 
+bool MEDFileField1TSStruct::isDataSetSupportFastlyEqualTo(const MEDFileField1TSStruct& other, const MEDFileFieldGlobsReal *globs) const throw(INTERP_KERNEL::Exception)
+{
+  int b0,b1;
+  bool a0(presenceOfCellDiscr(b0)),a1(presenceOfPartialNodeDiscr(b1));
+  int d0,d1;
+  bool c0(other.presenceOfCellDiscr(d0)),c1(other.presenceOfPartialNodeDiscr(d1)); 
+  if(a0!=c0 || a1!=c1)
+    return false;
+  if(a0)
+    if(!_already_checked[b0].isCellSupportEqual(other._already_checked[d0],globs))
+      return false;
+  if(a1)
+    if(!_already_checked[b1].isNodeSupportEqual(other._already_checked[d1],globs))
+      return false;
+  return true;
+}
+
 /*!
  * 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.
@@ -651,14 +712,16 @@ bool MEDFileField1TSStruct::presenceOfPartialNodeDiscr(int& pos) const throw(INT
 
 //=
 
-MEDFileFastCellSupportComparator *MEDFileFastCellSupportComparator::New(const MEDFileMesh *m, const MEDFileAnyTypeFieldMultiTS *ref) throw(INTERP_KERNEL::Exception)
+MEDFileFastCellSupportComparator *MEDFileFastCellSupportComparator::New(const MEDFileMeshStruct *m, const MEDFileAnyTypeFieldMultiTS *ref) throw(INTERP_KERNEL::Exception)
 {
   return new MEDFileFastCellSupportComparator(m,ref);
 }
 
-MEDFileFastCellSupportComparator::MEDFileFastCellSupportComparator(const MEDFileMesh *m, const MEDFileAnyTypeFieldMultiTS *ref)
+MEDFileFastCellSupportComparator::MEDFileFastCellSupportComparator(const MEDFileMeshStruct *m, const MEDFileAnyTypeFieldMultiTS *ref)
 {
-  _mesh_comp=MEDFileMeshStruct::New(m);
+  if(!m)
+    throw INTERP_KERNEL::Exception("MEDFileFastCellSupportComparator constructor : null input mesh struct !");
+  _mesh_comp=const_cast<MEDFileMeshStruct *>(m); _mesh_comp->incrRef();
   int nbPts=ref->getNumberOfTS();
   _f1ts_cmps.resize(nbPts);
   for(int i=0;i<nbPts;i++)
@@ -720,7 +783,7 @@ bool MEDFileFastCellSupportComparator::isCompatibleWithNodesDiscr(const MEDFileA
   return true;
 }
 
-MEDCouplingMesh *MEDFileFastCellSupportComparator::buildFromScratchDataSetSupport(int timeStepId, const MEDFileFieldGlobsReal *globs) const throw(INTERP_KERNEL::Exception)
+MEDMeshMultiLev *MEDFileFastCellSupportComparator::buildFromScratchDataSetSupport(int timeStepId, const MEDFileFieldGlobsReal *globs) const throw(INTERP_KERNEL::Exception)
 {
   if(timeStepId<0 || timeStepId>=(int)_f1ts_cmps.size())
     {
@@ -735,3 +798,215 @@ MEDCouplingMesh *MEDFileFastCellSupportComparator::buildFromScratchDataSetSuppor
     }
   return obj->buildFromScratchDataSetSupport(_mesh_comp,globs);
 }
+
+bool MEDFileFastCellSupportComparator::isDataSetSupportEqualToThePreviousOne(int timeStepId, const MEDFileFieldGlobsReal *globs) const throw(INTERP_KERNEL::Exception)
+{
+  if(timeStepId<=0 || timeStepId>=(int)_f1ts_cmps.size())
+    {
+      std::ostringstream oss; oss << "MEDFileFastCellSupportComparator::isDataSetSupportEqualToThePreviousOne : requested time step id #" << timeStepId << " is not in [1," << _f1ts_cmps.size() << ") !";
+      throw INTERP_KERNEL::Exception(oss.str().c_str());
+    }
+  const MEDFileField1TSStruct *obj(_f1ts_cmps[timeStepId]);
+  const MEDFileField1TSStruct *objRef(_f1ts_cmps[timeStepId-1]);
+  return objRef->isDataSetSupportFastlyEqualTo(*obj,globs);
+}
+
+//=
+
+std::size_t MEDMeshMultiLev::getHeapMemorySize() const
+{
+  return 0;
+}
+
+MEDMeshMultiLev *MEDMeshMultiLev::New(const MEDFileMesh *m, const std::vector<int>& levs) throw(INTERP_KERNEL::Exception)
+{
+  if(!m)
+    throw INTERP_KERNEL::Exception("MEDMeshMultiLev::New : null input pointer !");
+  const MEDFileUMesh *um(dynamic_cast<const MEDFileUMesh *>(m));
+  if(um)
+    return MEDUMeshMultiLev::New(um,levs);
+  const MEDFileCMesh *cm(dynamic_cast<const MEDFileCMesh *>(m));
+  if(cm)
+    return MEDCMeshMultiLev::New(cm,levs);
+  const MEDFileCurveLinearMesh *clm(dynamic_cast<const MEDFileCurveLinearMesh *>(m));
+  if(clm)
+    return MEDCurveLinearMeshMultiLev::New(clm,levs);
+  throw INTERP_KERNEL::Exception("MEDMeshMultiLev::New : unrecognized type of mesh ! Must be in [MEDFileUMesh,MEDFileCMesh,MEDFileCurveLinearMesh] !");
+}
+
+MEDMeshMultiLev *MEDMeshMultiLev::New(const MEDFileMesh *m, const std::vector<INTERP_KERNEL::NormalizedCellType>& gts, const std::vector<const DataArrayInt *>& pfls, const std::vector<int>& nbEntities) throw(INTERP_KERNEL::Exception)
+{
+  if(!m)
+    throw INTERP_KERNEL::Exception("MEDMeshMultiLev::New 2 : null input pointer !");
+  const MEDFileUMesh *um(dynamic_cast<const MEDFileUMesh *>(m));
+  if(um)
+    return MEDUMeshMultiLev::New(um,gts,pfls,nbEntities);
+  const MEDFileCMesh *cm(dynamic_cast<const MEDFileCMesh *>(m));
+  if(cm)
+    return MEDCMeshMultiLev::New(cm,gts,pfls,nbEntities);
+  const MEDFileCurveLinearMesh *clm(dynamic_cast<const MEDFileCurveLinearMesh *>(m));
+  if(clm)
+    return MEDCurveLinearMeshMultiLev::New(clm,gts,pfls,nbEntities);
+  throw INTERP_KERNEL::Exception("MEDMeshMultiLev::New 2 : unrecognized type of mesh ! Must be in [MEDFileUMesh,MEDFileCMesh,MEDFileCurveLinearMesh] !");
+}
+
+void MEDMeshMultiLev::setNodeReduction(const DataArrayInt *nr)
+{
+  if(nr)
+    nr->incrRef();
+  _node_reduction=const_cast<DataArrayInt*>(nr);
+}
+
+MEDMeshMultiLev::MEDMeshMultiLev()
+{
+}
+
+MEDMeshMultiLev::MEDMeshMultiLev(const std::vector<INTERP_KERNEL::NormalizedCellType>& gts, const std::vector<const DataArrayInt *>& pfls, const std::vector<int>& nbEntities):_geo_types(gts),_nb_entities(nbEntities)
+{
+  std::size_t sz(_geo_types.size());
+  if(sz!=pfls.size() || sz!=nbEntities.size())
+    throw INTERP_KERNEL::Exception("MEDMeshMultiLev::MEDMeshMultiLev : input vector must have the same size !");
+  _pfls.resize(sz);
+  for(std::size_t i=0;i<sz;i++)
+    {
+      if(pfls[i])
+        pfls[i]->incrRef();
+      _pfls[i]=const_cast<DataArrayInt *>(pfls[i]);
+    }
+}
+
+MEDUMeshMultiLev *MEDUMeshMultiLev::New(const MEDFileUMesh *m, const std::vector<int>& levs) throw(INTERP_KERNEL::Exception)
+{
+  return new MEDUMeshMultiLev(m,levs);
+}
+
+MEDUMeshMultiLev::MEDUMeshMultiLev(const MEDFileUMesh *m, const std::vector<int>& levs)
+{
+  if(!m)
+    throw INTERP_KERNEL::Exception("MEDUMeshMultiLev constructor : null input pointer !");
+  std::vector<MEDCoupling1GTUMesh *> v;
+  for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
+    {
+      std::vector<MEDCoupling1GTUMesh *> vTmp(m->getDirectUndergroundSingleGeoTypeMeshes(*it));
+      v.insert(v.end(),vTmp.begin(),vTmp.end());
+    }
+  std::size_t sz(v.size());
+  _parts.resize(sz);
+  _pfls.resize(sz);
+  _geo_types.resize(sz);
+  for(std::size_t i=0;i<sz;i++)
+    {
+      MEDCoupling1GTUMesh *obj(v[i]);
+      if(obj)
+        obj->incrRef();
+      else
+        throw INTERP_KERNEL::Exception("MEDUMeshMultiLev constructor : presence of a null pointer !");
+      _parts[i]=obj;
+      _geo_types[i]=obj->getCellModelEnum();
+    }
+}
+
+MEDUMeshMultiLev *MEDUMeshMultiLev::New(const MEDFileUMesh *m, const std::vector<INTERP_KERNEL::NormalizedCellType>& gts, const std::vector<const DataArrayInt *>& pfls, const std::vector<int>& nbEntities) throw(INTERP_KERNEL::Exception)
+{
+  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(gts,pfls,nbEntities)
+{
+  std::size_t sz(gts.size());
+  _parts.resize(sz);
+  for(std::size_t i=0;i<sz;i++)
+    {
+      MEDCoupling1GTUMesh *elt(m->getDirectUndergroundSingleGeoTypeMesh(gts[i]));
+      if(elt)
+        elt->incrRef();
+      _parts[i]=elt;
+    }
+}
+
+MEDCMeshMultiLev *MEDCMeshMultiLev::New(const MEDFileCMesh *m, const std::vector<int>& levs) throw(INTERP_KERNEL::Exception)
+{
+  return new MEDCMeshMultiLev(m,levs);
+}
+
+MEDCMeshMultiLev *MEDCMeshMultiLev::New(const MEDFileCMesh *m, const std::vector<INTERP_KERNEL::NormalizedCellType>& gts, const std::vector<const DataArrayInt *>& pfls, const std::vector<int>& nbEntities) throw(INTERP_KERNEL::Exception)
+{
+  return new MEDCMeshMultiLev(m,gts,pfls,nbEntities);
+}
+
+MEDCMeshMultiLev::MEDCMeshMultiLev(const MEDFileCMesh *m, const std::vector<int>& levs)
+{
+  if(!m)
+    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++)
+    {
+      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;
+    }
+}
+
+MEDCMeshMultiLev::MEDCMeshMultiLev(const MEDFileCMesh *m, const std::vector<INTERP_KERNEL::NormalizedCellType>& gts, const std::vector<const DataArrayInt *>& pfls, const std::vector<int>& nbEntities):MEDMeshMultiLev(gts,pfls,nbEntities)
+{
+  if(!m)
+    throw INTERP_KERNEL::Exception("MEDCMeshMultiLev constructor 2 : null input pointer !");
+  if(gts.size()!=1 || pfls.size()!=1)
+    throw INTERP_KERNEL::Exception("MEDCMeshMultiLev 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("MEDCMeshMultiLev constructor 2 : the unique geo type is invalid regarding meshdim !");
+  _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;
+    }
+}
+
+MEDCurveLinearMeshMultiLev *MEDCurveLinearMeshMultiLev::New(const MEDFileCurveLinearMesh *m, const std::vector<int>& levs) throw(INTERP_KERNEL::Exception)
+{
+  return new MEDCurveLinearMeshMultiLev(m,levs);
+}
+
+MEDCurveLinearMeshMultiLev *MEDCurveLinearMeshMultiLev::New(const MEDFileCurveLinearMesh *m, const std::vector<INTERP_KERNEL::NormalizedCellType>& gts, const std::vector<const DataArrayInt *>& pfls, const std::vector<int>& nbEntities) throw(INTERP_KERNEL::Exception)
+{
+  return new MEDCurveLinearMeshMultiLev(m,gts,pfls,nbEntities);
+}
+
+MEDCurveLinearMeshMultiLev::MEDCurveLinearMeshMultiLev(const MEDFileCurveLinearMesh *m, const std::vector<int>& levs)
+{
+  if(!m)
+    throw INTERP_KERNEL::Exception("MEDCurveLinearMeshMultiLev constructor : null input pointer !");
+  if(levs.size()!=1 || levs[0]!=0)
+    throw INTERP_KERNEL::Exception("MEDCurveLinearMeshMultiLev constructor : levels supported is 0 only !");
+  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();
+}
+
+MEDCurveLinearMeshMultiLev::MEDCurveLinearMeshMultiLev(const MEDFileCurveLinearMesh *m, const std::vector<INTERP_KERNEL::NormalizedCellType>& gts, const std::vector<const DataArrayInt *>& pfls, const std::vector<int>& nbEntities):MEDMeshMultiLev(gts,pfls,nbEntities)
+{
+  if(!m)
+    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();
+}
index 4b864b8ee839dbbaf4bc385e8409090242011049..1a3f2714e97c82334a33b3993124aa16f884d006 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "MEDCouplingAutoRefCountObjectPtr.hxx"
 #include "MEDCouplingRefCountObject.hxx"
+#include "MEDCoupling1GTUMesh.hxx"
 
 #include "NormalizedUnstructuredMesh.hxx"
 #include "InterpKernelException.hxx"
@@ -34,6 +35,9 @@ namespace ParaMEDMEM
   class DataArrayInt;
   class MEDCouplingMesh;
   class MEDFileMesh;
+  class MEDFileUMesh;
+  class MEDFileCMesh;
+  class MEDFileCurveLinearMesh;
   class MEDFileFieldGlobs;
   class MEDFileFieldGlobsReal;
   class MEDFileAnyTypeField1TS;
@@ -57,6 +61,61 @@ namespace ParaMEDMEM
     std::string _name;
     int _nb_nodes;
     std::vector< std::vector<int> > _geo_types_distrib;
+  }; 
+
+  class MEDMeshMultiLev : public RefCountObject
+  {
+  public:
+    std::size_t getHeapMemorySize() const;
+  public:
+    static MEDMeshMultiLev *New(const MEDFileMesh *m, const std::vector<INTERP_KERNEL::NormalizedCellType>& gts, const std::vector<const DataArrayInt *>& pfls, const std::vector<int>& nbEntities) throw(INTERP_KERNEL::Exception);
+    static MEDMeshMultiLev *New(const MEDFileMesh *m, const std::vector<int>& levs) throw(INTERP_KERNEL::Exception);
+    void setNodeReduction(const DataArrayInt *nr);
+  protected:
+    MEDMeshMultiLev();
+    MEDMeshMultiLev(const std::vector<INTERP_KERNEL::NormalizedCellType>& gts, const std::vector<const DataArrayInt *>& pfls, const std::vector<int>& nbEntities);
+    protected:
+    std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > _pfls;
+    std::vector< INTERP_KERNEL::NormalizedCellType > _geo_types;
+    std::vector<int> _nb_entities;
+    MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _node_reduction;
+  };
+
+  class MEDUMeshMultiLev : public MEDMeshMultiLev
+  {
+  public:
+    static MEDUMeshMultiLev *New(const MEDFileUMesh *m, const std::vector<int>& levs) throw(INTERP_KERNEL::Exception);
+    static MEDUMeshMultiLev *New(const MEDFileUMesh *m, const std::vector<INTERP_KERNEL::NormalizedCellType>& gts, const std::vector<const DataArrayInt *>& pfls, const std::vector<int>& nbEntities) throw(INTERP_KERNEL::Exception);
+  private:
+    MEDUMeshMultiLev(const MEDFileUMesh *m, const std::vector<int>& levs);
+    MEDUMeshMultiLev(const MEDFileUMesh *m, const std::vector<INTERP_KERNEL::NormalizedCellType>& gts, const std::vector<const DataArrayInt *>& pfls, const std::vector<int>& nbEntities);
+  private:
+    std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> > _parts;
+  };
+
+  class MEDCMeshMultiLev : public MEDMeshMultiLev
+  {
+  public:
+    static MEDCMeshMultiLev *New(const MEDFileCMesh *m, const std::vector<int>& levs) throw(INTERP_KERNEL::Exception);
+    static MEDCMeshMultiLev *New(const MEDFileCMesh *m, const std::vector<INTERP_KERNEL::NormalizedCellType>& gts, const std::vector<const DataArrayInt *>& pfls, const std::vector<int>& nbEntities) throw(INTERP_KERNEL::Exception);
+  private:
+    MEDCMeshMultiLev(const MEDFileCMesh *m, const std::vector<int>& levs);
+    MEDCMeshMultiLev(const MEDFileCMesh *m, const std::vector<INTERP_KERNEL::NormalizedCellType>& gts, const std::vector<const DataArrayInt *>& pfls, const std::vector<int>& nbEntities);
+  private:
+    std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> > _coords;
+  };
+
+  class MEDCurveLinearMeshMultiLev : public MEDMeshMultiLev
+  {
+  public:
+    static MEDCurveLinearMeshMultiLev *New(const MEDFileCurveLinearMesh *m, const std::vector<int>& levs) throw(INTERP_KERNEL::Exception);
+    static MEDCurveLinearMeshMultiLev *New(const MEDFileCurveLinearMesh *m, const std::vector<INTERP_KERNEL::NormalizedCellType>& gts, const std::vector<const DataArrayInt *>& pfls , const std::vector<int>& nbEntities) throw(INTERP_KERNEL::Exception);
+  private:
+    MEDCurveLinearMeshMultiLev(const MEDFileCurveLinearMesh *m, const std::vector<int>& levs);
+    MEDCurveLinearMeshMultiLev(const MEDFileCurveLinearMesh *m, const std::vector<INTERP_KERNEL::NormalizedCellType>& gts, const std::vector<const DataArrayInt *>& pfls, const std::vector<int>& nbEntities);
+  private:
+    MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> _coords;
+    std::vector<int> _structure;
   };
 
   class MEDFileField1TSStructItem2 : public RefCountObject
@@ -70,13 +129,17 @@ namespace ParaMEDMEM
     //
     std::size_t getHeapMemorySize() const;
     //
+    const DataArrayInt *getPfl(const MEDFileFieldGlobsReal *globs) const;
     INTERP_KERNEL::NormalizedCellType getGeo() const { return _geo_type; }
     std::string getPflName() const;
     //! warning this method also set _nb_of_entity attribute !
     void checkInRange(int nbOfEntity, int nip, const MEDFileFieldGlobs *globs) throw(INTERP_KERNEL::Exception);
     bool operator==(const MEDFileField1TSStructItem2& other) const throw(INTERP_KERNEL::Exception);
-    bool isCellSupportEqual(const MEDFileField1TSStructItem2& other) const throw(INTERP_KERNEL::Exception);
+    bool isCellSupportEqual(const MEDFileField1TSStructItem2& other, const MEDFileFieldGlobsReal *globs) const throw(INTERP_KERNEL::Exception);
+    bool isNodeSupportEqual(const MEDFileField1TSStructItem2& other, const MEDFileFieldGlobsReal *globs) const throw(INTERP_KERNEL::Exception);
     static MEDFileField1TSStructItem2 BuildAggregationOf(const std::vector<const MEDFileField1TSStructItem2 *>& objs, const MEDFileFieldGlobs *globs) throw(INTERP_KERNEL::Exception);
+  public:
+    static const char NEWLY_CREATED_PFL_NAME[];
   private:
     INTERP_KERNEL::NormalizedCellType _geo_type;
     std::pair<int,int> _start_end;
@@ -98,11 +161,12 @@ namespace ParaMEDMEM
     std::size_t getNumberOfItems() const { return _items.size(); }
     const MEDFileField1TSStructItem2& operator[](std::size_t i) const throw(INTERP_KERNEL::Exception);
     //
-    bool isCellSupportEqual(const MEDFileField1TSStructItem& other) const throw(INTERP_KERNEL::Exception);
+    bool isCellSupportEqual(const MEDFileField1TSStructItem& other, const MEDFileFieldGlobsReal *globs) const throw(INTERP_KERNEL::Exception);
+    bool isNodeSupportEqual(const MEDFileField1TSStructItem& other, const MEDFileFieldGlobsReal *globs) const throw(INTERP_KERNEL::Exception);
     MEDFileField1TSStructItem simplifyMeOnCellEntity(const MEDFileFieldGlobs *globs) const throw(INTERP_KERNEL::Exception);
     bool isCompatibleWithNodesDiscr(const MEDFileField1TSStructItem& other, const MEDFileMeshStruct *meshSt, const MEDFileFieldGlobs *globs) const throw(INTERP_KERNEL::Exception);
     bool isFullyOnOneLev(const MEDFileMeshStruct *meshSt, int& theFirstLevFull) const throw(INTERP_KERNEL::Exception);
-    MEDCouplingMesh *buildFromScratchDataSetSupportOnCells(const MEDFileMeshStruct *mst, const MEDFileFieldGlobsReal *globs) const throw(INTERP_KERNEL::Exception);
+    MEDMeshMultiLev *buildFromScratchDataSetSupportOnCells(const MEDFileMeshStruct *mst, const MEDFileFieldGlobsReal *globs) const throw(INTERP_KERNEL::Exception);
   private:
     bool _computed;
     TypeOfField _type;
@@ -118,7 +182,8 @@ namespace ParaMEDMEM
     bool isEqualConsideringThePast(const MEDFileAnyTypeField1TS *other, const MEDFileMeshStruct *mst) const throw(INTERP_KERNEL::Exception);
     bool isSupportSameAs(const MEDFileAnyTypeField1TS *other, const MEDFileMeshStruct *meshSt) throw(INTERP_KERNEL::Exception);
     bool isCompatibleWithNodesDiscr(const MEDFileAnyTypeField1TS *other, const MEDFileMeshStruct *meshSt) throw(INTERP_KERNEL::Exception);
-    MEDCouplingMesh *buildFromScratchDataSetSupport(const MEDFileMeshStruct *mst, const MEDFileFieldGlobsReal *globs) const throw(INTERP_KERNEL::Exception);
+    MEDMeshMultiLev *buildFromScratchDataSetSupport(const MEDFileMeshStruct *mst, const MEDFileFieldGlobsReal *globs) const throw(INTERP_KERNEL::Exception);
+    bool isDataSetSupportFastlyEqualTo(const MEDFileField1TSStruct& other, const MEDFileFieldGlobsReal *globs) const throw(INTERP_KERNEL::Exception);
   private:
     MEDFileField1TSStruct(const MEDFileAnyTypeField1TS *ref, MEDFileMeshStruct *mst);
     static MEDFileField1TSStructItem BuildItemFrom(const MEDFileAnyTypeField1TS *ref, const MEDFileMeshStruct *meshSt);
@@ -131,14 +196,14 @@ namespace ParaMEDMEM
   class MEDFileFastCellSupportComparator : public RefCountObject
   {
   public:
-    static MEDFileFastCellSupportComparator *New(const MEDFileMesh *m, const MEDFileAnyTypeFieldMultiTS *ref) throw(INTERP_KERNEL::Exception);
-    MEDCouplingMesh *buildFromScratchDataSetSupport(int timeStepId, const MEDFileFieldGlobsReal *globs) const throw(INTERP_KERNEL::Exception);
-    bool isDataSetSupportEqualToThePreviousOne(int timeStepId) const throw(INTERP_KERNEL::Exception);
+    static MEDFileFastCellSupportComparator *New(const MEDFileMeshStruct *m, const MEDFileAnyTypeFieldMultiTS *ref) throw(INTERP_KERNEL::Exception);
+    MEDMeshMultiLev *buildFromScratchDataSetSupport(int timeStepId, const MEDFileFieldGlobsReal *globs) const throw(INTERP_KERNEL::Exception);
+    bool isDataSetSupportEqualToThePreviousOne(int timeStepId, const MEDFileFieldGlobsReal *globs) const throw(INTERP_KERNEL::Exception);
     bool isEqual(const MEDFileAnyTypeFieldMultiTS *other) throw(INTERP_KERNEL::Exception);
     bool isCompatibleWithNodesDiscr(const MEDFileAnyTypeFieldMultiTS *other) throw(INTERP_KERNEL::Exception);
     std::size_t getHeapMemorySize() const;
   private:
-    MEDFileFastCellSupportComparator(const MEDFileMesh *m, const MEDFileAnyTypeFieldMultiTS *ref);
+    MEDFileFastCellSupportComparator(const MEDFileMeshStruct *m, const MEDFileAnyTypeFieldMultiTS *ref);
   private:
     MEDCouplingAutoRefCountObjectPtr<MEDFileMeshStruct> _mesh_comp;
     std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileField1TSStruct> > _f1ts_cmps;
index 986265c53d097ecb9b69aa24340ec9f289d49b28..08fdeff0f93ad7d41f7a6eb00d3d1ad4a1f6f4ca 100644 (file)
@@ -2934,6 +2934,29 @@ MEDCouplingUMesh *MEDFileUMesh::getLevelM3Mesh(bool renum) const throw(INTERP_KE
   return getMeshAtLevel(-3,renum);
 }
 
+/*!
+ * This method returns a vector of mesh parts containing each exactly one geometric type.
+ * This method will never launch an automatic computation of split by type (an INTERP_KERNEL::Exception will be then thrown).
+ * This method is only for memory aware users.
+ */
+std::vector<MEDCoupling1GTUMesh *> MEDFileUMesh::getDirectUndergroundSingleGeoTypeMeshes(int meshDimRelToMax) const throw(INTERP_KERNEL::Exception)
+{
+  const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(meshDimRelToMax));
+  return sp->getDirectUndergroundSingleGeoTypeMeshes();
+}
+
+/*!
+ * This method returns the part of \a this having the geometric type \a gt.
+ * If such part is not existing an exception will be thrown.
+ */
+MEDCoupling1GTUMesh *MEDFileUMesh::getDirectUndergroundSingleGeoTypeMesh(INTERP_KERNEL::NormalizedCellType gt) const throw(INTERP_KERNEL::Exception)
+{
+  const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
+  int lev=(int)cm.getDimension()-getMeshDimension();
+  const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(lev));
+  return sp->getDirectUndergroundSingleGeoTypeMesh(gt);
+}
+
 const MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
 {
   if(meshDimRelToMaxExt==1)
index f6fde111334c1c012cbe058ab0334f793af345c3..2df119a3c8edf4c712bfdc9d46b48925cf3085a7 100644 (file)
@@ -238,6 +238,8 @@ namespace ParaMEDMEM
     MEDCouplingUMesh *getLevelM1Mesh(bool renum=false) const throw(INTERP_KERNEL::Exception);
     MEDCouplingUMesh *getLevelM2Mesh(bool renum=false) const throw(INTERP_KERNEL::Exception);
     MEDCouplingUMesh *getLevelM3Mesh(bool renum=false) const throw(INTERP_KERNEL::Exception);
+    std::vector<MEDCoupling1GTUMesh *> getDirectUndergroundSingleGeoTypeMeshes(int meshDimRelToMax) const throw(INTERP_KERNEL::Exception);
+    MEDCoupling1GTUMesh *getDirectUndergroundSingleGeoTypeMesh(INTERP_KERNEL::NormalizedCellType gt) const throw(INTERP_KERNEL::Exception);
     //
     void setFamilyNameAttachedOnId(int id, const std::string& newFamName) throw(INTERP_KERNEL::Exception);
     void setCoords(DataArrayDouble *coords) throw(INTERP_KERNEL::Exception);
index ea4206e0da0807fdea7a9362dcb1a0235c1170da..c5983997e6a8f1dbd4a72d25f4d67152f6d402d3 100644 (file)
@@ -976,20 +976,11 @@ MEDCouplingUMesh *MEDFileUMeshAggregateCompute::getUmesh() const
   return _m;
 }
 
-std::vector<MEDCoupling1GTUMesh *> MEDFileUMeshAggregateCompute::getParts() const
+std::vector<MEDCoupling1GTUMesh *> MEDFileUMeshAggregateCompute::getPartsWithoutComputation() const throw(INTERP_KERNEL::Exception)
 {
-  if(_mp_time>=_m_time)
-    {
-      std::vector<MEDCoupling1GTUMesh *> ret(_m_parts.size());
-      std::size_t i(0);
-      for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> >::const_iterator it=_m_parts.begin();it!=_m_parts.end();it++,i++)
-        {
-          const MEDCoupling1GTUMesh *elt(*it);
-          ret[i]=const_cast<MEDCoupling1GTUMesh *>(elt);
-        }
-      return ret;
-    }
-  forceComputationOfPartsFromUMesh();
+  if(_mp_time<_m_time)
+    throw INTERP_KERNEL::Exception("MEDFileUMeshAggregateCompute::getPartsWithoutComputation : the parts require a computation !");
+  //
   std::vector<MEDCoupling1GTUMesh *> ret(_m_parts.size());
   std::size_t i(0);
   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> >::const_iterator it=_m_parts.begin();it!=_m_parts.end();it++,i++)
@@ -1000,6 +991,26 @@ std::vector<MEDCoupling1GTUMesh *> MEDFileUMeshAggregateCompute::getParts() cons
   return ret;
 }
 
+std::vector<MEDCoupling1GTUMesh *> MEDFileUMeshAggregateCompute::getParts() const
+{
+  if(_mp_time<_m_time)
+    forceComputationOfPartsFromUMesh();
+  return getPartsWithoutComputation();
+}
+
+MEDCoupling1GTUMesh *MEDFileUMeshAggregateCompute::getPartWithoutComputation(INTERP_KERNEL::NormalizedCellType gt) const throw(INTERP_KERNEL::Exception)
+{
+  std::vector<MEDCoupling1GTUMesh *> v(getPartsWithoutComputation());
+  std::size_t sz(v.size());
+  for(std::size_t i=0;i<sz;i++)
+    {
+      if(v[i])
+        if(v[i]->getCellModelEnum()==gt)
+          return v[i];
+    }
+  throw INTERP_KERNEL::Exception("MEDFileUMeshAggregateCompute::getPartWithoutComputation : the geometric type is not existing !");
+}
+
 void MEDFileUMeshAggregateCompute::forceComputationOfPartsFromUMesh() const
 {
   const MEDCouplingUMesh *m(_m);
index 896398aa49050e76ed5f65d44ab0d4056af22a07..9338ea825508c5da07ed1a129bce6fda31c83a7e 100644 (file)
@@ -144,6 +144,8 @@ namespace ParaMEDMEM
     void assignUMesh(MEDCouplingUMesh *m);
     MEDCouplingUMesh *getUmesh() const;
     std::vector<MEDCoupling1GTUMesh *> getParts() const;
+    std::vector<MEDCoupling1GTUMesh *> getPartsWithoutComputation() const throw(INTERP_KERNEL::Exception);
+    MEDCoupling1GTUMesh *getPartWithoutComputation(INTERP_KERNEL::NormalizedCellType gt) const throw(INTERP_KERNEL::Exception);
     std::size_t getTimeOfThis() const;
     std::size_t getHeapMemorySize() const;
     MEDFileUMeshAggregateCompute deepCpy(DataArrayDouble *coords) const;
@@ -189,6 +191,8 @@ namespace ParaMEDMEM
     MEDCouplingUMesh *getFamilyPart(const int *idsBg, const int *idsEnd, bool renum) const;
     DataArrayInt *getFamilyPartArr(const int *idsBg, const int *idsEnd, bool renum) const;
     MEDCouplingUMesh *getWholeMesh(bool renum) const;
+    std::vector<MEDCoupling1GTUMesh *> getDirectUndergroundSingleGeoTypeMeshes() const throw(INTERP_KERNEL::Exception) { return _m_by_types.getPartsWithoutComputation(); }
+    MEDCoupling1GTUMesh *getDirectUndergroundSingleGeoTypeMesh(INTERP_KERNEL::NormalizedCellType gt) const throw(INTERP_KERNEL::Exception) { return _m_by_types.getPartWithoutComputation(gt); }
     DataArrayInt *getOrCreateAndGetFamilyField() throw(INTERP_KERNEL::Exception);
     const DataArrayInt *getFamilyField() const;
     const DataArrayInt *getNumberField() const;
index 43d05e8b86ada3e0bb1925190e3832bd655fd420..d6a0a208302c234724b4eb31561341b9236a51a9 100644 (file)
@@ -97,6 +97,7 @@ using namespace ParaMEDMEM;
 %newobject ParaMEDMEM::MEDFileUMesh::getLevelM1Mesh;
 %newobject ParaMEDMEM::MEDFileUMesh::getLevelM2Mesh;
 %newobject ParaMEDMEM::MEDFileUMesh::getLevelM3Mesh;
+%newobject ParaMEDMEM::MEDFileUMesh::getDirectUndergroundSingleGeoTypeMesh;
 %newobject ParaMEDMEM::MEDFileUMesh::zipCoords;
 %newobject ParaMEDMEM::MEDFileCMesh::New;
 %newobject ParaMEDMEM::MEDFileCurveLinearMesh::New;
@@ -686,6 +687,7 @@ namespace ParaMEDMEM
     MEDCouplingUMesh *getLevelM1Mesh(bool renum=false) const throw(INTERP_KERNEL::Exception);
     MEDCouplingUMesh *getLevelM2Mesh(bool renum=false) const throw(INTERP_KERNEL::Exception);
     MEDCouplingUMesh *getLevelM3Mesh(bool renum=false) const throw(INTERP_KERNEL::Exception);
+    MEDCoupling1GTUMesh *getDirectUndergroundSingleGeoTypeMesh(INTERP_KERNEL::NormalizedCellType gt) const throw(INTERP_KERNEL::Exception);
     //
     void setFamilyNameAttachedOnId(int id, const std::string& newFamName) throw(INTERP_KERNEL::Exception);
     void setCoords(DataArrayDouble *coords) throw(INTERP_KERNEL::Exception);
@@ -767,6 +769,20 @@ namespace ParaMEDMEM
            PyTuple_SetItem(ret,2,SWIG_NewPointerObj(SWIG_as_voidptr(ret2),SWIGTYPE_p_ParaMEDMEM__DataArrayInt, SWIG_POINTER_OWN | 0 ));
            return ret;
          }
+
+         PyObject *getDirectUndergroundSingleGeoTypeMeshes(int meshDimRelToMax) const throw(INTERP_KERNEL::Exception)
+         {
+           std::vector<MEDCoupling1GTUMesh *> tmp(self->getDirectUndergroundSingleGeoTypeMeshes(meshDimRelToMax));
+           std::size_t sz(tmp.size());
+           PyObject *ret=PyList_New(sz);
+           for(std::size_t i=0;i<sz;i++)
+             {
+               if(tmp[i])
+                 tmp[i]->incrRef();
+               PyList_SetItem(ret,i,convertMesh(tmp[i], SWIG_POINTER_OWN | 0 ));
+             }
+           return ret;
+         }
        }
   };