diff --git a/dumux/decoupled/2p/transport/fv/capillarydiffusion.hh b/dumux/decoupled/2p/transport/fv/capillarydiffusion.hh index 79ffb93e304e9eb4f7a074f3b100e8e5811feb75..e91accc2aa3c7f7586c9c59f5411eaa3940547a2 100644 --- a/dumux/decoupled/2p/transport/fv/capillarydiffusion.hh +++ b/dumux/decoupled/2p/transport/fv/capillarydiffusion.hh @@ -51,7 +51,7 @@ private: 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_TYPE(TypeTag, PTAG(TwoPIndices)) Indices; + typedef typename GET_PROP_TYPE(TypeTag, PTAG(Indices)) Indices; typedef typename GET_PROP_TYPE(TypeTag, PTAG(SpatialParameters)) SpatialParameters; typedef typename SpatialParameters::MaterialLaw MaterialLaw; @@ -59,6 +59,9 @@ private: typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidSystem)) FluidSystem; typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidState)) FluidState; + typedef typename GET_PROP_TYPE(TypeTag, PTAG(CellData)) CellData; + + enum { dim = GridView::dimension, dimWorld = GridView::dimensionworld @@ -99,6 +102,7 @@ public: break; } int globalIdxI = problem_.variables().index(element); + CellData& CellDataI = problem_.variables().cellData(globalIdxI); // get geometry type of face //Dune::GeometryType faceGT = isIt->geometryInInside().type(); @@ -113,17 +117,19 @@ public: if (preComput_) { - mobilityWI = problem_.variables().mobilityWetting(globalIdxI); - mobilityNWI = problem_.variables().mobilityNonwetting(globalIdxI); + mobilityWI = CellDataI.mobility(wPhaseIdx); + mobilityNWI = CellDataI.mobility(nPhaseIdx); } else { FluidState fluidState; - fluidState.update(satI, referencePressure, referencePressure, temperature); + fluidState.setPressure(wPhaseIdx, referencePressure); + fluidState.setPressure(nPhaseIdx, referencePressure); + fluidState.setTemperature(temperature); mobilityWI = MaterialLaw::krw(problem_.spatialParameters().materialLawParams(element), satI); - mobilityWI /= FluidSystem::phaseViscosity(wPhaseIdx, temperature, referencePressure, fluidState); + mobilityWI /= FluidSystem::viscosity(fluidState, wPhaseIdx); mobilityNWI = MaterialLaw::krn(problem_.spatialParameters().materialLawParams(element), satI); - mobilityNWI /= FluidSystem::phaseViscosity(nPhaseIdx, temperature, referencePressure, fluidState); + mobilityNWI /= FluidSystem::viscosity(fluidState, nPhaseIdx); } FieldMatrix meanPermeability(0); @@ -134,6 +140,7 @@ public: ElementPointer neighborPointer = isIt->outside(); int globalIdxJ = problem_.variables().index(*neighborPointer); + CellData& cellDataJ = problem_.variables().cellData(globalIdxJ); // neighbor cell center in global coordinates const GlobalPosition& globalPosNeighbor = neighborPointer->geometry().center(); @@ -158,17 +165,20 @@ public: //get lambda_bar = lambda_n*f_w if(preComput_) { - mobilityWJ = problem_.variables().mobilityWetting(globalIdxJ); - mobilityNWJ = problem_.variables().mobilityNonwetting(globalIdxJ); + mobilityWJ = cellDataJ.mobility(wPhaseIdx); + mobilityNWJ = cellDataJ.mobility(nPhaseIdx); } else { FluidState fluidState; - fluidState.update(satJ, referencePressure, referencePressure, temperature); + fluidState.setPressure(wPhaseIdx, referencePressure); + fluidState.setPressure(nPhaseIdx, referencePressure); + fluidState.setTemperature(temperature); + mobilityWJ = MaterialLaw::krw(problem_.spatialParameters().materialLawParams(*neighborPointer), satJ); - mobilityWJ /= FluidSystem::phaseViscosity(wPhaseIdx, temperature, referencePressure, fluidState); + mobilityWJ /= FluidSystem::viscosity(fluidState, wPhaseIdx); mobilityNWJ = MaterialLaw::krn(problem_.spatialParameters().materialLawParams(*neighborPointer), satJ); - mobilityNWJ /= FluidSystem::phaseViscosity(nPhaseIdx, temperature, referencePressure, fluidState); + mobilityNWJ /= FluidSystem::viscosity(fluidState, nPhaseIdx); } Scalar mobilityWMean = 0.5*(mobilityWI + mobilityWJ); Scalar mobilityNWMean = 0.5*(mobilityNWI + mobilityNWJ); @@ -185,11 +195,13 @@ public: //calculate lambda_n*f_w at the boundary FluidState fluidState; - fluidState.update(satJ, referencePressure, referencePressure, temperature); + fluidState.setPressure(wPhaseIdx, referencePressure); + fluidState.setPressure(nPhaseIdx, referencePressure); + fluidState.setTemperature(temperature); mobilityWJ = MaterialLaw::krw(problem_.spatialParameters().materialLawParams(element), satJ); - mobilityWJ /= FluidSystem::phaseViscosity(wPhaseIdx, temperature, referencePressure, fluidState); + mobilityWJ /= FluidSystem::viscosity(fluidState, wPhaseIdx); mobilityNWJ = MaterialLaw::krn(problem_.spatialParameters().materialLawParams(element), satJ); - mobilityNWJ /= FluidSystem::phaseViscosity(nPhaseIdx, temperature, referencePressure, fluidState); + mobilityNWJ /= FluidSystem::viscosity(fluidState, nPhaseIdx); Scalar mobWMean = 0.5 * (mobilityWI + mobilityWJ); Scalar mobNWMean = 0.5 * (mobilityNWI + mobilityNWJ); diff --git a/dumux/decoupled/2p/transport/fv/evalcflflux_coats.hh b/dumux/decoupled/2p/transport/fv/evalcflflux_coats.hh index fd294eee9f7e5466fe82e86f1e1295fdfa0b2757..520be40352f3a7670ffd38813774da8781b291d1 100644 --- a/dumux/decoupled/2p/transport/fv/evalcflflux_coats.hh +++ b/dumux/decoupled/2p/transport/fv/evalcflflux_coats.hh @@ -52,12 +52,14 @@ private: typedef typename SpatialParameters::MaterialLaw MaterialLaw; typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidSystem)) FluidSystem; typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidState)) FluidState; - typedef typename GET_PROP_TYPE(TypeTag, PTAG(TwoPIndices)) Indices; + typedef typename GET_PROP_TYPE(TypeTag, PTAG(Indices)) Indices; typedef typename GET_PROP_TYPE(TypeTag, PTAG(BoundaryTypes)) BoundaryTypes; typedef typename GET_PROP(TypeTag, PTAG(SolutionTypes)) SolutionTypes; typedef typename SolutionTypes::PrimaryVariables PrimaryVariables; + typedef typename GET_PROP_TYPE(TypeTag, PTAG(CellData)) CellData; + enum { dim = GridView::dimension, dimWorld = GridView::dimensionworld @@ -122,11 +124,13 @@ public: // cell index int globalIdxI = problem_.variables().index(element); + CellData& cellDataI = problem_.variables().cellData(globalIdxI); + int indexInInside = intersection.indexInInside(); - Scalar satI = problem_.variables().saturation()[globalIdxI]; - Scalar lambdaWI = problem_.variables().mobilityWetting(globalIdxI); - Scalar lambdaNWI = problem_.variables().mobilityNonwetting(globalIdxI); + Scalar satI = cellDataI.saturation(wPhaseIdx); + Scalar lambdaWI = cellDataI.mobility(wPhaseIdx); + Scalar lambdaNWI = cellDataI.mobility(nPhaseIdx); Scalar dPcdSI = MaterialLaw::dpC_dSw(problem_.spatialParameters().materialLawParams(element), satI); @@ -148,19 +152,18 @@ public: int globalIdxJ = problem_.variables().index(neighbor); + CellData& cellDataJ = problem_.variables().cellData(globalIdxJ); + //calculate potential gradients if (element.level() < neighbor.level()) { hasHangingNode_ = true; return; } - //get phase potentials - Scalar potentialW = problem_.variables().potentialWetting(globalIdxI, indexInInside); - Scalar potentialNW = problem_.variables().potentialNonwetting(globalIdxI, indexInInside); - Scalar satJ = problem_.variables().saturation()[globalIdxJ]; - Scalar lambdaWJ = problem_.variables().mobilityWetting(globalIdxJ); - Scalar lambdaNWJ = problem_.variables().mobilityNonwetting(globalIdxJ); + Scalar satJ = cellDataJ.saturation(wPhaseIdx); + Scalar lambdaWJ = cellDataI.mobility(wPhaseIdx); + Scalar lambdaNWJ = cellDataI.mobility(nPhaseIdx); Scalar dPcdSJ = MaterialLaw::dpC_dSw(problem_.spatialParameters().materialLawParams(neighbor), satJ); @@ -177,7 +180,7 @@ public: Scalar transmissibility = (unitOuterNormal * permeability) * intersection.geometry().volume() / dist; Scalar satUpw = 0; - if (potentialW >= 0) + if (cellDataI.fluxData().isUpwindCell(wPhaseIdx, indexInInside)) { satUpw = std::max(satI, 0.0); } @@ -200,7 +203,7 @@ public: dLambdaWdS -= MaterialLaw::krw(problem_.spatialParameters().materialLawParams(neighbor), std::abs(satMinus)) / viscosityW; dLambdaWdS /= (dS); - if (potentialNW >= 0) + if (cellDataI.fluxData().isUpwindCell(nPhaseIdx, indexInInside)) { satUpw = std::max(1 - satI, 0.0); } @@ -288,43 +291,33 @@ public: Dune::FieldVector<Scalar, dim> permeability(0); meanPermeability.mv(unitOuterNormal, permeability); - Scalar satBound = 0; + Scalar satWBound = cellDataI.saturation(wPhaseIdx); if (bcType.isDirichlet(eqIdxSat)) { PrimaryVariables bcValues; problem_.dirichlet(bcValues, intersection); - satBound = bcValues[eqIdxSat]; - } - else - { - satBound = problem_.variables().saturation()[globalIdxI]; - } + switch (saturationType_) + { + case Sw: + { + satWBound = bcValues[eqIdxSat]; + break; + } + case Sn: + { + satWBound = 1 - bcValues[eqIdxSat]; + break; + } + default: + { + DUNE_THROW(Dune::RangeError, "saturation type not implemented"); + break; + } + } - //determine phase saturations from primary saturation variable - Scalar satW; - //Scalar satNW; - switch (saturationType_) - { - case Sw: - { - satW = satBound; - //satNW = 1 - satBound; - break; - } - case Sn: - { - satW = 1 - satBound; - //satNW = satBound; - break; - } - default: - { - DUNE_THROW(Dune::RangeError, "saturation type not implemented"); - break; - } } - Scalar dPcdSBound = MaterialLaw::dpC_dSw(problem_.spatialParameters().materialLawParams(element), satBound); + Scalar dPcdSBound = MaterialLaw::dpC_dSw(problem_.spatialParameters().materialLawParams(element), satWBound); Scalar lambdaWBound = 0; Scalar lambdaNWBound = 0; @@ -332,28 +325,26 @@ public: Scalar temperature = problem_.temperature(element); Scalar referencePressure = problem_.referencePressure(element); FluidState fluidState; - Scalar viscosityWBound = FluidSystem::phaseViscosity(wPhaseIdx, temperature, referencePressure, fluidState); - Scalar viscosityNWBound = - FluidSystem::phaseViscosity(nPhaseIdx, temperature, referencePressure, fluidState); - lambdaWBound = MaterialLaw::krw(problem_.spatialParameters().materialLawParams(element), satW) / viscosityWBound; - lambdaNWBound = MaterialLaw::krn(problem_.spatialParameters().materialLawParams(element), satW) / viscosityNWBound; - - Scalar potentialW = 0; - Scalar potentialNW = 0; + fluidState.setPressure(wPhaseIdx, referencePressure); + fluidState.setPressure(nPhaseIdx, referencePressure); + fluidState.setTemperature(temperature); - potentialW = problem_.variables().potentialWetting(globalIdxI, indexInInside); - potentialNW = problem_.variables().potentialNonwetting(globalIdxI, indexInInside); + Scalar viscosityWBound = FluidSystem::viscosity(fluidState, wPhaseIdx); + Scalar viscosityNWBound = + FluidSystem::viscosity(fluidState, nPhaseIdx); + lambdaWBound = MaterialLaw::krw(problem_.spatialParameters().materialLawParams(element), satWBound) / viscosityWBound; + lambdaNWBound = MaterialLaw::krn(problem_.spatialParameters().materialLawParams(element), satWBound) / viscosityNWBound; Scalar transmissibility = (unitOuterNormal * permeability) * intersection.geometry().volume() / dist; Scalar satUpw = 0; - if (potentialW >= 0) + if (cellDataI.fluxData().isUpwindCell(wPhaseIdx, indexInInside)) { satUpw = std::max(satI, 0.0); } else { - satUpw = std::max(satBound, 0.0); + satUpw = std::max(satWBound, 0.0); } Scalar dS = eps_; @@ -370,13 +361,13 @@ public: dLambdaWdS -= MaterialLaw::krw(problem_.spatialParameters().materialLawParams(element), satMinus) / viscosityW; dLambdaWdS /= (dS); - if (potentialNW >= 0) + if (cellDataI.fluxData().isUpwindCell(nPhaseIdx, indexInInside)) { satUpw = std::max(1 - satI, 0.0); } else { - satUpw = std::max(1 - satBound, 0.0); + satUpw = std::max(1 - satWBound, 0.0); } dS = eps_; diff --git a/dumux/decoupled/2p/transport/fv/evalcflflux_default.hh b/dumux/decoupled/2p/transport/fv/evalcflflux_default.hh index 8c429e2647ebbe41cfcbc2c4e0a9b934b1a09cd9..2b64a9c7b623e42ca5348be1a68ff20e7455980b 100644 --- a/dumux/decoupled/2p/transport/fv/evalcflflux_default.hh +++ b/dumux/decoupled/2p/transport/fv/evalcflflux_default.hh @@ -49,7 +49,7 @@ private: typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar; typedef typename GET_PROP_TYPE(TypeTag, PTAG(Problem)) Problem; - typedef typename GET_PROP_TYPE(TypeTag, PTAG(TwoPIndices)) Indices; + typedef typename GET_PROP_TYPE(TypeTag, PTAG(Indices)) Indices; enum { @@ -219,18 +219,9 @@ typename EvalCflFluxDefault<TypeTag>::Scalar EvalCflFluxDefault<TypeTag>::getCfl Scalar volumeCorrectionFactorOutW = 0; Scalar volumeCorrectionFactorOutNW = 0; - Scalar sat = problem_.variables().saturation()[problem_.variables().index(element)]; - - if (saturationType_ == Sw) - { - volumeCorrectionFactorOutW = std::max((sat - residualSatW), 1e-2); - volumeCorrectionFactorOutNW = std::max((1 - sat - residualSatNW), 1e-2); - } - if (saturationType_ == Sn) - { - volumeCorrectionFactorOutW = std::max((1 - sat - residualSatW), 1e-2); - volumeCorrectionFactorOutNW = std::max((sat - residualSatNW), 1e-2); - } + Scalar satW = problem_.variables().cellData(problem_.variables().index(element)).saturation(wPhaseIdx); + volumeCorrectionFactorOutW = std::max((satW - residualSatW), 1e-2); + volumeCorrectionFactorOutNW = std::max((1 - satW - residualSatNW), 1e-2); //make sure correction is in the right range. If not: force dt to be not min-dt! if (volumeCorrectionFactorOutW <= 0) diff --git a/dumux/decoupled/2p/transport/fv/evalcflflux_default_old.hh b/dumux/decoupled/2p/transport/fv/evalcflflux_default_old.hh new file mode 100644 index 0000000000000000000000000000000000000000..8c429e2647ebbe41cfcbc2c4e0a9b934b1a09cd9 --- /dev/null +++ b/dumux/decoupled/2p/transport/fv/evalcflflux_default_old.hh @@ -0,0 +1,268 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * Copyright (C) 2010 by Markus Wolff * + * Institute of Hydraulic Engineering * + * University of Stuttgart, Germany * + * email: <givenname>.<name>@iws.uni-stuttgart.de * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +#ifndef DUMUX_EVALCFLFLUX_DEFAULT_HH +#define DUMUX_EVALCFLFLUX_DEFAULT_HH + +/** + * @file + * @brief Fluxes to evaluate a CFL-Condition + * @author Markus Wolff + */ + +#include "evalcflflux.hh" + +namespace Dumux +{ +/*!\ingroup Saturation2p + * @brief Default implementation of cfl-fluxes to evaluate a CFL-Condition + * + * Compares the maximum of inflow and outflow to the element volume weighted by relative permeability and viscosity ratios. + * + * Template parameters are: + + - TypeTag PropertyTag of the problem implementation + */ +template<class TypeTag> +class EvalCflFluxDefault: public EvalCflFlux<TypeTag> +{ +private: + 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_TYPE(TypeTag, PTAG(TwoPIndices)) Indices; + + enum + { + dim = GridView::dimension, dimWorld = GridView::dimensionworld + }; + enum + { + wPhaseIdx = Indices::wPhaseIdx, nPhaseIdx = Indices::nPhaseIdx + }; + + 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, + }; + + typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition; + + typedef typename GridView::Traits::template Codim<0>::Entity Element; + typedef typename GridView::template Codim<0>::EntityPointer ElementPointer; + typedef typename GridView::Intersection Intersection; + +public: + + void addFlux(Scalar& lambdaW, Scalar& lambdaNW, Scalar& viscosityW, Scalar& viscosityNW, Scalar flux, const Element& element, int phaseIdx = -1) + { + addFlux(lambdaW, lambdaNW, viscosityW, viscosityNW, flux, phaseIdx); + } + + void addFlux(Scalar& lambdaW, Scalar& lambdaNW, Scalar& viscosityW, Scalar& viscosityNW, Scalar flux, const Intersection& intersection, int phaseIdx = -1) + { + addFlux(lambdaW, lambdaNW, viscosityW, viscosityNW, flux, phaseIdx); + } + + Scalar getCflFluxFunction(const GlobalPosition& globalPos, const Element& element); + + EvalCflFluxDefault (Problem& problem) + : problem_(problem) + { + reset(); + } + +private: + + void addFlux(Scalar& lambdaW, Scalar& lambdaNW, Scalar& viscosityW, Scalar& viscosityNW, Scalar flux, int phaseIdx = -1) + { + Scalar krSum = lambdaW * viscosityW + lambdaNW * viscosityNW; + Scalar viscosityRatio = 1 - fabs(0.5 - viscosityNW / (viscosityW + viscosityNW));//1 - fabs(viscosityWI-viscosityNWI)/(viscosityWI+viscosityNWI); + + switch (phaseIdx) + { + case wPhaseIdx: + { + //for time step criterion + if (flux >= 0) + { + fluxWettingOut_ += flux / (krSum * viscosityRatio); + } + if (flux < 0) + { + fluxIn_ -= flux / (krSum * viscosityRatio); + } + + break; + } + + //for time step criterion if the non-wetting phase velocity is used + case nPhaseIdx: + { + if (flux >= 0) + { + fluxNonwettingOut_ += flux / (krSum * viscosityRatio); + } + if (flux < 0) + { + fluxIn_ -= flux / (krSum * viscosityRatio); + } + + break; + } + default: + { + if (flux >= 0) + { + fluxOut_ += flux / (krSum * viscosityRatio); + } + if (flux < 0) + { + fluxIn_ -= flux / (krSum * viscosityRatio); + } + + break; + } + } + } + + Scalar getCFLFluxIn(int phaseIdx = 0) + { + if (std::isnan(fluxIn_) || std::isinf(fluxIn_)) + { + fluxIn_ = 1e-100; + } + + return fluxIn_; + } + + Scalar getCFLFluxOut(int phaseIdx = 0) + { + if (std::isnan(fluxWettingOut_) || std::isinf(fluxWettingOut_)) + { + fluxWettingOut_ = 1e-100; + } + + if (std::isnan(fluxNonwettingOut_) || std::isinf(fluxNonwettingOut_)) + { + fluxNonwettingOut_ = 1e-100; + } + if (std::isnan(fluxOut_) || std::isinf(fluxOut_)) + { + fluxOut_ = 1e-100; + } + + if (phaseIdx == wPhaseIdx) + return fluxWettingOut_; + else if (phaseIdx == nPhaseIdx) + return fluxNonwettingOut_; + else + return fluxOut_; + } + + +protected: + + //! resets the accumulated CFL-fluxes to zero + void reset() + { + fluxWettingOut_ = 0; + fluxNonwettingOut_ = 0; + fluxIn_ = 0; + fluxOut_ = 0; + } + +private: + Problem& problem_;//problem data + Scalar fluxWettingOut_; + Scalar fluxNonwettingOut_; + Scalar fluxOut_; + Scalar fluxIn_; + static const int velocityType_ = GET_PROP_VALUE(TypeTag, PTAG(VelocityFormulation)); + static const int saturationType_ = GET_PROP_VALUE(TypeTag, PTAG(SaturationFormulation)); +}; + +template<class TypeTag> +typename EvalCflFluxDefault<TypeTag>::Scalar EvalCflFluxDefault<TypeTag>::getCflFluxFunction(const GlobalPosition& globalPos, const Element& element) +{ + Scalar residualSatW = problem_.spatialParameters().materialLawParams(element).Swr(); + Scalar residualSatNW = problem_.spatialParameters().materialLawParams(element).Snr(); + + // compute dt restriction + Scalar volumeCorrectionFactor = 1 - residualSatW - residualSatNW; + Scalar volumeCorrectionFactorOutW = 0; + Scalar volumeCorrectionFactorOutNW = 0; + + Scalar sat = problem_.variables().saturation()[problem_.variables().index(element)]; + + if (saturationType_ == Sw) + { + volumeCorrectionFactorOutW = std::max((sat - residualSatW), 1e-2); + volumeCorrectionFactorOutNW = std::max((1 - sat - residualSatNW), 1e-2); + } + if (saturationType_ == Sn) + { + volumeCorrectionFactorOutW = std::max((1 - sat - residualSatW), 1e-2); + volumeCorrectionFactorOutNW = std::max((sat - residualSatNW), 1e-2); + } + + //make sure correction is in the right range. If not: force dt to be not min-dt! + if (volumeCorrectionFactorOutW <= 0) + { + volumeCorrectionFactorOutW = 1e100; + } + if (volumeCorrectionFactorOutNW <= 0) + { + volumeCorrectionFactorOutNW = 1e100; + } + + //correct volume + Scalar cFLFluxIn = volumeCorrectionFactor / getCFLFluxIn(); + Scalar cFLFluxOut = 0; + + if (velocityType_ == vt) + { + cFLFluxOut = volumeCorrectionFactor / getCFLFluxOut(-1); + } + else + { + cFLFluxOut = std::min(volumeCorrectionFactorOutW / getCFLFluxOut(wPhaseIdx), volumeCorrectionFactorOutNW / getCFLFluxOut(nPhaseIdx)); + } + + //determine timestep + Scalar cFLFluxFunction = std::min(cFLFluxIn, cFLFluxOut); + + reset(); + + return cFLFluxFunction; +} + +} + +#endif diff --git a/dumux/decoupled/2p/transport/fv/fvsaturation2p.hh b/dumux/decoupled/2p/transport/fv/fvsaturation2p.hh index fc9c62a6dbf3e789faef0d52ec1db340f8397c67..63a6d8178c11559586f4ad1cc6444e914d82ba3c 100644 --- a/dumux/decoupled/2p/transport/fv/fvsaturation2p.hh +++ b/dumux/decoupled/2p/transport/fv/fvsaturation2p.hh @@ -69,31 +69,30 @@ class FVSaturation2P typedef typename GET_PROP_TYPE(TypeTag, PTAG(Problem)) Problem; typedef typename GET_PROP_TYPE(TypeTag, PTAG(Variables)) Variables; - typedef Dune::GenericReferenceElements<Scalar, dim> - ReferenceElementContainer; - typedef Dune::GenericReferenceElements<Scalar, dim - 1> - ReferenceElementFaceContainer; + typedef Dune::GenericReferenceElements<Scalar, dim> ReferenceElementContainer; + typedef Dune::GenericReferenceElements<Scalar, dim - 1> 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(EvalCflFluxFunction)) - EvalCflFluxFunction; + typedef typename GET_PROP_TYPE(TypeTag, PTAG(ConvectivePart)) ConvectivePart; + typedef typename GET_PROP_TYPE(TypeTag, PTAG(EvalCflFluxFunction)) EvalCflFluxFunction; - typedef typename GET_PROP_TYPE(TypeTag, PTAG(SpatialParameters)) - SpatialParameters; + 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(Indices)) Indices; typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidSystem)) FluidSystem; typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidState)) FluidState; + typedef typename GET_PROP_TYPE(TypeTag, PTAG(WettingPhase)) WettingPhase; + typedef typename GET_PROP_TYPE(TypeTag, PTAG(NonwettingPhase)) NonwettingPhase; typedef typename GET_PROP(TypeTag, PTAG(SolutionTypes)) SolutionTypes; typedef typename GET_PROP_TYPE(TypeTag, PTAG(BoundaryTypes)) BoundaryTypes; typedef typename SolutionTypes::PrimaryVariables PrimaryVariables; + typedef typename GET_PROP_TYPE(TypeTag, PTAG(CellData)) CellData; + enum { pw = Indices::pressureW, @@ -172,8 +171,7 @@ public: * Additionally to the \a update vector, the recommended time step size \a dt is calculated * employing a CFL condition. */ - void update(const Scalar t, Scalar& dt, - RepresentationType& updateVec, bool impes); + void update(const Scalar t, Scalar& dt, RepresentationType& updateVec, bool impes); //! Sets the initial solution \f$S_0\f$. void initialize(); @@ -185,26 +183,71 @@ public: */ void updateMaterialLaws(RepresentationType& saturation, bool iterate); + void updateSaturationSolution() + { + int size = problem_.gridView().size(0); + for (int i = 0; i < size; i++) + { + Scalar sat = problem_.variables().primaryVariablesGlobal(satEqIdx)[i]; + updateSaturationSolution(i, sat); + } + } + + void updateSaturationSolution(int globalIdx, Scalar sat) + { + CellData& cellData = problem_.variables().cellData(globalIdx); + switch (saturationType_) + { + case Sw: + { + if (compressibility_) + { + cellData.fluidState().setSaturation(wPhaseIdx, sat); + cellData.fluidState().setSaturation(nPhaseIdx, 1 - sat); + } + else + { + cellData.setSaturation(wPhaseIdx, sat); + cellData.setSaturation(nPhaseIdx, 1 - sat); + } + break; + } + case Sn: + { + if (compressibility_) + { + cellData.fluidState().setSaturation(wPhaseIdx, 1 - sat); + cellData.fluidState().setSaturation(nPhaseIdx, sat); + } + else + { + cellData.setSaturation(wPhaseIdx,1 -sat); + cellData.setSaturation(nPhaseIdx, sat); + } + break; + } + } + } + //! \brief Write data files /* \param name file name */ template<class MultiWriter> void addOutputVtkFields(MultiWriter &writer) { - typename Variables::ScalarSolutionType *saturation = - writer.allocateManagedBuffer ( - problem_.gridView().size(0)); + int size = problem_.gridView().size(0); + typename Variables::ScalarSolutionType *saturationW = writer.allocateManagedBuffer(size); + typename Variables::ScalarSolutionType *saturationN = writer.allocateManagedBuffer(size); - *saturation = problem_.variables().saturation(); - - if (saturationType_ == Sw) - { - writer.attachCellData(*saturation, "wetting saturation"); - } - if (saturationType_ == Sn) + for (int i = 0; i < size; i++) { - writer.attachCellData(*saturation, "nonwetting saturation"); + CellData& cellData = problem_.variables().cellData(i); + (*saturationW)[i] = cellData.saturation(wPhaseIdx); + (*saturationN)[i] = cellData.saturation(nPhaseIdx); } + writer.attachCellData(*saturationW, "wetting saturation"); + writer.attachCellData(*saturationN, "nonwetting saturation"); + return; } @@ -215,14 +258,14 @@ public: template<class Restarter> void serialize(Restarter &res) { - problem_.variables().serialize<Restarter> (res); + problem_.variables().serialize<Restarter>(res); } //! Function needed for restart option. template<class Restarter> void deserialize(Restarter &res) { - problem_.variables().deserialize<Restarter> (res); + problem_.variables().deserialize<Restarter>(res); } //! Constructs a FVSaturation2P object @@ -232,20 +275,18 @@ public: */ FVSaturation2P(Problem& problem) : - problem_(problem), switchNormals_(false), threshold_(1e-6) + problem_(problem), switchNormals_(false), threshold_(1e-6) { if (compressibility_ && velocityType_ == vt) { - DUNE_THROW( - Dune::NotImplemented, + 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) + if (pressureType_ != pw && pressureType_ != pn && pressureType_ != pglobal) { DUNE_THROW(Dune::NotImplemented, "Pressure type not supported!"); } @@ -272,15 +313,11 @@ private: ConvectivePart* convectivePart_; EvalCflFluxFunction* evalCflFluxFunction_; - static const bool compressibility_ = - GET_PROP_VALUE(TypeTag, PTAG(EnableCompressibility)); + 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)); + 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_; const Scalar threshold_; @@ -298,8 +335,8 @@ void FVSaturation2P<TypeTag>::indicatorSaturation(RepresentationType &indicator, { // 1) calculate Indicator -> min, maxvalues // Schleife über alle Leaf-Elemente - for (ElementIterator it = problem_.gridView().template begin<0>(); - it!=problem_.gridView().template end<0>(); ++it) + for (ElementIterator it = problem_.gridView().template begin<0>(); it != problem_.gridView().template end<0>(); + ++it) { // Bestimme maximale und minimale Sättigung // Index des aktuellen Leaf-Elements @@ -309,23 +346,23 @@ void FVSaturation2P<TypeTag>::indicatorSaturation(RepresentationType &indicator, // Berechne Verfeinerungsindikator an allen Zellen IntersectionIterator isend = problem_.gridView().iend(*it); - for (IntersectionIterator is = problem_.gridView().ibegin(*it); is!= isend; ++is) + for (IntersectionIterator is = problem_.gridView().ibegin(*it); is != isend; ++is) { - const typename IntersectionIterator::Intersection &intersection =*is; + const typename IntersectionIterator::Intersection &intersection = *is; // Steige aus, falls es sich nicht um einen Nachbarn handelt - if ( !intersection.neighbor() ) - continue ; + if (!intersection.neighbor()) + continue; // Greife auf Nachbarn zu - const Element &outside =*intersection.outside(); - int indexj = problem_.variables().index( outside ); + const Element &outside = *intersection.outside(); + int indexj = problem_.variables().index(outside); // Jede Intersection nur von einer Seite betrachten - if ( it.level() > outside.level() || - (it.level() == outside.level() && indexi<indexj) ) + if (it.level() > outside.level() || (it.level() == outside.level() && indexi < indexj)) { - Scalar localdelta = std::abs(problem_.variables().saturation()[indexi][0] - problem_.variables().saturation()[indexj][0]); + Scalar localdelta = std::abs( + problem_.variables().saturation()[indexi][0] - problem_.variables().saturation()[indexj][0]); indicator[indexi][0] = std::max(indicator[indexi][0], localdelta); indicator[indexj][0] = std::max(indicator[indexj][0], localdelta); } @@ -334,8 +371,7 @@ void FVSaturation2P<TypeTag>::indicatorSaturation(RepresentationType &indicator, } template<class TypeTag> -void FVSaturation2P<TypeTag>::update(const Scalar t, Scalar& dt, - RepresentationType& updateVec, bool impes = false) +void FVSaturation2P<TypeTag>::update(const Scalar t, Scalar& dt, RepresentationType& updateVec, bool impes = false) { if (!impes) { @@ -353,10 +389,25 @@ void FVSaturation2P<TypeTag>::update(const Scalar t, Scalar& dt, BoundaryTypes bcType; + ElementIterator eItBegin = problem_.gridView().template begin<0>(); + Scalar densityW = 0; + Scalar densityNW = 0; + Scalar viscosityW = 0; + Scalar viscosityNW = 0; + + if (!compressibility_) + { + Scalar temp = problem_.temperature(*eItBegin); + Scalar pRef = problem_.referencePressure(*eItBegin); + densityW = WettingPhase::density(temp, pRef); + densityNW = NonwettingPhase::density(temp, pRef); + viscosityW = WettingPhase::viscosity(temp, pRef); + viscosityNW = NonwettingPhase::viscosity(temp, pRef); + } + // compute update vector - ElementIterator eItEnd = problem_.gridView().template end<0> (); - for (ElementIterator eIt = problem_.gridView().template begin<0> (); eIt - != eItEnd; ++eIt) + ElementIterator eItEnd = problem_.gridView().template end<0>(); + for (ElementIterator eIt = eItBegin; eIt != eItEnd; ++eIt) { #if HAVE_MPI if (eIt->partitionType() != Dune::InteriorEntity) @@ -373,27 +424,26 @@ void FVSaturation2P<TypeTag>::update(const Scalar t, Scalar& dt, // cell index int globalIdxI = problem_.variables().index(*eIt); + CellData& cellDataI = problem_.variables().cellData(globalIdxI); + //for benchmark only! // problem_.variables().storeSrn(residualSatNW, globalIdxI); //for benchmark only! - Scalar porosity = - problem_.spatialParameters().porosity(*eIt); - - Scalar viscosityWI = problem_.variables().viscosityWetting(globalIdxI); - Scalar viscosityNWI = problem_.variables().viscosityNonwetting( - globalIdxI); + Scalar porosity = problem_.spatialParameters().porosity(*eIt); - Scalar densityWI = problem_.variables().densityWetting(globalIdxI); - Scalar densityNWI = problem_.variables().densityNonwetting(globalIdxI); + Scalar lambdaWI = cellDataI.mobility(wPhaseIdx); + Scalar lambdaNWI = cellDataI.mobility(nPhaseIdx); - Scalar lambdaWI = problem_.variables().mobilityWetting(globalIdxI); - Scalar lambdaNWI = problem_.variables().mobilityNonwetting(globalIdxI); + if (compressibility_) + { + viscosityW = cellDataI.viscosity(wPhaseIdx); + viscosityNW = cellDataI.viscosity(nPhaseIdx); + } // run through all intersections with neighbors and boundary IntersectionIterator isItEnd = problem_.gridView().iend(*eIt); - for (IntersectionIterator isIt = problem_.gridView().ibegin(*eIt); isIt - != isItEnd; ++isIt) + for (IntersectionIterator isIt = problem_.gridView().ibegin(*eIt); isIt != isItEnd; ++isIt) { // local number of faces int isIndex = isIt->indexInInside(); @@ -404,8 +454,10 @@ void FVSaturation2P<TypeTag>::update(const Scalar t, Scalar& dt, Scalar faceArea = isIt->geometry().volume(); - Scalar factor = 0; - Scalar factorSecondPhase = 0; + //get velocity*normalvector*facearea/(volume*porosity) + Scalar factorW = (cellDataI.fluxData().velocity(wPhaseIdx, isIndex) * unitOuterNormal) * faceArea; + Scalar factorNW = (cellDataI.fluxData().velocity(nPhaseIdx, isIndex) * unitOuterNormal) * faceArea; + Scalar factorTotal = factorW + factorNW; // handle interior face if (isIt->neighbor()) @@ -414,82 +466,61 @@ void FVSaturation2P<TypeTag>::update(const Scalar t, Scalar& dt, ElementPointer neighborPointer = isIt->outside(); int globalIdxJ = problem_.variables().index(*neighborPointer); + CellData& cellDataJ = problem_.variables().cellData(globalIdxJ); + // neighbor cell center in global coordinates - const GlobalPosition& globalPosNeighbor = - neighborPointer->geometry().center(); + const GlobalPosition& globalPosNeighbor = neighborPointer->geometry().center(); // distance vector between barycenters GlobalPosition distVec = globalPosNeighbor - globalPos; // compute distance between cell centers - Scalar dist = distVec * unitOuterNormal; -// Scalar dist = distVec.two_norm(); + Scalar dist = distVec.two_norm(); bool takeNeighbor = (eIt->level() < neighborPointer->level()); //get phase potentials - Scalar potentialW = - (takeNeighbor) ? -problem_.variables().potentialWetting(globalIdxJ, isIt->indexInOutside()) : - problem_.variables().potentialWetting(globalIdxI, isIndex); - Scalar potentialNW = - (takeNeighbor) ? -problem_.variables().potentialNonwetting(globalIdxJ, isIt->indexInOutside()) : - 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; - factorSecondPhase - = (problem_.variables().velocitySecondPhase()[globalIdxI][isIndex] - * unitOuterNormal) * faceArea; + bool upwindWI = + (takeNeighbor) ? !cellDataJ.fluxData().isUpwindCell(wPhaseIdx, isIt->indexInOutside()) : + cellDataI.fluxData().isUpwindCell(wPhaseIdx, isIndex); + bool upwindNWI = + (takeNeighbor) ? !cellDataJ.fluxData().isUpwindCell(nPhaseIdx, isIt->indexInOutside()) : + cellDataI.fluxData().isUpwindCell(nPhaseIdx, isIndex); Scalar lambdaW = 0; Scalar lambdaNW = 0; - //Scalar viscosityW = 0; - //Scalar viscosityNW = 0; //upwinding of lambda dependend on the phase potential gradients - if (potentialW >= 0.) + if (upwindWI) { lambdaW = lambdaWI; if (compressibility_) { - lambdaW /= densityWI; - }//divide by density because lambda is saved as lambda*density - //viscosityW = viscosityWI; + lambdaW /= cellDataI.density(wPhaseIdx); + } //divide by density because lambda is saved as lambda*density } else { - lambdaW = problem_.variables().mobilityWetting(globalIdxJ); + lambdaW = cellDataJ.mobility(wPhaseIdx); if (compressibility_) { - lambdaW /= densityWJ; - }//divide by density because lambda is saved as lambda*density - //viscosityW = problem_.variables().viscosityWetting( - // globalIdxJ); + lambdaW /= cellDataJ.density(wPhaseIdx); + } //divide by density because lambda is saved as lambda*density } - if (potentialNW >= 0.) + if (upwindNWI) { lambdaNW = lambdaNWI; if (compressibility_) { - lambdaNW /= densityNWI; - }//divide by density because lambda is saved as lambda*density - //viscosityNW = viscosityNWI; + lambdaNW /= cellDataI.density(nPhaseIdx); + } //divide by density because lambda is saved as lambda*density } else { - lambdaNW = problem_.variables().mobilityNonwetting( - globalIdxJ); + lambdaNW = cellDataJ.mobility(nPhaseIdx); if (compressibility_) { - lambdaNW /= densityNWJ; - }//divide by density because lambda is saved as lambda*density - //viscosityNW = problem_.variables().viscosityNonwetting( - // globalIdxJ); + lambdaNW /= cellDataJ.density(nPhaseIdx); + } //divide by density because lambda is saved as lambda*density } switch (velocityType_) @@ -497,111 +528,68 @@ void FVSaturation2P<TypeTag>::update(const Scalar t, Scalar& dt, case vt: { //add cflFlux for time-stepping - evalCflFluxFunction().addFlux(lambdaW, lambdaNW, - viscosityWI, viscosityNWI, factor, *isIt); + evalCflFluxFunction().addFlux(lambdaW, lambdaNW, viscosityW, viscosityNW, factorTotal, *isIt); //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 satWI = cellDataI.saturation(wPhaseIdx); + Scalar satWJ = cellDataJ.saturation(wPhaseIdx); - Scalar pcI = problem_.variables().capillaryPressure( - globalIdxI); - Scalar pcJ = problem_.variables().capillaryPressure( - globalIdxJ); + Scalar pcI = cellDataI.capillaryPressure(); + Scalar pcJ = cellDataJ.capillaryPressure(); // calculate the saturation gradient GlobalPosition pcGradient = unitOuterNormal; pcGradient *= (pcI - pcJ) / dist; // get the diffusive part - Scalar diffPart = diffusivePart()(*eIt, isIndex, satWI, - satWJ, pcGradient) * unitOuterNormal * faceArea; + Scalar diffPart = diffusivePart()(*eIt, isIndex, satWI, satWJ, pcGradient) * unitOuterNormal + * faceArea; - - Scalar convPart = convectivePart()(*eIt, isIndex, satWI, - satWJ) * unitOuterNormal * faceArea; + Scalar convPart = convectivePart()(*eIt, isIndex, satWI, satWJ) * unitOuterNormal * faceArea; switch (saturationType_) { case Sw: { //vt*fw - factor *= lambdaW / (lambdaW + lambdaNW); + factorTotal *= lambdaW / (lambdaW + lambdaNW); break; } case Sn: { //vt*fn - factor *= lambdaNW / (lambdaW + lambdaNW); + factorTotal *= lambdaNW / (lambdaW + lambdaNW); diffPart *= -1; convPart *= -1; break; } } - factor -= diffPart; - factor += convPart; - - //add cflFlux for time-stepping - evalCflFluxFunction().addFlux(lambdaW, lambdaNW, - viscosityWI, viscosityNWI, 10 * diffPart, *isIt); - evalCflFluxFunction().addFlux(lambdaW, lambdaNW, - viscosityWI, viscosityNWI, 10 * convPart, *isIt); - - break; - } - case vw: - { - if (compressibility_) - { - factor /= densityWI; - factorSecondPhase /= densityNWI; - } + factorTotal -= diffPart; + factorTotal += convPart; //add cflFlux for time-stepping - evalCflFluxFunction().addFlux(lambdaW, lambdaNW, - viscosityWI, viscosityNWI, factor, *isIt, wPhaseIdx); - evalCflFluxFunction().addFlux(lambdaW, lambdaNW, - viscosityWI, viscosityNWI, factorSecondPhase, - *isIt, nPhaseIdx); + evalCflFluxFunction().addFlux(lambdaW, lambdaNW, viscosityW, viscosityNW, 10 * diffPart, *isIt); + evalCflFluxFunction().addFlux(lambdaW, lambdaNW, viscosityW, viscosityNW, 10 * convPart, *isIt); break; } - case vn: + default: { if (compressibility_) { - factor /= densityNWI; - factorSecondPhase /= densityWI; + factorW /= cellDataI.density(wPhaseIdx); + factorNW /= cellDataI.density(nPhaseIdx); } - - //add cflFlux for time-stepping - evalCflFluxFunction().addFlux(lambdaW, lambdaNW, - viscosityWI, viscosityNWI, factor, *isIt, nPhaseIdx); - evalCflFluxFunction().addFlux(lambdaW, lambdaNW, - viscosityWI, viscosityNWI, factorSecondPhase, - *isIt, wPhaseIdx); + //add cflFlux for time-stepping + evalCflFluxFunction().addFlux(lambdaW, lambdaNW, viscosityW, viscosityNW, factorW, *isIt, + wPhaseIdx); + evalCflFluxFunction().addFlux(lambdaW, lambdaNW, viscosityW, viscosityNW, factorNW, *isIt, + nPhaseIdx); break; } } - }//end intersection with neighbor element + } //end intersection with neighbor element // handle boundary face if (isIt->boundary()) @@ -616,8 +604,7 @@ void FVSaturation2P<TypeTag>::update(const Scalar t, Scalar& dt, // distance vector between barycenters GlobalPosition distVec = globalPosFace - globalPos; // compute distance between cell centers - Scalar dist = distVec * unitOuterNormal; -// Scalar dist = distVec.two_norm(); + Scalar dist = distVec.two_norm(); if (bcType.isDirichlet(satEqIdx)) { @@ -625,126 +612,70 @@ void FVSaturation2P<TypeTag>::update(const Scalar t, Scalar& dt, Scalar satBound = boundValues[saturationIdx]; - //get velocity*normalvector*facearea/(volume*porosity) - factor - = (problem_.variables().velocity()[globalIdxI][isIndex] - * unitOuterNormal) * faceArea; - factorSecondPhase - = (problem_.variables().velocitySecondPhase()[globalIdxI][isIndex] - * unitOuterNormal) * faceArea; - - Scalar pressBound = problem_.variables().pressure()[globalIdxI]; - Scalar temperature = problem_.temperature(*eIt); - //determine phase saturations from primary saturation variable - Scalar satWI = 0; + Scalar satWI = cellDataI.saturation(wPhaseIdx); 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(*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 pcBound = MaterialLaw::pC(problem_.spatialParameters().materialLawParams(*eIt), satBound); Scalar lambdaW = 0; Scalar lambdaNW = 0; //upwinding of lambda dependend on the phase potential gradients - if (potentialW > 0.) + if (cellDataI.fluxData().isUpwindCell(wPhaseIdx, isIndex)) { lambdaW = lambdaWI; if (compressibility_) { - lambdaW /= densityWI; - }//divide by density because lambda is saved as lambda*density + lambdaW /= cellDataI.density(wPhaseIdx); + } //divide by density because lambda is saved as lambda*density } else { if (compressibility_) { - lambdaW - = MaterialLaw::krw( - problem_.spatialParameters().materialLawParams(*eIt), satWBound) - / FluidSystem::phaseViscosity( - wPhaseIdx, temperature, - pressW, fluidState); + lambdaW = MaterialLaw::krw(problem_.spatialParameters().materialLawParams(*eIt), satWBound) + / FluidSystem::viscosity(cellDataI.fluidState(), wPhaseIdx); } else { - lambdaW - = MaterialLaw::krw( - problem_.spatialParameters().materialLawParams(*eIt), satWBound) - / viscosityWI; + lambdaW = MaterialLaw::krw(problem_.spatialParameters().materialLawParams(*eIt), satWBound) + / viscosityW; } } - if (potentialNW >= 0.) + if (cellDataI.fluxData().isUpwindCell(nPhaseIdx, isIndex)) { lambdaNW = lambdaNWI; if (compressibility_) { - lambdaNW /= densityNWI; - }//divide by density because lambda is saved as lambda*density + lambdaNW /= cellDataI.density(nPhaseIdx); + } //divide by density because lambda is saved as lambda*density } else { if (compressibility_) { - lambdaNW - = MaterialLaw::krn( - problem_.spatialParameters().materialLawParams(*eIt), satWBound) - / FluidSystem::phaseViscosity( - nPhaseIdx, temperature, - pressNW, fluidState); + lambdaNW = MaterialLaw::krn(problem_.spatialParameters().materialLawParams(*eIt), satWBound) + / FluidSystem::viscosity(cellDataI.fluidState(), nPhaseIdx); } else { - lambdaNW - = MaterialLaw::krn( - problem_.spatialParameters().materialLawParams(*eIt), satWBound) - / viscosityNWI; + lambdaNW = MaterialLaw::krn(problem_.spatialParameters().materialLawParams(*eIt), satWBound) + / viscosityNW; } } // std::cout<<lambdaW<<" "<<lambdaNW<<std::endl; @@ -753,136 +684,95 @@ void FVSaturation2P<TypeTag>::update(const Scalar t, Scalar& dt, { case vt: { - evalCflFluxFunction().addFlux(lambdaW, lambdaNW, - viscosityWI, viscosityNWI, factor, *isIt); + evalCflFluxFunction().addFlux(lambdaW, lambdaNW, viscosityW, viscosityNW, factorTotal, *isIt); - Scalar pcI = problem_.variables().capillaryPressure( - globalIdxI); + Scalar pcI = cellDataI.capillaryPressure(); // calculate the saturation gradient GlobalPosition pcGradient = unitOuterNormal; 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) * unitOuterNormal + Scalar diffPart = diffusivePart()(*eIt, isIndex, satWI, satWBound, pcGradient) * unitOuterNormal * faceArea; - Scalar convPart = convectivePart()(*eIt, isIndex, - satWI, satWBound) * unitOuterNormal * faceArea; + Scalar convPart = convectivePart()(*eIt, isIndex, satWI, satWBound) * unitOuterNormal + * faceArea; switch (saturationType_) { case Sw: { //vt*fw - factor *= lambdaW / (lambdaW + lambdaNW); + factorTotal *= lambdaW / (lambdaW + lambdaNW); break; } case Sn: { //vt*fn - factor *= lambdaNW / (lambdaW + lambdaNW); - diffPart *= -1; + factorTotal *= lambdaNW / (lambdaW + lambdaNW); + diffPart *= -1; //add cflFlux for time-stepping + evalCflFluxFunction().addFlux(lambdaW, lambdaNW, viscosityW, viscosityNW, factorW, *isIt, + wPhaseIdx); + evalCflFluxFunction().addFlux(lambdaW, lambdaNW, viscosityW, viscosityNW, factorNW, + *isIt, nPhaseIdx); convPart *= -1; break; } } //vt*fw - factor -= diffPart; - factor += convPart; - - //add cflFlux for time-stepping - evalCflFluxFunction().addFlux(lambdaW, lambdaNW, - viscosityWI, viscosityNWI, 10 * diffPart, *isIt); - evalCflFluxFunction().addFlux(lambdaW, lambdaNW, - viscosityWI, viscosityNWI, 10 * convPart, *isIt); - - break; - } - - case vw: - { - if (compressibility_) - { - factor /= densityWI; - factorSecondPhase /= densityNWI; - } + factorTotal -= diffPart; + factorTotal += convPart; //add cflFlux for time-stepping - evalCflFluxFunction().addFlux(lambdaW, lambdaNW, - viscosityWI, viscosityNWI, factor, *isIt, - wPhaseIdx); - evalCflFluxFunction().addFlux(lambdaW, lambdaNW, - viscosityWI, viscosityNWI, factorSecondPhase, - *isIt, nPhaseIdx); + evalCflFluxFunction().addFlux(lambdaW, lambdaNW, viscosityW, viscosityNW, 10 * diffPart, *isIt); + evalCflFluxFunction().addFlux(lambdaW, lambdaNW, viscosityW, viscosityNW, 10 * convPart, *isIt); break; } - - //for time step criterion if the non-wetting phase velocity is used - case vn: + default: { if (compressibility_) { - factor /= densityNWI; - factorSecondPhase /= densityWI; + factorW /= cellDataI.density(wPhaseIdx); + factorNW /= cellDataI.density(nPhaseIdx); } - //add cflFlux for time-stepping - evalCflFluxFunction().addFlux(lambdaW, lambdaNW, - viscosityWI, viscosityNWI, factor, *isIt, - nPhaseIdx); - evalCflFluxFunction().addFlux(lambdaW, lambdaNW, - viscosityWI, viscosityNWI, factorSecondPhase, - *isIt, wPhaseIdx); + //add cflFlux for time-stepping + evalCflFluxFunction().addFlux(lambdaW, lambdaNW, viscosityW, viscosityNW, factorW, *isIt, + wPhaseIdx); + evalCflFluxFunction().addFlux(lambdaW, lambdaNW, viscosityW, viscosityNW, factorNW, *isIt, + nPhaseIdx); break; } } - }//end dirichlet boundary + } //end dirichlet boundary if (bcType.isNeumann(satEqIdx)) { problem_.neumann(boundValues, *isIt); + factorW = boundValues[wPhaseIdx]; + factorNW = boundValues[nPhaseIdx]; + factorW *= faceArea; + factorNW *= faceArea; //get mobilities Scalar lambdaW, lambdaNW; lambdaW = lambdaWI; - if (compressibility_) - { - lambdaW /= densityWI; - } - lambdaNW = lambdaNWI; if (compressibility_) { - lambdaNW /= densityNWI; - } - - switch (saturationType_) - { - case Sw: - { - factor = boundValues[wPhaseIdx]; - factor /= densityWI; - factor *= faceArea; - factorSecondPhase = boundValues[nPhaseIdx]; - factorSecondPhase /= densityNWI; - factorSecondPhase *= faceArea; - break; + lambdaW /= cellDataI.density(wPhaseIdx); + lambdaNW /= cellDataI.density(nPhaseIdx); + factorW /= cellDataI.density(wPhaseIdx); + factorNW /= cellDataI.density(nPhaseIdx); } - case Sn: + else { - factor = boundValues[nPhaseIdx]; - factor /= densityNWI; - factor *= faceArea; - factorSecondPhase = boundValues[wPhaseIdx]; - factorSecondPhase /= densityWI; - factorSecondPhase *= faceArea; - break; - } + factorW /= densityW; + factorNW /= densityNW; } switch (velocityType_) @@ -890,60 +780,33 @@ void FVSaturation2P<TypeTag>::update(const Scalar t, Scalar& dt, case vt: { //add cflFlux for time-stepping - evalCflFluxFunction().addFlux(lambdaW, lambdaNW, - viscosityWI, viscosityNWI, factor+factorSecondPhase, *isIt); + evalCflFluxFunction().addFlux(lambdaW, lambdaNW, viscosityW, viscosityNW, factorW + factorNW, + *isIt); break; } - case vw: + default: { - //add cflFlux for time-stepping - evalCflFluxFunction().addFlux(lambdaW, lambdaNW, - viscosityWI, viscosityNWI, factor, *isIt, - wPhaseIdx); - evalCflFluxFunction().addFlux(lambdaW, lambdaNW, - viscosityWI, viscosityNWI, factorSecondPhase, *isIt, - nPhaseIdx); - break; - } - case vn: - { - //add cflFlux for time-stepping - evalCflFluxFunction().addFlux(lambdaW, lambdaNW, - viscosityWI, viscosityNWI, factor, *isIt, - nPhaseIdx); - evalCflFluxFunction().addFlux(lambdaW, lambdaNW, - viscosityWI, viscosityNWI, factorSecondPhase, *isIt, - wPhaseIdx); + evalCflFluxFunction().addFlux(lambdaW, lambdaNW, viscosityW, viscosityNW, factorW, *isIt, + wPhaseIdx); + evalCflFluxFunction().addFlux(lambdaW, lambdaNW, viscosityW, viscosityNW, factorNW, *isIt, + nPhaseIdx); + break; } } - }//end neumann boundary + } //end neumann boundary if (bcType.isOutflow(satEqIdx)) { //get mobilities - Scalar lambdaW, lambdaNW; - - lambdaW = lambdaWI; + Scalar lambdaW = lambdaWI; + Scalar lambdaNW = lambdaNWI; if (compressibility_) { - lambdaW /= densityWI; + lambdaW /= cellDataI.density(wPhaseIdx); + lambdaNW /= cellDataI.density(nPhaseIdx); } - lambdaNW = lambdaNWI; - if (compressibility_) - { - lambdaNW /= densityNWI; - } - - //get velocity*normalvector*facearea/(volume*porosity) - factor - = (problem_.variables().velocity()[globalIdxI][isIndex] - * unitOuterNormal) * faceArea; - factorSecondPhase - = (problem_.variables().velocitySecondPhase()[globalIdxI][isIndex] - * unitOuterNormal) * faceArea; - if (velocityType_ == vt) { switch (saturationType_) @@ -951,131 +814,120 @@ void FVSaturation2P<TypeTag>::update(const Scalar t, Scalar& dt, case Sw: { //vt*fw - factor *= lambdaW / (lambdaW + lambdaNW); + factorTotal *= lambdaW / (lambdaW + lambdaNW); + evalCflFluxFunction().addFlux(lambdaW, lambdaNW, viscosityW, viscosityNW, factorTotal, + *isIt); break; } case Sn: { //vt*fn - factor *= lambdaNW / (lambdaW + lambdaNW); + factorTotal *= lambdaNW / (lambdaW + lambdaNW); + evalCflFluxFunction().addFlux(lambdaW, lambdaNW, viscosityW, viscosityNW, factorTotal, + *isIt); break; } } } - - switch (velocityType_) - { - case vt: - { - //add cflFlux for time-stepping - evalCflFluxFunction().addFlux(lambdaW, lambdaNW, - viscosityWI, viscosityNWI, factor, *isIt); - break; - } - case vw: - { - //add cflFlux for time-stepping - evalCflFluxFunction().addFlux(lambdaW, lambdaNW, - viscosityWI, viscosityNWI, factor, *isIt, - wPhaseIdx); - evalCflFluxFunction().addFlux(lambdaW, lambdaNW, - viscosityWI, viscosityNWI, factorSecondPhase, *isIt, - nPhaseIdx); - break; - } - case vn: + else { - //add cflFlux for time-stepping - evalCflFluxFunction().addFlux(lambdaW, lambdaNW, - viscosityWI, viscosityNWI, factor, *isIt, - nPhaseIdx); - evalCflFluxFunction().addFlux(lambdaW, lambdaNW, - viscosityWI, viscosityNWI, factorSecondPhase, *isIt, - wPhaseIdx); + evalCflFluxFunction().addFlux(lambdaW, lambdaNW, viscosityW, viscosityNW, factorW, *isIt, + wPhaseIdx); + evalCflFluxFunction().addFlux(lambdaW, lambdaNW, viscosityW, viscosityNW, factorNW, *isIt, + nPhaseIdx); + break; } - } - }//end outflow boundary - }//end boundary - // add to update vector - updateVec[globalIdxI] -= factor / (volume * porosity);//-:v>0, if flow leaves the cell - }// end all intersections + } //end outflow boundary + } //end boundary + // add to update vector + + switch (velocityType_) + { + case vt: + updateVec[globalIdxI] -= factorTotal / (volume * porosity); //-:v>0, if flow leaves the cell + break; + default: + switch (saturationType_) + { + case Sw: + updateVec[globalIdxI] -= factorW / (volume * porosity); //-:v>0, if flow leaves the cell + break; + case Sn: + updateVec[globalIdxI] -= factorNW / (volume * porosity); //-:v>0, if flow leaves the cell + break; + } + break; + } + } // end all intersections PrimaryVariables sourceVec(0.0); problem_.source(sourceVec, *eIt); - sourceVec[wPhaseIdx] /= densityWI; - sourceVec[nPhaseIdx] /= densityNWI; - //get mobilities - Scalar lambdaW = 0; - Scalar lambdaNW = 0; + if (compressibility_) + { + sourceVec[wPhaseIdx] /= cellDataI.density(wPhaseIdx); + sourceVec[nPhaseIdx] /= cellDataI.density(nPhaseIdx); + } + else + { + sourceVec[wPhaseIdx] /= densityW; + sourceVec[nPhaseIdx] /= densityNW; + } - lambdaW = lambdaWI; - if (compressibility_) - { - lambdaW /= densityWI; - } - lambdaNW = lambdaNWI; - if (compressibility_) - { - lambdaNW /= densityNWI; - } + //get mobilities + Scalar lambdaW = lambdaWI; + Scalar lambdaNW = lambdaNWI; + if (compressibility_) + { + lambdaW /= cellDataI.density(wPhaseIdx); + lambdaNW /= cellDataI.density(nPhaseIdx); + } - switch (saturationType_) - { - case Sw: - { - if (sourceVec[wPhaseIdx] < 0 && problem_.variables().saturation()[globalIdxI] < threshold_) - sourceVec[wPhaseIdx] = 0.0; + switch (saturationType_) + { + case Sw: + { + if (sourceVec[wPhaseIdx] < 0 && cellDataI.saturation(wPhaseIdx) < threshold_) + sourceVec[wPhaseIdx] = 0.0; - updateVec[globalIdxI] += sourceVec[wPhaseIdx] / porosity; - break; - } - case Sn: - { - if (sourceVec[nPhaseIdx] < 0 && problem_.variables().saturation()[globalIdxI] < threshold_) - sourceVec[nPhaseIdx] = 0.0; + updateVec[globalIdxI] += sourceVec[wPhaseIdx] / porosity; + break; + } + case Sn: + { + if (sourceVec[nPhaseIdx] < 0 && cellDataI.saturation(nPhaseIdx) < threshold_) + sourceVec[nPhaseIdx] = 0.0; - updateVec[globalIdxI] += sourceVec[nPhaseIdx] / porosity; - break; - } - } + updateVec[globalIdxI] += sourceVec[nPhaseIdx] / porosity; + break; + } + } - switch (velocityType_) - { - case vw: - { - //add cflFlux for time-stepping - evalCflFluxFunction().addFlux(lambdaW, lambdaNW, viscosityWI, - viscosityNWI, sourceVec[wPhaseIdx] * volume, *eIt, wPhaseIdx); - evalCflFluxFunction().addFlux(lambdaW, lambdaNW, viscosityWI, - viscosityNWI, sourceVec[nPhaseIdx] * volume, *eIt, nPhaseIdx); - break; - } - case vn: - { - //add cflFlux for time-stepping - evalCflFluxFunction().addFlux(lambdaW, lambdaNW, viscosityWI, - viscosityNWI, sourceVec[nPhaseIdx] * volume, *eIt, nPhaseIdx); - evalCflFluxFunction().addFlux(lambdaW, lambdaNW, viscosityWI, - viscosityNWI, sourceVec[wPhaseIdx] * volume, *eIt, wPhaseIdx); - break; - } - case vt: - { + switch (velocityType_) + { + case vt: + { + //add cflFlux for time-stepping + evalCflFluxFunction().addFlux(lambdaW, lambdaNW, viscosityW, viscosityNW, + (sourceVec[wPhaseIdx] + sourceVec[nPhaseIdx]) * volume, *eIt); + break; + } + default: + { //add cflFlux for time-stepping - evalCflFluxFunction().addFlux(lambdaW, lambdaNW, viscosityWI, - viscosityNWI, (sourceVec[wPhaseIdx]+sourceVec[nPhaseIdx]) * volume, *eIt); - break; - } - } + evalCflFluxFunction().addFlux(lambdaW, lambdaNW, viscosityW, viscosityNW, sourceVec[wPhaseIdx] * volume, + *eIt, wPhaseIdx); + evalCflFluxFunction().addFlux(lambdaW, lambdaNW, viscosityW, viscosityNW, sourceVec[nPhaseIdx] * volume, + *eIt, nPhaseIdx); + break; + } + } //calculate time step - dt = std::min(dt, evalCflFluxFunction().getCflFluxFunction(globalPos, - *eIt) * (porosity * volume)); + dt = std::min(dt, evalCflFluxFunction().getCflFluxFunction(globalPos, *eIt) * (porosity * volume)); - problem_.variables().volumecorrection(globalIdxI) - = updateVec[globalIdxI]; + cellDataI.setUpdate(updateVec[globalIdxI]); } // end grid traversal } @@ -1083,97 +935,80 @@ 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) + ElementIterator eItEnd = problem_.gridView().template end<0>(); + for (ElementIterator eIt = problem_.gridView().template begin<0>(); eIt != eItEnd; ++eIt) { PrimaryVariables initSol(0.0); problem_.initial(initSol, *eIt); + + int globalIdx = problem_.variables().index(*eIt); + // initialize cell concentration - problem_.variables().saturation()[problem_.variables().index(*eIt)] - = initSol[saturationIdx]; + problem_.variables().primaryVariablesGlobal(satEqIdx)[globalIdx] = initSol[saturationIdx]; } return; } template<class TypeTag> -void FVSaturation2P<TypeTag>::updateMaterialLaws( - RepresentationType& saturation = *(new RepresentationType(0)), +void FVSaturation2P<TypeTag>::updateMaterialLaws(RepresentationType& saturation = *(new RepresentationType(0)), bool iterate = false) { - FluidState fluidState; + ElementIterator eItBegin = problem_.gridView().template begin<0>(); + + Scalar temp = problem_.temperature(*eItBegin); + Scalar pRef = problem_.referencePressure(*eItBegin); + Scalar densityW = WettingPhase::density(temp, pRef); + Scalar densityNW = NonwettingPhase::density(temp, pRef); + Scalar viscosityW = WettingPhase::viscosity(temp, pRef); + Scalar viscosityNW = NonwettingPhase::viscosity(temp, pRef); // 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) + ElementIterator eItEnd = problem_.gridView().template end<0>(); + for (ElementIterator eIt = eItBegin; eIt != eItEnd; ++eIt) { int globalIdx = problem_.variables().index(*eIt); - Scalar sat = 0; - if (!iterate) - { - sat = problem_.variables().saturation()[globalIdx]; - } - else - { - sat = saturation[globalIdx]; - } + CellData& cellData = problem_.variables().cellData(globalIdx); + + Scalar temperature = problem_.temperature(*eIt); //determine phase saturations from primary saturation variable Scalar satW = 0; - if (saturationType_ == Sw) + Scalar satNW = 0; + switch (saturationType_) + { + case Sw: { - satW = sat; + satW = problem_.variables().primaryVariablesGlobal(satEqIdx)[globalIdx]; + satNW = 1 - satW; + break; } - if (saturationType_ == Sn) + case Sn: { - satW = 1 - sat; + satNW = problem_.variables().primaryVariablesGlobal(satEqIdx)[globalIdx]; + satW = 1 - satNW; + break; + } } - Scalar temperature = problem_.temperature(*eIt); - Scalar referencePressure = problem_.referencePressure(*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); + Scalar pc = MaterialLaw::pC(problem_.spatialParameters().materialLawParams(*eIt), satW); + + cellData.setSaturation(wPhaseIdx, satW); + cellData.setSaturation(nPhaseIdx, satNW); + cellData.setCapillaryPressure(pc); // initialize mobilities - problem_.variables().mobilityWetting(globalIdx) - = MaterialLaw::krw( - problem_.spatialParameters().materialLawParams(*eIt), satW) - / problem_.variables().viscosityWetting(globalIdx); - problem_.variables().mobilityNonwetting(globalIdx) - = MaterialLaw::krn( - problem_.spatialParameters().materialLawParams(*eIt), satW) - / problem_.variables().viscosityNonwetting(globalIdx); - problem_.variables().capillaryPressure(globalIdx) - = MaterialLaw::pC( - problem_.spatialParameters().materialLawParams(*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)); + Scalar mobilityW = MaterialLaw::krw(problem_.spatialParameters().materialLawParams(*eIt), satW) / viscosityW; + Scalar mobilityNW = MaterialLaw::krn(problem_.spatialParameters().materialLawParams(*eIt), satW) / viscosityNW; + + // initialize mobilities + cellData.mobility(wPhaseIdx) = mobilityW; + cellData.mobility(nPhaseIdx) = mobilityNW; + + //initialize fractional flow functions + cellData.fracFlowFunc(wPhaseIdx) = mobilityW / (mobilityW + mobilityNW); + cellData.fracFlowFunc(nPhaseIdx) = mobilityNW / (mobilityW + mobilityNW); } return; } diff --git a/dumux/decoupled/2p/transport/fv/gravitypart.hh b/dumux/decoupled/2p/transport/fv/gravitypart.hh index 58d5dabc007033741b6d59c2bc76db4384b535de..df47bfeaad7dea9f92caf05530e5476b70650894 100644 --- a/dumux/decoupled/2p/transport/fv/gravitypart.hh +++ b/dumux/decoupled/2p/transport/fv/gravitypart.hh @@ -52,13 +52,17 @@ private: 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_TYPE(TypeTag, PTAG(TwoPIndices)) Indices; + typedef typename GET_PROP_TYPE(TypeTag, PTAG(Indices)) Indices; typedef typename GET_PROP_TYPE(TypeTag, PTAG(SpatialParameters)) SpatialParameters; typedef typename SpatialParameters::MaterialLaw MaterialLaw; typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidSystem)) FluidSystem; typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidState)) FluidState; + typedef typename GET_PROP_TYPE(TypeTag, PTAG(WettingPhase)) WettingPhase; + typedef typename GET_PROP_TYPE(TypeTag, PTAG(NonwettingPhase)) NonwettingPhase; + + typedef typename GET_PROP_TYPE(TypeTag, PTAG(CellData)) CellData; enum { @@ -90,8 +94,9 @@ public: { Scalar temperature = problem_.temperature(element); Scalar referencePressure = problem_.referencePressure(element); - FluidState fluidState; - fluidState.update(satI, referencePressure, referencePressure, temperature);//not for compressible flow -> thus constant + + Scalar densityW = WettingPhase::density(temperature, referencePressure); + Scalar densityNW = NonwettingPhase::density(temperature, referencePressure); IntersectionIterator isItEnd = problem_.gridView().iend(element); IntersectionIterator isIt = problem_.gridView().ibegin(element); @@ -101,38 +106,28 @@ public: break; } int globalIdxI = problem_.variables().index(element); + CellData& cellDataI = problem_.variables().cellData(globalIdxI); // get geometry type of face //Dune::GeometryType faceGT = isIt->geometryInInside().type(); - Scalar potentialW = problem_.variables().potentialWetting(globalIdxI, indexInInside); - Scalar potentialNW = problem_.variables().potentialNonwetting(globalIdxI, indexInInside); - //get lambda_bar = lambda_n*f_w Scalar lambdaWI = 0; Scalar lambdaNWI = 0; Scalar lambdaWJ = 0; Scalar lambdaNWJ = 0; - Scalar densityWI = 0; - Scalar densityNWI = 0; - Scalar densityWJ = 0; - Scalar densityNWJ = 0; if (preComput_) { - lambdaWI=problem_.variables().mobilityWetting(globalIdxI); - lambdaNWI=problem_.variables().mobilityNonwetting(globalIdxI); - densityWI = problem_.variables().densityWetting(globalIdxI); - densityNWI = problem_.variables().densityNonwetting(globalIdxI); + lambdaWI=cellDataI.mobility(wPhaseIdx); + lambdaNWI=cellDataI.mobility(nPhaseIdx); } else { lambdaWI = MaterialLaw::krw(problem_.spatialParameters().materialLawParams(element), satI); - lambdaWI /= FluidSystem::phaseViscosity(wPhaseIdx, temperature, referencePressure, fluidState); + lambdaWI /= FluidSystem::viscosity(fluidState, wPhaseIdx); lambdaNWI = MaterialLaw::krn(problem_.spatialParameters().materialLawParams(element), satI); - lambdaNWI /= FluidSystem::phaseViscosity(nPhaseIdx, temperature, referencePressure, fluidState); - densityWI = FluidSystem::phaseDensity(wPhaseIdx, temperature, referencePressure, fluidState); - densityNWI = FluidSystem::phaseDensity(nPhaseIdx, temperature, referencePressure, fluidState); + lambdaNWI /= FluidSystem::viscosity(fluidState, nPhaseIdx); } FieldMatrix meanPermeability(0); @@ -143,6 +138,7 @@ public: ElementPointer neighborPointer = isIt->outside(); int globalIdxJ = problem_.variables().index(*neighborPointer); + CellData& cellDataJ = problem_.variables().cellData(globalIdxJ); // get permeability problem_.spatialParameters().meanK(meanPermeability, @@ -152,19 +148,15 @@ public: //get lambda_bar = lambda_n*f_w if (preComput_) { - lambdaWJ=problem_.variables().mobilityWetting(globalIdxJ); - lambdaNWJ=problem_.variables().mobilityNonwetting(globalIdxJ); - densityWJ = problem_.variables().densityWetting(globalIdxJ); - densityNWJ = problem_.variables().densityNonwetting(globalIdxJ); + lambdaWJ=cellDataJ.mobility(wPhaseIdx); + lambdaNWJ=cellDataJ.mobility(nPhaseIdx); } else { lambdaWJ = MaterialLaw::krw(problem_.spatialParameters().materialLawParams(*neighborPointer), satJ); - lambdaWJ /= FluidSystem::phaseViscosity(wPhaseIdx, temperature, referencePressure, fluidState); + lambdaWJ /= FluidSystem::viscosity(fluidState, wPhaseIdx); lambdaNWJ = MaterialLaw::krn(problem_.spatialParameters().materialLawParams(*neighborPointer), satJ); - lambdaNWJ /= FluidSystem::phaseViscosity(nPhaseIdx, temperature, referencePressure, fluidState); - densityWJ = FluidSystem::phaseDensity(wPhaseIdx, temperature, referencePressure, fluidState); - densityNWJ = FluidSystem::phaseDensity(nPhaseIdx, temperature, referencePressure, fluidState); + lambdaNWJ /= FluidSystem::viscosity(fluidState, nPhaseIdx); } } else @@ -175,25 +167,22 @@ public: //calculate lambda_n*f_w at the boundary lambdaWJ = MaterialLaw::krw(problem_.spatialParameters().materialLawParams(element), satJ); - lambdaWJ /= FluidSystem::phaseViscosity(wPhaseIdx, temperature, referencePressure, fluidState); + lambdaWJ /= FluidSystem::viscosity(fluidState, wPhaseIdx); lambdaNWJ = MaterialLaw::krn(problem_.spatialParameters().materialLawParams(element), satJ); - lambdaNWJ /= FluidSystem::phaseViscosity(nPhaseIdx, temperature, referencePressure, fluidState); - densityWJ = FluidSystem::phaseDensity(wPhaseIdx, temperature, referencePressure, fluidState); - densityNWJ = FluidSystem::phaseDensity(nPhaseIdx, temperature, referencePressure, fluidState); + lambdaNWJ /= FluidSystem::viscosity(fluidState, nPhaseIdx); } // set result to K*grad(pc) FieldVector result(0); meanPermeability.umv(problem_.gravity(), result); + Scalar potentialW = cellDataI.fluxData().potential(wPhaseIdx, indexInInside); + Scalar potentialNW = cellDataI.fluxData().potential(nPhaseIdx, indexInInside); + Scalar lambdaW = (potentialW >= 0) ? lambdaWI : lambdaWJ; lambdaW = (potentialW == 0) ? 0.5 * (lambdaWI + lambdaWJ) : lambdaW; Scalar lambdaNW = (potentialNW >= 0) ? lambdaNWI : lambdaNWJ; lambdaNW = (potentialNW == 0) ? 0.5 * (lambdaNWI + lambdaNWJ) : lambdaNW; - Scalar densityW = (potentialW >= 0) ? densityWI : densityWJ; - densityW = (potentialW == 0.) ? 0.5 * (densityWI + densityWJ) : densityW; - Scalar densityNW = (potentialNW >= 0) ? densityNWI : densityNWJ; - densityNW = (potentialNW == 0.) ? 0.5 * (densityNWI + densityNWJ) : densityNW; // set result to f_w*lambda_n*K*grad(pc) result *= lambdaW*lambdaNW/(lambdaW+lambdaNW); diff --git a/dumux/decoupled/2p/transport/transportproblem2p.hh b/dumux/decoupled/2p/transport/transportproblem2p.hh index d85e51117fe4d7967eb3508593c4d98bc4c8154d..53c4f0bb9606ea2cca37162acd173a0b93847c0a 100644 --- a/dumux/decoupled/2p/transport/transportproblem2p.hh +++ b/dumux/decoupled/2p/transport/transportproblem2p.hh @@ -29,8 +29,10 @@ #define DUMUX_TRANSPORTPROBLEM_2P_HH #include <dumux/decoupled/common/onemodelproblem.hh> -#include <dumux/decoupled/2p/variableclass2p.hh> -#include <dumux/material/old_fluidsystems/2p_system.hh> +#include <dumux/decoupled/common/variableclass.hh> +#include <dumux/decoupled/2p/cellData2p.hh> +#include <dumux/material/fluidsystems/2pimmisciblefluidsystem.hh> +#include <dumux/material/fluidstates/isoimmisciblefluidstate.hh> #include <dumux/decoupled/2p/2pproperties.hh> @@ -65,10 +67,16 @@ class TransportProblem2P : public OneModelProblem<TypeTag> typedef typename GridView::Traits::template Codim<0>::Entity Element; + typedef typename GET_PROP_TYPE(TypeTag, PTAG(Indices)) Indices; + enum { dim = Grid::dimension, dimWorld = Grid::dimensionworld }; + enum + { + transportEqIdx = Indices::transportEqIdx + }; typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition; @@ -246,7 +254,7 @@ public: void timeIntegration() { // allocate temporary vectors for the updates - Solution k1 = this->asImp_().variables().saturation(); + Solution k1 = asImp_().variables().primaryVariablesGlobal(transportEqIdx); Scalar t = this->timeManager().time(); Scalar dt = 1e100; @@ -259,7 +267,13 @@ public: this->timeManager().setTimeStepSize(dt); // explicit Euler: Sat <- Sat + dt*N(Sat) - this->asImp_().variables().saturation() += (k1 *= dt); + int size = this->gridView().size(0); + Solution& newSol = asImp_().variables().primaryVariablesGlobal(transportEqIdx); + for (int i = 0; i < size; i++) + { + newSol[i] += (k1[i] *= dt); + this->model().updateSaturationSolution(i, newSol[i][0]); + } } // \}