diff --git a/dumux/discretization/fickslaw.hh b/dumux/discretization/fickslaw.hh index 9d0bbc0a840c615246e2ebf9186239812aead245..3058e6524105edca9b254904fb30dcdf757d89e5 100644 --- a/dumux/discretization/fickslaw.hh +++ b/dumux/discretization/fickslaw.hh @@ -45,5 +45,6 @@ using FicksLaw = FicksLawImplementation<TypeTag, GET_PROP_VALUE(TypeTag, Discret #include <dumux/discretization/cellcentered/tpfa/fickslaw.hh> #include <dumux/discretization/cellcentered/mpfa/fickslaw.hh> #include <dumux/discretization/box/fickslaw.hh> +#include <dumux/discretization/staggered/freeflow/fickslaw.hh> #endif diff --git a/dumux/discretization/staggered/freeflow/fickslaw.hh b/dumux/discretization/staggered/freeflow/fickslaw.hh new file mode 100644 index 0000000000000000000000000000000000000000..15c557c349423ef7374872e46334562ab3fe595e --- /dev/null +++ b/dumux/discretization/staggered/freeflow/fickslaw.hh @@ -0,0 +1,195 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * 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/>. * + *****************************************************************************/ +/*! + * \file + * \brief This file contains the data which is required to calculate + * diffusive mass fluxes due to molecular diffusion with Fick's law. + */ +#ifndef DUMUX_DISCRETIZATION_STAGGERED_FICKS_LAW_HH +#define DUMUX_DISCRETIZATION_STAGGERED_FICKS_LAW_HH + +#include <dune/common/float_cmp.hh> + +#include <dumux/common/math.hh> +#include <dumux/common/parameters.hh> + +#include <dumux/implicit/properties.hh> +#include <dumux/discretization/methods.hh> +#include <dumux/discretization/fluxvariablescaching.hh> + +namespace Dumux +{ + +namespace Properties +{ +// forward declaration of properties +NEW_PROP_TAG(NumPhases); +NEW_PROP_TAG(ReplaceCompEqIdx); +NEW_PROP_TAG(UseMoles); +} + +/*! + * \ingroup StaggeredFicksLaw + * \brief Specialization of Fick's Law for the staggered free flow method. + */ +template <class TypeTag> +class FicksLawImplementation<TypeTag, DiscretizationMethods::Staggered > +{ + using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Problem = typename GET_PROP_TYPE(TypeTag, Problem); + using SubControlVolume = typename GET_PROP_TYPE(TypeTag, SubControlVolume); + using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); + using GridView = typename GET_PROP_TYPE(TypeTag, GridView); + using IndexType = typename GridView::IndexSet::IndexType; + using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry); + using VolumeVariables = typename GET_PROP_TYPE(TypeTag, VolumeVariables); + using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables); + using Element = typename GridView::template Codim<0>::Entity; + using ElementFluxVariablesCache = typename GET_PROP_TYPE(TypeTag, ElementFluxVariablesCache); + using FluxVariablesCache = typename GET_PROP_TYPE(TypeTag, FluxVariablesCache); + using CellCenterPrimaryVariables = typename GET_PROP_TYPE(TypeTag, CellCenterPrimaryVariables); + using Indices = typename GET_PROP_TYPE(TypeTag, Indices); + + static const int dim = GridView::dimension; + static const int dimWorld = GridView::dimensionworld; + static const int numPhases = GET_PROP_VALUE(TypeTag, NumPhases); + + using DimWorldMatrix = Dune::FieldMatrix<Scalar, dimWorld, dimWorld>; + using GlobalPosition = Dune::FieldVector<Scalar, dimWorld>; + + static constexpr auto numComponents = GET_PROP_VALUE(TypeTag, NumComponents); + + static constexpr bool useMoles = GET_PROP_VALUE(TypeTag, UseMoles); + + //! The index of the component balance equation that gets replaced with the total mass balance + static const int replaceCompEqIdx = GET_PROP_VALUE(TypeTag, ReplaceCompEqIdx); + + enum { + + pressureIdx = Indices::pressureIdx, + velocityIdx = Indices::velocityIdx, + + massBalanceIdx = Indices::massBalanceIdx, + momentumBalanceIdx = Indices::momentumBalanceIdx, + conti0EqIdx = Indices::conti0EqIdx + }; + +public: + // state the discretization method this implementation belongs to + static const DiscretizationMethods myDiscretizationMethod = DiscretizationMethods::Staggered; + + //! state the type for the corresponding cache and its filler + //! We don't cache anything for this law + using Cache = FluxVariablesCaching::EmptyDiffusionCache; + using CacheFiller = FluxVariablesCaching::EmptyCacheFiller<TypeTag>; + + static CellCenterPrimaryVariables diffusiveFluxForCellCenter(const Problem& problem, + const FVElementGeometry& fvGeometry, + const ElementVolumeVariables& elemVolVars, + const SubControlVolumeFace &scvf) + { + CellCenterPrimaryVariables flux(0.0); + + const auto& insideScv = fvGeometry.scv(scvf.insideScvIdx()); + const auto& insideVolVars = elemVolVars[insideScv]; + const auto& outsideVolVars = scvf.boundary() ? insideVolVars : elemVolVars[scvf.outsideScvIdx()]; + + const Scalar insideDensity = useMoles ? insideVolVars.molarDensity() : insideVolVars.density(); + + for(int compIdx = 1; compIdx < numComponents; ++compIdx) + { + auto eqIdx = conti0EqIdx + compIdx; + + const Scalar tij = transmissibility_(problem, fvGeometry, elemVolVars, scvf, compIdx); + const Scalar insideFraction = useMoles ? insideVolVars.moleFraction(0, compIdx) : insideVolVars.massFraction(0, compIdx); + + if(scvf.boundary()) + { + const auto bcTypes = problem.boundaryTypesAtPos(scvf.center()); + if(bcTypes.isOutflow(eqIdx)) + return flux; + else if(bcTypes.isNeumann(eqIdx)) + return flux; // TODO: implement neumann + else + { + const Scalar dirichletFraction = problem.dirichletAtPos(scvf.center())[eqIdx]; + flux[eqIdx] = insideDensity * tij * (insideFraction - dirichletFraction); + } + } + else + { + const Scalar outsideDensity = useMoles ? outsideVolVars.molarDensity() : outsideVolVars.density(); + const Scalar avgDensity = 0.5*(insideDensity + outsideDensity); + const Scalar outsideFraction = useMoles ? outsideVolVars.moleFraction(0, compIdx) : outsideVolVars.massFraction(0, compIdx); + flux[eqIdx] = avgDensity * tij * (insideFraction - outsideFraction); + } + } + + if (replaceCompEqIdx >= numComponents) + { + const Scalar cumulativeFlux = std::accumulate(flux.begin(), flux.end(), 0.0); + flux[0] = - cumulativeFlux; + } + + return flux; + } + + static Scalar transmissibility_(const Problem& problem, + const FVElementGeometry& fvGeometry, + const ElementVolumeVariables& elemVolVars, + const SubControlVolumeFace& scvf, + const int compIdx) + { + Scalar tij = 0.0; + const auto& insideScv = fvGeometry.scv(scvf.insideScvIdx()); + const auto& outsideScv = fvGeometry.scv(scvf.outsideScvIdx()); + const auto& insideVolVars = elemVolVars[insideScv]; + const auto& outsideVolVars = scvf.boundary() ? insideVolVars : elemVolVars[scvf.outsideScvIdx()]; + + const Scalar insideDistance = (insideScv.dofPosition() - scvf.ipGlobal()).two_norm(); + const Scalar insideD = insideVolVars.diffusionCoefficient(0, compIdx); + const Scalar ti = calculateOmega_(insideDistance, insideD, 1.0); + + if(scvf.boundary()) + tij = scvf.area() * ti; + else + { + const Scalar outsideDistance = (outsideScv.dofPosition() - scvf.ipGlobal()).two_norm(); + const Scalar outsideD = outsideVolVars.diffusionCoefficient(0, compIdx); + const Scalar tj = calculateOmega_(outsideDistance, outsideD, 1.0); + + tij = scvf.area()*(ti * tj)/(ti + tj); + } + return tij; + } + + static Scalar calculateOmega_(const Scalar distance, + const Scalar D, + const Scalar extrusionFactor) + { + Scalar omega = D / distance; + omega *= extrusionFactor; + + return omega; + } + +}; +} // end namespace + +#endif diff --git a/dumux/freeflow/staggered/fluxvariables.hh b/dumux/freeflow/staggered/fluxvariables.hh index 4679085dac9e968c5ecc1e248c1cf11599a0bea3..f7c2698574a47975fdc5a58f697239f4c0a2e95d 100644 --- a/dumux/freeflow/staggered/fluxvariables.hh +++ b/dumux/freeflow/staggered/fluxvariables.hh @@ -367,217 +367,6 @@ private: } }; - -// specialization for miscible, isothermal flow -template<class TypeTag> -class FreeFlowFluxVariablesImpl<TypeTag, true, false> : public FreeFlowFluxVariablesImpl<TypeTag, false, false> -{ - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using Problem = typename GET_PROP_TYPE(TypeTag, Problem); - using Element = typename GridView::template Codim<0>::Entity; - using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry); - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - using Indices = typename GET_PROP_TYPE(TypeTag, Indices); - using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables); - using GlobalFaceVars = typename GET_PROP_TYPE(TypeTag, GlobalFaceVars); - using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); - using FluxVariablesCache = typename GET_PROP_TYPE(TypeTag, FluxVariablesCache); - using CellCenterPrimaryVariables = typename GET_PROP_TYPE(TypeTag, CellCenterPrimaryVariables); - using FacePrimaryVariables = typename GET_PROP_TYPE(TypeTag, FacePrimaryVariables); - using IndexType = typename GridView::IndexSet::IndexType; - using Stencil = std::vector<IndexType>; - - static constexpr bool navierStokes = GET_PROP_VALUE(TypeTag, EnableInertiaTerms); - static constexpr auto numComponents = GET_PROP_VALUE(TypeTag, NumComponents); - - static constexpr bool useMoles = true; - - //! The index of the component balance equation that gets replaced with the total mass balance - static const int replaceCompEqIdx = GET_PROP_VALUE(TypeTag, ReplaceCompEqIdx); - - using ParentType = FreeFlowFluxVariablesImpl<TypeTag, false, false>; - - enum { - // grid and world dimension - dim = GridView::dimension, - dimWorld = GridView::dimensionworld, - - pressureIdx = Indices::pressureIdx, - velocityIdx = Indices::velocityIdx, - - massBalanceIdx = Indices::massBalanceIdx, - momentumBalanceIdx = Indices::momentumBalanceIdx, - conti0EqIdx = Indices::conti0EqIdx - }; - -public: - CellCenterPrimaryVariables computeFluxForCellCenter(const Problem& problem, - const Element &element, - const FVElementGeometry& fvGeometry, - const ElementVolumeVariables& elemVolVars, - const GlobalFaceVars& globalFaceVars, - const SubControlVolumeFace &scvf, - const FluxVariablesCache& fluxVarsCache) - { - CellCenterPrimaryVariables flux(0.0); - - flux += advectiveFluxForCellCenter_(problem, fvGeometry, elemVolVars, globalFaceVars, scvf); - flux += diffusiveFluxForCellCenter_(problem, fvGeometry, elemVolVars, scvf); - return flux; - } - -private: - - CellCenterPrimaryVariables advectiveFluxForCellCenter_(const Problem& problem, - const FVElementGeometry& fvGeometry, - const ElementVolumeVariables& elemVolVars, - const GlobalFaceVars& globalFaceVars, - const SubControlVolumeFace &scvf) - { - CellCenterPrimaryVariables flux(0.0); - - const auto& insideScv = fvGeometry.scv(scvf.insideScvIdx()); - const auto& insideVolVars = elemVolVars[insideScv]; - - // if we are on an inflow/outflow boundary, use the volVars of the element itself - const auto& outsideVolVars = scvf.boundary() ? insideVolVars : elemVolVars[scvf.outsideScvIdx()]; - - const Scalar velocity = globalFaceVars.faceVars(scvf.dofIndex()).velocity(); - - const bool insideIsUpstream = sign(scvf.outerNormalScalar()) == sign(velocity) ? true : false; - const auto& upstreamVolVars = insideIsUpstream ? insideVolVars : outsideVolVars; - const auto& downstreamVolVars = insideIsUpstream ? insideVolVars : outsideVolVars; - - const Scalar upWindWeight = GET_PROP_VALUE(TypeTag, ImplicitUpwindWeight); - - for (int compIdx = 0; compIdx < numComponents; ++compIdx) - { - // get equation index - auto eqIdx = conti0EqIdx + compIdx; - - const Scalar upstreamDensity = useMoles ? upstreamVolVars.molarDensity() : upstreamVolVars.density(); - const Scalar downstreamDensity = useMoles ? downstreamVolVars.molarDensity() : downstreamVolVars.density(); - const Scalar upstreamFraction = useMoles ? upstreamVolVars.moleFraction(0, compIdx) : upstreamVolVars.massFraction(0, compIdx); - const Scalar downstreamFraction = useMoles ? downstreamVolVars.moleFraction(0, compIdx) : downstreamVolVars.massFraction(0, compIdx); - - Scalar advFlux = 0.0; - - if(scvf.boundary() && eqIdx > conti0EqIdx) - { - const auto bcTypes = problem.boundaryTypesAtPos(scvf.center()); - if(bcTypes.isDirichlet(eqIdx)) - advFlux = upstreamDensity * problem.dirichletAtPos(scvf.center())[eqIdx] * velocity; - if(bcTypes.isOutflow(eqIdx)) - advFlux = upstreamDensity * upstreamFraction * velocity; - } - else - advFlux = (upWindWeight * upstreamDensity * upstreamFraction + - (1.0 - upWindWeight) * downstreamDensity * downstreamFraction) * velocity; - - if (eqIdx != replaceCompEqIdx) - flux[eqIdx] += advFlux; - - // in case one balance is substituted by the total mass balance - if (replaceCompEqIdx < numComponents) - flux[replaceCompEqIdx] += advFlux; - } - - flux *= scvf.area() * sign(scvf.outerNormalScalar()); - return flux; - } - - - CellCenterPrimaryVariables diffusiveFluxForCellCenter_(const Problem& problem, - const FVElementGeometry& fvGeometry, - const ElementVolumeVariables& elemVolVars, - const SubControlVolumeFace &scvf) - { - CellCenterPrimaryVariables flux(0.0); - - const auto& insideScv = fvGeometry.scv(scvf.insideScvIdx()); - const auto& insideVolVars = elemVolVars[insideScv]; - const auto& outsideVolVars = scvf.boundary() ? insideVolVars : elemVolVars[scvf.outsideScvIdx()]; - - const Scalar insideDensity = useMoles ? insideVolVars.molarDensity() : insideVolVars.density(); - - for(int compIdx = 1; compIdx < numComponents; ++compIdx) - { - auto eqIdx = conti0EqIdx + compIdx; - - const Scalar tij = transmissibility_(problem, fvGeometry, elemVolVars, scvf, compIdx); - const Scalar insideFraction = useMoles ? insideVolVars.moleFraction(0, compIdx) : insideVolVars.massFraction(0, compIdx); - - if(scvf.boundary()) - { - const auto bcTypes = problem.boundaryTypesAtPos(scvf.center()); - if(bcTypes.isOutflow(eqIdx)) - return flux; - else if(bcTypes.isNeumann(eqIdx)) - return flux; // TODO: implement neumann - else - { - const Scalar dirichletFraction = problem.dirichletAtPos(scvf.center())[eqIdx]; - flux[eqIdx] = insideDensity * tij * (insideFraction - dirichletFraction); - } - } - else - { - const Scalar outsideDensity = useMoles ? outsideVolVars.molarDensity() : outsideVolVars.density(); - const Scalar avgDensity = 0.5*(insideDensity + outsideDensity); - const Scalar outsideFraction = useMoles ? outsideVolVars.moleFraction(0, compIdx) : outsideVolVars.massFraction(0, compIdx); - flux[eqIdx] = avgDensity * tij * (insideFraction - outsideFraction); - } - } - - if (replaceCompEqIdx >= numComponents) - { - const Scalar cumulativeFlux = std::accumulate(flux.begin(), flux.end(), 0.0); - flux[0] = - cumulativeFlux; - } - - return flux; - } - - static Scalar transmissibility_(const Problem& problem, - const FVElementGeometry& fvGeometry, - const ElementVolumeVariables& elemVolVars, - const SubControlVolumeFace& scvf, - const int compIdx) - { - Scalar tij = 0.0; - const auto& insideScv = fvGeometry.scv(scvf.insideScvIdx()); - const auto& outsideScv = fvGeometry.scv(scvf.outsideScvIdx()); - const auto& insideVolVars = elemVolVars[insideScv]; - const auto& outsideVolVars = scvf.boundary() ? insideVolVars : elemVolVars[scvf.outsideScvIdx()]; - - const Scalar insideDistance = (insideScv.dofPosition() - scvf.ipGlobal()).two_norm(); - const Scalar insideD = insideVolVars.diffusionCoefficient(0, compIdx); - const Scalar ti = calculateOmega_(insideDistance, insideD, 1.0); - - if(scvf.boundary()) - tij = scvf.area() * ti; - else - { - const Scalar outsideDistance = (outsideScv.dofPosition() - scvf.ipGlobal()).two_norm(); - const Scalar outsideD = outsideVolVars.diffusionCoefficient(0, compIdx); - const Scalar tj = calculateOmega_(outsideDistance, outsideD, 1.0); - - tij = scvf.area()*(ti * tj)/(ti + tj); - } - return tij; - } - - static Scalar calculateOmega_(const Scalar distance, - const Scalar D, - const Scalar extrusionFactor) - { - Scalar omega = D / distance; - omega *= extrusionFactor; - - return omega; - } -}; - } // end namespace #endif diff --git a/dumux/freeflow/staggerednc/fluxvariables.hh b/dumux/freeflow/staggerednc/fluxvariables.hh new file mode 100644 index 0000000000000000000000000000000000000000..44598f6c6081b1e12b008b9430384ae3115d6a7a --- /dev/null +++ b/dumux/freeflow/staggerednc/fluxvariables.hh @@ -0,0 +1,178 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * 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/>. * + *****************************************************************************/ +/*! + * \file + * \brief Base class for the flux variables + */ +#ifndef DUMUX_FREELOW_IMPLICIT_NC_FLUXVARIABLES_HH +#define DUMUX_FREELOW_IMPLICIT_NC_FLUXVARIABLES_HH + +#include <dumux/implicit/properties.hh> +#include <dumux/discretization/fluxvariablesbase.hh> +#include "../staggered/fluxvariables.hh" + +namespace Dumux +{ + +namespace Properties +{ +// forward declaration +NEW_PROP_TAG(EnableComponentTransport); +NEW_PROP_TAG(EnableEnergyBalance); +NEW_PROP_TAG(EnableInertiaTerms); +} + +// // forward declaration +// template<class TypeTag, bool enableComponentTransport, bool enableEnergyBalance> +// class FreeFlowFluxVariablesImpl; + +/*! + * \ingroup ImplicitModel + * \brief The flux variables class + * specializations are provided for combinations of physical processes + * \note Not all specializations are currently implemented + */ +// template<class TypeTag> +// using FreeFlowFluxVariables = FreeFlowFluxVariablesImpl<TypeTag, GET_PROP_VALUE(TypeTag, EnableComponentTransport), +// GET_PROP_VALUE(TypeTag, EnableEnergyBalance)>; + +// specialization for miscible, isothermal flow +template<class TypeTag> +class FreeFlowFluxVariablesImpl<TypeTag, true, false> : public FreeFlowFluxVariablesImpl<TypeTag, false, false> +{ + using GridView = typename GET_PROP_TYPE(TypeTag, GridView); + using Problem = typename GET_PROP_TYPE(TypeTag, Problem); + using Element = typename GridView::template Codim<0>::Entity; + using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry); + using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Indices = typename GET_PROP_TYPE(TypeTag, Indices); + using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables); + using GlobalFaceVars = typename GET_PROP_TYPE(TypeTag, GlobalFaceVars); + using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); + using FluxVariablesCache = typename GET_PROP_TYPE(TypeTag, FluxVariablesCache); + using CellCenterPrimaryVariables = typename GET_PROP_TYPE(TypeTag, CellCenterPrimaryVariables); + using FacePrimaryVariables = typename GET_PROP_TYPE(TypeTag, FacePrimaryVariables); + using IndexType = typename GridView::IndexSet::IndexType; + using Stencil = std::vector<IndexType>; + + using MolecularDiffusionType = typename GET_PROP_TYPE(TypeTag, MolecularDiffusionType); + + static constexpr bool navierStokes = GET_PROP_VALUE(TypeTag, EnableInertiaTerms); + static constexpr auto numComponents = GET_PROP_VALUE(TypeTag, NumComponents); + + static constexpr bool useMoles = GET_PROP_VALUE(TypeTag, UseMoles); + + //! The index of the component balance equation that gets replaced with the total mass balance + static const int replaceCompEqIdx = GET_PROP_VALUE(TypeTag, ReplaceCompEqIdx); + + using ParentType = FreeFlowFluxVariablesImpl<TypeTag, false, false>; + + enum { + // grid and world dimension + dim = GridView::dimension, + dimWorld = GridView::dimensionworld, + + pressureIdx = Indices::pressureIdx, + velocityIdx = Indices::velocityIdx, + + massBalanceIdx = Indices::massBalanceIdx, + momentumBalanceIdx = Indices::momentumBalanceIdx, + conti0EqIdx = Indices::conti0EqIdx + }; + +public: + CellCenterPrimaryVariables computeFluxForCellCenter(const Problem& problem, + const Element &element, + const FVElementGeometry& fvGeometry, + const ElementVolumeVariables& elemVolVars, + const GlobalFaceVars& globalFaceVars, + const SubControlVolumeFace &scvf, + const FluxVariablesCache& fluxVarsCache) + { + CellCenterPrimaryVariables flux(0.0); + + flux += advectiveFluxForCellCenter_(problem, fvGeometry, elemVolVars, globalFaceVars, scvf); + flux += MolecularDiffusionType::diffusiveFluxForCellCenter(problem, fvGeometry, elemVolVars, scvf); + return flux; + } + +private: + + CellCenterPrimaryVariables advectiveFluxForCellCenter_(const Problem& problem, + const FVElementGeometry& fvGeometry, + const ElementVolumeVariables& elemVolVars, + const GlobalFaceVars& globalFaceVars, + const SubControlVolumeFace &scvf) + { + CellCenterPrimaryVariables flux(0.0); + + const auto& insideScv = fvGeometry.scv(scvf.insideScvIdx()); + const auto& insideVolVars = elemVolVars[insideScv]; + + // if we are on an inflow/outflow boundary, use the volVars of the element itself + const auto& outsideVolVars = scvf.boundary() ? insideVolVars : elemVolVars[scvf.outsideScvIdx()]; + + const Scalar velocity = globalFaceVars.faceVars(scvf.dofIndex()).velocity(); + + const bool insideIsUpstream = sign(scvf.outerNormalScalar()) == sign(velocity) ? true : false; + const auto& upstreamVolVars = insideIsUpstream ? insideVolVars : outsideVolVars; + const auto& downstreamVolVars = insideIsUpstream ? insideVolVars : outsideVolVars; + + const Scalar upWindWeight = GET_PROP_VALUE(TypeTag, ImplicitUpwindWeight); + + for (int compIdx = 0; compIdx < numComponents; ++compIdx) + { + // get equation index + auto eqIdx = conti0EqIdx + compIdx; + + const Scalar upstreamDensity = useMoles ? upstreamVolVars.molarDensity() : upstreamVolVars.density(); + const Scalar downstreamDensity = useMoles ? downstreamVolVars.molarDensity() : downstreamVolVars.density(); + const Scalar upstreamFraction = useMoles ? upstreamVolVars.moleFraction(0, compIdx) : upstreamVolVars.massFraction(0, compIdx); + const Scalar downstreamFraction = useMoles ? downstreamVolVars.moleFraction(0, compIdx) : downstreamVolVars.massFraction(0, compIdx); + + Scalar advFlux = 0.0; + + if(scvf.boundary() && eqIdx > conti0EqIdx) + { + const auto bcTypes = problem.boundaryTypesAtPos(scvf.center()); + if(bcTypes.isDirichlet(eqIdx)) + advFlux = upstreamDensity * problem.dirichletAtPos(scvf.center())[eqIdx] * velocity; + if(bcTypes.isOutflow(eqIdx)) + advFlux = upstreamDensity * upstreamFraction * velocity; + } + else + advFlux = (upWindWeight * upstreamDensity * upstreamFraction + + (1.0 - upWindWeight) * downstreamDensity * downstreamFraction) * velocity; + + if (eqIdx != replaceCompEqIdx) + flux[eqIdx] += advFlux; + + // in case one balance is substituted by the total mass balance + if (replaceCompEqIdx < numComponents) + flux[replaceCompEqIdx] += advFlux; + } + + flux *= scvf.area() * sign(scvf.outerNormalScalar()); + return flux; + } +}; + +} // end namespace + +#endif diff --git a/dumux/freeflow/staggerednc/localresidual.hh b/dumux/freeflow/staggerednc/localresidual.hh index 6b085a835b789f33ee98442291c3671641c52f90..9496f9ca7a2ebbd2c0de967c9461538765c356fa 100644 --- a/dumux/freeflow/staggerednc/localresidual.hh +++ b/dumux/freeflow/staggerednc/localresidual.hh @@ -111,6 +111,8 @@ class StaggeredNavierStokesResidualImpl<TypeTag, true, false> : public Staggered static constexpr bool navierStokes = GET_PROP_VALUE(TypeTag, EnableInertiaTerms); static constexpr int numComponents = GET_PROP_VALUE(TypeTag, NumComponents); + static constexpr bool useMoles = GET_PROP_VALUE(TypeTag, UseMoles); + static constexpr int numPhases = GET_PROP_VALUE(TypeTag, NumPhases); //! The index of the component balance equation that gets replaced with the total mass balance @@ -126,8 +128,7 @@ class StaggeredNavierStokesResidualImpl<TypeTag, true, false> : public Staggered * the implicit euler time derivative here */ CellCenterPrimaryVariables computeStorageForCellCenter(const SubControlVolume& scv, - const VolumeVariables& volVars, - bool useMoles = true) const + const VolumeVariables& volVars) const { CellCenterPrimaryVariables storage(0.0); diff --git a/dumux/freeflow/staggerednc/model.hh b/dumux/freeflow/staggerednc/model.hh index e7111ac7a4535d4d1d6a9c409abd3ca446e4f6ed..01198e50f79e7471ba51d0d4a5ca82211c16d6da 100644 --- a/dumux/freeflow/staggerednc/model.hh +++ b/dumux/freeflow/staggerednc/model.hh @@ -93,6 +93,7 @@ public: // register standardized vtk output fields auto& vtkOutputModule = problem.vtkOutputModule(); + vtkOutputModule.addSecondaryVariable("rho",[](const VolumeVariables& v){ return v.molarDensity(); }); for (int j = 0; j < numComponents; ++j) vtkOutputModule.addSecondaryVariable("x" + FluidSystem::componentName(j) + FluidSystem::phaseName(0), [j](const VolumeVariables& v){ return v.massFraction(0,j); }); diff --git a/dumux/freeflow/staggerednc/properties.hh b/dumux/freeflow/staggerednc/properties.hh index da3f19c7a7ed8674f4e627d45b4fbf0ce553c872..ef5c28a23f25ec657aeaace2ad3142b3f590eebe 100644 --- a/dumux/freeflow/staggerednc/properties.hh +++ b/dumux/freeflow/staggerednc/properties.hh @@ -67,6 +67,7 @@ NEW_PROP_TAG(EnableComponentTransport); //!< Returns whether to consider compone NEW_PROP_TAG(EnableEnergyTransport); //!< Returns whether to consider energy transport or not NEW_PROP_TAG(FaceVariables); //!< Returns whether to consider energy transport or not NEW_PROP_TAG(ReplaceCompEqIdx); //!< Returns whether to consider energy transport or not +NEW_PROP_TAG(UseMoles); //!< Defines whether molar (true) or mass (false) density is used // \} } diff --git a/dumux/freeflow/staggerednc/propertydefaults.hh b/dumux/freeflow/staggerednc/propertydefaults.hh index 809511530cb5102bd0e59ddb7e383cf06ba4a485..31d7d5b87a472ad7d18d0f8a91d3c1e4f729ac69 100644 --- a/dumux/freeflow/staggerednc/propertydefaults.hh +++ b/dumux/freeflow/staggerednc/propertydefaults.hh @@ -33,6 +33,7 @@ #include "volumevariables.hh" #include "indices.hh" #include "localresidual.hh" +#include "fluxvariables.hh" #include "../staggered/problem.hh" // #include "../staggered/model.hh" #include "../staggered/propertydefaults.hh" @@ -47,8 +48,6 @@ #include <dumux/material/fluidstates/compositional.hh> - - namespace Dumux { @@ -166,6 +165,8 @@ SET_PROP(NavierStokesNC, FluidState) // SET_BOOL_PROP(NavierStokesNC, EnableComponentTransport, true); +SET_BOOL_PROP(NavierStokesNC, UseMoles, false); //!< Defines whether molar (true) or mass (false) density is used + //! average is used as default model to compute the effective thermal heat conductivity // SET_PROP(NavierStokesNI, ThermalConductivityModel)