diff --git a/dumux/implicit/mpnc/diffusion/diffusion.hh b/dumux/implicit/mpnc/diffusion/diffusion.hh index 3c47362859d1aafdcebd07f723864883631a7766..7bd444cb217f935abd65e0a665fcffb8683021f1 100644 --- a/dumux/implicit/mpnc/diffusion/diffusion.hh +++ b/dumux/implicit/mpnc/diffusion/diffusion.hh @@ -1,200 +1,8 @@ -// -*- 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 parts to calculate the diffusive flux in - * the fully coupled MpNc model - */ -#ifndef DUMUX_MPNC_DIFFUSION_HH -#define DUMUX_MPNC_DIFFUSION_HH +#ifndef DUMUX_MPNC_DIFFUSION_HH_OLD +#define DUMUX_MPNC_DIFFUSION_HH_OLD -#include <dune/common/float_cmp.hh> -#include <dune/common/fmatrix.hh> -#include <dune/common/fvector.hh> +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/diffusion/diffusion.hh instead +#include <dumux/porousmediumflow/mpnc/implicit/diffusion/diffusion.hh> -#include <dumux/implicit/mpnc/mpncproperties.hh> - -namespace Dumux { -/*! - * \brief Calculates the diffusive flux in the fully coupled MpNc model. - * Called from the mass module. - */ -template <class TypeTag, bool enableDiffusion> -class MPNCDiffusion -{ - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - - enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents)}; - enum { nPhaseIdx = FluidSystem::nPhaseIdx }; - enum { wPhaseIdx = FluidSystem::wPhaseIdx }; - enum { nCompIdx = FluidSystem::nCompIdx }; - - typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; - typedef Dune::FieldMatrix<Scalar, numComponents, numComponents> ComponentMatrix; - typedef Dune::FieldVector<Scalar, numComponents> ComponentVector; - -public: - - /*! - * \brief Calls the function for the diffusion in the gas and liquid phases, respectively. - * - * In the gas phase, the mutual influence of mole fractions can be considered. - * - * \param fluxes The Diffusive flux over the sub-control-volume face for each component - * \param phaseIdx The index of the phase we are calculating the diffusive flux for - * \param fluxVars The flux variables at the current sub control volume face - * \param molarDensity The (molar) density of the phase - */ - static void flux(ComponentVector &fluxes, - const unsigned int phaseIdx, - const FluxVariables &fluxVars, - const Scalar molarDensity ) - { - if ( not FluidSystem::isLiquid(phaseIdx) ) - gasFlux_(fluxes, fluxVars, molarDensity); - else if ( FluidSystem::isLiquid(phaseIdx) ){ - #if MACROSCALE_DIFFUSION_ONLY_GAS - return ; // in the case that only the diffusion in the gas phase is considered, - // the liquidFlux should not be called - #endif - liquidFlux_(fluxes, fluxVars, molarDensity); - } - else - DUNE_THROW(Dune::InvalidStateException, - "Invalid phase index: " << phaseIdx); - } - -protected: - - /*! - * \brief Calculates the diffusive flux in the liquid phase: only Fick diffusion (no mutual influence) is considered. - * - * \param fluxes The Diffusive flux over the sub-control-volume face for each component - * \param fluxVars The flux variables at the current sub control volume face - * \param molarDensity The (molar) density of the phase - */ - static void liquidFlux_(ComponentVector &fluxes, - const FluxVariables &fluxVars, - const Scalar molarDensity) - { - for (int compIdx = 0; compIdx < numComponents; ++compIdx) { - // TODO: tensorial diffusion coefficients - const Scalar xGrad = fluxVars.moleFractionGrad(wPhaseIdx, compIdx)*fluxVars.face().normal; - fluxes[compIdx] = - - xGrad * - molarDensity * - fluxVars.porousDiffCoeffL(compIdx) ; - } - } - - /*! - * \brief Calculates the diffusive flux in the gas phase: - * The property UseMaxwellDiffusion selects whether Maxwell or Fick diffusion is applied. - * Has to be the same for a 2-component system. However, Maxwells does not work always. - * - * \param fluxes The Diffusive flux over the sub-control-volume face for each component - * \param fluxVars The flux variables at the current sub control volume face - * \param molarDensity The (molar) density of the phase - * - * Reid et al. (1987, p. 596) \cite reid1987 <BR> - */ - static void gasFlux_(ComponentVector &fluxes, - const FluxVariables &fluxVars, - const Scalar molarDensity) - { - // Alternative: use Fick Diffusion: no mutual influence of diffusion - if (GET_PROP_VALUE(TypeTag, UseMaxwellDiffusion) ){ - // Stefan-Maxwell equation - // - // See: R. Reid, et al.: "The Properties of Liquids and - // Gases", 4th edition, 1987, McGraw-Hill, p 596 - - // TODO: tensorial diffusion coefficients - ComponentMatrix M(0); - - for (int compIIdx = 0; compIIdx < numComponents - 1; ++compIIdx) { - for (int compJIdx = 0; compJIdx < numComponents; ++compJIdx) { - Scalar Dij = fluxVars.porousDiffCoeffG(compIIdx, compJIdx); - if (Dune::FloatCmp::ne<Scalar, Dune::FloatCmp::absolute>(Dij, 0.0, 1.0e-30)) { - M[compIIdx][compJIdx] += fluxVars.moleFraction(nPhaseIdx, compIIdx) / Dij; - M[compIIdx][compIIdx] -= fluxVars.moleFraction(nPhaseIdx, compJIdx) / Dij; - } - } - } - - for (int compIIdx = 0; compIIdx < numComponents; ++compIIdx) { - M[numComponents - 1][compIIdx] = 1.0; - } - - ComponentVector rightHandSide ; // see source cited above - for (int compIIdx = 0; compIIdx < numComponents - 1; ++compIIdx) { - rightHandSide[compIIdx] = molarDensity*(fluxVars.moleFractionGrad(nPhaseIdx, compIIdx)*fluxVars.face().normal); - } - rightHandSide[numComponents - 1] = 0.0; - - M.solve(fluxes, rightHandSide); - } - else{// Fick Diffusion - for (int compIdx = 0; compIdx < numComponents; ++compIdx) { - // TODO: tensorial diffusion coefficients - const Scalar xGrad = fluxVars.moleFractionGrad(nPhaseIdx, compIdx)*fluxVars.face().normal; - fluxes[compIdx] = - - xGrad * - molarDensity - * fluxVars.porousDiffCoeffG(compIdx, nCompIdx) ; // this is == 0 for nComp==comp, - // i.e. no diffusion of the main component of the phase - } - } - } - - // return whether a concentration can be assumed to be a trace - // component in the context of diffusion - static Scalar isTraceComp_(Scalar x) - { return x < 0.5/numComponents; } -}; - -/*! - * \brief Specialization of the diffusion module for the case where - * diffusion is disabled. - * - * This class just does nothing. - */ -template <class TypeTag> -class MPNCDiffusion<TypeTag, false> -{ - enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; - - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; - typedef Dune::FieldVector<Scalar, numComponents> ComponentVector; - -public: - static void flux(ComponentVector &fluxes, - const unsigned int phaseIdx, - const FluxVariables &fluxVars, - const Scalar molarDensity) - { fluxes = 0; } -}; - -} - -#endif // DUMUX_MPNC_DIFFUSION_HH +#endif diff --git a/dumux/implicit/mpnc/diffusion/fluxvariables.hh b/dumux/implicit/mpnc/diffusion/fluxvariables.hh index 2fb8041a271af039dad0502ea9cdcb34f9c157ac..574625cbe0268b0105c8ccfedb2f41b21ec57565 100644 --- a/dumux/implicit/mpnc/diffusion/fluxvariables.hh +++ b/dumux/implicit/mpnc/diffusion/fluxvariables.hh @@ -1,258 +1,8 @@ -// -*- 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 diffusion module for the flux data of - * the fully coupled MpNc model - */ -#ifndef DUMUX_MPNC_DIFFUSION_FLUX_VARIABLES_HH -#define DUMUX_MPNC_DIFFUSION_FLUX_VARIABLES_HH +#ifndef DUMUX_MPNC_DIFFUSION_FLUX_VARIABLES_HH_OLD +#define DUMUX_MPNC_DIFFUSION_FLUX_VARIABLES_HH_OLD -#include <dune/common/fvector.hh> +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/diffusion/fluxvariables.hh instead -#include "../mpncproperties.hh" +#include <dumux/porousmediumflow/mpnc/implicit/diffusion/fluxvariables.hh> -namespace Dumux { - -/*! - * \ingroup MPNCModel - * \ingroup ImplicitFluxVariables - * \brief Variables for the diffusive fluxes in the MpNc model - */ -template<class TypeTag, bool enableDiffusion> -class MPNCFluxVariablesDiffusion -{ - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - typedef typename GridView::template Codim<0>::Entity Element; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename FVElementGeometry::SubControlVolumeFace SCVFace; - - enum{dim = GridView::dimension}; - enum{dimWorld = GridView::dimensionworld}; - enum{numPhases = GET_PROP_VALUE(TypeTag, NumPhases)}; - enum{numComponents = GET_PROP_VALUE(TypeTag, NumComponents)}; - enum{wPhaseIdx = FluidSystem::wPhaseIdx}; - enum{nPhaseIdx = FluidSystem::nPhaseIdx}; - - typedef Dune::FieldVector<Scalar, dim> DimVector; - typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition; - -public: - /*! - * \brief The constructor - */ - MPNCFluxVariablesDiffusion() - {} - /*! - * \brief update - * - * \param problem The problem - * \param element The finite element - * \param fvGeometry The finite-volume geometry in the fully implicit scheme - * \param face The SCV (sub-control-volume) face - * \param elemVolVars The volume variables of the current element - */ - void update(const Problem & problem, - const Element & element, - const FVElementGeometry & fvGeometry, - const SCVFace & face, - const ElementVolumeVariables & elemVolVars) - { - const unsigned int i = face.i; - const unsigned int j = face.j; - - - for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx){ - for (int compIdx = 0; compIdx < numComponents; ++compIdx){ - moleFraction_[phaseIdx][compIdx] = 0. ; - moleFractionGrad_[phaseIdx][compIdx] = 0. ; - } - } - - - GlobalPosition tmp ; - for (unsigned int idx = 0; - idx < face.numFap; - idx++) // loop over adjacent vertices - { - // FE gradient at vertex idx - const GlobalPosition & feGrad = face.grad[idx]; - - // index for the element volume variables - int volVarsIdx = face.fapIndices[idx]; - - for (int phaseIdx = 0; phaseIdx < numPhases; phaseIdx++){ - for (int compIdx = 0; compIdx < numComponents; ++compIdx){ - - // calculate mole fractions at the integration points of the face - moleFraction_[phaseIdx][compIdx] += elemVolVars[volVarsIdx].fluidState().moleFraction(phaseIdx, compIdx)* - face.shapeValue[idx]; - - // calculate mole fraction gradients - tmp = feGrad; - tmp *= elemVolVars[volVarsIdx].fluidState().moleFraction(phaseIdx, compIdx); - moleFractionGrad_[phaseIdx][compIdx] += tmp; - } - } - } - - // initialize the diffusion coefficients to zero - for (int compIIdx = 0; compIIdx < numComponents; ++compIIdx) { - porousDiffCoeffL_[compIIdx] = 0.0; - for (int compJIdx = 0; compJIdx < numComponents; ++compJIdx) - porousDiffCoeffG_[compIIdx][compJIdx] = 0.0; - } - - // calculate the diffusion coefficients at the integration - // point in the porous medium - for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) - { - // make sure to only calculate diffusion coefficents - // for phases which exist in both finite volumes - if (elemVolVars[i].fluidState().saturation(phaseIdx) <= 1e-4 || - elemVolVars[j].fluidState().saturation(phaseIdx) <= 1e-4) - { - continue; - } - - // reduction factor for the diffusion coefficients in the - // porous medium in nodes i and j. this is the tortuosity - // times porosity times phase saturation at the nodes i - // and j - // - Scalar red_i = - elemVolVars[i].fluidState().saturation(phaseIdx)/elemVolVars[i].porosity() * - pow(elemVolVars[i].porosity() * elemVolVars[i].fluidState().saturation(phaseIdx), 7.0/3); - Scalar red_j = - elemVolVars[j].fluidState().saturation(phaseIdx)/elemVolVars[j].porosity() * - pow(elemVolVars[j].porosity() * elemVolVars[j].fluidState().saturation(phaseIdx), 7.0/3); - - if (phaseIdx == wPhaseIdx) { - // Liquid phase diffusion coefficients in the porous medium - for (int compIIdx = 0; compIIdx < numComponents; ++compIIdx) { - // -> arithmetic mean - porousDiffCoeffL_[compIIdx] - = 1./2*(red_i * elemVolVars[i].diffCoeff(wPhaseIdx, 0, compIIdx) + - red_j * elemVolVars[j].diffCoeff(wPhaseIdx, 0, compIIdx)); - } - } - else { - // Gas phase diffusion coefficients in the porous medium - for (int compIIdx = 0; compIIdx < numComponents; ++compIIdx) { - for (int compJIdx = 0; compJIdx < numComponents; ++compJIdx) { - // -> arithmetic mean - porousDiffCoeffG_[compIIdx][compJIdx] - = 1./2*(red_i * elemVolVars[i].diffCoeff(nPhaseIdx, compIIdx, compJIdx) + - red_j * elemVolVars[j].diffCoeff(nPhaseIdx, compIIdx, compJIdx)); - } - } - } - } - } - /*! - * \brief The binary diffusion coefficient for each component in the fluid phase. - * \param compIdx The local index of the components - */ - Scalar porousDiffCoeffL(const unsigned int compIdx) const - { - // TODO: tensorial diffusion coefficients - return porousDiffCoeffL_[compIdx]; - } - /*! - * \brief The binary diffusion coefficient for each component in the gas phase. - * \param compIIdx The local index of the first component in the phase - * \param compJIdx The local index of the second component in the phase - */ - Scalar porousDiffCoeffG(const unsigned int compIIdx, - const unsigned int compJIdx) const - { - // TODO: tensorial diffusion coefficients - return porousDiffCoeffG_[compIIdx][compJIdx]; - } - /*! - * \brief The mole fraction and concentration gradient for all phases and components - * \param phaseIdx The local index of the phases - * \param compIdx The local index of the component - */ - Scalar moleFraction(const unsigned int phaseIdx, - const unsigned int compIdx) const - { return moleFraction_[phaseIdx][compIdx]; } - - const GlobalPosition &moleFractionGrad(const unsigned int phaseIdx, - const unsigned int compIdx) const - { return moleFractionGrad_[phaseIdx][compIdx];} - -protected: - // the diffusion coefficients for the porous medium for the - // liquid phase - Scalar porousDiffCoeffL_[numComponents]; - - // the diffusion coefficients for the porous medium for the - // gas phase - Scalar porousDiffCoeffG_[numComponents][numComponents]; - - // the concentration gradients of all components in all phases - GlobalPosition moleFractionGrad_[numPhases][numComponents]; - - // the mole fractions of each component at the integration point - Scalar moleFraction_[numPhases][numComponents]; -}; - - -template<class TypeTag> -class MPNCFluxVariablesDiffusion<TypeTag, false> -{ - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GridView::template Codim<0>::Entity Element; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename FVElementGeometry::SubControlVolumeFace SCVFace; - -public: - /*! - * \brief The constructor - */ - MPNCFluxVariablesDiffusion() - {} - /*! - * \brief update - * - * \param problem The problem - * \param element The finite element - * \param fvGeometry The finite-volume geometry in the fully implicit scheme - * \param face The SCV (sub-control-volume) face - * \param elemVolVars The volume variables of the current element - */ - void update(const Problem & problem, - const Element & element, - const FVElementGeometry & fvGeometry, - const SCVFace & face, - const ElementVolumeVariables & elemVolVars) - { - } -}; - -} - -#endif // DUMUX_MPNC_DIFFUSION_FLUX_VARIABLES_HH +#endif diff --git a/dumux/implicit/mpnc/diffusion/volumevariables.hh b/dumux/implicit/mpnc/diffusion/volumevariables.hh index 75c91bb32e03b90640097f056b4e98d147a47943..b2dc0bf69420df0b505f6194086fe2275850b55e 100644 --- a/dumux/implicit/mpnc/diffusion/volumevariables.hh +++ b/dumux/implicit/mpnc/diffusion/volumevariables.hh @@ -1,199 +1,8 @@ -// -*- 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 diffusion module for the vertex data - * of the fully coupled MpNc model - */ -#ifndef DUMUX_MPNC_DIFFUSION_VOLUME_VARIABLES_HH -#define DUMUX_MPNC_DIFFUSION_VOLUME_VARIABLES_HH +#ifndef DUMUX_MPNC_DIFFUSION_VOLUME_VARIABLES_HH_OLD +#define DUMUX_MPNC_DIFFUSION_VOLUME_VARIABLES_HH_OLD -#include <dumux/common/valgrind.hh> -#include <dumux/implicit/mpnc/mpncproperties.hh> +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/diffusion/volumevariables.hh instead -namespace Dumux { +#include <dumux/porousmediumflow/mpnc/implicit/diffusion/volumevariables.hh> -/*! - * \brief Variables for the diffusive fluxes in the MpNc model within - * a finite volume. - */ -template<class TypeTag, bool enableDiffusion> -class MPNCVolumeVariablesDiffusion -{ - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; - typedef typename FluidSystem::ParameterCache ParameterCache; - - enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; - enum { wPhaseIdx = FluidSystem::wPhaseIdx }; - enum { nPhaseIdx = FluidSystem::nPhaseIdx }; - -public: - /*! - * \brief The constructor - */ - MPNCVolumeVariablesDiffusion() - {} - /*! - * \brief update - * - * \param fluidState An arbitrary fluid state - * \param paramCache Container for cache parameters - * \param volVars The volume variables - * \param problem The problem - */ - void update(FluidState &fluidState, - ParameterCache ¶mCache, - const VolumeVariables &volVars, - const Problem &problem) - { - Valgrind::SetUndefined(*this); - - // diffusion coefficents in liquid - diffCoeffL_[0] = 0.0; - for (int compIdx = 1; compIdx < numComponents; ++compIdx) { - diffCoeffL_[compIdx] = - FluidSystem::binaryDiffusionCoefficient(fluidState, - paramCache, - wPhaseIdx, - 0, - compIdx); - } - Valgrind::CheckDefined(diffCoeffL_); - - // diffusion coefficents in gas - for (int compIIdx = 0; compIIdx < numComponents; ++compIIdx) { - diffCoeffG_[compIIdx][compIIdx] = 0; - for (int compJIdx = compIIdx + 1; compJIdx < numComponents; ++compJIdx) { - diffCoeffG_[compIIdx][compJIdx] = - FluidSystem::binaryDiffusionCoefficient(fluidState, - paramCache, - nPhaseIdx, - compIIdx, - compJIdx); - - // fill the symmetric part of the diffusion coefficent - // matrix - diffCoeffG_[compJIdx][compIIdx] = diffCoeffG_[compIIdx][compJIdx]; - } - } - Valgrind::CheckDefined(diffCoeffG_); - } - - /*! - * \brief The binary diffusion coefficient for each fluid phase. - * \param phaseIdx The local index of the phases - * \param compIIdx The local index of the first component in the phase - * \param compJIdx The local index of the second component in the phase - */ - Scalar diffCoeff(const unsigned int phaseIdx, - const unsigned int compIIdx, - const unsigned int compJIdx) const - { - if (phaseIdx == nPhaseIdx) - // TODO: tensorial diffusion coefficients - return diffCoeffG_[compIIdx][compJIdx]; - - const unsigned int i = std::min(compIIdx, compJIdx); - const unsigned int j = std::max(compIIdx, compJIdx); - if (i != 0) - return 0; - return diffCoeffL_[j]; - } - - /*! - * \brief If running under valgrind this produces an error message - * if some of the object's attributes is undefined. - */ - void checkDefined() const - { - Valgrind::CheckDefined(diffCoeffL_); - Valgrind::CheckDefined(diffCoeffG_); - } - - -protected: - // the diffusion coefficients for the porous medium for the - // liquid phase - Scalar diffCoeffL_[numComponents]; - - // the diffusion coefficients for the porous medium for the - // gas phase - Scalar diffCoeffG_[numComponents][numComponents]; -}; - -// dummy class for the case where diffusion is disabled -template<class TypeTag> -class MPNCVolumeVariablesDiffusion<TypeTag, false> -{ - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; - typedef typename FluidSystem::ParameterCache ParameterCache; - -public: - /*! - * \brief The constructor - */ - MPNCVolumeVariablesDiffusion() - {} - /*! - * \brief update - * - * \param fluidState An arbitrary fluid state - * \param paramCache Container for cache parameters - * \param volVars The volume variables - * \param problem The problem - */ - void update(FluidState &fluidState, - ParameterCache ¶mCache, - const VolumeVariables &volVars, - const Problem &problem) - { } - /*! - * \brief The binary diffusion coefficient for each component in the fluid phase. - * \param compIdx The local index of the components - */ - Scalar diffCoeffL(const unsigned int compIdx) const - { return 0; } - /*! - * \brief The binary diffusion coefficient for each component in the gas phase. - * \param compIIdx The local index of the first component in the phase - * \param compJIdx The local index of the second component in the phase - */ - Scalar diffCoeffG(const unsigned int compIIdx, const unsigned int compJIdx) const - { return 0; } - - /*! - * \brief If running under valgrind this produces an error message - * if some of the object's attributes is undefined. - */ - void checkDefined() const - { } -}; - -} - -#endif // DUMUX_MPNC_DIFFUSION_VOLUME_VARIABLES_HH +#endif diff --git a/dumux/implicit/mpnc/energy/mpncfluxvariablesenergy.hh b/dumux/implicit/mpnc/energy/mpncfluxvariablesenergy.hh index 066cb55620e90b1235d42d001a506fba73faf8ea..076d7f288e61fbc035c101090e9fd8ce638a0638 100644 --- a/dumux/implicit/mpnc/energy/mpncfluxvariablesenergy.hh +++ b/dumux/implicit/mpnc/energy/mpncfluxvariablesenergy.hh @@ -1,243 +1,8 @@ -// -*- 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 Contains the quantities to calculate the energy flux in the - * MpNc fully implicit model. - */ -#ifndef DUMUX_MPNC_ENERGY_FLUX_VARIABLES_HH -#define DUMUX_MPNC_ENERGY_FLUX_VARIABLES_HH +#ifndef DUMUX_MPNC_ENERGY_FLUX_VARIABLES_HH_OLD +#define DUMUX_MPNC_ENERGY_FLUX_VARIABLES_HH_OLD -#include <dune/common/fvector.hh> +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/energy/fluxvariables.hh instead -#include <dumux/implicit/mpnc/mpncproperties.hh> -#include <dumux/common/spline.hh> - -namespace Dumux -{ -/*! - * \ingroup MPNCModel - * \ingroup ImplicitFluxVariables - * \brief Variables for the enthalpy fluxes in the MpNc model - */ -template <class TypeTag, bool enableEnergy/*=false*/, int numEnergyEquations/*=0*/> -class MPNCFluxVariablesEnergy -{ - static_assert(!(numEnergyEquations && !enableEnergy), - "No kinetic energy transfer may only be enabled " - "if energy is enabled in general."); - static_assert(!numEnergyEquations, - "No kinetic energy transfer module included, " - "but kinetic energy transfer enabled."); - - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GridView::template Codim<0>::Entity Element; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; - typedef typename FVElementGeometry::SubControlVolumeFace SCVFace; - -public: - /*! - * \brief The constructor - */ - MPNCFluxVariablesEnergy() - { - } - /*! - * \brief update - * - * \param problem The problem - * \param element The finite element - * \param fvGeometry The finite-volume geometry in the fully implicit scheme - * \param face The SCV (sub-control-volume) face - * \param fluxVars The flux variables - * \param elemVolVars The volume variables of the current element - */ - void update(const Problem & problem, - const Element & element, - const FVElementGeometry & fvGeometry, - const SCVFace & face, - const FluxVariables & fluxVars, - const ElementVolumeVariables & elemVolVars) - {} -}; - -template <class TypeTag> -class MPNCFluxVariablesEnergy<TypeTag, /*enableEnergy=*/true, /*numEnergyEquations=*/1> -{ - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; - typedef typename FluidSystem::ParameterCache ParameterCache; - typedef typename GridView::ctype CoordScalar; - typedef typename GridView::template Codim<0>::Entity Element; - - enum{dimWorld = GridView::dimensionworld}; - enum{dim = GridView::dimension}; - enum{nPhaseIdx = FluidSystem::nPhaseIdx}; - enum{wPhaseIdx = FluidSystem::wPhaseIdx}; - - typedef Dune::FieldVector<CoordScalar, dim> DimVector; - typedef Dune::FieldVector<CoordScalar, dimWorld> GlobalPosition; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename FVElementGeometry::SubControlVolumeFace SCVFace; - typedef typename GET_PROP_TYPE(TypeTag, ThermalConductivityModel) ThermalConductivityModel; - -public: - /*! - * \brief The constructor - */ - MPNCFluxVariablesEnergy() - {} - /*! - * \brief update - * - * \param problem The problem - * \param element The finite element - * \param fvGeometry The finite-volume geometry in the fully implicit scheme - * \param face The SCV (sub-control-volume) face - * \param fluxVars The flux variables - * \param elemVolVars The volume variables of the current element - */ - void update(const Problem & problem, - const Element & element, - const FVElementGeometry & fvGeometry, - const SCVFace & face, - const FluxVariables & fluxVars, - const ElementVolumeVariables & elemVolVars) - { - // calculate temperature gradient using finite element - // gradients - GlobalPosition tmp(0.0); - GlobalPosition temperatureGradient(0.); - for (int idx = 0; idx < face.numFap; idx++) - { - tmp = face.grad[idx]; - - // index for the element volume variables - int volVarsIdx = face.fapIndices[idx]; - - tmp *= elemVolVars[volVarsIdx].fluidState().temperature(/*phaseIdx=*/0); - temperatureGradient += tmp; - } - - // project the heat flux vector on the face's normal vector - temperatureGradientNormal_ = temperatureGradient * face.normal; - - lambdaEff_ = 0; - calculateEffThermalConductivity_(problem, - element, - fvGeometry, - face, - elemVolVars); - } - - /*! - * \brief The lumped / average conductivity of solid plus phases \f$[W/mK]\f$. - */ - Scalar lambdaEff() const - { return lambdaEff_; } - - /*! - * \brief The normal of the gradient of temperature . - */ - Scalar temperatureGradientNormal() const - { - return temperatureGradientNormal_; - } - -protected: - /*! - * \brief Calculate the effective thermal conductivity of - * the porous medium plus residing phases \f$[W/mK]\f$. - * This basically means to access the model for averaging - * the individual conductivities, set by the property ThermalConductivityModel. - * Except the adapted arguments, this is the same function - * as used in the implicit TwoPTwoCNIFluxVariables. - */ - void calculateEffThermalConductivity_(const Problem &problem, - const Element &element, - const FVElementGeometry & fvGeometry, - const SCVFace & face, - const ElementVolumeVariables &elemVolVars) - { - const unsigned i = face.i; - const unsigned j = face.j; - Scalar lambdaI, lambdaJ; - - if (GET_PROP_VALUE(TypeTag, ImplicitIsBox)) - { - lambdaI = - ThermalConductivityModel::effectiveThermalConductivity(elemVolVars[i].fluidState().saturation(wPhaseIdx), - elemVolVars[i].thermalConductivity(wPhaseIdx), - elemVolVars[i].thermalConductivity(nPhaseIdx), - problem.spatialParams().solidThermalConductivity(element, fvGeometry, i), - problem.spatialParams().porosity(element, fvGeometry, i)); - lambdaJ = - ThermalConductivityModel::effectiveThermalConductivity(elemVolVars[j].fluidState().saturation(wPhaseIdx), - elemVolVars[j].thermalConductivity(wPhaseIdx), - elemVolVars[j].thermalConductivity(nPhaseIdx), - problem.spatialParams().solidThermalConductivity(element, fvGeometry, j), - problem.spatialParams().porosity(element, fvGeometry, j)); - } - else - { - const Element & elementI = fvGeometry.neighbors[i]; - FVElementGeometry fvGeometryI; - fvGeometryI.subContVol[0].global = elementI.geometry().center(); - - lambdaI = - ThermalConductivityModel::effectiveThermalConductivity(elemVolVars[i].fluidState().saturation(wPhaseIdx), - elemVolVars[i].thermalConductivity(wPhaseIdx), - elemVolVars[i].thermalConductivity(nPhaseIdx), - problem.spatialParams().solidThermalConductivity(elementI, fvGeometryI, 0), - problem.spatialParams().porosity(elementI, fvGeometryI, 0)); - - const Element & elementJ = fvGeometry.neighbors[j]; - FVElementGeometry fvGeometryJ; - fvGeometryJ.subContVol[0].global = elementJ.geometry().center(); - - lambdaJ = - ThermalConductivityModel::effectiveThermalConductivity(elemVolVars[j].fluidState().saturation(wPhaseIdx), - elemVolVars[j].thermalConductivity(wPhaseIdx), - elemVolVars[j].thermalConductivity(nPhaseIdx), - problem.spatialParams().solidThermalConductivity(elementJ, fvGeometryJ, 0), - problem.spatialParams().porosity(elementJ, fvGeometryJ, 0)); - } - - // -> harmonic mean - lambdaEff_ = harmonicMean(lambdaI, lambdaJ); - } - -private: - Scalar lambdaEff_ ; - Scalar temperatureGradientNormal_; -}; - -} // end namespace +#include <dumux/porousmediumflow/mpnc/implicit/energy/fluxvariables.hh> #endif diff --git a/dumux/implicit/mpnc/energy/mpncfluxvariablesenergykinetic.hh b/dumux/implicit/mpnc/energy/mpncfluxvariablesenergykinetic.hh index 67b6e1daa62dbbbab7a72e50f4c16cdfa3556aa4..217cfef172c3ec81c0cdc2885f80f00edc26b741 100644 --- a/dumux/implicit/mpnc/energy/mpncfluxvariablesenergykinetic.hh +++ b/dumux/implicit/mpnc/energy/mpncfluxvariablesenergykinetic.hh @@ -1,298 +1,8 @@ -// -*- 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 Contains the quantities to calculate the energy flux in the - * MpNc box model with kinetic energy transfer enabled. - */ -#ifndef DUMUX_MPNC_ENERGY_FLUX_VARIABLES_KINETIC_HH -#define DUMUX_MPNC_ENERGY_FLUX_VARIABLES_KINETIC_HH +#ifndef DUMUX_MPNC_ENERGY_FLUX_VARIABLES_KINETIC_HH_OLD +#define DUMUX_MPNC_ENERGY_FLUX_VARIABLES_KINETIC_HH_OLD -#include <dune/common/fvector.hh> +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/energy/fluxvariableskinetic.hh instead -#include <dumux/common/spline.hh> -#include <dumux/implicit/mpnc/mpncfluxvariables.hh> - -namespace Dumux -{ - -/*! - * \brief Specialization for the case of *3* energy balance equations. - */ -template <class TypeTag> -class MPNCFluxVariablesEnergy<TypeTag, /*enableEnergy=*/true, /*numEnergyEquations=*/3> -{ - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; - typedef typename GridView::ctype CoordScalar; - typedef typename GridView::template Codim<0>::Entity Element; - - enum {dim = GridView::dimension}; - enum {dimWorld = GridView::dimensionworld}; - enum {numEnergyEqs = Indices::numPrimaryEnergyVars}; - - typedef Dune::FieldVector<CoordScalar, dim> DimVector; - typedef Dune::FieldVector<CoordScalar, dimWorld> GlobalPosition; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename FVElementGeometry::SubControlVolume SCV; - typedef typename FVElementGeometry::SubControlVolumeFace SCVFace; - -public: - /*! - * \brief The constructor - */ - MPNCFluxVariablesEnergy() - {} - /*! - * \brief update - * - * \param problem The problem - * \param element The finite element - * \param fvGeometry The finite-volume geometry in the fully implicit scheme - * \param face The SCV (sub-control-volume) face - * \param fluxVars The flux variables - * \param elemVolVars The volume variables of the current element - */ - void update(const Problem & problem, - const Element & element, - const FVElementGeometry & fvGeometry, - const SCVFace & face, - const FluxVariables & fluxVars, - const ElementVolumeVariables & elemVolVars) - { - // calculate temperature gradient using finite element - // gradients - GlobalPosition tmp ; - - for(int energyEqIdx=0; energyEqIdx<numEnergyEqs; energyEqIdx++) - temperatureGradient_[energyEqIdx] = 0.; - - for (unsigned int idx = 0; - idx < face.numFap; - idx++){ - // FE gradient at vertex idx - const GlobalPosition & feGrad = face.grad[idx]; - - for (int energyEqIdx =0; energyEqIdx < numEnergyEqs; ++energyEqIdx){ - // index for the element volume variables - int volVarsIdx = face.fapIndices[idx]; - - tmp = feGrad; - tmp *= elemVolVars[volVarsIdx].temperature(energyEqIdx); - temperatureGradient_[energyEqIdx] += tmp; - } - } - } - - /*! - * \brief The total heat flux \f$[J/s]\f$ due to heat conduction - * of the rock matrix over the sub-control volume's face. - * - * \param energyEqIdx The index of the energy equation - */ - GlobalPosition temperatureGradient(const unsigned int energyEqIdx) const - { - return temperatureGradient_[energyEqIdx]; - } - -private: - GlobalPosition temperatureGradient_[numEnergyEqs]; -}; - - -/*! - * \brief Specialization for the case of *2* energy balance equations. - */ -template <class TypeTag> -class MPNCFluxVariablesEnergy<TypeTag, /*enableEnergy=*/true, /*numEnergyEquations=*/2> -{ - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - - typedef typename GridView::ctype CoordScalar; - typedef typename GridView::template Codim<0>::Entity Element; - - enum {dim = GridView::dimension}; - enum {dimWorld = GridView::dimensionworld}; - enum {numEnergyEqs = Indices::numPrimaryEnergyVars}; - enum {wPhaseIdx = FluidSystem::wPhaseIdx}; - enum {nPhaseIdx = FluidSystem::nPhaseIdx}; - - - typedef Dune::FieldVector<CoordScalar, dimWorld> GlobalPosition; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename FVElementGeometry::SubControlVolume SCV; - typedef typename FVElementGeometry::SubControlVolumeFace SCVFace; - typedef typename GET_PROP_TYPE(TypeTag, ThermalConductivityModel) ThermalConductivityModel; - - -public: - /*! - * \brief The constructor - */ - MPNCFluxVariablesEnergy() - {} - /*! - * \brief update - * - * \param problem The problem - * \param element The finite element - * \param fvGeometry The finite-volume geometry in the fully implicit scheme - * \param face The SCV (sub-control-volume) face - * \param fluxVars The flux variables - * \param elemVolVars The volume variables of the current element - */ - void update(const Problem & problem, - const Element & element, - const FVElementGeometry & fvGeometry, - const SCVFace & face, - const FluxVariables & fluxVars, - const ElementVolumeVariables & elemVolVars) - { - // calculate temperature gradient using finite element - // gradients - GlobalPosition tmp ; - - for(int energyEqIdx=0; energyEqIdx<numEnergyEqs; energyEqIdx++) - temperatureGradient_[energyEqIdx] = 0.; - - for (unsigned int idx = 0; - idx < face.numFap; - idx++){ - // FE gradient at vertex idx - const GlobalPosition & feGrad = face.grad[idx]; - - for (int energyEqIdx =0; energyEqIdx < numEnergyEqs; ++energyEqIdx){ - // index for the element volume variables - int volVarsIdx = face.fapIndices[idx]; - - tmp = feGrad; - tmp *= elemVolVars[volVarsIdx].temperature(energyEqIdx); - temperatureGradient_[energyEqIdx] += tmp; - } - } - - lambdaEff_ = 0; - calculateEffThermalConductivity_(problem, - element, - fvGeometry, - face, - elemVolVars); - - - } - - /*! - * \brief The lumped / average conductivity of solid plus phases \f$[W/mK]\f$. - */ - Scalar lambdaEff() const - { return lambdaEff_; } - - /*! - * \brief The total heat flux \f$[J/s]\f$ due to heat conduction - * of the rock matrix over the sub-control volume's face. - * - * \param energyEqIdx The index of the energy equation - */ - GlobalPosition temperatureGradient(const unsigned int energyEqIdx) const - { - return temperatureGradient_[energyEqIdx]; - } - -protected: - /*! - * \brief Calculate the effective thermal conductivity of - * the porous medium plus residing phases \f$[W/mK]\f$. - * This basically means to access the model for averaging - * the individual conductivities, set by the property ThermalConductivityModel. - * Except the adapted arguments, this is the same function - * as used in the implicit TwoPTwoCNIFluxVariables. - */ - void calculateEffThermalConductivity_(const Problem &problem, - const Element &element, - const FVElementGeometry & fvGeometry, - const SCVFace & face, - const ElementVolumeVariables &elemVolVars) - { - const unsigned i = face.i; - const unsigned j = face.j; - Scalar lambdaI, lambdaJ; - - if (GET_PROP_VALUE(TypeTag, ImplicitIsBox)) - { - lambdaI = - ThermalConductivityModel::effectiveThermalConductivity(elemVolVars[i].fluidState().saturation(wPhaseIdx), - elemVolVars[i].thermalConductivity(wPhaseIdx), - elemVolVars[i].thermalConductivity(nPhaseIdx), - problem.spatialParams().solidThermalConductivity(element, fvGeometry, i), - problem.spatialParams().porosity(element, fvGeometry, i)); - lambdaJ = - ThermalConductivityModel::effectiveThermalConductivity(elemVolVars[j].fluidState().saturation(wPhaseIdx), - elemVolVars[j].thermalConductivity(wPhaseIdx), - elemVolVars[j].thermalConductivity(nPhaseIdx), - problem.spatialParams().solidThermalConductivity(element, fvGeometry, j), - problem.spatialParams().porosity(element, fvGeometry, j)); - } - else - { - const Element & elementI = fvGeometry.neighbors[i]; - FVElementGeometry fvGeometryI; - fvGeometryI.subContVol[0].global = elementI.geometry().center(); - - lambdaI = - ThermalConductivityModel::effectiveThermalConductivity(elemVolVars[i].fluidState().saturation(wPhaseIdx), - elemVolVars[i].thermalConductivity(wPhaseIdx), - elemVolVars[i].thermalConductivity(nPhaseIdx), - problem.spatialParams().solidThermalConductivity(elementI, fvGeometryI, 0), - problem.spatialParams().porosity(elementI, fvGeometryI, 0)); - - const Element & elementJ = fvGeometry.neighbors[j]; - FVElementGeometry fvGeometryJ; - fvGeometryJ.subContVol[0].global = elementJ.geometry().center(); - - lambdaJ = - ThermalConductivityModel::effectiveThermalConductivity(elemVolVars[j].fluidState().saturation(wPhaseIdx), - elemVolVars[j].thermalConductivity(wPhaseIdx), - elemVolVars[j].thermalConductivity(nPhaseIdx), - problem.spatialParams().solidThermalConductivity(elementJ, fvGeometryJ, 0), - problem.spatialParams().porosity(elementJ, fvGeometryJ, 0)); - } - - // -> arithmetic mean, open to discussion - lambdaEff_ = 0.5 * (lambdaI+lambdaJ); - } - - -private: - Scalar lambdaEff_ ; - GlobalPosition temperatureGradient_[numEnergyEqs]; -}; - -} // end namespace +#include <dumux/porousmediumflow/mpnc/implicit/energy/fluxvariableskinetic.hh> #endif diff --git a/dumux/implicit/mpnc/energy/mpncindicesenergy.hh b/dumux/implicit/mpnc/energy/mpncindicesenergy.hh index fbe135b8b0a94aae8ce675638d62d2ba67eea7e7..2b174be3ad79f204c8e5fff116c1ab094853c2a9 100644 --- a/dumux/implicit/mpnc/energy/mpncindicesenergy.hh +++ b/dumux/implicit/mpnc/energy/mpncindicesenergy.hh @@ -1,81 +1,8 @@ -// -*- 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 The indices for the non-isothermal part of the compositional - * multi-phase model. - */ -#ifndef DUMUX_MPNC_INDICES_ENERGY_HH -#define DUMUX_MPNC_INDICES_ENERGY_HH +#ifndef DUMUX_MPNC_INDICES_ENERGY_HH_OLD +#define DUMUX_MPNC_INDICES_ENERGY_HH_OLD -namespace Dumux -{ -/*! - * \ingroup MPNCModel - * \ingroup ImplicitIndices - * \brief The indices for the energy equation. - * - * This is a dummy class for the isothermal case. - */ -template <int PVOffset, bool enableEnergy/*=false*/, int numEnergyEquations/*=0*/> -struct MPNCEnergyIndices -{ - static_assert(((numEnergyEquations<1) and not enableEnergy), - "No kinetic energy transfer may only be enabled " - "if energy is enabled in general."); +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/energy/indices.hh instead - static_assert( (numEnergyEquations < 1) , - "No kinetic energy transfer module included, " - "but kinetic energy transfer enabled."); -public: - /*! - * \brief This module does not define any primary variables in the - * isothermal case. - */ - static const unsigned int numPrimaryVars = 0; -}; - -/*! - * \ingroup MPNCModel - * \ingroup ImplicitIndices - * \brief The indices required for the energy equation. - */ -template <int PVOffset> -struct MPNCEnergyIndices<PVOffset, /*isNonIsothermal=*/true, /*numEnergyEquations=*/ 1 > -{ -public: - /*! - * \brief This module defines one new primary variable. - */ - static const unsigned int numPrimaryVars = 1; - - /*! - * \brief Index for the temperature in a vector of primary - * variables. - */ - static const unsigned int temperatureIdx = PVOffset + 0; - /*! - * \brief Equation index of the energy equation. - */ - static const unsigned int energyEqIdx = PVOffset + 0; -}; - -} +#include <dumux/porousmediumflow/mpnc/implicit/energy/indices.hh> #endif diff --git a/dumux/implicit/mpnc/energy/mpncindicesenergykinetic.hh b/dumux/implicit/mpnc/energy/mpncindicesenergykinetic.hh index bf7abb03a495cbc7f8d6a829bea70db1845531f4..5caf13d4a9994affe5fc8333b50f984f2b74836d 100644 --- a/dumux/implicit/mpnc/energy/mpncindicesenergykinetic.hh +++ b/dumux/implicit/mpnc/energy/mpncindicesenergykinetic.hh @@ -1,167 +1,8 @@ -// -*- 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 The indices for the thermal non-equilibrium part of the MpNc model. - */ -#ifndef DUMUX_MPNC_INDICES_ENERGY_KINETIC_HH -#define DUMUX_MPNC_INDICES_ENERGY_KINETIC_HH +#ifndef DUMUX_MPNC_INDICES_ENERGY_KINETIC_HH_OLD +#define DUMUX_MPNC_INDICES_ENERGY_KINETIC_HH_OLD -#include <dumux/implicit/mpnc/mpncindices.hh> +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/energy/indiceskinetic.hh instead -namespace Dumux -{ - -/*! - * \brief The indices required for the energy equation. Specialization for the case of - * *3* energy balance equations. - */ -template <int PVOffset> -struct MPNCEnergyIndices<PVOffset, /*enableEnergy=*/true, /*numEnergyEquations=*/3> -{ -public: - /*! - * \brief This module defines one new primary variable. - */ - static const unsigned int numPrimaryVars = 3; - - /*! - * \brief Index for the temperature of the wetting phase in a vector of primary - * variables. - */ - static const unsigned int temperature0Idx = PVOffset + 0; - - /*! - * \brief Compatibility with non kinetic models - */ - static const unsigned int temperatureIdx = temperature0Idx; - /*! - * \brief Equation index of the energy equation. - */ - static const unsigned int energyEq0Idx = PVOffset + 0; - /*! - * \brief Compatibility with non kinetic models - */ - static const unsigned int energyEqIdx = energyEq0Idx; -}; - -/*! - * \brief The indices required for the energy equation. Specialization for the case of - * *2* energy balance equations. - */ -template <int PVOffset> -struct MPNCEnergyIndices<PVOffset, /*enableEnergy=*/true, /*numEnergyEquations=*/2> -{ -public: - /*! - * \brief This module defines one new primary variable. - */ - static const unsigned int numPrimaryVars = 2; - - /*! - * \brief Index for the temperature of the wetting phase in a vector of primary - * variables. - */ - static const unsigned int temperature0Idx = PVOffset + 0; - - /*! - * \brief Compatibility with non kinetic models - */ - static const unsigned int temperatureIdx = temperature0Idx; - /*! - * \brief Equation index of the energy equation. - */ - static const unsigned int energyEq0Idx = PVOffset + 0; - /*! - * \brief Equation index of the energy equation. - */ - static const unsigned int energyEqSolidIdx = energyEq0Idx + numPrimaryVars - 1 ; - - /*! - * \brief Index for storing e.g. temperature fluidState - */ - static const unsigned int temperatureFluidIdx = 0 ; - static const unsigned int temperatureSolidIdx = 1 ; - - - /*! - * \brief Compatibility with non kinetic models - */ - static const unsigned int energyEqIdx = energyEq0Idx; - - -}; - -/*! - * \brief The indices required for the energy equation. - */ -template <int PVOffset, bool isNonIsothermal> -struct MPNCEnergyIndices<PVOffset, isNonIsothermal, /*numEnergyEquations=*/1 > -{ -public: - /*! - * \brief This module defines one new primary variable. - */ - static const unsigned int numPrimaryVars = 1; - - /*! - * \brief Index for the temperature in a vector of primary - * variables. - */ - static const unsigned int temperatureIdx = PVOffset + 0; - /*! - * \brief Equation index of the energy equation. - */ - static const unsigned int energyEqIdx = PVOffset + 0; -}; - -/*! - * \brief The indices for the energy equation. - * - * This is a dummy class for the isothermal case. - */ -template <int PVOffset> -struct MPNCEnergyIndices<PVOffset, /*isNonIsothermal=*/false, /*numEnergyEquations*/0> -{ -public: - /*! - * \brief This module does not define any primary variables in the - * isothermal case. - */ - static const unsigned int numPrimaryVars = 0; - - /*! - * \brief Equation index of the temperature primary variable. This - * is a dummy value which hopefully makes the simulation - * crash if used. - */ - static const unsigned int temperatureIdx = -1; - - /*! - * \brief Equation index of the energy equation. This is a dummy - * value which hopefully makes the simulation crash if used. - */ - static const unsigned int energyEqIdx = -1; -}; - - - -} +#include <dumux/porousmediumflow/mpnc/implicit/energy/indiceskinetic.hh> #endif diff --git a/dumux/implicit/mpnc/energy/mpnclocalresidualenergy.hh b/dumux/implicit/mpnc/energy/mpnclocalresidualenergy.hh index a2613ec6668260989338edcdeb13c6e58d550f72..8ca04ed37f14b9ab34122e445ad3336e8fdb87fb 100644 --- a/dumux/implicit/mpnc/energy/mpnclocalresidualenergy.hh +++ b/dumux/implicit/mpnc/energy/mpnclocalresidualenergy.hh @@ -1,296 +1,8 @@ -// -*- 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 parts of the local residual to - * calculate the heat flux in the fully coupled MpNc model. - */ -#ifndef DUMUX_MPNC_LOCAL_RESIDUAL_ENERGY_HH -#define DUMUX_MPNC_LOCAL_RESIDUAL_ENERGY_HH +#ifndef DUMUX_MPNC_LOCAL_RESIDUAL_ENERGY_HH_OLD +#define DUMUX_MPNC_LOCAL_RESIDUAL_ENERGY_HH_OLD -#include <dumux/implicit/mpnc/mpncproperties.hh> +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/energy/localresidual.hh instead -namespace Dumux { +#include <dumux/porousmediumflow/mpnc/implicit/energy/localresidual.hh> -/*! - * \brief Specialization of the energy module for the isothermal case. - * - * This class just does nothing. - */ -template <class TypeTag, bool enableEnergy/*=false*/, int numEnergyEquations /*=0*/> -class MPNCLocalResidualEnergy -{ - static_assert(!(numEnergyEquations && !enableEnergy), - "No kinetic energy transfer may only be enabled " - "if energy is enabled in general."); - static_assert(!numEnergyEquations, - "No kinetic energy transfer module included, " - "but kinetic energy transfer enabled."); - - typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - - enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; - enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; - - typedef typename Dune::FieldVector<Scalar, numComponents> ComponentVector; - -public: - /*! - * \brief Evaluate the amount all conservation quantities - * (e.g. phase mass) within a sub-control volume. - * - * The result should be averaged over the volume (e.g. phase mass - * inside a sub-control volume divided by the volume) - * - * \param storage The mass of the component within the sub-control volume - * \param volVars the Volume Variables - */ - static void computeStorage(PrimaryVariables &storage, - const VolumeVariables &volVars) - { - // do nothing, we're isothermal! - } - - /*! - * \brief Calculate the storage for all mass balance equations - * within a single fluid phase - * - * \param storage The mass of the component within the sub-control volume - * \param volVars the Volume Variables - * \param phaseIdx The local index of the phases - */ - static void addPhaseStorage(PrimaryVariables &storage, - const VolumeVariables &volVars, - const unsigned int phaseIdx) - { - // do nothing, we're isothermal! - } - - /*! - * \brief Evaluates the total flux of all conservation quantities - * over a face of a sub-control volume. - * - * \param flux The flux over the SCV (sub-control-volume) face for each component - * \param fluxVars The flux variables - * \param volVars The volume variables - * \param molarPhaseComponentValuesMassTransport The component-wise flux within a phase. Needed for energy transport. - */ - static void computeFlux(PrimaryVariables & flux, - const FluxVariables & fluxVars, - const ElementVolumeVariables & volVars, - const ComponentVector molarPhaseComponentValuesMassTransport[numPhases]) - { - // do nothing, we're isothermal! - } - /*! - * \brief Calculate the source term of the equation - * - * \param source The source/sink in the sub-control volume for each component - * \param volVars The volume variables - * \param componentIntoPhaseMassTransfer The component-wise transfer from one phase. Needed for energy transfer. - * - */ - static void computeSource(PrimaryVariables &source, - const VolumeVariables &volVars, - const ComponentVector componentIntoPhaseMassTransfer[numPhases]) - { - // do nothing, we're isothermal! - } -}; - - -template <class TypeTag> -class MPNCLocalResidualEnergy<TypeTag, /*enableEnergy=*/true, /*numEnergyEquations=*/ 1 > -{ - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; - typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; - - enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; - enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; - enum { energyEqIdx = Indices::energyEqIdx }; - - typedef typename Dune::FieldVector<Scalar, numComponents> ComponentVector; - -public: - /*! - * \brief Evaluate the amount all conservation quantities - * (e.g. phase mass) within a sub-control volume. - * - * The result should be averaged over the volume (e.g. phase mass - * inside a sub-control volume divided by the volume) - * - * \param storage The mass of the component within the sub-control volume - * \param volVars the Volume Variables - */ - static void computeStorage(PrimaryVariables &storage, - const VolumeVariables &volVars) - { - storage[energyEqIdx] = 0; - - // energy of the fluids - for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { - addPhaseStorage(storage, volVars, phaseIdx); - } - - // heat stored in the rock matrix - storage[energyEqIdx] += - volVars.fluidState().temperature(/*phaseIdx=*/0) - * volVars.solidDensity() - * (1.0 - volVars.porosity()) - * volVars.solidHeatCapacity(); - } - /*! - * \brief Calculate the storage for all mass balance equations - * within a single fluid phase - * - * \param storage The mass of the component within the sub-control volume - * \param volVars the Volume Variables - * \param phaseIdx The local index of the phases - */ - static void addPhaseStorage(PrimaryVariables &storage, - const VolumeVariables &volVars, - const unsigned int phaseIdx) - { - const FluidState &fs = volVars.fluidState(); - - // energy of the fluid - storage[energyEqIdx] += - fs.density(phaseIdx) - * fs.internalEnergy(phaseIdx) - * fs.saturation(phaseIdx) - * volVars.porosity(); - -#ifndef NDEBUG -if (!std::isfinite(storage[energyEqIdx])) - DUNE_THROW(NumericalProblem, "Calculated non-finite energy storage"); -#endif - } - /*! - * \brief Evaluates the total flux of all conservation quantities - * over a face of a sub-control volume. - * - * \param flux The flux over the SCV (sub-control-volume) face for each component - * \param fluxVars The flux Variables - * \param elemVolVars The volume variables of the current element - * \param molarPhaseComponentValuesMassTransport The component-wise flux within a phase. Needed for energy transport. - */ - static void computeFlux(PrimaryVariables & flux, - const FluxVariables & fluxVars, - const ElementVolumeVariables & elemVolVars, - const ComponentVector molarPhaseComponentValuesMassTransport[numPhases]) - { - flux[energyEqIdx] = 0.0; - - // fluid phases transport enthalpy individually - for(int phaseIdx=0; phaseIdx<numPhases; ++phaseIdx) - computePhaseEnthalpyFlux(flux, - fluxVars, - elemVolVars, - phaseIdx, - molarPhaseComponentValuesMassTransport[phaseIdx]); - - //conduction is treated lumped in this model - computeHeatConduction(flux, - fluxVars, - elemVolVars); - } - /*! - * \brief The advective Flux of the enthalpy - * \param flux The flux over the SCV (sub-control-volume) face for each component - * \param fluxVars The flux Variables - * \param elemVolVars The volume variables of the current element - * \param phaseIdx The local index of the phases - * \param molarComponentValuesMassTransport The component-wise flux in the current phase. Needed for energy transport. - */ - static void computePhaseEnthalpyFlux(PrimaryVariables & flux, - const FluxVariables & fluxVars, - const ElementVolumeVariables & elemVolVars, - const unsigned int phaseIdx, - const ComponentVector & molarComponentValuesMassTransport) - { - Scalar massFlux = 0; - - // calculate the mass flux in the phase i.e. make mass flux out of mole flux and add up the fluxes of a phase - for (int compIdx = 0; compIdx < numComponents; ++compIdx) - massFlux += molarComponentValuesMassTransport[compIdx] - * FluidSystem::molarMass(compIdx); - - unsigned int upIdx = fluxVars.face().i; - if (massFlux < 0) upIdx = fluxVars.face().j; - - // use the phase enthalpy of the upstream vertex to calculate - // the enthalpy transport - const VolumeVariables &up = elemVolVars[upIdx]; - flux[energyEqIdx] += up.fluidState().enthalpy(phaseIdx) * massFlux; -#ifndef NDEBUG -if (!std::isfinite(flux[energyEqIdx]) ) - DUNE_THROW(NumericalProblem, "Calculated non-finite energy flux"); -#endif - } - /*! - * \brief The heat conduction in the phase - * - * \param flux The flux over the SCV (sub-control-volume) face for each component - * \param fluxVars The flux Variables - * \param elemVolVars The volume variables of the current element - */ - static void computeHeatConduction(PrimaryVariables & flux, - const FluxVariables & fluxVars, - const ElementVolumeVariables & elemVolVars) - { - //lumped heat conduction of the rock matrix and the fluid phases - Scalar lumpedConductivity = fluxVars.fluxVarsEnergy().lambdaEff() ; - Scalar temperatureGradientNormal = fluxVars.fluxVarsEnergy().temperatureGradientNormal() ; - Scalar lumpedHeatConduction = - lumpedConductivity * temperatureGradientNormal ; - flux[energyEqIdx] += lumpedHeatConduction; -#ifndef NDEBUG -if (!std::isfinite(flux[energyEqIdx]) ) - DUNE_THROW(NumericalProblem, "Calculated non-finite energy flux"); #endif - } - - /*! - * \brief Calculate the source term of the equation - * - * \param source The source/sink in the sub-control volume for each component - * \param volVars The volume variables - * \param componentIntoPhaseMassTransfer The component-wise transfer from one phase. Needed for energy transfer. - */ - static void computeSource(PrimaryVariables &source, - const VolumeVariables &volVars, - const ComponentVector componentIntoPhaseMassTransfer[numPhases]) - { - source[energyEqIdx] = 0.0; - } -}; - -} - -#endif // DUMUX_MPNC_ENERGY_HH diff --git a/dumux/implicit/mpnc/energy/mpnclocalresidualenergykinetic.hh b/dumux/implicit/mpnc/energy/mpnclocalresidualenergykinetic.hh index bfe97a2a93911326618d85eed9b0769a246105d5..52da5be6dd5325c7f1966b14c8ed4f2f6242043c 100644 --- a/dumux/implicit/mpnc/energy/mpnclocalresidualenergykinetic.hh +++ b/dumux/implicit/mpnc/energy/mpnclocalresidualenergykinetic.hh @@ -1,786 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 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 parts of the local residual to - * calculate the heat conservation in the thermal non-equilibrium M-phase - * N-component model. - */ -#ifndef DUMUX_MPNC_LOCAL_RESIDUAL_ENERGY_KINETIC_HH -#define DUMUX_MPNC_LOCAL_RESIDUAL_ENERGY_KINETIC_HH +#ifndef DUMUX_MPNC_LOCAL_RESIDUAL_ENERGY_KINETIC_HH_OLD +#define DUMUX_MPNC_LOCAL_RESIDUAL_ENERGY_KINETIC_HH_OLD -#include <dumux/implicit/mpnc/mpnclocalresidual.hh> -#include <dumux/common/spline.hh> +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/energy/localresidualkinetic.hh instead +#include <dumux/porousmediumflow/mpnc/implicit/energy/localresidualkinetic.hh> -namespace Dumux -{ - -/*! - * \brief Specialization for the case of *3* energy balance equations. - */ -template <class TypeTag> -class MPNCLocalResidualEnergy<TypeTag, /*enableEnergy=*/true, /*numEnergyEquations=*/3> -{ - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; - typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; - - enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; - enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; - enum { energyEq0Idx = Indices::energyEq0Idx }; - enum { numEnergyEqs = Indices::numPrimaryEnergyVars}; - enum { wPhaseIdx = FluidSystem::wPhaseIdx}; - enum { nPhaseIdx = FluidSystem::nPhaseIdx}; - enum { nCompIdx = FluidSystem::nCompIdx}; - enum { wCompIdx = FluidSystem::wCompIdx}; - enum { sPhaseIdx = FluidSystem::sPhaseIdx}; - - typedef typename Dune::FieldVector<Scalar, numComponents> ComponentVector; - typedef typename Dune::FieldMatrix<Scalar, numPhases, numComponents> PhaseComponentMatrix; - -public: - /*! - * \brief Evaluate the amount all conservation quantities - * (e.g. phase mass) within a sub-control volume. - * - * The result should be averaged over the volume (e.g. phase mass - * inside a sub-control volume divided by the volume) - * - * \param storage The mass of the component within the sub-control volume - * \param volVars the Volume Variables - */ - static void computeStorage(PrimaryVariables & storage, - const VolumeVariables & volVars) - { - for(int energyEqIdx=0; energyEqIdx< numEnergyEqs; energyEqIdx++) - storage[energyEq0Idx+energyEqIdx] = 0; - - // energy of the fluids - for (int phaseIdx = 0; phaseIdx < numEnergyEqs; ++phaseIdx) { - addPhaseStorage(storage, volVars, phaseIdx); - } - } - /*! - * \brief BEWARE !!! - * Here comes some problem with the phase-specific conservation of energy: - * Imagine a displacement process, with the initial state being a fully saturated porous medium. - * If the residing phase is now displaced by another phase, what happens at the front of the process? - * At the very front there is one cell in which the invading phase enters and no invading (but residing) phase leaves. - * With enthalpy in the flux term and internal energy in the storage term, - * the difference (pv) has to be converted into temperature in order to fulfill energy conservation. - * -> A temperature peak at the front arises (if spatial discretization is sufficiently fine). - * This peak has a maximum value and does not increase with further refinement. - * -> Further evidence for this explanation: in a simple setting (constant parameters, - * few cells) the temperature peak can be correctly predicted a priori. - * -> -> For those situations with a distinct displacement process the same quantity has to be stored and transported - * This is equivalent to neglecting volume changing work. - * - * \brief Calculate the storage for all mass balance equations - * within a single fluid phase - * - * \param storage The mass of the component within the sub-control volume - * \param volVars the Volume Variables - * \param phaseIdx The local index of the phases - */ - static void addPhaseStorage(PrimaryVariables & storage, - const VolumeVariables & volVars, - const unsigned int phaseIdx) - { - - const FluidState & fs = volVars.fluidState(); - - if (phaseIdx not_eq sPhaseIdx) { - storage[energyEq0Idx + phaseIdx] += - fs.density(phaseIdx) * - fs.internalEnergy(phaseIdx) * - fs.saturation(phaseIdx) * - volVars.porosity(); - } - else if(phaseIdx == sPhaseIdx) { - // heat stored in the rock matrix - storage[energyEq0Idx+phaseIdx] += volVars.temperature(phaseIdx) * - volVars.solidDensity() * - (1.-volVars.porosity()) * - volVars.solidHeatCapacity(); - } - else - DUNE_THROW(Dune::NotImplemented, - "wrong index"); - - if (!std::isfinite(storage[energyEq0Idx+phaseIdx])) - DUNE_THROW(NumericalProblem, "Calculated non-finite storage"); - - } - /*! - * \brief Evaluates the total flux of all conservation quantities - * over a face of a sub-control volume. - * - * \param flux The flux over the SCV (sub-control-volume) face for each component - * \param fluxVars The flux Variables - * \param elemVolVars The volume variables of the current element - * \param molarPhaseComponentValuesMassTransport - */ - static void computeFlux(PrimaryVariables & flux, - const FluxVariables & fluxVars, - const ElementVolumeVariables & elemVolVars, - const ComponentVector molarPhaseComponentValuesMassTransport[numPhases]) - { - // reset all energy fluxes - for(int energyEqIdx=0; energyEqIdx<numEnergyEqs; ++energyEqIdx) - flux[energyEq0Idx + energyEqIdx] = 0.0; - - // only the fluid phases transport enthalpy - for(int phaseIdx=0; phaseIdx<numPhases; ++phaseIdx) - computePhaseEnthalpyFlux(flux, - fluxVars, - elemVolVars, - phaseIdx, - molarPhaseComponentValuesMassTransport[phaseIdx]); - - // all phases take part in conduction - for(int energyEqIdx=0; energyEqIdx<numEnergyEqs; ++energyEqIdx){ - computeHeatConduction(flux, - fluxVars, - elemVolVars, - energyEqIdx); - if (!std::isfinite(flux[energyEq0Idx + energyEqIdx])) - DUNE_THROW(NumericalProblem, "Calculated non-finite flux in phase " << energyEqIdx); - } - } - /*! - * \brief the advective Flux of the enthalpy - * \param flux The flux over the SCV (sub-control-volume) face for each component - * \param fluxVars The flux Variables - * \param elemVolVars The volume variables of the current element - * \param phaseIdx The local index of the phases - * \param molarComponentValuesMassTransport - */ - static void computePhaseEnthalpyFlux(PrimaryVariables & flux, - const FluxVariables & fluxVars, - const ElementVolumeVariables & elemVolVars, - const unsigned int phaseIdx, - const ComponentVector & molarComponentValuesMassTransport) - { - Scalar massFlux = 0; // mass flux is not the perfect term: sum_kappa (rho_alpha v_alpha x_alpha^kappa) = v_alpha rho_alpha - - // calculate the mass flux in the phase i.e. make mass flux out - // of mole flux and add up the fluxes of a phase - for (int compIdx = 0; compIdx < numComponents; ++compIdx){ - massFlux += molarComponentValuesMassTransport[compIdx] - * FluidSystem::molarMass(compIdx) ; - } - - unsigned int upIdx = fluxVars.face().i; - unsigned int dnIdx = fluxVars.face().j; - if (massFlux < 0){ - upIdx = fluxVars.face().j; - dnIdx = fluxVars.face().i; - } - - // use the phase enthalpy of the upstream vertex to calculate - // the enthalpy transport - const VolumeVariables & up = elemVolVars[upIdx]; - const VolumeVariables & dn = elemVolVars[dnIdx]; - - /* todo - * CAUTION: this is not exactly correct: does diffusion carry the upstream phase enthalpy? - * To be more precise this should be the components enthalpy. - * In the same vein: Counter current diffusion is not accounted for here. - */ - const Scalar transportedThingUp = up.fluidState().enthalpy(phaseIdx) ; - const Scalar transportedThingDn = dn.fluidState().enthalpy(phaseIdx) ; - - - const Scalar massUpwindWeight_ = GET_PARAM_FROM_GROUP(TypeTag, Scalar, Implicit, MassUpwindWeight); - flux[energyEq0Idx + phaseIdx] += massFlux * - (massUpwindWeight_ * transportedThingUp - + - (1.-massUpwindWeight_) * transportedThingDn ) ; - } - /*! - * \brief The heat conduction in the phase - * - * \param flux The flux over the SCV (sub-control-volume) face for each component - * \param fluxVars The flux Variables - * \param elemVolVars The volume variables of the current element - * \param phaseIdx The local index of the phases - */ - static void computeHeatConduction(PrimaryVariables & flux, - const FluxVariables & fluxVars, - const ElementVolumeVariables & elemVolVars, - const unsigned int phaseIdx) - { - const unsigned int iIdx = fluxVars.face().i; - const unsigned int kIdx = fluxVars.face().j; // k can be better distinguished from i - - const VolumeVariables & iVolVar = elemVolVars[iIdx]; - const VolumeVariables & kVolVar = elemVolVars[kIdx]; - - const FluidState & iFluidState = iVolVar.fluidState(); - const FluidState & kFluidState = kVolVar.fluidState(); - - const Scalar iPorosity = iVolVar.porosity(); - const Scalar kPorosity = kVolVar.porosity(); - const Scalar barPorosity = Dumux::harmonicMean(iPorosity, kPorosity); - - const Scalar ilambda = iVolVar.thermalConductivity(phaseIdx); - const Scalar klambda = kVolVar.thermalConductivity(phaseIdx); - // todo which average? - // Using a harmonic average is justified by its properties: if one phase does not conduct energy, there is no transfer - const Scalar barLambda = Dumux::harmonicMean(ilambda, klambda) ; - - const Scalar gradientNormal = fluxVars.fluxVarsEnergy().temperatureGradient(phaseIdx) - * fluxVars.face().normal ; - - // heat conduction of the rock matrix and the fluid phases - if (phaseIdx == sPhaseIdx){ - flux[energyEq0Idx + phaseIdx] -= barLambda * gradientNormal * (1.-barPorosity) ; - } - else if (phaseIdx == wPhaseIdx or phaseIdx == nPhaseIdx){ - const Scalar iSaturation = iFluidState.saturation(phaseIdx); - const Scalar kSaturation = kFluidState.saturation(phaseIdx); - const Scalar barSaturation = Dumux::harmonicMean(iSaturation, kSaturation); - flux[energyEq0Idx + phaseIdx] -= barLambda * gradientNormal * barPorosity * barSaturation ; - } - else - DUNE_THROW(Dune::NotImplemented, - "wrong index"); - } - /*! - * \brief Calculate the source term of the equation - * - * \param source The source/sink in the sub-control volume for each component - * \param volVars The volume variables - * \param componentIntoPhaseMassTransfer - */ - - static void computeSource(PrimaryVariables & source, - const VolumeVariables & volVars, - const ComponentVector componentIntoPhaseMassTransfer[numPhases]) - { - const Scalar awn = volVars.interfacialArea(wPhaseIdx, nPhaseIdx); - const Scalar aws = volVars.interfacialArea(wPhaseIdx, sPhaseIdx); - const Scalar ans = volVars.interfacialArea(nPhaseIdx, sPhaseIdx); - - const Scalar Tw = volVars.temperature(wPhaseIdx); - const Scalar Tn = volVars.temperature(nPhaseIdx); - const Scalar Ts = volVars.temperature(sPhaseIdx); - - const Scalar lambdaWetting = volVars.thermalConductivity(wPhaseIdx); - const Scalar lambdaNonWetting = volVars.thermalConductivity(nPhaseIdx); - const Scalar lambdaSolid = volVars.thermalConductivity(sPhaseIdx); - - // todo which average? - // Using a harmonic average is justified by its properties: if one phase does not conduct energy, there is no transfer - const Scalar lambdaWN = Dumux::harmonicMean(lambdaWetting, lambdaNonWetting); - const Scalar lambdaWS = Dumux::harmonicMean(lambdaWetting, lambdaSolid); - const Scalar lambdaNS = Dumux::harmonicMean(lambdaNonWetting, lambdaSolid); -// |------------------------------------------------------| -// | | | -// | | | -// | alpha | i | -// | T_alpha | T_i | -// | | | -// | | | -// |------------------------------------------------------| - -// T_i > T_\alpha i.e. heat going into \alpha phase - -// Q_{i \leadsto \alpha} = a_{\alpha i} lambda_{\alpha i} (T_i - T_\alpha) / d // i.e.: this is the r.h.s. of alpha - const Scalar characteristicLength = volVars.characteristicLength() ; - const Scalar factorEnergyTransfer = volVars.factorEnergyTransfer() ; - - const Scalar nusseltWN = Dumux::harmonicMean(volVars.nusseltNumber(wPhaseIdx), volVars.nusseltNumber(nPhaseIdx)); - const Scalar nusseltWS = volVars.nusseltNumber(wPhaseIdx); - const Scalar nusseltNS = volVars.nusseltNumber(nPhaseIdx); - -//#warning SET NUSSELT TO 1 -// const Scalar nusseltWN = 1. ; -// const Scalar nusseltWS = 1. ; -// const Scalar nusseltNS = 1. ; - - const Scalar wettingToNonWettingEnergyExchange = factorEnergyTransfer * (Tw - Tn) / characteristicLength * awn * lambdaWN * nusseltWN ; - const Scalar wettingToSolidEnergyExchange = factorEnergyTransfer * (Tw - Ts) / characteristicLength * aws * lambdaWS * nusseltWS ; - const Scalar nonWettingToSolidEnergyExchange = factorEnergyTransfer * (Tn - Ts) / characteristicLength * ans * lambdaNS * nusseltNS ; - -//#warning HEAT TRANSFER OFF -// const Scalar wettingToNonWettingEnergyExchange = 0. ; -// const Scalar wettingToSolidEnergyExchange = 0. ; -// const Scalar nonWettingToSolidEnergyExchange = 0. ; - - - for(int phaseIdx =0; phaseIdx<numEnergyEqs; ++phaseIdx){ - switch (phaseIdx){ - case wPhaseIdx: - source[energyEq0Idx + phaseIdx] = ( - wettingToNonWettingEnergyExchange - wettingToSolidEnergyExchange); - break; - case nPhaseIdx: - source[energyEq0Idx + phaseIdx] = (+ wettingToNonWettingEnergyExchange - nonWettingToSolidEnergyExchange); - break; - case sPhaseIdx: - source[energyEq0Idx + phaseIdx] = (+ wettingToSolidEnergyExchange + nonWettingToSolidEnergyExchange); - break; - default: - DUNE_THROW(Dune::NotImplemented, - "wrong index"); - } // end switch - - - - if (!std::isfinite(source[energyEq0Idx + phaseIdx])) - DUNE_THROW(NumericalProblem, "Calculated non-finite source, " << "Tw="<< Tw << " Tn="<< Tn<< " Ts="<< Ts); - }// end phases - -#define MASS_ENERGY_TRANSPORT 1 -#if MASS_ENERGY_TRANSPORT -// Here comes the catch: We are not doing energy conservation for the whole -// system, but rather for each individual phase. -// -> Therefore the energy fluxes over each phase boundary need be -// individually accounted for. -// -> Each particle crossing a phase boundary does carry some mass and -// thus energy! -// -> Therefore, this contribution needs to be added. - -// -> the particle always brings the energy of the originating phase. -// -> Energy advectivly transported into a phase = the moles of a component that go into a -// phase * molMass * enthalpy of the component in the *originating* phase - - // The fluidsystem likes to get a fluidstate. ... - const FluidState & fluidState = volVars.fluidState(); - - for(int phaseIdx =0; phaseIdx<numEnergyEqs; ++phaseIdx){ - switch (phaseIdx){ - case wPhaseIdx: - source[energyEq0Idx + phaseIdx] += (componentIntoPhaseMassTransfer[wPhaseIdx][nCompIdx] - * FluidSystem::molarMass(nCompIdx) - * FluidSystem::componentEnthalpy(fluidState, nPhaseIdx, nCompIdx) ); - source[energyEq0Idx + phaseIdx] += (componentIntoPhaseMassTransfer[wPhaseIdx][wCompIdx] - * FluidSystem::molarMass(wCompIdx) - * FluidSystem::componentEnthalpy(fluidState, nPhaseIdx, wCompIdx)); - break; - case nPhaseIdx: - source[energyEq0Idx + phaseIdx] += (componentIntoPhaseMassTransfer[nPhaseIdx][nCompIdx] - * FluidSystem::molarMass(nCompIdx) - * FluidSystem::componentEnthalpy(fluidState, wPhaseIdx, nCompIdx)); - source[energyEq0Idx + phaseIdx] += (componentIntoPhaseMassTransfer[nPhaseIdx][wCompIdx] - * FluidSystem::molarMass(wCompIdx) - * FluidSystem::componentEnthalpy(fluidState, wPhaseIdx, wCompIdx)); - break; - case sPhaseIdx: - break; // no sorption - default: - DUNE_THROW(Dune::NotImplemented, - "wrong index"); - } // end switch - }// end phases -#endif //MASS_ENERGY_TRANSPORT - Valgrind::CheckDefined(source); - }// end source -}; - - -/*! - * \brief Specialization for the case of *2* energy balance equations. - */ -template <class TypeTag> -class MPNCLocalResidualEnergy<TypeTag, /*enableEnergy=*/true, /*numEnergyEquations=*/2> -{ - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; - typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - - enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; - enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; - enum { energyEq0Idx = Indices::energyEq0Idx }; - enum { numEnergyEqs = Indices::numPrimaryEnergyVars}; - enum { wPhaseIdx = FluidSystem::wPhaseIdx}; - enum { nPhaseIdx = FluidSystem::nPhaseIdx}; - enum { nCompIdx = FluidSystem::nCompIdx}; - enum { wCompIdx = FluidSystem::wCompIdx}; - enum { sPhaseIdx = FluidSystem::sPhaseIdx}; - enum { energyEqSolidIdx = Indices::energyEqSolidIdx}; - enum { temperatureFluidIdx = Indices::temperatureFluidIdx}; - enum { temperatureSolidIdx = Indices::temperatureSolidIdx}; - enum { dim = GridView::dimension}; // Grid and world dimension - - - typedef typename Dune::FieldVector<Scalar, numComponents> ComponentVector; - typedef typename Dune::FieldMatrix<Scalar, numPhases, numComponents> PhaseComponentMatrix; - typedef typename FluidSystem::ParameterCache ParameterCache; - - typedef typename GET_PROP_TYPE(TypeTag, BaseLocalResidual) ParentType; - typedef Dumux::Spline<Scalar> Spline; - - -public: - /*! \brief Evaluate the amount all conservation quantities - * (e.g. phase mass) within a sub-control volume. - * - * The result should be averaged over the volume (e.g. phase mass - * inside a sub-control volume divided by the volume) - * - * \param storage The mass of the component within the sub-control volume - * \param volVars the Volume Variables - */ - static void computeStorage(PrimaryVariables & storage, - const VolumeVariables & volVars) - { - for(int energyEqIdx=0; energyEqIdx< numEnergyEqs; energyEqIdx++) - storage[energyEq0Idx+energyEqIdx] = 0; - - // energy of the fluids - for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { - addPhaseStorage(storage, volVars, phaseIdx); - } - // heat stored in the rock matrix - storage[energyEqSolidIdx] += - volVars.temperature(temperatureSolidIdx) - * volVars.solidDensity() - * (1.0 - volVars.porosity()) - * volVars.solidHeatCapacity(); - - if (!std::isfinite(storage[energyEqSolidIdx])) - DUNE_THROW(NumericalProblem, "Calculated non-finite storage"); - } - - /*! \brief Calculate the storage for all mass balance equations - * within a single fluid phase - * - * \param storage The mass of the component within the sub-control volume - * \param volVars the Volume Variables - * \param phaseIdx The local index of the phases - */ - static void addPhaseStorage(PrimaryVariables & storage, - const VolumeVariables & volVars, - const unsigned int phaseIdx) - { - - const FluidState & fs = volVars.fluidState(); - - if (phaseIdx not_eq sPhaseIdx) { - storage[energyEq0Idx ] += - fs.density(phaseIdx) * - fs.internalEnergy(phaseIdx) * - fs.saturation(phaseIdx) * - volVars.porosity(); - } - else - DUNE_THROW(Dune::NotImplemented, - "wrong index"); - - if (!std::isfinite(storage[energyEq0Idx])) - DUNE_THROW(NumericalProblem, "Calculated non-finite storage"); - } - - /*!\brief Evaluates the total flux of all conservation quantities - * over a face of a sub-control volume. - * - * \param flux The flux over the SCV (sub-control-volume) face for each component - * \param fluxVars The flux Variables - * \param elemVolVars The volume variables of the current element - * \param molarPhaseComponentValuesMassTransport - */ - static void computeFlux(PrimaryVariables & flux, - const FluxVariables & fluxVars, - const ElementVolumeVariables & elemVolVars, - const ComponentVector molarPhaseComponentValuesMassTransport[numPhases]) - { - // reset all energy fluxes - for(int energyEqIdx=0; energyEqIdx<numEnergyEqs; ++energyEqIdx) - flux[energyEq0Idx + energyEqIdx] = 0.0; - - // only the fluid phases transport enthalpy - for(int phaseIdx=0; phaseIdx<numPhases; ++phaseIdx) - computePhaseEnthalpyFlux(flux, - fluxVars, - elemVolVars, - phaseIdx, - molarPhaseComponentValuesMassTransport[phaseIdx]); - - // all phases take part in conduction - for(int energyEqIdx=0; energyEqIdx<numEnergyEqs; ++energyEqIdx){ - computeHeatConduction(flux, - fluxVars, - elemVolVars, - energyEqIdx); - - if (!std::isfinite(flux[energyEq0Idx + energyEqIdx])) - DUNE_THROW(NumericalProblem, "Calculated non-finite flux in phase " << energyEqIdx); - } - } - - /*! \brief the advective Flux of the enthalpy - * \param flux The flux over the SCV (sub-control-volume) face for each component - * \param fluxVars The flux Variables - * \param elemVolVars The volume variables of the current element - * \param phaseIdx The local index of the phases - * \param molarComponentValuesMassTransport - */ - static void computePhaseEnthalpyFlux(PrimaryVariables & flux, - const FluxVariables & fluxVars, - const ElementVolumeVariables & elemVolVars, - const unsigned int phaseIdx, - const ComponentVector & molarComponentValuesMassTransport) - { - Scalar massFlux = 0; // mass flux is not the perfect term: sum_kappa (rho_alpha v_alpha x_alpha^kappa) = v_alpha rho_alpha - - // calculate the mass flux in the phase i.e. make mass flux out - // of mole flux and add up the fluxes of a phase - for (int compIdx = 0; compIdx < numComponents; ++compIdx){ - massFlux += molarComponentValuesMassTransport[compIdx] - * FluidSystem::molarMass(compIdx) ; - } - - unsigned int upIdx = fluxVars.face().i; - unsigned int dnIdx = fluxVars.face().j; - if (massFlux < 0){ - upIdx = fluxVars.face().j; - dnIdx = fluxVars.face().i; - } - - // use the phase enthalpy of the upstream vertex to calculate - // the enthalpy transport - const VolumeVariables & up = elemVolVars[upIdx]; - const VolumeVariables & dn = elemVolVars[dnIdx]; - - /* todo - * CAUTION: this is not exactly correct: does diffusion carry the upstream phase enthalpy? To be more precise this should be the components enthalpy. In the same vein: Counter current diffusion is not accounted for here. - */ - const Scalar transportedThingUp = up.fluidState().enthalpy(phaseIdx) ; - const Scalar transportedThingDn = dn.fluidState().enthalpy(phaseIdx) ; - - const Scalar massUpwindWeight_ = GET_PARAM_FROM_GROUP(TypeTag, Scalar, Implicit, MassUpwindWeight); - flux[energyEq0Idx] += massFlux * - (massUpwindWeight_ * transportedThingUp - + - (1.-massUpwindWeight_) * transportedThingDn ) ; - } - - /*! \brief The heat conduction in the phase - * - * \param flux The flux over the SCV (sub-control-volume) face for each component - * \param fluxVars The flux Variables - * \param elemVolVars The volume variables of the current element - * \param energyEqIdx The index of the phase energy equation - */ - static void computeHeatConduction(PrimaryVariables & flux, - const FluxVariables & fluxVars, - const ElementVolumeVariables & elemVolVars, - const unsigned int energyEqIdx) - { - const unsigned int iIdx = fluxVars.face().i; - const unsigned int kIdx = fluxVars.face().j; // k can be better distinguished from i - - const VolumeVariables & iVolVar = elemVolVars[iIdx]; - const VolumeVariables & kVolVar = elemVolVars[kIdx]; - - const Scalar iPorosity = iVolVar.porosity(); - const Scalar kPorosity = kVolVar.porosity(); - const Scalar barPorosity = Dumux::harmonicMean(iPorosity, kPorosity); - - const Scalar iSolidLambda = iVolVar.thermalConductivity(sPhaseIdx); - const Scalar kSolidLambda = kVolVar.thermalConductivity(sPhaseIdx); - - // Using a harmonic average is justified by its properties: if one phase does not conduct energy, there is no transfer - const Scalar barSolidLambda = (iSolidLambda+kSolidLambda) / 2.0; - - const Scalar lumpedConductivity = fluxVars.fluxVarsEnergy().lambdaEff() ; - - const Scalar gradientNormal = fluxVars.fluxVarsEnergy().temperatureGradient(energyEqIdx) - * fluxVars.face().normal ; - - // heat conduction of the rock matrix and the fluid phases - if (energyEqIdx == temperatureSolidIdx){ - flux[energyEqSolidIdx] -= barSolidLambda * (1.-barPorosity) * gradientNormal ; - } - else if (energyEqIdx == temperatureFluidIdx){ - flux[energyEq0Idx ] -= lumpedConductivity /*already includes porosity*/ * gradientNormal ; - } - else - DUNE_THROW(Dune::NotImplemented, - "wrong index"); - } - - /*! \brief Calculate the source term of the equation - * - * \param source The source/sink in the sub-control volume for each component - * \param volVars The volume variables - * \param componentIntoPhaseMassTransfer - */ - static void computeSource(PrimaryVariables & source, - const VolumeVariables & volVars, - const ComponentVector componentIntoPhaseMassTransfer[numPhases]) - { - const Scalar solidToFluidEnergyExchange = qsf(volVars) ; - - for(int energyEqIdx =0; energyEqIdx<numEnergyEqs; ++energyEqIdx){ - switch (energyEqIdx){ - case 0 : - source[energyEq0Idx + energyEqIdx] = solidToFluidEnergyExchange; - break; - case 1 : - source[energyEq0Idx + energyEqIdx] = - solidToFluidEnergyExchange; - break; - default: - DUNE_THROW(Dune::NotImplemented, - "wrong index"); - } // end switch - }// end energyEqIdx - Valgrind::CheckDefined(source); - }// end source - - - /*! \brief Calculate the whole energy transfer - * - * \param volVars The volume variables - */ - static Scalar qsf(const VolumeVariables & volVars) - { - const FluidState & fs = volVars.fluidState() ; - const Scalar characteristicLength = volVars.characteristicLength() ; - - // Shi & Wang, Transport in porous media (2011) - const Scalar as = 6.0 * (1.0-volVars.porosity()) / characteristicLength ; - - const Scalar TFluid = volVars.temperature(temperatureFluidIdx); - const Scalar TSolid = volVars.temperature(temperatureSolidIdx); - - const Scalar satW = fs.saturation(wPhaseIdx) ; - const Scalar satN = fs.saturation(nPhaseIdx) ; - - const Scalar eps = 1e-6 ; - Scalar solidToFluidEnergyExchange ; - - Scalar fluidConductivity ; - if (satW < 1.0 - eps) - fluidConductivity = volVars.thermalConductivity(nPhaseIdx) ; - else if (satW >= 1.0 - eps) - fluidConductivity = volVars.thermalConductivity(wPhaseIdx) ; - else - DUNE_THROW(Dune::NotImplemented, - "wrong range"); - - const Scalar factorEnergyTransfer = volVars.factorEnergyTransfer() ; - - solidToFluidEnergyExchange = factorEnergyTransfer * (TSolid - TFluid) / characteristicLength * as * fluidConductivity ; - - const Scalar epsRegul = 1e-3 ; - - if (satW < (0 + eps) ) - solidToFluidEnergyExchange *= volVars.nusseltNumber(nPhaseIdx) ; - - else if ( (satW >= 0 + eps) and (satW < 1.0-eps) ){ - solidToFluidEnergyExchange *= (volVars.nusseltNumber(nPhaseIdx) * satN ); - Scalar qBoil ; - - if (satW<=epsRegul){// regularize - Spline sp(0.0, epsRegul, // x1, x2 - QBoilFunc(volVars, 0.0), QBoilFunc(volVars, epsRegul), // y1, y2 - 0.0, dQBoil_dSw(volVars, epsRegul) ); // m1, m2 - - qBoil = sp.eval(satW) ; - } - - else if (satW>= (1.0-epsRegul) ){// regularize - Spline sp(1.0-epsRegul, 1.0, // x1, x2 - QBoilFunc(volVars, 1.0-epsRegul), 0.0, // y1, y2 - dQBoil_dSw(volVars, 1.0-epsRegul), 0.0 ); // m1, m2 - - qBoil = sp.eval(satW) ; - } - else - qBoil = QBoilFunc(volVars, satW) ; - - solidToFluidEnergyExchange += qBoil; - } - else if (satW >= 1.0-eps) - solidToFluidEnergyExchange *= volVars.nusseltNumber(wPhaseIdx) ; - else - DUNE_THROW(Dune::NotImplemented, - "wrong range"); - - if (!std::isfinite(solidToFluidEnergyExchange)) - DUNE_THROW(NumericalProblem, "Calculated non-finite source, " << "TFluid="<< TFluid << " TSolid="<< TSolid ); - - return solidToFluidEnergyExchange ; - } - - /*! \brief Calculate the energy transfer during boiling, i.e. latent heat - * - * \param volVars The volume variables - * \param satW The wetting phase saturation. Not taken from volVars, because we regularize. - */ - static Scalar QBoilFunc(const VolumeVariables & volVars, - const Scalar satW) - { - // using saturation as input (instead of from volVars) - // in order to make regularization (evaluation at different points) easyer - const FluidState & fs = volVars.fluidState() ; - const Scalar g( 9.81 ) ; - const Scalar gamma(0.0589) ; - const Scalar TSolid = volVars.temperature(temperatureSolidIdx); - const Scalar characteristicLength = volVars.characteristicLength() ; - - const Scalar as = 6.0 * (1.0-volVars.porosity()) / characteristicLength ; - const Scalar mul = fs.viscosity(wPhaseIdx) ; - const Scalar deltahv = fs.enthalpy(nPhaseIdx) - fs.enthalpy(wPhaseIdx); - const Scalar deltaRho = fs.density(wPhaseIdx) - fs.density(nPhaseIdx) ; - const Scalar firstBracket = std::pow(g * deltaRho / gamma, 0.5); - const Scalar cp = FluidSystem::heatCapacity(fs, wPhaseIdx) ; - // This use of Tsat is only justified if the fluid is always boiling (tsat equals boiling conditions) - // If a different state is to be simulated, please use the actual fluid temperature instead. - const Scalar Tsat = FluidSystem::vaporTemperature(fs, nPhaseIdx ) ; - const Scalar deltaT = TSolid - Tsat ; - const Scalar secondBracket = std::pow( (cp *deltaT / (0.006 * deltahv) ) , 3.0 ) ; - const Scalar Prl = volVars.prandtlNumber(wPhaseIdx) ; - const Scalar thirdBracket = std::pow( 1/Prl , (1.7/0.33) ); - const Scalar QBoil = satW * as * mul * deltahv * firstBracket * secondBracket * thirdBracket ; - return QBoil; - } - - /*! \brief Calculate the derivative of the energy transfer function during boiling. Needed for regularization. - * - * \param volVars The volume variables - * \param satW The wetting phase saturation. Not taken from volVars, because we regularize. - */ - static Scalar dQBoil_dSw(const VolumeVariables & volVars, - const Scalar satW) - { - // on the fly derive w.r.t. Sw. - // Only linearly depending on it (directly) - return (QBoilFunc(volVars, satW) / satW ) ; - } -}; - - -} // end namespace Dumux - -#endif // DUMUX_MPNC_LOCAL_RESIDUAL_ENERGY_KINETIC_HH +#endif diff --git a/dumux/implicit/mpnc/energy/mpncvolumevariablesenergy.hh b/dumux/implicit/mpnc/energy/mpncvolumevariablesenergy.hh index 8b026a058c1418c339c4e98c7df77cf52225a86b..262ecb0325298e292bf8085715c5fce0bd217c54 100644 --- a/dumux/implicit/mpnc/energy/mpncvolumevariablesenergy.hh +++ b/dumux/implicit/mpnc/energy/mpncvolumevariablesenergy.hh @@ -1,248 +1,8 @@ -// -*- 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 Contains the energy part of volume variables of the MpNc model. - */ -#ifndef DUMUX_MPNC_ENERGY_VOLUME_VARIABLES_HH -#define DUMUX_MPNC_ENERGY_VOLUME_VARIABLES_HH +#ifndef DUMUX_MPNC_ENERGY_VOLUME_VARIABLES_HH_OLD +#define DUMUX_MPNC_ENERGY_VOLUME_VARIABLES_HH_OLD -#include <dumux/implicit/mpnc/mpncproperties.hh> -#include <dumux/material/fluidstates/compositionalfluidstate.hh> +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/energy/volumevariables.hh instead -namespace Dumux -{ -/*! - * \brief Contains the energy related quantities which are constant within a - * finite volume in a MpNc model. - * - * This is the dummy class for the isothermal case. Note that we're - * only isothermal in the sense that the temperature at a location and - * a time is specified outside of the model! - */ -template <class TypeTag, bool enableEnergy/*=false*/, int numEnergyEquations /*=don't care*/> -class MPNCVolumeVariablesEnergy -{ - static_assert(not (numEnergyEquations and not enableEnergy), - "No kinetic energy transfer may only be enabled " - "if energy is enabled in general."); - static_assert(numEnergyEquations < 1, - "No kinetic energy transfer module included, " - "but kinetic energy transfer enabled."); - - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GridView::template Codim<0>::Entity Element; - typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - - enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; - - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; - typedef typename FluidSystem::ParameterCache ParameterCache; - enum {dimWorld=GridView::dimensionworld}; - typedef Dune::FieldVector<Scalar,dimWorld> GlobalPosition; - - -public: - /*! - * \brief Update the temperature of the sub-control volume. - * - * \param fs Container for all the secondary variables concerning the fluids - * \param paramCache Container for cache parameters - * \param priVars The primary Variables - * \param element The finite element - * \param fvGeometry The finite-volume geometry in the fully implicit scheme - * \param scvIdx The index of the sub-control volume - * \param problem The problem - */ - void updateTemperatures(FluidState &fs, - ParameterCache ¶mCache, - const PrimaryVariables &priVars, - const Element &element, - const FVElementGeometry &fvGeometry, - const unsigned int scvIdx, - const Problem &problem) const - { - Scalar T = problem.temperatureAtPos(fvGeometry.subContVol[scvIdx].global); - fs.setTemperature(T); - } - - - /*! - * \brief Update the enthalpy and the internal energy for a given - * control volume. - * \param fs Container for all the secondary variables concerning the fluids - * \param paramCache Container for cache parameters - * \param element The finite element - * \param fvGeometry The finite-volume geometry in the fully implicit scheme - * \param scvIdx The index of the sub-control volume - * \param problem The problem - * - * Since we are isothermal, we don't need to do anything! - */ - void update(FluidState &fs, - ParameterCache ¶mCache, - const Element &element, - const FVElementGeometry &fvGeometry, - const unsigned int scvIdx, - const Problem &problem) - { - } - - /*! - * \brief If running under valgrind this produces an error message - * if some of the object's attributes is undefined. - */ - void checkDefined() const - { - } -}; - -/*! - * \brief Contains the energy related quantities which are constant within a - * finite volume in the two-phase, N-component model. - */ -template <class TypeTag> -class MPNCVolumeVariablesEnergy<TypeTag, /*enableEnergy=*/true, /*numEnergyEquations=*/ 1 > -{ - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GridView::template Codim<0>::Entity Element; - typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; - - enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; - enum { temperatureIdx = Indices::temperatureIdx }; - enum { numEnergyEqs = Indices::numPrimaryEnergyVars}; - enum { temperature0Idx = Indices::temperatureIdx }; - - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; - typedef typename FluidSystem::ParameterCache ParameterCache; - - enum { dimWorld = GridView::dimensionworld}; - typedef Dune::FieldVector<typename GridView::Grid::ctype, dimWorld> GlobalPosition; - -public: - /*! - * \brief Update the temperature of the sub-control volume. - * - * \param fs Container for all the secondary variables concerning the fluids - * \param paramCache Container for cache parameters - * \param sol The primary Vaiables - * \param element The finite element - * \param fvGeometry The finite-volume geometry in the fully implicit scheme - * \param scvIdx The index of the sub-control volume - * \param problem The problem - */ - void updateTemperatures(FluidState &fs, - ParameterCache ¶mCache, - const PrimaryVariables &sol, - const Element &element, - const FVElementGeometry &fvGeometry, - const unsigned int scvIdx, - const Problem &problem) const - { - // retrieve temperature from solution vector - Scalar T = sol[temperatureIdx]; - fs.setTemperature(T); - } - - /*! - * \brief Update the enthalpy and the internal energy for a given - * control volume. - * \param fs Container for all the secondary variables concerning the fluids - * \param paramCache Container for cache parameters - * \param element The finite element - * \param fvGeometry The finite-volume geometry in the fully implicit scheme - * \param scvIdx The index of the sub-control volume - * \param problem The problem - */ - void update(FluidState &fs, - ParameterCache ¶mCache, - const Element &element, - const FVElementGeometry &fvGeometry, - const unsigned int scvIdx, - const Problem &problem) - { - Valgrind::SetUndefined(*this); - - // heat capacities of the fluids plus the porous medium - solidHeatCapacity_ = - problem.spatialParams().solidHeatCapacity(element, fvGeometry, scvIdx); - Valgrind::CheckDefined(solidHeatCapacity_); - - solidDensity_ = - problem.spatialParams().solidDensity(element, fvGeometry, scvIdx); - Valgrind::CheckDefined(solidDensity_); - - // set the enthalpies - for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { - Scalar h = FluidSystem::enthalpy(fs, paramCache, phaseIdx); - fs.setEnthalpy(phaseIdx, h); - thermalConductivity_[phaseIdx] = FluidSystem::thermalConductivity(fs, phaseIdx); - } - } - - /*! - * \brief Returns the total heat capacity [J/(kg K)] of the rock matrix in - * the sub-control volume. - */ - Scalar solidHeatCapacity() const - { return solidHeatCapacity_; } - - /*! - * \brief Returns the thermal conductivity \f$\mathrm{[W/(m*K)]}\f$ of the fluid phase in - * the sub-control volume. - */ - Scalar thermalConductivity(const unsigned int phaseIdx) const - { return thermalConductivity_[phaseIdx] ; } - - /*! - * \brief Returns the total density of the given solid phase [kg / m^3] in - * the sub-control volume. - */ - Scalar solidDensity() const - { return solidDensity_; } - - /*! - * \brief If running under valgrind this produces an error message - * if some of the object's attributes is undefined. - */ - void checkDefined() const - { - Valgrind::CheckDefined(solidHeatCapacity_); - Valgrind::CheckDefined(solidDensity_); - } - -protected: - Scalar solidHeatCapacity_; - Scalar solidDensity_; - Scalar thermalConductivity_[numPhases] ; -}; - -} // end namespace +#include <dumux/porousmediumflow/mpnc/implicit/energy/volumevariables.hh> #endif diff --git a/dumux/implicit/mpnc/energy/mpncvolumevariablesenergykinetic.hh b/dumux/implicit/mpnc/energy/mpncvolumevariablesenergykinetic.hh index 9e62d336b5f7b8de6a91c152bdf56447e233b415..d893cdc0bc5b302d9048dd3976b731709abb2317 100644 --- a/dumux/implicit/mpnc/energy/mpncvolumevariablesenergykinetic.hh +++ b/dumux/implicit/mpnc/energy/mpncvolumevariablesenergykinetic.hh @@ -1,442 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 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 Contains the volume variables of the kinetic energy transfer - * module of the M-phase, N-component model. - */ -#ifndef DUMUX_MPNC_ENERGY_VOLUME_VARIABLES_KINETIC_HH -#define DUMUX_MPNC_ENERGY_VOLUME_VARIABLES_KINETIC_HH +#ifndef DUMUX_MPNC_ENERGY_VOLUME_VARIABLES_KINETIC_HH_OLD +#define DUMUX_MPNC_ENERGY_VOLUME_VARIABLES_KINETIC_HH_OLD -#include <dumux/implicit/mpnc/mpncvolumevariables.hh> -#include "mpncvtkwriterenergykinetic.hh" +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/energy/volumevariableskinetic.hh instead -namespace Dumux -{ -/*! - * \brief Contains the volume variables of the kinetic energy transfer - * module of the M-phase, N-component model. - * Specialization for the case of *3* energy balance equations. - */ -template <class TypeTag> -class MPNCVolumeVariablesEnergy<TypeTag, /*enableEnergy=*/true, /*numEnergyEquations=*/3> -{ - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GridView::template Codim<0>::Entity Element; - typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; - - enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; - enum { temperature0Idx = Indices::temperature0Idx }; - enum { nPhaseIdx = FluidSystem::nPhaseIdx }; - enum { wPhaseIdx = FluidSystem::wPhaseIdx }; - enum { sPhaseIdx = FluidSystem::sPhaseIdx }; - enum { numEnergyEqs = Indices::numPrimaryEnergyVars}; - - /*! - * \brief The fluid state which is used by the volume variables to - * store the thermodynamic state. - * - * If chemical equilibrium is not considered, we use the most - * generic fluid state. - */ - typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; - typedef typename FluidSystem::ParameterCache ParameterCache; - -public: - /*! - * \brief Update the temperature of the sub-control volume. - * - * \param priVars The primary variables - * \param element The finite Element - * \param fvGeometry The finite-volume geometry in the fully implicit scheme - * \param scvIdx The index of the sub-control volume - * \param problem The problem - * \param temperatureIdx The temperature Index - */ - Scalar getTemperature(const PrimaryVariables & priVars, - const Element & element, - const FVElementGeometry & fvGeometry, - const unsigned int scvIdx, - const Problem & problem, - const unsigned int temperatureIdx) const - { - // retrieve temperature from solution vector - return priVars[temperature0Idx + temperatureIdx]; // could also be solid phase - } - - /*! - * \brief Update the temperature of the sub-control volume. - * - * \param fluidState Container for all the secondary variables concerning the fluids - * \param paramCache Container for cache parameters - * \param priVars The primary Variables - * \param element The finite element - * \param fvGeometry The finite-volume geometry in the fully implicit scheme - * \param scvIdx The index of the sub-control volume - * \param problem The problem - */ - void updateTemperatures(FluidState & fluidState, - ParameterCache & paramCache, - const PrimaryVariables & priVars, - const Element & element, - const FVElementGeometry & fvGeometry, - const unsigned int scvIdx, - const Problem & problem) - { - assert(numPhases + 1 == numEnergyEqs); - for(int phaseIdx=0; phaseIdx < numPhases; ++phaseIdx){ - // retrieve temperature from solution vector - const Scalar T = priVars[temperature0Idx + phaseIdx]; - temperature_[phaseIdx]= T; - fluidState.setTemperature(phaseIdx, T); - } - - temperature_[sPhaseIdx] = priVars[temperature0Idx + sPhaseIdx]; - - Valgrind::CheckDefined(temperature_); - } - - /*! - * \brief Update the enthalpy and the internal energy for a given - * control volume. - * - * \param fluidState Container for all the secondary variables concerning the fluids - * \param paramCache Container for cache parameters - * \param element The finite element - * \param fvGeometry The finite-volume geometry in the fully implicit scheme - * \param scvIdx The index of the sub-control volume - * \param problem The problem - */ - void update(FluidState & fluidState, - ParameterCache & paramCache, - const Element & element, - const FVElementGeometry & fvGeometry, - const unsigned int scvIdx, - const Problem & problem) - { - solidHeatCapacity_ = - problem.spatialParams().solidHeatCapacity(element, fvGeometry, scvIdx); - Valgrind::CheckDefined(solidHeatCapacity_); - - for(int phaseIdx =0; phaseIdx<numPhases; ++phaseIdx){ - fluidThermalConductivity_[phaseIdx] = - FluidSystem::thermalConductivity(fluidState, paramCache, phaseIdx); - } - Valgrind::CheckDefined(fluidThermalConductivity_); - - - solidDensity_ = - problem.spatialParams().solidDensity(element, fvGeometry, scvIdx); - Valgrind::CheckDefined(solidDensity_); - - solidThermalConductivity_ = - problem.spatialParams().solidThermalConductivity(element, fvGeometry, scvIdx); - Valgrind::CheckDefined(solidThermalConductivity_); - - // set the enthalpies - for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { - Scalar h = FluidSystem::enthalpy(fluidState, paramCache, phaseIdx); - Valgrind::CheckDefined(h); - fluidState.setEnthalpy(phaseIdx, h); - } - } - - /*! - * \brief Returns the total heat capacity [J/(kg K)] of the rock matrix in - * the sub-control volume. - */ - Scalar solidHeatCapacity() const - { return solidHeatCapacity_; } - - /*! - * \brief Returns the temperature in fluid / solid phase(s) - * the sub-control volume. - * \param phaseIdx The local index of the phases - */ - Scalar temperature(const unsigned int phaseIdx) const - { return temperature_[phaseIdx]; } - - /*! - * \brief Returns the total density of the given solid phase [kg / m^3] in - * the sub-control volume. - */ - Scalar solidDensity() const - { return solidDensity_; } - - /*! - * \brief Returns the conductivity of the given solid phase [W/(m K)] in - * the sub-control volume. - */ - Scalar solidThermalConductivity() const - { return solidThermalConductivity_; } - - /*! - * \brief Returns the conductivity of the given fluid [W//m K)] in - * the sub-control volume. - * - * \param phaseIdx The local index of the phases - */ - Scalar thermalConductivity(const unsigned int phaseIdx) const - { - if(phaseIdx == wPhaseIdx or phaseIdx == nPhaseIdx ) - return fluidThermalConductivity_[phaseIdx]; - else if (phaseIdx == sPhaseIdx ) - return solidThermalConductivity_; - else - DUNE_THROW(Dune::NotImplemented, - "wrong index"); - } - - void checkDefinedTemp() const - { Valgrind::CheckDefined(temperature_); } - - /*! - * \brief If running under valgrind this produces an error message - * if some of the object's attributes is undefined. - */ - void checkDefined() const - { - Valgrind::CheckDefined(temperature_); - Valgrind::CheckDefined(fluidThermalConductivity_); - Valgrind::CheckDefined(solidThermalConductivity_); - Valgrind::CheckDefined(solidDensity_); - Valgrind::CheckDefined(solidHeatCapacity_); - } - -protected: - Scalar temperature_[numPhases + 1]; - Scalar solidHeatCapacity_; - Scalar solidDensity_; - Scalar solidThermalConductivity_; - Scalar fluidThermalConductivity_[numPhases]; -}; - - - -/*! - * \brief Contains the volume variables of the kinetic energy transfer - * module of the M-phase, N-component model. - * Specialization for the case of *2* energy balance equations. - */ -template <class TypeTag> -class MPNCVolumeVariablesEnergy<TypeTag, /*enableEnergy=*/true, /*numEnergyEquations=*/2> -{ - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GridView::template Codim<0>::Entity Element; - typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; - - enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; - enum { temperature0Idx = Indices::temperature0Idx }; - enum { nPhaseIdx = FluidSystem::nPhaseIdx }; - enum { wPhaseIdx = FluidSystem::wPhaseIdx }; - enum { sPhaseIdx = FluidSystem::sPhaseIdx }; - enum { numEnergyEqs = Indices::numPrimaryEnergyVars}; - - /*! - * \brief The fluid state which is used by the volume variables to - * store the thermodynamic state. - * - * If chemical equilibrium is not considered, we use the most - * generic fluid state. - */ - typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; - typedef typename FluidSystem::ParameterCache ParameterCache; - -public: - /*! - * \brief Update the temperature of the sub-control volume. - * - * \param priVars The primary variables - * \param element The finite Element - * \param fvGeometry The finite-volume geometry in the fully implicit scheme - * \param scvIdx The index of the sub-control volume - * \param problem The problem - * \param temperatureIdx The temperature Index - */ - Scalar getTemperature(const PrimaryVariables & priVars, - const Element & element, - const FVElementGeometry & fvGeometry, - const unsigned int scvIdx, - const Problem & problem, - const unsigned int temperatureIdx) const - { - // retrieve temperature from solution vector - return priVars[temperature0Idx + temperatureIdx]; // could also be solid phase - } - - /*! - * \brief Update the temperature of the sub-control volume. - * - * \param fluidState Container for all the secondary variables concerning the fluids - * \param paramCache Container for cache parameters - * \param priVars The primary Variables - * \param element The finite element - * \param fvGeometry The finite-volume geometry in the fully implicit scheme - * \param scvIdx The index of the sub-control volume - * \param problem The problem - */ - void updateTemperatures(FluidState & fluidState, - ParameterCache & paramCache, - const PrimaryVariables & priVars, - const Element & element, - const FVElementGeometry & fvGeometry, - const unsigned int scvIdx, - const Problem & problem) - { - assert(2 == numEnergyEqs); - - for(int energyEqIdx=0; energyEqIdx < numPhases; ++energyEqIdx){ - // retrieve temperature from solution vector - const Scalar T = priVars[temperature0Idx + energyEqIdx]; - temperature_[energyEqIdx]= T; - } - - fluidState.setTemperature(priVars[temperature0Idx]); - - Valgrind::CheckDefined(temperature_); - } - - /*! - * \brief Update the enthalpy and the internal energy for a given - * control volume. - * - * \param fluidState Container for all the secondary variables concerning the fluids - * \param paramCache Container for cache parameters - * \param element The finite element - * \param fvGeometry The finite-volume geometry in the fully implicit scheme - * \param scvIdx The index of the sub-control volume - * \param problem The problem - */ - void update(FluidState & fluidState, - ParameterCache & paramCache, - const Element & element, - const FVElementGeometry & fvGeometry, - const unsigned int scvIdx, - const Problem & problem) - { - solidHeatCapacity_ = - problem.spatialParams().solidHeatCapacity(element, fvGeometry, scvIdx); - Valgrind::CheckDefined(solidHeatCapacity_); - - for(int phaseIdx =0; phaseIdx<numPhases; ++phaseIdx){ - fluidThermalConductivity_[phaseIdx] = - FluidSystem::thermalConductivity(fluidState, paramCache, phaseIdx); - } - Valgrind::CheckDefined(fluidThermalConductivity_); - - - solidDensity_ = - problem.spatialParams().solidDensity(element, fvGeometry, scvIdx); - Valgrind::CheckDefined(solidDensity_); - - solidThermalConductivity_ = - problem.spatialParams().solidThermalConductivity(element, fvGeometry, scvIdx); - Valgrind::CheckDefined(solidThermalConductivity_); - - // set the enthalpies - for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { - Scalar h = FluidSystem::enthalpy(fluidState, paramCache, phaseIdx); - Valgrind::CheckDefined(h); - fluidState.setEnthalpy(phaseIdx, h); - } - } - - /*! - * \brief Returns the total heat capacity [J/(kg K)] of the rock matrix in - * the sub-control volume. - */ - Scalar solidHeatCapacity() const - { return solidHeatCapacity_; } - - /*! - * \brief Returns the temperature in fluid / solid phase(s) - * the sub-control volume. - * \param phaseIdx The local index of the phases - */ - Scalar temperature(const unsigned int phaseIdx) const - { return temperature_[phaseIdx]; } - - /*! - * \brief Returns the total density of the given solid phase [kg / m^3] in - * the sub-control volume. - */ - Scalar solidDensity() const - { return solidDensity_; } - - /*! - * \brief Returns the conductivity of the given solid phase [W/(m K)] in - * the sub-control volume. - */ - Scalar solidThermalConductivity() const - { return solidThermalConductivity_; } - - /*! - * \brief Returns the conductivity of the given fluid [W/(m K)] in - * the sub-control volume. - * - * \param phaseIdx The local index of the phases - */ - Scalar thermalConductivity(const unsigned int phaseIdx) const - { - if(phaseIdx == wPhaseIdx or phaseIdx == nPhaseIdx ) - return fluidThermalConductivity_[phaseIdx]; - else if (phaseIdx == sPhaseIdx ) - return solidThermalConductivity_; - else - DUNE_THROW(Dune::NotImplemented, - "wrong index"); - } - - void checkDefinedTemp() const - { Valgrind::CheckDefined(temperature_); } - - /*! - * \brief If running under valgrind this produces an error message - * if some of the object's attributes is undefined. - */ - void checkDefined() const - { - Valgrind::CheckDefined(temperature_); - Valgrind::CheckDefined(fluidThermalConductivity_); - Valgrind::CheckDefined(solidThermalConductivity_); - Valgrind::CheckDefined(solidDensity_); - Valgrind::CheckDefined(solidHeatCapacity_); - } - -protected: - Scalar temperature_[numEnergyEqs]; - Scalar solidHeatCapacity_; - Scalar solidDensity_; - Scalar solidThermalConductivity_; - Scalar fluidThermalConductivity_[numPhases]; -}; - -} // end namespace +#include <dumux/porousmediumflow/mpnc/implicit/energy/volumevariableskinetic.hh> #endif diff --git a/dumux/implicit/mpnc/energy/mpncvtkwriterenergy.hh b/dumux/implicit/mpnc/energy/mpncvtkwriterenergy.hh index 925560fed8c0460e728905e20755b05242ae31cf..2ec6d647e632c6c17ee8bfa4d30e36e6ea97dd2b 100644 --- a/dumux/implicit/mpnc/energy/mpncvtkwriterenergy.hh +++ b/dumux/implicit/mpnc/energy/mpncvtkwriterenergy.hh @@ -1,229 +1,8 @@ -// -*- 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 VTK writer module for the energy related quantities of the - * MpNc model. - */ -#ifndef DUMUX_MPNC_VTK_WRITER_ENERGY_HH -#define DUMUX_MPNC_VTK_WRITER_ENERGY_HH +#ifndef DUMUX_MPNC_VTK_WRITER_ENERGY_HH_OLD +#define DUMUX_MPNC_VTK_WRITER_ENERGY_HH_OLD -#include "../mpncvtkwritermodule.hh" +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/energy/vtkwriter.hh instead -namespace Dumux -{ -/*! - * \ingroup MPNCModel - * - * \brief VTK writer module for the energy related quantities of the - * MpNc model. - * - * This is the specialization for the case without energy. - */ -template<class TypeTag, - bool enableEnergy /* = false */, - int numEnergyEquations/*=0*/> -class MPNCVtkWriterEnergy : public MPNCVtkWriterModule<TypeTag> -{ - static_assert(numEnergyEquations < 1, - "If you enable kinetic energy transfer between fluids, you" - "also have to enable the energy in general!"); - - typedef MPNCVtkWriterModule<TypeTag> ParentType; - - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes; - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GridView::template Codim<0>::Entity Element; - - enum { dim = GridView::dimension }; - - typedef typename ParentType::ScalarVector ScalarVector; - typedef typename ParentType::PhaseVector PhaseVector; - enum { isBox = GET_PROP_VALUE(TypeTag, ImplicitIsBox) }; - enum { dofCodim = isBox ? dim : 0 }; - -public: - MPNCVtkWriterEnergy(const Problem &problem) - : ParentType(problem) - { - temperatureOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddTemperatures); - } - - /*! - * \brief Allocate memory for the scalar fields we would like to - * write to the VTK file. - */ - template <class MultiWriter> - void allocBuffers(MultiWriter &writer) - { - if (temperatureOutput_) this->resizeScalarBuffer_(temperature_, isBox); - } - - /*! - * \brief Modify the internal buffers according to the volume - * variables seen on an element - * - * \param element The finite element - * \param fvGeometry The finite-volume geometry in the fully implicit scheme - * \param elemVolVars The volume variables of the current element - * \param elemBcTypes The types of the boundary conditions for all vertices of the element - */ - void processElement(const Element &element, - const FVElementGeometry &fvGeometry, - const ElementVolumeVariables &elemVolVars, - const ElementBoundaryTypes &elemBcTypes) - { - for (int scvIdx = 0; scvIdx < fvGeometry.numScv; ++scvIdx) { - const unsigned int dofIdxGlobal = this->problem_.model().dofMapper().subIndex(element, scvIdx, dofCodim); - const VolumeVariables &volVars = elemVolVars[scvIdx]; - - if (temperatureOutput_) - temperature_[dofIdxGlobal] = volVars.fluidState().temperature(/*phaseIdx=*/0); - } - } - - /*! - * \brief Add all buffers to the VTK output writer. - */ - template <class MultiWriter> - void commitBuffers(MultiWriter &writer) - { - if (temperatureOutput_) - this->commitScalarBuffer_(writer, "T", temperature_, isBox); - } - -private: - bool temperatureOutput_; - - ScalarVector temperature_; -}; - -/*! - * \ingroup MPNCModel - * - * \brief VTK writer module for the energy related quantities of the - * MpNc model. - * - * This is the specialization for the case with an energy equation but - * local thermal equilibrium. (i.e. no kinetic energy transfer) - */ -template<class TypeTag> -class MPNCVtkWriterEnergy<TypeTag, /* enableEnergy = */ true, /* numEnergyEquations = */ 1 > - : public MPNCVtkWriterModule<TypeTag> -{ - typedef MPNCVtkWriterModule<TypeTag> ParentType; - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes; - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GridView::template Codim<0>::Entity Element; - - enum { dim = GridView::dimension }; - enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; - - typedef typename ParentType::ScalarVector ScalarVector; - typedef typename ParentType::PhaseVector PhaseVector; - enum { isBox = GET_PROP_VALUE(TypeTag, ImplicitIsBox) }; - enum { dofCodim = isBox ? dim : 0 }; - -public: - MPNCVtkWriterEnergy(const Problem &problem) - : ParentType(problem) - { - temperatureOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddTemperatures); - enthalpyOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddEnthalpies); - internalEnergyOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddInternalEnergies); - } - - /*! - * \brief Allocate memory for the scalar fields we would like to - * write to the VTK file. - */ - template <class MultiWriter> - void allocBuffers(MultiWriter &writer) - { - if (temperatureOutput_) this->resizeScalarBuffer_(temperature_, isBox); - if (enthalpyOutput_) this->resizePhaseBuffer_(enthalpy_, isBox); - if (internalEnergyOutput_) this->resizePhaseBuffer_(internalEnergy_, isBox); - } - - /*! - * \brief Modify the internal buffers according to the volume - * variables seen on an element - * - * \param element The finite element - * \param fvGeometry The finite-volume geometry in the fully implicit scheme - * \param elemVolVars The volume variables of the current element - * \param elemBcTypes The types of the boundary conditions for all vertices of the element - */ - void processElement(const Element &element, - const FVElementGeometry &fvGeometry, - const ElementVolumeVariables &elemVolVars, - const ElementBoundaryTypes &elemBcTypes) - { - for (int scvIdx = 0; scvIdx < fvGeometry.numScv; ++scvIdx) { - int gobalIdx = this->problem_.model().dofMapper().subIndex(element, scvIdx, dofCodim); - const VolumeVariables &volVars = elemVolVars[scvIdx]; - - if (temperatureOutput_) temperature_[gobalIdx] = volVars.fluidState().temperature(/*phaseIdx=*/0); - for (int phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) { - if (enthalpyOutput_) - enthalpy_[phaseIdx][gobalIdx] = volVars.fluidState().enthalpy(phaseIdx); - if (internalEnergyOutput_) - internalEnergy_[phaseIdx][gobalIdx] = volVars.fluidState().internalEnergy(phaseIdx); - } - } - } - - /*! - * \brief Add all buffers to the VTK output writer. - */ - template <class MultiWriter> - void commitBuffers(MultiWriter &writer) - { - if (temperatureOutput_) - this->commitScalarBuffer_(writer, "T", temperature_, isBox); - if (enthalpyOutput_) - this->commitPhaseBuffer_(writer, "h_%s", enthalpy_, isBox); - if (internalEnergyOutput_) - this->commitPhaseBuffer_(writer, "u_%s", internalEnergy_, isBox); - } - -private: - bool temperatureOutput_; - bool enthalpyOutput_; - bool internalEnergyOutput_; - - ScalarVector temperature_; - PhaseVector enthalpy_; - PhaseVector internalEnergy_; -}; - -} +#include <dumux/porousmediumflow/mpnc/implicit/energy/vtkwriter.hh> #endif diff --git a/dumux/implicit/mpnc/energy/mpncvtkwriterenergykinetic.hh b/dumux/implicit/mpnc/energy/mpncvtkwriterenergykinetic.hh index ab846374431e9b0850f5b3a359d2a5e861f26482..416453779cc62ef9fdf03054190ff5c32ba36563 100644 --- a/dumux/implicit/mpnc/energy/mpncvtkwriterenergykinetic.hh +++ b/dumux/implicit/mpnc/energy/mpncvtkwriterenergykinetic.hh @@ -1,533 +1,8 @@ -// -*- 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 VTK writer module for the energy related quantities of the - * MpNc model. - */ -#ifndef DUMUX_MPNC_VTK_WRITER_ENERGY_KINETIC_HH -#define DUMUX_MPNC_VTK_WRITER_ENERGY_KINETIC_HH +#ifndef DUMUX_MPNC_VTK_WRITER_ENERGY_KINETIC_HH_OLD +#define DUMUX_MPNC_VTK_WRITER_ENERGY_KINETIC_HH_OLD -#include <dumux/implicit/mpnc/mpncvtkwritermodule.hh> -#include <dumux/implicit/mpnc/energy/mpnclocalresidualenergykinetic.hh> -#include "mpncvtkwriterenergy.hh" +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/energy/vtkwriterkinetic.hh instead -namespace Dumux -{ -/*! - * \ingroup MPNCModel - * - * \brief VTK writer module for the energy related quantities of the - * MpNc model. - * - * This is the specialization for the case with *3* energy balance equations and - * no local thermal equilibrium. (i.e. _including_ kinetic energy transfer) - */ -template<class TypeTag> -class MPNCVtkWriterEnergy<TypeTag, /*enableEnergy = */ true, /* numEnergyEquations = */ 3 > - : public MPNCVtkWriterModule<TypeTag> -{ - typedef MPNCVtkWriterModule<TypeTag> ParentType; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes; - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GridView::template Codim<0>::Entity Element; - - enum { dim = GridView::dimension }; - enum { dimWorld = GridView::dimensionworld }; - enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; - enum { numEnergyEqs = Indices::numPrimaryEnergyVars}; - enum { velocityAveragingInModel = GET_PROP_VALUE(TypeTag, VelocityAveragingInModel) }; - - enum { reynoldsOutput = GET_PROP_VALUE(TypeTag, VtkAddReynolds) }; - enum { prandtlOutput = GET_PROP_VALUE(TypeTag, VtkAddPrandtl) }; - enum { nusseltOutput = GET_PROP_VALUE(TypeTag, VtkAddNusselt) }; - enum { interfacialAreaOutput= GET_PROP_VALUE(TypeTag, VtkAddInterfacialArea) }; - enum { velocityOutput = GET_PROP_VALUE(TypeTag, VtkAddVelocities) }; - - typedef typename ParentType::ScalarVector ScalarVector; - typedef typename ParentType::PhaseVector PhaseVector; - typedef typename ParentType::ComponentVector ComponentVector; - typedef std::array<ScalarVector, numEnergyEqs> EnergyEqVector; - - typedef Dune::FieldVector<Scalar, dimWorld> DimWorldVector; - typedef Dune::BlockVector<DimWorldVector> DimWorldField; - typedef std::array<DimWorldField, numPhases> PhaseDimWorldField; - - -public: - MPNCVtkWriterEnergy(const Problem &problem) - : ParentType(problem) - { - temperatureOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddTemperatures); - enthalpyOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddEnthalpies); - internalEnergyOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddInternalEnergies); - } - - /*! - * \brief Allocate memory for the scalar fields we would like to - * write to the VTK file. - */ - template <class MultiWriter> - void allocBuffers(MultiWriter &writer) - { - resizeTemperaturesBuffer_(temperature_); - this->resizeScalarBuffer_(TwMinusTn_); - this->resizeScalarBuffer_(TnMinusTs_); - this->resizeScalarBuffer_(awn_); - this->resizeScalarBuffer_(aws_); - this->resizeScalarBuffer_(ans_); - this->resizePhaseBuffer_(enthalpy_); - this->resizePhaseBuffer_(internalEnergy_); - this->resizePhaseBuffer_(reynoldsNumber_); - this->resizePhaseBuffer_(prandtlNumber_); - this->resizePhaseBuffer_(nusseltNumber_); - - /*only one of the two output options, otherwise paraview segfaults due to two times the same field name*/ - if (velocityAveragingInModel and not velocityOutput) { - Scalar numVertices = this->problem_.gridView().size(dim); - for (int phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) { - velocity_[phaseIdx].resize(numVertices); - velocity_[phaseIdx] = 0; - } - } - } - - /*! - * \brief Modify the internal buffers according to the volume - * variables seen on an element - * - * \param element The finite element - * \param fvGeometry The finite-volume geometry in the fully implicit scheme - * \param elemVolVars The volume variables of the current element - * \param elemBcTypes - */ - void processElement(const Element & element, - const FVElementGeometry & fvGeometry, - const ElementVolumeVariables & elemVolVars, - const ElementBoundaryTypes & elemBcTypes) - { - int numLocalVertices = element.geometry().corners(); - for (int localVertexIdx = 0; localVertexIdx < numLocalVertices; ++localVertexIdx) { - const unsigned int vIdxGlobal = this->problem_.vertexMapper().subIndex(element, localVertexIdx, dim); - const VolumeVariables &volVars = elemVolVars[localVertexIdx]; - - for (int phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) { - enthalpy_[phaseIdx][vIdxGlobal] = volVars.fluidState().enthalpy(phaseIdx); - internalEnergy_[phaseIdx][vIdxGlobal] = volVars.fluidState().internalEnergy(phaseIdx); - reynoldsNumber_[phaseIdx][vIdxGlobal] = volVars.reynoldsNumber(phaseIdx); - prandtlNumber_[phaseIdx][vIdxGlobal] = volVars.prandtlNumber(phaseIdx); - nusseltNumber_[phaseIdx][vIdxGlobal] = volVars.nusseltNumber(phaseIdx); - } - - // because numPhases only counts liquid phases - for (int phaseIdx = 0; phaseIdx < numEnergyEqs; ++ phaseIdx) { - temperature_[phaseIdx][vIdxGlobal] = volVars.temperature(phaseIdx); - Valgrind::CheckDefined(temperature_[phaseIdx][vIdxGlobal]); - } - - const unsigned int wPhaseIdx = FluidSystem::wPhaseIdx; - const unsigned int nPhaseIdx = FluidSystem::nPhaseIdx; - const unsigned int sPhaseIdx = FluidSystem::sPhaseIdx; - - TwMinusTn_[vIdxGlobal] = volVars.temperature(wPhaseIdx) - volVars.temperature(nPhaseIdx); - TnMinusTs_[vIdxGlobal] = volVars.temperature(nPhaseIdx) - volVars.temperature(sPhaseIdx); - - awn_[vIdxGlobal] = volVars.interfacialArea(wPhaseIdx, nPhaseIdx); - aws_[vIdxGlobal] = volVars.interfacialArea(wPhaseIdx, sPhaseIdx); - ans_[vIdxGlobal] = volVars.interfacialArea(nPhaseIdx, sPhaseIdx); - - /*only one of the two output options, otherwise paraview segfaults due to two times the same field name*/ - if (velocityAveragingInModel and not velocityOutput){ - // numVertices for vertexCentereed, numVolumes for volume centered - int numVertices = this->problem_.gridView().size(dim); - for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) - for (int I = 0; I < numVertices; ++I) - velocity_[phaseIdx][I] = this->problem_.model().volumeDarcyVelocity(phaseIdx, I); - } - } - } - - /*! - * \brief Add all buffers to the VTK output writer. - */ - template <class MultiWriter> - void commitBuffers(MultiWriter & writer) - { - - if(interfacialAreaOutput){ - this->commitScalarBuffer_(writer, "awn" , awn_); - this->commitScalarBuffer_(writer, "aws" , aws_); - this->commitScalarBuffer_(writer, "ans" , ans_); - } - - if (temperatureOutput_){ - this->commitTemperaturesBuffer_(writer, "T_%s", temperature_); - this->commitScalarBuffer_(writer, "TwMinusTn" , TwMinusTn_); - this->commitScalarBuffer_(writer, "TnMinusTs" , TnMinusTs_); - } - - if (enthalpyOutput_) - this->commitPhaseBuffer_(writer, "h_%s", enthalpy_); - if (internalEnergyOutput_) - this->commitPhaseBuffer_(writer, "u_%s", internalEnergy_); - if (reynoldsOutput) - this->commitPhaseBuffer_(writer, "reynoldsNumber_%s", reynoldsNumber_); - if (prandtlOutput) - this->commitPhaseBuffer_(writer, "prandtlNumber_%s", prandtlNumber_); - if (nusseltOutput) - this->commitPhaseBuffer_(writer, "nusseltNumber_%s", nusseltNumber_); - /*only one of the two output options, otherwise paraview segfaults due to two timies the same field name*/ - if (velocityAveragingInModel and not velocityOutput){ - for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { - // commit the phase velocity - std::ostringstream oss; - oss << "velocity_" << FluidSystem::phaseName(phaseIdx); - writer.attachVertexData(velocity_[phaseIdx], - oss.str(), - dim); - } - } - } - -private: - /*! - * \brief Allocate the space for a buffer storing temperatures. - * This is one more entry than (fluid) phases. - */ - void resizeTemperaturesBuffer_(EnergyEqVector & buffer, - bool vertexCentered = true) - { - Scalar n; // numVertices for vertexCentereed, numVolumes for volume centered - if (vertexCentered) - n = this->problem_.gridView().size(dim); - else - n = this->problem_.gridView().size(0); - - for (int energyEqIdx = 0; energyEqIdx < numEnergyEqs; ++energyEqIdx) { - buffer[energyEqIdx].resize(n); - std::fill(buffer[energyEqIdx].begin(), buffer[energyEqIdx].end(), 0.0); - } - } - -/*! - * \brief Add a buffer for the three tmeperatures (fluids+solid) to the VTK result file. - */ - template <class MultiWriter> - void commitTemperaturesBuffer_(MultiWriter & writer, - const char *pattern, - EnergyEqVector & buffer, - bool vertexCentered = true) - { - for (int energyEqIdx = 0; energyEqIdx < numEnergyEqs; ++energyEqIdx) { - std::ostringstream oss; - oss << "T_" << FluidSystem::phaseName(energyEqIdx); - - if (vertexCentered) - writer.attachVertexData(buffer[energyEqIdx], oss.str(), 1); - else - writer.attachCellData(buffer[energyEqIdx], oss.str(), 1); - } - } - - EnergyEqVector temperature_ ; - ScalarVector TwMinusTn_; - ScalarVector TnMinusTs_; - PhaseVector enthalpy_ ; - PhaseVector internalEnergy_ ; - PhaseVector reynoldsNumber_ ; - PhaseVector prandtlNumber_ ; - PhaseVector nusseltNumber_ ; - - PhaseDimWorldField velocity_; - - ScalarVector awn_; - ScalarVector aws_; - ScalarVector ans_; - - bool temperatureOutput_; - bool enthalpyOutput_; - bool internalEnergyOutput_; -}; - -/*! - * \ingroup MPNCModel - * - * \brief VTK writer module for the energy related quantities of the - * MpNc model. - * - * This is the specialization for the case with *2* energy balance equations and - * no local thermal equilibrium. (i.e. _including_ kinetic energy transfer) - */ -template<class TypeTag> -class MPNCVtkWriterEnergy<TypeTag, /*enableEnergy = */ true, /* numEnergyEquations = */ 2 > - : public MPNCVtkWriterModule<TypeTag> -{ - typedef MPNCVtkWriterModule<TypeTag> ParentType; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes; - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef MPNCLocalResidualEnergy<TypeTag, /*enableEnergy=*/true, /*numEnergyEquations=*/2> LocalResidual; - typedef typename GridView::template Codim<0>::Entity Element; - - enum { dim = GridView::dimension }; - enum { dimWorld = GridView::dimensionworld }; - enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; - enum { wPhaseIdx = FluidSystem::wPhaseIdx}; - - enum { numEnergyEqs = Indices::numPrimaryEnergyVars}; - enum { velocityAveragingInModel = GET_PROP_VALUE(TypeTag, VelocityAveragingInModel) }; - - enum { reynoldsOutput = GET_PROP_VALUE(TypeTag, VtkAddReynolds) }; - enum { prandtlOutput = GET_PROP_VALUE(TypeTag, VtkAddPrandtl) }; - enum { nusseltOutput = GET_PROP_VALUE(TypeTag, VtkAddNusselt) }; - enum { interfacialAreaOutput= GET_PROP_VALUE(TypeTag, VtkAddInterfacialArea) }; - enum { velocityOutput = GET_PROP_VALUE(TypeTag, VtkAddVelocities) }; - - typedef typename ParentType::ScalarVector ScalarVector; - typedef typename ParentType::PhaseVector PhaseVector; - typedef typename ParentType::ComponentVector ComponentVector; - typedef std::array<ScalarVector, numEnergyEqs> EnergyEqVector; - - typedef Dune::FieldVector<Scalar, dimWorld> DimWorldVector; - typedef Dune::BlockVector<DimWorldVector> DimWorldField; - typedef std::array<DimWorldField, numPhases> PhaseDimWorldField; - - -public: - MPNCVtkWriterEnergy(const Problem &problem) - : ParentType(problem) - { - temperatureOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddTemperatures); - enthalpyOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddEnthalpies); - internalEnergyOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddInternalEnergies); - } - - /*! - * \brief Allocate memory for the scalar fields we would like to - * write to the VTK file. - */ - template <class MultiWriter> - void allocBuffers(MultiWriter &writer) - { - resizeTemperaturesBuffer_(temperature_); - this->resizePhaseBuffer_(enthalpy_); - this->resizePhaseBuffer_(internalEnergy_); - this->resizePhaseBuffer_(reynoldsNumber_); - this->resizePhaseBuffer_(prandtlNumber_); - this->resizePhaseBuffer_(nusseltNumber_); - this->resizeScalarBuffer_(qBoil_); - this->resizeScalarBuffer_(qsf_); - - - if (velocityAveragingInModel and not velocityOutput/*only one of the two output options, otherwise paraview segfaults due to two times the same field name*/) { - Scalar numVertices = this->problem_.gridView().size(dim); - for (int phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) { - velocity_[phaseIdx].resize(numVertices); - velocity_[phaseIdx] = 0; - } - } - } - - /*! - * \brief Modify the internal buffers according to the volume - * variables seen on an element - * - * \param element The finite element - * \param fvGeometry The finite-volume geometry in the fully implicit scheme - * \param elemVolVars The volume variables of the current element - * \param elemBcTypes - */ - void processElement(const Element & element, - const FVElementGeometry & fvGeometry, - const ElementVolumeVariables & elemVolVars, - const ElementBoundaryTypes & elemBcTypes) - { - int numLocalVertices = element.geometry().corners(); - for (int localVertexIdx = 0; localVertexIdx < numLocalVertices; ++localVertexIdx) { - const unsigned int vIdxGlobal = this->problem_.vertexMapper().subIndex(element, localVertexIdx, dim); - const VolumeVariables &volVars = elemVolVars[localVertexIdx]; - - qBoil_[vIdxGlobal] = LocalResidual::QBoilFunc(volVars, volVars.fluidState().saturation(wPhaseIdx)); - qsf_[vIdxGlobal] = LocalResidual::qsf(volVars); - - for (int phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) { - enthalpy_[phaseIdx][vIdxGlobal] = volVars.fluidState().enthalpy(phaseIdx); - internalEnergy_[phaseIdx][vIdxGlobal] = volVars.fluidState().internalEnergy(phaseIdx); - reynoldsNumber_[phaseIdx][vIdxGlobal] = volVars.reynoldsNumber(phaseIdx); - prandtlNumber_[phaseIdx][vIdxGlobal] = volVars.prandtlNumber(phaseIdx); - nusseltNumber_[phaseIdx][vIdxGlobal] = volVars.nusseltNumber(phaseIdx); - } - - // because numPhases only counts liquid phases - for (int phaseIdx = 0; phaseIdx < numEnergyEqs; ++ phaseIdx) { - temperature_[phaseIdx][vIdxGlobal] = volVars.temperature(phaseIdx); - Valgrind::CheckDefined(temperature_[phaseIdx][vIdxGlobal]); - } - - if (velocityAveragingInModel and not velocityOutput/*only one of the two output options, otherwise paraview segfaults due to two times the same field name*/){ - int numVertices = this->problem_.gridView().size(dim); // numVertices for vertexCentereed, numVolumes for volume centered - - for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) - for (int I = 0; I < numVertices; ++I) - velocity_[phaseIdx][I] = this->problem_.model().volumeDarcyVelocity(phaseIdx, I); - } - } - } - - /*! - * \brief Add all buffers to the VTK output writer. - */ - template <class MultiWriter> - void commitBuffers(MultiWriter & writer) - { - - if (temperatureOutput_){ - this->commitTemperaturesBuffer_(writer, "T_%s", temperature_); - } - - this->commitScalarBuffer_(writer, "qBoil", qBoil_); - this->commitScalarBuffer_(writer, "qsf", qsf_); - - - if (enthalpyOutput_) - this->commitPhaseBuffer_(writer, "h_%s", enthalpy_); - if (internalEnergyOutput_) - this->commitPhaseBuffer_(writer, "u_%s", internalEnergy_); - if (reynoldsOutput) - this->commitPhaseBuffer_(writer, "reynoldsNumber_%s", reynoldsNumber_); - if (prandtlOutput) - this->commitPhaseBuffer_(writer, "prandtlNumber_%s", prandtlNumber_); - if (nusseltOutput) - this->commitPhaseBuffer_(writer, "nusseltNumber_%s", nusseltNumber_); - if (velocityAveragingInModel and not velocityOutput/*only one of the two output options, otherwise paraview segfaults due to two timies the same field name*/){ - for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { - // commit the phase velocity - std::ostringstream oss; - oss << "velocity_" << FluidSystem::phaseName(phaseIdx); - writer.attachVertexData(velocity_[phaseIdx], - oss.str(), - dim); - } - } - } - -private: - /*! - * \brief Allocate the space for a buffer storing temperatures. - * This is one more entry than (fluid) phases. - */ - void resizeTemperaturesBuffer_(EnergyEqVector & buffer, - bool vertexCentered = true) - { - Scalar n; // numVertices for vertexCentereed, numVolumes for volume centered - if (vertexCentered) - n = this->problem_.gridView().size(dim); - else - n = this->problem_.gridView().size(0); - - for (int energyEqIdx = 0; energyEqIdx < numEnergyEqs; ++energyEqIdx) { - buffer[energyEqIdx].resize(n); - std::fill(buffer[energyEqIdx].begin(), buffer[energyEqIdx].end(), 0.0); - } - } - -/*! - * \brief Add a buffer for the three tmeperatures (fluids+solid) to the VTK result file. - */ - template <class MultiWriter> - void commitTemperaturesBuffer_(MultiWriter & writer, - const char *pattern, - EnergyEqVector & buffer, - bool vertexCentered = true) - { - static const char *name[] = { - "fluid", - "solid" - }; - - for (int energyEqIdx = 0; energyEqIdx < numEnergyEqs; ++energyEqIdx) { - std::ostringstream oss; - oss << "T_" << name[energyEqIdx]; - - if (vertexCentered) - writer.attachVertexData(buffer[energyEqIdx], oss.str(), 1); - else - writer.attachCellData(buffer[energyEqIdx], oss.str(), 1); - } - } - -// static const char *phaseName(int phaseIdx) -// { -// static const char *name[] = { -// "w", -// "n" -// }; -// -// assert(0 <= phaseIdx && phaseIdx < numPhases); -// return name[phaseIdx]; -// } - - EnergyEqVector temperature_ ; - PhaseVector enthalpy_ ; - PhaseVector internalEnergy_ ; - PhaseVector reynoldsNumber_ ; - PhaseVector prandtlNumber_ ; - PhaseVector nusseltNumber_ ; - ScalarVector qBoil_ ; - ScalarVector qsf_ ; - PhaseDimWorldField velocity_; - - bool temperatureOutput_; - bool enthalpyOutput_; - bool internalEnergyOutput_; -}; - - - - - - - - - - - - - - - - - -} +#include <dumux/porousmediumflow/mpnc/implicit/energy/vtkwriterkinetic.hh> #endif diff --git a/dumux/implicit/mpnc/mass/mpncindicesmass.hh b/dumux/implicit/mpnc/mass/mpncindicesmass.hh index 3fad10dad2d767d459047e64ec0466193e7cf3ad..c2a4b4e0a2a3b65e8364ff37ccf1361e2630ca21 100644 --- a/dumux/implicit/mpnc/mass/mpncindicesmass.hh +++ b/dumux/implicit/mpnc/mass/mpncindicesmass.hh @@ -1,87 +1,8 @@ -// -*- 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 The indices for the mass flow part of the compositional - * multi-phase model. - */ -#ifndef DUMUX_MPNC_MASS_INDICES_HH -#define DUMUX_MPNC_MASS_INDICES_HH +#ifndef DUMUX_MPNC_MASS_INDICES_HH_OLD +#define DUMUX_MPNC_MASS_INDICES_HH_OLD -#include <dumux/implicit/mpnc/mpncproperties.hh> +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/mass/indices.hh instead -namespace Dumux -{ -/*! - * \ingroup MPNCModel - * \ingroup ImplicitIndices - * \brief The indices required for conservation of mass. - * - * This is the specialization for the case without kinetic mass - * transfer (i.e. assuming chemical equilibrium) - */ -template <int PVOffset, - class TypeTag, - bool enableKinetic /*=false*/> -class MPNCMassIndices -{ - static_assert(!enableKinetic, - "No kinetic mass transfer module included, " - "but kinetic mass transfer enabled."); - - enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; - -public: - /*! - * \brief This module defines one new primary variable. - */ - static const unsigned int numPrimaryVars = numComponents; - - /*! - * \brief Index for the fugacity of the first component in the - * first phase in a vector of primary variables. - * - * The next numComponents indices represent the remaining - * fugacities: - * - * fug0Idx + 0 = fugacity of component 0 - * fug0Idx + 1 = fugacity of component 1 - * ... - * fug0Idx + N - 1 = fugacity of component N - */ - static const unsigned int fug0Idx = PVOffset + 0; - - /*! - * \brief Equation index of the mass conservation equation for the - * first component. - * - * The next numComponents indices represent the equations of all - * components in all phases: - * - * conti00EqIdx + 0 = continuity of component 0 - * conti00EqIdx + 1 = continuity of component 1 - * ... - * conti00EqIdx + N - 1 = continuity of component N - */ - static const unsigned int conti0EqIdx = PVOffset + 0; -}; - -} +#include <dumux/porousmediumflow/mpnc/implicit/mass/indices.hh> #endif diff --git a/dumux/implicit/mpnc/mass/mpncindicesmasskinetic.hh b/dumux/implicit/mpnc/mass/mpncindicesmasskinetic.hh index 2ed88e3516bfb18c0292492fa91fd932ea87646a..b93814a4ef73ecd2c2f0d545111e9751f3fbfdc2 100644 --- a/dumux/implicit/mpnc/mass/mpncindicesmasskinetic.hh +++ b/dumux/implicit/mpnc/mass/mpncindicesmasskinetic.hh @@ -1,83 +1,8 @@ -// -*- 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 The indices for the kinetic mass transfer module of the - * compositional multi-phase model. - */ -#ifndef DUMUX_MPNC_MASS_INDICES_KINETIC_HH -#define DUMUX_MPNC_MASS_INDICES_KINETIC_HH +#ifndef DUMUX_MPNC_MASS_INDICES_KINETIC_HH_OLD +#define DUMUX_MPNC_MASS_INDICES_KINETIC_HH_OLD -#include <dumux/implicit/mpnc/mpncindices.hh> +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/mass/indiceskinetic.hh instead -namespace Dumux -{ -/*! - * \brief The indices required for conservation of mass. - * - * This is the specialization considering kinetic mass transfer - * (i.e. not assuming local chemical equilibrium) - */ -template <int PVOffset, class TypeTag> -class MPNCMassIndices<PVOffset, TypeTag, /*enableKinetic=*/true> -{ - enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; - enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; -public: - /*! - * \brief This module defines one new primary variable. - */ - static const unsigned int numPrimaryVars = numPhases*numComponents; - - /*! - * \brief Index for the mole fraction of the first component in - * the first phase in a vector of primary variables. - * - * The next numPhases*numComponents indices represent the - * compositions of all phases: - * - * moleFrac00Idx + 0 = mole fraction of component 0 in phase 0 - * moleFrac00Idx + 1 = mole fraction of component 1 in phase 0 - * ... - * moleFrac00Idx + N - 1 = mole fraction of component N in phase 0 - * moleFrac00Idx + N = mole fraction of component 0 in phase 1 - * ... - */ - static const unsigned int moleFrac00Idx = PVOffset + 0; - - /*! - * \brief Equation index of the mass conservation equation for the - * first component in the first phase. - * - * The next numPhases*numComponents indices represent the - * continuity equations of all components in all phases: - * - * conti00EqIdx + 0 = continuity of component 0 in phase 0 - * conti00EqIdx + 1 = continuity of component 1 in phase 0 - * ... - * conti00EqIdx + N - 1 = continuity of component N in phase 0 - * conti00EqIdx + N = continuity of component 0 in phase 1 - * ... - */ - static const unsigned int conti0EqIdx = PVOffset + 0; -}; - -} +#include <dumux/porousmediumflow/mpnc/implicit/mass/indiceskinetic.hh> #endif diff --git a/dumux/implicit/mpnc/mass/mpnclocalresidualmass.hh b/dumux/implicit/mpnc/mass/mpnclocalresidualmass.hh index 1f5743739f6a53101dbb04e171826f7182c482fd..efafcdfaaa38c62c8a733f5f7ecdcc00048ea269 100644 --- a/dumux/implicit/mpnc/mass/mpnclocalresidualmass.hh +++ b/dumux/implicit/mpnc/mass/mpnclocalresidualmass.hh @@ -1,401 +1,8 @@ -// -*- 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 The mass conservation part of the MpNc model. - */ -#ifndef DUMUX_MPNC_LOCAL_RESIDUAL_MASS_HH -#define DUMUX_MPNC_LOCAL_RESIDUAL_MASS_HH +#ifndef DUMUX_MPNC_LOCAL_RESIDUAL_MASS_HH_OLD +#define DUMUX_MPNC_LOCAL_RESIDUAL_MASS_HH_OLD -#include <dune/common/fvector.hh> +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/mass/localresidual.hh instead -#include <dumux/implicit/mpnc/mpncproperties.hh> -#include <dumux/material/constraintsolvers/compositionfromfugacities.hh> -#include <dumux/common/math.hh> -#include <dumux/common/spline.hh> - -#include "../diffusion/diffusion.hh" -#include "../energy/mpnclocalresidualenergy.hh" - -namespace Dumux -{ -/*! - * \brief This class represents methods which are shared amongst all - * mass conservation modules. - */ -template<class TypeTag> -class MPNCLocalResidualMassCommon -{ -protected: - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; - - enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; - enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; - enum { enableDiffusion = GET_PROP_VALUE(TypeTag, EnableDiffusion) }; - enum { enableEnergy = GET_PROP_VALUE(TypeTag, EnableEnergy) }; - enum { numEnergyEquations = GET_PROP_VALUE(TypeTag, NumEnergyEquations) }; - - typedef typename Dune::FieldVector<Scalar, numComponents> ComponentVector; - typedef MPNCDiffusion<TypeTag, enableDiffusion> Diffusion; - typedef MPNCLocalResidualEnergy<TypeTag, enableEnergy, numEnergyEquations> EnergyResid; - -public: - /*! - * \brief Evaluate the amount moles within a sub-control volume in - * a phase. - * - * \param storage The mass of the component within the sub-control volume - * \param volVars The volume variables - * \param phaseIdx phaseIdx The index of the fluid phase - * - * The result should be averaged over the volume. - */ - static void computePhaseStorage(ComponentVector &storage, - const VolumeVariables &volVars, - const unsigned int phaseIdx) - { - // compute storage term of all components within all phases - storage = 0; - for (int compIdx = 0; compIdx < numComponents; ++ compIdx) { - storage[compIdx] += - volVars.fluidState().saturation(phaseIdx)* - volVars.fluidState().molarity(phaseIdx, compIdx); -#ifndef NDEBUG -if (!std::isfinite(storage[compIdx])) - DUNE_THROW(NumericalProblem, "Calculated non-finite storage"); -#endif - } - - storage *= volVars.porosity(); - - } - - /*! - * \brief Evaluates the advective flux of all conservation - * quantities over a face of a subcontrol volume via a - * fluid phase. - * - * \param flux The flux over the SCV (sub-control-volume) face for each component - * \param fluxVars The flux Variables - * \param phaseIdx phaseIdx The index of the fluid phase - */ - static void computeAdvectivePhaseFlux(ComponentVector &flux, - const FluxVariables &fluxVars, - const unsigned int phaseIdx) - { - - const Scalar volumeFlux = fluxVars.volumeFlux(phaseIdx) ; - - - // retrieve the upwind weight for the mass conservation equations. Use the value - // specified via the property system as default, and overwrite - // it by the run-time parameter from the Dune::ParameterTree - const Scalar massUpwindWeight = GET_PARAM_FROM_GROUP(TypeTag, Scalar, Implicit, MassUpwindWeight); - - static bool enableSmoothUpwinding_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Implicit, EnableSmoothUpwinding); - - // data attached to upstream and the downstream vertices - // of the current phase - unsigned int upIdx = fluxVars.upstreamIdx(phaseIdx); - unsigned int dnIdx = fluxVars.downstreamIdx(phaseIdx); - - const VolumeVariables &up = fluxVars.volVars(upIdx); - const VolumeVariables &dn = fluxVars.volVars(dnIdx); - -if (!std::isfinite(volumeFlux)) - DUNE_THROW(NumericalProblem, "Calculated non-finite normal flux in phase" << phaseIdx); - //////// - // advective fluxes of all components in the phase - //////// - for (unsigned int compIdx = 0; compIdx < numComponents; ++compIdx) { - // add advective flux of current component in current - // phase. we use full upwinding. - if (enableSmoothUpwinding_) { - const Scalar kGradPNormal = fluxVars.kGradPNormal(phaseIdx); - const Scalar mobUp = up.mobility(phaseIdx); - const Scalar conUp = up.fluidState().molarity(phaseIdx, compIdx); - - const Scalar mobDn = dn.mobility(phaseIdx); - const Scalar conDn = dn.fluidState().molarity(phaseIdx, compIdx); - - const Scalar mobConUp = mobUp*conUp; - const Scalar mobConDn = mobDn*conDn; - const Scalar meanMobCon = Dumux::harmonicMean(mobConUp, mobConDn); - - const Scalar x = std::abs(kGradPNormal); - const Scalar sign = (kGradPNormal > 0)?-1:1; - - // approximate the mean viscosity at the face - const Scalar meanVisc = (up.fluidState().viscosity(phaseIdx) + - dn.fluidState().viscosity(phaseIdx))/2; - - // put the mean viscosity and permeanbility in - // relation to the viscosity of water at - // approximatly 20 degrees Celsius. - const Scalar pGradRef = 10; // [Pa/m] - const Scalar muRef = 1e-3; // [Ns/m^2] - const Scalar Kref = 1e-12; // [m^2] = approx 1 Darcy - - const Scalar faceArea = fluxVars.face().normal.two_norm(); - const Scalar eps = pGradRef * Kref * faceArea * meanVisc/muRef; // * (1e3/18e-3)/meanC; - - Scalar compFlux; - if (x >= eps) { - // we only do tricks if x is below the epsilon - // value - compFlux = x*mobConUp; - } - else { - const Scalar xPos[] = { 0, eps }; - const Scalar yPos[] = { 0, eps*mobConUp }; - const Spline<Scalar> sp2(xPos, yPos, meanMobCon, mobConUp); - compFlux = sp2.eval(x); - } - #ifndef NDEBUG - if (!std::isfinite(compFlux)) - DUNE_THROW(NumericalProblem, "Calculated non-finite normal flux in smooth upwinding"); - #endif - - flux[compIdx] = sign*compFlux; - } - else - {// not use smooth upwinding - flux[compIdx] = - volumeFlux * - (( massUpwindWeight)*up.fluidState().molarity(phaseIdx, compIdx) - + - ( 1. - massUpwindWeight)*dn.fluidState().molarity(phaseIdx, compIdx) ); - if (!std::isfinite(flux[compIdx])) - DUNE_THROW(NumericalProblem, "Calculated non-finite normal flux in phase " << phaseIdx << " comp " << compIdx << "T: "<< up.fluidState().temperature(phaseIdx) << "S "<<up.fluidState().saturation(phaseIdx) ) ; - } - } - } - - - /*! - * \brief Evaluates the advective flux of all conservation - * quantities over a face of a subcontrol volume via a - * fluid phase. - * - * \param flux The flux over the SCV (sub-control-volume) face for each component - * \param fluxVars The flux Variables - * \param phaseIdx phaseIdx The index of the fluid phase - */ - static void computeDiffusivePhaseFlux(ComponentVector &flux, - const FluxVariables &fluxVars, - const unsigned int phaseIdx) - { - if (!enableDiffusion) { - flux = 0.0; - return; - } - - - const VolumeVariables &volVarsI = fluxVars.volVars(fluxVars.face().i); - const VolumeVariables &volVarsJ = fluxVars.volVars(fluxVars.face().j); - if (volVarsI.fluidState().saturation(phaseIdx) < 1e-4 || - volVarsJ.fluidState().saturation(phaseIdx) < 1e-4) - { - return; // phase is not present in one of the finite volumes - } - - // approximate the total concentration of the phase at the - // integration point by the arithmetic mean of the - // concentration of the sub-control volumes - Scalar molarDensityAtIP; - molarDensityAtIP = volVarsI.fluidState().molarDensity(phaseIdx); - molarDensityAtIP += volVarsJ.fluidState().molarDensity(phaseIdx); - molarDensityAtIP /= 2; - - Diffusion::flux(flux, phaseIdx, fluxVars, molarDensityAtIP); - } -}; - -/*! - * \brief The mass conservation part of the MpNc model. - * - * This is the specialization for the case where kinetic mass transfer - * is _not_ considered. - */ -template<class TypeTag, bool enableKinetic /*=false*/> -class MPNCLocalResidualMass -{ - static_assert(!enableKinetic, - "No kinetic mass transfer module included, " - "but kinetic mass transfer enabled."); - - typedef MPNCLocalResidualMassCommon<TypeTag> MassCommon; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; - typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; - - enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; - enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; - enum { conti0EqIdx = Indices::conti0EqIdx }; - enum { enableEnergy = GET_PROP_VALUE(TypeTag, EnableEnergy) }; - enum { numEnergyEquations = GET_PROP_VALUE(TypeTag, NumEnergyEquations) }; - - typedef typename Dune::FieldVector<Scalar, numComponents> ComponentVector; - typedef MPNCLocalResidualEnergy<TypeTag, enableEnergy, numEnergyEquations> EnergyResid; - -public: - /*! - * \brief Calculate the storage for all mass balance equations - * - * \param storage The mass of the component within the sub-control volume - * \param volVars The volume variables - */ - static void computeStorage(PrimaryVariables &storage, - const VolumeVariables &volVars) - { - for (int compIdx = 0; compIdx < numComponents; ++compIdx) - storage[conti0EqIdx + compIdx] = 0.0; - - for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { - addPhaseStorage(storage, volVars, phaseIdx); - } - } - - /*! - * \brief Calculate the storage for all mass balance equations - * within a single fluid phase - * - * \param storage The mass of the component within the sub-control volume - * \param volVars The volume variables - * \param phaseIdx phaseIdx The index of the fluid phase - */ - static void addPhaseStorage(PrimaryVariables &storage, - const VolumeVariables &volVars, - const unsigned int phaseIdx) - { - // calculate the component-wise mass storage - ComponentVector phaseComponentValues; - MassCommon::computePhaseStorage(phaseComponentValues, - volVars, - phaseIdx); - - // copy to the primary variables - for (int compIdx = 0; compIdx < numComponents; ++compIdx) - storage[conti0EqIdx + compIdx] += phaseComponentValues[compIdx]; - } - - /*! - * \brief Calculate the storage for all mass balance equations - * - * \param flux The flux over the SCV (sub-control-volume) face for each component - * \param fluxVars The flux Variables - * \param elemVolVars The volume variables of the current element - */ - static void computeFlux(PrimaryVariables &flux, - const FluxVariables &fluxVars, - const ElementVolumeVariables & elemVolVars) - { - for (int compIdx = 0; compIdx < numComponents; ++compIdx) - flux[conti0EqIdx + compIdx] = 0.0; - - ComponentVector phaseComponentValuesAdvection(0.); - ComponentVector phaseComponentValuesDiffusion(0.); - ComponentVector phaseComponentValuesMassTransport[numPhases]; // what goes into the energy module - - for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { - MassCommon::computeAdvectivePhaseFlux(phaseComponentValuesAdvection, fluxVars, phaseIdx); - Valgrind::CheckDefined(phaseComponentValuesAdvection); - for (int compIdx = 0; compIdx < numComponents; ++compIdx) - flux[conti0EqIdx + compIdx] += - phaseComponentValuesAdvection[compIdx]; - - MassCommon::computeDiffusivePhaseFlux(phaseComponentValuesDiffusion, fluxVars, phaseIdx); - Valgrind::CheckDefined(phaseComponentValuesDiffusion); - for (int compIdx = 0; compIdx < numComponents; ++compIdx){ - flux[conti0EqIdx + compIdx] += - phaseComponentValuesDiffusion[compIdx]; - } - - - - // Right now I think that adding the two contributions individually into the flux is best for debugging and understanding. - // The Energy module needs both contributions. - phaseComponentValuesMassTransport[phaseIdx] = phaseComponentValuesDiffusion + phaseComponentValuesAdvection ; - - Valgrind::CheckDefined(flux); - } -// std::cout<< "KPN Mass: flux: " << flux << endl; - - - // \todo - // - // The computeflux() of the Energy module needs a - // component-wise flux (for the diffusive enthalpy transport) - // It makes some sense calling energy from here, because energy - // is carried by mass. However, it is not really a clean - // solution. - - // energy transport in fluid phases - EnergyResid::computeFlux(flux, - fluxVars, - elemVolVars, - phaseComponentValuesMassTransport); - Valgrind::CheckDefined(flux); - } - - - - /*! - * \brief Calculate the source terms for all mass balance - * equations - * - * \param source The source/sink in the sub-control volume for each component - * \param volVars the volume variables - */ - static void computeSource(PrimaryVariables &source, - const VolumeVariables &volVars) - { -// static_assert(not enableKineticEnergy, // enableKinetic is disabled, in this specialization -// "In the case of kinetic energy transfer the advective energy transport between the phases has to be considered. " -// "It is hard (technically) to say how much mass got transfered in the case of chemical equilibrium. " -// "Therefore, kineticEnergy and no kinetic mass does not fit (yet)."); - - - // mass transfer is not considered in this mass module - for (int compIdx = 0; compIdx < numComponents; ++compIdx) - source[conti0EqIdx + compIdx] = 0.0; - - - PrimaryVariables tmpPriVars(0); - // Similar to the compute Flux, the energy residual needs to be called from the - // mass residual. - ComponentVector dummy[numPhases]; - for (int iDummy =0; iDummy <numPhases; ++iDummy) - dummy[iDummy] = 0.; - EnergyResid::computeSource(tmpPriVars, - volVars, - dummy); - source += tmpPriVars; - Valgrind::CheckDefined(source); - } -}; - -} // end namespace +#include <dumux/porousmediumflow/mpnc/implicit/mass/localresidual.hh> #endif diff --git a/dumux/implicit/mpnc/mass/mpnclocalresidualmasskinetic.hh b/dumux/implicit/mpnc/mass/mpnclocalresidualmasskinetic.hh index 09400252acfad48805f553fc6b383b7d4acdbb17..676747e2432f714b034117f22e21d5ea2c7b8f85 100644 --- a/dumux/implicit/mpnc/mass/mpnclocalresidualmasskinetic.hh +++ b/dumux/implicit/mpnc/mass/mpnclocalresidualmasskinetic.hh @@ -1,288 +1,8 @@ -// -*- 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 The local residual for the kinetic mass transfer module of - * the compositional multi-phase model. - */ -#ifndef DUMUX_MPNC_LOCAL_RESIDUAL_MASS_KINETIC_HH -#define DUMUX_MPNC_LOCAL_RESIDUAL_MASS_KINETIC_HH +#ifndef DUMUX_MPNC_LOCAL_RESIDUAL_MASS_KINETIC_HH_OLD +#define DUMUX_MPNC_LOCAL_RESIDUAL_MASS_KINETIC_HH_OLD -#include <dumux/implicit/mpnc/mass/mpnclocalresidualmass.hh> +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/mass/localresidualkinetic.hh instead -namespace Dumux -{ -/*! - * \brief The mass conservation part of the Mp-Nc model. - * - * This is the specialization for the case where kinetic mass transfer - * *is* considered. - */ -template<class TypeTag> -class MPNCLocalResidualMass<TypeTag, /*enableKinetic=*/true> -{ - typedef MPNCLocalResidualMassCommon<TypeTag> MassCommon; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; - typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; - typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; - - enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; - enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; - enum { conti0EqIdx = Indices::conti0EqIdx }; - enum { nCompIdx = FluidSystem::nCompIdx } ; - enum { wCompIdx = FluidSystem::wCompIdx } ; - enum { wPhaseIdx = FluidSystem::wPhaseIdx} ; - enum { nPhaseIdx = FluidSystem::nPhaseIdx} ; - enum { sPhaseIdx = FluidSystem::sPhaseIdx} ; - enum { numEnergyEquations = GET_PROP_VALUE(TypeTag, NumEnergyEquations) }; - enum { enableEnergy = GET_PROP_VALUE(TypeTag, EnableEnergy) }; - - typedef MPNCLocalResidualEnergy<TypeTag, enableEnergy, numEnergyEquations> EnergyResid; - typedef typename Dune::FieldVector<Scalar, numComponents> ComponentVector; - -public: - - /*! - * \brief Calculate the storage for all mass balance equations - * - * \param storage The mass of the component within the sub-control volume - * \param volVars The volume variables - */ - static void computeStorage(PrimaryVariables & storage, - const VolumeVariables & volVars) - { - for (int phaseIdx =0; phaseIdx < numPhases; ++phaseIdx) - for (int compIdx = 0; compIdx < numComponents; ++compIdx) - storage[conti0EqIdx + phaseIdx*numComponents + compIdx] = 0.0; - - for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { - addPhaseStorage(storage, volVars, phaseIdx); - } - } - - /*! - * \brief Calculate the storage for all mass balance equations - * within a single fluid phase - * - * \param storage The mass of the component within the sub-control volume - * \param volVars The volume variables - * \param phaseIdx phaseIdx The index of the fluid phase - */ - static void addPhaseStorage(PrimaryVariables & storage, - const VolumeVariables & volVars, - const unsigned int phaseIdx) - { - if (phaseIdx == sPhaseIdx) - return; - - // calculate the component-wise mass storage - ComponentVector phaseComponentValues; - MassCommon::computePhaseStorage(phaseComponentValues, - volVars, - phaseIdx); - Valgrind::CheckDefined(phaseComponentValues); - Valgrind::CheckDefined(storage); - - // copy to the primary variables - for (int compIdx = 0; compIdx < numComponents; ++compIdx){ - storage[conti0EqIdx + phaseIdx*numComponents + compIdx] - += phaseComponentValues[compIdx]; - - if (!std::isfinite(storage[conti0EqIdx + phaseIdx*numComponents + compIdx])) - DUNE_THROW(NumericalProblem, "Calculated non-finite storage"); - } - - Valgrind::CheckDefined(storage); - } - - /*! - * \brief Calculate the storage for all mass balance equations - * - * \param flux The flux over the SCV (sub-control-volume) face for each component - * \param fluxVars The flux Variables - * \param elemVolVars The volume variables of the current element - */ - static void computeFlux(PrimaryVariables & flux, - const FluxVariables & fluxVars, - const ElementVolumeVariables & elemVolVars) - { - ComponentVector phaseComponentValuesMassTransport[numPhases]; // what goes into the energy module - - for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { - ComponentVector phaseComponentValuesAdvection(0.); - ComponentVector phaseComponentValuesDiffusion(0.); - MassCommon::computeAdvectivePhaseFlux(phaseComponentValuesAdvection, fluxVars, phaseIdx); - for (int compIdx = 0; compIdx < numComponents; ++compIdx) { - flux[conti0EqIdx + phaseIdx*numComponents + compIdx] = - phaseComponentValuesAdvection[compIdx]; - Valgrind::CheckDefined(flux); - } - MassCommon::computeDiffusivePhaseFlux(phaseComponentValuesDiffusion, fluxVars, phaseIdx); - for (int compIdx = 0; compIdx < numComponents; ++compIdx) { - flux[conti0EqIdx + phaseIdx*numComponents + compIdx] += - phaseComponentValuesDiffusion[compIdx]; - Valgrind::CheckDefined(flux); - - if (!std::isfinite(flux[conti0EqIdx + phaseIdx*numComponents + compIdx])) - DUNE_THROW(NumericalProblem, "Calculated non-finite flux"); - } - - // Right now I think that adding the two contributions individually into the flux is best for debugging and understanding. - // The Energy module needs both contributions. - phaseComponentValuesMassTransport[phaseIdx] = phaseComponentValuesDiffusion + phaseComponentValuesAdvection ; - Valgrind::CheckDefined(flux); - - }// phases - - // The computeflux() of the Energy module needs a component-wise flux (for the diffusive enthalpie transport) - // It makes some sense calling energy from here, because energy is carried by mass - // However, it is not really tidied up. - // todo is there a better way to do this? - EnergyResid::computeFlux(flux, - fluxVars, - elemVolVars, - phaseComponentValuesMassTransport); - Valgrind::CheckDefined(flux); - } - - - /*! - * \brief Calculate the source terms for all mass balance equations - * - * \param source The source/sink in the sub-control volume for each component - * \param volVars the volume variables - */ - static void computeSource(PrimaryVariables & source, - const VolumeVariables & volVars) - { - - // In the case of a kinetic consideration, mass transfer - // between phases is realized via source terms there is a - // balance equation for each component in each phase - ComponentVector componentIntoPhaseMassTransfer[numPhases]; -#define FUNKYMASSTRANSFER 0 -#if FUNKYMASSTRANSFER - const Scalar mu_nPhaseNCompEquil = volVars.chemicalPotentialEquil(nPhaseIdx, nCompIdx) ; // very 2p2c - const Scalar mu_wPhaseWCompEquil = volVars.chemicalPotentialEquil(wPhaseIdx, wCompIdx); // very 2p2c - - const Scalar mu_wPhaseNComp = volVars.chemicalPotential(wPhaseIdx, nCompIdx) ; // very 2p2c - const Scalar mu_nPhaseWComp = volVars.chemicalPotential(nPhaseIdx, wCompIdx); // very 2p2c - - Valgrind::CheckDefined(mu_nPhaseNCompEquil); - Valgrind::CheckDefined(mu_wPhaseWCompEquil); - Valgrind::CheckDefined(mu_wPhaseNComp); - Valgrind::CheckDefined(mu_nPhaseWComp); - - const Scalar characteristicLength = volVars.characteristicLength() ; - const Scalar temperature = volVars.fluidState().temperature(wPhaseIdx); - const Scalar pn = volVars.fluidState().pressure(nPhaseIdx); - const Scalar henry = FluidSystem::henry(temperature) ; - const Scalar gradNinWApprox = ( mu_wPhaseNComp - mu_nPhaseNCompEquil) / characteristicLength; // very 2p2c // 1. / henry * - const Scalar gradWinNApprox = ( mu_nPhaseWComp - mu_wPhaseWCompEquil) / characteristicLength; // very 2p2c // 1. / pn * - -#else // FUNKYMASSTRANSFER - Scalar x[numPhases][numComponents]; // mass fractions in wetting phase - for(int phaseIdx=0; phaseIdx<numPhases; ++phaseIdx){ - for (int compIdx=0; compIdx< numComponents; ++ compIdx){ - x[phaseIdx][compIdx] = volVars.fluidState().moleFraction(phaseIdx, compIdx); - } - } - Valgrind::CheckDefined(x); - -// "equilibrium" values: calculated in volume variables - const Scalar x_wPhaseNCompEquil = volVars.xEquil(wPhaseIdx, nCompIdx) ; // very 2p2c - const Scalar x_nPhaseWCompEquil = volVars.xEquil(nPhaseIdx, wCompIdx); // very 2p2c - Valgrind::CheckDefined(x_wPhaseNCompEquil); - Valgrind::CheckDefined(x_nPhaseWCompEquil); - const Scalar characteristicLength = volVars.characteristicLength() ; - const Scalar gradNinWApprox = (x[wPhaseIdx][nCompIdx] - x_wPhaseNCompEquil) / characteristicLength; // very 2p2c - const Scalar gradWinNApprox = (x[nPhaseIdx][wCompIdx] - x_nPhaseWCompEquil) / characteristicLength; // very 2p2c -#endif - Scalar phaseDensity[numPhases]; - for(int phaseIdx=0; phaseIdx<numPhases; ++phaseIdx){ - phaseDensity[phaseIdx] = volVars.fluidState().molarDensity(phaseIdx); - } - - // diffusion coefficients in wetting phase - const Scalar diffCoeffNinW = volVars.diffCoeff(wPhaseIdx, wCompIdx, nCompIdx) ; - Valgrind::CheckDefined(diffCoeffNinW); - // diffusion coefficients in non-wetting phase - const Scalar diffCoeffWinN = volVars.diffCoeff(nPhaseIdx, wCompIdx, nCompIdx) ; - Valgrind::CheckDefined(diffCoeffWinN); - - const Scalar factorMassTransfer = volVars.factorMassTransfer() ; - const Scalar awn = volVars.interfacialArea(wPhaseIdx, nPhaseIdx); - - const Scalar sherwoodWPhase = volVars.sherwoodNumber(wPhaseIdx); - const Scalar sherwoodNPhase = volVars.sherwoodNumber(nPhaseIdx); - - // actual diffusion is always calculated for eq's 2,3 - // Eq's 1,4 have to be the same with different sign, because no mass is accumulated in the interface - // i.e. automatically conserving mass that mvoes across the interface - - const Scalar nCompIntoWPhase = - factorMassTransfer * gradNinWApprox * awn * phaseDensity[wPhaseIdx] * diffCoeffNinW * sherwoodWPhase; - const Scalar nCompIntoNPhase = - nCompIntoWPhase ; - const Scalar wCompIntoNPhase = - factorMassTransfer * gradWinNApprox * awn * phaseDensity[nPhaseIdx] * diffCoeffWinN * sherwoodNPhase; - const Scalar wCompIntoWPhase = - wCompIntoNPhase ; - - componentIntoPhaseMassTransfer[wPhaseIdx][nCompIdx] = nCompIntoWPhase; - componentIntoPhaseMassTransfer[nPhaseIdx][nCompIdx] = nCompIntoNPhase; - componentIntoPhaseMassTransfer[nPhaseIdx][wCompIdx] = wCompIntoNPhase; - componentIntoPhaseMassTransfer[wPhaseIdx][wCompIdx] = wCompIntoWPhase; - -#if MASS_TRANSFER_OFF -#warning MASS TRANSFER OFF - for(int phaseIdx=0; phaseIdx<numPhases; ++phaseIdx){ - for (int compIdx=0; compIdx< numComponents; ++ compIdx){ - componentIntoPhaseMassTransfer[phaseIdx][compIdx] = 0.; - } - } -#endif - - Valgrind::CheckDefined(componentIntoPhaseMassTransfer); - - // Call the (kinetic) Energy module, for the source term. - // it has to be called from here, because the mass transfered has to be known. - EnergyResid::computeSource(source, - volVars, - componentIntoPhaseMassTransfer); - - // Actually add the mass transfer to the sources which might - // exist externally - for (int phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) { - for (int compIdx = 0; compIdx < numComponents; ++ compIdx) { - const unsigned int eqIdx = conti0EqIdx + compIdx + phaseIdx*numComponents; - source[eqIdx] += componentIntoPhaseMassTransfer[phaseIdx][compIdx] ; - - if (!std::isfinite(source[eqIdx])) - DUNE_THROW(NumericalProblem, "Calculated non-finite source"); - } - } - Valgrind::CheckDefined(source); - } -}; - -} // end namespace Dumux +#include <dumux/porousmediumflow/mpnc/implicit/mass/localresidualkinetic.hh> #endif diff --git a/dumux/implicit/mpnc/mass/mpncvolumevariablesmass.hh b/dumux/implicit/mpnc/mass/mpncvolumevariablesmass.hh index 0a0a6b5d70b36fc5fc6510e862d41478e7f3edad..f9e753159b9ff06ccb49d1e9528c5e5d3a830065 100644 --- a/dumux/implicit/mpnc/mass/mpncvolumevariablesmass.hh +++ b/dumux/implicit/mpnc/mass/mpncvolumevariablesmass.hh @@ -1,130 +1,8 @@ -// -*- 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 Contains the mass conservation part of the volume variables. - */ -#ifndef DUMUX_MPNC_VOLUME_VARIABLES_MASS_HH -#define DUMUX_MPNC_VOLUME_VARIABLES_MASS_HH +#ifndef DUMUX_MPNC_VOLUME_VARIABLES_MASS_HH_OLD +#define DUMUX_MPNC_VOLUME_VARIABLES_MASS_HH_OLD -#include <dumux/implicit/mpnc/mpncproperties.hh> +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/mass/volumevariables.hh instead -#include <dumux/material/fluidstates/compositionalfluidstate.hh> - -namespace Dumux -{ -/*! - * \brief The compositional part of the volume variables if chemical - * equilibrium _is_ assumed. - */ -template <class TypeTag, bool enableKinetic /* = false */> -class MPNCVolumeVariablesMass -{ - static_assert(!enableKinetic, - "No kinetic mass transfer module included, " - "but kinetic mass transfer enabled."); - - typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; - typedef typename FluidSystem::ParameterCache ParameterCache; - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GET_PROP_TYPE(TypeTag, ConstraintSolver) ConstraintSolver; - typedef typename GridView::template Codim<0>::Entity Element; - - enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; - enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; - enum { fug0Idx = Indices::fug0Idx }; - enum { dimWorld = GridView::dimensionworld}; - typedef Dune::FieldVector<typename GridView::Grid::ctype, dimWorld> GlobalPosition; - - typedef Dune::FieldVector<Scalar, numComponents> ComponentVector; - -public: - /*! - * \brief Update composition of all phases in the mutable - * parameters from the primary variables. - * - * \param fs Container for all the secondary variables concerning the fluids - * \param paramCache Container for cache parameters - * \param priVars The primary Variables - * \param *hint the volume variables, usable for initial guess of composition - * \param problem The problem - * \param element The finite element - * \param fvGeometry The finite-volume geometry in the fully implicit scheme - * \param scvIdx The index of the sub-control volume - */ - void update(FluidState &fs, - ParameterCache ¶mCache, - const PrimaryVariables &priVars, - const VolumeVariables *hint, - const Problem &problem, - const Element &element, - const FVElementGeometry &fvGeometry, - const unsigned int scvIdx) - { - ComponentVector fug; - // retrieve component fugacities - for (int compIdx = 0; compIdx < numComponents; ++compIdx) - fug[compIdx] = priVars[fug0Idx + compIdx]; - - // calculate phase compositions - for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { - // initial guess - for (int compIdx = 0; compIdx < numComponents; ++compIdx) { - Scalar x_ij = 1.0/numComponents; - if (hint) - // use the hint for the initial mole fraction! - x_ij = hint->fluidState().moleFraction(phaseIdx, compIdx); - - // set initial guess of the component's mole fraction - fs.setMoleFraction(phaseIdx, - compIdx, - x_ij); - - } - - // calculate the phase composition from the component - // fugacities - if (!hint) - // if no hint was given, we ask the constraint solver - // to make an initial guess - ConstraintSolver::guessInitial(fs, paramCache, phaseIdx, fug); - ConstraintSolver::solve(fs, paramCache, phaseIdx, fug); - } - } - - /*! - * \brief If running in valgrind this makes sure that all - * quantities in the volume variables are defined. - */ - void checkDefined() const - { - } -}; - -} // end namespace +#include <dumux/porousmediumflow/mpnc/implicit/mass/volumevariables.hh> #endif diff --git a/dumux/implicit/mpnc/mass/mpncvolumevariablesmasskinetic.hh b/dumux/implicit/mpnc/mass/mpncvolumevariablesmasskinetic.hh index 4e96c264764e70f435b3676894fcc1e3e1441d0b..de049882964b5e4004d16f1af911014bd34ce48d 100644 --- a/dumux/implicit/mpnc/mass/mpncvolumevariablesmasskinetic.hh +++ b/dumux/implicit/mpnc/mass/mpncvolumevariablesmasskinetic.hh @@ -1,175 +1,8 @@ -// -*- 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 Contains the mass conservation part of the volume variables - */ -#ifndef DUMUX_MPNC_VOLUME_VARIABLES_MASS_KINETIC_HH -#define DUMUX_MPNC_VOLUME_VARIABLES_MASS_KINETIC_HH +#ifndef DUMUX_MPNC_VOLUME_VARIABLES_MASS_KINETIC_HH_OLD +#define DUMUX_MPNC_VOLUME_VARIABLES_MASS_KINETIC_HH_OLD -#include <dumux/material/fluidstates/nonequilibriumfluidstate.hh> -#include <dumux/implicit/mpnc/mass/mpncvolumevariablesmass.hh> -#include <dumux/material/constraintsolvers/fluidsystemcomputefromreferencephase.hh> -#include <dumux/material/constraintsolvers/fluidsystemconstraintsolver.hh> -#include <dumux/material/constraintsolvers/misciblemultiphasecomposition.hh> +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/mass/volumevariableskinetic.hh instead - -namespace Dumux -{ -/*! - * \brief The compositional part of the volume variables if chemical - * equilibrium is _not_ assumed - * - * The interface for basing mass transfer on chemical potentials was present in revision 12743 - */ -template <class TypeTag> -class MPNCVolumeVariablesMass<TypeTag, /*bool enableKinetic=*/true> -{ - typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; - - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; - typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; - typedef typename FluidSystem::ParameterCache ParameterCache; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GridView::template Codim<0>::Entity Element; - - enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; - enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; - enum { moleFrac00Idx = Indices::moleFrac00Idx }; - - typedef typename Dune::FieldVector<Scalar, numComponents> ComponentVector; - - // here, we need a constraint solver, which gives me the composition of a phase, if the other one is given - typedef FluidSystemComputeFromReferencePhase<Scalar, FluidSystem> ConstraintReferencePhaseSolver; - - // here, we need a constraint solver, which gives me the composition of all phases if p,T is given - typedef FluidSystemConstraintSolver<Scalar, FluidSystem> ConstraintSolver; - - // this is the constraint solver that applies "fugacities" -// typedef MiscibleMultiPhaseComposition<Scalar, FluidSystem> ConstraintSolver; -public: - - /*! - * \brief Update composition of all phases in the mutable - * parameters from the primary variables. - * - * \param actualFluidState Container for all the secondary variables concerning the fluids - * \param paramCache Container for cache parameters - * \param priVars The primary Variables - * \param *hint the volume variables, usable for initial guess of composition - * \param problem The problem - * \param element The finite element - * \param fvGeometry The finite-volume geometry in the fully implicit scheme - * \param scvIdx The index of the sub-control volume - */ - void update(FluidState & actualFluidState, - ParameterCache & paramCache, - const PrimaryVariables & priVars, - const VolumeVariables * hint, - const Problem & problem, - const Element & element, - const FVElementGeometry & fvGeometry, - const unsigned int scvIdx) - { - // setting the mole fractions of the fluid state - for(int smallLoopPhaseIdx=0; smallLoopPhaseIdx<numPhases; ++smallLoopPhaseIdx){ - // set the component mole fractions - for (int compIdx = 0; compIdx < numComponents; ++compIdx) { - actualFluidState.setMoleFraction(smallLoopPhaseIdx, - compIdx, - priVars[moleFrac00Idx + - smallLoopPhaseIdx*numComponents + - compIdx]); - } - } - -// // For using the ... other way of calculating equilibrium -// THIS IS ONLY FOR silencing Valgrind but is not used in this model - for(int smallLoopPhaseIdx=0; smallLoopPhaseIdx<numPhases; ++smallLoopPhaseIdx) - for (int compIdx = 0; compIdx < numComponents; ++compIdx) { - const Scalar phi = FluidSystem::fugacityCoefficient(actualFluidState, - paramCache, - smallLoopPhaseIdx, - compIdx); - actualFluidState.setFugacityCoefficient(smallLoopPhaseIdx, - compIdx, - phi); - } - - FluidState equilFluidState; // the fluidState *on the interface* i.e. chemical equilibrium - equilFluidState.assign(actualFluidState) ; - ConstraintSolver::solve(equilFluidState, - paramCache, - /*setViscosity=*/false, - /*setEnthalpy=*/false) ; - - // Setting the equilibrium composition (in a kinetic model not necessarily the same as the actual mole fraction) - for(int smallLoopPhaseIdx=0; smallLoopPhaseIdx<numPhases; ++smallLoopPhaseIdx){ - for (int compIdx=0; compIdx< numComponents; ++ compIdx){ - xEquil_[smallLoopPhaseIdx][compIdx] = equilFluidState.moleFraction(smallLoopPhaseIdx, compIdx); - } - } - - // compute densities of all phases - for(int smallLoopPhaseIdx=0; smallLoopPhaseIdx<numPhases; ++smallLoopPhaseIdx){ - const Scalar rho = FluidSystem::density(actualFluidState, paramCache, smallLoopPhaseIdx); - actualFluidState.setDensity(smallLoopPhaseIdx, rho); - } - - // let Valgrind check whether everything is properly defined. - checkDefined(); - } - - /*! - * \brief The mole fraction we would have in the case of chemical equilibrium / - * on the interface. - * - * \param phaseIdx The index of the fluid phase - * \param compIdx The local index of the component - */ - const Scalar xEquil(const unsigned int phaseIdx, const unsigned int compIdx) const - { - return xEquil_[phaseIdx][compIdx] ; - } - - - /*! - * \brief If running in valgrind this makes sure that all - * quantities in the volume variables are defined. - */ - void checkDefined() const - { -#if HAVE_VALGRIND && !defined NDEBUG - Valgrind::CheckDefined(xEquil_); -#endif - } - -private: - Scalar xEquil_[numPhases][numComponents]; -}; - -} // end namespace +#include <dumux/porousmediumflow/mpnc/implicit/mass/volumevariableskinetic.hh> #endif diff --git a/dumux/implicit/mpnc/mass/mpncvtkwritermass.hh b/dumux/implicit/mpnc/mass/mpncvtkwritermass.hh index 123144d2ec1909be9bc70f2bda47d759fb93853e..18dc705e95b4b18e83b7acbb734a55059e9356e4 100644 --- a/dumux/implicit/mpnc/mass/mpncvtkwritermass.hh +++ b/dumux/implicit/mpnc/mass/mpncvtkwritermass.hh @@ -1,124 +1,8 @@ -// -*- 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 VTK writer module for the mass related quantities of the - * MpNc model. - */ -#ifndef DUMUX_MPNC_VTK_WRITER_MASS_HH -#define DUMUX_MPNC_VTK_WRITER_MASS_HH +#ifndef DUMUX_MPNC_VTK_WRITER_MASS_HH_OLD +#define DUMUX_MPNC_VTK_WRITER_MASS_HH_OLD -#include "../mpncvtkwritermodule.hh" +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/mass/vtkwriter.hh instead -namespace Dumux -{ -/*! - * \ingroup MPNCModel - * - * \brief VTK writer module for the mass related quantities of the - * MpNc model. - * - * This is the specialization for the case _without_ kinetic mass - * transfer between phases. - */ -template<class TypeTag, bool enableKinetic /* = false */> -class MPNCVtkWriterMass : public MPNCVtkWriterModule<TypeTag> -{ - static_assert(!enableKinetic, - "No kinetic mass transfer module included, " - "but kinetic mass transfer enabled."); - - typedef MPNCVtkWriterModule<TypeTag> ParentType; - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes; - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GridView::template Codim<0>::Entity Element; - - enum { dim = GridView::dimension }; - enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; - enum { isBox = GET_PROP_VALUE(TypeTag, ImplicitIsBox) }; - enum { dofCodim = isBox ? dim : 0 }; - - typedef typename ParentType::ComponentVector ComponentVector; - bool fugacityOutput_; - -public: - MPNCVtkWriterMass(const Problem &problem) - : ParentType(problem) - { - fugacityOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddFugacities); - } - - /*! - * \brief Allocate memory for the scalar fields we would like to - * write to the VTK file. - */ - template <class MultiWriter> - void allocBuffers(MultiWriter &writer) - { - if (fugacityOutput_) this->resizeComponentBuffer_(fugacity_, isBox); - } - - /*! - * \brief Modify the internal buffers according to the volume - * variables seen on an element - * - * \param element The finite element - * \param fvGeometry The finite-volume geometry in the fully implicit scheme - * \param elemVolVars The volume variables of the current element - * \param elemBcTypes The types of the boundary conditions for all vertices of the element - */ - void processElement(const Element &element, - const FVElementGeometry &fvGeometry, - const ElementVolumeVariables &elemVolVars, - const ElementBoundaryTypes &elemBcTypes) - { - for (int scvIdx = 0; scvIdx < fvGeometry.numScv; ++scvIdx) { - const unsigned int dofIdxGlobal = this->problem_.model().dofMapper().subIndex(element, scvIdx, dofCodim); - const VolumeVariables &volVars = elemVolVars[scvIdx]; - - if (fugacityOutput_) { - for (int compIdx = 0; compIdx < numComponents; ++compIdx) { - fugacity_[compIdx][dofIdxGlobal] = volVars.fluidState().fugacity(compIdx); - } - } - } - } - - /*! - * \brief Add all buffers to the VTK output writer. - */ - template <class MultiWriter> - void commitBuffers(MultiWriter &writer) - { - if (fugacityOutput_) - this->commitComponentBuffer_(writer, "f_%s", fugacity_, isBox); - } - -private: - ComponentVector fugacity_; -}; - -} +#include <dumux/porousmediumflow/mpnc/implicit/mass/vtkwriter.hh> #endif diff --git a/dumux/implicit/mpnc/mass/mpncvtkwritermasskinetic.hh b/dumux/implicit/mpnc/mass/mpncvtkwritermasskinetic.hh index cbf589a93fce95416e68bd4a7a81c27e480d7647..11ff13c378d682beb1bc0049bbce2a19fe7ff99f 100644 --- a/dumux/implicit/mpnc/mass/mpncvtkwritermasskinetic.hh +++ b/dumux/implicit/mpnc/mass/mpncvtkwritermasskinetic.hh @@ -1,164 +1,8 @@ -// -*- 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 VTK writer module for the mass related quantities of the - * MpNc model (kinetic mass transfer case). - */ -#ifndef DUMUX_MPNC_VTK_WRITER_MASS_KINETIC_HH -#define DUMUX_MPNC_VTK_WRITER_MASS_KINETIC_HH +#ifndef DUMUX_MPNC_VTK_WRITER_MASS_KINETIC_HH_OLD +#define DUMUX_MPNC_VTK_WRITER_MASS_KINETIC_HH_OLD -#include <dumux/implicit/mpnc/mpncvtkwritermodule.hh> -#include <dumux/implicit/mpnc/mpncpropertieskinetic.hh> -#include <dumux/implicit/mpnc/mass/mpncvtkwritermass.hh> +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/mass/vtkwriterkinetic.hh instead - -namespace Dumux -{ - -/*! - * \ingroup MPNCModel - * - * \brief VTK writer module for the mass related quantities of the - * MpNc model. - * - * This is the specialization for the case with kinetic mass transfer. - */ -template<class TypeTag> -class MPNCVtkWriterMass<TypeTag, /* enableKinetic = */ true> - : public MPNCVtkWriterModule<TypeTag> -{ - typedef MPNCVtkWriterModule<TypeTag> ParentType; - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes; - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - - enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; - enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; - enum { dim = GridView::dimension }; - enum { nPhaseIdx = FluidSystem::nPhaseIdx}; - enum { isBox = GET_PROP_VALUE(TypeTag, ImplicitIsBox) }; - enum { dofCodim = isBox ? dim : 0 }; - - enum { xEquilOutput = GET_PROP_VALUE(TypeTag, VtkAddxEquil) }; - - typedef typename GridView::template Codim<0>::Entity Element; - typedef typename ParentType::ScalarVector ScalarVector; - typedef typename ParentType::PhaseVector PhaseVector; - typedef typename ParentType::ComponentVector ComponentVector; - typedef typename ParentType::PhaseComponentMatrix PhaseComponentMatrix; - - bool deltaPOutput_; -public: - MPNCVtkWriterMass(const Problem &problem) - : ParentType(problem) - { - deltaPOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddDeltaP); - } - - /*! - * \brief Allocate memory for the scalar fields we would like to - * write to the VTK file. - */ - template <class MultiWriter> - void allocBuffers(MultiWriter &writer) - { -// this->resizePhaseComponentBuffer_(drivingThingyMu_); -// this->resizePhaseComponentBuffer_(drivingThingyMole_); - this->resizePhaseComponentBuffer_(moleFracEquil_); - -// this->resizePhaseComponentBuffer_(percentageEquilMoleFrac_); - if (deltaPOutput_) this->resizeScalarBuffer_(deltaP_, isBox); - - } - - /*! - * \brief Modify the internal buffers according to the volume - * variables seen on an element - * - * \param element The finite element - * \param fvGeometry The finite-volume geometry in the fully implicit scheme - * \param elemVolVars The volume variables of the current element - * \param elemBcTypes The types of the boundary conditions for all vertices of the element - */ - void processElement(const Element &element, - const FVElementGeometry &fvGeometry, - const ElementVolumeVariables &elemVolVars, - const ElementBoundaryTypes &elemBcTypes) - { - int numLocalVertices = element.geometry().corners(); - for (int localVertexIdx = 0; localVertexIdx< numLocalVertices; ++localVertexIdx) { - const unsigned int vIdxGlobal = this->problem_.vertexMapper().subIndex(element, localVertexIdx, dim); - const VolumeVariables &volVars = elemVolVars[localVertexIdx]; - - for (unsigned int phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) { - for (unsigned int compIdx = 0; compIdx < numComponents; ++ compIdx) { - moleFracEquil_[phaseIdx][compIdx][vIdxGlobal] = volVars.xEquil(phaseIdx, compIdx); - } - } - -// for (unsigned int phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) { -// for (unsigned int compIdx = 0; compIdx < numComponents; ++ compIdx) { -// drivingThingyMole_[phaseIdx][compIdx][vIdxGlobal] = volVars.xEquil(phaseIdx, compIdx) - volVars.fluidState().moleFraction(phaseIdx, compIdx); -// drivingThingyMu_[phaseIdx][compIdx][vIdxGlobal] = volVars.chemicalPotentialEquil(phaseIdx, compIdx) - volVars.chemicalPotential(phaseIdx, compIdx); -//// percentageEquilMoleFrac_[phaseIdx][compIdx][vIdxGlobal] = (volVars.fluidState().moleFraction(phaseIdx, compIdx)) / volVars.xEquil(phaseIdx, compIdx); -// } -// } - - if (deltaPOutput_) { - deltaP_[vIdxGlobal] = volVars.fluidState().pressure(nPhaseIdx) - 100000.; - } - } - } - - /*! - * \brief Add all buffers to the VTK output writer. - */ - template <class MultiWriter> - void commitBuffers(MultiWriter &writer) - { -// this->commitPhaseComponentBuffer_(writer, "dirivingThingyMole_%s^%s", drivingThingyMole_); -// this->commitPhaseComponentBuffer_(writer, "dirivingThingyMu_%s^%s", drivingThingyMu_); -// this->commitPhaseComponentBuffer_(writer, "percentageEquilMoleFrac_%s^%s", percentageEquilMoleFrac_); - - if(xEquilOutput){ - this->commitPhaseComponentBuffer_(writer, "xEquil_%s^%s", moleFracEquil_); - } - if (deltaPOutput_) - this->commitScalarBuffer_(writer, "pnMinus1e5", deltaP_, isBox); - } - -private: - PhaseComponentMatrix moleFracEquil_; -// PhaseComponentMatrix drivingThingyMole_; -// PhaseComponentMatrix drivingThingyMu_; -// PhaseComponentMatrix percentageEquilMoleFrac_; - - - ScalarVector deltaP_; -}; - -} +#include <dumux/porousmediumflow/mpnc/implicit/mass/vtkwriterkinetic.hh> #endif diff --git a/dumux/implicit/mpnc/mpncfluxvariables.hh b/dumux/implicit/mpnc/mpncfluxvariables.hh index f1bad27e4d847086be4ae367cb4f2eae9caa51ae..61bae9e7b90acddc870ff8ecae06c9feb1be6d02 100644 --- a/dumux/implicit/mpnc/mpncfluxvariables.hh +++ b/dumux/implicit/mpnc/mpncfluxvariables.hh @@ -1,171 +1,8 @@ -// -*- 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 - * all fluxes of components over a face of a finite volume. - * - * This means pressure, concentration and temperature gradients, phase - * densities at the integration point, etc. - */ -#ifndef DUMUX_MPNC_FLUX_VARIABLES_HH -#define DUMUX_MPNC_FLUX_VARIABLES_HH +#ifndef DUMUX_MPNC_FLUX_VARIABLES_HH_OLD +#define DUMUX_MPNC_FLUX_VARIABLES_HH_OLD -#include <dumux/common/spline.hh> +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/fluxvariables.hh instead -#include "diffusion/fluxvariables.hh" -#include "energy/mpncfluxvariablesenergy.hh" -#include <dumux/porousmediumflow/implicit/darcyfluxvariables.hh> -#include <dumux/porousmediumflow/implicit/forchheimerfluxvariables.hh> - -namespace Dumux -{ - -/*! - * \ingroup MPNCModel - * \ingroup ImplicitFluxVariables - * \brief This class contains the data which is required to - * calculate all fluxes of components over a face of a finite - * volume for the MpNc model. - * - * This means pressure and concentration gradients, phase densities at - * the intergration point, etc. - */ -template <class TypeTag> -class MPNCFluxVariables - : public GET_PROP_TYPE(TypeTag, BaseFluxVariables) -{ - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GridView::template Codim<0>::Entity Element; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; - - typedef typename GET_PROP_TYPE(TypeTag, BaseFluxVariables) BaseFluxVariables; - - enum {dim= GridView::dimension}; - enum {dimWorld= GridView::dimensionworld}; - enum {enableDiffusion = GET_PROP_VALUE(TypeTag, EnableDiffusion)}; - enum {enableEnergy = GET_PROP_VALUE(TypeTag, EnableEnergy)}; - enum {enableKinetic = GET_PROP_VALUE(TypeTag, EnableKinetic)}; - enum {numEnergyEquations = GET_PROP_VALUE(TypeTag, NumEnergyEquations)}; - - typedef Dune::FieldVector<Scalar, dim> DimVector; - typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef MPNCFluxVariablesDiffusion<TypeTag, enableDiffusion> FluxVariablesDiffusion; - typedef MPNCFluxVariablesEnergy<TypeTag, enableEnergy, numEnergyEquations> FluxVariablesEnergy; - -public: - /* - * \brief The constructor - * - * \param problem The problem - * \param element The finite element - * \param fvGeometry The finite-volume geometry in the fully implicit scheme - * \param fIdx The local index of the SCV (sub-control-volume) face - * \param elemVolVars The volume variables of the current element - * \param onBoundary A boolean variable to specify whether the flux variables - * are calculated for interior SCV faces or boundary faces, default=false - */ - MPNCFluxVariables(const Problem &problem, - const Element &element, - const FVElementGeometry &fvGeometry, - const unsigned int fIdx, - const ElementVolumeVariables &elemVolVars, - const bool onBoundary = false) - : BaseFluxVariables(problem, element, fvGeometry, fIdx, elemVolVars, onBoundary), - fvGeometry_(fvGeometry), faceIdx_(fIdx), elemVolVars_(elemVolVars), onBoundary_(onBoundary) - { - // velocities can be obtained from the Parent class. - - // update the flux data of the energy module (i.e. isothermal - // or non-isothermal) - fluxVarsEnergy_.update(problem, element, fvGeometry, this->face(), *this, elemVolVars); - - // update the flux data of the diffusion module (i.e. with or - // without diffusion) - fluxVarsDiffusion_.update(problem, element, fvGeometry, this->face(), elemVolVars); - - extrusionFactor_ = - (elemVolVars[this->face().i].extrusionFactor() - + elemVolVars[this->face().j].extrusionFactor()) / 2; - } - - /*! - * \brief Returns a reference to the volume - * variables of the i-th sub-control volume of the current - * element. - */ - const VolumeVariables &volVars(const unsigned int idx) const - { return elemVolVars_[idx]; } - - /*! - * \brief Returns th extrusion factor for the sub-control volume face - */ - Scalar extrusionFactor() const - { return extrusionFactor_; } - - //////////////////////////////////////////////// - // forward calls to the diffusion module - Scalar porousDiffCoeffL(const unsigned int compIdx) const - { return fluxVarsDiffusion_.porousDiffCoeffL(compIdx); } - - Scalar porousDiffCoeffG(const unsigned int compIIdx, - const unsigned int compJIdx) const - { return fluxVarsDiffusion_.porousDiffCoeffG(compIIdx, compJIdx); } - - const Scalar moleFraction(const unsigned int phaseIdx, - const unsigned int compIdx) const - { return fluxVarsDiffusion_.moleFraction(phaseIdx, compIdx); } - - const GlobalPosition &moleFractionGrad(const unsigned int phaseIdx, - const unsigned int compIdx) const - { return fluxVarsDiffusion_.moleFractionGrad(phaseIdx, compIdx); } - - // end of forward calls to the diffusion module - //////////////////////////////////////////////// - - //////////////////////////////////////////////// - // forward calls to the temperature module - const GlobalPosition &temperatureGrad() const - { return fluxVarsEnergy_.temperatureGrad(); } - - const FluxVariablesEnergy &fluxVarsEnergy() const - { return fluxVarsEnergy_; } - // end of forward calls to the temperature module - //////////////////////////////////////////////// - -private: - const FVElementGeometry &fvGeometry_; - const unsigned int faceIdx_; - const ElementVolumeVariables &elemVolVars_; - const bool onBoundary_; - - // The extrusion factor for the sub-control volume face - Scalar extrusionFactor_; - - FluxVariablesDiffusion fluxVarsDiffusion_; - FluxVariablesEnergy fluxVarsEnergy_; -}; - -} // end namespace +#include <dumux/porousmediumflow/mpnc/implicit/fluxvariables.hh> #endif diff --git a/dumux/implicit/mpnc/mpncindices.hh b/dumux/implicit/mpnc/mpncindices.hh index 2320a0481b6ea3272cc7be30ea8d97775a6ca333..e270d66b67c76a0b9467d72df970cc8d5bb3bc00 100644 --- a/dumux/implicit/mpnc/mpncindices.hh +++ b/dumux/implicit/mpnc/mpncindices.hh @@ -1,120 +1,8 @@ -// -*- 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 The primary variable and equation indices for the MpNc model. - */ -#ifndef DUMUX_MPNC_INDICES_HH -#define DUMUX_MPNC_INDICES_HH +#ifndef DUMUX_MPNC_INDICES_HH_OLD +#define DUMUX_MPNC_INDICES_HH_OLD -#include "mpncproperties.hh" +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/indices.hh instead -#include "mass/mpncindicesmass.hh" -#include "energy/mpncindicesenergy.hh" - -namespace Dumux -{ - -/*! - * \ingroup MPNCModel - * \ingroup ImplicitIndices - * \brief Enumerates the formulations which the MpNc model accepts. - */ -struct MpNcPressureFormulation -{ - enum { - mostWettingFirst, - leastWettingFirst - }; -}; - -/*! - * \ingroup MPNCModel - * \ingroup ImplicitIndices - * \brief The primary variable and equation indices for the MpNc model. - */ -template <class TypeTag, int BasePVOffset = 0> -struct MPNCIndices : - public MPNCMassIndices<BasePVOffset, - TypeTag, - GET_PROP_VALUE(TypeTag, EnableKinetic) >, - public MPNCEnergyIndices<BasePVOffset + - MPNCMassIndices<0, TypeTag, GET_PROP_VALUE(TypeTag, EnableKinetic) >::numPrimaryVars, - GET_PROP_VALUE(TypeTag, EnableEnergy), - GET_PROP_VALUE(TypeTag, NumEnergyEquations)> -{ -private: - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - enum { enableEnergy = GET_PROP_VALUE(TypeTag, EnableEnergy) }; - enum { enableKinetic = GET_PROP_VALUE(TypeTag, EnableKinetic) }; //mass transfer - enum { numEnergyEquations = GET_PROP_VALUE(TypeTag, NumEnergyEquations) }; // energy transfer - enum { numPhases = FluidSystem::numPhases }; - - typedef MPNCMassIndices<BasePVOffset, TypeTag, enableKinetic> MassIndices; - typedef MPNCEnergyIndices<BasePVOffset + MassIndices::numPrimaryVars, enableEnergy, numEnergyEquations> EnergyIndices; - -public: - /*! - * \brief The number of primary variables / equations. - */ - // temperature + Mass Balance + constraints for switch stuff - static const unsigned int numPrimaryVars = - MassIndices::numPrimaryVars + - EnergyIndices::numPrimaryVars + - numPhases; - - /*! - * \brief The number of primary variables / equations of the energy module. - */ - static const unsigned int numPrimaryEnergyVars = - EnergyIndices::numPrimaryVars ; - - /*! - * \brief Index of the saturation of the first phase in a vector - * of primary variables. - * - * The following (numPhases - 1) primary variables represent the - * saturations for the phases [1, ..., numPhases - 1] - */ - static const unsigned int s0Idx = - MassIndices::numPrimaryVars + - EnergyIndices::numPrimaryVars; - - /*! - * \brief Index of the first phase' pressure in a vector of - * primary variables. - */ - static const unsigned int p0Idx = - MassIndices::numPrimaryVars + - EnergyIndices::numPrimaryVars + - numPhases - 1; - - /*! - * \brief Index of the first phase NCP equation. - * - * The index for the remaining phases are consecutive. - */ - static const unsigned int phase0NcpIdx = - MassIndices::numPrimaryVars + - EnergyIndices::numPrimaryVars; -}; - -} +#include <dumux/porousmediumflow/mpnc/implicit/indices.hh> #endif diff --git a/dumux/implicit/mpnc/mpnclocalresidual.hh b/dumux/implicit/mpnc/mpnclocalresidual.hh index 0fe400c541559badc5be0d08d98431468fd0d414..819b0f3121201b5ae1941a835faf65152a2e6692 100644 --- a/dumux/implicit/mpnc/mpnclocalresidual.hh +++ b/dumux/implicit/mpnc/mpnclocalresidual.hh @@ -1,313 +1,8 @@ -// -*- 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 MpNc specific details needed to approximately calculate the local - * defect in the fully implicit scheme. - * - */ -#ifndef DUMUX_MPNC_LOCAL_RESIDUAL_HH -#define DUMUX_MPNC_LOCAL_RESIDUAL_HH +#ifndef DUMUX_MPNC_LOCAL_RESIDUAL_HH_OLD +#define DUMUX_MPNC_LOCAL_RESIDUAL_HH_OLD -#include "mpncfluxvariables.hh" -#include "diffusion/diffusion.hh" -#include "energy/mpnclocalresidualenergy.hh" -#include "mass/mpnclocalresidualmass.hh" -#include "mpncproperties.hh" +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/localresidual.hh instead -namespace Dumux -{ -/*! - * \ingroup MPNCModel - * \ingroup ImplicitLocalResidual - * \brief MpNc specific details needed to approximately calculate the local - * defect in the fully implicit scheme. - * - * This class is used to fill the gaps in ImplicitLocalResidual for the - * MpNc flow. - */ -template<class TypeTag> -class MPNCLocalResidual : public GET_PROP_TYPE(TypeTag, BaseLocalResidual) -{ - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; - -protected: - typedef typename GET_PROP_TYPE(TypeTag, LocalResidual) Implementation; - typedef typename GET_PROP_TYPE(TypeTag, BaseLocalResidual) ParentType; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - - enum {numPhases = GET_PROP_VALUE(TypeTag, NumPhases)}; - enum {numComponents = GET_PROP_VALUE(TypeTag, NumComponents)}; - enum {numEq = GET_PROP_VALUE(TypeTag, NumEq)}; - enum {enableEnergy = GET_PROP_VALUE(TypeTag, EnableEnergy)}; - enum {numEnergyEquations = GET_PROP_VALUE(TypeTag, NumEnergyEquations)}; - enum {enableKinetic = GET_PROP_VALUE(TypeTag, EnableKinetic)}; - enum {phase0NcpIdx = Indices::phase0NcpIdx}; - - typedef typename GridView::template Codim<0>::Entity Element; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes; - typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes; - - typedef MPNCLocalResidualEnergy<TypeTag, enableEnergy, numEnergyEquations> EnergyResid; - typedef MPNCLocalResidualMass<TypeTag, enableKinetic> MassResid; - -public: - /*! - * \brief Evaluate the amount all conservation quantites - * (e.g. phase mass) within a sub-control volume. - * - * The result should be averaged over the volume (e.g. phase mass - * inside a sub control volume divided by the volume) - * - * \param storage The mass of the component within the sub-control volume - * \param usePrevSol Evaluate function with solution of current or previous time step - * \param scvIdx The SCV (sub-control-volume) index - * - */ - void computeStorage(PrimaryVariables &storage, - const unsigned int scvIdx, - const bool usePrevSol) const - { - // if flag usePrevSol is set, the solution from the previous - // time step is used, otherwise the current solution is - // used. The secondary variables are used accordingly. This - // is required to compute the derivative of the storage term - // using the implicit euler method. - const ElementVolumeVariables &elemVolVars = usePrevSol ? this->prevVolVars_() : this->curVolVars_(); - const VolumeVariables &volVars = elemVolVars[scvIdx]; - - storage =0; - - // compute mass and energy storage terms - MassResid::computeStorage(storage, volVars); - Valgrind::CheckDefined(storage); - EnergyResid::computeStorage(storage, volVars); - Valgrind::CheckDefined(storage); - } - - /*! - * \brief Evaluate the amount all conservation quantities - * (e.g. phase mass) within all sub-control volumes of an - * element. - * - * \param phaseStorage The conserved quantity within the phase in the whole domain - * \param element The finite element - * \param phaseIdx The index of the fluid phase - */ - void addPhaseStorage(PrimaryVariables &phaseStorage, - const Element &element, - const unsigned int phaseIdx) const - { - // create a finite volume element geometry - FVElementGeometry fvGeometry; - fvGeometry.update(this->gridView_(), element); - - // calculate volume variables - ElementVolumeVariables elemVolVars; - this->model_().setHints(element, elemVolVars); - elemVolVars.update(this->problem_(), - element, - fvGeometry, - /*useOldSolution=*/false); - - // calculate the phase storage for all sub-control volumes - for (int scvIdx=0; - scvIdx < fvGeometry.numScv; - scvIdx++) - { - PrimaryVariables tmpPriVars(0.0); - - // compute mass and energy storage terms in terms of - // averaged quantities - MassResid::addPhaseStorage(tmpPriVars, - elemVolVars[scvIdx], - phaseIdx); - EnergyResid::addPhaseStorage(tmpPriVars, - elemVolVars[scvIdx], - phaseIdx); - - // multiply with volume of sub-control volume - tmpPriVars *= fvGeometry.subContVol[scvIdx].volume; - - // Add the storage of the current SCV to the total storage - phaseStorage += tmpPriVars; - } - } - - /*! - * \brief Calculate the source term of the equation - * - * \param scvIdx The SCV (sub-control-volume) index - * \param source The source/sink in the sub-control volume for each component - */ - void computeSource(PrimaryVariables &source, - const unsigned int scvIdx) - { - Valgrind::SetUndefined(source); - ParentType::computeSource(source, scvIdx); - - const VolumeVariables &volVars = this->curVolVars_(scvIdx); - - PrimaryVariables tmp(0); - MassResid::computeSource(tmp, volVars); - source += tmp; - Valgrind::CheckDefined(source); - - /* - * EnergyResid also called in the MassResid - * 1) Makes some sense because energy is also carried by mass - * 2) The mass transfer between the phases is needed. - */ -// tmp = 0.; -// EnergyResid::computeSource(tmp, volVars); -// source += tmp; -// Valgrind::CheckDefined(source); - }; - - - /*! - * \brief Evaluates the total flux of all conservation quantities - * over a face of a subcontrol volume. - * - * \param flux The flux over the SCV (sub-control-volume) face for each component - * \param fIdx The index of the SCV face - * \param onBoundary A boolean variable to specify whether the flux variables - * are calculated for interior SCV faces or boundary faces, default=false - */ - void computeFlux(PrimaryVariables &flux, - const unsigned int fIdx, const bool onBoundary=false) const - { - FluxVariables fluxVars(this->problem_(), - this->element_(), - this->fvGeometry_(), - fIdx, - this->curVolVars_(), - onBoundary); - - flux = 0.0; - MassResid::computeFlux(flux, fluxVars, this->curVolVars_() ); - Valgrind::CheckDefined(flux); -/* - * EnergyResid also called in the MassResid - * 1) Makes some sense because energy is also carried by mass - * 2) The component-wise mass flux in each phase is needed. - */ - } - - /*! - * \brief Compute the local residual, i.e. the deviation of the - * equations from zero. - * - * \param element The finite element - */ - void eval(const Element &element) - { ParentType::eval(element); } - - /*! - * \brief Evaluate the local residual. - * - * \param element The finite element - * \param fvGeometry The finite-volume geometry in the fully implicit scheme - * \param prevElemVolVars The element volume variables of the previous timestep - * \param curElemVolVars The element volume variables of the current timestep - * \param bcType The types of the boundary conditions for all vertices of the element - */ - void eval(const Element &element, - const FVElementGeometry &fvGeometry, - const ElementVolumeVariables &prevElemVolVars, - const ElementVolumeVariables &curElemVolVars, - const ElementBoundaryTypes &bcType) - { - ParentType::eval(element, - fvGeometry, - prevElemVolVars, - curElemVolVars, - bcType); - - if (GET_PROP_VALUE(TypeTag, ImplicitIsBox) - || !bcType.hasDirichlet()) - { - for (int i = 0; i < this->fvGeometry_().numScv; ++i) { - // add the two auxiliary equations, make sure that the - // dirichlet boundary condition is conserved - for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) - { - if (!bcType[i].isDirichlet(phase0NcpIdx + phaseIdx)) - { - this->residual_[i][phase0NcpIdx + phaseIdx] = - this->curVolVars_(i).phaseNcp(phaseIdx); - } - } - } - } - } - - - /*! - * \brief Add Dirichlet boundary conditions for a single intersection - * - * Sets the Dirichlet conditions in a strong sense, in contrast to - * the general handling in CCLocalResidual. - * - * \param isIt - * \param bcTypes - */ - template <class IntersectionIterator> - void evalDirichletSegment_(const IntersectionIterator &isIt, - const BoundaryTypes &bcTypes) - { - // temporary vector to store the Dirichlet boundary fluxes - PrimaryVariables values; - Valgrind::SetUndefined(values); - this->problem_().dirichlet(values, *isIt); - Valgrind::CheckDefined(values); - - // set Dirichlet conditions in a strong sense - for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) - { - if (bcTypes.isDirichlet(eqIdx)) - { - int pvIdx = bcTypes.eqToDirichletIndex(eqIdx); - this->residual_[0][eqIdx] - = this->curPriVar_(0, pvIdx) - values[pvIdx]; - } - else if (eqIdx >= phase0NcpIdx) - { - int phaseIdx = eqIdx - phase0NcpIdx; - this->residual_[0][eqIdx] = - this->curVolVars_(0).phaseNcp(phaseIdx); - } - } - } - -protected: - Implementation &asImp_() - { return *static_cast<Implementation *>(this); } - const Implementation &asImp_() const - { return *static_cast<const Implementation *>(this); } -}; - -} // end namespace +#include <dumux/porousmediumflow/mpnc/implicit/localresidual.hh> #endif diff --git a/dumux/implicit/mpnc/mpncmodel.hh b/dumux/implicit/mpnc/mpncmodel.hh index e6c0b9adb66d8d982dbb2867448446b8d50c021e..427b2ae9b8fa2e29814ae5c8429d4d47699f37d9 100644 --- a/dumux/implicit/mpnc/mpncmodel.hh +++ b/dumux/implicit/mpnc/mpncmodel.hh @@ -1,213 +1,8 @@ -// -*- 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 A fully implicit model for MpNc flow using - * vertex centered finite volumes. - * - */ +#ifndef DUMUX_MPNC_MODEL_HH_OLD +#define DUMUX_MPNC_MODEL_HH_OLD -#ifndef DUMUX_MPNC_MODEL_HH -#define DUMUX_MPNC_MODEL_HH +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/model.hh instead -#include "mpncproperties.hh" -#include "mpncvtkwriter.hh" - -#include <dumux/implicit/model.hh> - -namespace Dumux -{ -/*! - * \ingroup MPNCModel - * \brief A fully implicit model for MpNc flow using - * vertex centered finite volumes. - * - * This model implements a \f$M\f$-phase flow of a fluid mixture - * composed of \f$N\f$ chemical species. The phases are denoted by - * lower index \f$\alpha \in \{ 1, \dots, M \}\f$. All fluid phases - * are mixtures of \f$N \geq M - 1\f$ chemical species which are - * denoted by the upper index \f$\kappa \in \{ 1, \dots, N \} \f$. - * - * The momentum approximation can be selected via "BaseFluxVariables": - * Darcy (ImplicitDarcyFluxVariables) and Forchheimer (ImplicitForchheimerFluxVariables) - * relations are available for all Box models. - * - * By inserting this into the equations for the conservation of the - * mass of each component, one gets one mass-continuity equation for - * each component \f$\kappa\f$ - * \f[ - \sum_{\kappa} \left( - \phi \frac{\partial \left(\varrho_\alpha x_\alpha^\kappa S_\alpha\right)}{\partial t} - + - \mathrm{div}\; - \left\{ - v_\alpha - \frac{\varrho_\alpha}{\overline M_\alpha} x_\alpha^\kappa - \right\} - \right) - = q^\kappa - \f] - * with \f$\overline M_\alpha\f$ being the average molar mass of the - * phase \f$\alpha\f$: \f[ \overline M_\alpha = \sum_\kappa M^\kappa - * \; x_\alpha^\kappa \f] - * - * For the missing \f$M\f$ model assumptions, the model assumes that - * if a fluid phase is not present, the sum of the mole fractions of - * this fluid phase is smaller than \f$1\f$, i.e. - * \f[ - * \forall \alpha: S_\alpha = 0 \implies \sum_\kappa x_\alpha^\kappa \leq 1 - * \f] - * - * Also, if a fluid phase may be present at a given spatial location - * its saturation must be positive: - * \f[ \forall \alpha: \sum_\kappa x_\alpha^\kappa = 1 \implies S_\alpha \geq 0 \f] - * - * Since at any given spatial location, a phase is always either - * present or not present, one of the strict equalities on the - * right hand side is always true, i.e. - * \f[ \forall \alpha: S_\alpha \left( \sum_\kappa x_\alpha^\kappa - 1 \right) = 0 \f] - * always holds. - * - * These three equations constitute a non-linear complementarity - * problem, which can be solved using so-called non-linear - * complementarity functions \f$\Phi(a, b)\f$ which have the property - * \f[\Phi(a,b) = 0 \iff a \geq0 \land b \geq0 \land a \cdot b = 0 \f] - * - * Several non-linear complementarity functions have been suggested, - * e.g. the Fischer-Burmeister function - * \f[ \Phi(a,b) = a + b - \sqrt{a^2 + b^2} \;. \f] - * This model uses - * \f[ \Phi(a,b) = \min \{a, b \}\;, \f] - * because of its piecewise linearity. - * - * These equations are then discretized using a fully-implicit vertex - * centered finite volume scheme (often known as 'box'-scheme) for - * spatial discretization and the implicit Euler method as temporal - * discretization. - * - * The model assumes local thermodynamic equilibrium and uses the - * following primary variables: - * - The component fugacities \f$f^1, \dots, f^{N}\f$ - * - The pressure of the first phase \f$p_1\f$ - * - The saturations of the first \f$M-1\f$ phases \f$S_1, \dots, S_{M-1}\f$ - * - Temperature \f$T\f$ if the energy equation is enabled - */ -template<class TypeTag> -class MPNCModel : public GET_PROP_TYPE(TypeTag, BaseModel) -{ - typedef typename GET_PROP_TYPE(TypeTag, BaseModel) ParentType; - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; - typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector; - typedef Dumux::MPNCVtkWriter<TypeTag> MPNCVtkWriter; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - - enum {enableEnergy = GET_PROP_VALUE(TypeTag, EnableEnergy)}; - enum {enableDiffusion = GET_PROP_VALUE(TypeTag, EnableDiffusion)}; - enum {enableKinetic = GET_PROP_VALUE(TypeTag, EnableKinetic)}; - enum {numEnergyEquations = GET_PROP_VALUE(TypeTag, NumEnergyEquations)}; - enum {numPhases = GET_PROP_VALUE(TypeTag, NumPhases)}; - enum {numComponents = GET_PROP_VALUE(TypeTag, NumComponents)}; - enum {numEq = GET_PROP_VALUE(TypeTag, NumEq)}; - enum { numEnergyEqs = Indices::numPrimaryEnergyVars}; - enum { dimWorld = GridView::dimensionworld}; - enum { dim = GridView::dimension}; - - typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition; - - -public: - MPNCModel() - { - enableSmoothUpwinding_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Implicit, EnableSmoothUpwinding); - enablePartialReassemble_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Implicit, EnablePartialReassemble); - enableJacobianRecycling_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Implicit, EnableJacobianRecycling); - numDiffMethod_ = GET_PARAM_FROM_GROUP(TypeTag, int, Implicit, NumericDifferenceMethod); - } - - void init(Problem &problem) - { - ParentType::init(problem); - vtkWriter_ = std::make_shared<MPNCVtkWriter>(problem); - - if (this->gridView_().comm().rank() == 0) - std::cout - << "Initializing M-phase N-component model: \n" - << " phases: " << numPhases << "\n" - << " components: " << numComponents << "\n" - << " equations: " << numEq << "\n" - << " kinetic mass transfer: " << enableKinetic<< "\n" - << " number of energy equations: " << numEnergyEquations<< "\n" - << " diffusion: " << enableDiffusion << "\n" - << " energy equation: " << enableEnergy << "\n" - << " smooth upwinding: " << enableSmoothUpwinding_ << "\n" - << " partial jacobian reassembly: " << enablePartialReassemble_ << "\n" - << " numeric differentiation method: " << numDiffMethod_ << " (-1: backward, 0: central, +1 forward)\n" - << " jacobian recycling: " << enableJacobianRecycling_ << "\n"; - } - - /*! - * \brief Compute the total storage inside one phase of all - * conservation quantities. - * - * \param phaseStorage The conserved quantity within the phase in the whole domain - * \param phaseIdx The local index of the phases - */ - void globalPhaseStorage(PrimaryVariables &phaseStorage, const unsigned int phaseIdx) - { - phaseStorage = 0; - - for (const auto& element : Dune::elements(this->gridView_())) { - this->localResidual().addPhaseStorage(phaseStorage, element, phaseIdx); - } - - if (this->gridView_().comm().size() > 1) - phaseStorage = this->gridView_().comm().sum(phaseStorage); - } - - /*! - * \brief Add the result of the current timestep to the VTK output. - */ - template <class MultiWriter> - void addOutputVtkFields(const SolutionVector &sol, - MultiWriter &writer) - { - vtkWriter_->addCurrentSolution(writer); - } - - std::shared_ptr<MPNCVtkWriter> vtkWriter_; - -private: - bool enableSmoothUpwinding_; - bool enablePartialReassemble_; - bool enableJacobianRecycling_; - int numDiffMethod_; -}; - -} - -#include "mpncpropertydefaults.hh" +#include <dumux/porousmediumflow/mpnc/implicit/model.hh> #endif diff --git a/dumux/implicit/mpnc/mpncmodelkinetic.hh b/dumux/implicit/mpnc/mpncmodelkinetic.hh index b94104a695609e5de0b3e181d998e8e8763aba41..5cc894786a552b4ea448939fbbd161cb28eaedf2 100644 --- a/dumux/implicit/mpnc/mpncmodelkinetic.hh +++ b/dumux/implicit/mpnc/mpncmodelkinetic.hh @@ -1,341 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 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 adds kinetic mass and energy transfer modules to - * the M-phase N-component model. - */ -#ifndef DUMUX_MPNC_MODEL_KINETIC_HH -#define DUMUX_MPNC_MODEL_KINETIC_HH +#ifndef DUMUX_MPNC_MODEL_KINETIC_HH_OLD +#define DUMUX_MPNC_MODEL_KINETIC_HH_OLD -// equilibrium model -#include <dumux/implicit/mpnc/mpncmodel.hh> +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/modelkinetic.hh instead -// generic stuff -#include "mpncpropertieskinetic.hh" - -namespace Dumux -{ -/*! - * \ingroup MPNCModel - * \brief A fully implicit model for MpNc flow using - * vertex centered finite volumes. - * This is the specialization that is able to capture kinetic mass and / or energy transfer. - * - * Please see the comment in the localresidualenergykinetic class about the inclusion of volume changing work. - * - * Please see the comment about different possibilities of calculating phase-composition in the mpnclocalresidualmasskinetic class. - */ - -template<class TypeTag> -class MPNCModelKinetic : public MPNCModel<TypeTag> -{ - typedef MPNCModel<TypeTag> ParentType; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes; - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; - typedef Dune::BlockVector<Dune::FieldVector<Scalar, 1> > ScalarField; - typedef Dumux::MPNCVtkWriter<TypeTag> MPNCVtkWriter; - - enum { enableEnergy = GET_PROP_VALUE(TypeTag, EnableEnergy)}; - enum { enableDiffusion = GET_PROP_VALUE(TypeTag, EnableDiffusion)}; - enum { enableKinetic = GET_PROP_VALUE(TypeTag, EnableKinetic)}; - enum { numEnergyEquations = GET_PROP_VALUE(TypeTag, NumEnergyEquations)}; - enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases)}; - enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents)}; - enum { numEq = GET_PROP_VALUE(TypeTag, NumEq)}; - enum { numEnergyEqs = Indices::numPrimaryEnergyVars}; - enum { dimWorld = GridView::dimensionworld}; - enum { dim = GridView::dimension}; - - typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition; - typedef Dune::BlockVector<GlobalPosition> GlobalPositionField; - typedef std::array<GlobalPositionField, numPhases> PhaseGlobalPositionField; - - typedef std::vector<Dune::FieldVector<Scalar, 1> > ScalarVector; - typedef std::array<ScalarVector, numPhases> PhaseVector; - typedef Dune::FieldVector<Scalar, dim> DimVector; - typedef Dune::BlockVector<DimVector> DimVectorField; - typedef std::array<DimVectorField, numPhases> PhaseDimVectorField; - -public: - /*! - * \brief Initialize the fluid system's static parameters - * \param problem The Problem - */ - void init(Problem &problem) - { - ParentType::init(problem); - static_assert(FluidSystem::numComponents==2, " so far kinetic mass transfer assumes a two-component system. "); - } - - /*! - * \brief Initialze the velocity vectors. - * - * Otherwise the initial solution cannot be written to disk. - */ - void initVelocityStuff(){ - // belongs to velocity averaging - int numVertices = this->gridView().size(dim); - - // allocation and bringing to size - for (unsigned int phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) { - volumeDarcyVelocity_[phaseIdx].resize(numVertices); - volumeDarcyMagVelocity_[phaseIdx].resize(numVertices); - std::fill(volumeDarcyMagVelocity_[phaseIdx].begin(), volumeDarcyMagVelocity_[phaseIdx].end(), 0.0); - boxSurface_.resize(numVertices); - std::fill(boxSurface_.begin(), boxSurface_.end(), 0.0); - volumeDarcyVelocity_[phaseIdx] = 0; - } - } - - - /*! - * \brief face-area weighted average of the velocities. - * - * This function calculates the darcy velocities on the faces and averages them for one vertex. - * The weight of the average is the area of the face. - * - * Called by newtonControlle in newtonUpdate if velocityAveragingInProblem is true. - */ - void calcVelocityAverage() - { - Scalar numVertices = this->gridView().size(dim); - - // reset - for (int phaseIdx =0; phaseIdx<numPhases; ++phaseIdx){ - std::fill(boxSurface_.begin(), boxSurface_.end(), 0.0); - volumeDarcyVelocity_[phaseIdx] = 0; - std::fill(volumeDarcyMagVelocity_[phaseIdx].begin(), volumeDarcyMagVelocity_[phaseIdx].end(), 0.0); - } - - // loop all elements - for (const auto& element : Dune::elements(this->gridView_())){ - //obtaining the elementVolumeVariables needed for the Fluxvariables - FVElementGeometry fvGeometry; - ElementVolumeVariables elemVolVars; - ElementBoundaryTypes elemBcTypes; - - fvGeometry.update(this->gridView_(), element); - elemBcTypes.update(this->problem_(), element); - - this->setHints(element, elemVolVars); - elemVolVars.update(this->problem_(), - element, - fvGeometry, - false); - - this->updateCurHints(element, elemVolVars); - for (int fIdx = 0; fIdx < fvGeometry.numScvf; ++ fIdx) { - int i = fvGeometry.subContVolFace[fIdx].i; - int I = this->vertexMapper().subIndex(element, i, dim); - - int j = fvGeometry.subContVolFace[fIdx].j; - int J = this->vertexMapper().subIndex(element, j, dim); - - const Scalar scvfArea = fvGeometry.subContVolFace[fIdx].normal.two_norm(); - boxSurface_[I] += scvfArea; - boxSurface_[J] += scvfArea; - - FluxVariables fluxVars(this->problem_(), - element, - fvGeometry, - fIdx, - elemVolVars); - - for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { - GlobalPosition faceDarcyVelocity = fluxVars.velocity(phaseIdx); - faceDarcyVelocity *= scvfArea; - - // although not yet really a volume average, see later: divide by surface - volumeDarcyVelocity_[phaseIdx][I] += faceDarcyVelocity; - volumeDarcyVelocity_[phaseIdx][J] += faceDarcyVelocity; - } // end phases - } // end faces - } // end elements - - // Divide by the sum of the faces: actually producing the average (as well as it's magnitude) - for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { - // first, divide the velocity field by the - // respective finite volume's surface area - for (int I = 0; I < numVertices; ++I){ - volumeDarcyVelocity_[phaseIdx][I] /= boxSurface_[I]; - volumeDarcyMagVelocity_[phaseIdx][I] = volumeDarcyVelocity_[phaseIdx][I].two_norm() ; - }// end all vertices - }// end all phases - }// end calcVelocity - -// /*! -// * \brief Check whether the current solution makes sense. -// */ -// void checkPlausibility() const -// { -// // Looping over all elements of the domain -// for (const auto& element : Dune::elements(this->gridView_())) -// { -// ElementVolumeVariables elemVolVars; -// FVElementGeometry fvGeometry; -// -// // updating the volume variables -// fvGeometry.update(this->problem_().gridView(), element); -// elemVolVars.update(this->problem_(), element, fvGeometry, false); -// -// std::stringstream message ; -// // number of scv -// const unsigned int numScv = fvGeometry.numScv; // box: numSCV, cc:1 -// -// for (unsigned int scvIdx = 0; scvIdx < numScv; ++scvIdx) { -// -// const FluidState & fluidState = elemVolVars[scvIdx].fluidState(); -// -// // energy check -// for(unsigned int energyEqIdx=0; energyEqIdx<numEnergyEqs; energyEqIdx++){ -// const Scalar eps = 1e-6 ; -//// const Scalar temperatureTest = elemVolVars[scvIdx].fluidState().temperature(); -// const Scalar temperatureTest = elemVolVars[scvIdx].temperature(energyEqIdx); -//// const Scalar temperatureTest = 42; -// -// if (not std::isfinite(temperatureTest) or temperatureTest < 0. ){ -// message <<"\nUnphysical Value in Energy: \n"; -// message << "\tT" <<"_"<<FluidSystem::phaseName(energyEqIdx)<<"="<< temperatureTest <<"\n"; -// } -// } -// -// // mass Check -// for(int phaseIdx=0; phaseIdx<numPhases; phaseIdx++){ -// const Scalar eps = 1e-6 ; -// for (int compIdx=0; compIdx< numComponents; ++ compIdx){ -// const Scalar xTest = fluidState.moleFraction(phaseIdx, compIdx); -// if (not std::isfinite(xTest) or xTest < 0.-eps or xTest > 1.+eps ){ -// message <<"\nUnphysical Value in Mass: \n"; -// -// message << "\tx" <<"_"<<FluidSystem::phaseName(phaseIdx) -// <<"^"<<FluidSystem::componentName(compIdx)<<"=" -// << fluidState.moleFraction(phaseIdx, compIdx) <<"\n"; -// } -// } -// } -// -// // interfacial area check (interfacial area between fluid as well as solid phases) -// for(int phaseIdxI=0; phaseIdxI<numPhases+1; phaseIdxI++){ -// const Scalar eps = 1e-6 ; -// for (int phaseIdxII=0; phaseIdxII< numPhases+1; ++ phaseIdxII){ -// if (phaseIdxI == phaseIdxII) -// continue; -// assert(numEnergyEqs == 3) ; // otherwise this ia call does not make sense -// const Scalar ia = elemVolVars[scvIdx].interfacialArea(phaseIdxI, phaseIdxII); -// if (not std::isfinite(ia) or ia < 0.-eps ) { -// message <<"\nUnphysical Value in interfacial area: \n"; -// message << "\tia" <<FluidSystem::phaseName(phaseIdxI) -// <<FluidSystem::phaseName(phaseIdxII)<<"=" -// << ia << "\n" ; -// message << "\t S[0]=" << fluidState.saturation(0); -// message << "\t S[1]=" << fluidState.saturation(1); -// message << "\t p[0]=" << fluidState.pressure(0); -// message << "\t p[1]=" << fluidState.pressure(1); -// } -// } -// } -// -// // General Check -// for(int phaseIdx=0; phaseIdx<numPhases; phaseIdx++){ -// const Scalar eps = 1e-6 ; -// const Scalar saturationTest = fluidState.saturation(phaseIdx); -// if (not std::isfinite(saturationTest) or saturationTest< 0.-eps or saturationTest > 1.+eps ){ -// message <<"\nUnphysical Value in Saturation: \n"; -// message << "\tS" <<"_"<<FluidSystem::phaseName(phaseIdx)<<"=" << std::scientific -// << fluidState.saturation(phaseIdx) << std::fixed << "\n"; -// } -// } -// -// // velocity Check -// const unsigned int globalVertexIdx = this->problem_().vertexMapper().subIndex(element, scvIdx, dim); -// for(int phaseIdx=0; phaseIdx<numPhases; phaseIdx++){ -// const Scalar eps = 1e-6 ; -// const Scalar velocityTest = volumeDarcyMagVelocity(phaseIdx, globalVertexIdx); -// if (not std::isfinite(velocityTest) ){ -// message <<"\nUnphysical Value in Velocity: \n"; -// message << "\tv" <<"_"<<FluidSystem::phaseName(phaseIdx)<<"=" << std::scientific -// << velocityTest << std::fixed << "\n"; -// } -// } -// -// -// // Some check wrote into the error-message, add some additional information and throw -// if (not message.str().empty()){ -// // Getting the spatial coordinate -// const GlobalPosition & globalPosCurrent = fvGeometry.subContVol[scvIdx].global; -// std::stringstream positionString ; -// -// // Add physical location -// positionString << "Here:"; -// for(int i=0; i<dim; i++) -// positionString << " x"<< (i+1) << "=" << globalPosCurrent[i] << " " ; -// message << "Unphysical value found! \n" ; -// message << positionString.str() ; -// message << "\n"; -// -// message << " Here come the primary Variables:" << "\n" ; -// for(unsigned int priVarIdx =0 ; priVarIdx<numEq; ++priVarIdx){ -// message << "priVar[" << priVarIdx << "]=" << elemVolVars[scvIdx].priVar(priVarIdx) << "\n"; -// } -// DUNE_THROW(NumericalProblem, message.str()); -// } -// } // end scv-loop -// } // end element loop -// } - - /*! - * \brief Access to the averaged (magnitude of) velocity for each vertex. - * - * \param phaseIdx The index of the fluid phase - * \param dofIdxGlobal The global index of the degree of freedom - * - */ - const Scalar volumeDarcyMagVelocity(const unsigned int phaseIdx, - const unsigned int dofIdxGlobal) const - { return volumeDarcyMagVelocity_[phaseIdx][dofIdxGlobal]; } - - /*! - * \brief Access to the averaged velocity for each vertex. - * - * \param phaseIdx The index of the fluid phase - * \param dofIdxGlobal The global index of the degree of freedom - */ - const GlobalPosition volumeDarcyVelocity(const unsigned int phaseIdx, - const unsigned int dofIdxGlobal) const - { return volumeDarcyVelocity_[phaseIdx][dofIdxGlobal]; } - -private: - PhaseGlobalPositionField volumeDarcyVelocity_; - PhaseVector volumeDarcyMagVelocity_ ; - ScalarVector boxSurface_ ; -}; - -} // namespace Dumux - -#include "mpncpropertydefaultskinetic.hh" +#include <dumux/porousmediumflow/mpnc/implicit/modelkinetic.hh> #endif diff --git a/dumux/implicit/mpnc/mpncnewtoncontroller.hh b/dumux/implicit/mpnc/mpncnewtoncontroller.hh index d0cca6e2ec05653f83e8d7bf72e290600e95dc2f..94a0bde4c1f06bd28ec90f6fd9e469ce9f28f453 100644 --- a/dumux/implicit/mpnc/mpncnewtoncontroller.hh +++ b/dumux/implicit/mpnc/mpncnewtoncontroller.hh @@ -1,271 +1,8 @@ -// -*- 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 A MpNc specific controller for the newton solver, which knows - * 'physically meaningful' solution. - * - * This controller 'knows' what a 'physically meaningful' solution is - * which allows the newton method to abort quicker if the solution is - * way out of bounds. - */ -#ifndef DUMUX_MPNC_NEWTON_CONTROLLER_HH -#define DUMUX_MPNC_NEWTON_CONTROLLER_HH +#ifndef DUMUX_MPNC_NEWTON_CONTROLLER_HH_OLD +#define DUMUX_MPNC_NEWTON_CONTROLLER_HH_OLD -#include "mpncproperties.hh" +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/newtoncontroller.hh instead -#include <dumux/nonlinear/newtoncontroller.hh> -#include <algorithm> - -namespace Dumux { - -/*! - * \brief A MpNc specific controller for the newton solver, which knows - * 'physically meaningful' solution. - */ -template <class TypeTag, bool enableKinetic /* = false */> -class MpNcNewtonChop -{ - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector; - - enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; - enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; - enum { fug0Idx = Indices::fug0Idx }; - enum { s0Idx = Indices::s0Idx }; - enum { p0Idx = Indices::p0Idx }; - -public: - static void chop(SolutionVector &uCurrentIter, - const SolutionVector &uLastIter) - { - for (unsigned int i = 0; i < uLastIter.size(); ++i) { - for (unsigned int phaseIdx = 0; phaseIdx < numPhases - 1; ++phaseIdx) - saturationChop_(uCurrentIter[i][s0Idx + phaseIdx], - uLastIter[i][s0Idx + phaseIdx]); - pressureChop_(uCurrentIter[i][p0Idx], uLastIter[i][p0Idx]); - for (unsigned int comp = 0; comp < numComponents; ++comp) { - pressureChop_(uCurrentIter[i][fug0Idx + comp], uLastIter[i][fug0Idx + comp]); - } - - } - }; - -private: - static void clampValue_(Scalar &val, - const Scalar minVal, - const Scalar maxVal) - { - val = std::max(minVal, std::min(val, maxVal)); - }; - - static void pressureChop_(Scalar &val, - const Scalar oldVal) - { - const Scalar maxDelta = std::max(oldVal/4.0, 10e3); - clampValue_(val, oldVal - maxDelta, oldVal + maxDelta); - val = std::max(0.0, val); // don't allow negative pressures - } - - static void saturationChop_(Scalar &val, - const Scalar oldVal) - { - const Scalar maxDelta = 0.25; - clampValue_(val, oldVal - maxDelta, oldVal + maxDelta); - clampValue_(val, -0.001, 1.001); - } - -}; - -template <class TypeTag> -class MpNcNewtonChop<TypeTag, /*enableKinetic=*/true> -{ - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector; - - enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; - enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; - enum { moleFrac00Idx = Indices::moleFrac00Idx }; - enum { s0Idx = Indices::s0Idx }; - enum { p0Idx = Indices::p0Idx }; - -public: - static void chop(SolutionVector &uCurrentIter, - const SolutionVector &uLastIter) - { - for (unsigned int i = 0; i < uLastIter.size(); ++i) { - for (int phaseIdx = 0; phaseIdx < numPhases - 1; ++phaseIdx) - saturationChop_(uCurrentIter[i][s0Idx + phaseIdx], - uLastIter[i][s0Idx + phaseIdx]); - pressureChop_(uCurrentIter[i][p0Idx], uLastIter[i][p0Idx]); - for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { - for (int compIdx = 0; compIdx < numComponents; ++compIdx) { - moleFracChop_(uCurrentIter[i][moleFrac00Idx + phaseIdx*numComponents + compIdx], - uLastIter[i][moleFrac00Idx + phaseIdx*numComponents + compIdx]); - } - } - - } - } - -private: - static void clampValue_(Scalar &val, - const Scalar minVal, - const Scalar maxVal) - { - val = std::max(minVal, std::min(val, maxVal)); - }; - - static void pressureChop_(Scalar &val, - const Scalar oldVal) - { - const Scalar maxDelta = std::max(oldVal/4.0, 10e3); - clampValue_(val, oldVal - maxDelta, oldVal + maxDelta); - val = std::max(0.0, val); // don't allow negative pressures - } - - static void saturationChop_(Scalar &val, - const Scalar oldVal) - { - const Scalar maxDelta = 0.25; - clampValue_(val, oldVal - maxDelta, oldVal + maxDelta); - clampValue_(val, -0.001, 1.001); - } - - static void moleFracChop_(Scalar &val, - const Scalar oldVal) - { - // no component mole fraction can change by more than 20% per iteration - const Scalar maxDelta = 0.20; - clampValue_(val, oldVal - maxDelta, oldVal + maxDelta); - clampValue_(val, -0.001, 1.001); - } - -}; - -/*! - * \ingroup Newton - * \brief A MpNc specific controller for the newton solver. - * - * This controller 'knows' what a 'physically meaningful' solution is - * which allows the newton method to abort quicker if the solution is - * way out of bounds. - */ -template <class TypeTag> -class MPNCNewtonController : public NewtonController<TypeTag> -{ - typedef NewtonController<TypeTag> ParentType; - typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - - enum {numPhases = GET_PROP_VALUE(TypeTag, NumPhases)}; - enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents)}; - enum {enableKinetic = GET_PROP_VALUE(TypeTag, EnableKinetic)}; - enum {p0Idx = Indices::p0Idx}; - enum {s0Idx = Indices::s0Idx}; - - typedef MpNcNewtonChop<TypeTag, enableKinetic> NewtonChop; - -public: - MPNCNewtonController(const Problem &problem) - : ParentType(problem) - { - enableChop_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Newton, EnableChop); - Dune::FMatrixPrecision<>::set_singular_limit(1e-35); - }; - - void newtonUpdate(SolutionVector &uCurrentIter, - const SolutionVector &uLastIter, - const SolutionVector &deltaU) - { - if (this->enableShiftCriterion_ || this->enablePartialReassemble_) - this->newtonUpdateShift(uLastIter, deltaU); - - // compute the vertex and element colors for partial - // reassembly - if (this->enablePartialReassemble_) { - const Scalar minReasmTol = 1e-2*this->shiftTolerance_; - const Scalar maxReasmTol = 1e1*this->shiftTolerance_; - Scalar reassembleTol = std::max(minReasmTol, std::min(maxReasmTol, this->shift_/1e4)); - - this->model_().jacobianAssembler().updateDiscrepancy(uLastIter, deltaU); - this->model_().jacobianAssembler().computeColors(reassembleTol); - } - - this->writeConvergence_(uLastIter, deltaU); - - if (GET_PARAM_FROM_GROUP(TypeTag, bool, Newton, UseLineSearch)) { - lineSearchUpdate_(uCurrentIter, uLastIter, deltaU); - } - else { - for (unsigned int i = 0; i < uLastIter.size(); ++i) { - uCurrentIter[i] = uLastIter[i]; - uCurrentIter[i] -= deltaU[i]; - } - - if (this->numSteps_ < 2 && enableChop_) { - // put crash barriers along the update path at the - // beginning... - NewtonChop::chop(uCurrentIter, uLastIter); - } - - if (this->enableResidualCriterion_) - { - SolutionVector tmp(uLastIter); - this->reduction_ = this->method().model().globalResidual(tmp, uCurrentIter); - this->reduction_ /= this->initialResidual_; - } - } - } - -private: - void lineSearchUpdate_(SolutionVector &uCurrentIter, - const SolutionVector &uLastIter, - const SolutionVector &deltaU) - { - Scalar lambda = 1.0; - Scalar globDef; - - SolutionVector tmp(uLastIter); - Scalar oldGlobDef = this->model_().globalResidual(tmp, uLastIter); - while (true) { - uCurrentIter = deltaU; - uCurrentIter *= -lambda; - uCurrentIter += uLastIter; - - globDef = this->model_().globalResidual(tmp, uCurrentIter); - if (globDef < oldGlobDef || lambda <= 1.0/64) { - this->endIterMsg() << ", defect " << oldGlobDef << "->" << globDef << "@lambda=1/" << 1/lambda; - return; - } - - // try with a smaller update - lambda /= 2; - } - } - - bool enableChop_; -}; -} +#include <dumux/porousmediumflow/mpnc/implicit/newtoncontroller.hh> #endif diff --git a/dumux/implicit/mpnc/mpncproperties.hh b/dumux/implicit/mpnc/mpncproperties.hh index 3943d328ca8033f49716c9429691425a39549b44..c1b54fe4d3540ae4963447d7878fd5fbf222928f 100644 --- a/dumux/implicit/mpnc/mpncproperties.hh +++ b/dumux/implicit/mpnc/mpncproperties.hh @@ -1,144 +1,8 @@ -// -*- 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/>. * - *****************************************************************************/ -#ifndef DUMUX_MPNC_PROPERTIES_HH -#define DUMUX_MPNC_PROPERTIES_HH +#ifndef DUMUX_MPNC_PROPERTIES_HH_OLD +#define DUMUX_MPNC_PROPERTIES_HH_OLD -#include <dumux/implicit/box/properties.hh> -#include <dumux/implicit/cellcentered/properties.hh> +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/properties.hh instead -/*! - * \ingroup Properties - * \ingroup ImplicitProperties - * \ingroup BoxMpNcModel - * \file - * \brief Defines the properties required for the MpNc fully implicit model. - */ -namespace Dumux -{ -namespace Properties -{ - -////////////////////////////////////////////////////////////////// -// Type tags -////////////////////////////////////////////////////////////////// - -//! The type tags for the implicit m-phase n-component problems -NEW_TYPE_TAG(MPNC); -NEW_TYPE_TAG(BoxMPNC, INHERITS_FROM(BoxModel, MPNC)); -NEW_TYPE_TAG(CCMPNC, INHERITS_FROM(CCModel, MPNC)); - -////////////////////////////////////////////////////////////////// -// Property tags -////////////////////////////////////////////////////////////////// -NEW_PROP_TAG(NumPhases); //!< Number of fluid phases in the system -NEW_PROP_TAG(NumComponents); //!< Number of fluid components in the system -NEW_PROP_TAG(Indices); //!< Enumerations for the model - -NEW_PROP_TAG(BaseFluxVariables); //!< The type of velocity calculation that is to be used - -NEW_PROP_TAG(PressureFormulation); //!< The formulation of the model - -NEW_PROP_TAG(MPNCVtkCommonModule); //!< Vtk writer module for writing the common quantities into the VTK output file -NEW_PROP_TAG(MPNCVtkMassModule); //!< Vtk writer module for writing the mass related quantities into the VTK output file -NEW_PROP_TAG(MPNCVtkEnergyModule); //!< Vtk writer module for writing the energy related quantities into the VTK output file -NEW_PROP_TAG(MPNCVtkCustomModule); //!< Vtk writer module for writing the user-specified quantities into the VTK output file - -NEW_PROP_TAG(VelocityAveragingInModel);//!< Should the averaging of velocities be done in the model? - -//! specify which quantities are written to the vtk output files -NEW_PROP_TAG(VtkAddPorosity); -NEW_PROP_TAG(VtkAddPermeability); -NEW_PROP_TAG(VtkAddBoundaryTypes); -NEW_PROP_TAG(VtkAddSaturations); -NEW_PROP_TAG(VtkAddPressures); -NEW_PROP_TAG(VtkAddVarPressures); -NEW_PROP_TAG(VtkAddVelocities); -NEW_PROP_TAG(VtkAddVelocity); -NEW_PROP_TAG(VtkAddDensities); -NEW_PROP_TAG(VtkAddMobilities); -NEW_PROP_TAG(VtkAddAverageMolarMass); -NEW_PROP_TAG(VtkAddMassFractions); -NEW_PROP_TAG(VtkAddMoleFractions); -NEW_PROP_TAG(VtkAddMolarities); -NEW_PROP_TAG(VtkAddFugacities); -NEW_PROP_TAG(VtkAddFugacityCoefficients); -NEW_PROP_TAG(VtkAddTemperatures); -NEW_PROP_TAG(VtkAddEnthalpies); -NEW_PROP_TAG(VtkAddInternalEnergies); - -NEW_PROP_TAG(VtkAddxEquil); - -NEW_PROP_TAG(VtkAddReynolds); -NEW_PROP_TAG(VtkAddPrandtl); -NEW_PROP_TAG(VtkAddNusselt); -NEW_PROP_TAG(VtkAddInterfacialArea); - -NEW_PROP_TAG(SpatialParams); //!< The type of the spatial parameters - -NEW_PROP_TAG(MaterialLaw); //!< The material law which ought to be used (extracted from the spatialParams) -NEW_PROP_TAG(MaterialLawParams); //!< The context material law (extracted from the spatialParams) - -//! The compositional twophase system of fluids which is considered -NEW_PROP_TAG(FluidSystem); - -//! The thermodynamic constraint solver which calculates the -//! composition of any phase given all component fugacities. -NEW_PROP_TAG(ConstraintSolver); - -//! Enable the energy equation? -NEW_PROP_TAG(EnableEnergy); - -//! Enable diffusive fluxes? -NEW_PROP_TAG(EnableDiffusion); - -//! Enable kinetic resolution of mass transfer processes? -NEW_PROP_TAG(EnableKinetic); - -//! Property for the definition of the number of energy equations (0,1,2,3) -NEW_PROP_TAG(NumEnergyEquations); - -//! Enable Maxwell Diffusion? (If false: use Fickian Diffusion) Maxwell incorporated the mutual -//! influences of multiple diffusing components. However, Fick seems to be more robust. -NEW_PROP_TAG(UseMaxwellDiffusion); - -//! The model for the effective thermal conductivity -NEW_PROP_TAG(ThermalConductivityModel); - -//! Enable gravity? -NEW_PROP_TAG(ProblemEnableGravity); - -//! Use the smooth upwinding method? -NEW_PROP_TAG(ImplicitEnableSmoothUpwinding); - -NEW_PROP_TAG(ImplicitMassUpwindWeight); //!< The value of the weight of the upwind direction in the mass conservation equations - -NEW_PROP_TAG(ImplicitMobilityUpwindWeight); //!< Weight for the upwind mobility in the velocity calculation - -//! Chop the Newton update at the beginning of the non-linear solver? -NEW_PROP_TAG(NewtonEnableChop); - -//! Which type of fluidstate should be used? -NEW_PROP_TAG(FluidState); - -//! Property for the forchheimer coefficient -NEW_PROP_TAG(SpatialParamsForchCoeff); -} -} +#include <dumux/porousmediumflow/mpnc/implicit/properties.hh> #endif diff --git a/dumux/implicit/mpnc/mpncpropertieskinetic.hh b/dumux/implicit/mpnc/mpncpropertieskinetic.hh index 84013280c6c14251102ec7c8efb2198a0640eeff..216825e757934ea0bd5fc200dd2b6c25b083f0be 100644 --- a/dumux/implicit/mpnc/mpncpropertieskinetic.hh +++ b/dumux/implicit/mpnc/mpncpropertieskinetic.hh @@ -1,73 +1,8 @@ -// -*- 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 declares and defines the properties required by - * the kinetic modules the M-phase N-component model. - */ -#ifndef DUMUX_MPNC_PROPERTIES_KINETIC_HH -#define DUMUX_MPNC_PROPERTIES_KINETIC_HH +#ifndef DUMUX_MPNC_PROPERTIES_KINETIC_HH_OLD +#define DUMUX_MPNC_PROPERTIES_KINETIC_HH_OLD -#include "mpncproperties.hh" +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/propertieskinetic.hh instead -namespace Dumux -{ -namespace Properties -{ -////////////////////////////////////////////////////////////////// -// Type tags -////////////////////////////////////////////////////////////////// -NEW_TYPE_TAG(BoxMPNCKinetic, INHERITS_FROM(BoxMPNC)); -//NEW_TYPE_TAG(CCMPNCKinetic, INHERITS_FROM(CCMPNC)); - -////////////////////////////////////////////////////////////////// -// Property tags -////////////////////////////////////////////////////////////////// -NEW_PROP_TAG(AwnSurface); //!< The material law which ought to be used (extracted from the spatialParams) -NEW_PROP_TAG(AwnSurfaceParams); //!< The context material law (extracted from the spatialParams) -NEW_PROP_TAG(AwsSurface); //!< The material law which ought to be used (extracted from the spatialParams) -NEW_PROP_TAG(AwsSurfaceParams); //!< The context material law (extracted from the spatialParams) -NEW_PROP_TAG(AnsSurface); //!< The material law which ought to be used (extracted from the spatialParams) -NEW_PROP_TAG(AnsSurfaceParams); //!< The context material law (extracted from the spatialParams) - -NEW_PROP_TAG(VtkAddDeltaP); // !< Output of pressure minus a fixed value -SET_BOOL_PROP(MPNC, VtkAddDeltaP, false); - -//! The Model for kinetic Mass and Energy Transfer -NEW_PROP_TAG(MPNCModelKinetic); - -//! Enable kinetic resolution of mass transfer processes? -NEW_PROP_TAG(EnableKinetic); - -//! Property for the definition of the number of energy equations (0,1,2,3) -NEW_PROP_TAG(NumEnergyEquations); - -//! average the velocity in the model -NEW_PROP_TAG(VelocityAveragingInModel); - -//! which nusselt correlation to use -NEW_PROP_TAG(NusseltFormulation); - -//! which sherwood correlation to use -NEW_PROP_TAG(SherwoodFormulation); - -} -} +#include <dumux/porousmediumflow/mpnc/implicit/propertieskinetic.hh> #endif diff --git a/dumux/implicit/mpnc/mpncpropertydefaults.hh b/dumux/implicit/mpnc/mpncpropertydefaults.hh index a189e9ccb6b41ff6468a11bd624f55edcc41396e..8758e626f363ef6d2e81e04527f9caa59a4d3c31 100644 --- a/dumux/implicit/mpnc/mpncpropertydefaults.hh +++ b/dumux/implicit/mpnc/mpncpropertydefaults.hh @@ -1,280 +1,8 @@ -// -*- 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/>. * - *****************************************************************************/ -#ifndef DUMUX_MPNC_PROPERTY_DEFAULTS_HH -#define DUMUX_MPNC_PROPERTY_DEFAULTS_HH +#ifndef DUMUX_MPNC_PROPERTY_DEFAULTS_HH_OLD +#define DUMUX_MPNC_PROPERTY_DEFAULTS_HH_OLD -#include "mpncindices.hh" +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/propertydefaults.hh instead -#include "mpncmodel.hh" -#include "mpncindices.hh" -#include "mpnclocalresidual.hh" -#include "mpncfluxvariables.hh" -#include "mpncvolumevariables.hh" -#include "mpncproperties.hh" -#include "mpncnewtoncontroller.hh" -#include "mpncvtkwritermodule.hh" -#include "mpncvtkwritercommon.hh" -#include "mass/mpncvtkwritermass.hh" -#include "energy/mpncvtkwriterenergy.hh" - -#include <dumux/material/constraintsolvers/compositionfromfugacities.hh> -#include <dumux/material/spatialparams/implicitspatialparams.hh> - -#include <dumux/material/fluidmatrixinteractions/2p/thermalconductivitysomerton.hh> - - -/*! - * \ingroup Properties - * \ingroup ImplicitProperties - * \ingroup BoxMpNcModel - * \file - * \brief Default properties for the MpNc fully implicit model. - */ -namespace Dumux -{ -namespace Properties -{ -////////////////////////////////////////////////////////////////// -// default property values -////////////////////////////////////////////////////////////////// - -/*! - * \brief Set the property for the number of components. - * - * We just forward the number from the fluid system. - */ -SET_PROP(MPNC, NumComponents) -{ -private: - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - -public: - static const unsigned int value = FluidSystem::numComponents; -}; - -/*! - * \brief Set the property for the number of fluid phases. - */ -SET_PROP(MPNC, NumPhases) -{ -private: - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - -public: - static const unsigned int value = FluidSystem::numPhases; -}; - -/*! - * \brief Set the property for the number of equations and primary variables. - */ -SET_PROP(MPNC, NumEq) -{ -private: - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; - -public: - static const unsigned int value = Indices::numPrimaryVars; -}; - -/*! - * \brief Set the property for the material parameters by extracting - * it from the material law. - */ -SET_PROP(MPNC, MaterialLawParams) -{ -private: - typedef typename GET_PROP_TYPE(TypeTag, MaterialLaw) MaterialLaw; - -public: - typedef typename MaterialLaw::Params type; -}; - -/*! - * \brief Set the thermodynamic constraint solver which calculates the - * composition of any phase given all component fugacities. - */ -SET_PROP(MPNC, ConstraintSolver) -{ -private: - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - -public: - typedef Dumux::CompositionFromFugacities<Scalar, FluidSystem> type; -}; - - -//! Use the MpNc local jacobian operator for the MpNc model -SET_TYPE_PROP(MPNC, - LocalResidual, - MPNCLocalResidual<TypeTag>); - -//! Use the MpNc specific newton controller for the MpNc model -SET_PROP(MPNC, NewtonController) -{public: - typedef MPNCNewtonController<TypeTag> type; -}; - -//! the Model property -SET_TYPE_PROP(MPNC, Model, MPNCModel<TypeTag>); - -//! use an isothermal model by default -SET_BOOL_PROP(MPNC, EnableEnergy, false); - -//! disable diffusion by default -SET_BOOL_PROP(MPNC, EnableDiffusion, false); - -//! disable kinetic mass transfer by default -SET_BOOL_PROP(MPNC, EnableKinetic, false); - -//! disable kinetic energy transfer by default -SET_INT_PROP(MPNC, NumEnergyEquations, 0); - -//! disable Maxwell Diffusion by default: use Fick -SET_BOOL_PROP(MPNC, UseMaxwellDiffusion, false); - -//! enable smooth upwinding by default -SET_BOOL_PROP(MPNC, ImplicitEnableSmoothUpwinding, false); - -//! the VolumeVariables property -SET_TYPE_PROP(MPNC, VolumeVariables, MPNCVolumeVariables<TypeTag>); - -//! the FluxVariables property -SET_TYPE_PROP(MPNC, FluxVariables, MPNCFluxVariables<TypeTag>); - -//! the Base of the Fluxvariables property (Darcy / Forchheimer) -SET_TYPE_PROP(MPNC, BaseFluxVariables, ImplicitDarcyFluxVariables<TypeTag>); - -//! truncate the newton update for the first few Newton iterations of a time step -SET_BOOL_PROP(MPNC, NewtonEnableChop, true); - -//! The indices required by the mpnc model -SET_TYPE_PROP(MPNC, Indices, MPNCIndices<TypeTag, 0>); - -//! the upwind weight for the mass conservation equations. -SET_SCALAR_PROP(MPNC, ImplicitMassUpwindWeight, 1.0); - -//! weight for the upwind mobility in the velocity calculation -SET_SCALAR_PROP(MPNC, ImplicitMobilityUpwindWeight, 1.0); - -//! The spatial parameters to be employed. -//! Use ImplicitSpatialParams by default. -SET_TYPE_PROP(MPNC, SpatialParams, ImplicitSpatialParams<TypeTag>); - -//! The VTK writer module for common quantities -SET_PROP(MPNC, MPNCVtkCommonModule) -{ - typedef MPNCVtkWriterCommon<TypeTag> type; -}; - -//! The VTK writer module for quantities which are specific for each -//! mass module -SET_PROP(MPNC, MPNCVtkMassModule) -{ -private: enum { enableKinetic = GET_PROP_VALUE(TypeTag, EnableKinetic) }; -public: typedef MPNCVtkWriterMass<TypeTag, enableKinetic> type; -}; - -//! The VTK writer module for quantities which are specific for each -//! energy module -SET_PROP(MPNC, MPNCVtkEnergyModule) -{ -private: - enum { enableEnergy = GET_PROP_VALUE(TypeTag, EnableEnergy) }; - enum { numEnergyEquations = GET_PROP_VALUE(TypeTag, NumEnergyEquations) }; -public: - typedef MPNCVtkWriterEnergy<TypeTag, enableEnergy, numEnergyEquations> type; -}; - -//! Somerton is used as default model to compute the effective thermal heat conductivity -SET_PROP(MPNC, ThermalConductivityModel) -{ private : - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - public: - typedef ThermalConductivitySomerton<Scalar> type; -}; - -//! The VTK writer for user specified data (does nothing by default) -SET_PROP(MPNC, MPNCVtkCustomModule) -{ typedef MPNCVtkWriterModule<TypeTag> type; }; - -/*! - * \brief The fluid state which is used by the volume variables to - * store the thermodynamic state. This should be chosen - * appropriately for the model ((non-)isothermal, equilibrium, ...). - * This can be done in the problem. - */ -SET_PROP(MPNC, FluidState){ - private: - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - public: - typedef Dumux::CompositionalFluidState<Scalar, FluidSystem> type; -}; - -//! Set the default pressure formulation to the pressure of the (most) wetting phase -SET_INT_PROP(MPNC, - PressureFormulation, - MpNcPressureFormulation::mostWettingFirst); - -//! default value for the forchheimer coefficient -// Source: Ward, J.C. 1964 Turbulent flow in porous media. ASCE J. Hydraul. Div 90. -// Actually the Forchheimer coefficient is also a function of the dimensions of the -// porous medium. Taking it as a constant is only a first approximation -// (Nield, Bejan, Convection in porous media, 2006, p. 10) -SET_SCALAR_PROP(MPNC, SpatialParamsForchCoeff, 0.55); - - -//!< Should the averaging of velocities be done in the Model? (By default in the output) -SET_BOOL_PROP(MPNC, VelocityAveragingInModel, false); - -//! Specify what to add to the VTK output by default -SET_BOOL_PROP(MPNC, VtkAddPorosity, true); -SET_BOOL_PROP(MPNC, VtkAddPermeability, false); -SET_BOOL_PROP(MPNC, VtkAddBoundaryTypes, false); -SET_BOOL_PROP(MPNC, VtkAddSaturations, true); -SET_BOOL_PROP(MPNC, VtkAddPressures, true); -SET_BOOL_PROP(MPNC, VtkAddVarPressures, false); -SET_BOOL_PROP(MPNC, VtkAddVelocities, false); -SET_BOOL_PROP(MPNC, VtkAddVelocity, GET_PROP_VALUE(TypeTag, VtkAddVelocities)); -SET_BOOL_PROP(MPNC, VtkAddDensities, true); -SET_BOOL_PROP(MPNC, VtkAddMobilities, true); -SET_BOOL_PROP(MPNC, VtkAddAverageMolarMass, false); -SET_BOOL_PROP(MPNC, VtkAddMassFractions, false); -SET_BOOL_PROP(MPNC, VtkAddMoleFractions, true); -SET_BOOL_PROP(MPNC, VtkAddMolarities, false); -SET_BOOL_PROP(MPNC, VtkAddFugacities, false); -SET_BOOL_PROP(MPNC, VtkAddFugacityCoefficients, false); -SET_BOOL_PROP(MPNC, VtkAddTemperatures, false); -SET_BOOL_PROP(MPNC, VtkAddEnthalpies, true); -SET_BOOL_PROP(MPNC, VtkAddInternalEnergies, false); -SET_BOOL_PROP(MPNC, VtkAddReynolds, false); -SET_BOOL_PROP(MPNC, VtkAddPrandtl, false); -SET_BOOL_PROP(MPNC, VtkAddNusselt, false); -SET_BOOL_PROP(MPNC, VtkAddInterfacialArea, false); -SET_BOOL_PROP(MPNC, VtkAddxEquil, false); - -// enable gravity by default -SET_BOOL_PROP(MPNC, ProblemEnableGravity, true); - -} - -} +#include <dumux/porousmediumflow/mpnc/implicit/propertydefaults.hh> #endif diff --git a/dumux/implicit/mpnc/mpncpropertydefaultskinetic.hh b/dumux/implicit/mpnc/mpncpropertydefaultskinetic.hh index a8d9a4296b9f454b9379f3c9b4aae72a831ba4d9..31a1b30b4525a05bac67ca1cd2bdccc0759520f2 100644 --- a/dumux/implicit/mpnc/mpncpropertydefaultskinetic.hh +++ b/dumux/implicit/mpnc/mpncpropertydefaultskinetic.hh @@ -1,123 +1,8 @@ -// -*- 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 declares and defines the properties required by - * the kinetic modules the M-phase N-component model. - */ -#ifndef DUMUX_MPNC_PROPERTY_DEFAULTS_KINETIC_HH -#define DUMUX_MPNC_PROPERTY_DEFAULTS_KINETIC_HH +#ifndef DUMUX_MPNC_PROPERTY_DEFAULTS_KINETIC_HH_OLD +#define DUMUX_MPNC_PROPERTY_DEFAULTS_KINETIC_HH_OLD -#include <dumux/implicit/mpnc/mpncproperties.hh> +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/propertydefaultskinetic.hh instead -#include <dumux/implicit/mpnc/mpncmodelkinetic.hh> - -// interfacial area volume variables -#include "mpncvolumevariablesiakinetic.hh" - -// kinetic mass module -#include "mass/mpncindicesmasskinetic.hh" -#include "mass/mpnclocalresidualmasskinetic.hh" -#include "mass/mpncvolumevariablesmasskinetic.hh" -#include "mass/mpncvtkwritermasskinetic.hh" - -// kinetic energy module -#include "energy/mpncindicesenergykinetic.hh" -#include "energy/mpnclocalresidualenergykinetic.hh" -#include "energy/mpncfluxvariablesenergykinetic.hh" -#include "energy/mpncvolumevariablesenergykinetic.hh" -#include "energy/mpncvtkwriterenergykinetic.hh" - -namespace Dumux -{ -namespace Properties -{ - -/*! - * \brief Set the property for the model. - */ -SET_TYPE_PROP(BoxMPNCKinetic, Model, MPNCModelKinetic<TypeTag>); - -/*! - * \brief Set the property for the awn surface parameters by extracting - * it from awn surface. - */ -SET_PROP(BoxMPNCKinetic, AwnSurfaceParams) -{ -private: - typedef typename GET_PROP_TYPE(TypeTag, AwnSurface) AwnSurface; - -public: - typedef typename AwnSurface::Params type; -}; - -/*! - * \brief Set the property for the aws surface parameters by extracting - * it from aws surface. - */ -SET_PROP(BoxMPNCKinetic, AwsSurfaceParams) -{ -private: - typedef typename GET_PROP_TYPE(TypeTag, AwsSurface) AwsSurface; - -public: - typedef typename AwsSurface::Params type; -}; - -/*! - * \brief Set the property for the ans surface parameters by extracting - * it from the surface. - */ -SET_PROP(BoxMPNCKinetic, AnsSurfaceParams) -{ -private: - typedef typename GET_PROP_TYPE(TypeTag, AnsSurface) AnsSurface; - -public: - typedef typename AnsSurface::Params type; -}; - -SET_BOOL_PROP(BoxMPNCKinetic, VelocityAveragingInModel, true); - -/*! - * \brief Set the default formulation for the nusselt correlation - * Other possible parametrizations can be found in the dimensionlessnumbers - */ -SET_PROP(BoxMPNCKinetic, NusseltFormulation ){ - private: - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef DimensionlessNumbers<Scalar> DimLessNum; - public: - static constexpr int value = DimLessNum::NusseltFormulation::WakaoKaguei;}; - -/*! - * \brief Set the default formulation for the sherwood correlation - * Other possible parametrizations can be found in the dimensionlessnumbers - */ -SET_PROP(BoxMPNCKinetic, SherwoodFormulation ){ - private: - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef DimensionlessNumbers<Scalar> DimLessNum; - public: - static constexpr int value = DimLessNum::SherwoodFormulation::WakaoKaguei;}; - -} // end namespace Properties -} // end namespace Dumux +#include <dumux/porousmediumflow/mpnc/implicit/propertydefaultskinetic.hh> #endif diff --git a/dumux/implicit/mpnc/mpncvolumevariables.hh b/dumux/implicit/mpnc/mpncvolumevariables.hh index 21dedb121848f04f589f792154a8adfada944235..9970a45e498136498e00f3eb42ee728d4d09ce01 100644 --- a/dumux/implicit/mpnc/mpncvolumevariables.hh +++ b/dumux/implicit/mpnc/mpncvolumevariables.hh @@ -1,386 +1,8 @@ -// -*- 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 Contains the secondary variables (Quantities which are - * constant within a finite volume) of the MpNc model. - */ -#ifndef DUMUX_MPNC_VOLUME_VARIABLES_HH -#define DUMUX_MPNC_VOLUME_VARIABLES_HH +#ifndef DUMUX_MPNC_VOLUME_VARIABLES_HH_OLD +#define DUMUX_MPNC_VOLUME_VARIABLES_HH_OLD -#include "diffusion/volumevariables.hh" -#include "energy/mpncvolumevariablesenergy.hh" -#include "mass/mpncvolumevariablesmass.hh" -#include "mpncindices.hh" -#include "mpncvolumevariablesia.hh" +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/volumevariables.hh instead -#include <dumux/implicit/volumevariables.hh> -#include <dumux/material/constraintsolvers/ncpflash.hh> - -namespace Dumux -{ -/*! - * \ingroup MPNCModel - * \ingroup ImplicitVolumeVariables - * \brief Contains the quantities which are are constant within a - * finite volume in the MpNc model. - */ -template <class TypeTag> -class MPNCVolumeVariables - : public ImplicitVolumeVariables<TypeTag> - , public MPNCVolumeVariablesIA<TypeTag, GET_PROP_VALUE(TypeTag, EnableKinetic), GET_PROP_VALUE(TypeTag, NumEnergyEquations)> - , public MPNCVolumeVariablesMass<TypeTag, GET_PROP_VALUE(TypeTag, EnableKinetic)> - , public MPNCVolumeVariablesDiffusion<TypeTag, GET_PROP_VALUE(TypeTag, EnableDiffusion) || GET_PROP_VALUE(TypeTag, EnableKinetic)> - , public MPNCVolumeVariablesEnergy<TypeTag, GET_PROP_VALUE(TypeTag, EnableEnergy), GET_PROP_VALUE(TypeTag, NumEnergyEquations)> -{ - typedef ImplicitVolumeVariables<TypeTag> ParentType; - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) Implementation; - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; - typedef typename FluidSystem::ParameterCache ParameterCache; - typedef typename GET_PROP_TYPE(TypeTag, MaterialLaw) MaterialLaw; - typedef typename GET_PROP_TYPE(TypeTag, MaterialLawParams) MaterialLawParams; - typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; - - - // formulations - enum { - pressureFormulation = GET_PROP_VALUE(TypeTag, PressureFormulation), - mostWettingFirst = MpNcPressureFormulation::mostWettingFirst, - leastWettingFirst = MpNcPressureFormulation::leastWettingFirst - }; - - enum {numPhases = GET_PROP_VALUE(TypeTag, NumPhases)}; - enum {numComponents = GET_PROP_VALUE(TypeTag, NumComponents)}; - enum {enableEnergy = GET_PROP_VALUE(TypeTag, EnableEnergy)}; - enum {enableKinetic = GET_PROP_VALUE(TypeTag, EnableKinetic)}; - enum {numEnergyEquations = GET_PROP_VALUE(TypeTag, NumEnergyEquations)}; - enum {enableDiffusion = GET_PROP_VALUE(TypeTag, EnableDiffusion) || enableKinetic}; - enum {s0Idx = Indices::s0Idx}; - enum {p0Idx = Indices::p0Idx}; - - typedef typename GridView::template Codim<0>::Entity Element; - typedef MPNCVolumeVariablesMass<TypeTag, enableKinetic> MassVolumeVariables; - typedef MPNCVolumeVariablesEnergy<TypeTag, enableEnergy, numEnergyEquations> EnergyVolumeVariables; - typedef MPNCVolumeVariablesIA<TypeTag, enableKinetic, numEnergyEquations> IAVolumeVariables; - typedef MPNCVolumeVariablesDiffusion<TypeTag, enableDiffusion> DiffusionVolumeVariables; - -public: - MPNCVolumeVariables() - { hint_ = NULL; }; - - /*! - * \brief Set the volume variables which should be used as initial - * conditions for complex calculations. - */ - void setHint(const Implementation *hint) - { - hint_ = hint; - } - - /*! - * \copydoc ImplicitVolumeVariables::update - * - * \param priVars The primary Variables - * \param problem The Problem - * \param element The finite element - * \param fvGeometry The finite-volume geometry in the fully implicit scheme - * \param scvIdx The index of the sub-control volume - * \param isOldSol Specifies whether this is the previous solution or the current one - */ - void update(const PrimaryVariables &priVars, - const Problem &problem, - const Element &element, - const FVElementGeometry &fvGeometry, - const unsigned int scvIdx, - const bool isOldSol) - { - Valgrind::CheckDefined(priVars); - ParentType::update(priVars, - problem, - element, - fvGeometry, - scvIdx, - isOldSol); - ParentType::checkDefined(); - - ParameterCache paramCache; - - ///////////// - // set the phase saturations - ///////////// - Scalar sumSat = 0; - for (int phaseIdx = 0; phaseIdx < numPhases - 1; ++phaseIdx) { - sumSat += priVars[s0Idx + phaseIdx]; - fluidState_.setSaturation(phaseIdx, priVars[s0Idx + phaseIdx]); - } - Valgrind::CheckDefined(sumSat); - fluidState_.setSaturation(numPhases - 1, 1.0 - sumSat); - - ///////////// - // set the fluid phase temperatures - ///////////// - EnergyVolumeVariables::updateTemperatures(fluidState_, - paramCache, - priVars, - element, - fvGeometry, - scvIdx, - problem); - - ///////////// - // set the phase pressures - ///////////// - // capillary pressure parameters - const MaterialLawParams &materialParams = - problem.spatialParams().materialLawParams(element, fvGeometry, scvIdx); - // capillary pressures - Scalar capPress[numPhases]; - MaterialLaw::capillaryPressures(capPress, materialParams, fluidState_); - // add to the pressure of the first fluid phase - - // depending on which pressure is stored in the primary variables - if(pressureFormulation == mostWettingFirst){ - // This means that the pressures are sorted from the most wetting to the least wetting-1 in the primary variables vector. - // For two phases this means that there is one pressure as primary variable: pw - const Scalar pw = priVars[p0Idx]; - for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) - fluidState_.setPressure(phaseIdx, pw - capPress[0] + capPress[phaseIdx]); - } - else if(pressureFormulation == leastWettingFirst){ - // This means that the pressures are sorted from the least wetting to the most wetting-1 in the primary variables vector. - // For two phases this means that there is one pressure as primary variable: pn - const Scalar pn = priVars[p0Idx]; - for (int phaseIdx = numPhases-1; phaseIdx >= 0; --phaseIdx) - fluidState_.setPressure(phaseIdx, pn - capPress[numPhases-1] + capPress[phaseIdx]); - } - else DUNE_THROW(Dune::InvalidStateException, "Formulation: " << pressureFormulation << " is invalid."); - - ///////////// - // set the fluid compositions - ///////////// - MassVolumeVariables::update(fluidState_, - paramCache, - priVars, - hint_, - problem, - element, - fvGeometry, - scvIdx); - MassVolumeVariables::checkDefined(); - - ///////////// - // Porosity - ///////////// - - // porosity - porosity_ = problem.spatialParams().porosity(element, - fvGeometry, - scvIdx); - Valgrind::CheckDefined(porosity_); - - ///////////// - // Phase mobilities - ///////////// - - // relative permeabilities - MaterialLaw::relativePermeabilities(relativePermeability_, - materialParams, - fluidState_); - - // dynamic viscosities - for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { - // viscosities - Scalar mu = FluidSystem::viscosity(fluidState_, paramCache, phaseIdx); - - fluidState_.setViscosity(phaseIdx, mu); - } - - ///////////// - // diffusion - ///////////// - - // update the diffusion part of the volume data - DiffusionVolumeVariables::update(fluidState_, paramCache, *this, problem); - DiffusionVolumeVariables::checkDefined(); - - ///////////// - // energy - ///////////// - - // update the remaining parts of the energy module - EnergyVolumeVariables::update(fluidState_, - paramCache, - element, - fvGeometry, - scvIdx, - problem); - EnergyVolumeVariables::checkDefined(); - - // make sure the quantities in the fluid state are well-defined - fluidState_.checkDefined(); - - // specific interfacial area, - // well also all the dimensionless numbers :-) - // well, also the mass transfer rate - IAVolumeVariables::update(*this, - fluidState_, - paramCache, - priVars, - problem, - element, - fvGeometry, - scvIdx); - IAVolumeVariables::checkDefined(); - checkDefined(); - - } - - /*! - * \brief Return the fluid configuration at the given primary - * variables - */ - const FluidState &fluidState() const - { return fluidState_; } - - /*! - * \brief Returns the effective mobility of a given phase within - * the control volume. - * - * \param phaseIdx The local index of the phases - */ - Scalar mobility(const unsigned int phaseIdx) const - { - return relativePermeability(phaseIdx)/fluidState_.viscosity(phaseIdx); - } - - /*! - * \brief Returns the viscosity of a given phase within - * the control volume. - */ - Scalar viscosity(const unsigned int phaseIdx) const - { return fluidState_.viscosity(phaseIdx); } - - /*! - * \brief Returns the relative permeability of a given phase within - * the control volume. - * - * \param phaseIdx The local index of the phases - */ - Scalar relativePermeability(const unsigned int phaseIdx) const - { return relativePermeability_[phaseIdx]; } - - /*! - * \brief Returns the average porosity within the control volume. - */ - Scalar porosity() const - { return porosity_; } - - /*! - * \brief Returns true iff the fluid state is in the active set - * for a phase, - * - * \param phaseIdx The local index of the phases - */ - bool isPhaseActive(const unsigned int phaseIdx) const - { - return - phasePresentIneq(fluidState(), phaseIdx) - - phaseNotPresentIneq(fluidState(), phaseIdx) - >= 0; - } - - /*! - * \brief Returns the value of the NCP-function for a phase. - * - * \param phaseIdx The local index of the phases - */ - Scalar phaseNcp(const unsigned int phaseIdx) const - { - Scalar aEval = phaseNotPresentIneq(this->evalPoint().fluidState(), phaseIdx); - Scalar bEval = phasePresentIneq(this->evalPoint().fluidState(), phaseIdx); - if (aEval > bEval) - return phasePresentIneq(fluidState(), phaseIdx); - return phaseNotPresentIneq(fluidState(), phaseIdx); - }; - - /*! - * \brief Returns the value of the inequality where a phase is - * present. - * - * \param phaseIdx The local index of the phases - * \param fluidState Container for all the secondary variables concerning the fluids - */ - Scalar phasePresentIneq(const FluidState &fluidState, - const unsigned int phaseIdx) const - { return fluidState.saturation(phaseIdx); } - - /*! - * \brief Returns the value of the inequality where a phase is not - * present. - * - * \param phaseIdx The local index of the phases - * \param fluidState Container for all the secondary variables concerning the fluids - */ - Scalar phaseNotPresentIneq(const FluidState &fluidState, - const unsigned int phaseIdx) const - { - // difference of sum of mole fractions in the phase from 100% - Scalar a = 1; - for (int compIdx = 0; compIdx < numComponents; ++compIdx) - a -= fluidState.moleFraction(phaseIdx, compIdx); - return a; - } - - /*! - * \brief If running in valgrind this makes sure that all - * quantities in the volume variables are defined. - */ - void checkDefined() const - { -#if !defined NDEBUG && HAVE_VALGRIND - ParentType::checkDefined(); - - Valgrind::CheckDefined(porosity_); - Valgrind::CheckDefined(hint_); - Valgrind::CheckDefined(relativePermeability_); - - fluidState_.checkDefined(); -#endif - } - -protected: - Scalar porosity_; //!< Effective porosity within the control volume - Scalar relativePermeability_[numPhases]; //!< Effective relative permeability within the control volume - - const Implementation *hint_; - - //! Mass fractions of each component within each phase - FluidState fluidState_; -}; - -} // end namespace +#include <dumux/porousmediumflow/mpnc/implicit/volumevariables.hh> #endif diff --git a/dumux/implicit/mpnc/mpncvolumevariablesia.hh b/dumux/implicit/mpnc/mpncvolumevariablesia.hh index c7bd81ab1e792e82250b9353685464227c4747f1..c2059b9eaa986999bf69a5a22d68bb01b38acc98 100644 --- a/dumux/implicit/mpnc/mpncvolumevariablesia.hh +++ b/dumux/implicit/mpnc/mpncvolumevariablesia.hh @@ -1,98 +1,8 @@ -// -*- 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 class contains the volume variables required for the - * modules which require the specific interfacial area between - * fluid phases. - */ -#ifndef DUMUX_MPNC_VOLUME_VARIABLES_IA_HH -#define DUMUX_MPNC_VOLUME_VARIABLES_IA_HH +#ifndef DUMUX_MPNC_VOLUME_VARIABLES_IA_HH_OLD +#define DUMUX_MPNC_VOLUME_VARIABLES_IA_HH_OLD -#include <dumux/implicit/mpnc/mpncproperties.hh> +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/volumevariablesia.hh instead -namespace Dumux -{ - -/*! - * \brief This class contains the volume variables required for the - * modules which require the specific interfacial area between - * fluid phases. - * - * This is the specialization for the cases which do _not_ require - * specific interfacial area. - */ -template <class TypeTag, bool enableKinetic, int numEnergyEquations> -class MPNCVolumeVariablesIA -{ - static_assert(not enableKinetic and not numEnergyEquations, - "The kinetic energy modules need specific interfacial area " - "but no suitable specialization of the IA volume variables module " - "has been included."); - - typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; - typedef typename FluidSystem::ParameterCache ParameterCache; - typedef typename GridView::template Codim<0>::Entity Element; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - enum {dimWorld=GridView::dimensionworld}; - typedef Dune::FieldVector<Scalar,dimWorld> GlobalPosition; - -public: - /*! - * \brief Updates the volume specific interfacial area [m^2 / m^3] between the phases. - * - * \param volVars The volume variables - * \param fluidState Container for all the secondary variables concerning the fluids - * \param paramCache Container for cache parameters - * \param priVars The primary Variables - * \param problem The problem - * \param element The finite element - * \param fvGeometry The finite-volume geometry in the fully implicit scheme - * \param scvIdx The index of the sub-control volumete element - * - */ - void update(const VolumeVariables & volVars, - const FluidState &fluidState, - const ParameterCache ¶mCache, - const PrimaryVariables &priVars, - const Problem &problem, - const Element & element, - const FVElementGeometry & fvGeometry, - const unsigned int scvIdx) - { - } - - /*! - * \brief If running in valgrind this makes sure that all - * quantities in the volume variables are defined. - */ - void checkDefined() const - { } -}; - -} // namespace Dumux +#include <dumux/porousmediumflow/mpnc/implicit/volumevariablesia.hh> #endif diff --git a/dumux/implicit/mpnc/mpncvolumevariablesiakinetic.hh b/dumux/implicit/mpnc/mpncvolumevariablesiakinetic.hh index b54f4489a8baf602dcabe3418db1023a8e1e7bd5..d1ab858dcb02972578a2b49c14c217df0f2fa5e4 100644 --- a/dumux/implicit/mpnc/mpncvolumevariablesiakinetic.hh +++ b/dumux/implicit/mpnc/mpncvolumevariablesiakinetic.hh @@ -1,624 +1,8 @@ -// -*- 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 class contains the volume variables required for the - * modules which require the specific interfacial area between - * fluid phases. - * - * This files contains all specializations which use 'real' - * interfacial areas. - */ -#ifndef DUMUX_MPNC_VOLUME_VARIABLES_IA_KINETIC_HH -#define DUMUX_MPNC_VOLUME_VARIABLES_IA_KINETIC_HH +#ifndef DUMUX_MPNC_VOLUME_VARIABLES_IA_KINETIC_HH_OLD +#define DUMUX_MPNC_VOLUME_VARIABLES_IA_KINETIC_HH_OLD -#include <dumux/common/dimensionlessnumbers.hh> -#include "mpncvolumevariablesia.hh" -#include "mpncpropertieskinetic.hh" +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/volumevariablesiakinetic.hh instead -namespace Dumux -{ - - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// specialization for the case of kinetic mass AND energy transfer -//////////////////////////////////////////////////////////////////////////////////////////////////// -template <class TypeTag, bool enableKinetic > -class MPNCVolumeVariablesIA<TypeTag, enableKinetic, /*numEnergyEqs=*/3> -{ - typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; - typedef typename FluidSystem::ParameterCache ParameterCache; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; - typedef typename GridView::template Codim<0>::Entity Element; - typedef typename GET_PROP_TYPE(TypeTag, MaterialLawParams) MaterialLawParams; - - - enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; - enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; - enum { wPhaseIdx = FluidSystem::wPhaseIdx }; - enum { nPhaseIdx = FluidSystem::nPhaseIdx }; - enum { sPhaseIdx = FluidSystem::sPhaseIdx }; - enum { nCompIdx = FluidSystem::nCompIdx } ; - enum { wCompIdx = FluidSystem::wCompIdx } ; - enum { dim = GridView::dimension}; - enum { dimWorld = GridView::dimensionworld}; - enum { numEnergyEqs = Indices::numPrimaryEnergyVars}; - enum { nusseltFormulation = GET_PROP_VALUE(TypeTag, NusseltFormulation)} ; - enum { sherwoodFormulation = GET_PROP_VALUE(TypeTag, SherwoodFormulation)} ; - enum { enableDiffusion = GET_PROP_VALUE(TypeTag, EnableDiffusion)} ; - - - typedef DimensionlessNumbers<Scalar> DimLessNum ; - - typedef Dune::FieldVector<Scalar,dimWorld> GlobalPosition; - - - typedef typename GET_PROP_TYPE(TypeTag, AwnSurface) AwnSurface; - typedef typename AwnSurface::Params AwnSurfaceParams; - - typedef typename GET_PROP_TYPE(TypeTag, AwsSurface) AwsSurface; - typedef typename AwsSurface::Params AwsSurfaceParams; - - typedef typename GET_PROP_TYPE(TypeTag, AnsSurface) AnsSurface; - typedef typename AnsSurface::Params AnsSurfaceParams; - - -public: - /*! - * \brief Updates the volume specific interfacial area [m^2 / m^3] between the phases. - */ - void update(const VolumeVariables & volVars, - const FluidState & fluidState, - const ParameterCache ¶mCache, - const PrimaryVariables &priVars, - const Problem &problem, - const Element & element, - const FVElementGeometry & fvGeometry, - const unsigned int scvIdx) - { - // obtain (standard) material parameters (needed for the residual saturations) - const MaterialLawParams & materialParams = problem.spatialParams().materialLawParams(element,fvGeometry,scvIdx); - - //obtain parameters for interfacial area constitutive relations - const AwnSurfaceParams & aWettingNonWettingSurfaceParams - = problem.spatialParams().aWettingNonWettingSurfaceParams(element,fvGeometry,scvIdx); - const AnsSurfaceParams & aNonWettingSolidSurfaceParams - = problem.spatialParams().aNonWettingSolidSurfaceParams(element,fvGeometry,scvIdx); - - Valgrind::CheckDefined(aWettingNonWettingSurfaceParams); - Valgrind::CheckDefined(aNonWettingSolidSurfaceParams); - - const Scalar pc = fluidState.pressure(nPhaseIdx) - fluidState.pressure(wPhaseIdx); - const Scalar Sw = fluidState.saturation(wPhaseIdx); - Valgrind::CheckDefined(Sw); - Valgrind::CheckDefined(pc); - Scalar awn; - -#define AwnRegul 0 - // This regularizes the interfacial area between the fluid phases. - // This makes sure, that - // a) some saturation cannot be lost: Never leave two phase region. - // b) We cannot leave the fit region: no crazy (e.g. negative) values possible -// const Scalar Swr = aWettingNonWettingSurfaceParams.Swr() ; -// const Scalar Snr = aWettingNonWettingSurfaceParams.Snr() ; - - // this just leads to a stalling newton error as soon as this kicks in. - // May be a spline or sth like this would help, but I do not which derivatives - // to specify. -#if AwnRegul - if(Sw < 5e-3 ) // or Sw > (1.-1e-5 ) - { - awn = 0. ; // 10.; // - } - else -#endif - awn = AwnSurface::interfacialArea(aWettingNonWettingSurfaceParams, materialParams, Sw, pc ); // 10.; // - - interfacialArea_[wPhaseIdx][nPhaseIdx] = awn ; //10. ;// - interfacialArea_[nPhaseIdx][wPhaseIdx] = interfacialArea_[wPhaseIdx][nPhaseIdx]; - interfacialArea_[wPhaseIdx][wPhaseIdx] = 0. ; - - Scalar ans = AnsSurface::interfacialArea(aNonWettingSolidSurfaceParams, materialParams,Sw, pc ); // 10.; // -// if (ans <0 ) -// ans = 0 ; - -// Switch for using a a_{wn} relations that has some "maximum capillary pressure" as parameter. -// That value is obtained by regularization of the pc(Sw) function. -#if USE_PCMAX - const Scalar pcMax = problem.spatialParams().pcMax(element, - fvGeometry, - scvIdx); - // I know the solid surface from the pore network. But it is more consistent to use the fit value. - // solidSurface_ = GET_RUNTIME_PARAM(TypeTag, Scalar, SpatialParams.soil.specificSolidsurface); - solidSurface_ = AnsSurface::interfacialArea(aNonWettingSolidSurfaceParams, materialParams, /*Sw=*/0., pcMax ); - Valgrind::CheckDefined(solidSurface_); - -// if (ans > solidSurface_){ -// const GlobalPosition & globalPos = fvGeometry.subContVol[scvIdx].global ; -// std::stringstream positionString ; -// positionString << " Here:"; -// for(int i=0; i<dim; i++) -// positionString << " x"<< (i+1) << "=" << globalPos[i] << " " ; -// positionString << "\n"; -// -// std::cout<<"a_{ns} > a_s, set a_{ns}=" << ans <<" to a_{ns}=a_s="<<solidSurface_ << " -// with S_w="<< Sw << " p_c= "<< pc << positionString.str() ; -// -// ans = solidSurface_ ; -// } - -#endif - - - interfacialArea_[nPhaseIdx][sPhaseIdx] = ans ; //10. ; // - interfacialArea_[sPhaseIdx][nPhaseIdx] = interfacialArea_[nPhaseIdx][sPhaseIdx]; - interfacialArea_[nPhaseIdx][nPhaseIdx] = 0. ; - -#if USE_PCMAX - const Scalar aws = solidSurface_ - ans ; - interfacialArea_[wPhaseIdx][sPhaseIdx] = aws ; //10. ; // - interfacialArea_[sPhaseIdx][wPhaseIdx] = interfacialArea_[wPhaseIdx][sPhaseIdx]; - interfacialArea_[sPhaseIdx][sPhaseIdx] = 0. ; -#else - const AwsSurfaceParams & aWettingSolidSurfaceParams - = problem.spatialParams().aWettingSolidSurfaceParams(); - Valgrind::CheckDefined(aWettingSolidSurfaceParams); - const Scalar aws = AwsSurface::interfacialArea(aWettingSolidSurfaceParams,materialParams, Sw, pc ); // 10.; // - interfacialArea_[wPhaseIdx][sPhaseIdx] = aws ; - interfacialArea_[sPhaseIdx][wPhaseIdx] = interfacialArea_[wPhaseIdx][sPhaseIdx]; - interfacialArea_[sPhaseIdx][sPhaseIdx] = 0. ; -#endif - - Valgrind::CheckDefined(interfacialArea_); - - factorMassTransfer_ = problem.spatialParams().factorMassTransfer(element, - fvGeometry, - scvIdx); - - factorEnergyTransfer_ = problem.spatialParams().factorEnergyTransfer(element, - fvGeometry, - scvIdx); - - characteristicLength_ = problem.spatialParams().characteristicLength(element, - fvGeometry, - scvIdx); - - // setting the dimensionless numbers. - // obtaining the respective quantities. - const unsigned int globalVertexIdx = problem.vertexMapper().subIndex(element, scvIdx, dim); - - for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { - const Scalar darcyMagVelocity = problem.model().volumeDarcyMagVelocity(phaseIdx, globalVertexIdx); - const Scalar dynamicViscosity = fluidState.viscosity(phaseIdx); - const Scalar density = fluidState.density(phaseIdx); - const Scalar kinematicViscosity = dynamicViscosity / density; - const Scalar heatCapacity = FluidSystem::heatCapacity(fluidState, paramCache, phaseIdx); - const Scalar thermalConductivity = FluidSystem::thermalConductivity(fluidState, paramCache, phaseIdx); - - - // diffusion coefficient of non-wetting component in wetting phase - const Scalar diffCoeff = volVars.diffCoeff(phaseIdx, wCompIdx, nCompIdx) ; - const Scalar porosity = problem.spatialParams().porosity(element, - fvGeometry, - scvIdx); - - reynoldsNumber_[phaseIdx] = DimLessNum::reynoldsNumber(darcyMagVelocity, - characteristicLength_, - kinematicViscosity); - - prandtlNumber_[phaseIdx] = DimLessNum::prandtlNumber(dynamicViscosity, - heatCapacity, - thermalConductivity); - - nusseltNumber_[phaseIdx] = DimLessNum::nusseltNumberForced(reynoldsNumber_[phaseIdx], - prandtlNumber_[phaseIdx], - porosity, - nusseltFormulation); - - schmidtNumber_[phaseIdx] = DimLessNum::schmidtNumber(dynamicViscosity, - density, - diffCoeff); - - // If Diffusion is not enabled, Sherwood is divided by zero - sherwoodNumber_[phaseIdx] = DimLessNum::sherwoodNumber(reynoldsNumber_[phaseIdx], - schmidtNumber_[phaseIdx], - sherwoodFormulation); - } - } - - /*! - * \brief The specific interfacial area between two fluid phases [m^2 / m^3] - * - * This is _only_ required by the kinetic mass/energy modules - * - */ - const Scalar interfacialArea(const unsigned int phaseIIdx, const unsigned int phaseJIdx) const - { - // there is no interfacial area between a phase and itself - assert(phaseIIdx not_eq phaseJIdx); - return interfacialArea_[phaseIIdx][phaseJIdx]; - } - - //! access function Reynolds Number - const Scalar reynoldsNumber(const unsigned int phaseIdx) const - { return reynoldsNumber_[phaseIdx]; } - - //! access function Prandtl Number - const Scalar prandtlNumber(const unsigned int phaseIdx) const - { return prandtlNumber_[phaseIdx]; } - - //! access function Nusselt Number - const Scalar nusseltNumber(const unsigned int phaseIdx) const - { return nusseltNumber_[phaseIdx]; } - - //! access function Schmidt Number - const Scalar schmidtNumber(const unsigned int phaseIdx) const - { return schmidtNumber_[phaseIdx]; } - - //! access function Sherwood Number - const Scalar sherwoodNumber(const unsigned int phaseIdx) const - { return sherwoodNumber_[phaseIdx]; } - - //! access function characteristic length - const Scalar characteristicLength() const - { return characteristicLength_; } - - //! access function pre factor energy transfer - const Scalar factorEnergyTransfer() const - { return factorEnergyTransfer_; } - - //! access function pre factor mass transfer - const Scalar factorMassTransfer() const - { return factorMassTransfer_; } - - /*! - * \brief If running in valgrind this makes sure that all - * quantities in the volume variables are defined. - */ - void checkDefined() const - { -#if !defined NDEBUG && HAVE_VALGRIND - Valgrind::CheckDefined(reynoldsNumber_); - Valgrind::CheckDefined(prandtlNumber_); - Valgrind::CheckDefined(nusseltNumber_); - Valgrind::CheckDefined(schmidtNumber_); - Valgrind::CheckDefined(sherwoodNumber_); - Valgrind::CheckDefined(characteristicLength_); - Valgrind::CheckDefined(factorEnergyTransfer_); - Valgrind::CheckDefined(factorMassTransfer_); - Valgrind::CheckDefined(interfacialArea_); -#endif - } - -private: - //! dimensionless numbers - Scalar reynoldsNumber_[numPhases]; - Scalar prandtlNumber_[numPhases]; - Scalar nusseltNumber_[numPhases]; - Scalar schmidtNumber_[numPhases]; - Scalar sherwoodNumber_[numPhases]; - Scalar characteristicLength_; - Scalar factorEnergyTransfer_; - Scalar factorMassTransfer_; - Scalar solidSurface_ ; - Scalar interfacialArea_[numPhases+1][numPhases+1]; -}; - - -///////////////////////////////////////////////////////////////////////////////////////////////////////////// -// specialization for the case of NO kinetic mass but kinteic energy transfer of a fluid mixture and solid -///////////////////////////////////////////////////////////////////////////////////////////////////////////// -template <class TypeTag> -class MPNCVolumeVariablesIA<TypeTag, /*enableKinetic=*/false, /*numEnergyEqs=*/2> -{ - typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; - typedef typename FluidSystem::ParameterCache ParameterCache; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; - typedef typename GridView::template Codim<0>::Entity Element; - - enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; - enum { dim = GridView::dimension}; - enum { dimWorld = GridView::dimensionworld}; - enum { numEnergyEqs = Indices::numPrimaryEnergyVars}; - enum { nusseltFormulation = GET_PROP_VALUE(TypeTag, NusseltFormulation)} ; - - typedef DimensionlessNumbers<Scalar> DimLessNum ; -public: - /*! - * \brief Updates the volume specific interfacial area [m^2 / m^3] between the phases. - */ - void update(const VolumeVariables & volVars, - const FluidState & fluidState, - const ParameterCache ¶mCache, - const PrimaryVariables &priVars, - const Problem &problem, - const Element & element, - const FVElementGeometry & fvGeometry, - const unsigned int scvIdx) - { - factorMassTransfer_ = problem.spatialParams().factorMassTransfer(element, - fvGeometry, - scvIdx); - - factorEnergyTransfer_ = problem.spatialParams().factorEnergyTransfer(element, - fvGeometry, - scvIdx); - - characteristicLength_ = problem.spatialParams().characteristicLength(element, - fvGeometry, - scvIdx); - - // setting the dimensionless numbers. - // obtaining the respective quantities. - const unsigned int globalVertexIdx = problem.vertexMapper().subIndex(element, scvIdx, dim); - - for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { - const Scalar darcyMagVelocity = problem.model().volumeDarcyMagVelocity(phaseIdx, globalVertexIdx); - const Scalar dynamicViscosity = fluidState.viscosity(phaseIdx); - const Scalar density = fluidState.density(phaseIdx); - const Scalar kinematicViscosity = dynamicViscosity / density; - const Scalar heatCapacity = FluidSystem::heatCapacity(fluidState, - paramCache, - phaseIdx); - const Scalar thermalConductivity = FluidSystem::thermalConductivity(fluidState, - paramCache, - phaseIdx); - - const Scalar porosity = problem.spatialParams().porosity(element, - fvGeometry, - scvIdx); - - reynoldsNumber_[phaseIdx] = DimLessNum::reynoldsNumber(darcyMagVelocity, - characteristicLength_, - kinematicViscosity); - - prandtlNumber_[phaseIdx] = DimLessNum::prandtlNumber(dynamicViscosity, - heatCapacity, - thermalConductivity); - - - nusseltNumber_[phaseIdx] = DimLessNum::nusseltNumberForced(reynoldsNumber_[phaseIdx], - prandtlNumber_[phaseIdx], - porosity, - nusseltFormulation); - } - } - - - //! access function Reynolds Number - const Scalar reynoldsNumber(const unsigned int phaseIdx) const - { return reynoldsNumber_[phaseIdx]; } - - //! access function Prandtl Number - const Scalar prandtlNumber(const unsigned int phaseIdx) const - { return prandtlNumber_[phaseIdx]; } - - //! access function Nusselt Number - const Scalar nusseltNumber(const unsigned int phaseIdx) const - { return nusseltNumber_[phaseIdx]; } - - //! access function characteristic length - const Scalar characteristicLength() const - { return characteristicLength_; } - - //! access function pre factor energy transfer - const Scalar factorEnergyTransfer() const - { return factorEnergyTransfer_; } - - //! access function pre factor mass transfer - const Scalar factorMassTransfer() const - { return factorMassTransfer_; } - - /*! - * \brief If running in valgrind this makes sure that all - * quantities in the volume variables are defined. - */ - void checkDefined() const - { -#if !defined NDEBUG && HAVE_VALGRIND - Valgrind::CheckDefined(reynoldsNumber_); - Valgrind::CheckDefined(prandtlNumber_); - Valgrind::CheckDefined(nusseltNumber_); - Valgrind::CheckDefined(characteristicLength_); - Valgrind::CheckDefined(factorEnergyTransfer_); - Valgrind::CheckDefined(factorMassTransfer_); -#endif - } - -private: - //! dimensionless numbers - Scalar reynoldsNumber_[numPhases]; - Scalar prandtlNumber_[numPhases]; - Scalar nusseltNumber_[numPhases]; - Scalar characteristicLength_; - Scalar factorEnergyTransfer_; - Scalar factorMassTransfer_; - Scalar solidSurface_ ; -}; - - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// specialization for the case of (only) kinetic mass transfer -//////////////////////////////////////////////////////////////////////////////////////////////////// -template <class TypeTag> -class MPNCVolumeVariablesIA<TypeTag, /*enableKinetic=*/true, /*numEnergyEqs=*/0> -{ - typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; - typedef typename FluidSystem::ParameterCache ParameterCache; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; - typedef typename GridView::template Codim<0>::Entity Element; - typedef DimensionlessNumbers<Scalar> DimLessNum; - - typedef typename GET_PROP_TYPE(TypeTag, AwnSurface) AwnSurface; - typedef typename AwnSurface::Params AwnSurfaceParams; - - enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; - enum { wPhaseIdx = FluidSystem::wPhaseIdx }; - enum { nPhaseIdx = FluidSystem::nPhaseIdx }; - enum { wCompIdx = FluidSystem::wCompIdx }; - enum { nCompIdx = FluidSystem::nCompIdx }; - enum { dim = GridView::dimension}; - enum { dimWorld = GridView::dimensionworld}; - enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; - enum { sherwoodFormulation = GET_PROP_VALUE(TypeTag, SherwoodFormulation)} ; - typedef Dune::FieldVector<Scalar,dimWorld> GlobalPosition; - typedef typename GET_PROP_TYPE(TypeTag, MaterialLawParams) MaterialLawParams; - - -public: - /*! - * \brief Updates the volume specific interfacial area [m^2 / m^3] between the phases. - */ - void update(const VolumeVariables & volVars, - const FluidState & fluidState, - const ParameterCache & paramCache, - const PrimaryVariables &priVars, - const Problem &problem, - const Element & element, - const FVElementGeometry & fvGeometry, - const unsigned int scvIdx) - { - //obtain parameters for awnsurface - const AwnSurfaceParams & awnSurfaceParams = problem.spatialParams().aWettingNonWettingSurfaceParams(element,fvGeometry,scvIdx) ; - - // obtain (standard) material parameters (needed for the residual saturations) - const MaterialLawParams & materialParams = problem.spatialParams().materialLawParams(element,fvGeometry,scvIdx) ; - - Valgrind::CheckDefined(awnSurfaceParams); - const Scalar Sw = fluidState.saturation(wPhaseIdx) ; - const Scalar pc = fluidState.pressure(nPhaseIdx) - fluidState.pressure(wPhaseIdx); - - // so far there is only a model for kinetic mass transfer between fluid phases - interfacialArea_ = AwnSurface::interfacialArea(awnSurfaceParams, materialParams, Sw, pc ); - - Valgrind::CheckDefined(interfacialArea_); - - factorMassTransfer_ = problem.spatialParams().factorMassTransfer(element, - fvGeometry, - scvIdx); - - characteristicLength_ = problem.spatialParams().characteristicLength(element, - fvGeometry, - scvIdx); - // setting the dimensionless numbers. - // obtaining the respective quantities. - int globalVertexIdx = problem.vertexMapper().subIndex(element, scvIdx, dim); - for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { - const Scalar darcyMagVelocity = problem.model().volumeDarcyMagVelocity(phaseIdx, globalVertexIdx); - const Scalar dynamicViscosity = fluidState.viscosity(phaseIdx); - const Scalar density = fluidState.density(phaseIdx); - const Scalar kinematicViscosity = dynamicViscosity / density; - - // diffusion coefficient of non-wetting component in wetting phase - const Scalar diffCoeff = volVars.diffCoeff(phaseIdx, wCompIdx, nCompIdx) ; - - reynoldsNumber_[phaseIdx] = DimLessNum::reynoldsNumber(darcyMagVelocity, - characteristicLength_, - kinematicViscosity); - - schmidtNumber_[phaseIdx] = DimLessNum::schmidtNumber(dynamicViscosity, - density, - diffCoeff); - - sherwoodNumber_[phaseIdx] = DimLessNum::sherwoodNumber(reynoldsNumber_[phaseIdx], - schmidtNumber_[phaseIdx], - sherwoodFormulation); - } - } - - /*! - * \brief The specific interfacial area between two fluid phases [m^2 / m^3] - */ - const Scalar interfacialArea(const unsigned int phaseIIdx, const unsigned int phaseJIdx) const - { - // so far there is only a model for kinetic mass transfer between fluid phases - assert((phaseIIdx == nPhaseIdx and phaseJIdx == wPhaseIdx) or (phaseIIdx == wPhaseIdx and phaseJIdx == nPhaseIdx) ); - return interfacialArea_; - } - - //! access function Reynolds Number - const Scalar reynoldsNumber(const unsigned int phaseIdx) const - { return reynoldsNumber_[phaseIdx]; } - - //! access function Schmidt Number - const Scalar schmidtNumber(const unsigned int phaseIdx) const - { return schmidtNumber_[phaseIdx]; } - - //! access function Sherwood Number - const Scalar sherwoodNumber(const unsigned int phaseIdx) const - { return sherwoodNumber_[phaseIdx]; } - - //! access function characteristic length - const Scalar characteristicLength() const - { return characteristicLength_; } - - //! access function pre factor mass transfer - const Scalar factorMassTransfer() const - { return factorMassTransfer_; } - - /*! - * \brief If running in valgrind this makes sure that all - * quantities in the volume variables are defined. - */ - void checkDefined() const - { - Valgrind::CheckDefined(interfacialArea_); - Valgrind::CheckDefined(characteristicLength_); - Valgrind::CheckDefined(factorMassTransfer_); - Valgrind::CheckDefined(reynoldsNumber_); - Valgrind::CheckDefined(schmidtNumber_); - Valgrind::CheckDefined(sherwoodNumber_); - } - -private: - Scalar characteristicLength_; - Scalar factorMassTransfer_; - Scalar solidSurface_ ; - Scalar interfacialArea_ ; - Scalar sherwoodNumber_[numPhases] ; - Scalar schmidtNumber_[numPhases] ; - Scalar reynoldsNumber_[numPhases] ; -}; - - - -} // namespace Dumux +#include <dumux/porousmediumflow/mpnc/implicit/volumevariablesiakinetic.hh> #endif diff --git a/dumux/implicit/mpnc/mpncvtkwriter.hh b/dumux/implicit/mpnc/mpncvtkwriter.hh index a9389f7b47b69a34ccbd44697bd51d145e5d6436..9231e883e58ea46f0e554055a8ecae21bed2ec08 100644 --- a/dumux/implicit/mpnc/mpncvtkwriter.hh +++ b/dumux/implicit/mpnc/mpncvtkwriter.hh @@ -1,130 +1,8 @@ -// -*- 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 Writes the VTK output files for a solution of the MpNc model. - */ +#ifndef DUMUX_MPNC_VTK_WRITER_HH_OLD +#define DUMUX_MPNC_VTK_WRITER_HH_OLD -#ifndef DUMUX_MPNC_VTK_WRITER_HH -#define DUMUX_MPNC_VTK_WRITER_HH +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/vtkwriter.hh instead -#include "mpncproperties.hh" - -#include <dumux/io/vtkmultiwriter.hh> - -namespace Dumux -{ -/*! - * \ingroup MPNCModel - * \brief Writes the VTK output files for a - * solution of the MpNc model. - */ -template<class TypeTag> -class MPNCVtkWriter -{ - typedef typename GET_PROP_TYPE(TypeTag, MPNCVtkCommonModule) MPNCVtkCommonModule; - typedef typename GET_PROP_TYPE(TypeTag, MPNCVtkMassModule) MPNCVtkMassModule; - typedef typename GET_PROP_TYPE(TypeTag, MPNCVtkEnergyModule) MPNCVtkEnergyModule; - typedef typename GET_PROP_TYPE(TypeTag, MPNCVtkCustomModule) MPNCVtkCustomModule; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes; - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - -public: - MPNCVtkWriter(const Problem &problem) - : problem_(problem) - , commonWriter_(problem) - , massWriter_(problem) - , energyWriter_(problem) - , customWriter_(problem) - { - } - - /*! - * \brief Add the current solution to the VtkMultiWriter. - */ - template <class MultiWriter> - void addCurrentSolution(MultiWriter &writer) - { - // tell sub-writers to allocate their buffers - commonWriter_.allocBuffers(writer); - massWriter_.allocBuffers(writer); - energyWriter_.allocBuffers(writer); - customWriter_.allocBuffers(writer); - - // iterate over grid - FVElementGeometry fvGeometry; - ElementVolumeVariables elemVolVars; - ElementBoundaryTypes elemBcTypes; - - for (const auto& element : Dune::elements(problem_.gridView())) - { - if(element.partitionType() == Dune::InteriorEntity) - { - fvGeometry.update(problem_.gridView(), element); - elemBcTypes.update(problem_, element); - this->problem_.model().setHints(element, elemVolVars); - elemVolVars.update(problem_, - element, - fvGeometry, - false); - this->problem_.model().updateCurHints(element, elemVolVars); - - // tell the sub-writers to do what ever they need to with - // their internal buffers when a given element is seen. - commonWriter_.processElement(element, - fvGeometry, - elemVolVars, - elemBcTypes); - massWriter_.processElement(element, - fvGeometry, - elemVolVars, - elemBcTypes); - energyWriter_.processElement(element, - fvGeometry, - elemVolVars, - elemBcTypes); - customWriter_.processElement(element, - fvGeometry, - elemVolVars, - elemBcTypes); - } - } - - // write everything to the output file - commonWriter_.commitBuffers(writer); - massWriter_.commitBuffers(writer); - energyWriter_.commitBuffers(writer); - customWriter_.commitBuffers(writer); - } - -private: - const Problem &problem_; - - MPNCVtkCommonModule commonWriter_; - MPNCVtkMassModule massWriter_; - MPNCVtkEnergyModule energyWriter_; - MPNCVtkCustomModule customWriter_; -}; - -} +#include <dumux/porousmediumflow/mpnc/implicit/vtkwriter.hh> #endif diff --git a/dumux/implicit/mpnc/mpncvtkwritercommon.hh b/dumux/implicit/mpnc/mpncvtkwritercommon.hh index 95afe1fbb629549f380b4c891d3bd7678a72854d..48826190d8eddb2e48737d4f264cf283e5a93ef1 100644 --- a/dumux/implicit/mpnc/mpncvtkwritercommon.hh +++ b/dumux/implicit/mpnc/mpncvtkwritercommon.hh @@ -1,256 +1,8 @@ -// -*- 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 VTK writer module for the common quantities of the MpNc - * model. - */ -#ifndef DUMUX_MPNC_VTK_WRITER_COMMON_HH -#define DUMUX_MPNC_VTK_WRITER_COMMON_HH +#ifndef DUMUX_MPNC_VTK_WRITER_COMMON_HH_OLD +#define DUMUX_MPNC_VTK_WRITER_COMMON_HH_OLD -#include <dumux/porousmediumflow/implicit/velocityoutput.hh> -#include "mpncvtkwritermodule.hh" +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/vtkwritercommon.hh instead -namespace Dumux -{ -/*! - * \ingroup MPNCModel - * - * \brief VTK writer module for the common quantities of the MpNc - * model. - */ -template<class TypeTag> -class MPNCVtkWriterCommon : public MPNCVtkWriterModule<TypeTag> -{ - typedef MPNCVtkWriterModule<TypeTag> ParentType; - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes; - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GridView::template Codim<0>::Entity Element; - typedef typename ParentType::ScalarVector ScalarVector; - typedef typename ParentType::PhaseVector PhaseVector; - typedef typename ParentType::ComponentVector ComponentVector; - typedef typename ParentType::PhaseComponentMatrix PhaseComponentMatrix; - - enum { dim = GridView::dimension }; - enum { dimWorld = GridView::dimensionworld }; - enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; - enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; - enum { numEq = GET_PROP_VALUE(TypeTag, NumEq) }; - - typedef Dune::FieldVector<Scalar, dimWorld> DimWorldVector; - typedef Dune::BlockVector<DimWorldVector> DimWorldField; - typedef std::array<DimWorldField, numPhases> PhaseDimWorldField; - enum { isBox = GET_PROP_VALUE(TypeTag, ImplicitIsBox) }; - enum { dofCodim = isBox ? dim : 0 }; - -public: - MPNCVtkWriterCommon(const Problem &problem) - : ParentType(problem), velocityOutput_(problem) - { - porosityOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddPorosity); - permeabilityOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddPermeability); - boundaryTypesOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddBoundaryTypes); - saturationOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddSaturations); - pressureOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddPressures); - densityOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddDensities); - mobilityOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddMobilities); - averageMolarMassOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddAverageMolarMass); - massFracOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddMassFractions); - moleFracOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddMoleFractions); - molarityOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddMolarities); - } - - /*! - * \brief Allocate memory for the scalar fields we would like to - * write to the VTK file. - */ - template <class MultiWriter> - void allocBuffers(MultiWriter &writer) - { - if (porosityOutput_) - this->resizeScalarBuffer_(porosity_, isBox); - if (permeabilityOutput_) - this->resizeScalarBuffer_(permeability_); - if (boundaryTypesOutput_) - this->resizeScalarBuffer_(boundaryTypes_, isBox); - - if (velocityOutput_.enableOutput()) { - Scalar numDofs = this->problem_.model().numDofs(); - for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { - velocity_[phaseIdx].resize(numDofs); - velocity_[phaseIdx] = 0; - } - } - - if (saturationOutput_) this->resizePhaseBuffer_(saturation_, isBox); - if (pressureOutput_) this->resizePhaseBuffer_(pressure_, isBox); - if (densityOutput_) this->resizePhaseBuffer_(density_, isBox); - if (mobilityOutput_) this->resizePhaseBuffer_(mobility_, isBox); - if (averageMolarMassOutput_) this->resizePhaseBuffer_(averageMolarMass_, isBox); - if (moleFracOutput_) this->resizePhaseComponentBuffer_(moleFrac_, isBox); - if (massFracOutput_) this->resizePhaseComponentBuffer_(massFrac_, isBox); - if (molarityOutput_) this->resizePhaseComponentBuffer_(molarity_, isBox); - } - - /*! - * \brief Modify the internal buffers according to the volume - * variables seen on an element - * - * \param element The finite element - * \param fvGeometry The finite-volume geometry in the fully implicit scheme - * \param elemVolVars The volume variables of the current element - * \param elemBcTypes The types of the boundary conditions for all vertices of the element - */ - void processElement(const Element &element, - const FVElementGeometry &fvGeometry, - const ElementVolumeVariables &elemVolVars, - const ElementBoundaryTypes &elemBcTypes) - { - for (int scvIdx = 0; scvIdx < fvGeometry.numScv; ++scvIdx) - { - int dofIdxGlobal = this->problem_.model().dofMapper().subIndex(element, scvIdx, dofCodim); - - const VolumeVariables &volVars = elemVolVars[scvIdx]; - - if (porosityOutput_) porosity_[dofIdxGlobal] = volVars.porosity(); - - // works for scalar permeability in spatialparameters - if (permeabilityOutput_) permeability_[dofIdxGlobal] = this->problem_.spatialParams().intrinsicPermeability(element,fvGeometry,scvIdx); - - // calculate a single value for the boundary type: use one - // bit for each equation and set it to 1 if the equation - // is used for a dirichlet condition - int tmp = 0; - for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) { - if (elemBcTypes[scvIdx].isDirichlet(eqIdx)) - tmp += (1 << eqIdx); - } - if (boundaryTypesOutput_) boundaryTypes_[dofIdxGlobal] = tmp; - - for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { - if (saturationOutput_) saturation_[phaseIdx][dofIdxGlobal] = volVars.fluidState().saturation(phaseIdx); - if (pressureOutput_) pressure_[phaseIdx][dofIdxGlobal] = volVars.fluidState().pressure(phaseIdx); - if (densityOutput_) density_[phaseIdx][dofIdxGlobal] = volVars.fluidState().density(phaseIdx); - if (mobilityOutput_) mobility_[phaseIdx][dofIdxGlobal] = volVars.mobility(phaseIdx); - if (averageMolarMassOutput_) averageMolarMass_[phaseIdx][dofIdxGlobal] = volVars.fluidState().averageMolarMass(phaseIdx); - for (int compIdx = 0; compIdx < numComponents; ++compIdx) { - if (moleFracOutput_) moleFrac_[phaseIdx][compIdx][dofIdxGlobal] = volVars.fluidState().moleFraction(phaseIdx, compIdx); - if (massFracOutput_) massFrac_[phaseIdx][compIdx][dofIdxGlobal] = volVars.fluidState().massFraction(phaseIdx, compIdx); - if (molarityOutput_) molarity_[phaseIdx][compIdx][dofIdxGlobal] = volVars.fluidState().molarity(phaseIdx, compIdx); - } - } - } - - // velocity output - for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { - velocityOutput_.calculateVelocity(velocity_[phaseIdx], elemVolVars, fvGeometry, element, phaseIdx); - } - } - - /*! - * \brief Add all buffers to the VTK output writer. - */ - template <class MultiWriter> - void commitBuffers(MultiWriter &writer) - { - if (saturationOutput_) - this->commitPhaseBuffer_(writer, "S_%s", saturation_, isBox); - - if (pressureOutput_) - this->commitPhaseBuffer_(writer, "p_%s", pressure_, isBox); - - if (densityOutput_) - this->commitPhaseBuffer_(writer, "rho_%s", density_, isBox); - - if (averageMolarMassOutput_) - this->commitPhaseBuffer_(writer, "M_%s", averageMolarMass_, isBox); - - if (mobilityOutput_) - this->commitPhaseBuffer_(writer, "lambda_%s", mobility_, isBox); - - if (porosityOutput_) - this->commitScalarBuffer_(writer, "porosity", porosity_, isBox); - - if (boundaryTypesOutput_) - this->commitScalarBuffer_(writer, "boundary types", boundaryTypes_, isBox); - - if (moleFracOutput_) - this->commitPhaseComponentBuffer_(writer, "x_%s^%s", moleFrac_, isBox); - - if (massFracOutput_) - this->commitPhaseComponentBuffer_(writer, "X_%s^%s", massFrac_, isBox); - - if(molarityOutput_) - this->commitPhaseComponentBuffer_(writer, "c_%s^%s", molarity_, isBox); - - if (velocityOutput_.enableOutput()) { - for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { - std::ostringstream oss; - oss << "velocity_" << FluidSystem::phaseName(phaseIdx); - writer.attachDofData(velocity_[phaseIdx], - oss.str(), isBox, dim); - } - } - } - -private: - bool porosityOutput_; - bool permeabilityOutput_ ; - bool boundaryTypesOutput_; - bool saturationOutput_; - bool pressureOutput_; - bool densityOutput_; - bool mobilityOutput_; - bool massFracOutput_; - bool moleFracOutput_; - bool molarityOutput_; - bool averageMolarMassOutput_; - - PhaseVector saturation_; - PhaseVector pressure_; - PhaseVector density_; - PhaseVector mobility_; - PhaseVector averageMolarMass_; - - PhaseDimWorldField velocity_; - - ScalarVector porosity_; - ScalarVector permeability_; - ScalarVector temperature_; - ScalarVector boundaryTypes_; - - PhaseComponentMatrix moleFrac_; - PhaseComponentMatrix massFrac_; - PhaseComponentMatrix molarity_; - - ComponentVector fugacity_; - - ImplicitVelocityOutput<TypeTag> velocityOutput_; -}; - -} +#include <dumux/porousmediumflow/mpnc/implicit/vtkwritercommon.hh> #endif diff --git a/dumux/implicit/mpnc/mpncvtkwritermodule.hh b/dumux/implicit/mpnc/mpncvtkwritermodule.hh index 9be4de867b8cdedc927e94538784fa9686d75304..d8e9d73970831aba3e193ce76ce8a830f0f5f2ae 100644 --- a/dumux/implicit/mpnc/mpncvtkwritermodule.hh +++ b/dumux/implicit/mpnc/mpncvtkwritermodule.hh @@ -1,263 +1,8 @@ -// -*- 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 A VTK writer module which adheres to the required API but - * does nothing. - */ +#ifndef DUMUX_MPNC_VTK_BASE_WRITER_HH_OLD +#define DUMUX_MPNC_VTK_BASE_WRITER_HH_OLD -#ifndef DUMUX_MPNC_VTK_BASE_WRITER_HH -#define DUMUX_MPNC_VTK_BASE_WRITER_HH +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/vtkwritermodule.hh instead -#include <array> -#include <cstdio> - -#include <dune/istl/bvector.hh> - -#include <dumux/io/vtkmultiwriter.hh> -#include "mpncproperties.hh" - -namespace Dumux -{ -/*! - * \ingroup MPNCModel - * - * \brief A VTK writer module which adheres to the required API but - * does nothing. - * - * This class also provides some convenience methods for buffer - * management. - */ -template<class TypeTag> -class MPNCVtkWriterModule -{ - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes; - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - typedef typename GridView::template Codim<0>::Entity Element; - - enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; - enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; - enum { dim = GridView::dimension }; - -public: - typedef std::vector<Dune::FieldVector<Scalar, 1> > ScalarVector; - typedef std::array<ScalarVector, numPhases> PhaseVector; - typedef std::array<ScalarVector, numComponents> ComponentVector; - typedef std::array<ComponentVector, numPhases> PhaseComponentMatrix; - - MPNCVtkWriterModule(const Problem &problem) - : problem_(problem) - { - } - - /*! - * \brief Allocate memory for the scalar fields we would like to - * write to the VTK file. - */ - template <class MultiWriter> - void allocBuffers(MultiWriter &writer) - { - } - - /*! - * \brief Modify the internal buffers according to the volume - * variables seen on an element - */ - void processElement(const Element &element, - const FVElementGeometry &fvGeometry, - const ElementVolumeVariables &elemCurVolVars, - const ElementBoundaryTypes &elemBcTypes) - { - } - - /*! - * \brief Add all buffers to the VTK output writer. - */ - template <class MultiWriter> - void commitBuffers(MultiWriter &writer) - { - } - -protected: - /*! - * \brief Allocate the space for a buffer storing a scalar quantity - */ - void resizeScalarBuffer_(ScalarVector &buffer, - bool vertexCentered = true) - { - Scalar n; // numVertices for vertexCentereed, numVolumes for volume centered - if (vertexCentered) - n = problem_.gridView().size(dim); - else - n = problem_.gridView().size(0); - - buffer.resize(n); - std::fill(buffer.begin(), buffer.end(), 0.0); - } - - /*! - * \brief Allocate the space for a buffer storing a phase-specific - * quantity - */ - void resizePhaseBuffer_(PhaseVector &buffer, - bool vertexCentered = true) - { - Scalar n; // numVertices for vertexCentereed, numVolumes for volume centered - if (vertexCentered) - n = problem_.gridView().size(dim); - else - n = problem_.gridView().size(0); - - for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { - buffer[phaseIdx].resize(n); - std::fill(buffer[phaseIdx].begin(), buffer[phaseIdx].end(), 0.0); - } - } - - /*! - * \brief Allocate the space for a buffer storing a component - * specific quantity - */ - void resizeComponentBuffer_(ComponentVector &buffer, - bool vertexCentered = true) - { - Scalar n;// numVertices for vertexCentereed, numVolumes for volume centered - if (vertexCentered) - n = problem_.gridView().size(dim); - else - n = problem_.gridView().size(0); - - for (int compIdx = 0; compIdx < numComponents; ++compIdx) { - buffer[compIdx].resize(n); - std::fill(buffer[compIdx].begin(), buffer[compIdx].end(), 0.0); - } - } - - /*! - * \brief Allocate the space for a buffer storing a phase and - * component specific buffer - */ - void resizePhaseComponentBuffer_(PhaseComponentMatrix &buffer, - bool vertexCentered = true) - { - Scalar n;// numVertices for vertexCentereed, numVolumes for volume centered - if (vertexCentered) - n = problem_.gridView().size(dim); - else - n = problem_.gridView().size(0); - - for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { - for (int compIdx = 0; compIdx < numComponents; ++compIdx) { - buffer[phaseIdx][compIdx].resize(n); - std::fill(buffer[phaseIdx][compIdx].begin(), buffer[phaseIdx][compIdx].end(), 0.0); - } - } - } - - /*! - * \brief Add a phase-specific buffer to the VTK result file. - */ - template <class MultiWriter> - void commitScalarBuffer_(MultiWriter &writer, - const char *name, - ScalarVector &buffer, - bool vertexCentered = true) - { - if (vertexCentered) - writer.attachVertexData(buffer, name, 1); - else - writer.attachCellData(buffer, name, 1); - } - - /*! - * \brief Add a phase-specific buffer to the VTK result file. - */ - template <class MultiWriter> - void commitPhaseBuffer_(MultiWriter &writer, - const char *pattern, - PhaseVector &buffer, - bool vertexCentered = true) - { - char name[512]; - for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { - snprintf(name, 512, pattern, FluidSystem::phaseName(phaseIdx)); - - if (vertexCentered) - writer.attachVertexData(buffer[phaseIdx], name, 1); - else - writer.attachCellData(buffer[phaseIdx], name, 1); - } - } - - /*! - * \brief Add a component-specific buffer to the VTK result file. - */ - template <class MultiWriter> - void commitComponentBuffer_(MultiWriter &writer, - const char *pattern, - ComponentVector &buffer, - bool vertexCentered = true) - { - char name[512]; - for (int compIdx = 0; compIdx < numComponents; ++compIdx) { - snprintf(name, 512, pattern, FluidSystem::componentName(compIdx)); - - if (vertexCentered) - writer.attachVertexData(buffer[compIdx], name, 1); - else - writer.attachCellData(buffer[compIdx], name, 1); - } - } - - /*! - * \brief Add a phase and component specific quantities to the output. - */ - template <class MultiWriter> - void commitPhaseComponentBuffer_(MultiWriter &writer, - const char *pattern, - PhaseComponentMatrix &buffer, - bool vertexCentered = true) - { - char name[512]; - for (int phaseIdx= 0; phaseIdx < numPhases; ++phaseIdx) { - for (int compIdx = 0; compIdx < numComponents; ++compIdx) { - snprintf(name, 512, pattern, - FluidSystem::phaseName(phaseIdx), - FluidSystem::componentName(compIdx)); - - if (vertexCentered) - writer.attachVertexData(buffer[phaseIdx][compIdx], name, 1); - else - writer.attachCellData(buffer[phaseIdx][compIdx], name, 1); - } - } - } - - const Problem &problem_; -}; - -} +#include <dumux/porousmediumflow/mpnc/implicit/vtkwritermodule.hh> #endif diff --git a/dumux/implicit/mpnc/velomodelnewtoncontroller.hh b/dumux/implicit/mpnc/velomodelnewtoncontroller.hh index 46e15c703c2c1335ad8a38de1189368edcb47019..4734b3ade1a09ffb7c31f353a13ed66d160ff5b1 100644 --- a/dumux/implicit/mpnc/velomodelnewtoncontroller.hh +++ b/dumux/implicit/mpnc/velomodelnewtoncontroller.hh @@ -1,76 +1,8 @@ -// -*- 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 A MpNc specific controller for the newton solver. - * - * This controller calls the velocity averaging in the model after each iteration. - */ -#ifndef DUMUX_VELO_MODEL_NEWTON_CONTROLLER_HH -#define DUMUX_VELO_MODEL_NEWTON_CONTROLLER_HH +#ifndef DUMUX_VELO_MODEL_NEWTON_CONTROLLER_HH_OLD +#define DUMUX_VELO_MODEL_NEWTON_CONTROLLER_HH_OLD -#include <algorithm> +#warning this header is deprecated, use dumux/porousmediumflow/mpnc/implicit/velomodelnewtoncontroller.hh instead -#include <dumux/nonlinear/newtoncontroller.hh> -#include "mpncnewtoncontroller.hh" -#include "mpncproperties.hh" +#include <dumux/porousmediumflow/mpnc/implicit/velomodelnewtoncontroller.hh> -namespace Dumux { -/*! - * \brief A kinetic-MpNc specific controller for the newton solver. - * - * This controller calls the velocity averaging in the problem after each iteration. - * - * Everything else is taken from the standard mpnc newtoncontroller. - */ -template <class TypeTag> -class VeloModelNewtonController : public MPNCNewtonController<TypeTag> -{ - typedef MPNCNewtonController<TypeTag> ParentType; - typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector; - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - - enum {velocityAveragingInModel = GET_PROP_VALUE(TypeTag, VelocityAveragingInModel)}; - -public: - VeloModelNewtonController(const Problem &problem) - : ParentType(problem) - {}; - - void newtonBeginStep(){ - ParentType::newtonBeginStep(); - - // Averages the face velocities of a vertex. Implemented in the model. - // The velocities are stored in the model. - if(velocityAveragingInModel) - this->problem_().model().calcVelocityAverage(); - } - - void newtonUpdate(SolutionVector &uCurrentIter, - const SolutionVector &uLastIter, - const SolutionVector &deltaU) - { - ParentType::newtonUpdate(uCurrentIter, - uLastIter, - deltaU); - } -}; - -} // end namespace Dumux -#endif // DUMUX_VELO_PROB_AVERAGE_NEWTON_CONTROLLER_HH +#endif diff --git a/dumux/material/fluidmatrixinteractions/2p/thermalconductivitysimplefluidlumping.hh b/dumux/material/fluidmatrixinteractions/2p/thermalconductivitysimplefluidlumping.hh index 140e1b358798631ffaa2a5b7d85bd7d80e94d375..9f3377b91f683f4514d2c35d1fb3afba1a41dc7e 100644 --- a/dumux/material/fluidmatrixinteractions/2p/thermalconductivitysimplefluidlumping.hh +++ b/dumux/material/fluidmatrixinteractions/2p/thermalconductivitysimplefluidlumping.hh @@ -25,7 +25,7 @@ #define THERMALCONDUCTIVITY_SIMPLE_FLUID_LUMPING_HH #include <algorithm> -#include <dumux/implicit/mpnc/mpncproperties.hh> +#include <dumux/porousmediumflow/mpnc/implicit/properties.hh> namespace Dumux { diff --git a/dumux/porousmediumflow/mpnc/implicit/diffusion/diffusion.hh b/dumux/porousmediumflow/mpnc/implicit/diffusion/diffusion.hh new file mode 100644 index 0000000000000000000000000000000000000000..867f9fc677aa2a99b1d642f5d68465d6d8e47d9b --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/diffusion/diffusion.hh @@ -0,0 +1,200 @@ +// -*- 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 parts to calculate the diffusive flux in + * the fully coupled MpNc model + */ +#ifndef DUMUX_MPNC_DIFFUSION_HH +#define DUMUX_MPNC_DIFFUSION_HH + +#include <dune/common/float_cmp.hh> +#include <dune/common/fmatrix.hh> +#include <dune/common/fvector.hh> + + +#include <dumux/porousmediumflow/mpnc/implicit/properties.hh> + +namespace Dumux { +/*! + * \brief Calculates the diffusive flux in the fully coupled MpNc model. + * Called from the mass module. + */ +template <class TypeTag, bool enableDiffusion> +class MPNCDiffusion +{ + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + + enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents)}; + enum { nPhaseIdx = FluidSystem::nPhaseIdx }; + enum { wPhaseIdx = FluidSystem::wPhaseIdx }; + enum { nCompIdx = FluidSystem::nCompIdx }; + + typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; + typedef Dune::FieldMatrix<Scalar, numComponents, numComponents> ComponentMatrix; + typedef Dune::FieldVector<Scalar, numComponents> ComponentVector; + +public: + + /*! + * \brief Calls the function for the diffusion in the gas and liquid phases, respectively. + * + * In the gas phase, the mutual influence of mole fractions can be considered. + * + * \param fluxes The Diffusive flux over the sub-control-volume face for each component + * \param phaseIdx The index of the phase we are calculating the diffusive flux for + * \param fluxVars The flux variables at the current sub control volume face + * \param molarDensity The (molar) density of the phase + */ + static void flux(ComponentVector &fluxes, + const unsigned int phaseIdx, + const FluxVariables &fluxVars, + const Scalar molarDensity ) + { + if ( not FluidSystem::isLiquid(phaseIdx) ) + gasFlux_(fluxes, fluxVars, molarDensity); + else if ( FluidSystem::isLiquid(phaseIdx) ){ + #if MACROSCALE_DIFFUSION_ONLY_GAS + return ; // in the case that only the diffusion in the gas phase is considered, + // the liquidFlux should not be called + #endif + liquidFlux_(fluxes, fluxVars, molarDensity); + } + else + DUNE_THROW(Dune::InvalidStateException, + "Invalid phase index: " << phaseIdx); + } + +protected: + + /*! + * \brief Calculates the diffusive flux in the liquid phase: only Fick diffusion (no mutual influence) is considered. + * + * \param fluxes The Diffusive flux over the sub-control-volume face for each component + * \param fluxVars The flux variables at the current sub control volume face + * \param molarDensity The (molar) density of the phase + */ + static void liquidFlux_(ComponentVector &fluxes, + const FluxVariables &fluxVars, + const Scalar molarDensity) + { + for (int compIdx = 0; compIdx < numComponents; ++compIdx) { + // TODO: tensorial diffusion coefficients + const Scalar xGrad = fluxVars.moleFractionGrad(wPhaseIdx, compIdx)*fluxVars.face().normal; + fluxes[compIdx] = + - xGrad * + molarDensity * + fluxVars.porousDiffCoeffL(compIdx) ; + } + } + + /*! + * \brief Calculates the diffusive flux in the gas phase: + * The property UseMaxwellDiffusion selects whether Maxwell or Fick diffusion is applied. + * Has to be the same for a 2-component system. However, Maxwells does not work always. + * + * \param fluxes The Diffusive flux over the sub-control-volume face for each component + * \param fluxVars The flux variables at the current sub control volume face + * \param molarDensity The (molar) density of the phase + * + * Reid et al. (1987, p. 596) \cite reid1987 <BR> + */ + static void gasFlux_(ComponentVector &fluxes, + const FluxVariables &fluxVars, + const Scalar molarDensity) + { + // Alternative: use Fick Diffusion: no mutual influence of diffusion + if (GET_PROP_VALUE(TypeTag, UseMaxwellDiffusion) ){ + // Stefan-Maxwell equation + // + // See: R. Reid, et al.: "The Properties of Liquids and + // Gases", 4th edition, 1987, McGraw-Hill, p 596 + + // TODO: tensorial diffusion coefficients + ComponentMatrix M(0); + + for (int compIIdx = 0; compIIdx < numComponents - 1; ++compIIdx) { + for (int compJIdx = 0; compJIdx < numComponents; ++compJIdx) { + Scalar Dij = fluxVars.porousDiffCoeffG(compIIdx, compJIdx); + if (Dune::FloatCmp::ne<Scalar, Dune::FloatCmp::absolute>(Dij, 0.0, 1.0e-30)) { + M[compIIdx][compJIdx] += fluxVars.moleFraction(nPhaseIdx, compIIdx) / Dij; + M[compIIdx][compIIdx] -= fluxVars.moleFraction(nPhaseIdx, compJIdx) / Dij; + } + } + } + + for (int compIIdx = 0; compIIdx < numComponents; ++compIIdx) { + M[numComponents - 1][compIIdx] = 1.0; + } + + ComponentVector rightHandSide ; // see source cited above + for (int compIIdx = 0; compIIdx < numComponents - 1; ++compIIdx) { + rightHandSide[compIIdx] = molarDensity*(fluxVars.moleFractionGrad(nPhaseIdx, compIIdx)*fluxVars.face().normal); + } + rightHandSide[numComponents - 1] = 0.0; + + M.solve(fluxes, rightHandSide); + } + else{// Fick Diffusion + for (int compIdx = 0; compIdx < numComponents; ++compIdx) { + // TODO: tensorial diffusion coefficients + const Scalar xGrad = fluxVars.moleFractionGrad(nPhaseIdx, compIdx)*fluxVars.face().normal; + fluxes[compIdx] = + - xGrad * + molarDensity + * fluxVars.porousDiffCoeffG(compIdx, nCompIdx) ; // this is == 0 for nComp==comp, + // i.e. no diffusion of the main component of the phase + } + } + } + + // return whether a concentration can be assumed to be a trace + // component in the context of diffusion + static Scalar isTraceComp_(Scalar x) + { return x < 0.5/numComponents; } +}; + +/*! + * \brief Specialization of the diffusion module for the case where + * diffusion is disabled. + * + * This class just does nothing. + */ +template <class TypeTag> +class MPNCDiffusion<TypeTag, false> +{ + enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; + + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; + typedef Dune::FieldVector<Scalar, numComponents> ComponentVector; + +public: + static void flux(ComponentVector &fluxes, + const unsigned int phaseIdx, + const FluxVariables &fluxVars, + const Scalar molarDensity) + { fluxes = 0; } +}; + +} + +#endif // DUMUX_MPNC_DIFFUSION_HH diff --git a/dumux/porousmediumflow/mpnc/implicit/diffusion/fluxvariables.hh b/dumux/porousmediumflow/mpnc/implicit/diffusion/fluxvariables.hh new file mode 100644 index 0000000000000000000000000000000000000000..233f6f3e3bbb0774b9d3868f961d2be9e8fdc626 --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/diffusion/fluxvariables.hh @@ -0,0 +1,258 @@ +// -*- 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 diffusion module for the flux data of + * the fully coupled MpNc model + */ +#ifndef DUMUX_MPNC_DIFFUSION_FLUX_VARIABLES_HH +#define DUMUX_MPNC_DIFFUSION_FLUX_VARIABLES_HH + +#include <dune/common/fvector.hh> + +#include "../properties.hh" + +namespace Dumux { + +/*! + * \ingroup MPNCModel + * \ingroup ImplicitFluxVariables + * \brief Variables for the diffusive fluxes in the MpNc model + */ +template<class TypeTag, bool enableDiffusion> +class MPNCFluxVariablesDiffusion +{ + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + typedef typename GridView::template Codim<0>::Entity Element; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename FVElementGeometry::SubControlVolumeFace SCVFace; + + enum{dim = GridView::dimension}; + enum{dimWorld = GridView::dimensionworld}; + enum{numPhases = GET_PROP_VALUE(TypeTag, NumPhases)}; + enum{numComponents = GET_PROP_VALUE(TypeTag, NumComponents)}; + enum{wPhaseIdx = FluidSystem::wPhaseIdx}; + enum{nPhaseIdx = FluidSystem::nPhaseIdx}; + + typedef Dune::FieldVector<Scalar, dim> DimVector; + typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition; + +public: + /*! + * \brief The constructor + */ + MPNCFluxVariablesDiffusion() + {} + /*! + * \brief update + * + * \param problem The problem + * \param element The finite element + * \param fvGeometry The finite-volume geometry in the fully implicit scheme + * \param face The SCV (sub-control-volume) face + * \param elemVolVars The volume variables of the current element + */ + void update(const Problem & problem, + const Element & element, + const FVElementGeometry & fvGeometry, + const SCVFace & face, + const ElementVolumeVariables & elemVolVars) + { + const unsigned int i = face.i; + const unsigned int j = face.j; + + + for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx){ + for (int compIdx = 0; compIdx < numComponents; ++compIdx){ + moleFraction_[phaseIdx][compIdx] = 0. ; + moleFractionGrad_[phaseIdx][compIdx] = 0. ; + } + } + + + GlobalPosition tmp ; + for (unsigned int idx = 0; + idx < face.numFap; + idx++) // loop over adjacent vertices + { + // FE gradient at vertex idx + const GlobalPosition & feGrad = face.grad[idx]; + + // index for the element volume variables + int volVarsIdx = face.fapIndices[idx]; + + for (int phaseIdx = 0; phaseIdx < numPhases; phaseIdx++){ + for (int compIdx = 0; compIdx < numComponents; ++compIdx){ + + // calculate mole fractions at the integration points of the face + moleFraction_[phaseIdx][compIdx] += elemVolVars[volVarsIdx].fluidState().moleFraction(phaseIdx, compIdx)* + face.shapeValue[idx]; + + // calculate mole fraction gradients + tmp = feGrad; + tmp *= elemVolVars[volVarsIdx].fluidState().moleFraction(phaseIdx, compIdx); + moleFractionGrad_[phaseIdx][compIdx] += tmp; + } + } + } + + // initialize the diffusion coefficients to zero + for (int compIIdx = 0; compIIdx < numComponents; ++compIIdx) { + porousDiffCoeffL_[compIIdx] = 0.0; + for (int compJIdx = 0; compJIdx < numComponents; ++compJIdx) + porousDiffCoeffG_[compIIdx][compJIdx] = 0.0; + } + + // calculate the diffusion coefficients at the integration + // point in the porous medium + for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) + { + // make sure to only calculate diffusion coefficents + // for phases which exist in both finite volumes + if (elemVolVars[i].fluidState().saturation(phaseIdx) <= 1e-4 || + elemVolVars[j].fluidState().saturation(phaseIdx) <= 1e-4) + { + continue; + } + + // reduction factor for the diffusion coefficients in the + // porous medium in nodes i and j. this is the tortuosity + // times porosity times phase saturation at the nodes i + // and j + // + Scalar red_i = + elemVolVars[i].fluidState().saturation(phaseIdx)/elemVolVars[i].porosity() * + pow(elemVolVars[i].porosity() * elemVolVars[i].fluidState().saturation(phaseIdx), 7.0/3); + Scalar red_j = + elemVolVars[j].fluidState().saturation(phaseIdx)/elemVolVars[j].porosity() * + pow(elemVolVars[j].porosity() * elemVolVars[j].fluidState().saturation(phaseIdx), 7.0/3); + + if (phaseIdx == wPhaseIdx) { + // Liquid phase diffusion coefficients in the porous medium + for (int compIIdx = 0; compIIdx < numComponents; ++compIIdx) { + // -> arithmetic mean + porousDiffCoeffL_[compIIdx] + = 1./2*(red_i * elemVolVars[i].diffCoeff(wPhaseIdx, 0, compIIdx) + + red_j * elemVolVars[j].diffCoeff(wPhaseIdx, 0, compIIdx)); + } + } + else { + // Gas phase diffusion coefficients in the porous medium + for (int compIIdx = 0; compIIdx < numComponents; ++compIIdx) { + for (int compJIdx = 0; compJIdx < numComponents; ++compJIdx) { + // -> arithmetic mean + porousDiffCoeffG_[compIIdx][compJIdx] + = 1./2*(red_i * elemVolVars[i].diffCoeff(nPhaseIdx, compIIdx, compJIdx) + + red_j * elemVolVars[j].diffCoeff(nPhaseIdx, compIIdx, compJIdx)); + } + } + } + } + } + /*! + * \brief The binary diffusion coefficient for each component in the fluid phase. + * \param compIdx The local index of the components + */ + Scalar porousDiffCoeffL(const unsigned int compIdx) const + { + // TODO: tensorial diffusion coefficients + return porousDiffCoeffL_[compIdx]; + } + /*! + * \brief The binary diffusion coefficient for each component in the gas phase. + * \param compIIdx The local index of the first component in the phase + * \param compJIdx The local index of the second component in the phase + */ + Scalar porousDiffCoeffG(const unsigned int compIIdx, + const unsigned int compJIdx) const + { + // TODO: tensorial diffusion coefficients + return porousDiffCoeffG_[compIIdx][compJIdx]; + } + /*! + * \brief The mole fraction and concentration gradient for all phases and components + * \param phaseIdx The local index of the phases + * \param compIdx The local index of the component + */ + Scalar moleFraction(const unsigned int phaseIdx, + const unsigned int compIdx) const + { return moleFraction_[phaseIdx][compIdx]; } + + const GlobalPosition &moleFractionGrad(const unsigned int phaseIdx, + const unsigned int compIdx) const + { return moleFractionGrad_[phaseIdx][compIdx];} + +protected: + // the diffusion coefficients for the porous medium for the + // liquid phase + Scalar porousDiffCoeffL_[numComponents]; + + // the diffusion coefficients for the porous medium for the + // gas phase + Scalar porousDiffCoeffG_[numComponents][numComponents]; + + // the concentration gradients of all components in all phases + GlobalPosition moleFractionGrad_[numPhases][numComponents]; + + // the mole fractions of each component at the integration point + Scalar moleFraction_[numPhases][numComponents]; +}; + + +template<class TypeTag> +class MPNCFluxVariablesDiffusion<TypeTag, false> +{ + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GridView::template Codim<0>::Entity Element; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename FVElementGeometry::SubControlVolumeFace SCVFace; + +public: + /*! + * \brief The constructor + */ + MPNCFluxVariablesDiffusion() + {} + /*! + * \brief update + * + * \param problem The problem + * \param element The finite element + * \param fvGeometry The finite-volume geometry in the fully implicit scheme + * \param face The SCV (sub-control-volume) face + * \param elemVolVars The volume variables of the current element + */ + void update(const Problem & problem, + const Element & element, + const FVElementGeometry & fvGeometry, + const SCVFace & face, + const ElementVolumeVariables & elemVolVars) + { + } +}; + +} + +#endif // DUMUX_MPNC_DIFFUSION_FLUX_VARIABLES_HH diff --git a/dumux/porousmediumflow/mpnc/implicit/diffusion/volumevariables.hh b/dumux/porousmediumflow/mpnc/implicit/diffusion/volumevariables.hh new file mode 100644 index 0000000000000000000000000000000000000000..dc7246311850cc21596f14ec485a0985161d8c96 --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/diffusion/volumevariables.hh @@ -0,0 +1,199 @@ +// -*- 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 diffusion module for the vertex data + * of the fully coupled MpNc model + */ +#ifndef DUMUX_MPNC_DIFFUSION_VOLUME_VARIABLES_HH +#define DUMUX_MPNC_DIFFUSION_VOLUME_VARIABLES_HH + +#include <dumux/common/valgrind.hh> +#include <dumux/porousmediumflow/mpnc/implicit/properties.hh> + +namespace Dumux { + +/*! + * \brief Variables for the diffusive fluxes in the MpNc model within + * a finite volume. + */ +template<class TypeTag, bool enableDiffusion> +class MPNCVolumeVariablesDiffusion +{ + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; + typedef typename FluidSystem::ParameterCache ParameterCache; + + enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; + enum { wPhaseIdx = FluidSystem::wPhaseIdx }; + enum { nPhaseIdx = FluidSystem::nPhaseIdx }; + +public: + /*! + * \brief The constructor + */ + MPNCVolumeVariablesDiffusion() + {} + /*! + * \brief update + * + * \param fluidState An arbitrary fluid state + * \param paramCache Container for cache parameters + * \param volVars The volume variables + * \param problem The problem + */ + void update(FluidState &fluidState, + ParameterCache ¶mCache, + const VolumeVariables &volVars, + const Problem &problem) + { + Valgrind::SetUndefined(*this); + + // diffusion coefficents in liquid + diffCoeffL_[0] = 0.0; + for (int compIdx = 1; compIdx < numComponents; ++compIdx) { + diffCoeffL_[compIdx] = + FluidSystem::binaryDiffusionCoefficient(fluidState, + paramCache, + wPhaseIdx, + 0, + compIdx); + } + Valgrind::CheckDefined(diffCoeffL_); + + // diffusion coefficents in gas + for (int compIIdx = 0; compIIdx < numComponents; ++compIIdx) { + diffCoeffG_[compIIdx][compIIdx] = 0; + for (int compJIdx = compIIdx + 1; compJIdx < numComponents; ++compJIdx) { + diffCoeffG_[compIIdx][compJIdx] = + FluidSystem::binaryDiffusionCoefficient(fluidState, + paramCache, + nPhaseIdx, + compIIdx, + compJIdx); + + // fill the symmetric part of the diffusion coefficent + // matrix + diffCoeffG_[compJIdx][compIIdx] = diffCoeffG_[compIIdx][compJIdx]; + } + } + Valgrind::CheckDefined(diffCoeffG_); + } + + /*! + * \brief The binary diffusion coefficient for each fluid phase. + * \param phaseIdx The local index of the phases + * \param compIIdx The local index of the first component in the phase + * \param compJIdx The local index of the second component in the phase + */ + Scalar diffCoeff(const unsigned int phaseIdx, + const unsigned int compIIdx, + const unsigned int compJIdx) const + { + if (phaseIdx == nPhaseIdx) + // TODO: tensorial diffusion coefficients + return diffCoeffG_[compIIdx][compJIdx]; + + const unsigned int i = std::min(compIIdx, compJIdx); + const unsigned int j = std::max(compIIdx, compJIdx); + if (i != 0) + return 0; + return diffCoeffL_[j]; + } + + /*! + * \brief If running under valgrind this produces an error message + * if some of the object's attributes is undefined. + */ + void checkDefined() const + { + Valgrind::CheckDefined(diffCoeffL_); + Valgrind::CheckDefined(diffCoeffG_); + } + + +protected: + // the diffusion coefficients for the porous medium for the + // liquid phase + Scalar diffCoeffL_[numComponents]; + + // the diffusion coefficients for the porous medium for the + // gas phase + Scalar diffCoeffG_[numComponents][numComponents]; +}; + +// dummy class for the case where diffusion is disabled +template<class TypeTag> +class MPNCVolumeVariablesDiffusion<TypeTag, false> +{ + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; + typedef typename FluidSystem::ParameterCache ParameterCache; + +public: + /*! + * \brief The constructor + */ + MPNCVolumeVariablesDiffusion() + {} + /*! + * \brief update + * + * \param fluidState An arbitrary fluid state + * \param paramCache Container for cache parameters + * \param volVars The volume variables + * \param problem The problem + */ + void update(FluidState &fluidState, + ParameterCache ¶mCache, + const VolumeVariables &volVars, + const Problem &problem) + { } + /*! + * \brief The binary diffusion coefficient for each component in the fluid phase. + * \param compIdx The local index of the components + */ + Scalar diffCoeffL(const unsigned int compIdx) const + { return 0; } + /*! + * \brief The binary diffusion coefficient for each component in the gas phase. + * \param compIIdx The local index of the first component in the phase + * \param compJIdx The local index of the second component in the phase + */ + Scalar diffCoeffG(const unsigned int compIIdx, const unsigned int compJIdx) const + { return 0; } + + /*! + * \brief If running under valgrind this produces an error message + * if some of the object's attributes is undefined. + */ + void checkDefined() const + { } +}; + +} + +#endif // DUMUX_MPNC_DIFFUSION_VOLUME_VARIABLES_HH diff --git a/dumux/porousmediumflow/mpnc/implicit/energy/fluxvariables.hh b/dumux/porousmediumflow/mpnc/implicit/energy/fluxvariables.hh new file mode 100644 index 0000000000000000000000000000000000000000..dca4d60f006688a36de142b4e716ad4f023cd3f4 --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/energy/fluxvariables.hh @@ -0,0 +1,243 @@ +// -*- 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 Contains the quantities to calculate the energy flux in the + * MpNc fully implicit model. + */ +#ifndef DUMUX_MPNC_ENERGY_FLUX_VARIABLES_HH +#define DUMUX_MPNC_ENERGY_FLUX_VARIABLES_HH + +#include <dune/common/fvector.hh> + +#include <dumux/porousmediumflow/mpnc/implicit/properties.hh> +#include <dumux/common/spline.hh> + +namespace Dumux +{ +/*! + * \ingroup MPNCModel + * \ingroup ImplicitFluxVariables + * \brief Variables for the enthalpy fluxes in the MpNc model + */ +template <class TypeTag, bool enableEnergy/*=false*/, int numEnergyEquations/*=0*/> +class MPNCFluxVariablesEnergy +{ + static_assert(!(numEnergyEquations && !enableEnergy), + "No kinetic energy transfer may only be enabled " + "if energy is enabled in general."); + static_assert(!numEnergyEquations, + "No kinetic energy transfer module included, " + "but kinetic energy transfer enabled."); + + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GridView::template Codim<0>::Entity Element; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; + typedef typename FVElementGeometry::SubControlVolumeFace SCVFace; + +public: + /*! + * \brief The constructor + */ + MPNCFluxVariablesEnergy() + { + } + /*! + * \brief update + * + * \param problem The problem + * \param element The finite element + * \param fvGeometry The finite-volume geometry in the fully implicit scheme + * \param face The SCV (sub-control-volume) face + * \param fluxVars The flux variables + * \param elemVolVars The volume variables of the current element + */ + void update(const Problem & problem, + const Element & element, + const FVElementGeometry & fvGeometry, + const SCVFace & face, + const FluxVariables & fluxVars, + const ElementVolumeVariables & elemVolVars) + {} +}; + +template <class TypeTag> +class MPNCFluxVariablesEnergy<TypeTag, /*enableEnergy=*/true, /*numEnergyEquations=*/1> +{ + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; + typedef typename FluidSystem::ParameterCache ParameterCache; + typedef typename GridView::ctype CoordScalar; + typedef typename GridView::template Codim<0>::Entity Element; + + enum{dimWorld = GridView::dimensionworld}; + enum{dim = GridView::dimension}; + enum{nPhaseIdx = FluidSystem::nPhaseIdx}; + enum{wPhaseIdx = FluidSystem::wPhaseIdx}; + + typedef Dune::FieldVector<CoordScalar, dim> DimVector; + typedef Dune::FieldVector<CoordScalar, dimWorld> GlobalPosition; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename FVElementGeometry::SubControlVolumeFace SCVFace; + typedef typename GET_PROP_TYPE(TypeTag, ThermalConductivityModel) ThermalConductivityModel; + +public: + /*! + * \brief The constructor + */ + MPNCFluxVariablesEnergy() + {} + /*! + * \brief update + * + * \param problem The problem + * \param element The finite element + * \param fvGeometry The finite-volume geometry in the fully implicit scheme + * \param face The SCV (sub-control-volume) face + * \param fluxVars The flux variables + * \param elemVolVars The volume variables of the current element + */ + void update(const Problem & problem, + const Element & element, + const FVElementGeometry & fvGeometry, + const SCVFace & face, + const FluxVariables & fluxVars, + const ElementVolumeVariables & elemVolVars) + { + // calculate temperature gradient using finite element + // gradients + GlobalPosition tmp(0.0); + GlobalPosition temperatureGradient(0.); + for (int idx = 0; idx < face.numFap; idx++) + { + tmp = face.grad[idx]; + + // index for the element volume variables + int volVarsIdx = face.fapIndices[idx]; + + tmp *= elemVolVars[volVarsIdx].fluidState().temperature(/*phaseIdx=*/0); + temperatureGradient += tmp; + } + + // project the heat flux vector on the face's normal vector + temperatureGradientNormal_ = temperatureGradient * face.normal; + + lambdaEff_ = 0; + calculateEffThermalConductivity_(problem, + element, + fvGeometry, + face, + elemVolVars); + } + + /*! + * \brief The lumped / average conductivity of solid plus phases \f$[W/mK]\f$. + */ + Scalar lambdaEff() const + { return lambdaEff_; } + + /*! + * \brief The normal of the gradient of temperature . + */ + Scalar temperatureGradientNormal() const + { + return temperatureGradientNormal_; + } + +protected: + /*! + * \brief Calculate the effective thermal conductivity of + * the porous medium plus residing phases \f$[W/mK]\f$. + * This basically means to access the model for averaging + * the individual conductivities, set by the property ThermalConductivityModel. + * Except the adapted arguments, this is the same function + * as used in the implicit TwoPTwoCNIFluxVariables. + */ + void calculateEffThermalConductivity_(const Problem &problem, + const Element &element, + const FVElementGeometry & fvGeometry, + const SCVFace & face, + const ElementVolumeVariables &elemVolVars) + { + const unsigned i = face.i; + const unsigned j = face.j; + Scalar lambdaI, lambdaJ; + + if (GET_PROP_VALUE(TypeTag, ImplicitIsBox)) + { + lambdaI = + ThermalConductivityModel::effectiveThermalConductivity(elemVolVars[i].fluidState().saturation(wPhaseIdx), + elemVolVars[i].thermalConductivity(wPhaseIdx), + elemVolVars[i].thermalConductivity(nPhaseIdx), + problem.spatialParams().solidThermalConductivity(element, fvGeometry, i), + problem.spatialParams().porosity(element, fvGeometry, i)); + lambdaJ = + ThermalConductivityModel::effectiveThermalConductivity(elemVolVars[j].fluidState().saturation(wPhaseIdx), + elemVolVars[j].thermalConductivity(wPhaseIdx), + elemVolVars[j].thermalConductivity(nPhaseIdx), + problem.spatialParams().solidThermalConductivity(element, fvGeometry, j), + problem.spatialParams().porosity(element, fvGeometry, j)); + } + else + { + const Element & elementI = fvGeometry.neighbors[i]; + FVElementGeometry fvGeometryI; + fvGeometryI.subContVol[0].global = elementI.geometry().center(); + + lambdaI = + ThermalConductivityModel::effectiveThermalConductivity(elemVolVars[i].fluidState().saturation(wPhaseIdx), + elemVolVars[i].thermalConductivity(wPhaseIdx), + elemVolVars[i].thermalConductivity(nPhaseIdx), + problem.spatialParams().solidThermalConductivity(elementI, fvGeometryI, 0), + problem.spatialParams().porosity(elementI, fvGeometryI, 0)); + + const Element & elementJ = fvGeometry.neighbors[j]; + FVElementGeometry fvGeometryJ; + fvGeometryJ.subContVol[0].global = elementJ.geometry().center(); + + lambdaJ = + ThermalConductivityModel::effectiveThermalConductivity(elemVolVars[j].fluidState().saturation(wPhaseIdx), + elemVolVars[j].thermalConductivity(wPhaseIdx), + elemVolVars[j].thermalConductivity(nPhaseIdx), + problem.spatialParams().solidThermalConductivity(elementJ, fvGeometryJ, 0), + problem.spatialParams().porosity(elementJ, fvGeometryJ, 0)); + } + + // -> harmonic mean + lambdaEff_ = harmonicMean(lambdaI, lambdaJ); + } + +private: + Scalar lambdaEff_ ; + Scalar temperatureGradientNormal_; +}; + +} // end namespace + +#endif diff --git a/dumux/porousmediumflow/mpnc/implicit/energy/fluxvariableskinetic.hh b/dumux/porousmediumflow/mpnc/implicit/energy/fluxvariableskinetic.hh new file mode 100644 index 0000000000000000000000000000000000000000..f1595f2afe2de229f77fc12969b325ab61bde1cb --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/energy/fluxvariableskinetic.hh @@ -0,0 +1,298 @@ +// -*- 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 Contains the quantities to calculate the energy flux in the + * MpNc box model with kinetic energy transfer enabled. + */ +#ifndef DUMUX_MPNC_ENERGY_FLUX_VARIABLES_KINETIC_HH +#define DUMUX_MPNC_ENERGY_FLUX_VARIABLES_KINETIC_HH + +#include <dune/common/fvector.hh> + +#include <dumux/common/spline.hh> +#include <dumux/porousmediumflow/mpnc/implicit/fluxvariables.hh> + +namespace Dumux +{ + +/*! + * \brief Specialization for the case of *3* energy balance equations. + */ +template <class TypeTag> +class MPNCFluxVariablesEnergy<TypeTag, /*enableEnergy=*/true, /*numEnergyEquations=*/3> +{ + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + typedef typename GridView::ctype CoordScalar; + typedef typename GridView::template Codim<0>::Entity Element; + + enum {dim = GridView::dimension}; + enum {dimWorld = GridView::dimensionworld}; + enum {numEnergyEqs = Indices::numPrimaryEnergyVars}; + + typedef Dune::FieldVector<CoordScalar, dim> DimVector; + typedef Dune::FieldVector<CoordScalar, dimWorld> GlobalPosition; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename FVElementGeometry::SubControlVolume SCV; + typedef typename FVElementGeometry::SubControlVolumeFace SCVFace; + +public: + /*! + * \brief The constructor + */ + MPNCFluxVariablesEnergy() + {} + /*! + * \brief update + * + * \param problem The problem + * \param element The finite element + * \param fvGeometry The finite-volume geometry in the fully implicit scheme + * \param face The SCV (sub-control-volume) face + * \param fluxVars The flux variables + * \param elemVolVars The volume variables of the current element + */ + void update(const Problem & problem, + const Element & element, + const FVElementGeometry & fvGeometry, + const SCVFace & face, + const FluxVariables & fluxVars, + const ElementVolumeVariables & elemVolVars) + { + // calculate temperature gradient using finite element + // gradients + GlobalPosition tmp ; + + for(int energyEqIdx=0; energyEqIdx<numEnergyEqs; energyEqIdx++) + temperatureGradient_[energyEqIdx] = 0.; + + for (unsigned int idx = 0; + idx < face.numFap; + idx++){ + // FE gradient at vertex idx + const GlobalPosition & feGrad = face.grad[idx]; + + for (int energyEqIdx =0; energyEqIdx < numEnergyEqs; ++energyEqIdx){ + // index for the element volume variables + int volVarsIdx = face.fapIndices[idx]; + + tmp = feGrad; + tmp *= elemVolVars[volVarsIdx].temperature(energyEqIdx); + temperatureGradient_[energyEqIdx] += tmp; + } + } + } + + /*! + * \brief The total heat flux \f$[J/s]\f$ due to heat conduction + * of the rock matrix over the sub-control volume's face. + * + * \param energyEqIdx The index of the energy equation + */ + GlobalPosition temperatureGradient(const unsigned int energyEqIdx) const + { + return temperatureGradient_[energyEqIdx]; + } + +private: + GlobalPosition temperatureGradient_[numEnergyEqs]; +}; + + +/*! + * \brief Specialization for the case of *2* energy balance equations. + */ +template <class TypeTag> +class MPNCFluxVariablesEnergy<TypeTag, /*enableEnergy=*/true, /*numEnergyEquations=*/2> +{ + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + + typedef typename GridView::ctype CoordScalar; + typedef typename GridView::template Codim<0>::Entity Element; + + enum {dim = GridView::dimension}; + enum {dimWorld = GridView::dimensionworld}; + enum {numEnergyEqs = Indices::numPrimaryEnergyVars}; + enum {wPhaseIdx = FluidSystem::wPhaseIdx}; + enum {nPhaseIdx = FluidSystem::nPhaseIdx}; + + + typedef Dune::FieldVector<CoordScalar, dimWorld> GlobalPosition; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename FVElementGeometry::SubControlVolume SCV; + typedef typename FVElementGeometry::SubControlVolumeFace SCVFace; + typedef typename GET_PROP_TYPE(TypeTag, ThermalConductivityModel) ThermalConductivityModel; + + +public: + /*! + * \brief The constructor + */ + MPNCFluxVariablesEnergy() + {} + /*! + * \brief update + * + * \param problem The problem + * \param element The finite element + * \param fvGeometry The finite-volume geometry in the fully implicit scheme + * \param face The SCV (sub-control-volume) face + * \param fluxVars The flux variables + * \param elemVolVars The volume variables of the current element + */ + void update(const Problem & problem, + const Element & element, + const FVElementGeometry & fvGeometry, + const SCVFace & face, + const FluxVariables & fluxVars, + const ElementVolumeVariables & elemVolVars) + { + // calculate temperature gradient using finite element + // gradients + GlobalPosition tmp ; + + for(int energyEqIdx=0; energyEqIdx<numEnergyEqs; energyEqIdx++) + temperatureGradient_[energyEqIdx] = 0.; + + for (unsigned int idx = 0; + idx < face.numFap; + idx++){ + // FE gradient at vertex idx + const GlobalPosition & feGrad = face.grad[idx]; + + for (int energyEqIdx =0; energyEqIdx < numEnergyEqs; ++energyEqIdx){ + // index for the element volume variables + int volVarsIdx = face.fapIndices[idx]; + + tmp = feGrad; + tmp *= elemVolVars[volVarsIdx].temperature(energyEqIdx); + temperatureGradient_[energyEqIdx] += tmp; + } + } + + lambdaEff_ = 0; + calculateEffThermalConductivity_(problem, + element, + fvGeometry, + face, + elemVolVars); + + + } + + /*! + * \brief The lumped / average conductivity of solid plus phases \f$[W/mK]\f$. + */ + Scalar lambdaEff() const + { return lambdaEff_; } + + /*! + * \brief The total heat flux \f$[J/s]\f$ due to heat conduction + * of the rock matrix over the sub-control volume's face. + * + * \param energyEqIdx The index of the energy equation + */ + GlobalPosition temperatureGradient(const unsigned int energyEqIdx) const + { + return temperatureGradient_[energyEqIdx]; + } + +protected: + /*! + * \brief Calculate the effective thermal conductivity of + * the porous medium plus residing phases \f$[W/mK]\f$. + * This basically means to access the model for averaging + * the individual conductivities, set by the property ThermalConductivityModel. + * Except the adapted arguments, this is the same function + * as used in the implicit TwoPTwoCNIFluxVariables. + */ + void calculateEffThermalConductivity_(const Problem &problem, + const Element &element, + const FVElementGeometry & fvGeometry, + const SCVFace & face, + const ElementVolumeVariables &elemVolVars) + { + const unsigned i = face.i; + const unsigned j = face.j; + Scalar lambdaI, lambdaJ; + + if (GET_PROP_VALUE(TypeTag, ImplicitIsBox)) + { + lambdaI = + ThermalConductivityModel::effectiveThermalConductivity(elemVolVars[i].fluidState().saturation(wPhaseIdx), + elemVolVars[i].thermalConductivity(wPhaseIdx), + elemVolVars[i].thermalConductivity(nPhaseIdx), + problem.spatialParams().solidThermalConductivity(element, fvGeometry, i), + problem.spatialParams().porosity(element, fvGeometry, i)); + lambdaJ = + ThermalConductivityModel::effectiveThermalConductivity(elemVolVars[j].fluidState().saturation(wPhaseIdx), + elemVolVars[j].thermalConductivity(wPhaseIdx), + elemVolVars[j].thermalConductivity(nPhaseIdx), + problem.spatialParams().solidThermalConductivity(element, fvGeometry, j), + problem.spatialParams().porosity(element, fvGeometry, j)); + } + else + { + const Element & elementI = fvGeometry.neighbors[i]; + FVElementGeometry fvGeometryI; + fvGeometryI.subContVol[0].global = elementI.geometry().center(); + + lambdaI = + ThermalConductivityModel::effectiveThermalConductivity(elemVolVars[i].fluidState().saturation(wPhaseIdx), + elemVolVars[i].thermalConductivity(wPhaseIdx), + elemVolVars[i].thermalConductivity(nPhaseIdx), + problem.spatialParams().solidThermalConductivity(elementI, fvGeometryI, 0), + problem.spatialParams().porosity(elementI, fvGeometryI, 0)); + + const Element & elementJ = fvGeometry.neighbors[j]; + FVElementGeometry fvGeometryJ; + fvGeometryJ.subContVol[0].global = elementJ.geometry().center(); + + lambdaJ = + ThermalConductivityModel::effectiveThermalConductivity(elemVolVars[j].fluidState().saturation(wPhaseIdx), + elemVolVars[j].thermalConductivity(wPhaseIdx), + elemVolVars[j].thermalConductivity(nPhaseIdx), + problem.spatialParams().solidThermalConductivity(elementJ, fvGeometryJ, 0), + problem.spatialParams().porosity(elementJ, fvGeometryJ, 0)); + } + + // -> arithmetic mean, open to discussion + lambdaEff_ = 0.5 * (lambdaI+lambdaJ); + } + + +private: + Scalar lambdaEff_ ; + GlobalPosition temperatureGradient_[numEnergyEqs]; +}; + +} // end namespace + +#endif diff --git a/dumux/porousmediumflow/mpnc/implicit/energy/indices.hh b/dumux/porousmediumflow/mpnc/implicit/energy/indices.hh new file mode 100644 index 0000000000000000000000000000000000000000..fbe135b8b0a94aae8ce675638d62d2ba67eea7e7 --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/energy/indices.hh @@ -0,0 +1,81 @@ +// -*- 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 The indices for the non-isothermal part of the compositional + * multi-phase model. + */ +#ifndef DUMUX_MPNC_INDICES_ENERGY_HH +#define DUMUX_MPNC_INDICES_ENERGY_HH + +namespace Dumux +{ +/*! + * \ingroup MPNCModel + * \ingroup ImplicitIndices + * \brief The indices for the energy equation. + * + * This is a dummy class for the isothermal case. + */ +template <int PVOffset, bool enableEnergy/*=false*/, int numEnergyEquations/*=0*/> +struct MPNCEnergyIndices +{ + static_assert(((numEnergyEquations<1) and not enableEnergy), + "No kinetic energy transfer may only be enabled " + "if energy is enabled in general."); + + static_assert( (numEnergyEquations < 1) , + "No kinetic energy transfer module included, " + "but kinetic energy transfer enabled."); +public: + /*! + * \brief This module does not define any primary variables in the + * isothermal case. + */ + static const unsigned int numPrimaryVars = 0; +}; + +/*! + * \ingroup MPNCModel + * \ingroup ImplicitIndices + * \brief The indices required for the energy equation. + */ +template <int PVOffset> +struct MPNCEnergyIndices<PVOffset, /*isNonIsothermal=*/true, /*numEnergyEquations=*/ 1 > +{ +public: + /*! + * \brief This module defines one new primary variable. + */ + static const unsigned int numPrimaryVars = 1; + + /*! + * \brief Index for the temperature in a vector of primary + * variables. + */ + static const unsigned int temperatureIdx = PVOffset + 0; + /*! + * \brief Equation index of the energy equation. + */ + static const unsigned int energyEqIdx = PVOffset + 0; +}; + +} + +#endif diff --git a/dumux/porousmediumflow/mpnc/implicit/energy/indiceskinetic.hh b/dumux/porousmediumflow/mpnc/implicit/energy/indiceskinetic.hh new file mode 100644 index 0000000000000000000000000000000000000000..dcbf9563dd37873d046c88ad1a12c2f4218adafa --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/energy/indiceskinetic.hh @@ -0,0 +1,167 @@ +// -*- 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 The indices for the thermal non-equilibrium part of the MpNc model. + */ +#ifndef DUMUX_MPNC_INDICES_ENERGY_KINETIC_HH +#define DUMUX_MPNC_INDICES_ENERGY_KINETIC_HH + +#include <dumux/porousmediumflow/mpnc/implicit/indices.hh> + +namespace Dumux +{ + +/*! + * \brief The indices required for the energy equation. Specialization for the case of + * *3* energy balance equations. + */ +template <int PVOffset> +struct MPNCEnergyIndices<PVOffset, /*enableEnergy=*/true, /*numEnergyEquations=*/3> +{ +public: + /*! + * \brief This module defines one new primary variable. + */ + static const unsigned int numPrimaryVars = 3; + + /*! + * \brief Index for the temperature of the wetting phase in a vector of primary + * variables. + */ + static const unsigned int temperature0Idx = PVOffset + 0; + + /*! + * \brief Compatibility with non kinetic models + */ + static const unsigned int temperatureIdx = temperature0Idx; + /*! + * \brief Equation index of the energy equation. + */ + static const unsigned int energyEq0Idx = PVOffset + 0; + /*! + * \brief Compatibility with non kinetic models + */ + static const unsigned int energyEqIdx = energyEq0Idx; +}; + +/*! + * \brief The indices required for the energy equation. Specialization for the case of + * *2* energy balance equations. + */ +template <int PVOffset> +struct MPNCEnergyIndices<PVOffset, /*enableEnergy=*/true, /*numEnergyEquations=*/2> +{ +public: + /*! + * \brief This module defines one new primary variable. + */ + static const unsigned int numPrimaryVars = 2; + + /*! + * \brief Index for the temperature of the wetting phase in a vector of primary + * variables. + */ + static const unsigned int temperature0Idx = PVOffset + 0; + + /*! + * \brief Compatibility with non kinetic models + */ + static const unsigned int temperatureIdx = temperature0Idx; + /*! + * \brief Equation index of the energy equation. + */ + static const unsigned int energyEq0Idx = PVOffset + 0; + /*! + * \brief Equation index of the energy equation. + */ + static const unsigned int energyEqSolidIdx = energyEq0Idx + numPrimaryVars - 1 ; + + /*! + * \brief Index for storing e.g. temperature fluidState + */ + static const unsigned int temperatureFluidIdx = 0 ; + static const unsigned int temperatureSolidIdx = 1 ; + + + /*! + * \brief Compatibility with non kinetic models + */ + static const unsigned int energyEqIdx = energyEq0Idx; + + +}; + +/*! + * \brief The indices required for the energy equation. + */ +template <int PVOffset, bool isNonIsothermal> +struct MPNCEnergyIndices<PVOffset, isNonIsothermal, /*numEnergyEquations=*/1 > +{ +public: + /*! + * \brief This module defines one new primary variable. + */ + static const unsigned int numPrimaryVars = 1; + + /*! + * \brief Index for the temperature in a vector of primary + * variables. + */ + static const unsigned int temperatureIdx = PVOffset + 0; + /*! + * \brief Equation index of the energy equation. + */ + static const unsigned int energyEqIdx = PVOffset + 0; +}; + +/*! + * \brief The indices for the energy equation. + * + * This is a dummy class for the isothermal case. + */ +template <int PVOffset> +struct MPNCEnergyIndices<PVOffset, /*isNonIsothermal=*/false, /*numEnergyEquations*/0> +{ +public: + /*! + * \brief This module does not define any primary variables in the + * isothermal case. + */ + static const unsigned int numPrimaryVars = 0; + + /*! + * \brief Equation index of the temperature primary variable. This + * is a dummy value which hopefully makes the simulation + * crash if used. + */ + static const unsigned int temperatureIdx = -1; + + /*! + * \brief Equation index of the energy equation. This is a dummy + * value which hopefully makes the simulation crash if used. + */ + static const unsigned int energyEqIdx = -1; +}; + + + +} + +#endif diff --git a/dumux/porousmediumflow/mpnc/implicit/energy/localresidual.hh b/dumux/porousmediumflow/mpnc/implicit/energy/localresidual.hh new file mode 100644 index 0000000000000000000000000000000000000000..3d09f690b48edbda1df0b715b61ae599d7421962 --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/energy/localresidual.hh @@ -0,0 +1,296 @@ +// -*- 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 parts of the local residual to + * calculate the heat flux in the fully coupled MpNc model. + */ +#ifndef DUMUX_MPNC_LOCAL_RESIDUAL_ENERGY_HH +#define DUMUX_MPNC_LOCAL_RESIDUAL_ENERGY_HH + +#include <dumux/porousmediumflow/mpnc/implicit/properties.hh> + +namespace Dumux { + +/*! + * \brief Specialization of the energy module for the isothermal case. + * + * This class just does nothing. + */ +template <class TypeTag, bool enableEnergy/*=false*/, int numEnergyEquations /*=0*/> +class MPNCLocalResidualEnergy +{ + static_assert(!(numEnergyEquations && !enableEnergy), + "No kinetic energy transfer may only be enabled " + "if energy is enabled in general."); + static_assert(!numEnergyEquations, + "No kinetic energy transfer module included, " + "but kinetic energy transfer enabled."); + + typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; + typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + + enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; + enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; + + typedef typename Dune::FieldVector<Scalar, numComponents> ComponentVector; + +public: + /*! + * \brief Evaluate the amount all conservation quantities + * (e.g. phase mass) within a sub-control volume. + * + * The result should be averaged over the volume (e.g. phase mass + * inside a sub-control volume divided by the volume) + * + * \param storage The mass of the component within the sub-control volume + * \param volVars the Volume Variables + */ + static void computeStorage(PrimaryVariables &storage, + const VolumeVariables &volVars) + { + // do nothing, we're isothermal! + } + + /*! + * \brief Calculate the storage for all mass balance equations + * within a single fluid phase + * + * \param storage The mass of the component within the sub-control volume + * \param volVars the Volume Variables + * \param phaseIdx The local index of the phases + */ + static void addPhaseStorage(PrimaryVariables &storage, + const VolumeVariables &volVars, + const unsigned int phaseIdx) + { + // do nothing, we're isothermal! + } + + /*! + * \brief Evaluates the total flux of all conservation quantities + * over a face of a sub-control volume. + * + * \param flux The flux over the SCV (sub-control-volume) face for each component + * \param fluxVars The flux variables + * \param volVars The volume variables + * \param molarPhaseComponentValuesMassTransport The component-wise flux within a phase. Needed for energy transport. + */ + static void computeFlux(PrimaryVariables & flux, + const FluxVariables & fluxVars, + const ElementVolumeVariables & volVars, + const ComponentVector molarPhaseComponentValuesMassTransport[numPhases]) + { + // do nothing, we're isothermal! + } + /*! + * \brief Calculate the source term of the equation + * + * \param source The source/sink in the sub-control volume for each component + * \param volVars The volume variables + * \param componentIntoPhaseMassTransfer The component-wise transfer from one phase. Needed for energy transfer. + * + */ + static void computeSource(PrimaryVariables &source, + const VolumeVariables &volVars, + const ComponentVector componentIntoPhaseMassTransfer[numPhases]) + { + // do nothing, we're isothermal! + } +}; + + +template <class TypeTag> +class MPNCLocalResidualEnergy<TypeTag, /*enableEnergy=*/true, /*numEnergyEquations=*/ 1 > +{ + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; + typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; + typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + + enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; + enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; + enum { energyEqIdx = Indices::energyEqIdx }; + + typedef typename Dune::FieldVector<Scalar, numComponents> ComponentVector; + +public: + /*! + * \brief Evaluate the amount all conservation quantities + * (e.g. phase mass) within a sub-control volume. + * + * The result should be averaged over the volume (e.g. phase mass + * inside a sub-control volume divided by the volume) + * + * \param storage The mass of the component within the sub-control volume + * \param volVars the Volume Variables + */ + static void computeStorage(PrimaryVariables &storage, + const VolumeVariables &volVars) + { + storage[energyEqIdx] = 0; + + // energy of the fluids + for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { + addPhaseStorage(storage, volVars, phaseIdx); + } + + // heat stored in the rock matrix + storage[energyEqIdx] += + volVars.fluidState().temperature(/*phaseIdx=*/0) + * volVars.solidDensity() + * (1.0 - volVars.porosity()) + * volVars.solidHeatCapacity(); + } + /*! + * \brief Calculate the storage for all mass balance equations + * within a single fluid phase + * + * \param storage The mass of the component within the sub-control volume + * \param volVars the Volume Variables + * \param phaseIdx The local index of the phases + */ + static void addPhaseStorage(PrimaryVariables &storage, + const VolumeVariables &volVars, + const unsigned int phaseIdx) + { + const FluidState &fs = volVars.fluidState(); + + // energy of the fluid + storage[energyEqIdx] += + fs.density(phaseIdx) + * fs.internalEnergy(phaseIdx) + * fs.saturation(phaseIdx) + * volVars.porosity(); + +#ifndef NDEBUG +if (!std::isfinite(storage[energyEqIdx])) + DUNE_THROW(NumericalProblem, "Calculated non-finite energy storage"); +#endif + } + /*! + * \brief Evaluates the total flux of all conservation quantities + * over a face of a sub-control volume. + * + * \param flux The flux over the SCV (sub-control-volume) face for each component + * \param fluxVars The flux Variables + * \param elemVolVars The volume variables of the current element + * \param molarPhaseComponentValuesMassTransport The component-wise flux within a phase. Needed for energy transport. + */ + static void computeFlux(PrimaryVariables & flux, + const FluxVariables & fluxVars, + const ElementVolumeVariables & elemVolVars, + const ComponentVector molarPhaseComponentValuesMassTransport[numPhases]) + { + flux[energyEqIdx] = 0.0; + + // fluid phases transport enthalpy individually + for(int phaseIdx=0; phaseIdx<numPhases; ++phaseIdx) + computePhaseEnthalpyFlux(flux, + fluxVars, + elemVolVars, + phaseIdx, + molarPhaseComponentValuesMassTransport[phaseIdx]); + + //conduction is treated lumped in this model + computeHeatConduction(flux, + fluxVars, + elemVolVars); + } + /*! + * \brief The advective Flux of the enthalpy + * \param flux The flux over the SCV (sub-control-volume) face for each component + * \param fluxVars The flux Variables + * \param elemVolVars The volume variables of the current element + * \param phaseIdx The local index of the phases + * \param molarComponentValuesMassTransport The component-wise flux in the current phase. Needed for energy transport. + */ + static void computePhaseEnthalpyFlux(PrimaryVariables & flux, + const FluxVariables & fluxVars, + const ElementVolumeVariables & elemVolVars, + const unsigned int phaseIdx, + const ComponentVector & molarComponentValuesMassTransport) + { + Scalar massFlux = 0; + + // calculate the mass flux in the phase i.e. make mass flux out of mole flux and add up the fluxes of a phase + for (int compIdx = 0; compIdx < numComponents; ++compIdx) + massFlux += molarComponentValuesMassTransport[compIdx] + * FluidSystem::molarMass(compIdx); + + unsigned int upIdx = fluxVars.face().i; + if (massFlux < 0) upIdx = fluxVars.face().j; + + // use the phase enthalpy of the upstream vertex to calculate + // the enthalpy transport + const VolumeVariables &up = elemVolVars[upIdx]; + flux[energyEqIdx] += up.fluidState().enthalpy(phaseIdx) * massFlux; +#ifndef NDEBUG +if (!std::isfinite(flux[energyEqIdx]) ) + DUNE_THROW(NumericalProblem, "Calculated non-finite energy flux"); +#endif + } + /*! + * \brief The heat conduction in the phase + * + * \param flux The flux over the SCV (sub-control-volume) face for each component + * \param fluxVars The flux Variables + * \param elemVolVars The volume variables of the current element + */ + static void computeHeatConduction(PrimaryVariables & flux, + const FluxVariables & fluxVars, + const ElementVolumeVariables & elemVolVars) + { + //lumped heat conduction of the rock matrix and the fluid phases + Scalar lumpedConductivity = fluxVars.fluxVarsEnergy().lambdaEff() ; + Scalar temperatureGradientNormal = fluxVars.fluxVarsEnergy().temperatureGradientNormal() ; + Scalar lumpedHeatConduction = - lumpedConductivity * temperatureGradientNormal ; + flux[energyEqIdx] += lumpedHeatConduction; +#ifndef NDEBUG +if (!std::isfinite(flux[energyEqIdx]) ) + DUNE_THROW(NumericalProblem, "Calculated non-finite energy flux"); +#endif + } + + /*! + * \brief Calculate the source term of the equation + * + * \param source The source/sink in the sub-control volume for each component + * \param volVars The volume variables + * \param componentIntoPhaseMassTransfer The component-wise transfer from one phase. Needed for energy transfer. + */ + static void computeSource(PrimaryVariables &source, + const VolumeVariables &volVars, + const ComponentVector componentIntoPhaseMassTransfer[numPhases]) + { + source[energyEqIdx] = 0.0; + } +}; + +} + +#endif // DUMUX_MPNC_ENERGY_HH diff --git a/dumux/porousmediumflow/mpnc/implicit/energy/localresidualkinetic.hh b/dumux/porousmediumflow/mpnc/implicit/energy/localresidualkinetic.hh new file mode 100644 index 0000000000000000000000000000000000000000..0f31f943244b9b40b33398889ae11ce20d4fe56d --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/energy/localresidualkinetic.hh @@ -0,0 +1,786 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 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 parts of the local residual to + * calculate the heat conservation in the thermal non-equilibrium M-phase + * N-component model. + */ +#ifndef DUMUX_MPNC_LOCAL_RESIDUAL_ENERGY_KINETIC_HH +#define DUMUX_MPNC_LOCAL_RESIDUAL_ENERGY_KINETIC_HH + +#include <dumux/porousmediumflow/mpnc/implicit/localresidual.hh> +#include <dumux/common/spline.hh> + + +namespace Dumux +{ + +/*! + * \brief Specialization for the case of *3* energy balance equations. + */ +template <class TypeTag> +class MPNCLocalResidualEnergy<TypeTag, /*enableEnergy=*/true, /*numEnergyEquations=*/3> +{ + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; + typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; + typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + + enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; + enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; + enum { energyEq0Idx = Indices::energyEq0Idx }; + enum { numEnergyEqs = Indices::numPrimaryEnergyVars}; + enum { wPhaseIdx = FluidSystem::wPhaseIdx}; + enum { nPhaseIdx = FluidSystem::nPhaseIdx}; + enum { nCompIdx = FluidSystem::nCompIdx}; + enum { wCompIdx = FluidSystem::wCompIdx}; + enum { sPhaseIdx = FluidSystem::sPhaseIdx}; + + typedef typename Dune::FieldVector<Scalar, numComponents> ComponentVector; + typedef typename Dune::FieldMatrix<Scalar, numPhases, numComponents> PhaseComponentMatrix; + +public: + /*! + * \brief Evaluate the amount all conservation quantities + * (e.g. phase mass) within a sub-control volume. + * + * The result should be averaged over the volume (e.g. phase mass + * inside a sub-control volume divided by the volume) + * + * \param storage The mass of the component within the sub-control volume + * \param volVars the Volume Variables + */ + static void computeStorage(PrimaryVariables & storage, + const VolumeVariables & volVars) + { + for(int energyEqIdx=0; energyEqIdx< numEnergyEqs; energyEqIdx++) + storage[energyEq0Idx+energyEqIdx] = 0; + + // energy of the fluids + for (int phaseIdx = 0; phaseIdx < numEnergyEqs; ++phaseIdx) { + addPhaseStorage(storage, volVars, phaseIdx); + } + } + /*! + * \brief BEWARE !!! + * Here comes some problem with the phase-specific conservation of energy: + * Imagine a displacement process, with the initial state being a fully saturated porous medium. + * If the residing phase is now displaced by another phase, what happens at the front of the process? + * At the very front there is one cell in which the invading phase enters and no invading (but residing) phase leaves. + * With enthalpy in the flux term and internal energy in the storage term, + * the difference (pv) has to be converted into temperature in order to fulfill energy conservation. + * -> A temperature peak at the front arises (if spatial discretization is sufficiently fine). + * This peak has a maximum value and does not increase with further refinement. + * -> Further evidence for this explanation: in a simple setting (constant parameters, + * few cells) the temperature peak can be correctly predicted a priori. + * -> -> For those situations with a distinct displacement process the same quantity has to be stored and transported + * This is equivalent to neglecting volume changing work. + * + * \brief Calculate the storage for all mass balance equations + * within a single fluid phase + * + * \param storage The mass of the component within the sub-control volume + * \param volVars the Volume Variables + * \param phaseIdx The local index of the phases + */ + static void addPhaseStorage(PrimaryVariables & storage, + const VolumeVariables & volVars, + const unsigned int phaseIdx) + { + + const FluidState & fs = volVars.fluidState(); + + if (phaseIdx not_eq sPhaseIdx) { + storage[energyEq0Idx + phaseIdx] += + fs.density(phaseIdx) * + fs.internalEnergy(phaseIdx) * + fs.saturation(phaseIdx) * + volVars.porosity(); + } + else if(phaseIdx == sPhaseIdx) { + // heat stored in the rock matrix + storage[energyEq0Idx+phaseIdx] += volVars.temperature(phaseIdx) * + volVars.solidDensity() * + (1.-volVars.porosity()) * + volVars.solidHeatCapacity(); + } + else + DUNE_THROW(Dune::NotImplemented, + "wrong index"); + + if (!std::isfinite(storage[energyEq0Idx+phaseIdx])) + DUNE_THROW(NumericalProblem, "Calculated non-finite storage"); + + } + /*! + * \brief Evaluates the total flux of all conservation quantities + * over a face of a sub-control volume. + * + * \param flux The flux over the SCV (sub-control-volume) face for each component + * \param fluxVars The flux Variables + * \param elemVolVars The volume variables of the current element + * \param molarPhaseComponentValuesMassTransport + */ + static void computeFlux(PrimaryVariables & flux, + const FluxVariables & fluxVars, + const ElementVolumeVariables & elemVolVars, + const ComponentVector molarPhaseComponentValuesMassTransport[numPhases]) + { + // reset all energy fluxes + for(int energyEqIdx=0; energyEqIdx<numEnergyEqs; ++energyEqIdx) + flux[energyEq0Idx + energyEqIdx] = 0.0; + + // only the fluid phases transport enthalpy + for(int phaseIdx=0; phaseIdx<numPhases; ++phaseIdx) + computePhaseEnthalpyFlux(flux, + fluxVars, + elemVolVars, + phaseIdx, + molarPhaseComponentValuesMassTransport[phaseIdx]); + + // all phases take part in conduction + for(int energyEqIdx=0; energyEqIdx<numEnergyEqs; ++energyEqIdx){ + computeHeatConduction(flux, + fluxVars, + elemVolVars, + energyEqIdx); + if (!std::isfinite(flux[energyEq0Idx + energyEqIdx])) + DUNE_THROW(NumericalProblem, "Calculated non-finite flux in phase " << energyEqIdx); + } + } + /*! + * \brief the advective Flux of the enthalpy + * \param flux The flux over the SCV (sub-control-volume) face for each component + * \param fluxVars The flux Variables + * \param elemVolVars The volume variables of the current element + * \param phaseIdx The local index of the phases + * \param molarComponentValuesMassTransport + */ + static void computePhaseEnthalpyFlux(PrimaryVariables & flux, + const FluxVariables & fluxVars, + const ElementVolumeVariables & elemVolVars, + const unsigned int phaseIdx, + const ComponentVector & molarComponentValuesMassTransport) + { + Scalar massFlux = 0; // mass flux is not the perfect term: sum_kappa (rho_alpha v_alpha x_alpha^kappa) = v_alpha rho_alpha + + // calculate the mass flux in the phase i.e. make mass flux out + // of mole flux and add up the fluxes of a phase + for (int compIdx = 0; compIdx < numComponents; ++compIdx){ + massFlux += molarComponentValuesMassTransport[compIdx] + * FluidSystem::molarMass(compIdx) ; + } + + unsigned int upIdx = fluxVars.face().i; + unsigned int dnIdx = fluxVars.face().j; + if (massFlux < 0){ + upIdx = fluxVars.face().j; + dnIdx = fluxVars.face().i; + } + + // use the phase enthalpy of the upstream vertex to calculate + // the enthalpy transport + const VolumeVariables & up = elemVolVars[upIdx]; + const VolumeVariables & dn = elemVolVars[dnIdx]; + + /* todo + * CAUTION: this is not exactly correct: does diffusion carry the upstream phase enthalpy? + * To be more precise this should be the components enthalpy. + * In the same vein: Counter current diffusion is not accounted for here. + */ + const Scalar transportedThingUp = up.fluidState().enthalpy(phaseIdx) ; + const Scalar transportedThingDn = dn.fluidState().enthalpy(phaseIdx) ; + + + const Scalar massUpwindWeight_ = GET_PARAM_FROM_GROUP(TypeTag, Scalar, Implicit, MassUpwindWeight); + flux[energyEq0Idx + phaseIdx] += massFlux * + (massUpwindWeight_ * transportedThingUp + + + (1.-massUpwindWeight_) * transportedThingDn ) ; + } + /*! + * \brief The heat conduction in the phase + * + * \param flux The flux over the SCV (sub-control-volume) face for each component + * \param fluxVars The flux Variables + * \param elemVolVars The volume variables of the current element + * \param phaseIdx The local index of the phases + */ + static void computeHeatConduction(PrimaryVariables & flux, + const FluxVariables & fluxVars, + const ElementVolumeVariables & elemVolVars, + const unsigned int phaseIdx) + { + const unsigned int iIdx = fluxVars.face().i; + const unsigned int kIdx = fluxVars.face().j; // k can be better distinguished from i + + const VolumeVariables & iVolVar = elemVolVars[iIdx]; + const VolumeVariables & kVolVar = elemVolVars[kIdx]; + + const FluidState & iFluidState = iVolVar.fluidState(); + const FluidState & kFluidState = kVolVar.fluidState(); + + const Scalar iPorosity = iVolVar.porosity(); + const Scalar kPorosity = kVolVar.porosity(); + const Scalar barPorosity = Dumux::harmonicMean(iPorosity, kPorosity); + + const Scalar ilambda = iVolVar.thermalConductivity(phaseIdx); + const Scalar klambda = kVolVar.thermalConductivity(phaseIdx); + // todo which average? + // Using a harmonic average is justified by its properties: if one phase does not conduct energy, there is no transfer + const Scalar barLambda = Dumux::harmonicMean(ilambda, klambda) ; + + const Scalar gradientNormal = fluxVars.fluxVarsEnergy().temperatureGradient(phaseIdx) + * fluxVars.face().normal ; + + // heat conduction of the rock matrix and the fluid phases + if (phaseIdx == sPhaseIdx){ + flux[energyEq0Idx + phaseIdx] -= barLambda * gradientNormal * (1.-barPorosity) ; + } + else if (phaseIdx == wPhaseIdx or phaseIdx == nPhaseIdx){ + const Scalar iSaturation = iFluidState.saturation(phaseIdx); + const Scalar kSaturation = kFluidState.saturation(phaseIdx); + const Scalar barSaturation = Dumux::harmonicMean(iSaturation, kSaturation); + flux[energyEq0Idx + phaseIdx] -= barLambda * gradientNormal * barPorosity * barSaturation ; + } + else + DUNE_THROW(Dune::NotImplemented, + "wrong index"); + } + /*! + * \brief Calculate the source term of the equation + * + * \param source The source/sink in the sub-control volume for each component + * \param volVars The volume variables + * \param componentIntoPhaseMassTransfer + */ + + static void computeSource(PrimaryVariables & source, + const VolumeVariables & volVars, + const ComponentVector componentIntoPhaseMassTransfer[numPhases]) + { + const Scalar awn = volVars.interfacialArea(wPhaseIdx, nPhaseIdx); + const Scalar aws = volVars.interfacialArea(wPhaseIdx, sPhaseIdx); + const Scalar ans = volVars.interfacialArea(nPhaseIdx, sPhaseIdx); + + const Scalar Tw = volVars.temperature(wPhaseIdx); + const Scalar Tn = volVars.temperature(nPhaseIdx); + const Scalar Ts = volVars.temperature(sPhaseIdx); + + const Scalar lambdaWetting = volVars.thermalConductivity(wPhaseIdx); + const Scalar lambdaNonWetting = volVars.thermalConductivity(nPhaseIdx); + const Scalar lambdaSolid = volVars.thermalConductivity(sPhaseIdx); + + // todo which average? + // Using a harmonic average is justified by its properties: if one phase does not conduct energy, there is no transfer + const Scalar lambdaWN = Dumux::harmonicMean(lambdaWetting, lambdaNonWetting); + const Scalar lambdaWS = Dumux::harmonicMean(lambdaWetting, lambdaSolid); + const Scalar lambdaNS = Dumux::harmonicMean(lambdaNonWetting, lambdaSolid); +// |------------------------------------------------------| +// | | | +// | | | +// | alpha | i | +// | T_alpha | T_i | +// | | | +// | | | +// |------------------------------------------------------| + +// T_i > T_\alpha i.e. heat going into \alpha phase + +// Q_{i \leadsto \alpha} = a_{\alpha i} lambda_{\alpha i} (T_i - T_\alpha) / d // i.e.: this is the r.h.s. of alpha + const Scalar characteristicLength = volVars.characteristicLength() ; + const Scalar factorEnergyTransfer = volVars.factorEnergyTransfer() ; + + const Scalar nusseltWN = Dumux::harmonicMean(volVars.nusseltNumber(wPhaseIdx), volVars.nusseltNumber(nPhaseIdx)); + const Scalar nusseltWS = volVars.nusseltNumber(wPhaseIdx); + const Scalar nusseltNS = volVars.nusseltNumber(nPhaseIdx); + +//#warning SET NUSSELT TO 1 +// const Scalar nusseltWN = 1. ; +// const Scalar nusseltWS = 1. ; +// const Scalar nusseltNS = 1. ; + + const Scalar wettingToNonWettingEnergyExchange = factorEnergyTransfer * (Tw - Tn) / characteristicLength * awn * lambdaWN * nusseltWN ; + const Scalar wettingToSolidEnergyExchange = factorEnergyTransfer * (Tw - Ts) / characteristicLength * aws * lambdaWS * nusseltWS ; + const Scalar nonWettingToSolidEnergyExchange = factorEnergyTransfer * (Tn - Ts) / characteristicLength * ans * lambdaNS * nusseltNS ; + +//#warning HEAT TRANSFER OFF +// const Scalar wettingToNonWettingEnergyExchange = 0. ; +// const Scalar wettingToSolidEnergyExchange = 0. ; +// const Scalar nonWettingToSolidEnergyExchange = 0. ; + + + for(int phaseIdx =0; phaseIdx<numEnergyEqs; ++phaseIdx){ + switch (phaseIdx){ + case wPhaseIdx: + source[energyEq0Idx + phaseIdx] = ( - wettingToNonWettingEnergyExchange - wettingToSolidEnergyExchange); + break; + case nPhaseIdx: + source[energyEq0Idx + phaseIdx] = (+ wettingToNonWettingEnergyExchange - nonWettingToSolidEnergyExchange); + break; + case sPhaseIdx: + source[energyEq0Idx + phaseIdx] = (+ wettingToSolidEnergyExchange + nonWettingToSolidEnergyExchange); + break; + default: + DUNE_THROW(Dune::NotImplemented, + "wrong index"); + } // end switch + + + + if (!std::isfinite(source[energyEq0Idx + phaseIdx])) + DUNE_THROW(NumericalProblem, "Calculated non-finite source, " << "Tw="<< Tw << " Tn="<< Tn<< " Ts="<< Ts); + }// end phases + +#define MASS_ENERGY_TRANSPORT 1 +#if MASS_ENERGY_TRANSPORT +// Here comes the catch: We are not doing energy conservation for the whole +// system, but rather for each individual phase. +// -> Therefore the energy fluxes over each phase boundary need be +// individually accounted for. +// -> Each particle crossing a phase boundary does carry some mass and +// thus energy! +// -> Therefore, this contribution needs to be added. + +// -> the particle always brings the energy of the originating phase. +// -> Energy advectivly transported into a phase = the moles of a component that go into a +// phase * molMass * enthalpy of the component in the *originating* phase + + // The fluidsystem likes to get a fluidstate. ... + const FluidState & fluidState = volVars.fluidState(); + + for(int phaseIdx =0; phaseIdx<numEnergyEqs; ++phaseIdx){ + switch (phaseIdx){ + case wPhaseIdx: + source[energyEq0Idx + phaseIdx] += (componentIntoPhaseMassTransfer[wPhaseIdx][nCompIdx] + * FluidSystem::molarMass(nCompIdx) + * FluidSystem::componentEnthalpy(fluidState, nPhaseIdx, nCompIdx) ); + source[energyEq0Idx + phaseIdx] += (componentIntoPhaseMassTransfer[wPhaseIdx][wCompIdx] + * FluidSystem::molarMass(wCompIdx) + * FluidSystem::componentEnthalpy(fluidState, nPhaseIdx, wCompIdx)); + break; + case nPhaseIdx: + source[energyEq0Idx + phaseIdx] += (componentIntoPhaseMassTransfer[nPhaseIdx][nCompIdx] + * FluidSystem::molarMass(nCompIdx) + * FluidSystem::componentEnthalpy(fluidState, wPhaseIdx, nCompIdx)); + source[energyEq0Idx + phaseIdx] += (componentIntoPhaseMassTransfer[nPhaseIdx][wCompIdx] + * FluidSystem::molarMass(wCompIdx) + * FluidSystem::componentEnthalpy(fluidState, wPhaseIdx, wCompIdx)); + break; + case sPhaseIdx: + break; // no sorption + default: + DUNE_THROW(Dune::NotImplemented, + "wrong index"); + } // end switch + }// end phases +#endif //MASS_ENERGY_TRANSPORT + Valgrind::CheckDefined(source); + }// end source +}; + + +/*! + * \brief Specialization for the case of *2* energy balance equations. + */ +template <class TypeTag> +class MPNCLocalResidualEnergy<TypeTag, /*enableEnergy=*/true, /*numEnergyEquations=*/2> +{ + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; + typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; + typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + + enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; + enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; + enum { energyEq0Idx = Indices::energyEq0Idx }; + enum { numEnergyEqs = Indices::numPrimaryEnergyVars}; + enum { wPhaseIdx = FluidSystem::wPhaseIdx}; + enum { nPhaseIdx = FluidSystem::nPhaseIdx}; + enum { nCompIdx = FluidSystem::nCompIdx}; + enum { wCompIdx = FluidSystem::wCompIdx}; + enum { sPhaseIdx = FluidSystem::sPhaseIdx}; + enum { energyEqSolidIdx = Indices::energyEqSolidIdx}; + enum { temperatureFluidIdx = Indices::temperatureFluidIdx}; + enum { temperatureSolidIdx = Indices::temperatureSolidIdx}; + enum { dim = GridView::dimension}; // Grid and world dimension + + + typedef typename Dune::FieldVector<Scalar, numComponents> ComponentVector; + typedef typename Dune::FieldMatrix<Scalar, numPhases, numComponents> PhaseComponentMatrix; + typedef typename FluidSystem::ParameterCache ParameterCache; + + typedef typename GET_PROP_TYPE(TypeTag, BaseLocalResidual) ParentType; + typedef Dumux::Spline<Scalar> Spline; + + +public: + /*! \brief Evaluate the amount all conservation quantities + * (e.g. phase mass) within a sub-control volume. + * + * The result should be averaged over the volume (e.g. phase mass + * inside a sub-control volume divided by the volume) + * + * \param storage The mass of the component within the sub-control volume + * \param volVars the Volume Variables + */ + static void computeStorage(PrimaryVariables & storage, + const VolumeVariables & volVars) + { + for(int energyEqIdx=0; energyEqIdx< numEnergyEqs; energyEqIdx++) + storage[energyEq0Idx+energyEqIdx] = 0; + + // energy of the fluids + for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { + addPhaseStorage(storage, volVars, phaseIdx); + } + // heat stored in the rock matrix + storage[energyEqSolidIdx] += + volVars.temperature(temperatureSolidIdx) + * volVars.solidDensity() + * (1.0 - volVars.porosity()) + * volVars.solidHeatCapacity(); + + if (!std::isfinite(storage[energyEqSolidIdx])) + DUNE_THROW(NumericalProblem, "Calculated non-finite storage"); + } + + /*! \brief Calculate the storage for all mass balance equations + * within a single fluid phase + * + * \param storage The mass of the component within the sub-control volume + * \param volVars the Volume Variables + * \param phaseIdx The local index of the phases + */ + static void addPhaseStorage(PrimaryVariables & storage, + const VolumeVariables & volVars, + const unsigned int phaseIdx) + { + + const FluidState & fs = volVars.fluidState(); + + if (phaseIdx not_eq sPhaseIdx) { + storage[energyEq0Idx ] += + fs.density(phaseIdx) * + fs.internalEnergy(phaseIdx) * + fs.saturation(phaseIdx) * + volVars.porosity(); + } + else + DUNE_THROW(Dune::NotImplemented, + "wrong index"); + + if (!std::isfinite(storage[energyEq0Idx])) + DUNE_THROW(NumericalProblem, "Calculated non-finite storage"); + } + + /*!\brief Evaluates the total flux of all conservation quantities + * over a face of a sub-control volume. + * + * \param flux The flux over the SCV (sub-control-volume) face for each component + * \param fluxVars The flux Variables + * \param elemVolVars The volume variables of the current element + * \param molarPhaseComponentValuesMassTransport + */ + static void computeFlux(PrimaryVariables & flux, + const FluxVariables & fluxVars, + const ElementVolumeVariables & elemVolVars, + const ComponentVector molarPhaseComponentValuesMassTransport[numPhases]) + { + // reset all energy fluxes + for(int energyEqIdx=0; energyEqIdx<numEnergyEqs; ++energyEqIdx) + flux[energyEq0Idx + energyEqIdx] = 0.0; + + // only the fluid phases transport enthalpy + for(int phaseIdx=0; phaseIdx<numPhases; ++phaseIdx) + computePhaseEnthalpyFlux(flux, + fluxVars, + elemVolVars, + phaseIdx, + molarPhaseComponentValuesMassTransport[phaseIdx]); + + // all phases take part in conduction + for(int energyEqIdx=0; energyEqIdx<numEnergyEqs; ++energyEqIdx){ + computeHeatConduction(flux, + fluxVars, + elemVolVars, + energyEqIdx); + + if (!std::isfinite(flux[energyEq0Idx + energyEqIdx])) + DUNE_THROW(NumericalProblem, "Calculated non-finite flux in phase " << energyEqIdx); + } + } + + /*! \brief the advective Flux of the enthalpy + * \param flux The flux over the SCV (sub-control-volume) face for each component + * \param fluxVars The flux Variables + * \param elemVolVars The volume variables of the current element + * \param phaseIdx The local index of the phases + * \param molarComponentValuesMassTransport + */ + static void computePhaseEnthalpyFlux(PrimaryVariables & flux, + const FluxVariables & fluxVars, + const ElementVolumeVariables & elemVolVars, + const unsigned int phaseIdx, + const ComponentVector & molarComponentValuesMassTransport) + { + Scalar massFlux = 0; // mass flux is not the perfect term: sum_kappa (rho_alpha v_alpha x_alpha^kappa) = v_alpha rho_alpha + + // calculate the mass flux in the phase i.e. make mass flux out + // of mole flux and add up the fluxes of a phase + for (int compIdx = 0; compIdx < numComponents; ++compIdx){ + massFlux += molarComponentValuesMassTransport[compIdx] + * FluidSystem::molarMass(compIdx) ; + } + + unsigned int upIdx = fluxVars.face().i; + unsigned int dnIdx = fluxVars.face().j; + if (massFlux < 0){ + upIdx = fluxVars.face().j; + dnIdx = fluxVars.face().i; + } + + // use the phase enthalpy of the upstream vertex to calculate + // the enthalpy transport + const VolumeVariables & up = elemVolVars[upIdx]; + const VolumeVariables & dn = elemVolVars[dnIdx]; + + /* todo + * CAUTION: this is not exactly correct: does diffusion carry the upstream phase enthalpy? To be more precise this should be the components enthalpy. In the same vein: Counter current diffusion is not accounted for here. + */ + const Scalar transportedThingUp = up.fluidState().enthalpy(phaseIdx) ; + const Scalar transportedThingDn = dn.fluidState().enthalpy(phaseIdx) ; + + const Scalar massUpwindWeight_ = GET_PARAM_FROM_GROUP(TypeTag, Scalar, Implicit, MassUpwindWeight); + flux[energyEq0Idx] += massFlux * + (massUpwindWeight_ * transportedThingUp + + + (1.-massUpwindWeight_) * transportedThingDn ) ; + } + + /*! \brief The heat conduction in the phase + * + * \param flux The flux over the SCV (sub-control-volume) face for each component + * \param fluxVars The flux Variables + * \param elemVolVars The volume variables of the current element + * \param energyEqIdx The index of the phase energy equation + */ + static void computeHeatConduction(PrimaryVariables & flux, + const FluxVariables & fluxVars, + const ElementVolumeVariables & elemVolVars, + const unsigned int energyEqIdx) + { + const unsigned int iIdx = fluxVars.face().i; + const unsigned int kIdx = fluxVars.face().j; // k can be better distinguished from i + + const VolumeVariables & iVolVar = elemVolVars[iIdx]; + const VolumeVariables & kVolVar = elemVolVars[kIdx]; + + const Scalar iPorosity = iVolVar.porosity(); + const Scalar kPorosity = kVolVar.porosity(); + const Scalar barPorosity = Dumux::harmonicMean(iPorosity, kPorosity); + + const Scalar iSolidLambda = iVolVar.thermalConductivity(sPhaseIdx); + const Scalar kSolidLambda = kVolVar.thermalConductivity(sPhaseIdx); + + // Using a harmonic average is justified by its properties: if one phase does not conduct energy, there is no transfer + const Scalar barSolidLambda = (iSolidLambda+kSolidLambda) / 2.0; + + const Scalar lumpedConductivity = fluxVars.fluxVarsEnergy().lambdaEff() ; + + const Scalar gradientNormal = fluxVars.fluxVarsEnergy().temperatureGradient(energyEqIdx) + * fluxVars.face().normal ; + + // heat conduction of the rock matrix and the fluid phases + if (energyEqIdx == temperatureSolidIdx){ + flux[energyEqSolidIdx] -= barSolidLambda * (1.-barPorosity) * gradientNormal ; + } + else if (energyEqIdx == temperatureFluidIdx){ + flux[energyEq0Idx ] -= lumpedConductivity /*already includes porosity*/ * gradientNormal ; + } + else + DUNE_THROW(Dune::NotImplemented, + "wrong index"); + } + + /*! \brief Calculate the source term of the equation + * + * \param source The source/sink in the sub-control volume for each component + * \param volVars The volume variables + * \param componentIntoPhaseMassTransfer + */ + static void computeSource(PrimaryVariables & source, + const VolumeVariables & volVars, + const ComponentVector componentIntoPhaseMassTransfer[numPhases]) + { + const Scalar solidToFluidEnergyExchange = qsf(volVars) ; + + for(int energyEqIdx =0; energyEqIdx<numEnergyEqs; ++energyEqIdx){ + switch (energyEqIdx){ + case 0 : + source[energyEq0Idx + energyEqIdx] = solidToFluidEnergyExchange; + break; + case 1 : + source[energyEq0Idx + energyEqIdx] = - solidToFluidEnergyExchange; + break; + default: + DUNE_THROW(Dune::NotImplemented, + "wrong index"); + } // end switch + }// end energyEqIdx + Valgrind::CheckDefined(source); + }// end source + + + /*! \brief Calculate the whole energy transfer + * + * \param volVars The volume variables + */ + static Scalar qsf(const VolumeVariables & volVars) + { + const FluidState & fs = volVars.fluidState() ; + const Scalar characteristicLength = volVars.characteristicLength() ; + + // Shi & Wang, Transport in porous media (2011) + const Scalar as = 6.0 * (1.0-volVars.porosity()) / characteristicLength ; + + const Scalar TFluid = volVars.temperature(temperatureFluidIdx); + const Scalar TSolid = volVars.temperature(temperatureSolidIdx); + + const Scalar satW = fs.saturation(wPhaseIdx) ; + const Scalar satN = fs.saturation(nPhaseIdx) ; + + const Scalar eps = 1e-6 ; + Scalar solidToFluidEnergyExchange ; + + Scalar fluidConductivity ; + if (satW < 1.0 - eps) + fluidConductivity = volVars.thermalConductivity(nPhaseIdx) ; + else if (satW >= 1.0 - eps) + fluidConductivity = volVars.thermalConductivity(wPhaseIdx) ; + else + DUNE_THROW(Dune::NotImplemented, + "wrong range"); + + const Scalar factorEnergyTransfer = volVars.factorEnergyTransfer() ; + + solidToFluidEnergyExchange = factorEnergyTransfer * (TSolid - TFluid) / characteristicLength * as * fluidConductivity ; + + const Scalar epsRegul = 1e-3 ; + + if (satW < (0 + eps) ) + solidToFluidEnergyExchange *= volVars.nusseltNumber(nPhaseIdx) ; + + else if ( (satW >= 0 + eps) and (satW < 1.0-eps) ){ + solidToFluidEnergyExchange *= (volVars.nusseltNumber(nPhaseIdx) * satN ); + Scalar qBoil ; + + if (satW<=epsRegul){// regularize + Spline sp(0.0, epsRegul, // x1, x2 + QBoilFunc(volVars, 0.0), QBoilFunc(volVars, epsRegul), // y1, y2 + 0.0, dQBoil_dSw(volVars, epsRegul) ); // m1, m2 + + qBoil = sp.eval(satW) ; + } + + else if (satW>= (1.0-epsRegul) ){// regularize + Spline sp(1.0-epsRegul, 1.0, // x1, x2 + QBoilFunc(volVars, 1.0-epsRegul), 0.0, // y1, y2 + dQBoil_dSw(volVars, 1.0-epsRegul), 0.0 ); // m1, m2 + + qBoil = sp.eval(satW) ; + } + else + qBoil = QBoilFunc(volVars, satW) ; + + solidToFluidEnergyExchange += qBoil; + } + else if (satW >= 1.0-eps) + solidToFluidEnergyExchange *= volVars.nusseltNumber(wPhaseIdx) ; + else + DUNE_THROW(Dune::NotImplemented, + "wrong range"); + + if (!std::isfinite(solidToFluidEnergyExchange)) + DUNE_THROW(NumericalProblem, "Calculated non-finite source, " << "TFluid="<< TFluid << " TSolid="<< TSolid ); + + return solidToFluidEnergyExchange ; + } + + /*! \brief Calculate the energy transfer during boiling, i.e. latent heat + * + * \param volVars The volume variables + * \param satW The wetting phase saturation. Not taken from volVars, because we regularize. + */ + static Scalar QBoilFunc(const VolumeVariables & volVars, + const Scalar satW) + { + // using saturation as input (instead of from volVars) + // in order to make regularization (evaluation at different points) easyer + const FluidState & fs = volVars.fluidState() ; + const Scalar g( 9.81 ) ; + const Scalar gamma(0.0589) ; + const Scalar TSolid = volVars.temperature(temperatureSolidIdx); + const Scalar characteristicLength = volVars.characteristicLength() ; + + const Scalar as = 6.0 * (1.0-volVars.porosity()) / characteristicLength ; + const Scalar mul = fs.viscosity(wPhaseIdx) ; + const Scalar deltahv = fs.enthalpy(nPhaseIdx) - fs.enthalpy(wPhaseIdx); + const Scalar deltaRho = fs.density(wPhaseIdx) - fs.density(nPhaseIdx) ; + const Scalar firstBracket = std::pow(g * deltaRho / gamma, 0.5); + const Scalar cp = FluidSystem::heatCapacity(fs, wPhaseIdx) ; + // This use of Tsat is only justified if the fluid is always boiling (tsat equals boiling conditions) + // If a different state is to be simulated, please use the actual fluid temperature instead. + const Scalar Tsat = FluidSystem::vaporTemperature(fs, nPhaseIdx ) ; + const Scalar deltaT = TSolid - Tsat ; + const Scalar secondBracket = std::pow( (cp *deltaT / (0.006 * deltahv) ) , 3.0 ) ; + const Scalar Prl = volVars.prandtlNumber(wPhaseIdx) ; + const Scalar thirdBracket = std::pow( 1/Prl , (1.7/0.33) ); + const Scalar QBoil = satW * as * mul * deltahv * firstBracket * secondBracket * thirdBracket ; + return QBoil; + } + + /*! \brief Calculate the derivative of the energy transfer function during boiling. Needed for regularization. + * + * \param volVars The volume variables + * \param satW The wetting phase saturation. Not taken from volVars, because we regularize. + */ + static Scalar dQBoil_dSw(const VolumeVariables & volVars, + const Scalar satW) + { + // on the fly derive w.r.t. Sw. + // Only linearly depending on it (directly) + return (QBoilFunc(volVars, satW) / satW ) ; + } +}; + + +} // end namespace Dumux + +#endif // DUMUX_MPNC_LOCAL_RESIDUAL_ENERGY_KINETIC_HH diff --git a/dumux/porousmediumflow/mpnc/implicit/energy/volumevariables.hh b/dumux/porousmediumflow/mpnc/implicit/energy/volumevariables.hh new file mode 100644 index 0000000000000000000000000000000000000000..e4d83ae3e4c323a836cc7948921b473749fa3026 --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/energy/volumevariables.hh @@ -0,0 +1,248 @@ +// -*- 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 Contains the energy part of volume variables of the MpNc model. + */ +#ifndef DUMUX_MPNC_ENERGY_VOLUME_VARIABLES_HH +#define DUMUX_MPNC_ENERGY_VOLUME_VARIABLES_HH + +#include <dumux/porousmediumflow/mpnc/implicit/properties.hh> +#include <dumux/material/fluidstates/compositionalfluidstate.hh> + +namespace Dumux +{ +/*! + * \brief Contains the energy related quantities which are constant within a + * finite volume in a MpNc model. + * + * This is the dummy class for the isothermal case. Note that we're + * only isothermal in the sense that the temperature at a location and + * a time is specified outside of the model! + */ +template <class TypeTag, bool enableEnergy/*=false*/, int numEnergyEquations /*=don't care*/> +class MPNCVolumeVariablesEnergy +{ + static_assert(not (numEnergyEquations and not enableEnergy), + "No kinetic energy transfer may only be enabled " + "if energy is enabled in general."); + static_assert(numEnergyEquations < 1, + "No kinetic energy transfer module included, " + "but kinetic energy transfer enabled."); + + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GridView::template Codim<0>::Entity Element; + typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + + enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; + + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; + typedef typename FluidSystem::ParameterCache ParameterCache; + enum {dimWorld=GridView::dimensionworld}; + typedef Dune::FieldVector<Scalar,dimWorld> GlobalPosition; + + +public: + /*! + * \brief Update the temperature of the sub-control volume. + * + * \param fs Container for all the secondary variables concerning the fluids + * \param paramCache Container for cache parameters + * \param priVars The primary Variables + * \param element The finite element + * \param fvGeometry The finite-volume geometry in the fully implicit scheme + * \param scvIdx The index of the sub-control volume + * \param problem The problem + */ + void updateTemperatures(FluidState &fs, + ParameterCache ¶mCache, + const PrimaryVariables &priVars, + const Element &element, + const FVElementGeometry &fvGeometry, + const unsigned int scvIdx, + const Problem &problem) const + { + Scalar T = problem.temperatureAtPos(fvGeometry.subContVol[scvIdx].global); + fs.setTemperature(T); + } + + + /*! + * \brief Update the enthalpy and the internal energy for a given + * control volume. + * \param fs Container for all the secondary variables concerning the fluids + * \param paramCache Container for cache parameters + * \param element The finite element + * \param fvGeometry The finite-volume geometry in the fully implicit scheme + * \param scvIdx The index of the sub-control volume + * \param problem The problem + * + * Since we are isothermal, we don't need to do anything! + */ + void update(FluidState &fs, + ParameterCache ¶mCache, + const Element &element, + const FVElementGeometry &fvGeometry, + const unsigned int scvIdx, + const Problem &problem) + { + } + + /*! + * \brief If running under valgrind this produces an error message + * if some of the object's attributes is undefined. + */ + void checkDefined() const + { + } +}; + +/*! + * \brief Contains the energy related quantities which are constant within a + * finite volume in the two-phase, N-component model. + */ +template <class TypeTag> +class MPNCVolumeVariablesEnergy<TypeTag, /*enableEnergy=*/true, /*numEnergyEquations=*/ 1 > +{ + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GridView::template Codim<0>::Entity Element; + typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + + enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; + enum { temperatureIdx = Indices::temperatureIdx }; + enum { numEnergyEqs = Indices::numPrimaryEnergyVars}; + enum { temperature0Idx = Indices::temperatureIdx }; + + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; + typedef typename FluidSystem::ParameterCache ParameterCache; + + enum { dimWorld = GridView::dimensionworld}; + typedef Dune::FieldVector<typename GridView::Grid::ctype, dimWorld> GlobalPosition; + +public: + /*! + * \brief Update the temperature of the sub-control volume. + * + * \param fs Container for all the secondary variables concerning the fluids + * \param paramCache Container for cache parameters + * \param sol The primary Vaiables + * \param element The finite element + * \param fvGeometry The finite-volume geometry in the fully implicit scheme + * \param scvIdx The index of the sub-control volume + * \param problem The problem + */ + void updateTemperatures(FluidState &fs, + ParameterCache ¶mCache, + const PrimaryVariables &sol, + const Element &element, + const FVElementGeometry &fvGeometry, + const unsigned int scvIdx, + const Problem &problem) const + { + // retrieve temperature from solution vector + Scalar T = sol[temperatureIdx]; + fs.setTemperature(T); + } + + /*! + * \brief Update the enthalpy and the internal energy for a given + * control volume. + * \param fs Container for all the secondary variables concerning the fluids + * \param paramCache Container for cache parameters + * \param element The finite element + * \param fvGeometry The finite-volume geometry in the fully implicit scheme + * \param scvIdx The index of the sub-control volume + * \param problem The problem + */ + void update(FluidState &fs, + ParameterCache ¶mCache, + const Element &element, + const FVElementGeometry &fvGeometry, + const unsigned int scvIdx, + const Problem &problem) + { + Valgrind::SetUndefined(*this); + + // heat capacities of the fluids plus the porous medium + solidHeatCapacity_ = + problem.spatialParams().solidHeatCapacity(element, fvGeometry, scvIdx); + Valgrind::CheckDefined(solidHeatCapacity_); + + solidDensity_ = + problem.spatialParams().solidDensity(element, fvGeometry, scvIdx); + Valgrind::CheckDefined(solidDensity_); + + // set the enthalpies + for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { + Scalar h = FluidSystem::enthalpy(fs, paramCache, phaseIdx); + fs.setEnthalpy(phaseIdx, h); + thermalConductivity_[phaseIdx] = FluidSystem::thermalConductivity(fs, phaseIdx); + } + } + + /*! + * \brief Returns the total heat capacity [J/(kg K)] of the rock matrix in + * the sub-control volume. + */ + Scalar solidHeatCapacity() const + { return solidHeatCapacity_; } + + /*! + * \brief Returns the thermal conductivity \f$\mathrm{[W/(m*K)]}\f$ of the fluid phase in + * the sub-control volume. + */ + Scalar thermalConductivity(const unsigned int phaseIdx) const + { return thermalConductivity_[phaseIdx] ; } + + /*! + * \brief Returns the total density of the given solid phase [kg / m^3] in + * the sub-control volume. + */ + Scalar solidDensity() const + { return solidDensity_; } + + /*! + * \brief If running under valgrind this produces an error message + * if some of the object's attributes is undefined. + */ + void checkDefined() const + { + Valgrind::CheckDefined(solidHeatCapacity_); + Valgrind::CheckDefined(solidDensity_); + } + +protected: + Scalar solidHeatCapacity_; + Scalar solidDensity_; + Scalar thermalConductivity_[numPhases] ; +}; + +} // end namespace + +#endif diff --git a/dumux/porousmediumflow/mpnc/implicit/energy/volumevariableskinetic.hh b/dumux/porousmediumflow/mpnc/implicit/energy/volumevariableskinetic.hh new file mode 100644 index 0000000000000000000000000000000000000000..bc5595301a2e88f1c09c662925219e6a202ee446 --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/energy/volumevariableskinetic.hh @@ -0,0 +1,442 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 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 Contains the volume variables of the kinetic energy transfer + * module of the M-phase, N-component model. + */ +#ifndef DUMUX_MPNC_ENERGY_VOLUME_VARIABLES_KINETIC_HH +#define DUMUX_MPNC_ENERGY_VOLUME_VARIABLES_KINETIC_HH + +#include <dumux/porousmediumflow/mpnc/implicit/volumevariables.hh> +#include "vtkwriterkinetic.hh" + +namespace Dumux +{ +/*! + * \brief Contains the volume variables of the kinetic energy transfer + * module of the M-phase, N-component model. + * Specialization for the case of *3* energy balance equations. + */ +template <class TypeTag> +class MPNCVolumeVariablesEnergy<TypeTag, /*enableEnergy=*/true, /*numEnergyEquations=*/3> +{ + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GridView::template Codim<0>::Entity Element; + typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + + enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; + enum { temperature0Idx = Indices::temperature0Idx }; + enum { nPhaseIdx = FluidSystem::nPhaseIdx }; + enum { wPhaseIdx = FluidSystem::wPhaseIdx }; + enum { sPhaseIdx = FluidSystem::sPhaseIdx }; + enum { numEnergyEqs = Indices::numPrimaryEnergyVars}; + + /*! + * \brief The fluid state which is used by the volume variables to + * store the thermodynamic state. + * + * If chemical equilibrium is not considered, we use the most + * generic fluid state. + */ + typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; + typedef typename FluidSystem::ParameterCache ParameterCache; + +public: + /*! + * \brief Update the temperature of the sub-control volume. + * + * \param priVars The primary variables + * \param element The finite Element + * \param fvGeometry The finite-volume geometry in the fully implicit scheme + * \param scvIdx The index of the sub-control volume + * \param problem The problem + * \param temperatureIdx The temperature Index + */ + Scalar getTemperature(const PrimaryVariables & priVars, + const Element & element, + const FVElementGeometry & fvGeometry, + const unsigned int scvIdx, + const Problem & problem, + const unsigned int temperatureIdx) const + { + // retrieve temperature from solution vector + return priVars[temperature0Idx + temperatureIdx]; // could also be solid phase + } + + /*! + * \brief Update the temperature of the sub-control volume. + * + * \param fluidState Container for all the secondary variables concerning the fluids + * \param paramCache Container for cache parameters + * \param priVars The primary Variables + * \param element The finite element + * \param fvGeometry The finite-volume geometry in the fully implicit scheme + * \param scvIdx The index of the sub-control volume + * \param problem The problem + */ + void updateTemperatures(FluidState & fluidState, + ParameterCache & paramCache, + const PrimaryVariables & priVars, + const Element & element, + const FVElementGeometry & fvGeometry, + const unsigned int scvIdx, + const Problem & problem) + { + assert(numPhases + 1 == numEnergyEqs); + for(int phaseIdx=0; phaseIdx < numPhases; ++phaseIdx){ + // retrieve temperature from solution vector + const Scalar T = priVars[temperature0Idx + phaseIdx]; + temperature_[phaseIdx]= T; + fluidState.setTemperature(phaseIdx, T); + } + + temperature_[sPhaseIdx] = priVars[temperature0Idx + sPhaseIdx]; + + Valgrind::CheckDefined(temperature_); + } + + /*! + * \brief Update the enthalpy and the internal energy for a given + * control volume. + * + * \param fluidState Container for all the secondary variables concerning the fluids + * \param paramCache Container for cache parameters + * \param element The finite element + * \param fvGeometry The finite-volume geometry in the fully implicit scheme + * \param scvIdx The index of the sub-control volume + * \param problem The problem + */ + void update(FluidState & fluidState, + ParameterCache & paramCache, + const Element & element, + const FVElementGeometry & fvGeometry, + const unsigned int scvIdx, + const Problem & problem) + { + solidHeatCapacity_ = + problem.spatialParams().solidHeatCapacity(element, fvGeometry, scvIdx); + Valgrind::CheckDefined(solidHeatCapacity_); + + for(int phaseIdx =0; phaseIdx<numPhases; ++phaseIdx){ + fluidThermalConductivity_[phaseIdx] = + FluidSystem::thermalConductivity(fluidState, paramCache, phaseIdx); + } + Valgrind::CheckDefined(fluidThermalConductivity_); + + + solidDensity_ = + problem.spatialParams().solidDensity(element, fvGeometry, scvIdx); + Valgrind::CheckDefined(solidDensity_); + + solidThermalConductivity_ = + problem.spatialParams().solidThermalConductivity(element, fvGeometry, scvIdx); + Valgrind::CheckDefined(solidThermalConductivity_); + + // set the enthalpies + for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { + Scalar h = FluidSystem::enthalpy(fluidState, paramCache, phaseIdx); + Valgrind::CheckDefined(h); + fluidState.setEnthalpy(phaseIdx, h); + } + } + + /*! + * \brief Returns the total heat capacity [J/(kg K)] of the rock matrix in + * the sub-control volume. + */ + Scalar solidHeatCapacity() const + { return solidHeatCapacity_; } + + /*! + * \brief Returns the temperature in fluid / solid phase(s) + * the sub-control volume. + * \param phaseIdx The local index of the phases + */ + Scalar temperature(const unsigned int phaseIdx) const + { return temperature_[phaseIdx]; } + + /*! + * \brief Returns the total density of the given solid phase [kg / m^3] in + * the sub-control volume. + */ + Scalar solidDensity() const + { return solidDensity_; } + + /*! + * \brief Returns the conductivity of the given solid phase [W/(m K)] in + * the sub-control volume. + */ + Scalar solidThermalConductivity() const + { return solidThermalConductivity_; } + + /*! + * \brief Returns the conductivity of the given fluid [W//m K)] in + * the sub-control volume. + * + * \param phaseIdx The local index of the phases + */ + Scalar thermalConductivity(const unsigned int phaseIdx) const + { + if(phaseIdx == wPhaseIdx or phaseIdx == nPhaseIdx ) + return fluidThermalConductivity_[phaseIdx]; + else if (phaseIdx == sPhaseIdx ) + return solidThermalConductivity_; + else + DUNE_THROW(Dune::NotImplemented, + "wrong index"); + } + + void checkDefinedTemp() const + { Valgrind::CheckDefined(temperature_); } + + /*! + * \brief If running under valgrind this produces an error message + * if some of the object's attributes is undefined. + */ + void checkDefined() const + { + Valgrind::CheckDefined(temperature_); + Valgrind::CheckDefined(fluidThermalConductivity_); + Valgrind::CheckDefined(solidThermalConductivity_); + Valgrind::CheckDefined(solidDensity_); + Valgrind::CheckDefined(solidHeatCapacity_); + } + +protected: + Scalar temperature_[numPhases + 1]; + Scalar solidHeatCapacity_; + Scalar solidDensity_; + Scalar solidThermalConductivity_; + Scalar fluidThermalConductivity_[numPhases]; +}; + + + +/*! + * \brief Contains the volume variables of the kinetic energy transfer + * module of the M-phase, N-component model. + * Specialization for the case of *2* energy balance equations. + */ +template <class TypeTag> +class MPNCVolumeVariablesEnergy<TypeTag, /*enableEnergy=*/true, /*numEnergyEquations=*/2> +{ + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GridView::template Codim<0>::Entity Element; + typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + + enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; + enum { temperature0Idx = Indices::temperature0Idx }; + enum { nPhaseIdx = FluidSystem::nPhaseIdx }; + enum { wPhaseIdx = FluidSystem::wPhaseIdx }; + enum { sPhaseIdx = FluidSystem::sPhaseIdx }; + enum { numEnergyEqs = Indices::numPrimaryEnergyVars}; + + /*! + * \brief The fluid state which is used by the volume variables to + * store the thermodynamic state. + * + * If chemical equilibrium is not considered, we use the most + * generic fluid state. + */ + typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; + typedef typename FluidSystem::ParameterCache ParameterCache; + +public: + /*! + * \brief Update the temperature of the sub-control volume. + * + * \param priVars The primary variables + * \param element The finite Element + * \param fvGeometry The finite-volume geometry in the fully implicit scheme + * \param scvIdx The index of the sub-control volume + * \param problem The problem + * \param temperatureIdx The temperature Index + */ + Scalar getTemperature(const PrimaryVariables & priVars, + const Element & element, + const FVElementGeometry & fvGeometry, + const unsigned int scvIdx, + const Problem & problem, + const unsigned int temperatureIdx) const + { + // retrieve temperature from solution vector + return priVars[temperature0Idx + temperatureIdx]; // could also be solid phase + } + + /*! + * \brief Update the temperature of the sub-control volume. + * + * \param fluidState Container for all the secondary variables concerning the fluids + * \param paramCache Container for cache parameters + * \param priVars The primary Variables + * \param element The finite element + * \param fvGeometry The finite-volume geometry in the fully implicit scheme + * \param scvIdx The index of the sub-control volume + * \param problem The problem + */ + void updateTemperatures(FluidState & fluidState, + ParameterCache & paramCache, + const PrimaryVariables & priVars, + const Element & element, + const FVElementGeometry & fvGeometry, + const unsigned int scvIdx, + const Problem & problem) + { + assert(2 == numEnergyEqs); + + for(int energyEqIdx=0; energyEqIdx < numPhases; ++energyEqIdx){ + // retrieve temperature from solution vector + const Scalar T = priVars[temperature0Idx + energyEqIdx]; + temperature_[energyEqIdx]= T; + } + + fluidState.setTemperature(priVars[temperature0Idx]); + + Valgrind::CheckDefined(temperature_); + } + + /*! + * \brief Update the enthalpy and the internal energy for a given + * control volume. + * + * \param fluidState Container for all the secondary variables concerning the fluids + * \param paramCache Container for cache parameters + * \param element The finite element + * \param fvGeometry The finite-volume geometry in the fully implicit scheme + * \param scvIdx The index of the sub-control volume + * \param problem The problem + */ + void update(FluidState & fluidState, + ParameterCache & paramCache, + const Element & element, + const FVElementGeometry & fvGeometry, + const unsigned int scvIdx, + const Problem & problem) + { + solidHeatCapacity_ = + problem.spatialParams().solidHeatCapacity(element, fvGeometry, scvIdx); + Valgrind::CheckDefined(solidHeatCapacity_); + + for(int phaseIdx =0; phaseIdx<numPhases; ++phaseIdx){ + fluidThermalConductivity_[phaseIdx] = + FluidSystem::thermalConductivity(fluidState, paramCache, phaseIdx); + } + Valgrind::CheckDefined(fluidThermalConductivity_); + + + solidDensity_ = + problem.spatialParams().solidDensity(element, fvGeometry, scvIdx); + Valgrind::CheckDefined(solidDensity_); + + solidThermalConductivity_ = + problem.spatialParams().solidThermalConductivity(element, fvGeometry, scvIdx); + Valgrind::CheckDefined(solidThermalConductivity_); + + // set the enthalpies + for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { + Scalar h = FluidSystem::enthalpy(fluidState, paramCache, phaseIdx); + Valgrind::CheckDefined(h); + fluidState.setEnthalpy(phaseIdx, h); + } + } + + /*! + * \brief Returns the total heat capacity [J/(kg K)] of the rock matrix in + * the sub-control volume. + */ + Scalar solidHeatCapacity() const + { return solidHeatCapacity_; } + + /*! + * \brief Returns the temperature in fluid / solid phase(s) + * the sub-control volume. + * \param phaseIdx The local index of the phases + */ + Scalar temperature(const unsigned int phaseIdx) const + { return temperature_[phaseIdx]; } + + /*! + * \brief Returns the total density of the given solid phase [kg / m^3] in + * the sub-control volume. + */ + Scalar solidDensity() const + { return solidDensity_; } + + /*! + * \brief Returns the conductivity of the given solid phase [W/(m K)] in + * the sub-control volume. + */ + Scalar solidThermalConductivity() const + { return solidThermalConductivity_; } + + /*! + * \brief Returns the conductivity of the given fluid [W/(m K)] in + * the sub-control volume. + * + * \param phaseIdx The local index of the phases + */ + Scalar thermalConductivity(const unsigned int phaseIdx) const + { + if(phaseIdx == wPhaseIdx or phaseIdx == nPhaseIdx ) + return fluidThermalConductivity_[phaseIdx]; + else if (phaseIdx == sPhaseIdx ) + return solidThermalConductivity_; + else + DUNE_THROW(Dune::NotImplemented, + "wrong index"); + } + + void checkDefinedTemp() const + { Valgrind::CheckDefined(temperature_); } + + /*! + * \brief If running under valgrind this produces an error message + * if some of the object's attributes is undefined. + */ + void checkDefined() const + { + Valgrind::CheckDefined(temperature_); + Valgrind::CheckDefined(fluidThermalConductivity_); + Valgrind::CheckDefined(solidThermalConductivity_); + Valgrind::CheckDefined(solidDensity_); + Valgrind::CheckDefined(solidHeatCapacity_); + } + +protected: + Scalar temperature_[numEnergyEqs]; + Scalar solidHeatCapacity_; + Scalar solidDensity_; + Scalar solidThermalConductivity_; + Scalar fluidThermalConductivity_[numPhases]; +}; + +} // end namespace + +#endif diff --git a/dumux/porousmediumflow/mpnc/implicit/energy/vtkwriter.hh b/dumux/porousmediumflow/mpnc/implicit/energy/vtkwriter.hh new file mode 100644 index 0000000000000000000000000000000000000000..abab6bbae5816477b24b97ffc797a03fa63ba02b --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/energy/vtkwriter.hh @@ -0,0 +1,229 @@ +// -*- 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 VTK writer module for the energy related quantities of the + * MpNc model. + */ +#ifndef DUMUX_MPNC_VTK_WRITER_ENERGY_HH +#define DUMUX_MPNC_VTK_WRITER_ENERGY_HH + +#include "../vtkwritermodule.hh" + +namespace Dumux +{ +/*! + * \ingroup MPNCModel + * + * \brief VTK writer module for the energy related quantities of the + * MpNc model. + * + * This is the specialization for the case without energy. + */ +template<class TypeTag, + bool enableEnergy /* = false */, + int numEnergyEquations/*=0*/> +class MPNCVtkWriterEnergy : public MPNCVtkWriterModule<TypeTag> +{ + static_assert(numEnergyEquations < 1, + "If you enable kinetic energy transfer between fluids, you" + "also have to enable the energy in general!"); + + typedef MPNCVtkWriterModule<TypeTag> ParentType; + + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes; + typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GridView::template Codim<0>::Entity Element; + + enum { dim = GridView::dimension }; + + typedef typename ParentType::ScalarVector ScalarVector; + typedef typename ParentType::PhaseVector PhaseVector; + enum { isBox = GET_PROP_VALUE(TypeTag, ImplicitIsBox) }; + enum { dofCodim = isBox ? dim : 0 }; + +public: + MPNCVtkWriterEnergy(const Problem &problem) + : ParentType(problem) + { + temperatureOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddTemperatures); + } + + /*! + * \brief Allocate memory for the scalar fields we would like to + * write to the VTK file. + */ + template <class MultiWriter> + void allocBuffers(MultiWriter &writer) + { + if (temperatureOutput_) this->resizeScalarBuffer_(temperature_, isBox); + } + + /*! + * \brief Modify the internal buffers according to the volume + * variables seen on an element + * + * \param element The finite element + * \param fvGeometry The finite-volume geometry in the fully implicit scheme + * \param elemVolVars The volume variables of the current element + * \param elemBcTypes The types of the boundary conditions for all vertices of the element + */ + void processElement(const Element &element, + const FVElementGeometry &fvGeometry, + const ElementVolumeVariables &elemVolVars, + const ElementBoundaryTypes &elemBcTypes) + { + for (int scvIdx = 0; scvIdx < fvGeometry.numScv; ++scvIdx) { + const unsigned int dofIdxGlobal = this->problem_.model().dofMapper().subIndex(element, scvIdx, dofCodim); + const VolumeVariables &volVars = elemVolVars[scvIdx]; + + if (temperatureOutput_) + temperature_[dofIdxGlobal] = volVars.fluidState().temperature(/*phaseIdx=*/0); + } + } + + /*! + * \brief Add all buffers to the VTK output writer. + */ + template <class MultiWriter> + void commitBuffers(MultiWriter &writer) + { + if (temperatureOutput_) + this->commitScalarBuffer_(writer, "T", temperature_, isBox); + } + +private: + bool temperatureOutput_; + + ScalarVector temperature_; +}; + +/*! + * \ingroup MPNCModel + * + * \brief VTK writer module for the energy related quantities of the + * MpNc model. + * + * This is the specialization for the case with an energy equation but + * local thermal equilibrium. (i.e. no kinetic energy transfer) + */ +template<class TypeTag> +class MPNCVtkWriterEnergy<TypeTag, /* enableEnergy = */ true, /* numEnergyEquations = */ 1 > + : public MPNCVtkWriterModule<TypeTag> +{ + typedef MPNCVtkWriterModule<TypeTag> ParentType; + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes; + typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GridView::template Codim<0>::Entity Element; + + enum { dim = GridView::dimension }; + enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; + + typedef typename ParentType::ScalarVector ScalarVector; + typedef typename ParentType::PhaseVector PhaseVector; + enum { isBox = GET_PROP_VALUE(TypeTag, ImplicitIsBox) }; + enum { dofCodim = isBox ? dim : 0 }; + +public: + MPNCVtkWriterEnergy(const Problem &problem) + : ParentType(problem) + { + temperatureOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddTemperatures); + enthalpyOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddEnthalpies); + internalEnergyOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddInternalEnergies); + } + + /*! + * \brief Allocate memory for the scalar fields we would like to + * write to the VTK file. + */ + template <class MultiWriter> + void allocBuffers(MultiWriter &writer) + { + if (temperatureOutput_) this->resizeScalarBuffer_(temperature_, isBox); + if (enthalpyOutput_) this->resizePhaseBuffer_(enthalpy_, isBox); + if (internalEnergyOutput_) this->resizePhaseBuffer_(internalEnergy_, isBox); + } + + /*! + * \brief Modify the internal buffers according to the volume + * variables seen on an element + * + * \param element The finite element + * \param fvGeometry The finite-volume geometry in the fully implicit scheme + * \param elemVolVars The volume variables of the current element + * \param elemBcTypes The types of the boundary conditions for all vertices of the element + */ + void processElement(const Element &element, + const FVElementGeometry &fvGeometry, + const ElementVolumeVariables &elemVolVars, + const ElementBoundaryTypes &elemBcTypes) + { + for (int scvIdx = 0; scvIdx < fvGeometry.numScv; ++scvIdx) { + int gobalIdx = this->problem_.model().dofMapper().subIndex(element, scvIdx, dofCodim); + const VolumeVariables &volVars = elemVolVars[scvIdx]; + + if (temperatureOutput_) temperature_[gobalIdx] = volVars.fluidState().temperature(/*phaseIdx=*/0); + for (int phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) { + if (enthalpyOutput_) + enthalpy_[phaseIdx][gobalIdx] = volVars.fluidState().enthalpy(phaseIdx); + if (internalEnergyOutput_) + internalEnergy_[phaseIdx][gobalIdx] = volVars.fluidState().internalEnergy(phaseIdx); + } + } + } + + /*! + * \brief Add all buffers to the VTK output writer. + */ + template <class MultiWriter> + void commitBuffers(MultiWriter &writer) + { + if (temperatureOutput_) + this->commitScalarBuffer_(writer, "T", temperature_, isBox); + if (enthalpyOutput_) + this->commitPhaseBuffer_(writer, "h_%s", enthalpy_, isBox); + if (internalEnergyOutput_) + this->commitPhaseBuffer_(writer, "u_%s", internalEnergy_, isBox); + } + +private: + bool temperatureOutput_; + bool enthalpyOutput_; + bool internalEnergyOutput_; + + ScalarVector temperature_; + PhaseVector enthalpy_; + PhaseVector internalEnergy_; +}; + +} + +#endif diff --git a/dumux/porousmediumflow/mpnc/implicit/energy/vtkwriterkinetic.hh b/dumux/porousmediumflow/mpnc/implicit/energy/vtkwriterkinetic.hh new file mode 100644 index 0000000000000000000000000000000000000000..a90707c50e7788a99678a9075a21b7ae2ee40ae1 --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/energy/vtkwriterkinetic.hh @@ -0,0 +1,533 @@ +// -*- 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 VTK writer module for the energy related quantities of the + * MpNc model. + */ +#ifndef DUMUX_MPNC_VTK_WRITER_ENERGY_KINETIC_HH +#define DUMUX_MPNC_VTK_WRITER_ENERGY_KINETIC_HH + +#include <dumux/porousmediumflow/mpnc/implicit/vtkwritermodule.hh> +#include <dumux/porousmediumflow/mpnc/implicit/energy/localresidualkinetic.hh> +#include "vtkwriter.hh" + +namespace Dumux +{ +/*! + * \ingroup MPNCModel + * + * \brief VTK writer module for the energy related quantities of the + * MpNc model. + * + * This is the specialization for the case with *3* energy balance equations and + * no local thermal equilibrium. (i.e. _including_ kinetic energy transfer) + */ +template<class TypeTag> +class MPNCVtkWriterEnergy<TypeTag, /*enableEnergy = */ true, /* numEnergyEquations = */ 3 > + : public MPNCVtkWriterModule<TypeTag> +{ + typedef MPNCVtkWriterModule<TypeTag> ParentType; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes; + typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GridView::template Codim<0>::Entity Element; + + enum { dim = GridView::dimension }; + enum { dimWorld = GridView::dimensionworld }; + enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; + enum { numEnergyEqs = Indices::numPrimaryEnergyVars}; + enum { velocityAveragingInModel = GET_PROP_VALUE(TypeTag, VelocityAveragingInModel) }; + + enum { reynoldsOutput = GET_PROP_VALUE(TypeTag, VtkAddReynolds) }; + enum { prandtlOutput = GET_PROP_VALUE(TypeTag, VtkAddPrandtl) }; + enum { nusseltOutput = GET_PROP_VALUE(TypeTag, VtkAddNusselt) }; + enum { interfacialAreaOutput= GET_PROP_VALUE(TypeTag, VtkAddInterfacialArea) }; + enum { velocityOutput = GET_PROP_VALUE(TypeTag, VtkAddVelocities) }; + + typedef typename ParentType::ScalarVector ScalarVector; + typedef typename ParentType::PhaseVector PhaseVector; + typedef typename ParentType::ComponentVector ComponentVector; + typedef std::array<ScalarVector, numEnergyEqs> EnergyEqVector; + + typedef Dune::FieldVector<Scalar, dimWorld> DimWorldVector; + typedef Dune::BlockVector<DimWorldVector> DimWorldField; + typedef std::array<DimWorldField, numPhases> PhaseDimWorldField; + + +public: + MPNCVtkWriterEnergy(const Problem &problem) + : ParentType(problem) + { + temperatureOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddTemperatures); + enthalpyOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddEnthalpies); + internalEnergyOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddInternalEnergies); + } + + /*! + * \brief Allocate memory for the scalar fields we would like to + * write to the VTK file. + */ + template <class MultiWriter> + void allocBuffers(MultiWriter &writer) + { + resizeTemperaturesBuffer_(temperature_); + this->resizeScalarBuffer_(TwMinusTn_); + this->resizeScalarBuffer_(TnMinusTs_); + this->resizeScalarBuffer_(awn_); + this->resizeScalarBuffer_(aws_); + this->resizeScalarBuffer_(ans_); + this->resizePhaseBuffer_(enthalpy_); + this->resizePhaseBuffer_(internalEnergy_); + this->resizePhaseBuffer_(reynoldsNumber_); + this->resizePhaseBuffer_(prandtlNumber_); + this->resizePhaseBuffer_(nusseltNumber_); + + /*only one of the two output options, otherwise paraview segfaults due to two times the same field name*/ + if (velocityAveragingInModel and not velocityOutput) { + Scalar numVertices = this->problem_.gridView().size(dim); + for (int phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) { + velocity_[phaseIdx].resize(numVertices); + velocity_[phaseIdx] = 0; + } + } + } + + /*! + * \brief Modify the internal buffers according to the volume + * variables seen on an element + * + * \param element The finite element + * \param fvGeometry The finite-volume geometry in the fully implicit scheme + * \param elemVolVars The volume variables of the current element + * \param elemBcTypes + */ + void processElement(const Element & element, + const FVElementGeometry & fvGeometry, + const ElementVolumeVariables & elemVolVars, + const ElementBoundaryTypes & elemBcTypes) + { + int numLocalVertices = element.geometry().corners(); + for (int localVertexIdx = 0; localVertexIdx < numLocalVertices; ++localVertexIdx) { + const unsigned int vIdxGlobal = this->problem_.vertexMapper().subIndex(element, localVertexIdx, dim); + const VolumeVariables &volVars = elemVolVars[localVertexIdx]; + + for (int phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) { + enthalpy_[phaseIdx][vIdxGlobal] = volVars.fluidState().enthalpy(phaseIdx); + internalEnergy_[phaseIdx][vIdxGlobal] = volVars.fluidState().internalEnergy(phaseIdx); + reynoldsNumber_[phaseIdx][vIdxGlobal] = volVars.reynoldsNumber(phaseIdx); + prandtlNumber_[phaseIdx][vIdxGlobal] = volVars.prandtlNumber(phaseIdx); + nusseltNumber_[phaseIdx][vIdxGlobal] = volVars.nusseltNumber(phaseIdx); + } + + // because numPhases only counts liquid phases + for (int phaseIdx = 0; phaseIdx < numEnergyEqs; ++ phaseIdx) { + temperature_[phaseIdx][vIdxGlobal] = volVars.temperature(phaseIdx); + Valgrind::CheckDefined(temperature_[phaseIdx][vIdxGlobal]); + } + + const unsigned int wPhaseIdx = FluidSystem::wPhaseIdx; + const unsigned int nPhaseIdx = FluidSystem::nPhaseIdx; + const unsigned int sPhaseIdx = FluidSystem::sPhaseIdx; + + TwMinusTn_[vIdxGlobal] = volVars.temperature(wPhaseIdx) - volVars.temperature(nPhaseIdx); + TnMinusTs_[vIdxGlobal] = volVars.temperature(nPhaseIdx) - volVars.temperature(sPhaseIdx); + + awn_[vIdxGlobal] = volVars.interfacialArea(wPhaseIdx, nPhaseIdx); + aws_[vIdxGlobal] = volVars.interfacialArea(wPhaseIdx, sPhaseIdx); + ans_[vIdxGlobal] = volVars.interfacialArea(nPhaseIdx, sPhaseIdx); + + /*only one of the two output options, otherwise paraview segfaults due to two times the same field name*/ + if (velocityAveragingInModel and not velocityOutput){ + // numVertices for vertexCentereed, numVolumes for volume centered + int numVertices = this->problem_.gridView().size(dim); + for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) + for (int I = 0; I < numVertices; ++I) + velocity_[phaseIdx][I] = this->problem_.model().volumeDarcyVelocity(phaseIdx, I); + } + } + } + + /*! + * \brief Add all buffers to the VTK output writer. + */ + template <class MultiWriter> + void commitBuffers(MultiWriter & writer) + { + + if(interfacialAreaOutput){ + this->commitScalarBuffer_(writer, "awn" , awn_); + this->commitScalarBuffer_(writer, "aws" , aws_); + this->commitScalarBuffer_(writer, "ans" , ans_); + } + + if (temperatureOutput_){ + this->commitTemperaturesBuffer_(writer, "T_%s", temperature_); + this->commitScalarBuffer_(writer, "TwMinusTn" , TwMinusTn_); + this->commitScalarBuffer_(writer, "TnMinusTs" , TnMinusTs_); + } + + if (enthalpyOutput_) + this->commitPhaseBuffer_(writer, "h_%s", enthalpy_); + if (internalEnergyOutput_) + this->commitPhaseBuffer_(writer, "u_%s", internalEnergy_); + if (reynoldsOutput) + this->commitPhaseBuffer_(writer, "reynoldsNumber_%s", reynoldsNumber_); + if (prandtlOutput) + this->commitPhaseBuffer_(writer, "prandtlNumber_%s", prandtlNumber_); + if (nusseltOutput) + this->commitPhaseBuffer_(writer, "nusseltNumber_%s", nusseltNumber_); + /*only one of the two output options, otherwise paraview segfaults due to two timies the same field name*/ + if (velocityAveragingInModel and not velocityOutput){ + for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { + // commit the phase velocity + std::ostringstream oss; + oss << "velocity_" << FluidSystem::phaseName(phaseIdx); + writer.attachVertexData(velocity_[phaseIdx], + oss.str(), + dim); + } + } + } + +private: + /*! + * \brief Allocate the space for a buffer storing temperatures. + * This is one more entry than (fluid) phases. + */ + void resizeTemperaturesBuffer_(EnergyEqVector & buffer, + bool vertexCentered = true) + { + Scalar n; // numVertices for vertexCentereed, numVolumes for volume centered + if (vertexCentered) + n = this->problem_.gridView().size(dim); + else + n = this->problem_.gridView().size(0); + + for (int energyEqIdx = 0; energyEqIdx < numEnergyEqs; ++energyEqIdx) { + buffer[energyEqIdx].resize(n); + std::fill(buffer[energyEqIdx].begin(), buffer[energyEqIdx].end(), 0.0); + } + } + +/*! + * \brief Add a buffer for the three tmeperatures (fluids+solid) to the VTK result file. + */ + template <class MultiWriter> + void commitTemperaturesBuffer_(MultiWriter & writer, + const char *pattern, + EnergyEqVector & buffer, + bool vertexCentered = true) + { + for (int energyEqIdx = 0; energyEqIdx < numEnergyEqs; ++energyEqIdx) { + std::ostringstream oss; + oss << "T_" << FluidSystem::phaseName(energyEqIdx); + + if (vertexCentered) + writer.attachVertexData(buffer[energyEqIdx], oss.str(), 1); + else + writer.attachCellData(buffer[energyEqIdx], oss.str(), 1); + } + } + + EnergyEqVector temperature_ ; + ScalarVector TwMinusTn_; + ScalarVector TnMinusTs_; + PhaseVector enthalpy_ ; + PhaseVector internalEnergy_ ; + PhaseVector reynoldsNumber_ ; + PhaseVector prandtlNumber_ ; + PhaseVector nusseltNumber_ ; + + PhaseDimWorldField velocity_; + + ScalarVector awn_; + ScalarVector aws_; + ScalarVector ans_; + + bool temperatureOutput_; + bool enthalpyOutput_; + bool internalEnergyOutput_; +}; + +/*! + * \ingroup MPNCModel + * + * \brief VTK writer module for the energy related quantities of the + * MpNc model. + * + * This is the specialization for the case with *2* energy balance equations and + * no local thermal equilibrium. (i.e. _including_ kinetic energy transfer) + */ +template<class TypeTag> +class MPNCVtkWriterEnergy<TypeTag, /*enableEnergy = */ true, /* numEnergyEquations = */ 2 > + : public MPNCVtkWriterModule<TypeTag> +{ + typedef MPNCVtkWriterModule<TypeTag> ParentType; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes; + typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef MPNCLocalResidualEnergy<TypeTag, /*enableEnergy=*/true, /*numEnergyEquations=*/2> LocalResidual; + typedef typename GridView::template Codim<0>::Entity Element; + + enum { dim = GridView::dimension }; + enum { dimWorld = GridView::dimensionworld }; + enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; + enum { wPhaseIdx = FluidSystem::wPhaseIdx}; + + enum { numEnergyEqs = Indices::numPrimaryEnergyVars}; + enum { velocityAveragingInModel = GET_PROP_VALUE(TypeTag, VelocityAveragingInModel) }; + + enum { reynoldsOutput = GET_PROP_VALUE(TypeTag, VtkAddReynolds) }; + enum { prandtlOutput = GET_PROP_VALUE(TypeTag, VtkAddPrandtl) }; + enum { nusseltOutput = GET_PROP_VALUE(TypeTag, VtkAddNusselt) }; + enum { interfacialAreaOutput= GET_PROP_VALUE(TypeTag, VtkAddInterfacialArea) }; + enum { velocityOutput = GET_PROP_VALUE(TypeTag, VtkAddVelocities) }; + + typedef typename ParentType::ScalarVector ScalarVector; + typedef typename ParentType::PhaseVector PhaseVector; + typedef typename ParentType::ComponentVector ComponentVector; + typedef std::array<ScalarVector, numEnergyEqs> EnergyEqVector; + + typedef Dune::FieldVector<Scalar, dimWorld> DimWorldVector; + typedef Dune::BlockVector<DimWorldVector> DimWorldField; + typedef std::array<DimWorldField, numPhases> PhaseDimWorldField; + + +public: + MPNCVtkWriterEnergy(const Problem &problem) + : ParentType(problem) + { + temperatureOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddTemperatures); + enthalpyOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddEnthalpies); + internalEnergyOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddInternalEnergies); + } + + /*! + * \brief Allocate memory for the scalar fields we would like to + * write to the VTK file. + */ + template <class MultiWriter> + void allocBuffers(MultiWriter &writer) + { + resizeTemperaturesBuffer_(temperature_); + this->resizePhaseBuffer_(enthalpy_); + this->resizePhaseBuffer_(internalEnergy_); + this->resizePhaseBuffer_(reynoldsNumber_); + this->resizePhaseBuffer_(prandtlNumber_); + this->resizePhaseBuffer_(nusseltNumber_); + this->resizeScalarBuffer_(qBoil_); + this->resizeScalarBuffer_(qsf_); + + + if (velocityAveragingInModel and not velocityOutput/*only one of the two output options, otherwise paraview segfaults due to two times the same field name*/) { + Scalar numVertices = this->problem_.gridView().size(dim); + for (int phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) { + velocity_[phaseIdx].resize(numVertices); + velocity_[phaseIdx] = 0; + } + } + } + + /*! + * \brief Modify the internal buffers according to the volume + * variables seen on an element + * + * \param element The finite element + * \param fvGeometry The finite-volume geometry in the fully implicit scheme + * \param elemVolVars The volume variables of the current element + * \param elemBcTypes + */ + void processElement(const Element & element, + const FVElementGeometry & fvGeometry, + const ElementVolumeVariables & elemVolVars, + const ElementBoundaryTypes & elemBcTypes) + { + int numLocalVertices = element.geometry().corners(); + for (int localVertexIdx = 0; localVertexIdx < numLocalVertices; ++localVertexIdx) { + const unsigned int vIdxGlobal = this->problem_.vertexMapper().subIndex(element, localVertexIdx, dim); + const VolumeVariables &volVars = elemVolVars[localVertexIdx]; + + qBoil_[vIdxGlobal] = LocalResidual::QBoilFunc(volVars, volVars.fluidState().saturation(wPhaseIdx)); + qsf_[vIdxGlobal] = LocalResidual::qsf(volVars); + + for (int phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) { + enthalpy_[phaseIdx][vIdxGlobal] = volVars.fluidState().enthalpy(phaseIdx); + internalEnergy_[phaseIdx][vIdxGlobal] = volVars.fluidState().internalEnergy(phaseIdx); + reynoldsNumber_[phaseIdx][vIdxGlobal] = volVars.reynoldsNumber(phaseIdx); + prandtlNumber_[phaseIdx][vIdxGlobal] = volVars.prandtlNumber(phaseIdx); + nusseltNumber_[phaseIdx][vIdxGlobal] = volVars.nusseltNumber(phaseIdx); + } + + // because numPhases only counts liquid phases + for (int phaseIdx = 0; phaseIdx < numEnergyEqs; ++ phaseIdx) { + temperature_[phaseIdx][vIdxGlobal] = volVars.temperature(phaseIdx); + Valgrind::CheckDefined(temperature_[phaseIdx][vIdxGlobal]); + } + + if (velocityAveragingInModel and not velocityOutput/*only one of the two output options, otherwise paraview segfaults due to two times the same field name*/){ + int numVertices = this->problem_.gridView().size(dim); // numVertices for vertexCentereed, numVolumes for volume centered + + for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) + for (int I = 0; I < numVertices; ++I) + velocity_[phaseIdx][I] = this->problem_.model().volumeDarcyVelocity(phaseIdx, I); + } + } + } + + /*! + * \brief Add all buffers to the VTK output writer. + */ + template <class MultiWriter> + void commitBuffers(MultiWriter & writer) + { + + if (temperatureOutput_){ + this->commitTemperaturesBuffer_(writer, "T_%s", temperature_); + } + + this->commitScalarBuffer_(writer, "qBoil", qBoil_); + this->commitScalarBuffer_(writer, "qsf", qsf_); + + + if (enthalpyOutput_) + this->commitPhaseBuffer_(writer, "h_%s", enthalpy_); + if (internalEnergyOutput_) + this->commitPhaseBuffer_(writer, "u_%s", internalEnergy_); + if (reynoldsOutput) + this->commitPhaseBuffer_(writer, "reynoldsNumber_%s", reynoldsNumber_); + if (prandtlOutput) + this->commitPhaseBuffer_(writer, "prandtlNumber_%s", prandtlNumber_); + if (nusseltOutput) + this->commitPhaseBuffer_(writer, "nusseltNumber_%s", nusseltNumber_); + if (velocityAveragingInModel and not velocityOutput/*only one of the two output options, otherwise paraview segfaults due to two timies the same field name*/){ + for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { + // commit the phase velocity + std::ostringstream oss; + oss << "velocity_" << FluidSystem::phaseName(phaseIdx); + writer.attachVertexData(velocity_[phaseIdx], + oss.str(), + dim); + } + } + } + +private: + /*! + * \brief Allocate the space for a buffer storing temperatures. + * This is one more entry than (fluid) phases. + */ + void resizeTemperaturesBuffer_(EnergyEqVector & buffer, + bool vertexCentered = true) + { + Scalar n; // numVertices for vertexCentereed, numVolumes for volume centered + if (vertexCentered) + n = this->problem_.gridView().size(dim); + else + n = this->problem_.gridView().size(0); + + for (int energyEqIdx = 0; energyEqIdx < numEnergyEqs; ++energyEqIdx) { + buffer[energyEqIdx].resize(n); + std::fill(buffer[energyEqIdx].begin(), buffer[energyEqIdx].end(), 0.0); + } + } + +/*! + * \brief Add a buffer for the three tmeperatures (fluids+solid) to the VTK result file. + */ + template <class MultiWriter> + void commitTemperaturesBuffer_(MultiWriter & writer, + const char *pattern, + EnergyEqVector & buffer, + bool vertexCentered = true) + { + static const char *name[] = { + "fluid", + "solid" + }; + + for (int energyEqIdx = 0; energyEqIdx < numEnergyEqs; ++energyEqIdx) { + std::ostringstream oss; + oss << "T_" << name[energyEqIdx]; + + if (vertexCentered) + writer.attachVertexData(buffer[energyEqIdx], oss.str(), 1); + else + writer.attachCellData(buffer[energyEqIdx], oss.str(), 1); + } + } + +// static const char *phaseName(int phaseIdx) +// { +// static const char *name[] = { +// "w", +// "n" +// }; +// +// assert(0 <= phaseIdx && phaseIdx < numPhases); +// return name[phaseIdx]; +// } + + EnergyEqVector temperature_ ; + PhaseVector enthalpy_ ; + PhaseVector internalEnergy_ ; + PhaseVector reynoldsNumber_ ; + PhaseVector prandtlNumber_ ; + PhaseVector nusseltNumber_ ; + ScalarVector qBoil_ ; + ScalarVector qsf_ ; + PhaseDimWorldField velocity_; + + bool temperatureOutput_; + bool enthalpyOutput_; + bool internalEnergyOutput_; +}; + + + + + + + + + + + + + + + + + +} + +#endif diff --git a/dumux/porousmediumflow/mpnc/implicit/fluxvariables.hh b/dumux/porousmediumflow/mpnc/implicit/fluxvariables.hh new file mode 100644 index 0000000000000000000000000000000000000000..2f6ab0e53595cd3d788540b082a7c87f22ed444e --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/fluxvariables.hh @@ -0,0 +1,171 @@ +// -*- 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 + * all fluxes of components over a face of a finite volume. + * + * This means pressure, concentration and temperature gradients, phase + * densities at the integration point, etc. + */ +#ifndef DUMUX_MPNC_FLUX_VARIABLES_HH +#define DUMUX_MPNC_FLUX_VARIABLES_HH + +#include <dumux/common/spline.hh> + +#include "diffusion/fluxvariables.hh" +#include "energy/fluxvariables.hh" +#include <dumux/porousmediumflow/implicit/darcyfluxvariables.hh> +#include <dumux/porousmediumflow/implicit/forchheimerfluxvariables.hh> + +namespace Dumux +{ + +/*! + * \ingroup MPNCModel + * \ingroup ImplicitFluxVariables + * \brief This class contains the data which is required to + * calculate all fluxes of components over a face of a finite + * volume for the MpNc model. + * + * This means pressure and concentration gradients, phase densities at + * the intergration point, etc. + */ +template <class TypeTag> +class MPNCFluxVariables + : public GET_PROP_TYPE(TypeTag, BaseFluxVariables) +{ + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GridView::template Codim<0>::Entity Element; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; + + typedef typename GET_PROP_TYPE(TypeTag, BaseFluxVariables) BaseFluxVariables; + + enum {dim= GridView::dimension}; + enum {dimWorld= GridView::dimensionworld}; + enum {enableDiffusion = GET_PROP_VALUE(TypeTag, EnableDiffusion)}; + enum {enableEnergy = GET_PROP_VALUE(TypeTag, EnableEnergy)}; + enum {enableKinetic = GET_PROP_VALUE(TypeTag, EnableKinetic)}; + enum {numEnergyEquations = GET_PROP_VALUE(TypeTag, NumEnergyEquations)}; + + typedef Dune::FieldVector<Scalar, dim> DimVector; + typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef MPNCFluxVariablesDiffusion<TypeTag, enableDiffusion> FluxVariablesDiffusion; + typedef MPNCFluxVariablesEnergy<TypeTag, enableEnergy, numEnergyEquations> FluxVariablesEnergy; + +public: + /* + * \brief The constructor + * + * \param problem The problem + * \param element The finite element + * \param fvGeometry The finite-volume geometry in the fully implicit scheme + * \param fIdx The local index of the SCV (sub-control-volume) face + * \param elemVolVars The volume variables of the current element + * \param onBoundary A boolean variable to specify whether the flux variables + * are calculated for interior SCV faces or boundary faces, default=false + */ + MPNCFluxVariables(const Problem &problem, + const Element &element, + const FVElementGeometry &fvGeometry, + const unsigned int fIdx, + const ElementVolumeVariables &elemVolVars, + const bool onBoundary = false) + : BaseFluxVariables(problem, element, fvGeometry, fIdx, elemVolVars, onBoundary), + fvGeometry_(fvGeometry), faceIdx_(fIdx), elemVolVars_(elemVolVars), onBoundary_(onBoundary) + { + // velocities can be obtained from the Parent class. + + // update the flux data of the energy module (i.e. isothermal + // or non-isothermal) + fluxVarsEnergy_.update(problem, element, fvGeometry, this->face(), *this, elemVolVars); + + // update the flux data of the diffusion module (i.e. with or + // without diffusion) + fluxVarsDiffusion_.update(problem, element, fvGeometry, this->face(), elemVolVars); + + extrusionFactor_ = + (elemVolVars[this->face().i].extrusionFactor() + + elemVolVars[this->face().j].extrusionFactor()) / 2; + } + + /*! + * \brief Returns a reference to the volume + * variables of the i-th sub-control volume of the current + * element. + */ + const VolumeVariables &volVars(const unsigned int idx) const + { return elemVolVars_[idx]; } + + /*! + * \brief Returns th extrusion factor for the sub-control volume face + */ + Scalar extrusionFactor() const + { return extrusionFactor_; } + + //////////////////////////////////////////////// + // forward calls to the diffusion module + Scalar porousDiffCoeffL(const unsigned int compIdx) const + { return fluxVarsDiffusion_.porousDiffCoeffL(compIdx); } + + Scalar porousDiffCoeffG(const unsigned int compIIdx, + const unsigned int compJIdx) const + { return fluxVarsDiffusion_.porousDiffCoeffG(compIIdx, compJIdx); } + + const Scalar moleFraction(const unsigned int phaseIdx, + const unsigned int compIdx) const + { return fluxVarsDiffusion_.moleFraction(phaseIdx, compIdx); } + + const GlobalPosition &moleFractionGrad(const unsigned int phaseIdx, + const unsigned int compIdx) const + { return fluxVarsDiffusion_.moleFractionGrad(phaseIdx, compIdx); } + + // end of forward calls to the diffusion module + //////////////////////////////////////////////// + + //////////////////////////////////////////////// + // forward calls to the temperature module + const GlobalPosition &temperatureGrad() const + { return fluxVarsEnergy_.temperatureGrad(); } + + const FluxVariablesEnergy &fluxVarsEnergy() const + { return fluxVarsEnergy_; } + // end of forward calls to the temperature module + //////////////////////////////////////////////// + +private: + const FVElementGeometry &fvGeometry_; + const unsigned int faceIdx_; + const ElementVolumeVariables &elemVolVars_; + const bool onBoundary_; + + // The extrusion factor for the sub-control volume face + Scalar extrusionFactor_; + + FluxVariablesDiffusion fluxVarsDiffusion_; + FluxVariablesEnergy fluxVarsEnergy_; +}; + +} // end namespace + +#endif diff --git a/dumux/porousmediumflow/mpnc/implicit/indices.hh b/dumux/porousmediumflow/mpnc/implicit/indices.hh new file mode 100644 index 0000000000000000000000000000000000000000..506aec406324dc013078cb4af3e254ab448be32a --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/indices.hh @@ -0,0 +1,120 @@ +// -*- 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 The primary variable and equation indices for the MpNc model. + */ +#ifndef DUMUX_MPNC_INDICES_HH +#define DUMUX_MPNC_INDICES_HH + +#include "properties.hh" + +#include "mass/indices.hh" +#include "energy/indices.hh" + +namespace Dumux +{ + +/*! + * \ingroup MPNCModel + * \ingroup ImplicitIndices + * \brief Enumerates the formulations which the MpNc model accepts. + */ +struct MpNcPressureFormulation +{ + enum { + mostWettingFirst, + leastWettingFirst + }; +}; + +/*! + * \ingroup MPNCModel + * \ingroup ImplicitIndices + * \brief The primary variable and equation indices for the MpNc model. + */ +template <class TypeTag, int BasePVOffset = 0> +struct MPNCIndices : + public MPNCMassIndices<BasePVOffset, + TypeTag, + GET_PROP_VALUE(TypeTag, EnableKinetic) >, + public MPNCEnergyIndices<BasePVOffset + + MPNCMassIndices<0, TypeTag, GET_PROP_VALUE(TypeTag, EnableKinetic) >::numPrimaryVars, + GET_PROP_VALUE(TypeTag, EnableEnergy), + GET_PROP_VALUE(TypeTag, NumEnergyEquations)> +{ +private: + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + enum { enableEnergy = GET_PROP_VALUE(TypeTag, EnableEnergy) }; + enum { enableKinetic = GET_PROP_VALUE(TypeTag, EnableKinetic) }; //mass transfer + enum { numEnergyEquations = GET_PROP_VALUE(TypeTag, NumEnergyEquations) }; // energy transfer + enum { numPhases = FluidSystem::numPhases }; + + typedef MPNCMassIndices<BasePVOffset, TypeTag, enableKinetic> MassIndices; + typedef MPNCEnergyIndices<BasePVOffset + MassIndices::numPrimaryVars, enableEnergy, numEnergyEquations> EnergyIndices; + +public: + /*! + * \brief The number of primary variables / equations. + */ + // temperature + Mass Balance + constraints for switch stuff + static const unsigned int numPrimaryVars = + MassIndices::numPrimaryVars + + EnergyIndices::numPrimaryVars + + numPhases; + + /*! + * \brief The number of primary variables / equations of the energy module. + */ + static const unsigned int numPrimaryEnergyVars = + EnergyIndices::numPrimaryVars ; + + /*! + * \brief Index of the saturation of the first phase in a vector + * of primary variables. + * + * The following (numPhases - 1) primary variables represent the + * saturations for the phases [1, ..., numPhases - 1] + */ + static const unsigned int s0Idx = + MassIndices::numPrimaryVars + + EnergyIndices::numPrimaryVars; + + /*! + * \brief Index of the first phase' pressure in a vector of + * primary variables. + */ + static const unsigned int p0Idx = + MassIndices::numPrimaryVars + + EnergyIndices::numPrimaryVars + + numPhases - 1; + + /*! + * \brief Index of the first phase NCP equation. + * + * The index for the remaining phases are consecutive. + */ + static const unsigned int phase0NcpIdx = + MassIndices::numPrimaryVars + + EnergyIndices::numPrimaryVars; +}; + +} + +#endif diff --git a/dumux/porousmediumflow/mpnc/implicit/localresidual.hh b/dumux/porousmediumflow/mpnc/implicit/localresidual.hh new file mode 100644 index 0000000000000000000000000000000000000000..93c5bc89c47fb500c3f482f365ec9741eaeebe46 --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/localresidual.hh @@ -0,0 +1,313 @@ +// -*- 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 MpNc specific details needed to approximately calculate the local + * defect in the fully implicit scheme. + * + */ +#ifndef DUMUX_MPNC_LOCAL_RESIDUAL_HH +#define DUMUX_MPNC_LOCAL_RESIDUAL_HH + +#include "fluxvariables.hh" +#include "diffusion/diffusion.hh" +#include "energy/localresidual.hh" +#include "mass/localresidual.hh" +#include "properties.hh" + +namespace Dumux +{ +/*! + * \ingroup MPNCModel + * \ingroup ImplicitLocalResidual + * \brief MpNc specific details needed to approximately calculate the local + * defect in the fully implicit scheme. + * + * This class is used to fill the gaps in ImplicitLocalResidual for the + * MpNc flow. + */ +template<class TypeTag> +class MPNCLocalResidual : public GET_PROP_TYPE(TypeTag, BaseLocalResidual) +{ + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + +protected: + typedef typename GET_PROP_TYPE(TypeTag, LocalResidual) Implementation; + typedef typename GET_PROP_TYPE(TypeTag, BaseLocalResidual) ParentType; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + + enum {numPhases = GET_PROP_VALUE(TypeTag, NumPhases)}; + enum {numComponents = GET_PROP_VALUE(TypeTag, NumComponents)}; + enum {numEq = GET_PROP_VALUE(TypeTag, NumEq)}; + enum {enableEnergy = GET_PROP_VALUE(TypeTag, EnableEnergy)}; + enum {numEnergyEquations = GET_PROP_VALUE(TypeTag, NumEnergyEquations)}; + enum {enableKinetic = GET_PROP_VALUE(TypeTag, EnableKinetic)}; + enum {phase0NcpIdx = Indices::phase0NcpIdx}; + + typedef typename GridView::template Codim<0>::Entity Element; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; + typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes; + typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes; + + typedef MPNCLocalResidualEnergy<TypeTag, enableEnergy, numEnergyEquations> EnergyResid; + typedef MPNCLocalResidualMass<TypeTag, enableKinetic> MassResid; + +public: + /*! + * \brief Evaluate the amount all conservation quantites + * (e.g. phase mass) within a sub-control volume. + * + * The result should be averaged over the volume (e.g. phase mass + * inside a sub control volume divided by the volume) + * + * \param storage The mass of the component within the sub-control volume + * \param usePrevSol Evaluate function with solution of current or previous time step + * \param scvIdx The SCV (sub-control-volume) index + * + */ + void computeStorage(PrimaryVariables &storage, + const unsigned int scvIdx, + const bool usePrevSol) const + { + // if flag usePrevSol is set, the solution from the previous + // time step is used, otherwise the current solution is + // used. The secondary variables are used accordingly. This + // is required to compute the derivative of the storage term + // using the implicit euler method. + const ElementVolumeVariables &elemVolVars = usePrevSol ? this->prevVolVars_() : this->curVolVars_(); + const VolumeVariables &volVars = elemVolVars[scvIdx]; + + storage =0; + + // compute mass and energy storage terms + MassResid::computeStorage(storage, volVars); + Valgrind::CheckDefined(storage); + EnergyResid::computeStorage(storage, volVars); + Valgrind::CheckDefined(storage); + } + + /*! + * \brief Evaluate the amount all conservation quantities + * (e.g. phase mass) within all sub-control volumes of an + * element. + * + * \param phaseStorage The conserved quantity within the phase in the whole domain + * \param element The finite element + * \param phaseIdx The index of the fluid phase + */ + void addPhaseStorage(PrimaryVariables &phaseStorage, + const Element &element, + const unsigned int phaseIdx) const + { + // create a finite volume element geometry + FVElementGeometry fvGeometry; + fvGeometry.update(this->gridView_(), element); + + // calculate volume variables + ElementVolumeVariables elemVolVars; + this->model_().setHints(element, elemVolVars); + elemVolVars.update(this->problem_(), + element, + fvGeometry, + /*useOldSolution=*/false); + + // calculate the phase storage for all sub-control volumes + for (int scvIdx=0; + scvIdx < fvGeometry.numScv; + scvIdx++) + { + PrimaryVariables tmpPriVars(0.0); + + // compute mass and energy storage terms in terms of + // averaged quantities + MassResid::addPhaseStorage(tmpPriVars, + elemVolVars[scvIdx], + phaseIdx); + EnergyResid::addPhaseStorage(tmpPriVars, + elemVolVars[scvIdx], + phaseIdx); + + // multiply with volume of sub-control volume + tmpPriVars *= fvGeometry.subContVol[scvIdx].volume; + + // Add the storage of the current SCV to the total storage + phaseStorage += tmpPriVars; + } + } + + /*! + * \brief Calculate the source term of the equation + * + * \param scvIdx The SCV (sub-control-volume) index + * \param source The source/sink in the sub-control volume for each component + */ + void computeSource(PrimaryVariables &source, + const unsigned int scvIdx) + { + Valgrind::SetUndefined(source); + ParentType::computeSource(source, scvIdx); + + const VolumeVariables &volVars = this->curVolVars_(scvIdx); + + PrimaryVariables tmp(0); + MassResid::computeSource(tmp, volVars); + source += tmp; + Valgrind::CheckDefined(source); + + /* + * EnergyResid also called in the MassResid + * 1) Makes some sense because energy is also carried by mass + * 2) The mass transfer between the phases is needed. + */ +// tmp = 0.; +// EnergyResid::computeSource(tmp, volVars); +// source += tmp; +// Valgrind::CheckDefined(source); + }; + + + /*! + * \brief Evaluates the total flux of all conservation quantities + * over a face of a subcontrol volume. + * + * \param flux The flux over the SCV (sub-control-volume) face for each component + * \param fIdx The index of the SCV face + * \param onBoundary A boolean variable to specify whether the flux variables + * are calculated for interior SCV faces or boundary faces, default=false + */ + void computeFlux(PrimaryVariables &flux, + const unsigned int fIdx, const bool onBoundary=false) const + { + FluxVariables fluxVars(this->problem_(), + this->element_(), + this->fvGeometry_(), + fIdx, + this->curVolVars_(), + onBoundary); + + flux = 0.0; + MassResid::computeFlux(flux, fluxVars, this->curVolVars_() ); + Valgrind::CheckDefined(flux); +/* + * EnergyResid also called in the MassResid + * 1) Makes some sense because energy is also carried by mass + * 2) The component-wise mass flux in each phase is needed. + */ + } + + /*! + * \brief Compute the local residual, i.e. the deviation of the + * equations from zero. + * + * \param element The finite element + */ + void eval(const Element &element) + { ParentType::eval(element); } + + /*! + * \brief Evaluate the local residual. + * + * \param element The finite element + * \param fvGeometry The finite-volume geometry in the fully implicit scheme + * \param prevElemVolVars The element volume variables of the previous timestep + * \param curElemVolVars The element volume variables of the current timestep + * \param bcType The types of the boundary conditions for all vertices of the element + */ + void eval(const Element &element, + const FVElementGeometry &fvGeometry, + const ElementVolumeVariables &prevElemVolVars, + const ElementVolumeVariables &curElemVolVars, + const ElementBoundaryTypes &bcType) + { + ParentType::eval(element, + fvGeometry, + prevElemVolVars, + curElemVolVars, + bcType); + + if (GET_PROP_VALUE(TypeTag, ImplicitIsBox) + || !bcType.hasDirichlet()) + { + for (int i = 0; i < this->fvGeometry_().numScv; ++i) { + // add the two auxiliary equations, make sure that the + // dirichlet boundary condition is conserved + for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) + { + if (!bcType[i].isDirichlet(phase0NcpIdx + phaseIdx)) + { + this->residual_[i][phase0NcpIdx + phaseIdx] = + this->curVolVars_(i).phaseNcp(phaseIdx); + } + } + } + } + } + + + /*! + * \brief Add Dirichlet boundary conditions for a single intersection + * + * Sets the Dirichlet conditions in a strong sense, in contrast to + * the general handling in CCLocalResidual. + * + * \param isIt + * \param bcTypes + */ + template <class IntersectionIterator> + void evalDirichletSegment_(const IntersectionIterator &isIt, + const BoundaryTypes &bcTypes) + { + // temporary vector to store the Dirichlet boundary fluxes + PrimaryVariables values; + Valgrind::SetUndefined(values); + this->problem_().dirichlet(values, *isIt); + Valgrind::CheckDefined(values); + + // set Dirichlet conditions in a strong sense + for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) + { + if (bcTypes.isDirichlet(eqIdx)) + { + int pvIdx = bcTypes.eqToDirichletIndex(eqIdx); + this->residual_[0][eqIdx] + = this->curPriVar_(0, pvIdx) - values[pvIdx]; + } + else if (eqIdx >= phase0NcpIdx) + { + int phaseIdx = eqIdx - phase0NcpIdx; + this->residual_[0][eqIdx] = + this->curVolVars_(0).phaseNcp(phaseIdx); + } + } + } + +protected: + Implementation &asImp_() + { return *static_cast<Implementation *>(this); } + const Implementation &asImp_() const + { return *static_cast<const Implementation *>(this); } +}; + +} // end namespace + +#endif diff --git a/dumux/porousmediumflow/mpnc/implicit/mass/indices.hh b/dumux/porousmediumflow/mpnc/implicit/mass/indices.hh new file mode 100644 index 0000000000000000000000000000000000000000..555091607148615fb0c95d91fda4150e70bbb1e0 --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/mass/indices.hh @@ -0,0 +1,87 @@ +// -*- 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 The indices for the mass flow part of the compositional + * multi-phase model. + */ +#ifndef DUMUX_MPNC_MASS_INDICES_HH +#define DUMUX_MPNC_MASS_INDICES_HH + +#include <dumux/porousmediumflow/mpnc/implicit/properties.hh> + +namespace Dumux +{ +/*! + * \ingroup MPNCModel + * \ingroup ImplicitIndices + * \brief The indices required for conservation of mass. + * + * This is the specialization for the case without kinetic mass + * transfer (i.e. assuming chemical equilibrium) + */ +template <int PVOffset, + class TypeTag, + bool enableKinetic /*=false*/> +class MPNCMassIndices +{ + static_assert(!enableKinetic, + "No kinetic mass transfer module included, " + "but kinetic mass transfer enabled."); + + enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; + +public: + /*! + * \brief This module defines one new primary variable. + */ + static const unsigned int numPrimaryVars = numComponents; + + /*! + * \brief Index for the fugacity of the first component in the + * first phase in a vector of primary variables. + * + * The next numComponents indices represent the remaining + * fugacities: + * + * fug0Idx + 0 = fugacity of component 0 + * fug0Idx + 1 = fugacity of component 1 + * ... + * fug0Idx + N - 1 = fugacity of component N + */ + static const unsigned int fug0Idx = PVOffset + 0; + + /*! + * \brief Equation index of the mass conservation equation for the + * first component. + * + * The next numComponents indices represent the equations of all + * components in all phases: + * + * conti00EqIdx + 0 = continuity of component 0 + * conti00EqIdx + 1 = continuity of component 1 + * ... + * conti00EqIdx + N - 1 = continuity of component N + */ + static const unsigned int conti0EqIdx = PVOffset + 0; +}; + +} + +#endif diff --git a/dumux/porousmediumflow/mpnc/implicit/mass/indiceskinetic.hh b/dumux/porousmediumflow/mpnc/implicit/mass/indiceskinetic.hh new file mode 100644 index 0000000000000000000000000000000000000000..f00389de8f6a87f774bc957fcbb2163657647f63 --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/mass/indiceskinetic.hh @@ -0,0 +1,83 @@ +// -*- 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 The indices for the kinetic mass transfer module of the + * compositional multi-phase model. + */ +#ifndef DUMUX_MPNC_MASS_INDICES_KINETIC_HH +#define DUMUX_MPNC_MASS_INDICES_KINETIC_HH + +#include <dumux/porousmediumflow/mpnc/implicit/indices.hh> + +namespace Dumux +{ +/*! + * \brief The indices required for conservation of mass. + * + * This is the specialization considering kinetic mass transfer + * (i.e. not assuming local chemical equilibrium) + */ +template <int PVOffset, class TypeTag> +class MPNCMassIndices<PVOffset, TypeTag, /*enableKinetic=*/true> +{ + enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; + enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; +public: + /*! + * \brief This module defines one new primary variable. + */ + static const unsigned int numPrimaryVars = numPhases*numComponents; + + /*! + * \brief Index for the mole fraction of the first component in + * the first phase in a vector of primary variables. + * + * The next numPhases*numComponents indices represent the + * compositions of all phases: + * + * moleFrac00Idx + 0 = mole fraction of component 0 in phase 0 + * moleFrac00Idx + 1 = mole fraction of component 1 in phase 0 + * ... + * moleFrac00Idx + N - 1 = mole fraction of component N in phase 0 + * moleFrac00Idx + N = mole fraction of component 0 in phase 1 + * ... + */ + static const unsigned int moleFrac00Idx = PVOffset + 0; + + /*! + * \brief Equation index of the mass conservation equation for the + * first component in the first phase. + * + * The next numPhases*numComponents indices represent the + * continuity equations of all components in all phases: + * + * conti00EqIdx + 0 = continuity of component 0 in phase 0 + * conti00EqIdx + 1 = continuity of component 1 in phase 0 + * ... + * conti00EqIdx + N - 1 = continuity of component N in phase 0 + * conti00EqIdx + N = continuity of component 0 in phase 1 + * ... + */ + static const unsigned int conti0EqIdx = PVOffset + 0; +}; + +} + +#endif diff --git a/dumux/porousmediumflow/mpnc/implicit/mass/localresidual.hh b/dumux/porousmediumflow/mpnc/implicit/mass/localresidual.hh new file mode 100644 index 0000000000000000000000000000000000000000..cf2030600aa6989d2010b80433b6acc6e99cc2a5 --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/mass/localresidual.hh @@ -0,0 +1,401 @@ +// -*- 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 The mass conservation part of the MpNc model. + */ +#ifndef DUMUX_MPNC_LOCAL_RESIDUAL_MASS_HH +#define DUMUX_MPNC_LOCAL_RESIDUAL_MASS_HH + +#include <dune/common/fvector.hh> + +#include <dumux/porousmediumflow/mpnc/implicit/properties.hh> +#include <dumux/material/constraintsolvers/compositionfromfugacities.hh> +#include <dumux/common/math.hh> +#include <dumux/common/spline.hh> + +#include "../diffusion/diffusion.hh" +#include "../energy/localresidual.hh" + +namespace Dumux +{ +/*! + * \brief This class represents methods which are shared amongst all + * mass conservation modules. + */ +template<class TypeTag> +class MPNCLocalResidualMassCommon +{ +protected: + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; + + enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; + enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; + enum { enableDiffusion = GET_PROP_VALUE(TypeTag, EnableDiffusion) }; + enum { enableEnergy = GET_PROP_VALUE(TypeTag, EnableEnergy) }; + enum { numEnergyEquations = GET_PROP_VALUE(TypeTag, NumEnergyEquations) }; + + typedef typename Dune::FieldVector<Scalar, numComponents> ComponentVector; + typedef MPNCDiffusion<TypeTag, enableDiffusion> Diffusion; + typedef MPNCLocalResidualEnergy<TypeTag, enableEnergy, numEnergyEquations> EnergyResid; + +public: + /*! + * \brief Evaluate the amount moles within a sub-control volume in + * a phase. + * + * \param storage The mass of the component within the sub-control volume + * \param volVars The volume variables + * \param phaseIdx phaseIdx The index of the fluid phase + * + * The result should be averaged over the volume. + */ + static void computePhaseStorage(ComponentVector &storage, + const VolumeVariables &volVars, + const unsigned int phaseIdx) + { + // compute storage term of all components within all phases + storage = 0; + for (int compIdx = 0; compIdx < numComponents; ++ compIdx) { + storage[compIdx] += + volVars.fluidState().saturation(phaseIdx)* + volVars.fluidState().molarity(phaseIdx, compIdx); +#ifndef NDEBUG +if (!std::isfinite(storage[compIdx])) + DUNE_THROW(NumericalProblem, "Calculated non-finite storage"); +#endif + } + + storage *= volVars.porosity(); + + } + + /*! + * \brief Evaluates the advective flux of all conservation + * quantities over a face of a subcontrol volume via a + * fluid phase. + * + * \param flux The flux over the SCV (sub-control-volume) face for each component + * \param fluxVars The flux Variables + * \param phaseIdx phaseIdx The index of the fluid phase + */ + static void computeAdvectivePhaseFlux(ComponentVector &flux, + const FluxVariables &fluxVars, + const unsigned int phaseIdx) + { + + const Scalar volumeFlux = fluxVars.volumeFlux(phaseIdx) ; + + + // retrieve the upwind weight for the mass conservation equations. Use the value + // specified via the property system as default, and overwrite + // it by the run-time parameter from the Dune::ParameterTree + const Scalar massUpwindWeight = GET_PARAM_FROM_GROUP(TypeTag, Scalar, Implicit, MassUpwindWeight); + + static bool enableSmoothUpwinding_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Implicit, EnableSmoothUpwinding); + + // data attached to upstream and the downstream vertices + // of the current phase + unsigned int upIdx = fluxVars.upstreamIdx(phaseIdx); + unsigned int dnIdx = fluxVars.downstreamIdx(phaseIdx); + + const VolumeVariables &up = fluxVars.volVars(upIdx); + const VolumeVariables &dn = fluxVars.volVars(dnIdx); + +if (!std::isfinite(volumeFlux)) + DUNE_THROW(NumericalProblem, "Calculated non-finite normal flux in phase" << phaseIdx); + //////// + // advective fluxes of all components in the phase + //////// + for (unsigned int compIdx = 0; compIdx < numComponents; ++compIdx) { + // add advective flux of current component in current + // phase. we use full upwinding. + if (enableSmoothUpwinding_) { + const Scalar kGradPNormal = fluxVars.kGradPNormal(phaseIdx); + const Scalar mobUp = up.mobility(phaseIdx); + const Scalar conUp = up.fluidState().molarity(phaseIdx, compIdx); + + const Scalar mobDn = dn.mobility(phaseIdx); + const Scalar conDn = dn.fluidState().molarity(phaseIdx, compIdx); + + const Scalar mobConUp = mobUp*conUp; + const Scalar mobConDn = mobDn*conDn; + const Scalar meanMobCon = Dumux::harmonicMean(mobConUp, mobConDn); + + const Scalar x = std::abs(kGradPNormal); + const Scalar sign = (kGradPNormal > 0)?-1:1; + + // approximate the mean viscosity at the face + const Scalar meanVisc = (up.fluidState().viscosity(phaseIdx) + + dn.fluidState().viscosity(phaseIdx))/2; + + // put the mean viscosity and permeanbility in + // relation to the viscosity of water at + // approximatly 20 degrees Celsius. + const Scalar pGradRef = 10; // [Pa/m] + const Scalar muRef = 1e-3; // [Ns/m^2] + const Scalar Kref = 1e-12; // [m^2] = approx 1 Darcy + + const Scalar faceArea = fluxVars.face().normal.two_norm(); + const Scalar eps = pGradRef * Kref * faceArea * meanVisc/muRef; // * (1e3/18e-3)/meanC; + + Scalar compFlux; + if (x >= eps) { + // we only do tricks if x is below the epsilon + // value + compFlux = x*mobConUp; + } + else { + const Scalar xPos[] = { 0, eps }; + const Scalar yPos[] = { 0, eps*mobConUp }; + const Spline<Scalar> sp2(xPos, yPos, meanMobCon, mobConUp); + compFlux = sp2.eval(x); + } + #ifndef NDEBUG + if (!std::isfinite(compFlux)) + DUNE_THROW(NumericalProblem, "Calculated non-finite normal flux in smooth upwinding"); + #endif + + flux[compIdx] = sign*compFlux; + } + else + {// not use smooth upwinding + flux[compIdx] = + volumeFlux * + (( massUpwindWeight)*up.fluidState().molarity(phaseIdx, compIdx) + + + ( 1. - massUpwindWeight)*dn.fluidState().molarity(phaseIdx, compIdx) ); + if (!std::isfinite(flux[compIdx])) + DUNE_THROW(NumericalProblem, "Calculated non-finite normal flux in phase " << phaseIdx << " comp " << compIdx << "T: "<< up.fluidState().temperature(phaseIdx) << "S "<<up.fluidState().saturation(phaseIdx) ) ; + } + } + } + + + /*! + * \brief Evaluates the advective flux of all conservation + * quantities over a face of a subcontrol volume via a + * fluid phase. + * + * \param flux The flux over the SCV (sub-control-volume) face for each component + * \param fluxVars The flux Variables + * \param phaseIdx phaseIdx The index of the fluid phase + */ + static void computeDiffusivePhaseFlux(ComponentVector &flux, + const FluxVariables &fluxVars, + const unsigned int phaseIdx) + { + if (!enableDiffusion) { + flux = 0.0; + return; + } + + + const VolumeVariables &volVarsI = fluxVars.volVars(fluxVars.face().i); + const VolumeVariables &volVarsJ = fluxVars.volVars(fluxVars.face().j); + if (volVarsI.fluidState().saturation(phaseIdx) < 1e-4 || + volVarsJ.fluidState().saturation(phaseIdx) < 1e-4) + { + return; // phase is not present in one of the finite volumes + } + + // approximate the total concentration of the phase at the + // integration point by the arithmetic mean of the + // concentration of the sub-control volumes + Scalar molarDensityAtIP; + molarDensityAtIP = volVarsI.fluidState().molarDensity(phaseIdx); + molarDensityAtIP += volVarsJ.fluidState().molarDensity(phaseIdx); + molarDensityAtIP /= 2; + + Diffusion::flux(flux, phaseIdx, fluxVars, molarDensityAtIP); + } +}; + +/*! + * \brief The mass conservation part of the MpNc model. + * + * This is the specialization for the case where kinetic mass transfer + * is _not_ considered. + */ +template<class TypeTag, bool enableKinetic /*=false*/> +class MPNCLocalResidualMass +{ + static_assert(!enableKinetic, + "No kinetic mass transfer module included, " + "but kinetic mass transfer enabled."); + + typedef MPNCLocalResidualMassCommon<TypeTag> MassCommon; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; + typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; + + enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; + enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; + enum { conti0EqIdx = Indices::conti0EqIdx }; + enum { enableEnergy = GET_PROP_VALUE(TypeTag, EnableEnergy) }; + enum { numEnergyEquations = GET_PROP_VALUE(TypeTag, NumEnergyEquations) }; + + typedef typename Dune::FieldVector<Scalar, numComponents> ComponentVector; + typedef MPNCLocalResidualEnergy<TypeTag, enableEnergy, numEnergyEquations> EnergyResid; + +public: + /*! + * \brief Calculate the storage for all mass balance equations + * + * \param storage The mass of the component within the sub-control volume + * \param volVars The volume variables + */ + static void computeStorage(PrimaryVariables &storage, + const VolumeVariables &volVars) + { + for (int compIdx = 0; compIdx < numComponents; ++compIdx) + storage[conti0EqIdx + compIdx] = 0.0; + + for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { + addPhaseStorage(storage, volVars, phaseIdx); + } + } + + /*! + * \brief Calculate the storage for all mass balance equations + * within a single fluid phase + * + * \param storage The mass of the component within the sub-control volume + * \param volVars The volume variables + * \param phaseIdx phaseIdx The index of the fluid phase + */ + static void addPhaseStorage(PrimaryVariables &storage, + const VolumeVariables &volVars, + const unsigned int phaseIdx) + { + // calculate the component-wise mass storage + ComponentVector phaseComponentValues; + MassCommon::computePhaseStorage(phaseComponentValues, + volVars, + phaseIdx); + + // copy to the primary variables + for (int compIdx = 0; compIdx < numComponents; ++compIdx) + storage[conti0EqIdx + compIdx] += phaseComponentValues[compIdx]; + } + + /*! + * \brief Calculate the storage for all mass balance equations + * + * \param flux The flux over the SCV (sub-control-volume) face for each component + * \param fluxVars The flux Variables + * \param elemVolVars The volume variables of the current element + */ + static void computeFlux(PrimaryVariables &flux, + const FluxVariables &fluxVars, + const ElementVolumeVariables & elemVolVars) + { + for (int compIdx = 0; compIdx < numComponents; ++compIdx) + flux[conti0EqIdx + compIdx] = 0.0; + + ComponentVector phaseComponentValuesAdvection(0.); + ComponentVector phaseComponentValuesDiffusion(0.); + ComponentVector phaseComponentValuesMassTransport[numPhases]; // what goes into the energy module + + for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { + MassCommon::computeAdvectivePhaseFlux(phaseComponentValuesAdvection, fluxVars, phaseIdx); + Valgrind::CheckDefined(phaseComponentValuesAdvection); + for (int compIdx = 0; compIdx < numComponents; ++compIdx) + flux[conti0EqIdx + compIdx] += + phaseComponentValuesAdvection[compIdx]; + + MassCommon::computeDiffusivePhaseFlux(phaseComponentValuesDiffusion, fluxVars, phaseIdx); + Valgrind::CheckDefined(phaseComponentValuesDiffusion); + for (int compIdx = 0; compIdx < numComponents; ++compIdx){ + flux[conti0EqIdx + compIdx] += + phaseComponentValuesDiffusion[compIdx]; + } + + + + // Right now I think that adding the two contributions individually into the flux is best for debugging and understanding. + // The Energy module needs both contributions. + phaseComponentValuesMassTransport[phaseIdx] = phaseComponentValuesDiffusion + phaseComponentValuesAdvection ; + + Valgrind::CheckDefined(flux); + } +// std::cout<< "KPN Mass: flux: " << flux << endl; + + + // \todo + // + // The computeflux() of the Energy module needs a + // component-wise flux (for the diffusive enthalpy transport) + // It makes some sense calling energy from here, because energy + // is carried by mass. However, it is not really a clean + // solution. + + // energy transport in fluid phases + EnergyResid::computeFlux(flux, + fluxVars, + elemVolVars, + phaseComponentValuesMassTransport); + Valgrind::CheckDefined(flux); + } + + + + /*! + * \brief Calculate the source terms for all mass balance + * equations + * + * \param source The source/sink in the sub-control volume for each component + * \param volVars the volume variables + */ + static void computeSource(PrimaryVariables &source, + const VolumeVariables &volVars) + { +// static_assert(not enableKineticEnergy, // enableKinetic is disabled, in this specialization +// "In the case of kinetic energy transfer the advective energy transport between the phases has to be considered. " +// "It is hard (technically) to say how much mass got transfered in the case of chemical equilibrium. " +// "Therefore, kineticEnergy and no kinetic mass does not fit (yet)."); + + + // mass transfer is not considered in this mass module + for (int compIdx = 0; compIdx < numComponents; ++compIdx) + source[conti0EqIdx + compIdx] = 0.0; + + + PrimaryVariables tmpPriVars(0); + // Similar to the compute Flux, the energy residual needs to be called from the + // mass residual. + ComponentVector dummy[numPhases]; + for (int iDummy =0; iDummy <numPhases; ++iDummy) + dummy[iDummy] = 0.; + EnergyResid::computeSource(tmpPriVars, + volVars, + dummy); + source += tmpPriVars; + Valgrind::CheckDefined(source); + } +}; + +} // end namespace + +#endif diff --git a/dumux/porousmediumflow/mpnc/implicit/mass/localresidualkinetic.hh b/dumux/porousmediumflow/mpnc/implicit/mass/localresidualkinetic.hh new file mode 100644 index 0000000000000000000000000000000000000000..e2eb52905d4214743ad6a6429173ab28ea79cf2b --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/mass/localresidualkinetic.hh @@ -0,0 +1,288 @@ +// -*- 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 The local residual for the kinetic mass transfer module of + * the compositional multi-phase model. + */ +#ifndef DUMUX_MPNC_LOCAL_RESIDUAL_MASS_KINETIC_HH +#define DUMUX_MPNC_LOCAL_RESIDUAL_MASS_KINETIC_HH + +#include <dumux/porousmediumflow/mpnc/implicit/mass/localresidual.hh> + +namespace Dumux +{ +/*! + * \brief The mass conservation part of the Mp-Nc model. + * + * This is the specialization for the case where kinetic mass transfer + * *is* considered. + */ +template<class TypeTag> +class MPNCLocalResidualMass<TypeTag, /*enableKinetic=*/true> +{ + typedef MPNCLocalResidualMassCommon<TypeTag> MassCommon; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; + typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; + typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; + + enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; + enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; + enum { conti0EqIdx = Indices::conti0EqIdx }; + enum { nCompIdx = FluidSystem::nCompIdx } ; + enum { wCompIdx = FluidSystem::wCompIdx } ; + enum { wPhaseIdx = FluidSystem::wPhaseIdx} ; + enum { nPhaseIdx = FluidSystem::nPhaseIdx} ; + enum { sPhaseIdx = FluidSystem::sPhaseIdx} ; + enum { numEnergyEquations = GET_PROP_VALUE(TypeTag, NumEnergyEquations) }; + enum { enableEnergy = GET_PROP_VALUE(TypeTag, EnableEnergy) }; + + typedef MPNCLocalResidualEnergy<TypeTag, enableEnergy, numEnergyEquations> EnergyResid; + typedef typename Dune::FieldVector<Scalar, numComponents> ComponentVector; + +public: + + /*! + * \brief Calculate the storage for all mass balance equations + * + * \param storage The mass of the component within the sub-control volume + * \param volVars The volume variables + */ + static void computeStorage(PrimaryVariables & storage, + const VolumeVariables & volVars) + { + for (int phaseIdx =0; phaseIdx < numPhases; ++phaseIdx) + for (int compIdx = 0; compIdx < numComponents; ++compIdx) + storage[conti0EqIdx + phaseIdx*numComponents + compIdx] = 0.0; + + for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { + addPhaseStorage(storage, volVars, phaseIdx); + } + } + + /*! + * \brief Calculate the storage for all mass balance equations + * within a single fluid phase + * + * \param storage The mass of the component within the sub-control volume + * \param volVars The volume variables + * \param phaseIdx phaseIdx The index of the fluid phase + */ + static void addPhaseStorage(PrimaryVariables & storage, + const VolumeVariables & volVars, + const unsigned int phaseIdx) + { + if (phaseIdx == sPhaseIdx) + return; + + // calculate the component-wise mass storage + ComponentVector phaseComponentValues; + MassCommon::computePhaseStorage(phaseComponentValues, + volVars, + phaseIdx); + Valgrind::CheckDefined(phaseComponentValues); + Valgrind::CheckDefined(storage); + + // copy to the primary variables + for (int compIdx = 0; compIdx < numComponents; ++compIdx){ + storage[conti0EqIdx + phaseIdx*numComponents + compIdx] + += phaseComponentValues[compIdx]; + + if (!std::isfinite(storage[conti0EqIdx + phaseIdx*numComponents + compIdx])) + DUNE_THROW(NumericalProblem, "Calculated non-finite storage"); + } + + Valgrind::CheckDefined(storage); + } + + /*! + * \brief Calculate the storage for all mass balance equations + * + * \param flux The flux over the SCV (sub-control-volume) face for each component + * \param fluxVars The flux Variables + * \param elemVolVars The volume variables of the current element + */ + static void computeFlux(PrimaryVariables & flux, + const FluxVariables & fluxVars, + const ElementVolumeVariables & elemVolVars) + { + ComponentVector phaseComponentValuesMassTransport[numPhases]; // what goes into the energy module + + for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { + ComponentVector phaseComponentValuesAdvection(0.); + ComponentVector phaseComponentValuesDiffusion(0.); + MassCommon::computeAdvectivePhaseFlux(phaseComponentValuesAdvection, fluxVars, phaseIdx); + for (int compIdx = 0; compIdx < numComponents; ++compIdx) { + flux[conti0EqIdx + phaseIdx*numComponents + compIdx] = + phaseComponentValuesAdvection[compIdx]; + Valgrind::CheckDefined(flux); + } + MassCommon::computeDiffusivePhaseFlux(phaseComponentValuesDiffusion, fluxVars, phaseIdx); + for (int compIdx = 0; compIdx < numComponents; ++compIdx) { + flux[conti0EqIdx + phaseIdx*numComponents + compIdx] += + phaseComponentValuesDiffusion[compIdx]; + Valgrind::CheckDefined(flux); + + if (!std::isfinite(flux[conti0EqIdx + phaseIdx*numComponents + compIdx])) + DUNE_THROW(NumericalProblem, "Calculated non-finite flux"); + } + + // Right now I think that adding the two contributions individually into the flux is best for debugging and understanding. + // The Energy module needs both contributions. + phaseComponentValuesMassTransport[phaseIdx] = phaseComponentValuesDiffusion + phaseComponentValuesAdvection ; + Valgrind::CheckDefined(flux); + + }// phases + + // The computeflux() of the Energy module needs a component-wise flux (for the diffusive enthalpie transport) + // It makes some sense calling energy from here, because energy is carried by mass + // However, it is not really tidied up. + // todo is there a better way to do this? + EnergyResid::computeFlux(flux, + fluxVars, + elemVolVars, + phaseComponentValuesMassTransport); + Valgrind::CheckDefined(flux); + } + + + /*! + * \brief Calculate the source terms for all mass balance equations + * + * \param source The source/sink in the sub-control volume for each component + * \param volVars the volume variables + */ + static void computeSource(PrimaryVariables & source, + const VolumeVariables & volVars) + { + + // In the case of a kinetic consideration, mass transfer + // between phases is realized via source terms there is a + // balance equation for each component in each phase + ComponentVector componentIntoPhaseMassTransfer[numPhases]; +#define FUNKYMASSTRANSFER 0 +#if FUNKYMASSTRANSFER + const Scalar mu_nPhaseNCompEquil = volVars.chemicalPotentialEquil(nPhaseIdx, nCompIdx) ; // very 2p2c + const Scalar mu_wPhaseWCompEquil = volVars.chemicalPotentialEquil(wPhaseIdx, wCompIdx); // very 2p2c + + const Scalar mu_wPhaseNComp = volVars.chemicalPotential(wPhaseIdx, nCompIdx) ; // very 2p2c + const Scalar mu_nPhaseWComp = volVars.chemicalPotential(nPhaseIdx, wCompIdx); // very 2p2c + + Valgrind::CheckDefined(mu_nPhaseNCompEquil); + Valgrind::CheckDefined(mu_wPhaseWCompEquil); + Valgrind::CheckDefined(mu_wPhaseNComp); + Valgrind::CheckDefined(mu_nPhaseWComp); + + const Scalar characteristicLength = volVars.characteristicLength() ; + const Scalar temperature = volVars.fluidState().temperature(wPhaseIdx); + const Scalar pn = volVars.fluidState().pressure(nPhaseIdx); + const Scalar henry = FluidSystem::henry(temperature) ; + const Scalar gradNinWApprox = ( mu_wPhaseNComp - mu_nPhaseNCompEquil) / characteristicLength; // very 2p2c // 1. / henry * + const Scalar gradWinNApprox = ( mu_nPhaseWComp - mu_wPhaseWCompEquil) / characteristicLength; // very 2p2c // 1. / pn * + +#else // FUNKYMASSTRANSFER + Scalar x[numPhases][numComponents]; // mass fractions in wetting phase + for(int phaseIdx=0; phaseIdx<numPhases; ++phaseIdx){ + for (int compIdx=0; compIdx< numComponents; ++ compIdx){ + x[phaseIdx][compIdx] = volVars.fluidState().moleFraction(phaseIdx, compIdx); + } + } + Valgrind::CheckDefined(x); + +// "equilibrium" values: calculated in volume variables + const Scalar x_wPhaseNCompEquil = volVars.xEquil(wPhaseIdx, nCompIdx) ; // very 2p2c + const Scalar x_nPhaseWCompEquil = volVars.xEquil(nPhaseIdx, wCompIdx); // very 2p2c + Valgrind::CheckDefined(x_wPhaseNCompEquil); + Valgrind::CheckDefined(x_nPhaseWCompEquil); + const Scalar characteristicLength = volVars.characteristicLength() ; + const Scalar gradNinWApprox = (x[wPhaseIdx][nCompIdx] - x_wPhaseNCompEquil) / characteristicLength; // very 2p2c + const Scalar gradWinNApprox = (x[nPhaseIdx][wCompIdx] - x_nPhaseWCompEquil) / characteristicLength; // very 2p2c +#endif + Scalar phaseDensity[numPhases]; + for(int phaseIdx=0; phaseIdx<numPhases; ++phaseIdx){ + phaseDensity[phaseIdx] = volVars.fluidState().molarDensity(phaseIdx); + } + + // diffusion coefficients in wetting phase + const Scalar diffCoeffNinW = volVars.diffCoeff(wPhaseIdx, wCompIdx, nCompIdx) ; + Valgrind::CheckDefined(diffCoeffNinW); + // diffusion coefficients in non-wetting phase + const Scalar diffCoeffWinN = volVars.diffCoeff(nPhaseIdx, wCompIdx, nCompIdx) ; + Valgrind::CheckDefined(diffCoeffWinN); + + const Scalar factorMassTransfer = volVars.factorMassTransfer() ; + const Scalar awn = volVars.interfacialArea(wPhaseIdx, nPhaseIdx); + + const Scalar sherwoodWPhase = volVars.sherwoodNumber(wPhaseIdx); + const Scalar sherwoodNPhase = volVars.sherwoodNumber(nPhaseIdx); + + // actual diffusion is always calculated for eq's 2,3 + // Eq's 1,4 have to be the same with different sign, because no mass is accumulated in the interface + // i.e. automatically conserving mass that mvoes across the interface + + const Scalar nCompIntoWPhase = - factorMassTransfer * gradNinWApprox * awn * phaseDensity[wPhaseIdx] * diffCoeffNinW * sherwoodWPhase; + const Scalar nCompIntoNPhase = - nCompIntoWPhase ; + const Scalar wCompIntoNPhase = - factorMassTransfer * gradWinNApprox * awn * phaseDensity[nPhaseIdx] * diffCoeffWinN * sherwoodNPhase; + const Scalar wCompIntoWPhase = - wCompIntoNPhase ; + + componentIntoPhaseMassTransfer[wPhaseIdx][nCompIdx] = nCompIntoWPhase; + componentIntoPhaseMassTransfer[nPhaseIdx][nCompIdx] = nCompIntoNPhase; + componentIntoPhaseMassTransfer[nPhaseIdx][wCompIdx] = wCompIntoNPhase; + componentIntoPhaseMassTransfer[wPhaseIdx][wCompIdx] = wCompIntoWPhase; + +#if MASS_TRANSFER_OFF +#warning MASS TRANSFER OFF + for(int phaseIdx=0; phaseIdx<numPhases; ++phaseIdx){ + for (int compIdx=0; compIdx< numComponents; ++ compIdx){ + componentIntoPhaseMassTransfer[phaseIdx][compIdx] = 0.; + } + } +#endif + + Valgrind::CheckDefined(componentIntoPhaseMassTransfer); + + // Call the (kinetic) Energy module, for the source term. + // it has to be called from here, because the mass transfered has to be known. + EnergyResid::computeSource(source, + volVars, + componentIntoPhaseMassTransfer); + + // Actually add the mass transfer to the sources which might + // exist externally + for (int phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) { + for (int compIdx = 0; compIdx < numComponents; ++ compIdx) { + const unsigned int eqIdx = conti0EqIdx + compIdx + phaseIdx*numComponents; + source[eqIdx] += componentIntoPhaseMassTransfer[phaseIdx][compIdx] ; + + if (!std::isfinite(source[eqIdx])) + DUNE_THROW(NumericalProblem, "Calculated non-finite source"); + } + } + Valgrind::CheckDefined(source); + } +}; + +} // end namespace Dumux + +#endif diff --git a/dumux/porousmediumflow/mpnc/implicit/mass/volumevariables.hh b/dumux/porousmediumflow/mpnc/implicit/mass/volumevariables.hh new file mode 100644 index 0000000000000000000000000000000000000000..765d644905d4c61605b3fe7449f16c285e210b96 --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/mass/volumevariables.hh @@ -0,0 +1,130 @@ +// -*- 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 Contains the mass conservation part of the volume variables. + */ +#ifndef DUMUX_MPNC_VOLUME_VARIABLES_MASS_HH +#define DUMUX_MPNC_VOLUME_VARIABLES_MASS_HH + +#include <dumux/porousmediumflow/mpnc/implicit/properties.hh> + +#include <dumux/material/fluidstates/compositionalfluidstate.hh> + +namespace Dumux +{ +/*! + * \brief The compositional part of the volume variables if chemical + * equilibrium _is_ assumed. + */ +template <class TypeTag, bool enableKinetic /* = false */> +class MPNCVolumeVariablesMass +{ + static_assert(!enableKinetic, + "No kinetic mass transfer module included, " + "but kinetic mass transfer enabled."); + + typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; + typedef typename FluidSystem::ParameterCache ParameterCache; + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GET_PROP_TYPE(TypeTag, ConstraintSolver) ConstraintSolver; + typedef typename GridView::template Codim<0>::Entity Element; + + enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; + enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; + enum { fug0Idx = Indices::fug0Idx }; + enum { dimWorld = GridView::dimensionworld}; + typedef Dune::FieldVector<typename GridView::Grid::ctype, dimWorld> GlobalPosition; + + typedef Dune::FieldVector<Scalar, numComponents> ComponentVector; + +public: + /*! + * \brief Update composition of all phases in the mutable + * parameters from the primary variables. + * + * \param fs Container for all the secondary variables concerning the fluids + * \param paramCache Container for cache parameters + * \param priVars The primary Variables + * \param *hint the volume variables, usable for initial guess of composition + * \param problem The problem + * \param element The finite element + * \param fvGeometry The finite-volume geometry in the fully implicit scheme + * \param scvIdx The index of the sub-control volume + */ + void update(FluidState &fs, + ParameterCache ¶mCache, + const PrimaryVariables &priVars, + const VolumeVariables *hint, + const Problem &problem, + const Element &element, + const FVElementGeometry &fvGeometry, + const unsigned int scvIdx) + { + ComponentVector fug; + // retrieve component fugacities + for (int compIdx = 0; compIdx < numComponents; ++compIdx) + fug[compIdx] = priVars[fug0Idx + compIdx]; + + // calculate phase compositions + for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { + // initial guess + for (int compIdx = 0; compIdx < numComponents; ++compIdx) { + Scalar x_ij = 1.0/numComponents; + if (hint) + // use the hint for the initial mole fraction! + x_ij = hint->fluidState().moleFraction(phaseIdx, compIdx); + + // set initial guess of the component's mole fraction + fs.setMoleFraction(phaseIdx, + compIdx, + x_ij); + + } + + // calculate the phase composition from the component + // fugacities + if (!hint) + // if no hint was given, we ask the constraint solver + // to make an initial guess + ConstraintSolver::guessInitial(fs, paramCache, phaseIdx, fug); + ConstraintSolver::solve(fs, paramCache, phaseIdx, fug); + } + } + + /*! + * \brief If running in valgrind this makes sure that all + * quantities in the volume variables are defined. + */ + void checkDefined() const + { + } +}; + +} // end namespace + +#endif diff --git a/dumux/porousmediumflow/mpnc/implicit/mass/volumevariableskinetic.hh b/dumux/porousmediumflow/mpnc/implicit/mass/volumevariableskinetic.hh new file mode 100644 index 0000000000000000000000000000000000000000..898c45ef713035215f7b12248eeb754b551fb656 --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/mass/volumevariableskinetic.hh @@ -0,0 +1,175 @@ +// -*- 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 Contains the mass conservation part of the volume variables + */ +#ifndef DUMUX_MPNC_VOLUME_VARIABLES_MASS_KINETIC_HH +#define DUMUX_MPNC_VOLUME_VARIABLES_MASS_KINETIC_HH + +#include <dumux/material/fluidstates/nonequilibriumfluidstate.hh> +#include <dumux/porousmediumflow/mpnc/implicit/mass/volumevariables.hh> +#include <dumux/material/constraintsolvers/fluidsystemcomputefromreferencephase.hh> +#include <dumux/material/constraintsolvers/fluidsystemconstraintsolver.hh> +#include <dumux/material/constraintsolvers/misciblemultiphasecomposition.hh> + + +namespace Dumux +{ +/*! + * \brief The compositional part of the volume variables if chemical + * equilibrium is _not_ assumed + * + * The interface for basing mass transfer on chemical potentials was present in revision 12743 + */ +template <class TypeTag> +class MPNCVolumeVariablesMass<TypeTag, /*bool enableKinetic=*/true> +{ + typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; + + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; + typedef typename FluidSystem::ParameterCache ParameterCache; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GridView::template Codim<0>::Entity Element; + + enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; + enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; + enum { moleFrac00Idx = Indices::moleFrac00Idx }; + + typedef typename Dune::FieldVector<Scalar, numComponents> ComponentVector; + + // here, we need a constraint solver, which gives me the composition of a phase, if the other one is given + typedef FluidSystemComputeFromReferencePhase<Scalar, FluidSystem> ConstraintReferencePhaseSolver; + + // here, we need a constraint solver, which gives me the composition of all phases if p,T is given + typedef FluidSystemConstraintSolver<Scalar, FluidSystem> ConstraintSolver; + + // this is the constraint solver that applies "fugacities" +// typedef MiscibleMultiPhaseComposition<Scalar, FluidSystem> ConstraintSolver; +public: + + /*! + * \brief Update composition of all phases in the mutable + * parameters from the primary variables. + * + * \param actualFluidState Container for all the secondary variables concerning the fluids + * \param paramCache Container for cache parameters + * \param priVars The primary Variables + * \param *hint the volume variables, usable for initial guess of composition + * \param problem The problem + * \param element The finite element + * \param fvGeometry The finite-volume geometry in the fully implicit scheme + * \param scvIdx The index of the sub-control volume + */ + void update(FluidState & actualFluidState, + ParameterCache & paramCache, + const PrimaryVariables & priVars, + const VolumeVariables * hint, + const Problem & problem, + const Element & element, + const FVElementGeometry & fvGeometry, + const unsigned int scvIdx) + { + // setting the mole fractions of the fluid state + for(int smallLoopPhaseIdx=0; smallLoopPhaseIdx<numPhases; ++smallLoopPhaseIdx){ + // set the component mole fractions + for (int compIdx = 0; compIdx < numComponents; ++compIdx) { + actualFluidState.setMoleFraction(smallLoopPhaseIdx, + compIdx, + priVars[moleFrac00Idx + + smallLoopPhaseIdx*numComponents + + compIdx]); + } + } + +// // For using the ... other way of calculating equilibrium +// THIS IS ONLY FOR silencing Valgrind but is not used in this model + for(int smallLoopPhaseIdx=0; smallLoopPhaseIdx<numPhases; ++smallLoopPhaseIdx) + for (int compIdx = 0; compIdx < numComponents; ++compIdx) { + const Scalar phi = FluidSystem::fugacityCoefficient(actualFluidState, + paramCache, + smallLoopPhaseIdx, + compIdx); + actualFluidState.setFugacityCoefficient(smallLoopPhaseIdx, + compIdx, + phi); + } + + FluidState equilFluidState; // the fluidState *on the interface* i.e. chemical equilibrium + equilFluidState.assign(actualFluidState) ; + ConstraintSolver::solve(equilFluidState, + paramCache, + /*setViscosity=*/false, + /*setEnthalpy=*/false) ; + + // Setting the equilibrium composition (in a kinetic model not necessarily the same as the actual mole fraction) + for(int smallLoopPhaseIdx=0; smallLoopPhaseIdx<numPhases; ++smallLoopPhaseIdx){ + for (int compIdx=0; compIdx< numComponents; ++ compIdx){ + xEquil_[smallLoopPhaseIdx][compIdx] = equilFluidState.moleFraction(smallLoopPhaseIdx, compIdx); + } + } + + // compute densities of all phases + for(int smallLoopPhaseIdx=0; smallLoopPhaseIdx<numPhases; ++smallLoopPhaseIdx){ + const Scalar rho = FluidSystem::density(actualFluidState, paramCache, smallLoopPhaseIdx); + actualFluidState.setDensity(smallLoopPhaseIdx, rho); + } + + // let Valgrind check whether everything is properly defined. + checkDefined(); + } + + /*! + * \brief The mole fraction we would have in the case of chemical equilibrium / + * on the interface. + * + * \param phaseIdx The index of the fluid phase + * \param compIdx The local index of the component + */ + const Scalar xEquil(const unsigned int phaseIdx, const unsigned int compIdx) const + { + return xEquil_[phaseIdx][compIdx] ; + } + + + /*! + * \brief If running in valgrind this makes sure that all + * quantities in the volume variables are defined. + */ + void checkDefined() const + { +#if HAVE_VALGRIND && !defined NDEBUG + Valgrind::CheckDefined(xEquil_); +#endif + } + +private: + Scalar xEquil_[numPhases][numComponents]; +}; + +} // end namespace + +#endif diff --git a/dumux/porousmediumflow/mpnc/implicit/mass/vtkwriter.hh b/dumux/porousmediumflow/mpnc/implicit/mass/vtkwriter.hh new file mode 100644 index 0000000000000000000000000000000000000000..6fac1ef659c0f573621a8b9c3fff56799b144dfb --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/mass/vtkwriter.hh @@ -0,0 +1,124 @@ +// -*- 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 VTK writer module for the mass related quantities of the + * MpNc model. + */ +#ifndef DUMUX_MPNC_VTK_WRITER_MASS_HH +#define DUMUX_MPNC_VTK_WRITER_MASS_HH + +#include "../vtkwritermodule.hh" + +namespace Dumux +{ +/*! + * \ingroup MPNCModel + * + * \brief VTK writer module for the mass related quantities of the + * MpNc model. + * + * This is the specialization for the case _without_ kinetic mass + * transfer between phases. + */ +template<class TypeTag, bool enableKinetic /* = false */> +class MPNCVtkWriterMass : public MPNCVtkWriterModule<TypeTag> +{ + static_assert(!enableKinetic, + "No kinetic mass transfer module included, " + "but kinetic mass transfer enabled."); + + typedef MPNCVtkWriterModule<TypeTag> ParentType; + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes; + typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GridView::template Codim<0>::Entity Element; + + enum { dim = GridView::dimension }; + enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; + enum { isBox = GET_PROP_VALUE(TypeTag, ImplicitIsBox) }; + enum { dofCodim = isBox ? dim : 0 }; + + typedef typename ParentType::ComponentVector ComponentVector; + bool fugacityOutput_; + +public: + MPNCVtkWriterMass(const Problem &problem) + : ParentType(problem) + { + fugacityOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddFugacities); + } + + /*! + * \brief Allocate memory for the scalar fields we would like to + * write to the VTK file. + */ + template <class MultiWriter> + void allocBuffers(MultiWriter &writer) + { + if (fugacityOutput_) this->resizeComponentBuffer_(fugacity_, isBox); + } + + /*! + * \brief Modify the internal buffers according to the volume + * variables seen on an element + * + * \param element The finite element + * \param fvGeometry The finite-volume geometry in the fully implicit scheme + * \param elemVolVars The volume variables of the current element + * \param elemBcTypes The types of the boundary conditions for all vertices of the element + */ + void processElement(const Element &element, + const FVElementGeometry &fvGeometry, + const ElementVolumeVariables &elemVolVars, + const ElementBoundaryTypes &elemBcTypes) + { + for (int scvIdx = 0; scvIdx < fvGeometry.numScv; ++scvIdx) { + const unsigned int dofIdxGlobal = this->problem_.model().dofMapper().subIndex(element, scvIdx, dofCodim); + const VolumeVariables &volVars = elemVolVars[scvIdx]; + + if (fugacityOutput_) { + for (int compIdx = 0; compIdx < numComponents; ++compIdx) { + fugacity_[compIdx][dofIdxGlobal] = volVars.fluidState().fugacity(compIdx); + } + } + } + } + + /*! + * \brief Add all buffers to the VTK output writer. + */ + template <class MultiWriter> + void commitBuffers(MultiWriter &writer) + { + if (fugacityOutput_) + this->commitComponentBuffer_(writer, "f_%s", fugacity_, isBox); + } + +private: + ComponentVector fugacity_; +}; + +} + +#endif diff --git a/dumux/porousmediumflow/mpnc/implicit/mass/vtkwriterkinetic.hh b/dumux/porousmediumflow/mpnc/implicit/mass/vtkwriterkinetic.hh new file mode 100644 index 0000000000000000000000000000000000000000..2295e2d8c0df8225d509818204416eb60ea01997 --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/mass/vtkwriterkinetic.hh @@ -0,0 +1,164 @@ +// -*- 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 VTK writer module for the mass related quantities of the + * MpNc model (kinetic mass transfer case). + */ +#ifndef DUMUX_MPNC_VTK_WRITER_MASS_KINETIC_HH +#define DUMUX_MPNC_VTK_WRITER_MASS_KINETIC_HH + +#include <dumux/porousmediumflow/mpnc/implicit/vtkwritermodule.hh> +#include <dumux/porousmediumflow/mpnc/implicit/propertieskinetic.hh> +#include <dumux/porousmediumflow/mpnc/implicit/mass/vtkwriter.hh> + + +namespace Dumux +{ + +/*! + * \ingroup MPNCModel + * + * \brief VTK writer module for the mass related quantities of the + * MpNc model. + * + * This is the specialization for the case with kinetic mass transfer. + */ +template<class TypeTag> +class MPNCVtkWriterMass<TypeTag, /* enableKinetic = */ true> + : public MPNCVtkWriterModule<TypeTag> +{ + typedef MPNCVtkWriterModule<TypeTag> ParentType; + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes; + typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + + enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; + enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; + enum { dim = GridView::dimension }; + enum { nPhaseIdx = FluidSystem::nPhaseIdx}; + enum { isBox = GET_PROP_VALUE(TypeTag, ImplicitIsBox) }; + enum { dofCodim = isBox ? dim : 0 }; + + enum { xEquilOutput = GET_PROP_VALUE(TypeTag, VtkAddxEquil) }; + + typedef typename GridView::template Codim<0>::Entity Element; + typedef typename ParentType::ScalarVector ScalarVector; + typedef typename ParentType::PhaseVector PhaseVector; + typedef typename ParentType::ComponentVector ComponentVector; + typedef typename ParentType::PhaseComponentMatrix PhaseComponentMatrix; + + bool deltaPOutput_; +public: + MPNCVtkWriterMass(const Problem &problem) + : ParentType(problem) + { + deltaPOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddDeltaP); + } + + /*! + * \brief Allocate memory for the scalar fields we would like to + * write to the VTK file. + */ + template <class MultiWriter> + void allocBuffers(MultiWriter &writer) + { +// this->resizePhaseComponentBuffer_(drivingThingyMu_); +// this->resizePhaseComponentBuffer_(drivingThingyMole_); + this->resizePhaseComponentBuffer_(moleFracEquil_); + +// this->resizePhaseComponentBuffer_(percentageEquilMoleFrac_); + if (deltaPOutput_) this->resizeScalarBuffer_(deltaP_, isBox); + + } + + /*! + * \brief Modify the internal buffers according to the volume + * variables seen on an element + * + * \param element The finite element + * \param fvGeometry The finite-volume geometry in the fully implicit scheme + * \param elemVolVars The volume variables of the current element + * \param elemBcTypes The types of the boundary conditions for all vertices of the element + */ + void processElement(const Element &element, + const FVElementGeometry &fvGeometry, + const ElementVolumeVariables &elemVolVars, + const ElementBoundaryTypes &elemBcTypes) + { + int numLocalVertices = element.geometry().corners(); + for (int localVertexIdx = 0; localVertexIdx< numLocalVertices; ++localVertexIdx) { + const unsigned int vIdxGlobal = this->problem_.vertexMapper().subIndex(element, localVertexIdx, dim); + const VolumeVariables &volVars = elemVolVars[localVertexIdx]; + + for (unsigned int phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) { + for (unsigned int compIdx = 0; compIdx < numComponents; ++ compIdx) { + moleFracEquil_[phaseIdx][compIdx][vIdxGlobal] = volVars.xEquil(phaseIdx, compIdx); + } + } + +// for (unsigned int phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) { +// for (unsigned int compIdx = 0; compIdx < numComponents; ++ compIdx) { +// drivingThingyMole_[phaseIdx][compIdx][vIdxGlobal] = volVars.xEquil(phaseIdx, compIdx) - volVars.fluidState().moleFraction(phaseIdx, compIdx); +// drivingThingyMu_[phaseIdx][compIdx][vIdxGlobal] = volVars.chemicalPotentialEquil(phaseIdx, compIdx) - volVars.chemicalPotential(phaseIdx, compIdx); +//// percentageEquilMoleFrac_[phaseIdx][compIdx][vIdxGlobal] = (volVars.fluidState().moleFraction(phaseIdx, compIdx)) / volVars.xEquil(phaseIdx, compIdx); +// } +// } + + if (deltaPOutput_) { + deltaP_[vIdxGlobal] = volVars.fluidState().pressure(nPhaseIdx) - 100000.; + } + } + } + + /*! + * \brief Add all buffers to the VTK output writer. + */ + template <class MultiWriter> + void commitBuffers(MultiWriter &writer) + { +// this->commitPhaseComponentBuffer_(writer, "dirivingThingyMole_%s^%s", drivingThingyMole_); +// this->commitPhaseComponentBuffer_(writer, "dirivingThingyMu_%s^%s", drivingThingyMu_); +// this->commitPhaseComponentBuffer_(writer, "percentageEquilMoleFrac_%s^%s", percentageEquilMoleFrac_); + + if(xEquilOutput){ + this->commitPhaseComponentBuffer_(writer, "xEquil_%s^%s", moleFracEquil_); + } + if (deltaPOutput_) + this->commitScalarBuffer_(writer, "pnMinus1e5", deltaP_, isBox); + } + +private: + PhaseComponentMatrix moleFracEquil_; +// PhaseComponentMatrix drivingThingyMole_; +// PhaseComponentMatrix drivingThingyMu_; +// PhaseComponentMatrix percentageEquilMoleFrac_; + + + ScalarVector deltaP_; +}; + +} + +#endif diff --git a/dumux/porousmediumflow/mpnc/implicit/model.hh b/dumux/porousmediumflow/mpnc/implicit/model.hh new file mode 100644 index 0000000000000000000000000000000000000000..e60daf5b2a6acd05671e88df397594c14e88684c --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/model.hh @@ -0,0 +1,213 @@ +// -*- 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 A fully implicit model for MpNc flow using + * vertex centered finite volumes. + * + */ + +#ifndef DUMUX_MPNC_MODEL_HH +#define DUMUX_MPNC_MODEL_HH + +#include "properties.hh" +#include "vtkwriter.hh" + +#include <dumux/implicit/model.hh> + +namespace Dumux +{ +/*! + * \ingroup MPNCModel + * \brief A fully implicit model for MpNc flow using + * vertex centered finite volumes. + * + * This model implements a \f$M\f$-phase flow of a fluid mixture + * composed of \f$N\f$ chemical species. The phases are denoted by + * lower index \f$\alpha \in \{ 1, \dots, M \}\f$. All fluid phases + * are mixtures of \f$N \geq M - 1\f$ chemical species which are + * denoted by the upper index \f$\kappa \in \{ 1, \dots, N \} \f$. + * + * The momentum approximation can be selected via "BaseFluxVariables": + * Darcy (ImplicitDarcyFluxVariables) and Forchheimer (ImplicitForchheimerFluxVariables) + * relations are available for all Box models. + * + * By inserting this into the equations for the conservation of the + * mass of each component, one gets one mass-continuity equation for + * each component \f$\kappa\f$ + * \f[ + \sum_{\kappa} \left( + \phi \frac{\partial \left(\varrho_\alpha x_\alpha^\kappa S_\alpha\right)}{\partial t} + + + \mathrm{div}\; + \left\{ + v_\alpha + \frac{\varrho_\alpha}{\overline M_\alpha} x_\alpha^\kappa + \right\} + \right) + = q^\kappa + \f] + * with \f$\overline M_\alpha\f$ being the average molar mass of the + * phase \f$\alpha\f$: \f[ \overline M_\alpha = \sum_\kappa M^\kappa + * \; x_\alpha^\kappa \f] + * + * For the missing \f$M\f$ model assumptions, the model assumes that + * if a fluid phase is not present, the sum of the mole fractions of + * this fluid phase is smaller than \f$1\f$, i.e. + * \f[ + * \forall \alpha: S_\alpha = 0 \implies \sum_\kappa x_\alpha^\kappa \leq 1 + * \f] + * + * Also, if a fluid phase may be present at a given spatial location + * its saturation must be positive: + * \f[ \forall \alpha: \sum_\kappa x_\alpha^\kappa = 1 \implies S_\alpha \geq 0 \f] + * + * Since at any given spatial location, a phase is always either + * present or not present, one of the strict equalities on the + * right hand side is always true, i.e. + * \f[ \forall \alpha: S_\alpha \left( \sum_\kappa x_\alpha^\kappa - 1 \right) = 0 \f] + * always holds. + * + * These three equations constitute a non-linear complementarity + * problem, which can be solved using so-called non-linear + * complementarity functions \f$\Phi(a, b)\f$ which have the property + * \f[\Phi(a,b) = 0 \iff a \geq0 \land b \geq0 \land a \cdot b = 0 \f] + * + * Several non-linear complementarity functions have been suggested, + * e.g. the Fischer-Burmeister function + * \f[ \Phi(a,b) = a + b - \sqrt{a^2 + b^2} \;. \f] + * This model uses + * \f[ \Phi(a,b) = \min \{a, b \}\;, \f] + * because of its piecewise linearity. + * + * These equations are then discretized using a fully-implicit vertex + * centered finite volume scheme (often known as 'box'-scheme) for + * spatial discretization and the implicit Euler method as temporal + * discretization. + * + * The model assumes local thermodynamic equilibrium and uses the + * following primary variables: + * - The component fugacities \f$f^1, \dots, f^{N}\f$ + * - The pressure of the first phase \f$p_1\f$ + * - The saturations of the first \f$M-1\f$ phases \f$S_1, \dots, S_{M-1}\f$ + * - Temperature \f$T\f$ if the energy equation is enabled + */ +template<class TypeTag> +class MPNCModel : public GET_PROP_TYPE(TypeTag, BaseModel) +{ + typedef typename GET_PROP_TYPE(TypeTag, BaseModel) ParentType; + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; + typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector; + typedef Dumux::MPNCVtkWriter<TypeTag> MPNCVtkWriter; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + + enum {enableEnergy = GET_PROP_VALUE(TypeTag, EnableEnergy)}; + enum {enableDiffusion = GET_PROP_VALUE(TypeTag, EnableDiffusion)}; + enum {enableKinetic = GET_PROP_VALUE(TypeTag, EnableKinetic)}; + enum {numEnergyEquations = GET_PROP_VALUE(TypeTag, NumEnergyEquations)}; + enum {numPhases = GET_PROP_VALUE(TypeTag, NumPhases)}; + enum {numComponents = GET_PROP_VALUE(TypeTag, NumComponents)}; + enum {numEq = GET_PROP_VALUE(TypeTag, NumEq)}; + enum { numEnergyEqs = Indices::numPrimaryEnergyVars}; + enum { dimWorld = GridView::dimensionworld}; + enum { dim = GridView::dimension}; + + typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition; + + +public: + MPNCModel() + { + enableSmoothUpwinding_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Implicit, EnableSmoothUpwinding); + enablePartialReassemble_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Implicit, EnablePartialReassemble); + enableJacobianRecycling_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Implicit, EnableJacobianRecycling); + numDiffMethod_ = GET_PARAM_FROM_GROUP(TypeTag, int, Implicit, NumericDifferenceMethod); + } + + void init(Problem &problem) + { + ParentType::init(problem); + vtkWriter_ = std::make_shared<MPNCVtkWriter>(problem); + + if (this->gridView_().comm().rank() == 0) + std::cout + << "Initializing M-phase N-component model: \n" + << " phases: " << numPhases << "\n" + << " components: " << numComponents << "\n" + << " equations: " << numEq << "\n" + << " kinetic mass transfer: " << enableKinetic<< "\n" + << " number of energy equations: " << numEnergyEquations<< "\n" + << " diffusion: " << enableDiffusion << "\n" + << " energy equation: " << enableEnergy << "\n" + << " smooth upwinding: " << enableSmoothUpwinding_ << "\n" + << " partial jacobian reassembly: " << enablePartialReassemble_ << "\n" + << " numeric differentiation method: " << numDiffMethod_ << " (-1: backward, 0: central, +1 forward)\n" + << " jacobian recycling: " << enableJacobianRecycling_ << "\n"; + } + + /*! + * \brief Compute the total storage inside one phase of all + * conservation quantities. + * + * \param phaseStorage The conserved quantity within the phase in the whole domain + * \param phaseIdx The local index of the phases + */ + void globalPhaseStorage(PrimaryVariables &phaseStorage, const unsigned int phaseIdx) + { + phaseStorage = 0; + + for (const auto& element : Dune::elements(this->gridView_())) { + this->localResidual().addPhaseStorage(phaseStorage, element, phaseIdx); + } + + if (this->gridView_().comm().size() > 1) + phaseStorage = this->gridView_().comm().sum(phaseStorage); + } + + /*! + * \brief Add the result of the current timestep to the VTK output. + */ + template <class MultiWriter> + void addOutputVtkFields(const SolutionVector &sol, + MultiWriter &writer) + { + vtkWriter_->addCurrentSolution(writer); + } + + std::shared_ptr<MPNCVtkWriter> vtkWriter_; + +private: + bool enableSmoothUpwinding_; + bool enablePartialReassemble_; + bool enableJacobianRecycling_; + int numDiffMethod_; +}; + +} + +#include "propertydefaults.hh" + +#endif diff --git a/dumux/porousmediumflow/mpnc/implicit/modelkinetic.hh b/dumux/porousmediumflow/mpnc/implicit/modelkinetic.hh new file mode 100644 index 0000000000000000000000000000000000000000..135180101795f78c9be90253695ecb95129f0a5d --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/modelkinetic.hh @@ -0,0 +1,341 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 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 adds kinetic mass and energy transfer modules to + * the M-phase N-component model. + */ +#ifndef DUMUX_MPNC_MODEL_KINETIC_HH +#define DUMUX_MPNC_MODEL_KINETIC_HH + +// equilibrium model +#include <dumux/porousmediumflow/mpnc/implicit/model.hh> + +// generic stuff +#include "propertieskinetic.hh" + +namespace Dumux +{ +/*! + * \ingroup MPNCModel + * \brief A fully implicit model for MpNc flow using + * vertex centered finite volumes. + * This is the specialization that is able to capture kinetic mass and / or energy transfer. + * + * Please see the comment in the localresidualenergykinetic class about the inclusion of volume changing work. + * + * Please see the comment about different possibilities of calculating phase-composition in the mpnclocalresidualmasskinetic class. + */ + +template<class TypeTag> +class MPNCModelKinetic : public MPNCModel<TypeTag> +{ + typedef MPNCModel<TypeTag> ParentType; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes; + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + typedef Dune::BlockVector<Dune::FieldVector<Scalar, 1> > ScalarField; + typedef Dumux::MPNCVtkWriter<TypeTag> MPNCVtkWriter; + + enum { enableEnergy = GET_PROP_VALUE(TypeTag, EnableEnergy)}; + enum { enableDiffusion = GET_PROP_VALUE(TypeTag, EnableDiffusion)}; + enum { enableKinetic = GET_PROP_VALUE(TypeTag, EnableKinetic)}; + enum { numEnergyEquations = GET_PROP_VALUE(TypeTag, NumEnergyEquations)}; + enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases)}; + enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents)}; + enum { numEq = GET_PROP_VALUE(TypeTag, NumEq)}; + enum { numEnergyEqs = Indices::numPrimaryEnergyVars}; + enum { dimWorld = GridView::dimensionworld}; + enum { dim = GridView::dimension}; + + typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition; + typedef Dune::BlockVector<GlobalPosition> GlobalPositionField; + typedef std::array<GlobalPositionField, numPhases> PhaseGlobalPositionField; + + typedef std::vector<Dune::FieldVector<Scalar, 1> > ScalarVector; + typedef std::array<ScalarVector, numPhases> PhaseVector; + typedef Dune::FieldVector<Scalar, dim> DimVector; + typedef Dune::BlockVector<DimVector> DimVectorField; + typedef std::array<DimVectorField, numPhases> PhaseDimVectorField; + +public: + /*! + * \brief Initialize the fluid system's static parameters + * \param problem The Problem + */ + void init(Problem &problem) + { + ParentType::init(problem); + static_assert(FluidSystem::numComponents==2, " so far kinetic mass transfer assumes a two-component system. "); + } + + /*! + * \brief Initialze the velocity vectors. + * + * Otherwise the initial solution cannot be written to disk. + */ + void initVelocityStuff(){ + // belongs to velocity averaging + int numVertices = this->gridView().size(dim); + + // allocation and bringing to size + for (unsigned int phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) { + volumeDarcyVelocity_[phaseIdx].resize(numVertices); + volumeDarcyMagVelocity_[phaseIdx].resize(numVertices); + std::fill(volumeDarcyMagVelocity_[phaseIdx].begin(), volumeDarcyMagVelocity_[phaseIdx].end(), 0.0); + boxSurface_.resize(numVertices); + std::fill(boxSurface_.begin(), boxSurface_.end(), 0.0); + volumeDarcyVelocity_[phaseIdx] = 0; + } + } + + + /*! + * \brief face-area weighted average of the velocities. + * + * This function calculates the darcy velocities on the faces and averages them for one vertex. + * The weight of the average is the area of the face. + * + * Called by newtonControlle in newtonUpdate if velocityAveragingInProblem is true. + */ + void calcVelocityAverage() + { + Scalar numVertices = this->gridView().size(dim); + + // reset + for (int phaseIdx =0; phaseIdx<numPhases; ++phaseIdx){ + std::fill(boxSurface_.begin(), boxSurface_.end(), 0.0); + volumeDarcyVelocity_[phaseIdx] = 0; + std::fill(volumeDarcyMagVelocity_[phaseIdx].begin(), volumeDarcyMagVelocity_[phaseIdx].end(), 0.0); + } + + // loop all elements + for (const auto& element : Dune::elements(this->gridView_())){ + //obtaining the elementVolumeVariables needed for the Fluxvariables + FVElementGeometry fvGeometry; + ElementVolumeVariables elemVolVars; + ElementBoundaryTypes elemBcTypes; + + fvGeometry.update(this->gridView_(), element); + elemBcTypes.update(this->problem_(), element); + + this->setHints(element, elemVolVars); + elemVolVars.update(this->problem_(), + element, + fvGeometry, + false); + + this->updateCurHints(element, elemVolVars); + for (int fIdx = 0; fIdx < fvGeometry.numScvf; ++ fIdx) { + int i = fvGeometry.subContVolFace[fIdx].i; + int I = this->vertexMapper().subIndex(element, i, dim); + + int j = fvGeometry.subContVolFace[fIdx].j; + int J = this->vertexMapper().subIndex(element, j, dim); + + const Scalar scvfArea = fvGeometry.subContVolFace[fIdx].normal.two_norm(); + boxSurface_[I] += scvfArea; + boxSurface_[J] += scvfArea; + + FluxVariables fluxVars(this->problem_(), + element, + fvGeometry, + fIdx, + elemVolVars); + + for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { + GlobalPosition faceDarcyVelocity = fluxVars.velocity(phaseIdx); + faceDarcyVelocity *= scvfArea; + + // although not yet really a volume average, see later: divide by surface + volumeDarcyVelocity_[phaseIdx][I] += faceDarcyVelocity; + volumeDarcyVelocity_[phaseIdx][J] += faceDarcyVelocity; + } // end phases + } // end faces + } // end elements + + // Divide by the sum of the faces: actually producing the average (as well as it's magnitude) + for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { + // first, divide the velocity field by the + // respective finite volume's surface area + for (int I = 0; I < numVertices; ++I){ + volumeDarcyVelocity_[phaseIdx][I] /= boxSurface_[I]; + volumeDarcyMagVelocity_[phaseIdx][I] = volumeDarcyVelocity_[phaseIdx][I].two_norm() ; + }// end all vertices + }// end all phases + }// end calcVelocity + +// /*! +// * \brief Check whether the current solution makes sense. +// */ +// void checkPlausibility() const +// { +// // Looping over all elements of the domain +// for (const auto& element : Dune::elements(this->gridView_())) +// { +// ElementVolumeVariables elemVolVars; +// FVElementGeometry fvGeometry; +// +// // updating the volume variables +// fvGeometry.update(this->problem_().gridView(), element); +// elemVolVars.update(this->problem_(), element, fvGeometry, false); +// +// std::stringstream message ; +// // number of scv +// const unsigned int numScv = fvGeometry.numScv; // box: numSCV, cc:1 +// +// for (unsigned int scvIdx = 0; scvIdx < numScv; ++scvIdx) { +// +// const FluidState & fluidState = elemVolVars[scvIdx].fluidState(); +// +// // energy check +// for(unsigned int energyEqIdx=0; energyEqIdx<numEnergyEqs; energyEqIdx++){ +// const Scalar eps = 1e-6 ; +//// const Scalar temperatureTest = elemVolVars[scvIdx].fluidState().temperature(); +// const Scalar temperatureTest = elemVolVars[scvIdx].temperature(energyEqIdx); +//// const Scalar temperatureTest = 42; +// +// if (not std::isfinite(temperatureTest) or temperatureTest < 0. ){ +// message <<"\nUnphysical Value in Energy: \n"; +// message << "\tT" <<"_"<<FluidSystem::phaseName(energyEqIdx)<<"="<< temperatureTest <<"\n"; +// } +// } +// +// // mass Check +// for(int phaseIdx=0; phaseIdx<numPhases; phaseIdx++){ +// const Scalar eps = 1e-6 ; +// for (int compIdx=0; compIdx< numComponents; ++ compIdx){ +// const Scalar xTest = fluidState.moleFraction(phaseIdx, compIdx); +// if (not std::isfinite(xTest) or xTest < 0.-eps or xTest > 1.+eps ){ +// message <<"\nUnphysical Value in Mass: \n"; +// +// message << "\tx" <<"_"<<FluidSystem::phaseName(phaseIdx) +// <<"^"<<FluidSystem::componentName(compIdx)<<"=" +// << fluidState.moleFraction(phaseIdx, compIdx) <<"\n"; +// } +// } +// } +// +// // interfacial area check (interfacial area between fluid as well as solid phases) +// for(int phaseIdxI=0; phaseIdxI<numPhases+1; phaseIdxI++){ +// const Scalar eps = 1e-6 ; +// for (int phaseIdxII=0; phaseIdxII< numPhases+1; ++ phaseIdxII){ +// if (phaseIdxI == phaseIdxII) +// continue; +// assert(numEnergyEqs == 3) ; // otherwise this ia call does not make sense +// const Scalar ia = elemVolVars[scvIdx].interfacialArea(phaseIdxI, phaseIdxII); +// if (not std::isfinite(ia) or ia < 0.-eps ) { +// message <<"\nUnphysical Value in interfacial area: \n"; +// message << "\tia" <<FluidSystem::phaseName(phaseIdxI) +// <<FluidSystem::phaseName(phaseIdxII)<<"=" +// << ia << "\n" ; +// message << "\t S[0]=" << fluidState.saturation(0); +// message << "\t S[1]=" << fluidState.saturation(1); +// message << "\t p[0]=" << fluidState.pressure(0); +// message << "\t p[1]=" << fluidState.pressure(1); +// } +// } +// } +// +// // General Check +// for(int phaseIdx=0; phaseIdx<numPhases; phaseIdx++){ +// const Scalar eps = 1e-6 ; +// const Scalar saturationTest = fluidState.saturation(phaseIdx); +// if (not std::isfinite(saturationTest) or saturationTest< 0.-eps or saturationTest > 1.+eps ){ +// message <<"\nUnphysical Value in Saturation: \n"; +// message << "\tS" <<"_"<<FluidSystem::phaseName(phaseIdx)<<"=" << std::scientific +// << fluidState.saturation(phaseIdx) << std::fixed << "\n"; +// } +// } +// +// // velocity Check +// const unsigned int globalVertexIdx = this->problem_().vertexMapper().subIndex(element, scvIdx, dim); +// for(int phaseIdx=0; phaseIdx<numPhases; phaseIdx++){ +// const Scalar eps = 1e-6 ; +// const Scalar velocityTest = volumeDarcyMagVelocity(phaseIdx, globalVertexIdx); +// if (not std::isfinite(velocityTest) ){ +// message <<"\nUnphysical Value in Velocity: \n"; +// message << "\tv" <<"_"<<FluidSystem::phaseName(phaseIdx)<<"=" << std::scientific +// << velocityTest << std::fixed << "\n"; +// } +// } +// +// +// // Some check wrote into the error-message, add some additional information and throw +// if (not message.str().empty()){ +// // Getting the spatial coordinate +// const GlobalPosition & globalPosCurrent = fvGeometry.subContVol[scvIdx].global; +// std::stringstream positionString ; +// +// // Add physical location +// positionString << "Here:"; +// for(int i=0; i<dim; i++) +// positionString << " x"<< (i+1) << "=" << globalPosCurrent[i] << " " ; +// message << "Unphysical value found! \n" ; +// message << positionString.str() ; +// message << "\n"; +// +// message << " Here come the primary Variables:" << "\n" ; +// for(unsigned int priVarIdx =0 ; priVarIdx<numEq; ++priVarIdx){ +// message << "priVar[" << priVarIdx << "]=" << elemVolVars[scvIdx].priVar(priVarIdx) << "\n"; +// } +// DUNE_THROW(NumericalProblem, message.str()); +// } +// } // end scv-loop +// } // end element loop +// } + + /*! + * \brief Access to the averaged (magnitude of) velocity for each vertex. + * + * \param phaseIdx The index of the fluid phase + * \param dofIdxGlobal The global index of the degree of freedom + * + */ + const Scalar volumeDarcyMagVelocity(const unsigned int phaseIdx, + const unsigned int dofIdxGlobal) const + { return volumeDarcyMagVelocity_[phaseIdx][dofIdxGlobal]; } + + /*! + * \brief Access to the averaged velocity for each vertex. + * + * \param phaseIdx The index of the fluid phase + * \param dofIdxGlobal The global index of the degree of freedom + */ + const GlobalPosition volumeDarcyVelocity(const unsigned int phaseIdx, + const unsigned int dofIdxGlobal) const + { return volumeDarcyVelocity_[phaseIdx][dofIdxGlobal]; } + +private: + PhaseGlobalPositionField volumeDarcyVelocity_; + PhaseVector volumeDarcyMagVelocity_ ; + ScalarVector boxSurface_ ; +}; + +} // namespace Dumux + +#include "propertydefaultskinetic.hh" + +#endif diff --git a/dumux/porousmediumflow/mpnc/implicit/newtoncontroller.hh b/dumux/porousmediumflow/mpnc/implicit/newtoncontroller.hh new file mode 100644 index 0000000000000000000000000000000000000000..4d2229acdbaef2fb058b005b9e785a05596913ac --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/newtoncontroller.hh @@ -0,0 +1,271 @@ +// -*- 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 A MpNc specific controller for the newton solver, which knows + * 'physically meaningful' solution. + * + * This controller 'knows' what a 'physically meaningful' solution is + * which allows the newton method to abort quicker if the solution is + * way out of bounds. + */ +#ifndef DUMUX_MPNC_NEWTON_CONTROLLER_HH +#define DUMUX_MPNC_NEWTON_CONTROLLER_HH + +#include "properties.hh" + +#include <dumux/nonlinear/newtoncontroller.hh> +#include <algorithm> + +namespace Dumux { + +/*! + * \brief A MpNc specific controller for the newton solver, which knows + * 'physically meaningful' solution. + */ +template <class TypeTag, bool enableKinetic /* = false */> +class MpNcNewtonChop +{ + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector; + + enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; + enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; + enum { fug0Idx = Indices::fug0Idx }; + enum { s0Idx = Indices::s0Idx }; + enum { p0Idx = Indices::p0Idx }; + +public: + static void chop(SolutionVector &uCurrentIter, + const SolutionVector &uLastIter) + { + for (unsigned int i = 0; i < uLastIter.size(); ++i) { + for (unsigned int phaseIdx = 0; phaseIdx < numPhases - 1; ++phaseIdx) + saturationChop_(uCurrentIter[i][s0Idx + phaseIdx], + uLastIter[i][s0Idx + phaseIdx]); + pressureChop_(uCurrentIter[i][p0Idx], uLastIter[i][p0Idx]); + for (unsigned int comp = 0; comp < numComponents; ++comp) { + pressureChop_(uCurrentIter[i][fug0Idx + comp], uLastIter[i][fug0Idx + comp]); + } + + } + }; + +private: + static void clampValue_(Scalar &val, + const Scalar minVal, + const Scalar maxVal) + { + val = std::max(minVal, std::min(val, maxVal)); + }; + + static void pressureChop_(Scalar &val, + const Scalar oldVal) + { + const Scalar maxDelta = std::max(oldVal/4.0, 10e3); + clampValue_(val, oldVal - maxDelta, oldVal + maxDelta); + val = std::max(0.0, val); // don't allow negative pressures + } + + static void saturationChop_(Scalar &val, + const Scalar oldVal) + { + const Scalar maxDelta = 0.25; + clampValue_(val, oldVal - maxDelta, oldVal + maxDelta); + clampValue_(val, -0.001, 1.001); + } + +}; + +template <class TypeTag> +class MpNcNewtonChop<TypeTag, /*enableKinetic=*/true> +{ + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector; + + enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; + enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; + enum { moleFrac00Idx = Indices::moleFrac00Idx }; + enum { s0Idx = Indices::s0Idx }; + enum { p0Idx = Indices::p0Idx }; + +public: + static void chop(SolutionVector &uCurrentIter, + const SolutionVector &uLastIter) + { + for (unsigned int i = 0; i < uLastIter.size(); ++i) { + for (int phaseIdx = 0; phaseIdx < numPhases - 1; ++phaseIdx) + saturationChop_(uCurrentIter[i][s0Idx + phaseIdx], + uLastIter[i][s0Idx + phaseIdx]); + pressureChop_(uCurrentIter[i][p0Idx], uLastIter[i][p0Idx]); + for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { + for (int compIdx = 0; compIdx < numComponents; ++compIdx) { + moleFracChop_(uCurrentIter[i][moleFrac00Idx + phaseIdx*numComponents + compIdx], + uLastIter[i][moleFrac00Idx + phaseIdx*numComponents + compIdx]); + } + } + + } + } + +private: + static void clampValue_(Scalar &val, + const Scalar minVal, + const Scalar maxVal) + { + val = std::max(minVal, std::min(val, maxVal)); + }; + + static void pressureChop_(Scalar &val, + const Scalar oldVal) + { + const Scalar maxDelta = std::max(oldVal/4.0, 10e3); + clampValue_(val, oldVal - maxDelta, oldVal + maxDelta); + val = std::max(0.0, val); // don't allow negative pressures + } + + static void saturationChop_(Scalar &val, + const Scalar oldVal) + { + const Scalar maxDelta = 0.25; + clampValue_(val, oldVal - maxDelta, oldVal + maxDelta); + clampValue_(val, -0.001, 1.001); + } + + static void moleFracChop_(Scalar &val, + const Scalar oldVal) + { + // no component mole fraction can change by more than 20% per iteration + const Scalar maxDelta = 0.20; + clampValue_(val, oldVal - maxDelta, oldVal + maxDelta); + clampValue_(val, -0.001, 1.001); + } + +}; + +/*! + * \ingroup Newton + * \brief A MpNc specific controller for the newton solver. + * + * This controller 'knows' what a 'physically meaningful' solution is + * which allows the newton method to abort quicker if the solution is + * way out of bounds. + */ +template <class TypeTag> +class MPNCNewtonController : public NewtonController<TypeTag> +{ + typedef NewtonController<TypeTag> ParentType; + typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + + enum {numPhases = GET_PROP_VALUE(TypeTag, NumPhases)}; + enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents)}; + enum {enableKinetic = GET_PROP_VALUE(TypeTag, EnableKinetic)}; + enum {p0Idx = Indices::p0Idx}; + enum {s0Idx = Indices::s0Idx}; + + typedef MpNcNewtonChop<TypeTag, enableKinetic> NewtonChop; + +public: + MPNCNewtonController(const Problem &problem) + : ParentType(problem) + { + enableChop_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Newton, EnableChop); + Dune::FMatrixPrecision<>::set_singular_limit(1e-35); + }; + + void newtonUpdate(SolutionVector &uCurrentIter, + const SolutionVector &uLastIter, + const SolutionVector &deltaU) + { + if (this->enableShiftCriterion_ || this->enablePartialReassemble_) + this->newtonUpdateShift(uLastIter, deltaU); + + // compute the vertex and element colors for partial + // reassembly + if (this->enablePartialReassemble_) { + const Scalar minReasmTol = 1e-2*this->shiftTolerance_; + const Scalar maxReasmTol = 1e1*this->shiftTolerance_; + Scalar reassembleTol = std::max(minReasmTol, std::min(maxReasmTol, this->shift_/1e4)); + + this->model_().jacobianAssembler().updateDiscrepancy(uLastIter, deltaU); + this->model_().jacobianAssembler().computeColors(reassembleTol); + } + + this->writeConvergence_(uLastIter, deltaU); + + if (GET_PARAM_FROM_GROUP(TypeTag, bool, Newton, UseLineSearch)) { + lineSearchUpdate_(uCurrentIter, uLastIter, deltaU); + } + else { + for (unsigned int i = 0; i < uLastIter.size(); ++i) { + uCurrentIter[i] = uLastIter[i]; + uCurrentIter[i] -= deltaU[i]; + } + + if (this->numSteps_ < 2 && enableChop_) { + // put crash barriers along the update path at the + // beginning... + NewtonChop::chop(uCurrentIter, uLastIter); + } + + if (this->enableResidualCriterion_) + { + SolutionVector tmp(uLastIter); + this->reduction_ = this->method().model().globalResidual(tmp, uCurrentIter); + this->reduction_ /= this->initialResidual_; + } + } + } + +private: + void lineSearchUpdate_(SolutionVector &uCurrentIter, + const SolutionVector &uLastIter, + const SolutionVector &deltaU) + { + Scalar lambda = 1.0; + Scalar globDef; + + SolutionVector tmp(uLastIter); + Scalar oldGlobDef = this->model_().globalResidual(tmp, uLastIter); + while (true) { + uCurrentIter = deltaU; + uCurrentIter *= -lambda; + uCurrentIter += uLastIter; + + globDef = this->model_().globalResidual(tmp, uCurrentIter); + if (globDef < oldGlobDef || lambda <= 1.0/64) { + this->endIterMsg() << ", defect " << oldGlobDef << "->" << globDef << "@lambda=1/" << 1/lambda; + return; + } + + // try with a smaller update + lambda /= 2; + } + } + + bool enableChop_; +}; +} + +#endif diff --git a/dumux/porousmediumflow/mpnc/implicit/properties.hh b/dumux/porousmediumflow/mpnc/implicit/properties.hh new file mode 100644 index 0000000000000000000000000000000000000000..3943d328ca8033f49716c9429691425a39549b44 --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/properties.hh @@ -0,0 +1,144 @@ +// -*- 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/>. * + *****************************************************************************/ +#ifndef DUMUX_MPNC_PROPERTIES_HH +#define DUMUX_MPNC_PROPERTIES_HH + +#include <dumux/implicit/box/properties.hh> +#include <dumux/implicit/cellcentered/properties.hh> + +/*! + * \ingroup Properties + * \ingroup ImplicitProperties + * \ingroup BoxMpNcModel + * \file + * \brief Defines the properties required for the MpNc fully implicit model. + */ +namespace Dumux +{ +namespace Properties +{ + +////////////////////////////////////////////////////////////////// +// Type tags +////////////////////////////////////////////////////////////////// + +//! The type tags for the implicit m-phase n-component problems +NEW_TYPE_TAG(MPNC); +NEW_TYPE_TAG(BoxMPNC, INHERITS_FROM(BoxModel, MPNC)); +NEW_TYPE_TAG(CCMPNC, INHERITS_FROM(CCModel, MPNC)); + +////////////////////////////////////////////////////////////////// +// Property tags +////////////////////////////////////////////////////////////////// +NEW_PROP_TAG(NumPhases); //!< Number of fluid phases in the system +NEW_PROP_TAG(NumComponents); //!< Number of fluid components in the system +NEW_PROP_TAG(Indices); //!< Enumerations for the model + +NEW_PROP_TAG(BaseFluxVariables); //!< The type of velocity calculation that is to be used + +NEW_PROP_TAG(PressureFormulation); //!< The formulation of the model + +NEW_PROP_TAG(MPNCVtkCommonModule); //!< Vtk writer module for writing the common quantities into the VTK output file +NEW_PROP_TAG(MPNCVtkMassModule); //!< Vtk writer module for writing the mass related quantities into the VTK output file +NEW_PROP_TAG(MPNCVtkEnergyModule); //!< Vtk writer module for writing the energy related quantities into the VTK output file +NEW_PROP_TAG(MPNCVtkCustomModule); //!< Vtk writer module for writing the user-specified quantities into the VTK output file + +NEW_PROP_TAG(VelocityAveragingInModel);//!< Should the averaging of velocities be done in the model? + +//! specify which quantities are written to the vtk output files +NEW_PROP_TAG(VtkAddPorosity); +NEW_PROP_TAG(VtkAddPermeability); +NEW_PROP_TAG(VtkAddBoundaryTypes); +NEW_PROP_TAG(VtkAddSaturations); +NEW_PROP_TAG(VtkAddPressures); +NEW_PROP_TAG(VtkAddVarPressures); +NEW_PROP_TAG(VtkAddVelocities); +NEW_PROP_TAG(VtkAddVelocity); +NEW_PROP_TAG(VtkAddDensities); +NEW_PROP_TAG(VtkAddMobilities); +NEW_PROP_TAG(VtkAddAverageMolarMass); +NEW_PROP_TAG(VtkAddMassFractions); +NEW_PROP_TAG(VtkAddMoleFractions); +NEW_PROP_TAG(VtkAddMolarities); +NEW_PROP_TAG(VtkAddFugacities); +NEW_PROP_TAG(VtkAddFugacityCoefficients); +NEW_PROP_TAG(VtkAddTemperatures); +NEW_PROP_TAG(VtkAddEnthalpies); +NEW_PROP_TAG(VtkAddInternalEnergies); + +NEW_PROP_TAG(VtkAddxEquil); + +NEW_PROP_TAG(VtkAddReynolds); +NEW_PROP_TAG(VtkAddPrandtl); +NEW_PROP_TAG(VtkAddNusselt); +NEW_PROP_TAG(VtkAddInterfacialArea); + +NEW_PROP_TAG(SpatialParams); //!< The type of the spatial parameters + +NEW_PROP_TAG(MaterialLaw); //!< The material law which ought to be used (extracted from the spatialParams) +NEW_PROP_TAG(MaterialLawParams); //!< The context material law (extracted from the spatialParams) + +//! The compositional twophase system of fluids which is considered +NEW_PROP_TAG(FluidSystem); + +//! The thermodynamic constraint solver which calculates the +//! composition of any phase given all component fugacities. +NEW_PROP_TAG(ConstraintSolver); + +//! Enable the energy equation? +NEW_PROP_TAG(EnableEnergy); + +//! Enable diffusive fluxes? +NEW_PROP_TAG(EnableDiffusion); + +//! Enable kinetic resolution of mass transfer processes? +NEW_PROP_TAG(EnableKinetic); + +//! Property for the definition of the number of energy equations (0,1,2,3) +NEW_PROP_TAG(NumEnergyEquations); + +//! Enable Maxwell Diffusion? (If false: use Fickian Diffusion) Maxwell incorporated the mutual +//! influences of multiple diffusing components. However, Fick seems to be more robust. +NEW_PROP_TAG(UseMaxwellDiffusion); + +//! The model for the effective thermal conductivity +NEW_PROP_TAG(ThermalConductivityModel); + +//! Enable gravity? +NEW_PROP_TAG(ProblemEnableGravity); + +//! Use the smooth upwinding method? +NEW_PROP_TAG(ImplicitEnableSmoothUpwinding); + +NEW_PROP_TAG(ImplicitMassUpwindWeight); //!< The value of the weight of the upwind direction in the mass conservation equations + +NEW_PROP_TAG(ImplicitMobilityUpwindWeight); //!< Weight for the upwind mobility in the velocity calculation + +//! Chop the Newton update at the beginning of the non-linear solver? +NEW_PROP_TAG(NewtonEnableChop); + +//! Which type of fluidstate should be used? +NEW_PROP_TAG(FluidState); + +//! Property for the forchheimer coefficient +NEW_PROP_TAG(SpatialParamsForchCoeff); +} +} + +#endif diff --git a/dumux/porousmediumflow/mpnc/implicit/propertieskinetic.hh b/dumux/porousmediumflow/mpnc/implicit/propertieskinetic.hh new file mode 100644 index 0000000000000000000000000000000000000000..5e03f986dce393fc55edbc035552d61313a3f822 --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/propertieskinetic.hh @@ -0,0 +1,73 @@ +// -*- 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 declares and defines the properties required by + * the kinetic modules the M-phase N-component model. + */ +#ifndef DUMUX_MPNC_PROPERTIES_KINETIC_HH +#define DUMUX_MPNC_PROPERTIES_KINETIC_HH + +#include "properties.hh" + +namespace Dumux +{ +namespace Properties +{ +////////////////////////////////////////////////////////////////// +// Type tags +////////////////////////////////////////////////////////////////// +NEW_TYPE_TAG(BoxMPNCKinetic, INHERITS_FROM(BoxMPNC)); +//NEW_TYPE_TAG(CCMPNCKinetic, INHERITS_FROM(CCMPNC)); + +////////////////////////////////////////////////////////////////// +// Property tags +////////////////////////////////////////////////////////////////// +NEW_PROP_TAG(AwnSurface); //!< The material law which ought to be used (extracted from the spatialParams) +NEW_PROP_TAG(AwnSurfaceParams); //!< The context material law (extracted from the spatialParams) +NEW_PROP_TAG(AwsSurface); //!< The material law which ought to be used (extracted from the spatialParams) +NEW_PROP_TAG(AwsSurfaceParams); //!< The context material law (extracted from the spatialParams) +NEW_PROP_TAG(AnsSurface); //!< The material law which ought to be used (extracted from the spatialParams) +NEW_PROP_TAG(AnsSurfaceParams); //!< The context material law (extracted from the spatialParams) + +NEW_PROP_TAG(VtkAddDeltaP); // !< Output of pressure minus a fixed value +SET_BOOL_PROP(MPNC, VtkAddDeltaP, false); + +//! The Model for kinetic Mass and Energy Transfer +NEW_PROP_TAG(MPNCModelKinetic); + +//! Enable kinetic resolution of mass transfer processes? +NEW_PROP_TAG(EnableKinetic); + +//! Property for the definition of the number of energy equations (0,1,2,3) +NEW_PROP_TAG(NumEnergyEquations); + +//! average the velocity in the model +NEW_PROP_TAG(VelocityAveragingInModel); + +//! which nusselt correlation to use +NEW_PROP_TAG(NusseltFormulation); + +//! which sherwood correlation to use +NEW_PROP_TAG(SherwoodFormulation); + +} +} + +#endif diff --git a/dumux/porousmediumflow/mpnc/implicit/propertydefaults.hh b/dumux/porousmediumflow/mpnc/implicit/propertydefaults.hh new file mode 100644 index 0000000000000000000000000000000000000000..d27cf7cd7bb20afb0f2ec5f8b1ac572f24bdc908 --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/propertydefaults.hh @@ -0,0 +1,278 @@ +// -*- 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/>. * + *****************************************************************************/ +#ifndef DUMUX_MPNC_PROPERTY_DEFAULTS_HH +#define DUMUX_MPNC_PROPERTY_DEFAULTS_HH + +#include "indices.hh" +#include "model.hh" +#include "localresidual.hh" +#include "fluxvariables.hh" +#include "volumevariables.hh" +#include "properties.hh" +#include "newtoncontroller.hh" +#include "vtkwritermodule.hh" +#include "vtkwritercommon.hh" +#include "mass/vtkwriter.hh" +#include "energy/vtkwriter.hh" + +#include <dumux/material/constraintsolvers/compositionfromfugacities.hh> +#include <dumux/material/spatialparams/implicitspatialparams.hh> + +#include <dumux/material/fluidmatrixinteractions/2p/thermalconductivitysomerton.hh> + + +/*! + * \ingroup Properties + * \ingroup ImplicitProperties + * \ingroup BoxMpNcModel + * \file + * \brief Default properties for the MpNc fully implicit model. + */ +namespace Dumux +{ +namespace Properties +{ +////////////////////////////////////////////////////////////////// +// default property values +////////////////////////////////////////////////////////////////// + +/*! + * \brief Set the property for the number of components. + * + * We just forward the number from the fluid system. + */ +SET_PROP(MPNC, NumComponents) +{ +private: + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + +public: + static const unsigned int value = FluidSystem::numComponents; +}; + +/*! + * \brief Set the property for the number of fluid phases. + */ +SET_PROP(MPNC, NumPhases) +{ +private: + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + +public: + static const unsigned int value = FluidSystem::numPhases; +}; + +/*! + * \brief Set the property for the number of equations and primary variables. + */ +SET_PROP(MPNC, NumEq) +{ +private: + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + +public: + static const unsigned int value = Indices::numPrimaryVars; +}; + +/*! + * \brief Set the property for the material parameters by extracting + * it from the material law. + */ +SET_PROP(MPNC, MaterialLawParams) +{ +private: + typedef typename GET_PROP_TYPE(TypeTag, MaterialLaw) MaterialLaw; + +public: + typedef typename MaterialLaw::Params type; +}; + +/*! + * \brief Set the thermodynamic constraint solver which calculates the + * composition of any phase given all component fugacities. + */ +SET_PROP(MPNC, ConstraintSolver) +{ +private: + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + +public: + typedef Dumux::CompositionFromFugacities<Scalar, FluidSystem> type; +}; + + +//! Use the MpNc local jacobian operator for the MpNc model +SET_TYPE_PROP(MPNC, + LocalResidual, + MPNCLocalResidual<TypeTag>); + +//! Use the MpNc specific newton controller for the MpNc model +SET_PROP(MPNC, NewtonController) +{public: + typedef MPNCNewtonController<TypeTag> type; +}; + +//! the Model property +SET_TYPE_PROP(MPNC, Model, MPNCModel<TypeTag>); + +//! use an isothermal model by default +SET_BOOL_PROP(MPNC, EnableEnergy, false); + +//! disable diffusion by default +SET_BOOL_PROP(MPNC, EnableDiffusion, false); + +//! disable kinetic mass transfer by default +SET_BOOL_PROP(MPNC, EnableKinetic, false); + +//! disable kinetic energy transfer by default +SET_INT_PROP(MPNC, NumEnergyEquations, 0); + +//! disable Maxwell Diffusion by default: use Fick +SET_BOOL_PROP(MPNC, UseMaxwellDiffusion, false); + +//! enable smooth upwinding by default +SET_BOOL_PROP(MPNC, ImplicitEnableSmoothUpwinding, false); + +//! the VolumeVariables property +SET_TYPE_PROP(MPNC, VolumeVariables, MPNCVolumeVariables<TypeTag>); + +//! the FluxVariables property +SET_TYPE_PROP(MPNC, FluxVariables, MPNCFluxVariables<TypeTag>); + +//! the Base of the Fluxvariables property (Darcy / Forchheimer) +SET_TYPE_PROP(MPNC, BaseFluxVariables, ImplicitDarcyFluxVariables<TypeTag>); + +//! truncate the newton update for the first few Newton iterations of a time step +SET_BOOL_PROP(MPNC, NewtonEnableChop, true); + +//! The indices required by the mpnc model +SET_TYPE_PROP(MPNC, Indices, MPNCIndices<TypeTag, 0>); + +//! the upwind weight for the mass conservation equations. +SET_SCALAR_PROP(MPNC, ImplicitMassUpwindWeight, 1.0); + +//! weight for the upwind mobility in the velocity calculation +SET_SCALAR_PROP(MPNC, ImplicitMobilityUpwindWeight, 1.0); + +//! The spatial parameters to be employed. +//! Use ImplicitSpatialParams by default. +SET_TYPE_PROP(MPNC, SpatialParams, ImplicitSpatialParams<TypeTag>); + +//! The VTK writer module for common quantities +SET_PROP(MPNC, MPNCVtkCommonModule) +{ + typedef MPNCVtkWriterCommon<TypeTag> type; +}; + +//! The VTK writer module for quantities which are specific for each +//! mass module +SET_PROP(MPNC, MPNCVtkMassModule) +{ +private: enum { enableKinetic = GET_PROP_VALUE(TypeTag, EnableKinetic) }; +public: typedef MPNCVtkWriterMass<TypeTag, enableKinetic> type; +}; + +//! The VTK writer module for quantities which are specific for each +//! energy module +SET_PROP(MPNC, MPNCVtkEnergyModule) +{ +private: + enum { enableEnergy = GET_PROP_VALUE(TypeTag, EnableEnergy) }; + enum { numEnergyEquations = GET_PROP_VALUE(TypeTag, NumEnergyEquations) }; +public: + typedef MPNCVtkWriterEnergy<TypeTag, enableEnergy, numEnergyEquations> type; +}; + +//! Somerton is used as default model to compute the effective thermal heat conductivity +SET_PROP(MPNC, ThermalConductivityModel) +{ private : + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + public: + typedef ThermalConductivitySomerton<Scalar> type; +}; + +//! The VTK writer for user specified data (does nothing by default) +SET_PROP(MPNC, MPNCVtkCustomModule) +{ typedef MPNCVtkWriterModule<TypeTag> type; }; + +/*! + * \brief The fluid state which is used by the volume variables to + * store the thermodynamic state. This should be chosen + * appropriately for the model ((non-)isothermal, equilibrium, ...). + * This can be done in the problem. + */ +SET_PROP(MPNC, FluidState){ + private: + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + public: + typedef Dumux::CompositionalFluidState<Scalar, FluidSystem> type; +}; + +//! Set the default pressure formulation to the pressure of the (most) wetting phase +SET_INT_PROP(MPNC, + PressureFormulation, + MpNcPressureFormulation::mostWettingFirst); + +//! default value for the forchheimer coefficient +// Source: Ward, J.C. 1964 Turbulent flow in porous media. ASCE J. Hydraul. Div 90. +// Actually the Forchheimer coefficient is also a function of the dimensions of the +// porous medium. Taking it as a constant is only a first approximation +// (Nield, Bejan, Convection in porous media, 2006, p. 10) +SET_SCALAR_PROP(MPNC, SpatialParamsForchCoeff, 0.55); + + +//!< Should the averaging of velocities be done in the Model? (By default in the output) +SET_BOOL_PROP(MPNC, VelocityAveragingInModel, false); + +//! Specify what to add to the VTK output by default +SET_BOOL_PROP(MPNC, VtkAddPorosity, true); +SET_BOOL_PROP(MPNC, VtkAddPermeability, false); +SET_BOOL_PROP(MPNC, VtkAddBoundaryTypes, false); +SET_BOOL_PROP(MPNC, VtkAddSaturations, true); +SET_BOOL_PROP(MPNC, VtkAddPressures, true); +SET_BOOL_PROP(MPNC, VtkAddVarPressures, false); +SET_BOOL_PROP(MPNC, VtkAddVelocities, false); +SET_BOOL_PROP(MPNC, VtkAddVelocity, GET_PROP_VALUE(TypeTag, VtkAddVelocities)); +SET_BOOL_PROP(MPNC, VtkAddDensities, true); +SET_BOOL_PROP(MPNC, VtkAddMobilities, true); +SET_BOOL_PROP(MPNC, VtkAddAverageMolarMass, false); +SET_BOOL_PROP(MPNC, VtkAddMassFractions, false); +SET_BOOL_PROP(MPNC, VtkAddMoleFractions, true); +SET_BOOL_PROP(MPNC, VtkAddMolarities, false); +SET_BOOL_PROP(MPNC, VtkAddFugacities, false); +SET_BOOL_PROP(MPNC, VtkAddFugacityCoefficients, false); +SET_BOOL_PROP(MPNC, VtkAddTemperatures, false); +SET_BOOL_PROP(MPNC, VtkAddEnthalpies, true); +SET_BOOL_PROP(MPNC, VtkAddInternalEnergies, false); +SET_BOOL_PROP(MPNC, VtkAddReynolds, false); +SET_BOOL_PROP(MPNC, VtkAddPrandtl, false); +SET_BOOL_PROP(MPNC, VtkAddNusselt, false); +SET_BOOL_PROP(MPNC, VtkAddInterfacialArea, false); +SET_BOOL_PROP(MPNC, VtkAddxEquil, false); + +// enable gravity by default +SET_BOOL_PROP(MPNC, ProblemEnableGravity, true); + +} + +} + +#endif diff --git a/dumux/porousmediumflow/mpnc/implicit/propertydefaultskinetic.hh b/dumux/porousmediumflow/mpnc/implicit/propertydefaultskinetic.hh new file mode 100644 index 0000000000000000000000000000000000000000..684eb56989014bdd636f93bd88aafad531939417 --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/propertydefaultskinetic.hh @@ -0,0 +1,123 @@ +// -*- 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 declares and defines the properties required by + * the kinetic modules the M-phase N-component model. + */ +#ifndef DUMUX_MPNC_PROPERTY_DEFAULTS_KINETIC_HH +#define DUMUX_MPNC_PROPERTY_DEFAULTS_KINETIC_HH + +#include <dumux/porousmediumflow/mpnc/implicit/properties.hh> + +#include <dumux/porousmediumflow/mpnc/implicit/modelkinetic.hh> + +// interfacial area volume variables +#include "volumevariablesiakinetic.hh" + +// kinetic mass module +#include "mass/indiceskinetic.hh" +#include "mass/localresidualkinetic.hh" +#include "mass/volumevariableskinetic.hh" +#include "mass/vtkwriterkinetic.hh" + +// kinetic energy module +#include "energy/indiceskinetic.hh" +#include "energy/localresidualkinetic.hh" +#include "energy/fluxvariableskinetic.hh" +#include "energy/volumevariableskinetic.hh" +#include "energy/vtkwriterkinetic.hh" + +namespace Dumux +{ +namespace Properties +{ + +/*! + * \brief Set the property for the model. + */ +SET_TYPE_PROP(BoxMPNCKinetic, Model, MPNCModelKinetic<TypeTag>); + +/*! + * \brief Set the property for the awn surface parameters by extracting + * it from awn surface. + */ +SET_PROP(BoxMPNCKinetic, AwnSurfaceParams) +{ +private: + typedef typename GET_PROP_TYPE(TypeTag, AwnSurface) AwnSurface; + +public: + typedef typename AwnSurface::Params type; +}; + +/*! + * \brief Set the property for the aws surface parameters by extracting + * it from aws surface. + */ +SET_PROP(BoxMPNCKinetic, AwsSurfaceParams) +{ +private: + typedef typename GET_PROP_TYPE(TypeTag, AwsSurface) AwsSurface; + +public: + typedef typename AwsSurface::Params type; +}; + +/*! + * \brief Set the property for the ans surface parameters by extracting + * it from the surface. + */ +SET_PROP(BoxMPNCKinetic, AnsSurfaceParams) +{ +private: + typedef typename GET_PROP_TYPE(TypeTag, AnsSurface) AnsSurface; + +public: + typedef typename AnsSurface::Params type; +}; + +SET_BOOL_PROP(BoxMPNCKinetic, VelocityAveragingInModel, true); + +/*! + * \brief Set the default formulation for the nusselt correlation + * Other possible parametrizations can be found in the dimensionlessnumbers + */ +SET_PROP(BoxMPNCKinetic, NusseltFormulation ){ + private: + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef DimensionlessNumbers<Scalar> DimLessNum; + public: + static constexpr int value = DimLessNum::NusseltFormulation::WakaoKaguei;}; + +/*! + * \brief Set the default formulation for the sherwood correlation + * Other possible parametrizations can be found in the dimensionlessnumbers + */ +SET_PROP(BoxMPNCKinetic, SherwoodFormulation ){ + private: + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef DimensionlessNumbers<Scalar> DimLessNum; + public: + static constexpr int value = DimLessNum::SherwoodFormulation::WakaoKaguei;}; + +} // end namespace Properties +} // end namespace Dumux + +#endif diff --git a/dumux/porousmediumflow/mpnc/implicit/velomodelnewtoncontroller.hh b/dumux/porousmediumflow/mpnc/implicit/velomodelnewtoncontroller.hh new file mode 100644 index 0000000000000000000000000000000000000000..5eca1f2132079571f917987a77c7307233805b9b --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/velomodelnewtoncontroller.hh @@ -0,0 +1,76 @@ +// -*- 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 A MpNc specific controller for the newton solver. + * + * This controller calls the velocity averaging in the model after each iteration. + */ +#ifndef DUMUX_VELO_MODEL_NEWTON_CONTROLLER_HH +#define DUMUX_VELO_MODEL_NEWTON_CONTROLLER_HH + +#include <algorithm> + +#include <dumux/nonlinear/newtoncontroller.hh> +#include "newtoncontroller.hh" +#include "properties.hh" + +namespace Dumux { +/*! + * \brief A kinetic-MpNc specific controller for the newton solver. + * + * This controller calls the velocity averaging in the problem after each iteration. + * + * Everything else is taken from the standard mpnc newtoncontroller. + */ +template <class TypeTag> +class VeloModelNewtonController : public MPNCNewtonController<TypeTag> +{ + typedef MPNCNewtonController<TypeTag> ParentType; + typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector; + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + + enum {velocityAveragingInModel = GET_PROP_VALUE(TypeTag, VelocityAveragingInModel)}; + +public: + VeloModelNewtonController(const Problem &problem) + : ParentType(problem) + {}; + + void newtonBeginStep(){ + ParentType::newtonBeginStep(); + + // Averages the face velocities of a vertex. Implemented in the model. + // The velocities are stored in the model. + if(velocityAveragingInModel) + this->problem_().model().calcVelocityAverage(); + } + + void newtonUpdate(SolutionVector &uCurrentIter, + const SolutionVector &uLastIter, + const SolutionVector &deltaU) + { + ParentType::newtonUpdate(uCurrentIter, + uLastIter, + deltaU); + } +}; + +} // end namespace Dumux +#endif // DUMUX_VELO_PROB_AVERAGE_NEWTON_CONTROLLER_HH diff --git a/dumux/porousmediumflow/mpnc/implicit/volumevariables.hh b/dumux/porousmediumflow/mpnc/implicit/volumevariables.hh new file mode 100644 index 0000000000000000000000000000000000000000..5e031fc81f41cf4595c80f956f9d10b6b5fc7160 --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/volumevariables.hh @@ -0,0 +1,386 @@ +// -*- 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 Contains the secondary variables (Quantities which are + * constant within a finite volume) of the MpNc model. + */ +#ifndef DUMUX_MPNC_VOLUME_VARIABLES_HH +#define DUMUX_MPNC_VOLUME_VARIABLES_HH + +#include "diffusion/volumevariables.hh" +#include "energy/mpncvolumevariablesenergy.hh" +#include "mass/mpncvolumevariablesmass.hh" +#include "indices.hh" +#include "volumevariablesia.hh" + +#include <dumux/implicit/volumevariables.hh> +#include <dumux/material/constraintsolvers/ncpflash.hh> + +namespace Dumux +{ +/*! + * \ingroup MPNCModel + * \ingroup ImplicitVolumeVariables + * \brief Contains the quantities which are are constant within a + * finite volume in the MpNc model. + */ +template <class TypeTag> +class MPNCVolumeVariables + : public ImplicitVolumeVariables<TypeTag> + , public MPNCVolumeVariablesIA<TypeTag, GET_PROP_VALUE(TypeTag, EnableKinetic), GET_PROP_VALUE(TypeTag, NumEnergyEquations)> + , public MPNCVolumeVariablesMass<TypeTag, GET_PROP_VALUE(TypeTag, EnableKinetic)> + , public MPNCVolumeVariablesDiffusion<TypeTag, GET_PROP_VALUE(TypeTag, EnableDiffusion) || GET_PROP_VALUE(TypeTag, EnableKinetic)> + , public MPNCVolumeVariablesEnergy<TypeTag, GET_PROP_VALUE(TypeTag, EnableEnergy), GET_PROP_VALUE(TypeTag, NumEnergyEquations)> +{ + typedef ImplicitVolumeVariables<TypeTag> ParentType; + typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) Implementation; + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; + typedef typename FluidSystem::ParameterCache ParameterCache; + typedef typename GET_PROP_TYPE(TypeTag, MaterialLaw) MaterialLaw; + typedef typename GET_PROP_TYPE(TypeTag, MaterialLawParams) MaterialLawParams; + typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + + + // formulations + enum { + pressureFormulation = GET_PROP_VALUE(TypeTag, PressureFormulation), + mostWettingFirst = MpNcPressureFormulation::mostWettingFirst, + leastWettingFirst = MpNcPressureFormulation::leastWettingFirst + }; + + enum {numPhases = GET_PROP_VALUE(TypeTag, NumPhases)}; + enum {numComponents = GET_PROP_VALUE(TypeTag, NumComponents)}; + enum {enableEnergy = GET_PROP_VALUE(TypeTag, EnableEnergy)}; + enum {enableKinetic = GET_PROP_VALUE(TypeTag, EnableKinetic)}; + enum {numEnergyEquations = GET_PROP_VALUE(TypeTag, NumEnergyEquations)}; + enum {enableDiffusion = GET_PROP_VALUE(TypeTag, EnableDiffusion) || enableKinetic}; + enum {s0Idx = Indices::s0Idx}; + enum {p0Idx = Indices::p0Idx}; + + typedef typename GridView::template Codim<0>::Entity Element; + typedef MPNCVolumeVariablesMass<TypeTag, enableKinetic> MassVolumeVariables; + typedef MPNCVolumeVariablesEnergy<TypeTag, enableEnergy, numEnergyEquations> EnergyVolumeVariables; + typedef MPNCVolumeVariablesIA<TypeTag, enableKinetic, numEnergyEquations> IAVolumeVariables; + typedef MPNCVolumeVariablesDiffusion<TypeTag, enableDiffusion> DiffusionVolumeVariables; + +public: + MPNCVolumeVariables() + { hint_ = NULL; }; + + /*! + * \brief Set the volume variables which should be used as initial + * conditions for complex calculations. + */ + void setHint(const Implementation *hint) + { + hint_ = hint; + } + + /*! + * \copydoc ImplicitVolumeVariables::update + * + * \param priVars The primary Variables + * \param problem The Problem + * \param element The finite element + * \param fvGeometry The finite-volume geometry in the fully implicit scheme + * \param scvIdx The index of the sub-control volume + * \param isOldSol Specifies whether this is the previous solution or the current one + */ + void update(const PrimaryVariables &priVars, + const Problem &problem, + const Element &element, + const FVElementGeometry &fvGeometry, + const unsigned int scvIdx, + const bool isOldSol) + { + Valgrind::CheckDefined(priVars); + ParentType::update(priVars, + problem, + element, + fvGeometry, + scvIdx, + isOldSol); + ParentType::checkDefined(); + + ParameterCache paramCache; + + ///////////// + // set the phase saturations + ///////////// + Scalar sumSat = 0; + for (int phaseIdx = 0; phaseIdx < numPhases - 1; ++phaseIdx) { + sumSat += priVars[s0Idx + phaseIdx]; + fluidState_.setSaturation(phaseIdx, priVars[s0Idx + phaseIdx]); + } + Valgrind::CheckDefined(sumSat); + fluidState_.setSaturation(numPhases - 1, 1.0 - sumSat); + + ///////////// + // set the fluid phase temperatures + ///////////// + EnergyVolumeVariables::updateTemperatures(fluidState_, + paramCache, + priVars, + element, + fvGeometry, + scvIdx, + problem); + + ///////////// + // set the phase pressures + ///////////// + // capillary pressure parameters + const MaterialLawParams &materialParams = + problem.spatialParams().materialLawParams(element, fvGeometry, scvIdx); + // capillary pressures + Scalar capPress[numPhases]; + MaterialLaw::capillaryPressures(capPress, materialParams, fluidState_); + // add to the pressure of the first fluid phase + + // depending on which pressure is stored in the primary variables + if(pressureFormulation == mostWettingFirst){ + // This means that the pressures are sorted from the most wetting to the least wetting-1 in the primary variables vector. + // For two phases this means that there is one pressure as primary variable: pw + const Scalar pw = priVars[p0Idx]; + for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) + fluidState_.setPressure(phaseIdx, pw - capPress[0] + capPress[phaseIdx]); + } + else if(pressureFormulation == leastWettingFirst){ + // This means that the pressures are sorted from the least wetting to the most wetting-1 in the primary variables vector. + // For two phases this means that there is one pressure as primary variable: pn + const Scalar pn = priVars[p0Idx]; + for (int phaseIdx = numPhases-1; phaseIdx >= 0; --phaseIdx) + fluidState_.setPressure(phaseIdx, pn - capPress[numPhases-1] + capPress[phaseIdx]); + } + else DUNE_THROW(Dune::InvalidStateException, "Formulation: " << pressureFormulation << " is invalid."); + + ///////////// + // set the fluid compositions + ///////////// + MassVolumeVariables::update(fluidState_, + paramCache, + priVars, + hint_, + problem, + element, + fvGeometry, + scvIdx); + MassVolumeVariables::checkDefined(); + + ///////////// + // Porosity + ///////////// + + // porosity + porosity_ = problem.spatialParams().porosity(element, + fvGeometry, + scvIdx); + Valgrind::CheckDefined(porosity_); + + ///////////// + // Phase mobilities + ///////////// + + // relative permeabilities + MaterialLaw::relativePermeabilities(relativePermeability_, + materialParams, + fluidState_); + + // dynamic viscosities + for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { + // viscosities + Scalar mu = FluidSystem::viscosity(fluidState_, paramCache, phaseIdx); + + fluidState_.setViscosity(phaseIdx, mu); + } + + ///////////// + // diffusion + ///////////// + + // update the diffusion part of the volume data + DiffusionVolumeVariables::update(fluidState_, paramCache, *this, problem); + DiffusionVolumeVariables::checkDefined(); + + ///////////// + // energy + ///////////// + + // update the remaining parts of the energy module + EnergyVolumeVariables::update(fluidState_, + paramCache, + element, + fvGeometry, + scvIdx, + problem); + EnergyVolumeVariables::checkDefined(); + + // make sure the quantities in the fluid state are well-defined + fluidState_.checkDefined(); + + // specific interfacial area, + // well also all the dimensionless numbers :-) + // well, also the mass transfer rate + IAVolumeVariables::update(*this, + fluidState_, + paramCache, + priVars, + problem, + element, + fvGeometry, + scvIdx); + IAVolumeVariables::checkDefined(); + checkDefined(); + + } + + /*! + * \brief Return the fluid configuration at the given primary + * variables + */ + const FluidState &fluidState() const + { return fluidState_; } + + /*! + * \brief Returns the effective mobility of a given phase within + * the control volume. + * + * \param phaseIdx The local index of the phases + */ + Scalar mobility(const unsigned int phaseIdx) const + { + return relativePermeability(phaseIdx)/fluidState_.viscosity(phaseIdx); + } + + /*! + * \brief Returns the viscosity of a given phase within + * the control volume. + */ + Scalar viscosity(const unsigned int phaseIdx) const + { return fluidState_.viscosity(phaseIdx); } + + /*! + * \brief Returns the relative permeability of a given phase within + * the control volume. + * + * \param phaseIdx The local index of the phases + */ + Scalar relativePermeability(const unsigned int phaseIdx) const + { return relativePermeability_[phaseIdx]; } + + /*! + * \brief Returns the average porosity within the control volume. + */ + Scalar porosity() const + { return porosity_; } + + /*! + * \brief Returns true iff the fluid state is in the active set + * for a phase, + * + * \param phaseIdx The local index of the phases + */ + bool isPhaseActive(const unsigned int phaseIdx) const + { + return + phasePresentIneq(fluidState(), phaseIdx) - + phaseNotPresentIneq(fluidState(), phaseIdx) + >= 0; + } + + /*! + * \brief Returns the value of the NCP-function for a phase. + * + * \param phaseIdx The local index of the phases + */ + Scalar phaseNcp(const unsigned int phaseIdx) const + { + Scalar aEval = phaseNotPresentIneq(this->evalPoint().fluidState(), phaseIdx); + Scalar bEval = phasePresentIneq(this->evalPoint().fluidState(), phaseIdx); + if (aEval > bEval) + return phasePresentIneq(fluidState(), phaseIdx); + return phaseNotPresentIneq(fluidState(), phaseIdx); + }; + + /*! + * \brief Returns the value of the inequality where a phase is + * present. + * + * \param phaseIdx The local index of the phases + * \param fluidState Container for all the secondary variables concerning the fluids + */ + Scalar phasePresentIneq(const FluidState &fluidState, + const unsigned int phaseIdx) const + { return fluidState.saturation(phaseIdx); } + + /*! + * \brief Returns the value of the inequality where a phase is not + * present. + * + * \param phaseIdx The local index of the phases + * \param fluidState Container for all the secondary variables concerning the fluids + */ + Scalar phaseNotPresentIneq(const FluidState &fluidState, + const unsigned int phaseIdx) const + { + // difference of sum of mole fractions in the phase from 100% + Scalar a = 1; + for (int compIdx = 0; compIdx < numComponents; ++compIdx) + a -= fluidState.moleFraction(phaseIdx, compIdx); + return a; + } + + /*! + * \brief If running in valgrind this makes sure that all + * quantities in the volume variables are defined. + */ + void checkDefined() const + { +#if !defined NDEBUG && HAVE_VALGRIND + ParentType::checkDefined(); + + Valgrind::CheckDefined(porosity_); + Valgrind::CheckDefined(hint_); + Valgrind::CheckDefined(relativePermeability_); + + fluidState_.checkDefined(); +#endif + } + +protected: + Scalar porosity_; //!< Effective porosity within the control volume + Scalar relativePermeability_[numPhases]; //!< Effective relative permeability within the control volume + + const Implementation *hint_; + + //! Mass fractions of each component within each phase + FluidState fluidState_; +}; + +} // end namespace + +#endif diff --git a/dumux/porousmediumflow/mpnc/implicit/volumevariablesia.hh b/dumux/porousmediumflow/mpnc/implicit/volumevariablesia.hh new file mode 100644 index 0000000000000000000000000000000000000000..bb987bdec55d0f2cb367496a4654b4baed8c6f77 --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/volumevariablesia.hh @@ -0,0 +1,98 @@ +// -*- 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 class contains the volume variables required for the + * modules which require the specific interfacial area between + * fluid phases. + */ +#ifndef DUMUX_MPNC_VOLUME_VARIABLES_IA_HH +#define DUMUX_MPNC_VOLUME_VARIABLES_IA_HH + +#include <dumux/porousmediumflow/mpnc/implicit/properties.hh> + +namespace Dumux +{ + +/*! + * \brief This class contains the volume variables required for the + * modules which require the specific interfacial area between + * fluid phases. + * + * This is the specialization for the cases which do _not_ require + * specific interfacial area. + */ +template <class TypeTag, bool enableKinetic, int numEnergyEquations> +class MPNCVolumeVariablesIA +{ + static_assert(not enableKinetic and not numEnergyEquations, + "The kinetic energy modules need specific interfacial area " + "but no suitable specialization of the IA volume variables module " + "has been included."); + + typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; + typedef typename FluidSystem::ParameterCache ParameterCache; + typedef typename GridView::template Codim<0>::Entity Element; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + enum {dimWorld=GridView::dimensionworld}; + typedef Dune::FieldVector<Scalar,dimWorld> GlobalPosition; + +public: + /*! + * \brief Updates the volume specific interfacial area [m^2 / m^3] between the phases. + * + * \param volVars The volume variables + * \param fluidState Container for all the secondary variables concerning the fluids + * \param paramCache Container for cache parameters + * \param priVars The primary Variables + * \param problem The problem + * \param element The finite element + * \param fvGeometry The finite-volume geometry in the fully implicit scheme + * \param scvIdx The index of the sub-control volumete element + * + */ + void update(const VolumeVariables & volVars, + const FluidState &fluidState, + const ParameterCache ¶mCache, + const PrimaryVariables &priVars, + const Problem &problem, + const Element & element, + const FVElementGeometry & fvGeometry, + const unsigned int scvIdx) + { + } + + /*! + * \brief If running in valgrind this makes sure that all + * quantities in the volume variables are defined. + */ + void checkDefined() const + { } +}; + +} // namespace Dumux + +#endif diff --git a/dumux/porousmediumflow/mpnc/implicit/volumevariablesiakinetic.hh b/dumux/porousmediumflow/mpnc/implicit/volumevariablesiakinetic.hh new file mode 100644 index 0000000000000000000000000000000000000000..4aed774192bb65d54736595b6ccb5dedd28db875 --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/volumevariablesiakinetic.hh @@ -0,0 +1,624 @@ +// -*- 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 class contains the volume variables required for the + * modules which require the specific interfacial area between + * fluid phases. + * + * This files contains all specializations which use 'real' + * interfacial areas. + */ +#ifndef DUMUX_MPNC_VOLUME_VARIABLES_IA_KINETIC_HH +#define DUMUX_MPNC_VOLUME_VARIABLES_IA_KINETIC_HH + +#include <dumux/common/dimensionlessnumbers.hh> +#include "volumevariablesia.hh" +#include "propertieskinetic.hh" + +namespace Dumux +{ + + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// specialization for the case of kinetic mass AND energy transfer +//////////////////////////////////////////////////////////////////////////////////////////////////// +template <class TypeTag, bool enableKinetic > +class MPNCVolumeVariablesIA<TypeTag, enableKinetic, /*numEnergyEqs=*/3> +{ + typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; + typedef typename FluidSystem::ParameterCache ParameterCache; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + typedef typename GridView::template Codim<0>::Entity Element; + typedef typename GET_PROP_TYPE(TypeTag, MaterialLawParams) MaterialLawParams; + + + enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; + enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; + enum { wPhaseIdx = FluidSystem::wPhaseIdx }; + enum { nPhaseIdx = FluidSystem::nPhaseIdx }; + enum { sPhaseIdx = FluidSystem::sPhaseIdx }; + enum { nCompIdx = FluidSystem::nCompIdx } ; + enum { wCompIdx = FluidSystem::wCompIdx } ; + enum { dim = GridView::dimension}; + enum { dimWorld = GridView::dimensionworld}; + enum { numEnergyEqs = Indices::numPrimaryEnergyVars}; + enum { nusseltFormulation = GET_PROP_VALUE(TypeTag, NusseltFormulation)} ; + enum { sherwoodFormulation = GET_PROP_VALUE(TypeTag, SherwoodFormulation)} ; + enum { enableDiffusion = GET_PROP_VALUE(TypeTag, EnableDiffusion)} ; + + + typedef DimensionlessNumbers<Scalar> DimLessNum ; + + typedef Dune::FieldVector<Scalar,dimWorld> GlobalPosition; + + + typedef typename GET_PROP_TYPE(TypeTag, AwnSurface) AwnSurface; + typedef typename AwnSurface::Params AwnSurfaceParams; + + typedef typename GET_PROP_TYPE(TypeTag, AwsSurface) AwsSurface; + typedef typename AwsSurface::Params AwsSurfaceParams; + + typedef typename GET_PROP_TYPE(TypeTag, AnsSurface) AnsSurface; + typedef typename AnsSurface::Params AnsSurfaceParams; + + +public: + /*! + * \brief Updates the volume specific interfacial area [m^2 / m^3] between the phases. + */ + void update(const VolumeVariables & volVars, + const FluidState & fluidState, + const ParameterCache ¶mCache, + const PrimaryVariables &priVars, + const Problem &problem, + const Element & element, + const FVElementGeometry & fvGeometry, + const unsigned int scvIdx) + { + // obtain (standard) material parameters (needed for the residual saturations) + const MaterialLawParams & materialParams = problem.spatialParams().materialLawParams(element,fvGeometry,scvIdx); + + //obtain parameters for interfacial area constitutive relations + const AwnSurfaceParams & aWettingNonWettingSurfaceParams + = problem.spatialParams().aWettingNonWettingSurfaceParams(element,fvGeometry,scvIdx); + const AnsSurfaceParams & aNonWettingSolidSurfaceParams + = problem.spatialParams().aNonWettingSolidSurfaceParams(element,fvGeometry,scvIdx); + + Valgrind::CheckDefined(aWettingNonWettingSurfaceParams); + Valgrind::CheckDefined(aNonWettingSolidSurfaceParams); + + const Scalar pc = fluidState.pressure(nPhaseIdx) - fluidState.pressure(wPhaseIdx); + const Scalar Sw = fluidState.saturation(wPhaseIdx); + Valgrind::CheckDefined(Sw); + Valgrind::CheckDefined(pc); + Scalar awn; + +#define AwnRegul 0 + // This regularizes the interfacial area between the fluid phases. + // This makes sure, that + // a) some saturation cannot be lost: Never leave two phase region. + // b) We cannot leave the fit region: no crazy (e.g. negative) values possible +// const Scalar Swr = aWettingNonWettingSurfaceParams.Swr() ; +// const Scalar Snr = aWettingNonWettingSurfaceParams.Snr() ; + + // this just leads to a stalling newton error as soon as this kicks in. + // May be a spline or sth like this would help, but I do not which derivatives + // to specify. +#if AwnRegul + if(Sw < 5e-3 ) // or Sw > (1.-1e-5 ) + { + awn = 0. ; // 10.; // + } + else +#endif + awn = AwnSurface::interfacialArea(aWettingNonWettingSurfaceParams, materialParams, Sw, pc ); // 10.; // + + interfacialArea_[wPhaseIdx][nPhaseIdx] = awn ; //10. ;// + interfacialArea_[nPhaseIdx][wPhaseIdx] = interfacialArea_[wPhaseIdx][nPhaseIdx]; + interfacialArea_[wPhaseIdx][wPhaseIdx] = 0. ; + + Scalar ans = AnsSurface::interfacialArea(aNonWettingSolidSurfaceParams, materialParams,Sw, pc ); // 10.; // +// if (ans <0 ) +// ans = 0 ; + +// Switch for using a a_{wn} relations that has some "maximum capillary pressure" as parameter. +// That value is obtained by regularization of the pc(Sw) function. +#if USE_PCMAX + const Scalar pcMax = problem.spatialParams().pcMax(element, + fvGeometry, + scvIdx); + // I know the solid surface from the pore network. But it is more consistent to use the fit value. + // solidSurface_ = GET_RUNTIME_PARAM(TypeTag, Scalar, SpatialParams.soil.specificSolidsurface); + solidSurface_ = AnsSurface::interfacialArea(aNonWettingSolidSurfaceParams, materialParams, /*Sw=*/0., pcMax ); + Valgrind::CheckDefined(solidSurface_); + +// if (ans > solidSurface_){ +// const GlobalPosition & globalPos = fvGeometry.subContVol[scvIdx].global ; +// std::stringstream positionString ; +// positionString << " Here:"; +// for(int i=0; i<dim; i++) +// positionString << " x"<< (i+1) << "=" << globalPos[i] << " " ; +// positionString << "\n"; +// +// std::cout<<"a_{ns} > a_s, set a_{ns}=" << ans <<" to a_{ns}=a_s="<<solidSurface_ << " +// with S_w="<< Sw << " p_c= "<< pc << positionString.str() ; +// +// ans = solidSurface_ ; +// } + +#endif + + + interfacialArea_[nPhaseIdx][sPhaseIdx] = ans ; //10. ; // + interfacialArea_[sPhaseIdx][nPhaseIdx] = interfacialArea_[nPhaseIdx][sPhaseIdx]; + interfacialArea_[nPhaseIdx][nPhaseIdx] = 0. ; + +#if USE_PCMAX + const Scalar aws = solidSurface_ - ans ; + interfacialArea_[wPhaseIdx][sPhaseIdx] = aws ; //10. ; // + interfacialArea_[sPhaseIdx][wPhaseIdx] = interfacialArea_[wPhaseIdx][sPhaseIdx]; + interfacialArea_[sPhaseIdx][sPhaseIdx] = 0. ; +#else + const AwsSurfaceParams & aWettingSolidSurfaceParams + = problem.spatialParams().aWettingSolidSurfaceParams(); + Valgrind::CheckDefined(aWettingSolidSurfaceParams); + const Scalar aws = AwsSurface::interfacialArea(aWettingSolidSurfaceParams,materialParams, Sw, pc ); // 10.; // + interfacialArea_[wPhaseIdx][sPhaseIdx] = aws ; + interfacialArea_[sPhaseIdx][wPhaseIdx] = interfacialArea_[wPhaseIdx][sPhaseIdx]; + interfacialArea_[sPhaseIdx][sPhaseIdx] = 0. ; +#endif + + Valgrind::CheckDefined(interfacialArea_); + + factorMassTransfer_ = problem.spatialParams().factorMassTransfer(element, + fvGeometry, + scvIdx); + + factorEnergyTransfer_ = problem.spatialParams().factorEnergyTransfer(element, + fvGeometry, + scvIdx); + + characteristicLength_ = problem.spatialParams().characteristicLength(element, + fvGeometry, + scvIdx); + + // setting the dimensionless numbers. + // obtaining the respective quantities. + const unsigned int globalVertexIdx = problem.vertexMapper().subIndex(element, scvIdx, dim); + + for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { + const Scalar darcyMagVelocity = problem.model().volumeDarcyMagVelocity(phaseIdx, globalVertexIdx); + const Scalar dynamicViscosity = fluidState.viscosity(phaseIdx); + const Scalar density = fluidState.density(phaseIdx); + const Scalar kinematicViscosity = dynamicViscosity / density; + const Scalar heatCapacity = FluidSystem::heatCapacity(fluidState, paramCache, phaseIdx); + const Scalar thermalConductivity = FluidSystem::thermalConductivity(fluidState, paramCache, phaseIdx); + + + // diffusion coefficient of non-wetting component in wetting phase + const Scalar diffCoeff = volVars.diffCoeff(phaseIdx, wCompIdx, nCompIdx) ; + const Scalar porosity = problem.spatialParams().porosity(element, + fvGeometry, + scvIdx); + + reynoldsNumber_[phaseIdx] = DimLessNum::reynoldsNumber(darcyMagVelocity, + characteristicLength_, + kinematicViscosity); + + prandtlNumber_[phaseIdx] = DimLessNum::prandtlNumber(dynamicViscosity, + heatCapacity, + thermalConductivity); + + nusseltNumber_[phaseIdx] = DimLessNum::nusseltNumberForced(reynoldsNumber_[phaseIdx], + prandtlNumber_[phaseIdx], + porosity, + nusseltFormulation); + + schmidtNumber_[phaseIdx] = DimLessNum::schmidtNumber(dynamicViscosity, + density, + diffCoeff); + + // If Diffusion is not enabled, Sherwood is divided by zero + sherwoodNumber_[phaseIdx] = DimLessNum::sherwoodNumber(reynoldsNumber_[phaseIdx], + schmidtNumber_[phaseIdx], + sherwoodFormulation); + } + } + + /*! + * \brief The specific interfacial area between two fluid phases [m^2 / m^3] + * + * This is _only_ required by the kinetic mass/energy modules + * + */ + const Scalar interfacialArea(const unsigned int phaseIIdx, const unsigned int phaseJIdx) const + { + // there is no interfacial area between a phase and itself + assert(phaseIIdx not_eq phaseJIdx); + return interfacialArea_[phaseIIdx][phaseJIdx]; + } + + //! access function Reynolds Number + const Scalar reynoldsNumber(const unsigned int phaseIdx) const + { return reynoldsNumber_[phaseIdx]; } + + //! access function Prandtl Number + const Scalar prandtlNumber(const unsigned int phaseIdx) const + { return prandtlNumber_[phaseIdx]; } + + //! access function Nusselt Number + const Scalar nusseltNumber(const unsigned int phaseIdx) const + { return nusseltNumber_[phaseIdx]; } + + //! access function Schmidt Number + const Scalar schmidtNumber(const unsigned int phaseIdx) const + { return schmidtNumber_[phaseIdx]; } + + //! access function Sherwood Number + const Scalar sherwoodNumber(const unsigned int phaseIdx) const + { return sherwoodNumber_[phaseIdx]; } + + //! access function characteristic length + const Scalar characteristicLength() const + { return characteristicLength_; } + + //! access function pre factor energy transfer + const Scalar factorEnergyTransfer() const + { return factorEnergyTransfer_; } + + //! access function pre factor mass transfer + const Scalar factorMassTransfer() const + { return factorMassTransfer_; } + + /*! + * \brief If running in valgrind this makes sure that all + * quantities in the volume variables are defined. + */ + void checkDefined() const + { +#if !defined NDEBUG && HAVE_VALGRIND + Valgrind::CheckDefined(reynoldsNumber_); + Valgrind::CheckDefined(prandtlNumber_); + Valgrind::CheckDefined(nusseltNumber_); + Valgrind::CheckDefined(schmidtNumber_); + Valgrind::CheckDefined(sherwoodNumber_); + Valgrind::CheckDefined(characteristicLength_); + Valgrind::CheckDefined(factorEnergyTransfer_); + Valgrind::CheckDefined(factorMassTransfer_); + Valgrind::CheckDefined(interfacialArea_); +#endif + } + +private: + //! dimensionless numbers + Scalar reynoldsNumber_[numPhases]; + Scalar prandtlNumber_[numPhases]; + Scalar nusseltNumber_[numPhases]; + Scalar schmidtNumber_[numPhases]; + Scalar sherwoodNumber_[numPhases]; + Scalar characteristicLength_; + Scalar factorEnergyTransfer_; + Scalar factorMassTransfer_; + Scalar solidSurface_ ; + Scalar interfacialArea_[numPhases+1][numPhases+1]; +}; + + +///////////////////////////////////////////////////////////////////////////////////////////////////////////// +// specialization for the case of NO kinetic mass but kinteic energy transfer of a fluid mixture and solid +///////////////////////////////////////////////////////////////////////////////////////////////////////////// +template <class TypeTag> +class MPNCVolumeVariablesIA<TypeTag, /*enableKinetic=*/false, /*numEnergyEqs=*/2> +{ + typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; + typedef typename FluidSystem::ParameterCache ParameterCache; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + typedef typename GridView::template Codim<0>::Entity Element; + + enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; + enum { dim = GridView::dimension}; + enum { dimWorld = GridView::dimensionworld}; + enum { numEnergyEqs = Indices::numPrimaryEnergyVars}; + enum { nusseltFormulation = GET_PROP_VALUE(TypeTag, NusseltFormulation)} ; + + typedef DimensionlessNumbers<Scalar> DimLessNum ; +public: + /*! + * \brief Updates the volume specific interfacial area [m^2 / m^3] between the phases. + */ + void update(const VolumeVariables & volVars, + const FluidState & fluidState, + const ParameterCache ¶mCache, + const PrimaryVariables &priVars, + const Problem &problem, + const Element & element, + const FVElementGeometry & fvGeometry, + const unsigned int scvIdx) + { + factorMassTransfer_ = problem.spatialParams().factorMassTransfer(element, + fvGeometry, + scvIdx); + + factorEnergyTransfer_ = problem.spatialParams().factorEnergyTransfer(element, + fvGeometry, + scvIdx); + + characteristicLength_ = problem.spatialParams().characteristicLength(element, + fvGeometry, + scvIdx); + + // setting the dimensionless numbers. + // obtaining the respective quantities. + const unsigned int globalVertexIdx = problem.vertexMapper().subIndex(element, scvIdx, dim); + + for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { + const Scalar darcyMagVelocity = problem.model().volumeDarcyMagVelocity(phaseIdx, globalVertexIdx); + const Scalar dynamicViscosity = fluidState.viscosity(phaseIdx); + const Scalar density = fluidState.density(phaseIdx); + const Scalar kinematicViscosity = dynamicViscosity / density; + const Scalar heatCapacity = FluidSystem::heatCapacity(fluidState, + paramCache, + phaseIdx); + const Scalar thermalConductivity = FluidSystem::thermalConductivity(fluidState, + paramCache, + phaseIdx); + + const Scalar porosity = problem.spatialParams().porosity(element, + fvGeometry, + scvIdx); + + reynoldsNumber_[phaseIdx] = DimLessNum::reynoldsNumber(darcyMagVelocity, + characteristicLength_, + kinematicViscosity); + + prandtlNumber_[phaseIdx] = DimLessNum::prandtlNumber(dynamicViscosity, + heatCapacity, + thermalConductivity); + + + nusseltNumber_[phaseIdx] = DimLessNum::nusseltNumberForced(reynoldsNumber_[phaseIdx], + prandtlNumber_[phaseIdx], + porosity, + nusseltFormulation); + } + } + + + //! access function Reynolds Number + const Scalar reynoldsNumber(const unsigned int phaseIdx) const + { return reynoldsNumber_[phaseIdx]; } + + //! access function Prandtl Number + const Scalar prandtlNumber(const unsigned int phaseIdx) const + { return prandtlNumber_[phaseIdx]; } + + //! access function Nusselt Number + const Scalar nusseltNumber(const unsigned int phaseIdx) const + { return nusseltNumber_[phaseIdx]; } + + //! access function characteristic length + const Scalar characteristicLength() const + { return characteristicLength_; } + + //! access function pre factor energy transfer + const Scalar factorEnergyTransfer() const + { return factorEnergyTransfer_; } + + //! access function pre factor mass transfer + const Scalar factorMassTransfer() const + { return factorMassTransfer_; } + + /*! + * \brief If running in valgrind this makes sure that all + * quantities in the volume variables are defined. + */ + void checkDefined() const + { +#if !defined NDEBUG && HAVE_VALGRIND + Valgrind::CheckDefined(reynoldsNumber_); + Valgrind::CheckDefined(prandtlNumber_); + Valgrind::CheckDefined(nusseltNumber_); + Valgrind::CheckDefined(characteristicLength_); + Valgrind::CheckDefined(factorEnergyTransfer_); + Valgrind::CheckDefined(factorMassTransfer_); +#endif + } + +private: + //! dimensionless numbers + Scalar reynoldsNumber_[numPhases]; + Scalar prandtlNumber_[numPhases]; + Scalar nusseltNumber_[numPhases]; + Scalar characteristicLength_; + Scalar factorEnergyTransfer_; + Scalar factorMassTransfer_; + Scalar solidSurface_ ; +}; + + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// specialization for the case of (only) kinetic mass transfer +//////////////////////////////////////////////////////////////////////////////////////////////////// +template <class TypeTag> +class MPNCVolumeVariablesIA<TypeTag, /*enableKinetic=*/true, /*numEnergyEqs=*/0> +{ + typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; + typedef typename FluidSystem::ParameterCache ParameterCache; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; + typedef typename GridView::template Codim<0>::Entity Element; + typedef DimensionlessNumbers<Scalar> DimLessNum; + + typedef typename GET_PROP_TYPE(TypeTag, AwnSurface) AwnSurface; + typedef typename AwnSurface::Params AwnSurfaceParams; + + enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; + enum { wPhaseIdx = FluidSystem::wPhaseIdx }; + enum { nPhaseIdx = FluidSystem::nPhaseIdx }; + enum { wCompIdx = FluidSystem::wCompIdx }; + enum { nCompIdx = FluidSystem::nCompIdx }; + enum { dim = GridView::dimension}; + enum { dimWorld = GridView::dimensionworld}; + enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; + enum { sherwoodFormulation = GET_PROP_VALUE(TypeTag, SherwoodFormulation)} ; + typedef Dune::FieldVector<Scalar,dimWorld> GlobalPosition; + typedef typename GET_PROP_TYPE(TypeTag, MaterialLawParams) MaterialLawParams; + + +public: + /*! + * \brief Updates the volume specific interfacial area [m^2 / m^3] between the phases. + */ + void update(const VolumeVariables & volVars, + const FluidState & fluidState, + const ParameterCache & paramCache, + const PrimaryVariables &priVars, + const Problem &problem, + const Element & element, + const FVElementGeometry & fvGeometry, + const unsigned int scvIdx) + { + //obtain parameters for awnsurface + const AwnSurfaceParams & awnSurfaceParams = problem.spatialParams().aWettingNonWettingSurfaceParams(element,fvGeometry,scvIdx) ; + + // obtain (standard) material parameters (needed for the residual saturations) + const MaterialLawParams & materialParams = problem.spatialParams().materialLawParams(element,fvGeometry,scvIdx) ; + + Valgrind::CheckDefined(awnSurfaceParams); + const Scalar Sw = fluidState.saturation(wPhaseIdx) ; + const Scalar pc = fluidState.pressure(nPhaseIdx) - fluidState.pressure(wPhaseIdx); + + // so far there is only a model for kinetic mass transfer between fluid phases + interfacialArea_ = AwnSurface::interfacialArea(awnSurfaceParams, materialParams, Sw, pc ); + + Valgrind::CheckDefined(interfacialArea_); + + factorMassTransfer_ = problem.spatialParams().factorMassTransfer(element, + fvGeometry, + scvIdx); + + characteristicLength_ = problem.spatialParams().characteristicLength(element, + fvGeometry, + scvIdx); + // setting the dimensionless numbers. + // obtaining the respective quantities. + int globalVertexIdx = problem.vertexMapper().subIndex(element, scvIdx, dim); + for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { + const Scalar darcyMagVelocity = problem.model().volumeDarcyMagVelocity(phaseIdx, globalVertexIdx); + const Scalar dynamicViscosity = fluidState.viscosity(phaseIdx); + const Scalar density = fluidState.density(phaseIdx); + const Scalar kinematicViscosity = dynamicViscosity / density; + + // diffusion coefficient of non-wetting component in wetting phase + const Scalar diffCoeff = volVars.diffCoeff(phaseIdx, wCompIdx, nCompIdx) ; + + reynoldsNumber_[phaseIdx] = DimLessNum::reynoldsNumber(darcyMagVelocity, + characteristicLength_, + kinematicViscosity); + + schmidtNumber_[phaseIdx] = DimLessNum::schmidtNumber(dynamicViscosity, + density, + diffCoeff); + + sherwoodNumber_[phaseIdx] = DimLessNum::sherwoodNumber(reynoldsNumber_[phaseIdx], + schmidtNumber_[phaseIdx], + sherwoodFormulation); + } + } + + /*! + * \brief The specific interfacial area between two fluid phases [m^2 / m^3] + */ + const Scalar interfacialArea(const unsigned int phaseIIdx, const unsigned int phaseJIdx) const + { + // so far there is only a model for kinetic mass transfer between fluid phases + assert((phaseIIdx == nPhaseIdx and phaseJIdx == wPhaseIdx) or (phaseIIdx == wPhaseIdx and phaseJIdx == nPhaseIdx) ); + return interfacialArea_; + } + + //! access function Reynolds Number + const Scalar reynoldsNumber(const unsigned int phaseIdx) const + { return reynoldsNumber_[phaseIdx]; } + + //! access function Schmidt Number + const Scalar schmidtNumber(const unsigned int phaseIdx) const + { return schmidtNumber_[phaseIdx]; } + + //! access function Sherwood Number + const Scalar sherwoodNumber(const unsigned int phaseIdx) const + { return sherwoodNumber_[phaseIdx]; } + + //! access function characteristic length + const Scalar characteristicLength() const + { return characteristicLength_; } + + //! access function pre factor mass transfer + const Scalar factorMassTransfer() const + { return factorMassTransfer_; } + + /*! + * \brief If running in valgrind this makes sure that all + * quantities in the volume variables are defined. + */ + void checkDefined() const + { + Valgrind::CheckDefined(interfacialArea_); + Valgrind::CheckDefined(characteristicLength_); + Valgrind::CheckDefined(factorMassTransfer_); + Valgrind::CheckDefined(reynoldsNumber_); + Valgrind::CheckDefined(schmidtNumber_); + Valgrind::CheckDefined(sherwoodNumber_); + } + +private: + Scalar characteristicLength_; + Scalar factorMassTransfer_; + Scalar solidSurface_ ; + Scalar interfacialArea_ ; + Scalar sherwoodNumber_[numPhases] ; + Scalar schmidtNumber_[numPhases] ; + Scalar reynoldsNumber_[numPhases] ; +}; + + + +} // namespace Dumux + +#endif diff --git a/dumux/porousmediumflow/mpnc/implicit/vtkwriter.hh b/dumux/porousmediumflow/mpnc/implicit/vtkwriter.hh new file mode 100644 index 0000000000000000000000000000000000000000..d8d43a0b71cd1c569cd19d6fd69702aba57737ae --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/vtkwriter.hh @@ -0,0 +1,130 @@ +// -*- 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 Writes the VTK output files for a solution of the MpNc model. + */ + +#ifndef DUMUX_MPNC_VTK_WRITER_HH +#define DUMUX_MPNC_VTK_WRITER_HH + +#include "properties.hh" + +#include <dumux/io/vtkmultiwriter.hh> + +namespace Dumux +{ +/*! + * \ingroup MPNCModel + * \brief Writes the VTK output files for a + * solution of the MpNc model. + */ +template<class TypeTag> +class MPNCVtkWriter +{ + typedef typename GET_PROP_TYPE(TypeTag, MPNCVtkCommonModule) MPNCVtkCommonModule; + typedef typename GET_PROP_TYPE(TypeTag, MPNCVtkMassModule) MPNCVtkMassModule; + typedef typename GET_PROP_TYPE(TypeTag, MPNCVtkEnergyModule) MPNCVtkEnergyModule; + typedef typename GET_PROP_TYPE(TypeTag, MPNCVtkCustomModule) MPNCVtkCustomModule; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes; + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + +public: + MPNCVtkWriter(const Problem &problem) + : problem_(problem) + , commonWriter_(problem) + , massWriter_(problem) + , energyWriter_(problem) + , customWriter_(problem) + { + } + + /*! + * \brief Add the current solution to the VtkMultiWriter. + */ + template <class MultiWriter> + void addCurrentSolution(MultiWriter &writer) + { + // tell sub-writers to allocate their buffers + commonWriter_.allocBuffers(writer); + massWriter_.allocBuffers(writer); + energyWriter_.allocBuffers(writer); + customWriter_.allocBuffers(writer); + + // iterate over grid + FVElementGeometry fvGeometry; + ElementVolumeVariables elemVolVars; + ElementBoundaryTypes elemBcTypes; + + for (const auto& element : Dune::elements(problem_.gridView())) + { + if(element.partitionType() == Dune::InteriorEntity) + { + fvGeometry.update(problem_.gridView(), element); + elemBcTypes.update(problem_, element); + this->problem_.model().setHints(element, elemVolVars); + elemVolVars.update(problem_, + element, + fvGeometry, + false); + this->problem_.model().updateCurHints(element, elemVolVars); + + // tell the sub-writers to do what ever they need to with + // their internal buffers when a given element is seen. + commonWriter_.processElement(element, + fvGeometry, + elemVolVars, + elemBcTypes); + massWriter_.processElement(element, + fvGeometry, + elemVolVars, + elemBcTypes); + energyWriter_.processElement(element, + fvGeometry, + elemVolVars, + elemBcTypes); + customWriter_.processElement(element, + fvGeometry, + elemVolVars, + elemBcTypes); + } + } + + // write everything to the output file + commonWriter_.commitBuffers(writer); + massWriter_.commitBuffers(writer); + energyWriter_.commitBuffers(writer); + customWriter_.commitBuffers(writer); + } + +private: + const Problem &problem_; + + MPNCVtkCommonModule commonWriter_; + MPNCVtkMassModule massWriter_; + MPNCVtkEnergyModule energyWriter_; + MPNCVtkCustomModule customWriter_; +}; + +} + +#endif diff --git a/dumux/porousmediumflow/mpnc/implicit/vtkwritercommon.hh b/dumux/porousmediumflow/mpnc/implicit/vtkwritercommon.hh new file mode 100644 index 0000000000000000000000000000000000000000..b45128e4832cb6d8276b34e0640f05627e4a8efc --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/vtkwritercommon.hh @@ -0,0 +1,256 @@ +// -*- 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 VTK writer module for the common quantities of the MpNc + * model. + */ +#ifndef DUMUX_MPNC_VTK_WRITER_COMMON_HH +#define DUMUX_MPNC_VTK_WRITER_COMMON_HH + +#include <dumux/porousmediumflow/implicit/velocityoutput.hh> +#include "vtkwritermodule.hh" + +namespace Dumux +{ +/*! + * \ingroup MPNCModel + * + * \brief VTK writer module for the common quantities of the MpNc + * model. + */ +template<class TypeTag> +class MPNCVtkWriterCommon : public MPNCVtkWriterModule<TypeTag> +{ + typedef MPNCVtkWriterModule<TypeTag> ParentType; + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes; + typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GridView::template Codim<0>::Entity Element; + typedef typename ParentType::ScalarVector ScalarVector; + typedef typename ParentType::PhaseVector PhaseVector; + typedef typename ParentType::ComponentVector ComponentVector; + typedef typename ParentType::PhaseComponentMatrix PhaseComponentMatrix; + + enum { dim = GridView::dimension }; + enum { dimWorld = GridView::dimensionworld }; + enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; + enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; + enum { numEq = GET_PROP_VALUE(TypeTag, NumEq) }; + + typedef Dune::FieldVector<Scalar, dimWorld> DimWorldVector; + typedef Dune::BlockVector<DimWorldVector> DimWorldField; + typedef std::array<DimWorldField, numPhases> PhaseDimWorldField; + enum { isBox = GET_PROP_VALUE(TypeTag, ImplicitIsBox) }; + enum { dofCodim = isBox ? dim : 0 }; + +public: + MPNCVtkWriterCommon(const Problem &problem) + : ParentType(problem), velocityOutput_(problem) + { + porosityOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddPorosity); + permeabilityOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddPermeability); + boundaryTypesOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddBoundaryTypes); + saturationOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddSaturations); + pressureOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddPressures); + densityOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddDensities); + mobilityOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddMobilities); + averageMolarMassOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddAverageMolarMass); + massFracOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddMassFractions); + moleFracOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddMoleFractions); + molarityOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddMolarities); + } + + /*! + * \brief Allocate memory for the scalar fields we would like to + * write to the VTK file. + */ + template <class MultiWriter> + void allocBuffers(MultiWriter &writer) + { + if (porosityOutput_) + this->resizeScalarBuffer_(porosity_, isBox); + if (permeabilityOutput_) + this->resizeScalarBuffer_(permeability_); + if (boundaryTypesOutput_) + this->resizeScalarBuffer_(boundaryTypes_, isBox); + + if (velocityOutput_.enableOutput()) { + Scalar numDofs = this->problem_.model().numDofs(); + for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { + velocity_[phaseIdx].resize(numDofs); + velocity_[phaseIdx] = 0; + } + } + + if (saturationOutput_) this->resizePhaseBuffer_(saturation_, isBox); + if (pressureOutput_) this->resizePhaseBuffer_(pressure_, isBox); + if (densityOutput_) this->resizePhaseBuffer_(density_, isBox); + if (mobilityOutput_) this->resizePhaseBuffer_(mobility_, isBox); + if (averageMolarMassOutput_) this->resizePhaseBuffer_(averageMolarMass_, isBox); + if (moleFracOutput_) this->resizePhaseComponentBuffer_(moleFrac_, isBox); + if (massFracOutput_) this->resizePhaseComponentBuffer_(massFrac_, isBox); + if (molarityOutput_) this->resizePhaseComponentBuffer_(molarity_, isBox); + } + + /*! + * \brief Modify the internal buffers according to the volume + * variables seen on an element + * + * \param element The finite element + * \param fvGeometry The finite-volume geometry in the fully implicit scheme + * \param elemVolVars The volume variables of the current element + * \param elemBcTypes The types of the boundary conditions for all vertices of the element + */ + void processElement(const Element &element, + const FVElementGeometry &fvGeometry, + const ElementVolumeVariables &elemVolVars, + const ElementBoundaryTypes &elemBcTypes) + { + for (int scvIdx = 0; scvIdx < fvGeometry.numScv; ++scvIdx) + { + int dofIdxGlobal = this->problem_.model().dofMapper().subIndex(element, scvIdx, dofCodim); + + const VolumeVariables &volVars = elemVolVars[scvIdx]; + + if (porosityOutput_) porosity_[dofIdxGlobal] = volVars.porosity(); + + // works for scalar permeability in spatialparameters + if (permeabilityOutput_) permeability_[dofIdxGlobal] = this->problem_.spatialParams().intrinsicPermeability(element,fvGeometry,scvIdx); + + // calculate a single value for the boundary type: use one + // bit for each equation and set it to 1 if the equation + // is used for a dirichlet condition + int tmp = 0; + for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) { + if (elemBcTypes[scvIdx].isDirichlet(eqIdx)) + tmp += (1 << eqIdx); + } + if (boundaryTypesOutput_) boundaryTypes_[dofIdxGlobal] = tmp; + + for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { + if (saturationOutput_) saturation_[phaseIdx][dofIdxGlobal] = volVars.fluidState().saturation(phaseIdx); + if (pressureOutput_) pressure_[phaseIdx][dofIdxGlobal] = volVars.fluidState().pressure(phaseIdx); + if (densityOutput_) density_[phaseIdx][dofIdxGlobal] = volVars.fluidState().density(phaseIdx); + if (mobilityOutput_) mobility_[phaseIdx][dofIdxGlobal] = volVars.mobility(phaseIdx); + if (averageMolarMassOutput_) averageMolarMass_[phaseIdx][dofIdxGlobal] = volVars.fluidState().averageMolarMass(phaseIdx); + for (int compIdx = 0; compIdx < numComponents; ++compIdx) { + if (moleFracOutput_) moleFrac_[phaseIdx][compIdx][dofIdxGlobal] = volVars.fluidState().moleFraction(phaseIdx, compIdx); + if (massFracOutput_) massFrac_[phaseIdx][compIdx][dofIdxGlobal] = volVars.fluidState().massFraction(phaseIdx, compIdx); + if (molarityOutput_) molarity_[phaseIdx][compIdx][dofIdxGlobal] = volVars.fluidState().molarity(phaseIdx, compIdx); + } + } + } + + // velocity output + for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { + velocityOutput_.calculateVelocity(velocity_[phaseIdx], elemVolVars, fvGeometry, element, phaseIdx); + } + } + + /*! + * \brief Add all buffers to the VTK output writer. + */ + template <class MultiWriter> + void commitBuffers(MultiWriter &writer) + { + if (saturationOutput_) + this->commitPhaseBuffer_(writer, "S_%s", saturation_, isBox); + + if (pressureOutput_) + this->commitPhaseBuffer_(writer, "p_%s", pressure_, isBox); + + if (densityOutput_) + this->commitPhaseBuffer_(writer, "rho_%s", density_, isBox); + + if (averageMolarMassOutput_) + this->commitPhaseBuffer_(writer, "M_%s", averageMolarMass_, isBox); + + if (mobilityOutput_) + this->commitPhaseBuffer_(writer, "lambda_%s", mobility_, isBox); + + if (porosityOutput_) + this->commitScalarBuffer_(writer, "porosity", porosity_, isBox); + + if (boundaryTypesOutput_) + this->commitScalarBuffer_(writer, "boundary types", boundaryTypes_, isBox); + + if (moleFracOutput_) + this->commitPhaseComponentBuffer_(writer, "x_%s^%s", moleFrac_, isBox); + + if (massFracOutput_) + this->commitPhaseComponentBuffer_(writer, "X_%s^%s", massFrac_, isBox); + + if(molarityOutput_) + this->commitPhaseComponentBuffer_(writer, "c_%s^%s", molarity_, isBox); + + if (velocityOutput_.enableOutput()) { + for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { + std::ostringstream oss; + oss << "velocity_" << FluidSystem::phaseName(phaseIdx); + writer.attachDofData(velocity_[phaseIdx], + oss.str(), isBox, dim); + } + } + } + +private: + bool porosityOutput_; + bool permeabilityOutput_ ; + bool boundaryTypesOutput_; + bool saturationOutput_; + bool pressureOutput_; + bool densityOutput_; + bool mobilityOutput_; + bool massFracOutput_; + bool moleFracOutput_; + bool molarityOutput_; + bool averageMolarMassOutput_; + + PhaseVector saturation_; + PhaseVector pressure_; + PhaseVector density_; + PhaseVector mobility_; + PhaseVector averageMolarMass_; + + PhaseDimWorldField velocity_; + + ScalarVector porosity_; + ScalarVector permeability_; + ScalarVector temperature_; + ScalarVector boundaryTypes_; + + PhaseComponentMatrix moleFrac_; + PhaseComponentMatrix massFrac_; + PhaseComponentMatrix molarity_; + + ComponentVector fugacity_; + + ImplicitVelocityOutput<TypeTag> velocityOutput_; +}; + +} + +#endif diff --git a/dumux/porousmediumflow/mpnc/implicit/vtkwritermodule.hh b/dumux/porousmediumflow/mpnc/implicit/vtkwritermodule.hh new file mode 100644 index 0000000000000000000000000000000000000000..7d13ad1d3afe20af3f443b8438ff5320d88f3761 --- /dev/null +++ b/dumux/porousmediumflow/mpnc/implicit/vtkwritermodule.hh @@ -0,0 +1,263 @@ +// -*- 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 A VTK writer module which adheres to the required API but + * does nothing. + */ + +#ifndef DUMUX_MPNC_VTK_BASE_WRITER_HH +#define DUMUX_MPNC_VTK_BASE_WRITER_HH + +#include <array> +#include <cstdio> + +#include <dune/istl/bvector.hh> + +#include <dumux/io/vtkmultiwriter.hh> +#include "properties.hh" + +namespace Dumux +{ +/*! + * \ingroup MPNCModel + * + * \brief A VTK writer module which adheres to the required API but + * does nothing. + * + * This class also provides some convenience methods for buffer + * management. + */ +template<class TypeTag> +class MPNCVtkWriterModule +{ + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes; + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + typedef typename GridView::template Codim<0>::Entity Element; + + enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; + enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) }; + enum { dim = GridView::dimension }; + +public: + typedef std::vector<Dune::FieldVector<Scalar, 1> > ScalarVector; + typedef std::array<ScalarVector, numPhases> PhaseVector; + typedef std::array<ScalarVector, numComponents> ComponentVector; + typedef std::array<ComponentVector, numPhases> PhaseComponentMatrix; + + MPNCVtkWriterModule(const Problem &problem) + : problem_(problem) + { + } + + /*! + * \brief Allocate memory for the scalar fields we would like to + * write to the VTK file. + */ + template <class MultiWriter> + void allocBuffers(MultiWriter &writer) + { + } + + /*! + * \brief Modify the internal buffers according to the volume + * variables seen on an element + */ + void processElement(const Element &element, + const FVElementGeometry &fvGeometry, + const ElementVolumeVariables &elemCurVolVars, + const ElementBoundaryTypes &elemBcTypes) + { + } + + /*! + * \brief Add all buffers to the VTK output writer. + */ + template <class MultiWriter> + void commitBuffers(MultiWriter &writer) + { + } + +protected: + /*! + * \brief Allocate the space for a buffer storing a scalar quantity + */ + void resizeScalarBuffer_(ScalarVector &buffer, + bool vertexCentered = true) + { + Scalar n; // numVertices for vertexCentereed, numVolumes for volume centered + if (vertexCentered) + n = problem_.gridView().size(dim); + else + n = problem_.gridView().size(0); + + buffer.resize(n); + std::fill(buffer.begin(), buffer.end(), 0.0); + } + + /*! + * \brief Allocate the space for a buffer storing a phase-specific + * quantity + */ + void resizePhaseBuffer_(PhaseVector &buffer, + bool vertexCentered = true) + { + Scalar n; // numVertices for vertexCentereed, numVolumes for volume centered + if (vertexCentered) + n = problem_.gridView().size(dim); + else + n = problem_.gridView().size(0); + + for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { + buffer[phaseIdx].resize(n); + std::fill(buffer[phaseIdx].begin(), buffer[phaseIdx].end(), 0.0); + } + } + + /*! + * \brief Allocate the space for a buffer storing a component + * specific quantity + */ + void resizeComponentBuffer_(ComponentVector &buffer, + bool vertexCentered = true) + { + Scalar n;// numVertices for vertexCentereed, numVolumes for volume centered + if (vertexCentered) + n = problem_.gridView().size(dim); + else + n = problem_.gridView().size(0); + + for (int compIdx = 0; compIdx < numComponents; ++compIdx) { + buffer[compIdx].resize(n); + std::fill(buffer[compIdx].begin(), buffer[compIdx].end(), 0.0); + } + } + + /*! + * \brief Allocate the space for a buffer storing a phase and + * component specific buffer + */ + void resizePhaseComponentBuffer_(PhaseComponentMatrix &buffer, + bool vertexCentered = true) + { + Scalar n;// numVertices for vertexCentereed, numVolumes for volume centered + if (vertexCentered) + n = problem_.gridView().size(dim); + else + n = problem_.gridView().size(0); + + for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { + for (int compIdx = 0; compIdx < numComponents; ++compIdx) { + buffer[phaseIdx][compIdx].resize(n); + std::fill(buffer[phaseIdx][compIdx].begin(), buffer[phaseIdx][compIdx].end(), 0.0); + } + } + } + + /*! + * \brief Add a phase-specific buffer to the VTK result file. + */ + template <class MultiWriter> + void commitScalarBuffer_(MultiWriter &writer, + const char *name, + ScalarVector &buffer, + bool vertexCentered = true) + { + if (vertexCentered) + writer.attachVertexData(buffer, name, 1); + else + writer.attachCellData(buffer, name, 1); + } + + /*! + * \brief Add a phase-specific buffer to the VTK result file. + */ + template <class MultiWriter> + void commitPhaseBuffer_(MultiWriter &writer, + const char *pattern, + PhaseVector &buffer, + bool vertexCentered = true) + { + char name[512]; + for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { + snprintf(name, 512, pattern, FluidSystem::phaseName(phaseIdx)); + + if (vertexCentered) + writer.attachVertexData(buffer[phaseIdx], name, 1); + else + writer.attachCellData(buffer[phaseIdx], name, 1); + } + } + + /*! + * \brief Add a component-specific buffer to the VTK result file. + */ + template <class MultiWriter> + void commitComponentBuffer_(MultiWriter &writer, + const char *pattern, + ComponentVector &buffer, + bool vertexCentered = true) + { + char name[512]; + for (int compIdx = 0; compIdx < numComponents; ++compIdx) { + snprintf(name, 512, pattern, FluidSystem::componentName(compIdx)); + + if (vertexCentered) + writer.attachVertexData(buffer[compIdx], name, 1); + else + writer.attachCellData(buffer[compIdx], name, 1); + } + } + + /*! + * \brief Add a phase and component specific quantities to the output. + */ + template <class MultiWriter> + void commitPhaseComponentBuffer_(MultiWriter &writer, + const char *pattern, + PhaseComponentMatrix &buffer, + bool vertexCentered = true) + { + char name[512]; + for (int phaseIdx= 0; phaseIdx < numPhases; ++phaseIdx) { + for (int compIdx = 0; compIdx < numComponents; ++compIdx) { + snprintf(name, 512, pattern, + FluidSystem::phaseName(phaseIdx), + FluidSystem::componentName(compIdx)); + + if (vertexCentered) + writer.attachVertexData(buffer[phaseIdx][compIdx], name, 1); + else + writer.attachCellData(buffer[phaseIdx][compIdx], name, 1); + } + } + } + + const Problem &problem_; +}; + +} + +#endif diff --git a/test/porousmediumflow/mpnc/implicit/combustionproblem1c.hh b/test/porousmediumflow/mpnc/implicit/combustionproblem1c.hh index 1f33d5a6f2f6caad030fb1e8b4a18483b00d0d18..5bdbbccb5e03e28520d09d303eb500347b9c3e6e 100644 --- a/test/porousmediumflow/mpnc/implicit/combustionproblem1c.hh +++ b/test/porousmediumflow/mpnc/implicit/combustionproblem1c.hh @@ -42,11 +42,11 @@ #include <dumux/porousmediumflow/implicit/problem.hh> -#include <dumux/implicit/mpnc/mpncmodelkinetic.hh> +#include <dumux/porousmediumflow/mpnc/implicit/modelkinetic.hh> #include "combustionspatialparams.hh" -#include <dumux/implicit/mpnc/velomodelnewtoncontroller.hh> +#include <dumux/porousmediumflow/mpnc/implicit/velomodelnewtoncontroller.hh> #include <dumux/material/fluidsystems/purewatersimplefluidsystem.hh> diff --git a/test/porousmediumflow/mpnc/implicit/evaporationatmosphereproblem.hh b/test/porousmediumflow/mpnc/implicit/evaporationatmosphereproblem.hh index a14f0f25c62546ecee5c08717f90ff2f31eafc90..f0d8a494b2022485ffca1207c483b5072fe040f7 100644 --- a/test/porousmediumflow/mpnc/implicit/evaporationatmosphereproblem.hh +++ b/test/porousmediumflow/mpnc/implicit/evaporationatmosphereproblem.hh @@ -50,9 +50,9 @@ #include <dune/grid/io/file/dgfparser/dgfyasp.hh> -#include <dumux/implicit/mpnc/mpncmodelkinetic.hh> +#include <dumux/porousmediumflow/mpnc/implicit/modelkinetic.hh> #include <dumux/porousmediumflow/implicit/problem.hh> -#include <dumux/implicit/mpnc/velomodelnewtoncontroller.hh> +#include <dumux/porousmediumflow/mpnc/implicit/velomodelnewtoncontroller.hh> #include <dumux/material/fluidsystems/h2on2fluidsystemkinetic.hh> #include <dumux/io/gnuplotinterface.hh> diff --git a/test/porousmediumflow/mpnc/implicit/evaporationatmospherespatialparams.hh b/test/porousmediumflow/mpnc/implicit/evaporationatmospherespatialparams.hh index 3d8dbdd56e9a16ac4dfcefbab327091a66240361..972d9a10746075dd162d2e2be588db3c5c8e45fa 100644 --- a/test/porousmediumflow/mpnc/implicit/evaporationatmospherespatialparams.hh +++ b/test/porousmediumflow/mpnc/implicit/evaporationatmospherespatialparams.hh @@ -43,7 +43,7 @@ #include <dune/common/parametertreeparser.hh> -#include <dumux/implicit/mpnc/mpncmodelkinetic.hh> +#include <dumux/porousmediumflow/mpnc/implicit/modelkinetic.hh> namespace Dumux { diff --git a/test/porousmediumflow/mpnc/implicit/forchheimer1pproblem.hh b/test/porousmediumflow/mpnc/implicit/forchheimer1pproblem.hh index bb7cd207a7a5a9d876323edc30fd06d2c818cdb3..450c0680052c11762c9749d8ffc9d4a93101d71a 100644 --- a/test/porousmediumflow/mpnc/implicit/forchheimer1pproblem.hh +++ b/test/porousmediumflow/mpnc/implicit/forchheimer1pproblem.hh @@ -29,7 +29,7 @@ #include <dune/grid/io/file/dgfparser/dgfyasp.hh> -#include <dumux/implicit/mpnc/mpncmodel.hh> +#include <dumux/porousmediumflow/mpnc/implicit/model.hh> #include <dumux/porousmediumflow/implicit/problem.hh> #include <dumux/material/fluidsystems/h2oairfluidsystem.hh> diff --git a/test/porousmediumflow/mpnc/implicit/forchheimer2pproblem.hh b/test/porousmediumflow/mpnc/implicit/forchheimer2pproblem.hh index 7632629a170bce8cf6db5a2d8990cbf365b00a95..c218885da16a6300d9d4bc0fa8301e27c13c8e72 100644 --- a/test/porousmediumflow/mpnc/implicit/forchheimer2pproblem.hh +++ b/test/porousmediumflow/mpnc/implicit/forchheimer2pproblem.hh @@ -27,7 +27,7 @@ #include <dune/grid/io/file/dgfparser/dgfyasp.hh> -#include <dumux/implicit/mpnc/mpncmodel.hh> +#include <dumux/porousmediumflow/mpnc/implicit/model.hh> #include <dumux/porousmediumflow/implicit/problem.hh> #include <dumux/material/fluidsystems/h2on2fluidsystem.hh> diff --git a/test/porousmediumflow/mpnc/implicit/forchheimerspatialparams.hh b/test/porousmediumflow/mpnc/implicit/forchheimerspatialparams.hh index 95bae23651b374ed28017927b0059dd44c28ba95..2a89eafca7d6c6fedcb863ab2866e7d6e3ec5448 100644 --- a/test/porousmediumflow/mpnc/implicit/forchheimerspatialparams.hh +++ b/test/porousmediumflow/mpnc/implicit/forchheimerspatialparams.hh @@ -30,7 +30,7 @@ #include <dumux/material/fluidmatrixinteractions/2p/regularizedlinearmaterial.hh> #include <dumux/material/fluidmatrixinteractions/2p/efftoabslaw.hh> -#include <dumux/implicit/mpnc/mpncmodel.hh> +#include <dumux/porousmediumflow/mpnc/implicit/model.hh> #include <dumux/material/fluidmatrixinteractions/mp/mplinearmaterial.hh> #include <dumux/material/fluidmatrixinteractions/mp/2padapter.hh> diff --git a/test/porousmediumflow/mpnc/implicit/obstacleproblem.hh b/test/porousmediumflow/mpnc/implicit/obstacleproblem.hh index 3771c91c14cfc2024a306908471850bf02bc7f0a..16a85fb2f890f18d1f6f01b40d47a2f1a46d7645 100644 --- a/test/porousmediumflow/mpnc/implicit/obstacleproblem.hh +++ b/test/porousmediumflow/mpnc/implicit/obstacleproblem.hh @@ -29,7 +29,7 @@ #include <dune/grid/io/file/dgfparser/dgfyasp.hh> -#include <dumux/implicit/mpnc/mpncmodel.hh> +#include <dumux/porousmediumflow/mpnc/implicit/model.hh> #include <dumux/porousmediumflow/implicit/problem.hh> #include <dumux/material/fluidsystems/h2on2fluidsystem.hh> diff --git a/test/porousmediumflow/mpnc/implicit/obstaclespatialparams.hh b/test/porousmediumflow/mpnc/implicit/obstaclespatialparams.hh index ca08eabfeca8a52847c2d9b69176abf0ba328d4d..0f394201a59a688811e4b8408173df0baad8717e 100644 --- a/test/porousmediumflow/mpnc/implicit/obstaclespatialparams.hh +++ b/test/porousmediumflow/mpnc/implicit/obstaclespatialparams.hh @@ -29,7 +29,7 @@ #include <dumux/material/fluidmatrixinteractions/2p/regularizedlinearmaterial.hh> #include <dumux/material/fluidmatrixinteractions/2p/efftoabslaw.hh> -#include <dumux/implicit/mpnc/mpncmodel.hh> +#include <dumux/porousmediumflow/mpnc/implicit/model.hh> #include <dumux/material/fluidmatrixinteractions/mp/mplinearmaterial.hh> #include <dumux/material/fluidmatrixinteractions/mp/2padapter.hh>