From 177c9fce2f023c08548280236f15aac0f5a77dc1 Mon Sep 17 00:00:00 2001 From: Bernd Flemisch <bernd@iws.uni-stuttgart.de> Date: Thu, 12 Aug 2010 14:27:08 +0000 Subject: [PATCH] finished transport test git-svn-id: svn://svn.iws.uni-stuttgart.de/DUMUX/dumux/trunk@4062 2fb0f335-1f38-0410-981e-8018bf24f1b0 --- dumux/common/timemanager.hh | 3 +- .../2p/transport/fv/fvsaturation2p.hh | 2085 +++++++++-------- .../2p/transport/transportproperties.hh | 35 +- dumux/decoupled/2p/variableclass2p.hh | 2 +- dumux/decoupled/common/onemodelproblem.hh | 20 +- dumux/decoupled/common/variableclass.hh | 57 +- test/decoupled/2p/grids/test_transport.dgf | 11 + test/decoupled/2p/test_transport.cc | 23 +- test/decoupled/2p/test_transport_problem.hh | 6 +- 9 files changed, 1168 insertions(+), 1074 deletions(-) create mode 100644 test/decoupled/2p/grids/test_transport.dgf diff --git a/dumux/common/timemanager.hh b/dumux/common/timemanager.hh index 16d31364dc..ac118299e1 100644 --- a/dumux/common/timemanager.hh +++ b/dumux/common/timemanager.hh @@ -322,8 +322,7 @@ public: if (problem_->shouldWriteOutput()) problem_->writeOutput(); - // advance the simulated time by the current time step - // size + // advance the simulated time by the current time step size Scalar dt = timeStepSize(); time_ += timeStepSize_; ++timeStepIdx_; diff --git a/dumux/decoupled/2p/transport/fv/fvsaturation2p.hh b/dumux/decoupled/2p/transport/fv/fvsaturation2p.hh index fca60f982d..1fd9020beb 100644 --- a/dumux/decoupled/2p/transport/fv/fvsaturation2p.hh +++ b/dumux/decoupled/2p/transport/fv/fvsaturation2p.hh @@ -57,1073 +57,1086 @@ namespace Dumux template<class TypeTag> class FVSaturation2P { - typedef typename GET_PROP_TYPE(TypeTag, PTAG(GridView)) GridView; - typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, PTAG(Problem)) Problem; - typedef typename GET_PROP(TypeTag, PTAG(ReferenceElements)) ReferenceElements; - typedef typename ReferenceElements::Container ReferenceElementContainer; - typedef typename ReferenceElements::ContainerFaces ReferenceElementFaceContainer; - - typedef typename GET_PROP_TYPE(TypeTag, PTAG(DiffusivePart)) DiffusivePart; - typedef typename GET_PROP_TYPE(TypeTag, PTAG(ConvectivePart)) ConvectivePart; - - typedef typename GET_PROP_TYPE(TypeTag, PTAG(SpatialParameters)) SpatialParameters; - typedef typename SpatialParameters::MaterialLaw MaterialLaw; - - typedef typename GET_PROP_TYPE(TypeTag, PTAG(TwoPIndices)) Indices; - - typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidSystem)) FluidSystem; - typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidState)) FluidState; - - enum - { - dim = GridView::dimension, dimWorld = GridView::dimensionworld - }; - enum - { - pw = Indices::pressureW, - pn = Indices::pressureNW, - pglobal = Indices::pressureGlobal, - vw = Indices::velocityW, - vn = Indices::velocityNW, - vt = Indices::velocityTotal, - Sw = Indices::saturationW, - Sn = Indices::saturationNW, - }; - enum - { - wPhaseIdx = Indices::wPhaseIdx, nPhaseIdx = Indices::nPhaseIdx - }; - - typedef typename GET_PROP(TypeTag, PTAG(SolutionTypes)) SolutionTypes; - typedef typename SolutionTypes::ScalarSolution RepresentationType; - typedef typename GridView::Traits::template Codim<0>::Entity Element; - typedef typename GridView::Grid Grid; - typedef typename GridView::template Codim<0>::Iterator ElementIterator; - typedef typename GridView::template Codim<0>::EntityPointer ElementPointer; - typedef typename GridView::IntersectionIterator IntersectionIterator; - - typedef Dune::FieldVector<Scalar, dim> LocalPosition; - typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition; - - DiffusivePart& diffusivePart() - { - return *diffusivePart_; - } - - const DiffusivePart& diffusivePart() const - { - return *diffusivePart_; - } - - ConvectivePart& convectivPart() - { - return *convectivePart_; - } - - const ConvectivePart& convectivePart() const - { - return *convectivePart_; - } - - //function to calculate the time step if a non-wetting phase velocity is used - Scalar evaluateTimeStepPhaseFlux(Scalar timestepFactorIn, Scalar timestepFactorOutNW, Scalar& residualSatW, - Scalar& residualSatNW, int globalIdxI); - - //function to calculate the time step if a total velocity is used - Scalar evaluateTimeStepTotalFlux(Scalar timestepFactorIn, Scalar timestepFactorOut, Scalar diffFactorIn, - Scalar diffFactorOut, Scalar& residualSatW, Scalar& residualSatNW); + typedef typename GET_PROP_TYPE(TypeTag, PTAG(GridView)) GridView; + typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, PTAG(Problem)) Problem; + typedef typename GET_PROP(TypeTag, PTAG(ReferenceElements)) ReferenceElements; + typedef typename ReferenceElements::Container ReferenceElementContainer; + typedef typename ReferenceElements::ContainerFaces ReferenceElementFaceContainer; + + typedef typename GET_PROP_TYPE(TypeTag, PTAG(DiffusivePart)) DiffusivePart; + typedef typename GET_PROP_TYPE(TypeTag, PTAG(ConvectivePart)) ConvectivePart; + + typedef typename GET_PROP_TYPE(TypeTag, PTAG(SpatialParameters)) SpatialParameters; + typedef typename SpatialParameters::MaterialLaw MaterialLaw; + + typedef typename GET_PROP_TYPE(TypeTag, PTAG(TwoPIndices)) Indices; + + typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidSystem)) FluidSystem; + typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidState)) FluidState; + + enum + { + dim = GridView::dimension, dimWorld = GridView::dimensionworld + }; + enum + { + pw = Indices::pressureW, + pn = Indices::pressureNW, + pglobal = Indices::pressureGlobal, + vw = Indices::velocityW, + vn = Indices::velocityNW, + vt = Indices::velocityTotal, + Sw = Indices::saturationW, + Sn = Indices::saturationNW, + }; + enum + { + wPhaseIdx = Indices::wPhaseIdx, nPhaseIdx = Indices::nPhaseIdx + }; + + typedef typename GET_PROP(TypeTag, PTAG(SolutionTypes)) SolutionTypes; + typedef typename SolutionTypes::ScalarSolution RepresentationType; + typedef typename GridView::Traits::template Codim<0>::Entity Element; + typedef typename GridView::Grid Grid; + typedef typename GridView::template Codim<0>::Iterator ElementIterator; + typedef typename GridView::template Codim<0>::EntityPointer ElementPointer; + typedef typename GridView::IntersectionIterator IntersectionIterator; + + typedef Dune::FieldVector<Scalar, dim> LocalPosition; + typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition; + + DiffusivePart& diffusivePart() + { + return *diffusivePart_; + } + + const DiffusivePart& diffusivePart() const + { + return *diffusivePart_; + } + + ConvectivePart& convectivePart() + { + return *convectivePart_; + } + + const ConvectivePart& convectivePart() const + { + return *convectivePart_; + } + + //function to calculate the time step if a non-wetting phase velocity is used + Scalar evaluateTimeStepPhaseFlux(Scalar timestepFactorIn, Scalar timestepFactorOutNW, Scalar& residualSatW, + Scalar& residualSatNW, int globalIdxI); + + //function to calculate the time step if a total velocity is used + Scalar evaluateTimeStepTotalFlux(Scalar timestepFactorIn, Scalar timestepFactorOut, Scalar diffFactorIn, + Scalar diffFactorOut, Scalar& residualSatW, Scalar& residualSatNW); public: - //! Calculate the update vector. - /*! - * \param[in] t time - * \param[in] dt time step size - * \param[in] updateVec vector for the update values - * \param[in] CLFFac security factor for the time step criterion (0 < CLFFac <= 1) - * \param[in] impes variable is true if an impes algorithm is used and false if the transport part is solved independently - * - * This method calculates the update vector \f$ u \f$ of the discretized equation - * \f[ - * S_{n_{new}} = S_{n_{old}} - u, - * \f] - * where \f$ u = \sum_{element faces} \boldsymbol{v}_n * \boldsymbol{n} * A_{element face}\f$, \f$\boldsymbol{n}\f$ is the face normal and \f$A_{element face}\f$ is the face area. - * - * Additionally to the \a update vector, the recommended time step size \a dt is calculated - * employing a CFL condition. - */ - virtual int update(const Scalar t, Scalar& dt, RepresentationType& updateVec, bool impes); - - //! Sets the initial solution \f$S_0\f$. - void initialize(); - - //! Update the values of the material laws and constitutive relations. - /*! - * Constitutive relations like capillary pressure-saturation relationships, mobility-saturation relationships... are updated and stored in the variable class - * of type Dumux::VariableClass2P. The update has to be done when new saturation are available. - */ - void updateMaterialLaws(RepresentationType& saturation, bool iterate); - - //! Constructs a FVSaturationNonWetting2P object - /** - * \param gridView gridView object of type GridView - * \param problem a problem class object - * \param velocityType a string giving the type of velocity used (could be: vn, vt) - * \param diffPart a object of class Dune::DiffusivePart or derived from Dune::DiffusivePart (only used with vt) - */ - - FVSaturation2P(Problem& problem) : - problem_(problem), switchNormals_(false) - { - if (compressibility_ && velocityType_ == vt) - { - DUNE_THROW(Dune::NotImplemented, - "Total velocity - global pressure - model cannot be used with compressible fluids!"); - } - if (saturationType_ != Sw && saturationType_ != Sn) - { - DUNE_THROW(Dune::NotImplemented, "Saturation type not supported!"); - } - if (pressureType_ != pw && pressureType_ != pn && pressureType_ != pglobal) - { - DUNE_THROW(Dune::NotImplemented, "Pressure type not supported!"); - } - if (velocityType_ != vw && velocityType_ != vn && velocityType_ != vt) - { - DUNE_THROW(Dune::NotImplemented, "Velocity type not supported!"); - } - - - diffusivePart_ = new DiffusivePart(problem); - convectivePart_ = new ConvectivePart(problem); - } - - ~FVSaturation2P() - { - delete diffusivePart_; - delete convectivePart_; - } + //! Calculate the update vector. + /*! + * \param[in] t time + * \param[in] dt time step size + * \param[in] updateVec vector for the update values + * \param[in] CLFFac security factor for the time step criterion (0 < CLFFac <= 1) + * \param[in] impes variable is true if an impes algorithm is used and false if the transport part is solved independently + * + * This method calculates the update vector \f$ u \f$ of the discretized equation + * \f[ + * S_{n_{new}} = S_{n_{old}} - u, + * \f] + * where \f$ u = \sum_{element faces} \boldsymbol{v}_n * \boldsymbol{n} * A_{element face}\f$, \f$\boldsymbol{n}\f$ is the face normal and \f$A_{element face}\f$ is the face area. + * + * Additionally to the \a update vector, the recommended time step size \a dt is calculated + * employing a CFL condition. + */ + virtual int update(const Scalar t, Scalar& dt, RepresentationType& updateVec, bool impes); + + //! Sets the initial solution \f$S_0\f$. + void initialize(); + + //! Update the values of the material laws and constitutive relations. + /*! + * Constitutive relations like capillary pressure-saturation relationships, mobility-saturation relationships... are updated and stored in the variable class + * of type Dumux::VariableClass2P. The update has to be done when new saturation are available. + */ + void updateMaterialLaws(RepresentationType& saturation, bool iterate); + + template<class MultiWriter> + void addOutputVtkFields(MultiWriter &writer) + { + problem_.variables().addOutputVtkFields(writer); + return; + } + + // serialization methods + template<class Restarter> + void serialize(Restarter &res) + { + problem_.variables().serialize<Restarter> (res); + } + template<class Restarter> + void deserialize(Restarter &res) + { + problem_.variables().deserialize<Restarter> (res); + } + + //! Constructs a FVSaturationNonWetting2P object + /** + * \param gridView gridView object of type GridView + * \param problem a problem class object + * \param velocityType a string giving the type of velocity used (could be: vn, vt) + * \param diffPart a object of class Dune::DiffusivePart or derived from Dune::DiffusivePart (only used with vt) + */ + + FVSaturation2P(Problem& problem) : + problem_(problem), switchNormals_(false) + { + if (compressibility_ && velocityType_ == vt) + { + DUNE_THROW(Dune::NotImplemented, + "Total velocity - global pressure - model cannot be used with compressible fluids!"); + } + if (saturationType_ != Sw && saturationType_ != Sn) + { + DUNE_THROW(Dune::NotImplemented, "Saturation type not supported!"); + } + if (pressureType_ != pw && pressureType_ != pn && pressureType_ != pglobal) + { + DUNE_THROW(Dune::NotImplemented, "Pressure type not supported!"); + } + if (velocityType_ != vw && velocityType_ != vn && velocityType_ != vt) + { + DUNE_THROW(Dune::NotImplemented, "Velocity type not supported!"); + } + + + diffusivePart_ = new DiffusivePart(problem); + convectivePart_ = new ConvectivePart(problem); + } + + ~FVSaturation2P() + { + delete diffusivePart_; + delete convectivePart_; + } private: - Problem& problem_; - DiffusivePart* diffusivePart_; - ConvectivePart* convectivePart_; - - static const bool compressibility_ = GET_PROP_VALUE(TypeTag, PTAG(EnableCompressibility)); - ; - static const int saturationType_ = GET_PROP_VALUE(TypeTag, PTAG(SaturationFormulation)); - static const int velocityType_ = GET_PROP_VALUE(TypeTag, PTAG(VelocityFormulation)); - static const int pressureType_ = GET_PROP_VALUE(TypeTag, PTAG(PressureFormulation)); - bool switchNormals_; + Problem& problem_; + DiffusivePart* diffusivePart_; + ConvectivePart* convectivePart_; + + static const bool compressibility_ = GET_PROP_VALUE(TypeTag, PTAG(EnableCompressibility)); + ; + static const int saturationType_ = GET_PROP_VALUE(TypeTag, PTAG(SaturationFormulation)); + static const int velocityType_ = GET_PROP_VALUE(TypeTag, PTAG(VelocityFormulation)); + static const int pressureType_ = GET_PROP_VALUE(TypeTag, PTAG(PressureFormulation)); + bool switchNormals_; }; template<class TypeTag> int FVSaturation2P<TypeTag>::update(const Scalar t, Scalar& dt, RepresentationType& updateVec, bool impes = false) { - if (!impes) - { - updateMaterialLaws(); - } + if (!impes) + { + updateMaterialLaws(); + } - // initialize dt very large - dt = 1E100; + // initialize dt very large + dt = 1E100; - // set update vector to zero - updateVec = 0; + // set update vector to zero + updateVec = 0; - // some phase properties - Dune::FieldVector<Scalar, dimWorld> gravity = problem_.gravity(); + // some phase properties + Dune::FieldVector<Scalar, dimWorld> gravity = problem_.gravity(); - // compute update vector - ElementIterator eItEnd = problem_.gridView().template end<0> (); - for (ElementIterator eIt = problem_.gridView().template begin<0> (); eIt != eItEnd; ++eIt) - { - // cell geometry type - Dune::GeometryType gt = eIt->geometry().type(); + // compute update vector + ElementIterator eItEnd = problem_.gridView().template end<0> (); + for (ElementIterator eIt = problem_.gridView().template begin<0> (); eIt != eItEnd; ++eIt) + { + // cell geometry type + Dune::GeometryType gt = eIt->geometry().type(); - // cell center in reference element - const LocalPosition &localPos = ReferenceElementContainer::general(gt).position(0, 0); + // cell center in reference element + const LocalPosition &localPos = ReferenceElementContainer::general(gt).position(0, 0); - // - GlobalPosition globalPos = eIt->geometry().global(localPos); + // + GlobalPosition globalPos = eIt->geometry().global(localPos); - // cell volume, assume linear map here - Scalar volume = eIt->geometry().volume(); + // cell volume, assume linear map here + Scalar volume = eIt->geometry().volume(); - // cell index - int globalIdxI = problem_.variables().index(*eIt); + // cell index + int globalIdxI = problem_.variables().index(*eIt); - Scalar residualSatW = problem_.spatialParameters().materialLawParams(globalPos, *eIt).Swr(); - Scalar residualSatNW = problem_.spatialParameters().materialLawParams(globalPos, *eIt).Snr(); - - //for benchmark only! - // problem_.variables().storeSrn(residualSatNW, globalIdxI); - //for benchmark only! - - Scalar porosity = problem_.spatialParameters().porosity(globalPos, *eIt); - - Scalar viscosityWI = problem_.variables().viscosityWetting(globalIdxI); - Scalar viscosityNWI = problem_.variables().viscosityNonwetting(globalIdxI); - Scalar viscosityRatio = 1 - fabs(0.5 - viscosityNWI / (viscosityWI + viscosityNWI));//1 - fabs(viscosityWI-viscosityNWI)/(viscosityWI+viscosityNWI); - - Scalar densityWI = problem_.variables().densityWetting(globalIdxI); - Scalar densityNWI = problem_.variables().densityNonwetting(globalIdxI); - - Scalar lambdaWI = problem_.variables().mobilityWetting(globalIdxI); - Scalar lambdaNWI = problem_.variables().mobilityNonwetting(globalIdxI); - - Scalar timestepFactorIn = 0; - Scalar timestepFactorOut = 0; - Scalar diffFactorIn = 0; - Scalar diffFactorOut = 0; - - // run through all intersections with neighbors and boundary - IntersectionIterator isItEnd = problem_.gridView().iend(*eIt); - for (IntersectionIterator isIt = problem_.gridView().ibegin(*eIt); isIt != isItEnd; ++isIt) - { - // local number of facet - int isIndex = isIt->indexInInside(); - - // get geometry type of face - Dune::GeometryType faceGT = isIt->geometryInInside().type(); - - // center in face's reference element - const Dune::FieldVector<Scalar, dim - 1>& faceLocal = - ReferenceElementFaceContainer::general(faceGT).position(0, 0); - - // center of face inside volume reference element - const LocalPosition localPosFace(0); - - Dune::FieldVector<Scalar, dimWorld> unitOuterNormal = isIt->unitOuterNormal(faceLocal); - if (switchNormals_) - unitOuterNormal *= -1.0; - - Scalar faceArea = isIt->geometry().volume(); - - Scalar factor = 0; - Scalar factorSecondPhase = 0; - - // handle interior face - if (isIt->neighbor()) - { - // access neighbor - ElementPointer neighborPointer = isIt->outside(); - int globalIdxJ = problem_.variables().index(*neighborPointer); - - // compute factor in neighbor - Dune::GeometryType neighborGT = neighborPointer->geometry().type(); - const LocalPosition& localPosNeighbor = ReferenceElementContainer::general(neighborGT).position(0, 0); - - // cell center in global coordinates - const GlobalPosition& globalPos = eIt->geometry().global(localPos); - - // neighbor cell center in global coordinates - const GlobalPosition& globalPosNeighbor = neighborPointer->geometry().global(localPosNeighbor); - - // distance vector between barycenters - Dune::FieldVector<Scalar, dimWorld> distVec = globalPosNeighbor - globalPos; - // compute distance between cell centers - Scalar dist = distVec.two_norm(); - - Dune::FieldVector<Scalar, dimWorld> unitDistVec(distVec); - unitDistVec /= dist; - - //get phase potentials - Scalar potentialW = problem_.variables().potentialWetting(globalIdxI, isIndex); - Scalar potentialNW = problem_.variables().potentialNonwetting(globalIdxI, isIndex); - - Scalar densityWJ = problem_.variables().densityWetting(globalIdxJ); - Scalar densityNWJ = problem_.variables().densityNonwetting(globalIdxJ); - - //get velocity*normalvector*facearea/(volume*porosity) - factor = (problem_.variables().velocity()[globalIdxI][isIndex] * unitDistVec) * (faceArea - * (unitOuterNormal * unitDistVec)) / (volume * porosity); - factorSecondPhase = (problem_.variables().velocitySecondPhase()[globalIdxI][isIndex] * unitDistVec) - * (faceArea * (unitOuterNormal * unitDistVec)) / (volume * porosity); - - Scalar lambdaW = 0; - Scalar lambdaNW = 0; - Scalar viscosityW = 0; - Scalar viscosityNW = 0; - - //upwinding of lambda dependend on the phase potential gradients - if (potentialW >= 0.) - { - lambdaW = lambdaWI; - if (compressibility_) - { - lambdaW /= densityWI; - }//divide by density because lambda is saved as lambda*density - viscosityW = viscosityWI; - } - else - { - lambdaW = problem_.variables().mobilityWetting(globalIdxJ); - if (compressibility_) - { - lambdaW /= densityWJ; - }//divide by density because lambda is saved as lambda*density - viscosityW = problem_.variables().viscosityWetting(globalIdxJ); - } - - if (potentialNW >= 0.) - { - lambdaNW = lambdaNWI; - if (compressibility_) - { - lambdaNW /= densityNWI; - }//divide by density because lambda is saved as lambda*density - viscosityNW = viscosityNWI; - } - else - { - lambdaNW = problem_.variables().mobilityNonwetting(globalIdxJ); - if (compressibility_) - { - lambdaNW /= densityNWJ; - }//divide by density because lambda is saved as lambda*density - viscosityNW = problem_.variables().viscosityNonwetting(globalIdxJ); - } - Scalar krSum = lambdaW * viscosityW + lambdaNW * viscosityNW; - - switch (velocityType_) - { - case vt: - { - //for time step criterion - - if (factor >= 0) - { - timestepFactorOut += factor / (krSum * viscosityRatio); - } - if (factor < 0) - { - timestepFactorIn -= factor / (krSum * viscosityRatio); - } - - //determine phase saturations from primary saturation variable - Scalar satWI = 0; - Scalar satWJ = 0; - switch (saturationType_) - { - case Sw: - { - satWI = problem_.variables().saturation()[globalIdxI]; - satWJ = problem_.variables().saturation()[globalIdxJ]; - break; - } - case Sn: - { - satWI = 1 - problem_.variables().saturation()[globalIdxI]; - satWJ = 1 - problem_.variables().saturation()[globalIdxJ]; - break; - } - } - - Scalar pcI = problem_.variables().capillaryPressure(globalIdxI); - Scalar pcJ = problem_.variables().capillaryPressure(globalIdxJ); - - // calculate the saturation gradient - Dune::FieldVector<Scalar, dimWorld> pcGradient = unitDistVec; - pcGradient *= (pcI - pcJ) / dist; - - // get the diffusive part -> give 1-sat because sat = S_n and lambda = lambda(S_w) and pc = pc(S_w) - Scalar diffPart = diffusivePart()(*eIt, isIndex, satWI, satWJ, pcGradient) * unitDistVec * faceArea - / (volume * porosity) * (unitOuterNormal * unitDistVec); - Scalar convPart = convectivePart() (*eIt, isIndex, satWI, satWJ) * unitDistVec * faceArea / (volume * porosity) * (unitOuterNormal * unitDistVec); - - //for time step criterion - if (diffPart >= 0) - { - diffFactorIn += diffPart / (krSum * viscosityRatio); - } - if (diffPart < 0) - { - diffFactorOut -= diffPart / (krSum * viscosityRatio); - } - if (convPart >= 0) - { - timestepFactorOut += convPart / (krSum * viscosityRatio); - } - if (convPart < 0) - { - timestepFactorIn -= convPart / (krSum * viscosityRatio); - } - - switch (saturationType_) - { - case Sw: - { - //vt*fw - factor *= lambdaW / (lambdaW + lambdaNW); - break; - } - case Sn: - { - //vt*fn - factor *= lambdaNW / (lambdaW + lambdaNW); - break; - } - } - factor -= diffPart; - factor += convPart; - break; - } - case vw: - { - if (compressibility_) - { - factor /= densityWI; - factorSecondPhase /= densityNWI; - } - - //for time step criterion - if (factor >= 0) - { - timestepFactorOut += factor / (krSum * viscosityRatio); - } - if (factor < 0) - { - timestepFactorIn -= factor / (krSum * viscosityRatio); - } - if (factorSecondPhase < 0) - { - timestepFactorIn -= factorSecondPhase / (krSum * viscosityRatio); - } - - if (std::isnan(timestepFactorIn) || std::isinf(timestepFactorIn)) - { - timestepFactorIn = 1e-100; - } - break; - } - - //for time step criterion if the non-wetting phase velocity is used - case vn: - { - if (compressibility_) - { - factor /= densityNWI; - factorSecondPhase /= densityWI; - } - - //for time step criterion - if (factor >= 0) - { - timestepFactorOut += factor / (krSum * viscosityRatio); - } - if (factor < 0) - { - timestepFactorIn -= factor / (krSum * viscosityRatio); - } - if (factorSecondPhase < 0) - { - timestepFactorIn -= factorSecondPhase / (krSum * viscosityRatio); - } - - if (std::isnan(timestepFactorIn) || std::isinf(timestepFactorIn)) - { - timestepFactorIn = 1e-100; - } - break; - } - } - }//end intersection with neighbor element - - // handle boundary face - if (isIt->boundary()) - { - // center of face in global coordinates - GlobalPosition globalPosFace = isIt->geometry().global(faceLocal); - - // cell center in global coordinates - GlobalPosition globalPos = eIt->geometry().global(localPos); - - // distance vector between barycenters - Dune::FieldVector<Scalar, dimWorld> distVec = globalPosFace - globalPos; - // compute distance between cell centers - Scalar dist = distVec.two_norm(); - - Dune::FieldVector<Scalar, dimWorld> unitDistVec(distVec); - unitDistVec /= dist; - - //get boundary type - BoundaryConditions::Flags bcTypeSat = problem_.bctypeSat(globalPosFace, *isIt); - - if (bcTypeSat == BoundaryConditions::dirichlet) - { - Scalar satBound = problem_.dirichletSat(globalPosFace, *isIt); - - //get velocity*normalvector*facearea/(volume*porosity) - factor = (problem_.variables().velocity()[globalIdxI][isIndex] * unitDistVec) * (faceArea - * (unitOuterNormal * unitDistVec)) / (volume * porosity); - factorSecondPhase = (problem_.variables().velocitySecondPhase()[globalIdxI][isIndex] * unitDistVec) - * (faceArea * (unitOuterNormal * unitDistVec)) / (volume * porosity); - - Scalar pressBound = problem_.variables().pressure()[globalIdxI]; - Scalar temperature = problem_.temperature(globalPosFace, *eIt); - - //determine phase saturations from primary saturation variable - Scalar satWI = 0; - Scalar satWBound = 0; - switch (saturationType_) - { - case Sw: - { - satWI = problem_.variables().saturation()[globalIdxI]; - satWBound = satBound; - break; - } - case Sn: - { - satWI = 1 - problem_.variables().saturation()[globalIdxI]; - satWBound = 1 - satBound; - break; - } - } - - Scalar pcBound = MaterialLaw::pC(problem_.spatialParameters().materialLawParams(globalPos, *eIt), - satBound); - - //determine phase pressures from primary pressure variable - Scalar pressW = 0; - Scalar pressNW = 0; - switch (pressureType_) - { - case pw: - { - pressW = pressBound; - pressNW = pressBound + pcBound; - break; - } - case pn: - { - pressW = pressBound - pcBound; - pressNW = pressBound; - break; - } - } - - FluidState fluidState; - fluidState.update(satBound, pressW, pressNW, temperature); - - //get phase potentials - Scalar potentialW = problem_.variables().potentialWetting(globalIdxI, isIndex); - Scalar potentialNW = problem_.variables().potentialNonwetting(globalIdxI, isIndex); - - Scalar lambdaW = 0; - Scalar lambdaNW = 0; - - //upwinding of lambda dependend on the phase potential gradients - if (potentialW > 0.) - { - lambdaW = lambdaWI; - if (compressibility_) - { - lambdaW /= densityWI; - }//divide by density because lambda is saved as lambda*density - } - else - { - if (compressibility_) - { - lambdaW = MaterialLaw::krw(problem_.spatialParameters().materialLawParams(globalPos, *eIt), - satWBound) / FluidSystem::phaseViscosity(wPhaseIdx, temperature, pressW, fluidState); - } - else - { - lambdaW = MaterialLaw::krw(problem_.spatialParameters().materialLawParams(globalPos, *eIt), - satWBound) / viscosityWI; - } - } - - if (potentialNW >= 0.) - { - lambdaNW = lambdaNWI; - if (compressibility_) - { - lambdaNW /= densityNWI; - }//divide by density because lambda is saved as lambda*density - } - else - { - if (compressibility_) - { - lambdaNW = MaterialLaw::krn( - problem_.spatialParameters().materialLawParams(globalPos, *eIt), satWBound) - / FluidSystem::phaseViscosity(nPhaseIdx, temperature, pressNW, fluidState); - } - else - { - lambdaNW = MaterialLaw::krn( - problem_.spatialParameters().materialLawParams(globalPos, *eIt), satWBound) - / viscosityNWI; - } - } - // std::cout<<lambdaW<<" "<<lambdaNW<<std::endl; - - Scalar krSum = lambdaW * viscosityWI + lambdaNW * viscosityNWI; - - switch (velocityType_) - { - case vt: - { - //for time step criterion - - if (factor >= 0) - { - timestepFactorOut += factor / (krSum * viscosityRatio); - } - if (factor < 0) - { - timestepFactorIn -= factor / (krSum * viscosityRatio); - } - - Scalar pcI = problem_.variables().capillaryPressure(globalIdxI); - - // calculate the saturation gradient - Dune::FieldVector<Scalar, dimWorld> pcGradient = unitDistVec; - pcGradient *= (pcI - pcBound) / dist; - - // get the diffusive part -> give 1-sat because sat = S_n and lambda = lambda(S_w) and pc = pc(S_w) - Scalar diffPart = diffusivePart()(*eIt, isIndex, satWI, satWBound, pcGradient) * unitDistVec - * faceArea / (volume * porosity) * (unitOuterNormal * unitDistVec); - Scalar convPart = convectivePart()(*eIt, isIndex, satWI, satWBound) * unitDistVec * faceArea / (volume * porosity) * (unitOuterNormal * unitDistVec); - - //for time step criterion - if (diffPart >= 0) - { - diffFactorIn += diffPart / (krSum * viscosityRatio); - } - if (diffPart < 0) - { - diffFactorOut -= diffPart / (krSum * viscosityRatio); - } - if (convPart >= 0) - { - timestepFactorOut += convPart / (krSum * viscosityRatio); - } - if (convPart < 0) - { - timestepFactorIn -= convPart / (krSum * viscosityRatio); - } - - switch (saturationType_) - { - case Sw: - { - //vt*fw - factor *= lambdaW / (lambdaW + lambdaNW); - break; - } - case Sn: - { - //vt*fn - factor *= lambdaNW / (lambdaW + lambdaNW); - break; - } - } - //vt*fw - factor -= diffPart; - factor += convPart; - break; - } - - case vw: - { - if (compressibility_) - { - factor /= densityWI; - factorSecondPhase /= densityNWI; - } - - //for time step criterion - if (factor >= 0) - { - timestepFactorOut += factor / (krSum * viscosityRatio); - } - if (factor < 0) - { - timestepFactorIn -= factor / (krSum * viscosityRatio); - } - if (factorSecondPhase < 0) - { - timestepFactorIn -= factorSecondPhase / (krSum * viscosityRatio); - } - - if (std::isnan(timestepFactorIn) || std::isinf(timestepFactorIn)) - { - timestepFactorIn = 1e-100; - } - break; - } - - //for time step criterion if the non-wetting phase velocity is used - case vn: - { - if (compressibility_) - { - factor /= densityNWI; - factorSecondPhase /= densityWI; - } - - //for time step criterion - if (factor >= 0) - { - timestepFactorOut += factor / (krSum * viscosityRatio); - } - if (factor < 0) - { - timestepFactorIn -= factor / (krSum * viscosityRatio); - } - if (factorSecondPhase < 0) - { - timestepFactorIn -= factorSecondPhase / (krSum * viscosityRatio); - } - - if (std::isnan(timestepFactorIn) || std::isinf(timestepFactorIn)) - { - timestepFactorIn = 1e-100; - } - break; - } - } - }//end dirichlet boundary - - if (bcTypeSat == BoundaryConditions::neumann) - { - //get mobilities - Scalar lambdaW, lambdaNW; - - lambdaW = lambdaWI; - if (compressibility_) - { - lambdaW /= densityWI; - } - - lambdaNW = lambdaNWI; - if (compressibility_) - { - lambdaNW /= densityNWI; - } - - Scalar krSum = lambdaW * viscosityWI + lambdaNW * viscosityNWI; - - //get velocity*normalvector*facearea/(volume*porosity) - factor = (problem_.variables().velocity()[globalIdxI][isIndex] * unitOuterNormal) * faceArea - / (volume * porosity); - switch (velocityType_) - { - case vt: - { - switch (saturationType_) - { - case Sw: - { - //vt*fw - factor *= lambdaW / (lambdaW + lambdaNW); - break; - } - case Sn: - { - //vt*fn - factor *= lambdaNW / (lambdaW + lambdaNW); - break; - } - } - break; - } - } - Scalar boundaryFactor = problem_.neumannSat(globalPosFace, *isIt, factor); - - if (factor != boundaryFactor) - { - switch (saturationType_) - { - case Sw: - { - factor = boundaryFactor / densityWI * faceArea / (volume * porosity); - break; - } - case Sn: - { - factor = boundaryFactor / densityNWI * faceArea / (volume * porosity); - break; - } - } - } - - //for time step criterion - - if (factor >= 0) - { - timestepFactorOut += factor / (krSum * viscosityRatio); - } - if (factor < 0) - { - timestepFactorIn -= factor / (krSum * viscosityRatio); - } - }//end neumann boundary - }//end boundary - // add to update vector - updateVec[globalIdxI] -= factor;//-:v>0, if flow leaves the cell - }// end all intersections - Scalar source = 0; - switch (velocityType_) - { - case vw: - { - source = problem_.source(globalPos, *eIt)[wPhaseIdx] / densityWI; - break; - } - case vn: - { - source = problem_.source(globalPos, *eIt)[nPhaseIdx] / densityNWI; - break; - } - case vt: - { - source = problem_.source(globalPos, *eIt)[wPhaseIdx] / densityWI + problem_.source(globalPos, - *eIt)[nPhaseIdx] / densityNWI; - break; - } - } - if (source) - { - //get mobilities - Scalar lambdaW = 0; - Scalar lambdaNW = 0; - - lambdaW = lambdaWI; - if (compressibility_) - { - lambdaW /= densityWI; - } - lambdaNW = lambdaNWI; - if (compressibility_) - { - lambdaNW /= densityNWI; - } - - Scalar krSum = lambdaW * viscosityWI + lambdaNW * viscosityNWI; - switch (saturationType_) - { - case Sw: - { - updateVec[globalIdxI] += source / porosity; - break; - } - case Sn: - { - updateVec[globalIdxI] += source / porosity; - break; - } - } - if (source >= 0) - { - timestepFactorIn += source / (porosity * viscosityRatio * krSum); - } - else - { - timestepFactorOut -= source / (porosity * viscosityRatio * krSum); - } - } - - //calculate time step - if (velocityType_ == vw || velocityType_ == vn) - { - dt = std::min(dt, evaluateTimeStepPhaseFlux(timestepFactorIn, timestepFactorOut, residualSatW, - residualSatNW, globalIdxI)); - } - if (velocityType_ == vt) - { - dt = std::min(dt, evaluateTimeStepTotalFlux(timestepFactorIn, timestepFactorOut, diffFactorIn, - diffFactorOut, residualSatW, residualSatNW)); - } - - problem_.variables().volumecorrection(globalIdxI) = updateVec[globalIdxI]; - } // end grid traversal - - return 0; + Scalar residualSatW = problem_.spatialParameters().materialLawParams(globalPos, *eIt).Swr(); + Scalar residualSatNW = problem_.spatialParameters().materialLawParams(globalPos, *eIt).Snr(); + + //for benchmark only! + // problem_.variables().storeSrn(residualSatNW, globalIdxI); + //for benchmark only! + + Scalar porosity = problem_.spatialParameters().porosity(globalPos, *eIt); + + Scalar viscosityWI = problem_.variables().viscosityWetting(globalIdxI); + Scalar viscosityNWI = problem_.variables().viscosityNonwetting(globalIdxI); + Scalar viscosityRatio = 1 - fabs(0.5 - viscosityNWI / (viscosityWI + viscosityNWI));//1 - fabs(viscosityWI-viscosityNWI)/(viscosityWI+viscosityNWI); + + Scalar densityWI = problem_.variables().densityWetting(globalIdxI); + Scalar densityNWI = problem_.variables().densityNonwetting(globalIdxI); + + Scalar lambdaWI = problem_.variables().mobilityWetting(globalIdxI); + Scalar lambdaNWI = problem_.variables().mobilityNonwetting(globalIdxI); + + Scalar timestepFactorIn = 0; + Scalar timestepFactorOut = 0; + Scalar diffFactorIn = 0; + Scalar diffFactorOut = 0; + + // run through all intersections with neighbors and boundary + IntersectionIterator isItEnd = problem_.gridView().iend(*eIt); + for (IntersectionIterator isIt = problem_.gridView().ibegin(*eIt); isIt != isItEnd; ++isIt) + { + // local number of facet + int isIndex = isIt->indexInInside(); + + // get geometry type of face + Dune::GeometryType faceGT = isIt->geometryInInside().type(); + + // center in face's reference element + const Dune::FieldVector<Scalar, dim - 1>& faceLocal = + ReferenceElementFaceContainer::general(faceGT).position(0, 0); + + // center of face inside volume reference element + const LocalPosition localPosFace(0); + + Dune::FieldVector<Scalar, dimWorld> unitOuterNormal = isIt->unitOuterNormal(faceLocal); + if (switchNormals_) + unitOuterNormal *= -1.0; + + Scalar faceArea = isIt->geometry().volume(); + + Scalar factor = 0; + Scalar factorSecondPhase = 0; + + // handle interior face + if (isIt->neighbor()) + { + // access neighbor + ElementPointer neighborPointer = isIt->outside(); + int globalIdxJ = problem_.variables().index(*neighborPointer); + + // compute factor in neighbor + Dune::GeometryType neighborGT = neighborPointer->geometry().type(); + const LocalPosition& localPosNeighbor = ReferenceElementContainer::general(neighborGT).position(0, 0); + + // cell center in global coordinates + const GlobalPosition& globalPos = eIt->geometry().global(localPos); + + // neighbor cell center in global coordinates + const GlobalPosition& globalPosNeighbor = neighborPointer->geometry().global(localPosNeighbor); + + // distance vector between barycenters + Dune::FieldVector<Scalar, dimWorld> distVec = globalPosNeighbor - globalPos; + // compute distance between cell centers + Scalar dist = distVec.two_norm(); + + Dune::FieldVector<Scalar, dimWorld> unitDistVec(distVec); + unitDistVec /= dist; + + //get phase potentials + Scalar potentialW = problem_.variables().potentialWetting(globalIdxI, isIndex); + Scalar potentialNW = problem_.variables().potentialNonwetting(globalIdxI, isIndex); + + Scalar densityWJ = problem_.variables().densityWetting(globalIdxJ); + Scalar densityNWJ = problem_.variables().densityNonwetting(globalIdxJ); + + //get velocity*normalvector*facearea/(volume*porosity) + factor = (problem_.variables().velocity()[globalIdxI][isIndex] * unitOuterNormal) + * (faceArea) / (volume * porosity); + factorSecondPhase = (problem_.variables().velocitySecondPhase()[globalIdxI][isIndex] * unitOuterNormal) + * (faceArea) / (volume * porosity); + + Scalar lambdaW = 0; + Scalar lambdaNW = 0; + Scalar viscosityW = 0; + Scalar viscosityNW = 0; + + //upwinding of lambda dependend on the phase potential gradients + if (potentialW >= 0.) + { + lambdaW = lambdaWI; + if (compressibility_) + { + lambdaW /= densityWI; + }//divide by density because lambda is saved as lambda*density + viscosityW = viscosityWI; + } + else + { + lambdaW = problem_.variables().mobilityWetting(globalIdxJ); + if (compressibility_) + { + lambdaW /= densityWJ; + }//divide by density because lambda is saved as lambda*density + viscosityW = problem_.variables().viscosityWetting(globalIdxJ); + } + + if (potentialNW >= 0.) + { + lambdaNW = lambdaNWI; + if (compressibility_) + { + lambdaNW /= densityNWI; + }//divide by density because lambda is saved as lambda*density + viscosityNW = viscosityNWI; + } + else + { + lambdaNW = problem_.variables().mobilityNonwetting(globalIdxJ); + if (compressibility_) + { + lambdaNW /= densityNWJ; + }//divide by density because lambda is saved as lambda*density + viscosityNW = problem_.variables().viscosityNonwetting(globalIdxJ); + } + Scalar krSum = lambdaW * viscosityW + lambdaNW * viscosityNW; + + switch (velocityType_) + { + case vt: + { + //for time step criterion + + if (factor >= 0) + { + timestepFactorOut += factor / (krSum * viscosityRatio); + } + if (factor < 0) + { + timestepFactorIn -= factor / (krSum * viscosityRatio); + } + + //determine phase saturations from primary saturation variable + Scalar satWI = 0; + Scalar satWJ = 0; + switch (saturationType_) + { + case Sw: + { + satWI = problem_.variables().saturation()[globalIdxI]; + satWJ = problem_.variables().saturation()[globalIdxJ]; + break; + } + case Sn: + { + satWI = 1 - problem_.variables().saturation()[globalIdxI]; + satWJ = 1 - problem_.variables().saturation()[globalIdxJ]; + break; + } + } + + Scalar pcI = problem_.variables().capillaryPressure(globalIdxI); + Scalar pcJ = problem_.variables().capillaryPressure(globalIdxJ); + + // calculate the saturation gradient + Dune::FieldVector<Scalar, dimWorld> pcGradient = unitDistVec; + pcGradient *= (pcI - pcJ) / dist; + + // get the diffusive part -> give 1-sat because sat = S_n and lambda = lambda(S_w) and pc = pc(S_w) + Scalar diffPart = diffusivePart()(*eIt, isIndex, satWI, satWJ, pcGradient) * unitDistVec * faceArea + / (volume * porosity) * (unitOuterNormal * unitDistVec); + Scalar convPart = convectivePart() (*eIt, isIndex, satWI, satWJ) * unitDistVec * faceArea / (volume * porosity) * (unitOuterNormal * unitDistVec); + + //for time step criterion + if (diffPart >= 0) + { + diffFactorIn += diffPart / (krSum * viscosityRatio); + } + if (diffPart < 0) + { + diffFactorOut -= diffPart / (krSum * viscosityRatio); + } + if (convPart >= 0) + { + timestepFactorOut += convPart / (krSum * viscosityRatio); + } + if (convPart < 0) + { + timestepFactorIn -= convPart / (krSum * viscosityRatio); + } + + switch (saturationType_) + { + case Sw: + { + //vt*fw + factor *= lambdaW / (lambdaW + lambdaNW); + break; + } + case Sn: + { + //vt*fn + factor *= lambdaNW / (lambdaW + lambdaNW); + break; + } + } + factor -= diffPart; + factor += convPart; + break; + } + case vw: + { + if (compressibility_) + { + factor /= densityWI; + factorSecondPhase /= densityNWI; + } + + //for time step criterion + if (factor >= 0) + { + timestepFactorOut += factor / (krSum * viscosityRatio); + } + if (factor < 0) + { + timestepFactorIn -= factor / (krSum * viscosityRatio); + } + if (factorSecondPhase < 0) + { + timestepFactorIn -= factorSecondPhase / (krSum * viscosityRatio); + } + + if (std::isnan(timestepFactorIn) || std::isinf(timestepFactorIn)) + { + timestepFactorIn = 1e-100; + } + break; + } + + //for time step criterion if the non-wetting phase velocity is used + case vn: + { + if (compressibility_) + { + factor /= densityNWI; + factorSecondPhase /= densityWI; + } + + //for time step criterion + if (factor >= 0) + { + timestepFactorOut += factor / (krSum * viscosityRatio); + } + if (factor < 0) + { + timestepFactorIn -= factor / (krSum * viscosityRatio); + } + if (factorSecondPhase < 0) + { + timestepFactorIn -= factorSecondPhase / (krSum * viscosityRatio); + } + + if (std::isnan(timestepFactorIn) || std::isinf(timestepFactorIn)) + { + timestepFactorIn = 1e-100; + } + break; + } + } + }//end intersection with neighbor element + + // handle boundary face + if (isIt->boundary()) + { + // center of face in global coordinates + GlobalPosition globalPosFace = isIt->geometry().global(faceLocal); + + // cell center in global coordinates + GlobalPosition globalPos = eIt->geometry().global(localPos); + + // distance vector between barycenters + Dune::FieldVector<Scalar, dimWorld> distVec = globalPosFace - globalPos; + // compute distance between cell centers + Scalar dist = distVec.two_norm(); + + Dune::FieldVector<Scalar, dimWorld> unitDistVec(distVec); + unitDistVec /= dist; + + //get boundary type + BoundaryConditions::Flags bcTypeSat = problem_.bctypeSat(globalPosFace, *isIt); + + if (bcTypeSat == BoundaryConditions::dirichlet) + { + Scalar satBound = problem_.dirichletSat(globalPosFace, *isIt); + + //get velocity*normalvector*facearea/(volume*porosity) + factor = (problem_.variables().velocity()[globalIdxI][isIndex] * unitOuterNormal) + * (faceArea) / (volume * porosity); + factorSecondPhase = (problem_.variables().velocitySecondPhase()[globalIdxI][isIndex] * unitOuterNormal) + * (faceArea) / (volume * porosity); + + Scalar pressBound = problem_.variables().pressure()[globalIdxI]; + Scalar temperature = problem_.temperature(globalPosFace, *eIt); + + //determine phase saturations from primary saturation variable + Scalar satWI = 0; + Scalar satWBound = 0; + switch (saturationType_) + { + case Sw: + { + satWI = problem_.variables().saturation()[globalIdxI]; + satWBound = satBound; + break; + } + case Sn: + { + satWI = 1 - problem_.variables().saturation()[globalIdxI]; + satWBound = 1 - satBound; + break; + } + } + + Scalar pcBound = MaterialLaw::pC(problem_.spatialParameters().materialLawParams(globalPos, *eIt), + satBound); + + //determine phase pressures from primary pressure variable + Scalar pressW = 0; + Scalar pressNW = 0; + switch (pressureType_) + { + case pw: + { + pressW = pressBound; + pressNW = pressBound + pcBound; + break; + } + case pn: + { + pressW = pressBound - pcBound; + pressNW = pressBound; + break; + } + } + + FluidState fluidState; + fluidState.update(satBound, pressW, pressNW, temperature); + + //get phase potentials + Scalar potentialW = problem_.variables().potentialWetting(globalIdxI, isIndex); + Scalar potentialNW = problem_.variables().potentialNonwetting(globalIdxI, isIndex); + + Scalar lambdaW = 0; + Scalar lambdaNW = 0; + + //upwinding of lambda dependend on the phase potential gradients + if (potentialW > 0.) + { + lambdaW = lambdaWI; + if (compressibility_) + { + lambdaW /= densityWI; + }//divide by density because lambda is saved as lambda*density + } + else + { + if (compressibility_) + { + lambdaW = MaterialLaw::krw(problem_.spatialParameters().materialLawParams(globalPos, *eIt), + satWBound) / FluidSystem::phaseViscosity(wPhaseIdx, temperature, pressW, fluidState); + } + else + { + lambdaW = MaterialLaw::krw(problem_.spatialParameters().materialLawParams(globalPos, *eIt), + satWBound) / viscosityWI; + } + } + + if (potentialNW >= 0.) + { + lambdaNW = lambdaNWI; + if (compressibility_) + { + lambdaNW /= densityNWI; + }//divide by density because lambda is saved as lambda*density + } + else + { + if (compressibility_) + { + lambdaNW = MaterialLaw::krn( + problem_.spatialParameters().materialLawParams(globalPos, *eIt), satWBound) + / FluidSystem::phaseViscosity(nPhaseIdx, temperature, pressNW, fluidState); + } + else + { + lambdaNW = MaterialLaw::krn( + problem_.spatialParameters().materialLawParams(globalPos, *eIt), satWBound) + / viscosityNWI; + } + } + // std::cout<<lambdaW<<" "<<lambdaNW<<std::endl; + + Scalar krSum = lambdaW * viscosityWI + lambdaNW * viscosityNWI; + + switch (velocityType_) + { + case vt: + { + //for time step criterion + + if (factor >= 0) + { + timestepFactorOut += factor / (krSum * viscosityRatio); + } + if (factor < 0) + { + timestepFactorIn -= factor / (krSum * viscosityRatio); + } + + Scalar pcI = problem_.variables().capillaryPressure(globalIdxI); + + // calculate the saturation gradient + Dune::FieldVector<Scalar, dimWorld> pcGradient = unitDistVec; + pcGradient *= (pcI - pcBound) / dist; + + // get the diffusive part -> give 1-sat because sat = S_n and lambda = lambda(S_w) and pc = pc(S_w) + Scalar diffPart = diffusivePart()(*eIt, isIndex, satWI, satWBound, pcGradient) * unitDistVec + * faceArea / (volume * porosity) * (unitOuterNormal * unitDistVec); + Scalar convPart = convectivePart()(*eIt, isIndex, satWI, satWBound) * unitDistVec * faceArea / (volume * porosity) * (unitOuterNormal * unitDistVec); + + //for time step criterion + if (diffPart >= 0) + { + diffFactorIn += diffPart / (krSum * viscosityRatio); + } + if (diffPart < 0) + { + diffFactorOut -= diffPart / (krSum * viscosityRatio); + } + if (convPart >= 0) + { + timestepFactorOut += convPart / (krSum * viscosityRatio); + } + if (convPart < 0) + { + timestepFactorIn -= convPart / (krSum * viscosityRatio); + } + + switch (saturationType_) + { + case Sw: + { + //vt*fw + factor *= lambdaW / (lambdaW + lambdaNW); + break; + } + case Sn: + { + //vt*fn + factor *= lambdaNW / (lambdaW + lambdaNW); + break; + } + } + //vt*fw + factor -= diffPart; + factor += convPart; + break; + } + + case vw: + { + if (compressibility_) + { + factor /= densityWI; + factorSecondPhase /= densityNWI; + } + + //for time step criterion + if (factor >= 0) + { + timestepFactorOut += factor / (krSum * viscosityRatio); + } + if (factor < 0) + { + timestepFactorIn -= factor / (krSum * viscosityRatio); + } + if (factorSecondPhase < 0) + { + timestepFactorIn -= factorSecondPhase / (krSum * viscosityRatio); + } + + if (std::isnan(timestepFactorIn) || std::isinf(timestepFactorIn)) + { + timestepFactorIn = 1e-100; + } + break; + } + + //for time step criterion if the non-wetting phase velocity is used + case vn: + { + if (compressibility_) + { + factor /= densityNWI; + factorSecondPhase /= densityWI; + } + + //for time step criterion + if (factor >= 0) + { + timestepFactorOut += factor / (krSum * viscosityRatio); + } + if (factor < 0) + { + timestepFactorIn -= factor / (krSum * viscosityRatio); + } + if (factorSecondPhase < 0) + { + timestepFactorIn -= factorSecondPhase / (krSum * viscosityRatio); + } + + if (std::isnan(timestepFactorIn) || std::isinf(timestepFactorIn)) + { + timestepFactorIn = 1e-100; + } + break; + } + } + }//end dirichlet boundary + + if (bcTypeSat == BoundaryConditions::neumann) + { + //get mobilities + Scalar lambdaW, lambdaNW; + + lambdaW = lambdaWI; + if (compressibility_) + { + lambdaW /= densityWI; + } + + lambdaNW = lambdaNWI; + if (compressibility_) + { + lambdaNW /= densityNWI; + } + + Scalar krSum = lambdaW * viscosityWI + lambdaNW * viscosityNWI; + + //get velocity*normalvector*facearea/(volume*porosity) + factor = (problem_.variables().velocity()[globalIdxI][isIndex] * unitOuterNormal) * faceArea + / (volume * porosity); + switch (velocityType_) + { + case vt: + { + switch (saturationType_) + { + case Sw: + { + //vt*fw + factor *= lambdaW / (lambdaW + lambdaNW); + break; + } + case Sn: + { + //vt*fn + factor *= lambdaNW / (lambdaW + lambdaNW); + break; + } + } + break; + } + } + Scalar boundaryFactor = problem_.neumannSat(globalPosFace, *isIt, factor); + + if (factor != boundaryFactor) + { + switch (saturationType_) + { + case Sw: + { + factor = boundaryFactor / densityWI * faceArea / (volume * porosity); + break; + } + case Sn: + { + factor = boundaryFactor / densityNWI * faceArea / (volume * porosity); + break; + } + } + } + + //for time step criterion + + if (factor >= 0) + { + timestepFactorOut += factor / (krSum * viscosityRatio); + } + if (factor < 0) + { + timestepFactorIn -= factor / (krSum * viscosityRatio); + } + }//end neumann boundary + }//end boundary + // add to update vector + updateVec[globalIdxI] -= factor;//-:v>0, if flow leaves the cell + }// end all intersections + Scalar source = 0; + switch (velocityType_) + { + case vw: + { + source = problem_.source(globalPos, *eIt)[wPhaseIdx] / densityWI; + break; + } + case vn: + { + source = problem_.source(globalPos, *eIt)[nPhaseIdx] / densityNWI; + break; + } + case vt: + { + source = problem_.source(globalPos, *eIt)[wPhaseIdx] / densityWI + problem_.source(globalPos, + *eIt)[nPhaseIdx] / densityNWI; + break; + } + } + if (source) + { + //get mobilities + Scalar lambdaW = 0; + Scalar lambdaNW = 0; + + lambdaW = lambdaWI; + if (compressibility_) + { + lambdaW /= densityWI; + } + lambdaNW = lambdaNWI; + if (compressibility_) + { + lambdaNW /= densityNWI; + } + + Scalar krSum = lambdaW * viscosityWI + lambdaNW * viscosityNWI; + switch (saturationType_) + { + case Sw: + { + updateVec[globalIdxI] += source / porosity; + break; + } + case Sn: + { + updateVec[globalIdxI] += source / porosity; + break; + } + } + if (source >= 0) + { + timestepFactorIn += source / (porosity * viscosityRatio * krSum); + } + else + { + timestepFactorOut -= source / (porosity * viscosityRatio * krSum); + } + } + + //calculate time step + if (velocityType_ == vw || velocityType_ == vn) + { + dt = std::min(dt, evaluateTimeStepPhaseFlux(timestepFactorIn, timestepFactorOut, residualSatW, + residualSatNW, globalIdxI)); + } + if (velocityType_ == vt) + { + dt = std::min(dt, evaluateTimeStepTotalFlux(timestepFactorIn, timestepFactorOut, diffFactorIn, + diffFactorOut, residualSatW, residualSatNW)); + } + + problem_.variables().volumecorrection(globalIdxI) = updateVec[globalIdxI]; + } // end grid traversal + + return 0; } template<class TypeTag> void FVSaturation2P<TypeTag>::initialize() { - // iterate through leaf grid an evaluate c0 at cell center - ElementIterator eItEnd = problem_.gridView().template end<0> (); - for (ElementIterator eIt = problem_.gridView().template begin<0> (); eIt != eItEnd; ++eIt) - { - // get geometry type - Dune::GeometryType gt = eIt->geometry().type(); - - // get cell center in reference element - const LocalPosition &localPos = ReferenceElementContainer::general(gt).position(0, 0); - - // get global coordinate of cell center - GlobalPosition globalPos = eIt->geometry().global(localPos); - - // initialize cell concentration - problem_.variables().saturation()[problem_.variables().index(*eIt)] = problem_.initSat(globalPos, *eIt); - } - return; + // iterate through leaf grid an evaluate c0 at cell center + ElementIterator eItEnd = problem_.gridView().template end<0> (); + for (ElementIterator eIt = problem_.gridView().template begin<0> (); eIt != eItEnd; ++eIt) + { + // get geometry type + Dune::GeometryType gt = eIt->geometry().type(); + + // get cell center in reference element + const LocalPosition &localPos = ReferenceElementContainer::general(gt).position(0, 0); + + // get global coordinate of cell center + GlobalPosition globalPos = eIt->geometry().global(localPos); + + // initialize cell concentration + problem_.variables().saturation()[problem_.variables().index(*eIt)] = problem_.initSat(globalPos, *eIt); + } + return; } template<class TypeTag> typename FVSaturation2P<TypeTag>::Scalar FVSaturation2P<TypeTag>::evaluateTimeStepTotalFlux(Scalar timestepFactorIn, - Scalar timestepFactorOut, Scalar diffFactorIn, Scalar diffFactorOut, Scalar& residualSatW, - Scalar& residualSatNW) -{ - // compute volume correction - Scalar volumeCorrectionFactor = (1 - residualSatW - residualSatNW); - - //make sure correction is in the right range. If not: force dt to be not min-dt! - if (timestepFactorIn <= 0) - { - timestepFactorIn = 1e-100; - } - if (timestepFactorOut <= 0) - { - timestepFactorOut = 1e-100; - } - - Scalar sumFactor = std::min(volumeCorrectionFactor / timestepFactorIn, volumeCorrectionFactor / timestepFactorOut); - - //make sure that diffFactor > 0 - if (diffFactorIn <= 0) - { - diffFactorIn = 1e-100; - } - if (diffFactorOut <= 0) - { - diffFactorOut = 1e-100; - } - - Scalar minDiff = std::min(volumeCorrectionFactor / diffFactorIn, volumeCorrectionFactor / diffFactorOut); - - //determine time step - sumFactor = std::min(sumFactor, 0.1 * minDiff); - - return sumFactor; -} + Scalar timestepFactorOut, Scalar diffFactorIn, Scalar diffFactorOut, Scalar& residualSatW, + Scalar& residualSatNW) + { + // compute volume correction + Scalar volumeCorrectionFactor = (1 - residualSatW - residualSatNW); + + //make sure correction is in the right range. If not: force dt to be not min-dt! + if (timestepFactorIn <= 0) + { + timestepFactorIn = 1e-100; + } + if (timestepFactorOut <= 0) + { + timestepFactorOut = 1e-100; + } + + Scalar sumFactor = std::min(volumeCorrectionFactor / timestepFactorIn, volumeCorrectionFactor / timestepFactorOut); + + //make sure that diffFactor > 0 + if (diffFactorIn <= 0) + { + diffFactorIn = 1e-100; + } + if (diffFactorOut <= 0) + { + diffFactorOut = 1e-100; + } + + Scalar minDiff = std::min(volumeCorrectionFactor / diffFactorIn, volumeCorrectionFactor / diffFactorOut); + + //determine time step + sumFactor = std::min(sumFactor, 0.1 * minDiff); + + return sumFactor; + } template<class TypeTag> typename FVSaturation2P<TypeTag>::Scalar FVSaturation2P<TypeTag>::evaluateTimeStepPhaseFlux( - Scalar timestepFactorIn, Scalar timestepFactorOut, Scalar& residualSatW, Scalar& residualSatNW, int globalIdxI) -{ - // compute dt restriction - Scalar volumeCorrectionFactorIn = 1 - residualSatW - residualSatNW; - Scalar volumeCorrectionFactorOut = 0; - if (saturationType_ == Sw) - { - Scalar satI = problem_.variables().saturation()[globalIdxI]; - volumeCorrectionFactorOut = std::max((satI - residualSatW), 1e-2); - } - if (saturationType_ == Sn) - { - Scalar satI = problem_.variables().saturation()[globalIdxI]; - volumeCorrectionFactorOut = std::max((satI - residualSatNW), 1e-2); - } - - //make sure correction is in the right range. If not: force dt to be not min-dt! - if (volumeCorrectionFactorOut <= 0) - { - volumeCorrectionFactorOut = 1e100; - } - - //make sure correction is in the right range. If not: force dt to be not min-dt! - if (timestepFactorIn <= 0) - { - timestepFactorIn = 1e-100; - } - if (timestepFactorOut <= 0) - { - timestepFactorOut = 1e-100; - } - - //correct volume - timestepFactorIn = volumeCorrectionFactorIn / timestepFactorIn; - timestepFactorOut = volumeCorrectionFactorOut / timestepFactorOut; - - //determine timestep - Scalar timestepFactor = std::min(timestepFactorIn, timestepFactorOut); - - return timestepFactor; -} + Scalar timestepFactorIn, Scalar timestepFactorOut, Scalar& residualSatW, Scalar& residualSatNW, int globalIdxI) + { + // compute dt restriction + Scalar volumeCorrectionFactorIn = 1 - residualSatW - residualSatNW; + Scalar volumeCorrectionFactorOut = 0; + if (saturationType_ == Sw) + { + Scalar satI = problem_.variables().saturation()[globalIdxI]; + volumeCorrectionFactorOut = std::max((satI - residualSatW), 1e-2); + } + if (saturationType_ == Sn) + { + Scalar satI = problem_.variables().saturation()[globalIdxI]; + volumeCorrectionFactorOut = std::max((satI - residualSatNW), 1e-2); + } + + //make sure correction is in the right range. If not: force dt to be not min-dt! + if (volumeCorrectionFactorOut <= 0) + { + volumeCorrectionFactorOut = 1e100; + } + + //make sure correction is in the right range. If not: force dt to be not min-dt! + if (timestepFactorIn <= 0) + { + timestepFactorIn = 1e-100; + } + if (timestepFactorOut <= 0) + { + timestepFactorOut = 1e-100; + } + + //correct volume + timestepFactorIn = volumeCorrectionFactorIn / timestepFactorIn; + timestepFactorOut = volumeCorrectionFactorOut / timestepFactorOut; + + //determine timestep + Scalar timestepFactor = std::min(timestepFactorIn, timestepFactorOut); + + return timestepFactor; + } template<class TypeTag> void FVSaturation2P<TypeTag>::updateMaterialLaws(RepresentationType& saturation = *(new RepresentationType(0)), - bool iterate = false) -{ - FluidState fluidState; - - // iterate through leaf grid an evaluate c0 at cell center - ElementIterator eItEnd = problem_.gridView().template end<0> (); - for (ElementIterator eIt = problem_.gridView().template begin<0> (); eIt != eItEnd; ++eIt) - { - // get geometry type - Dune::GeometryType gt = eIt->geometry().type(); - - // get cell center in reference element - const LocalPosition &localPos = ReferenceElementContainer::general(gt).position(0, 0); - - // get global coordinate of cell center - GlobalPosition globalPos = eIt->geometry().global(localPos); - - int globalIdx = problem_.variables().index(*eIt); - - Scalar sat = 0; - if (!iterate) - { - sat = problem_.variables().saturation()[globalIdx]; - } - else - { - sat = saturation[globalIdx]; - } - - //determine phase saturations from primary saturation variable - Scalar satW = 0; - if (saturationType_ == Sw) - { - satW = sat; - } - if (saturationType_ == Sn) - { - satW = 1 - sat; - } - - Scalar temperature = problem_.temperature(globalPos, *eIt); - Scalar referencePressure = problem_.referencePressure(globalPos, *eIt); - - fluidState.update(satW, referencePressure, referencePressure, temperature); - - problem_.variables().densityWetting(globalIdx) = FluidSystem::phaseDensity(wPhaseIdx, temperature, referencePressure, fluidState); - problem_.variables().densityNonwetting(globalIdx) = FluidSystem::phaseDensity(nPhaseIdx, temperature, referencePressure, fluidState); - problem_.variables().viscosityWetting(globalIdx) = FluidSystem::phaseViscosity(wPhaseIdx, temperature, referencePressure, fluidState); - problem_.variables().viscosityNonwetting(globalIdx) = FluidSystem::phaseViscosity(nPhaseIdx, temperature, referencePressure, fluidState); - - // initialize mobilities - problem_.variables().mobilityWetting(globalIdx) = MaterialLaw::krw( - problem_.spatialParameters().materialLawParams(globalPos, *eIt), satW) - / problem_.variables().viscosityWetting(globalIdx); - problem_.variables().mobilityNonwetting(globalIdx) = MaterialLaw::krn( - problem_.spatialParameters().materialLawParams(globalPos, *eIt), satW) - / problem_.variables().viscosityNonwetting(globalIdx); - problem_.variables().capillaryPressure(globalIdx) = MaterialLaw::pC( - problem_.spatialParameters().materialLawParams(globalPos, *eIt), satW); - - problem_.variables().fracFlowFuncWetting(globalIdx) = problem_.variables().densityWetting(globalIdx) - * problem_.variables().mobilityWetting(globalIdx) / (problem_.variables().densityWetting(globalIdx) - * problem_.variables().mobilityWetting(globalIdx) + problem_.variables().densityNonwetting(globalIdx) - * problem_.variables().mobilityNonwetting(globalIdx)); - problem_.variables().fracFlowFuncNonwetting(globalIdx) = problem_.variables().densityNonwetting(globalIdx) - * problem_.variables().mobilityNonwetting(globalIdx) / (problem_.variables().densityWetting(globalIdx) - * problem_.variables().mobilityWetting(globalIdx) + problem_.variables().densityNonwetting(globalIdx) - * problem_.variables().mobilityNonwetting(globalIdx)); - - problem_.spatialParameters().update(satW, *eIt); - } - return; -} + bool iterate = false) + { + FluidState fluidState; + + // iterate through leaf grid an evaluate c0 at cell center + ElementIterator eItEnd = problem_.gridView().template end<0> (); + for (ElementIterator eIt = problem_.gridView().template begin<0> (); eIt != eItEnd; ++eIt) + { + // get geometry type + Dune::GeometryType gt = eIt->geometry().type(); + + // get cell center in reference element + const LocalPosition &localPos = ReferenceElementContainer::general(gt).position(0, 0); + + // get global coordinate of cell center + GlobalPosition globalPos = eIt->geometry().global(localPos); + + int globalIdx = problem_.variables().index(*eIt); + + Scalar sat = 0; + if (!iterate) + { + sat = problem_.variables().saturation()[globalIdx]; + } + else + { + sat = saturation[globalIdx]; + } + + //determine phase saturations from primary saturation variable + Scalar satW = 0; + if (saturationType_ == Sw) + { + satW = sat; + } + if (saturationType_ == Sn) + { + satW = 1 - sat; + } + + Scalar temperature = problem_.temperature(globalPos, *eIt); + Scalar referencePressure = problem_.referencePressure(globalPos, *eIt); + + fluidState.update(satW, referencePressure, referencePressure, temperature); + + problem_.variables().densityWetting(globalIdx) = FluidSystem::phaseDensity(wPhaseIdx, temperature, referencePressure, fluidState); + problem_.variables().densityNonwetting(globalIdx) = FluidSystem::phaseDensity(nPhaseIdx, temperature, referencePressure, fluidState); + problem_.variables().viscosityWetting(globalIdx) = FluidSystem::phaseViscosity(wPhaseIdx, temperature, referencePressure, fluidState); + problem_.variables().viscosityNonwetting(globalIdx) = FluidSystem::phaseViscosity(nPhaseIdx, temperature, referencePressure, fluidState); + + // initialize mobilities + problem_.variables().mobilityWetting(globalIdx) = MaterialLaw::krw( + problem_.spatialParameters().materialLawParams(globalPos, *eIt), satW) + / problem_.variables().viscosityWetting(globalIdx); + problem_.variables().mobilityNonwetting(globalIdx) = MaterialLaw::krn( + problem_.spatialParameters().materialLawParams(globalPos, *eIt), satW) + / problem_.variables().viscosityNonwetting(globalIdx); + problem_.variables().capillaryPressure(globalIdx) = MaterialLaw::pC( + problem_.spatialParameters().materialLawParams(globalPos, *eIt), satW); + + problem_.variables().fracFlowFuncWetting(globalIdx) = problem_.variables().mobilityWetting(globalIdx) / (problem_.variables().mobilityWetting(globalIdx) + problem_.variables().mobilityNonwetting(globalIdx)); + problem_.variables().fracFlowFuncNonwetting(globalIdx) = problem_.variables().mobilityNonwetting(globalIdx) / (problem_.variables().mobilityWetting(globalIdx) + problem_.variables().mobilityNonwetting(globalIdx)); + + problem_.spatialParameters().update(satW, *eIt); + } + return; + } } #endif diff --git a/dumux/decoupled/2p/transport/transportproperties.hh b/dumux/decoupled/2p/transport/transportproperties.hh index 0d7c4c1722..b5d2aaff09 100644 --- a/dumux/decoupled/2p/transport/transportproperties.hh +++ b/dumux/decoupled/2p/transport/transportproperties.hh @@ -31,6 +31,18 @@ class DiffusivePart; template<class TypeTag> class ConvectivePart; +template<class TypeTag> +class TwoPCommonIndices; + +template<class TypeTag> +class FluidSystem2P; + +template<class TypeTag> +class TwoPFluidState; + +template<class TypeTag> +class VariableClass2P; + namespace Properties { /*! @@ -51,10 +63,31 @@ NEW_TYPE_TAG(Transport); NEW_PROP_TAG( DiffusivePart ); //!< The type of the diffusive part in a transport equation NEW_PROP_TAG( ConvectivePart ); //!< The type of a convective part in a transport equation +NEW_PROP_TAG( Variables ); +NEW_PROP_TAG( NumPhases ); +NEW_PROP_TAG( NumComponents ); +NEW_PROP_TAG( TwoPIndices ); +NEW_PROP_TAG( FluidSystem ); +NEW_PROP_TAG( FluidState ); +NEW_PROP_TAG( EnableCompressibility ); +NEW_PROP_TAG( PressureFormulation ); +NEW_PROP_TAG( SaturationFormulation ); +NEW_PROP_TAG( VelocityFormulation ); +NEW_PROP_TAG( CFLFactor ); SET_TYPE_PROP(Transport, DiffusivePart, DiffusivePart<TypeTag>); SET_TYPE_PROP(Transport, ConvectivePart, ConvectivePart<TypeTag>); - +SET_TYPE_PROP(Transport, Variables, VariableClass2P<TypeTag>); +SET_INT_PROP(Transport, NumPhases, 2); +SET_INT_PROP(Transport, NumComponents, 1); +SET_TYPE_PROP(Transport, TwoPIndices, TwoPCommonIndices<TypeTag>); +SET_TYPE_PROP(Transport, FluidSystem, FluidSystem2P<TypeTag>); +SET_TYPE_PROP(Transport, FluidState, TwoPFluidState<TypeTag>); +SET_BOOL_PROP(Transport, EnableCompressibility, false); +SET_INT_PROP(Transport, PressureFormulation, TwoPCommonIndices<TypeTag>::pressureW); +SET_INT_PROP(Transport, SaturationFormulation, TwoPCommonIndices<TypeTag>::saturationW); +SET_INT_PROP(Transport, VelocityFormulation, TwoPCommonIndices<TypeTag>::velocityTotal); +SET_SCALAR_PROP(Transport, CFLFactor, 1.0); } } diff --git a/dumux/decoupled/2p/variableclass2p.hh b/dumux/decoupled/2p/variableclass2p.hh index 0ab82fe317..63588d9641 100644 --- a/dumux/decoupled/2p/variableclass2p.hh +++ b/dumux/decoupled/2p/variableclass2p.hh @@ -82,7 +82,7 @@ public: typedef typename SolutionTypes::PhasePropertyElemFace PhasePropertyElemFaceType;//!<type for vector of vectors (of size 2 x dimension) of scalars typedef typename SolutionTypes::DimVecElemFace DimVecElemFaceType;//!<type for vector of vectors (of size 2 x dimension) of vector (of size dimension) of scalars -private: +public: const int codim_; ScalarSolutionType saturation_; diff --git a/dumux/decoupled/common/onemodelproblem.hh b/dumux/decoupled/common/onemodelproblem.hh index cf59b35378..3265a85711 100644 --- a/dumux/decoupled/common/onemodelproblem.hh +++ b/dumux/decoupled/common/onemodelproblem.hh @@ -33,6 +33,11 @@ namespace Dumux { +namespace Properties +{ +NEW_PROP_TAG(CFLFactor); +} + /*! \ingroup diffusion * @brief base class that defines the parameters of loosely coupled diffusion and transport equations * @@ -67,6 +72,9 @@ private: typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar; + typedef typename GET_PROP(TypeTag, PTAG(SolutionTypes)) SolutionTypes; + typedef typename SolutionTypes::ScalarSolution Solution; + enum { dim = GridView::dimension, @@ -108,6 +116,7 @@ public: // bboxMax_[i] = std::max(bboxMax_[i], vIt->geometry().corner(0)[i]); // } // } + cFLFactor_ = GET_PROP_VALUE(TypeTag, PTAG(CFLFactor)); model_ = new Model(asImp_()) ; } @@ -126,7 +135,7 @@ public: void init() { // set the initial condition of the model - model().initial(); + model().initialize(); } /*! @@ -150,7 +159,6 @@ public: void timeIntegration() { // allocate temporary vectors for the updates - typedef typename Model::SolutionType Solution; Solution k1 = asImp_().variables().saturation(); dt_ = 1e100; @@ -160,7 +168,7 @@ public: model().update(t, dt_, k1); //make sure t_old + dt is not larger than tend - dt_ = std::min(dt_, timeManager().episodeMaxTimeStepSize()); + dt_ = std::min(dt_*cFLFactor_, timeManager().episodeMaxTimeStepSize()); timeManager().setTimeStepSize(dt_); // explicit Euler: Sat <- Sat + dt*N(Sat) @@ -226,7 +234,7 @@ public: if (gridView().comm().rank() == 0) std::cout << "Writing result file for current time step\n"; - resultWriter_.beginTimestep(timeManager_.time(), gridView()); + resultWriter_.beginTimestep(timeManager_.time() + timeManager_.timeStepSize(), gridView()); model().addOutputVtkFields(resultWriter_); resultWriter_.endTimestep(); } @@ -338,7 +346,7 @@ public: typedef Dumux::Restart Restarter; Restarter res; - res.serializeBegin(*asImp_()); + res.serializeBegin(asImp_()); std::cerr << "Serialize to file " << res.fileName() << "\n"; timeManager_.serialize(res); @@ -405,6 +413,8 @@ private: Scalar dt_; + Scalar cFLFactor_; + Model* model_; VtkMultiWriter resultWriter_; diff --git a/dumux/decoupled/common/variableclass.hh b/dumux/decoupled/common/variableclass.hh index 7dc0e3adaf..3b4bf93d3e 100644 --- a/dumux/decoupled/common/variableclass.hh +++ b/dumux/decoupled/common/variableclass.hh @@ -141,19 +141,6 @@ public: instream >> pressure_[globalIdx]; } -private: - void initializeGlobalVariables(Dune::FieldVector<Scalar, dim>& initialVel) - { - //resize to grid size - pressure_.resize(gridSize_); - velocity_.resize(gridSize_);//depends on pressure - potential_.resize(gridSize_);//depends on pressure - - //initialise variables - pressure_ = 0; - velocity_ = initialVel; - } - void initializePotentials(Dune::FieldVector<Scalar, dim>& initialVel) { if (initialVel.two_norm()) @@ -185,6 +172,50 @@ private: return; } +private: + void initializeGlobalVariables(Dune::FieldVector<Scalar, dim>& initialVel) + { + //resize to grid size + pressure_.resize(gridSize_); + velocity_.resize(gridSize_);//depends on pressure + potential_.resize(gridSize_);//depends on pressure + + //initialise variables + pressure_ = 0; + velocity_ = initialVel; + } + +// void initializePotentials(Dune::FieldVector<Scalar, dim>& initialVel) +// { +// if (initialVel.two_norm()) +// { +// // compute update vector +// ElementIterator eItEnd = gridView_.template end<0> (); +// for (ElementIterator eIt = gridView_.template begin<0> (); eIt != eItEnd; ++eIt) +// { +// // cell index +// int globalIdxI = elementMapper_.map(*eIt); +// +// // run through all intersections with neighbors and boundary +// IntersectionIterator isItEnd = gridView_.iend(*eIt); +// for (IntersectionIterator isIt = gridView_.ibegin(*eIt); isIt != isItEnd; ++isIt) +// { +// // local number of facet +// int indexInInside = isIt->indexInInside(); +// +// Dune::FieldVector<Scalar, dimWorld> unitOuterNormal = isIt->centerUnitOuterNormal(); +// +// for (int i = 0; i < numPhase; i++) {potential_[globalIdxI][indexInInside][i] = initialVel * unitOuterNormal;} +// } +// } +// } +// else +// { +// potential_ = Dune::FieldVector<Scalar, numPhase> (0); +// } +// return; +// } + //Write saturation and pressure into file template<class MultiWriter> void addOutputVtkFields(MultiWriter &writer) diff --git a/test/decoupled/2p/grids/test_transport.dgf b/test/decoupled/2p/grids/test_transport.dgf new file mode 100644 index 0000000000..0321c37549 --- /dev/null +++ b/test/decoupled/2p/grids/test_transport.dgf @@ -0,0 +1,11 @@ +DGF +Interval +0 0 % first corner +1 1 % second corner +10 10 % cells in x and y direction +# + +BOUNDARYDOMAIN +default 1 % all boundaries have id 1 +#BOUNDARYDOMAIN +# unitcube.dgf diff --git a/test/decoupled/2p/test_transport.cc b/test/decoupled/2p/test_transport.cc index 71482ac270..f51a3df403 100644 --- a/test/decoupled/2p/test_transport.cc +++ b/test/decoupled/2p/test_transport.cc @@ -33,7 +33,7 @@ //////////////////////// void usage(const char *progname) { - std::cout << boost::format("usage: %s [--restart restartTime] tEnd\n")%progname; + std::cout << boost::format("usage: %s [--restart restartTime] gridFile.dgf tEnd\n")%progname; exit(1); } @@ -54,7 +54,7 @@ int main(int argc, char** argv) //////////////////////////////////////////////////////////// // parse the command line arguments //////////////////////////////////////////////////////////// - if (argc < 2) + if (argc < 3) usage(argv[0]); // deal with the restart stuff @@ -68,28 +68,27 @@ int main(int argc, char** argv) std::istringstream(argv[argPos++]) >> restartTime; } - if (argc - argPos != 1) { + if (argc - argPos != 2) { usage(argv[0]); } + //////////////////////////////////////////////////////////// + // create the grid + //////////////////////////////////////////////////////////// + const char *dgfFileName = argv[argPos++]; + Dune::GridPtr<Grid> gridPtr(dgfFileName); + // read the initial time step and the end time double tEnd, dt; std::istringstream(argv[argPos++]) >> tEnd; dt = tEnd; //////////////////////////////////////////////////////////// - // create the grid + // instantiate and run the concrete problem //////////////////////////////////////////////////////////// - Dune::FieldVector<int,dim> N(4); N[0] = 4; Dune::FieldVector<double ,dim> L(0); Dune::FieldVector<double,dim> H(1); - Grid grid(N,L,H); - - //////////////////////////////////////////////////////////// - // instantiate and run the concrete problem - //////////////////////////////////////////////////////////// - - Problem problem(grid.leafView(), L, H); + Problem problem(gridPtr->leafView(), L, H); // load restart file if necessarry if (restart) diff --git a/test/decoupled/2p/test_transport_problem.hh b/test/decoupled/2p/test_transport_problem.hh index 6a3fe9cd04..e055f93fe1 100644 --- a/test/decoupled/2p/test_transport_problem.hh +++ b/test/decoupled/2p/test_transport_problem.hh @@ -22,8 +22,7 @@ #include <dune/grid/uggrid.hh> #endif -#include <dune/grid/yaspgrid.hh> -#include <dune/grid/sgrid.hh> +#include <dune/grid/io/file/dgfparser/dgfug.hh> #include <dumux/material/fluidsystems/liquidphase.hh> #include <dumux/material/components/unit.hh> @@ -51,8 +50,7 @@ NEW_TYPE_TAG(TransportTestProblem, INHERITS_FROM(DecoupledModel, Transport)); // Set the grid type SET_PROP(TransportTestProblem, Grid) { - // typedef Dune::YaspGrid<2> type; - typedef Dune::SGrid<2, 2> type; + typedef Dune::UGGrid<2> type; }; // Set the problem property -- GitLab