From c0c0e77a2f5be5007455bf16094561b51b42dae0 Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Sun, 12 Jun 2016 15:16:16 +0200 Subject: [PATCH 01/45] [implicit] more specific flux vars The flux vars and the flux vars cache are moved to the folder porousmediumflow/implicit and are renamed to be more specific to porous medium. This is done because the freeflow models will have flux vars related to free flow, thus will appear in the corresponding folder in the new structure. By default, the flux vars are set to the ones for porous media (see propertydefaults). --- .../cellcentered/tpfa/propertydefaults.hh | 6 ++-- dumux/implicit/propertydefaults.hh | 10 ++++--- .../implicit/fluxvariables.hh | 28 +++++++++---------- .../implicit/fluxvariablescache.hh | 8 +++--- 4 files changed, 27 insertions(+), 25 deletions(-) rename dumux/{ => porousmediumflow}/implicit/fluxvariables.hh (93%) rename dumux/{ => porousmediumflow}/implicit/fluxvariablescache.hh (95%) diff --git a/dumux/implicit/cellcentered/tpfa/propertydefaults.hh b/dumux/implicit/cellcentered/tpfa/propertydefaults.hh index 348ad210a3..3977efcfbb 100644 --- a/dumux/implicit/cellcentered/tpfa/propertydefaults.hh +++ b/dumux/implicit/cellcentered/tpfa/propertydefaults.hh @@ -29,7 +29,7 @@ #include #include - #include +#include #include #include #include @@ -65,8 +65,8 @@ public: typedef Dumux::SubControlVolumeFace type; }; -//! The flux variables cache class -SET_TYPE_PROP(CCTpfaModel, FluxVariablesCache, Dumux::CCTpfaFluxVariablesCache); +//! The flux variables cache class, by default the one for porous media +SET_TYPE_PROP(CCTpfaModel, FluxVariablesCache, Dumux::CCTpfaPorousMediumFluxVariablesCache); //! The darcy flux variables SET_TYPE_PROP(CCTpfaModel, AdvectionType, Dumux::CCTpfaDarcysLaw); diff --git a/dumux/implicit/propertydefaults.hh b/dumux/implicit/propertydefaults.hh index 375b0c46ef..5bf7a7ddd2 100644 --- a/dumux/implicit/propertydefaults.hh +++ b/dumux/implicit/propertydefaults.hh @@ -35,14 +35,15 @@ #include #include +#include +#include + #include "properties.hh" #include "model.hh" #include "assembler.hh" #include "localjacobian.hh" #include "volumevariables.hh" #include "volumevariablesvector.hh" -#include "fluxvariables.hh" -#include "fluxvariablescache.hh" #include "fluxvariablescachevector.hh" #include "fvelementgeometry.hh" @@ -105,7 +106,8 @@ SET_TYPE_PROP(ImplicitBase, PreviousVolumeVariablesVector, Dumux::VolumeVariable //! The global flux variables cache vector class SET_TYPE_PROP(ImplicitBase, FluxVariablesCacheVector, Dumux::FluxVariablesCacheVector); -// //! The class that contains the different flux variables (i.e. darcy, diffusion, energy) +//! The class that contains the different flux variables (i.e. darcy, diffusion, energy) +//! by default, we set the flux variables to ones for porous media SET_PROP(ImplicitBase, FluxVariables) { private: @@ -113,7 +115,7 @@ private: static constexpr bool diffusion = GET_PROP_VALUE(TypeTag, EnableMolecularDiffusion); static constexpr bool energy = GET_PROP_VALUE(TypeTag, EnableEnergyBalance); public: - typedef Dumux::FluxVariables type; + typedef Dumux::PorousMediumFluxVariables type; }; //! The type of a solution for the whole grid at a fixed time diff --git a/dumux/implicit/fluxvariables.hh b/dumux/porousmediumflow/implicit/fluxvariables.hh similarity index 93% rename from dumux/implicit/fluxvariables.hh rename to dumux/porousmediumflow/implicit/fluxvariables.hh index e7a4513161..5a9d9bc38c 100644 --- a/dumux/implicit/fluxvariables.hh +++ b/dumux/porousmediumflow/implicit/fluxvariables.hh @@ -20,8 +20,8 @@ * \file * \brief Base class for the flux variables */ -#ifndef DUMUX_IMPLICIT_FLUXVARIABLES_HH -#define DUMUX_IMPLICIT_FLUXVARIABLES_HH +#ifndef DUMUX_POROUSMEDIUMFLOW_IMPLICIT_FLUXVARIABLES_HH +#define DUMUX_POROUSMEDIUMFLOW_IMPLICIT_FLUXVARIABLES_HH #include @@ -40,7 +40,7 @@ NEW_PROP_TAG(NumComponents); * Actual flux variables inherit from this class */ template -class FluxVariablesBase +class PorousMediumFluxVariablesBase { using Problem = typename GET_PROP_TYPE(TypeTag, Problem); using GridView = typename GET_PROP_TYPE(TypeTag, GridView); @@ -53,7 +53,7 @@ class FluxVariablesBase enum{ enableFluxVarsCache = GET_PROP_VALUE(TypeTag, EnableFluxVariablesCache) }; public: - FluxVariablesBase() : problemPtr_(nullptr), scvFacePtr_(nullptr) + PorousMediumFluxVariablesBase() : problemPtr_(nullptr), scvFacePtr_(nullptr) {} void init(const Problem& problem, @@ -116,14 +116,14 @@ private: * specializations are provided for combinations of physical processes */ template -class FluxVariables {}; +class PorousMediumFluxVariables {}; // specialization for pure advective flow (e.g. 1p/2p/3p immiscible darcy flow) template -class FluxVariables : public FluxVariablesBase> +class PorousMediumFluxVariables : public PorousMediumFluxVariablesBase> { - using ParentType = FluxVariablesBase>; + using ParentType = PorousMediumFluxVariablesBase>; using Problem = typename GET_PROP_TYPE(TypeTag, Problem); using GridView = typename GET_PROP_TYPE(TypeTag, GridView); using Element = typename GridView::template Codim<0>::Entity; @@ -170,9 +170,9 @@ public: // specialization for isothermal advection molecularDiffusion equations template -class FluxVariables : public FluxVariablesBase> +class PorousMediumFluxVariables : public PorousMediumFluxVariablesBase> { - using ParentType = FluxVariablesBase>; + using ParentType = PorousMediumFluxVariablesBase>; using Problem = typename GET_PROP_TYPE(TypeTag, Problem); using GridView = typename GET_PROP_TYPE(TypeTag, GridView); using Element = typename GridView::template Codim<0>::Entity; @@ -241,7 +241,7 @@ private: // specialization for pure molecularDiffusion_ template -class FluxVariables +class PorousMediumFluxVariables { using Problem = typename GET_PROP_TYPE(TypeTag, Problem); using GridView = typename GET_PROP_TYPE(TypeTag, GridView); @@ -281,7 +281,7 @@ private: // specialization for non-isothermal advective flow (e.g. non-isothermal one-phase darcy equation) template -class FluxVariables +class PorousMediumFluxVariables { using Problem = typename GET_PROP_TYPE(TypeTag, Problem); using GridView = typename GET_PROP_TYPE(TypeTag, GridView); @@ -326,7 +326,7 @@ private: // specialization for non-isothermal advection molecularDiffusion_ equations template -class FluxVariables +class PorousMediumFluxVariables { using Problem = typename GET_PROP_TYPE(TypeTag, Problem); using GridView = typename GET_PROP_TYPE(TypeTag, GridView); @@ -392,7 +392,7 @@ private: // specialization for non-isothermal molecularDiffusion_ template -class FluxVariables +class PorousMediumFluxVariables { using Problem = typename GET_PROP_TYPE(TypeTag, Problem); using GridView = typename GET_PROP_TYPE(TypeTag, GridView); @@ -445,7 +445,7 @@ private: // specialization for pure heat conduction (e.g. the heat equation) template -class FluxVariables +class PorousMediumFluxVariables { using Problem = typename GET_PROP_TYPE(TypeTag, Problem); using GridView = typename GET_PROP_TYPE(TypeTag, GridView); diff --git a/dumux/implicit/fluxvariablescache.hh b/dumux/porousmediumflow/implicit/fluxvariablescache.hh similarity index 95% rename from dumux/implicit/fluxvariablescache.hh rename to dumux/porousmediumflow/implicit/fluxvariablescache.hh index 153b249912..5212045676 100644 --- a/dumux/implicit/fluxvariablescache.hh +++ b/dumux/porousmediumflow/implicit/fluxvariablescache.hh @@ -20,8 +20,8 @@ * \file * \brief Base class for the flux variables */ -#ifndef DUMUX_IMPLICIT_FLUXVARIABLESCACHE_HH -#define DUMUX_IMPLICIT_FLUXVARIABLESCACHE_HH +#ifndef DUMUX_POROUSMEDIUM_IMPLICIT_FLUXVARIABLESCACHE_HH +#define DUMUX_POROUSMEDIUM_IMPLICIT_FLUXVARIABLESCACHE_HH #include @@ -41,7 +41,7 @@ NEW_PROP_TAG(NumComponents); */ // specialization for the Box Method template -class BoxFluxVariablesCache +class BoxPorousMediumFluxVariablesCache { using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); using Problem = typename GET_PROP_TYPE(TypeTag, Problem); @@ -80,7 +80,7 @@ private: // specialization for the cell centered tpfa method template -class CCTpfaFluxVariablesCache +class CCTpfaPorousMediumFluxVariablesCache { using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); using Problem = typename GET_PROP_TYPE(TypeTag, Problem); -- GitLab From d802b142d294b4b4ca8db78510e2730a5fed4c8f Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Mon, 20 Jun 2016 15:14:27 +0200 Subject: [PATCH 02/45] [implicit] move flux vars base class The base class for the flux variables is moved to the folder /dumux/implicit, as the flux vars implementations for free flow and/or geomechanical models will also inherit from this base class. --- dumux/implicit/fluxvariablesbase.hh | 106 ++++++++++++++++++ .../implicit/fluxvariables.hh | 85 +------------- 2 files changed, 111 insertions(+), 80 deletions(-) create mode 100644 dumux/implicit/fluxvariablesbase.hh diff --git a/dumux/implicit/fluxvariablesbase.hh b/dumux/implicit/fluxvariablesbase.hh new file mode 100644 index 0000000000..5ac578db94 --- /dev/null +++ b/dumux/implicit/fluxvariablesbase.hh @@ -0,0 +1,106 @@ +// -*- 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 . * + *****************************************************************************/ +/*! + * \file + * \brief Base class for the flux variables + */ +#ifndef DUMUX_IMPLICIT_FLUXVARIABLESBASE_HH +#define DUMUX_IMPLICIT_FLUXVARIABLESBASE_HH + +#include + +namespace Dumux +{ + +/*! + * \ingroup ImplicitModel + * \brief Base class for the flux variables + * Actual flux variables inherit from this class + */ +template +class FluxVariablesBase +{ + using Problem = typename GET_PROP_TYPE(TypeTag, Problem); + using GridView = typename GET_PROP_TYPE(TypeTag, GridView); + using Element = typename GridView::template Codim<0>::Entity; + using IndexType = typename GridView::IndexSet::IndexType; + using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Stencil = std::vector; + using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); + + enum{ enableFluxVarsCache = GET_PROP_VALUE(TypeTag, EnableFluxVariablesCache) }; + +public: + FluxVariablesBase() : problemPtr_(nullptr), scvFacePtr_(nullptr) + {} + + void init(const Problem& problem, + const Element& element, + const SubControlVolumeFace &scvFace) + { + problemPtr_ = &problem; + scvFacePtr_ = &scvFace; + + // update the stencil if needed + if (!enableFluxVarsCache) + stencil_ = asImp_().computeStencil(problem, scvFace); + } + + // when caching is enabled, get the stencil from the cache class + template + const typename std::enable_if::type& stencil() const + { return problem().model().fluxVarsCache(scvFace()).stencil(); } + + // when caching is disabled, return the private stencil variable. The update(...) routine has to be called beforehand. + template + const typename std::enable_if::type& stencil() + { return stencil_; } + + const Problem& problem() const + { return *problemPtr_; } + + const SubControlVolumeFace& scvFace() const + { + return *scvFacePtr_; + } + + Stencil computeStencil(const Problem& problem, const SubControlVolumeFace& scvFace) + { DUNE_THROW(Dune::InvalidStateException, "computeStencil() routine is not provided by the implementation."); } + +private: + + Implementation &asImp_() + { + assert(static_cast(this) != 0); + return *static_cast(this); + } + + const Implementation &asImp_() const + { + assert(static_cast(this) != 0); + return *static_cast(this); + } + + const Problem *problemPtr_; //! Pointer to the problem + const SubControlVolumeFace *scvFacePtr_; //! Pointer to the sub control volume face for which the flux variables are created + Stencil stencil_; //! The flux stencil +}; +} // end namespace + +#endif diff --git a/dumux/porousmediumflow/implicit/fluxvariables.hh b/dumux/porousmediumflow/implicit/fluxvariables.hh index 5a9d9bc38c..97e3d5629f 100644 --- a/dumux/porousmediumflow/implicit/fluxvariables.hh +++ b/dumux/porousmediumflow/implicit/fluxvariables.hh @@ -24,6 +24,7 @@ #define DUMUX_POROUSMEDIUMFLOW_IMPLICIT_FLUXVARIABLES_HH #include +#include namespace Dumux { @@ -34,82 +35,6 @@ NEW_PROP_TAG(NumPhases); NEW_PROP_TAG(NumComponents); } -/*! - * \ingroup ImplicitModel - * \brief Base class for the flux variables - * Actual flux variables inherit from this class - */ -template -class PorousMediumFluxVariablesBase -{ - using Problem = typename GET_PROP_TYPE(TypeTag, Problem); - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using Element = typename GridView::template Codim<0>::Entity; - using IndexType = typename GridView::IndexSet::IndexType; - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - using Stencil = std::vector; - using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); - - enum{ enableFluxVarsCache = GET_PROP_VALUE(TypeTag, EnableFluxVariablesCache) }; - -public: - PorousMediumFluxVariablesBase() : problemPtr_(nullptr), scvFacePtr_(nullptr) - {} - - void init(const Problem& problem, - const Element& element, - const SubControlVolumeFace &scvFace) - { - problemPtr_ = &problem; - scvFacePtr_ = &scvFace; - - // update the stencil if needed - if (!enableFluxVarsCache) - stencil_ = asImp_().computeStencil(problem, scvFace); - } - - // when caching is enabled, get the stencil from the cache class - template - const typename std::enable_if::type& stencil() const - { return problem().model().fluxVarsCache(scvFace()).stencil(); } - - // when caching is disabled, return the private stencil variable. The update(...) routine has to be called beforehand. - template - const typename std::enable_if::type& stencil() - { return stencil_; } - - const Problem& problem() const - { return *problemPtr_; } - - const SubControlVolumeFace& scvFace() const - { - return *scvFacePtr_; - } - - Stencil computeStencil(const Problem& problem, const SubControlVolumeFace& scvFace) - { DUNE_THROW(Dune::InvalidStateException, "computeStencil() routine is not provided by the implementation."); } - -private: - - Implementation &asImp_() - { - assert(static_cast(this) != 0); - return *static_cast(this); - } - - const Implementation &asImp_() const - { - assert(static_cast(this) != 0); - return *static_cast(this); - } - - const Problem *problemPtr_; //! Pointer to the problem - const SubControlVolumeFace *scvFacePtr_; //! Pointer to the sub control volume face for which the flux variables are created - Stencil stencil_; //! The flux stencil -}; - - - /*! * \ingroup ImplicitModel * \brief the flux variables class @@ -121,9 +46,9 @@ class PorousMediumFluxVariables {}; // specialization for pure advective flow (e.g. 1p/2p/3p immiscible darcy flow) template -class PorousMediumFluxVariables : public PorousMediumFluxVariablesBase> +class PorousMediumFluxVariables : public FluxVariablesBase> { - using ParentType = PorousMediumFluxVariablesBase>; + using ParentType = FluxVariablesBase>; using Problem = typename GET_PROP_TYPE(TypeTag, Problem); using GridView = typename GET_PROP_TYPE(TypeTag, GridView); using Element = typename GridView::template Codim<0>::Entity; @@ -170,9 +95,9 @@ public: // specialization for isothermal advection molecularDiffusion equations template -class PorousMediumFluxVariables : public PorousMediumFluxVariablesBase> +class PorousMediumFluxVariables : public FluxVariablesBase> { - using ParentType = PorousMediumFluxVariablesBase>; + using ParentType = FluxVariablesBase>; using Problem = typename GET_PROP_TYPE(TypeTag, Problem); using GridView = typename GET_PROP_TYPE(TypeTag, GridView); using Element = typename GridView::template Codim<0>::Entity; -- GitLab From acf6341d7c69beca9415f16300877ba31eb276d5 Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Mon, 20 Jun 2016 16:42:12 +0200 Subject: [PATCH 03/45] [implicit] introduce flags for discretization method Each discretization method (Box, CCTpfa, Mpfa etc) now has a corresponding flag which is set as a property. This allows a specialization of the used constitutive laws for the different methods. For a model it is thus no longer necessary to define additional typetags for the different discretization methods. On the problem level one can simply derive from the discretization method's typetag and the model type tag. Additional method-dependend classes are automatically set via the DiscretizationMethod property in the form of template specializations --- dumux/implicit/box/propertydefaults.hh | 15 +- .../cellcentered/tpfa/propertydefaults.hh | 15 +- dumux/implicit/properties.hh | 3 + dumux/implicit/propertydefaults.hh | 26 +++ dumux/porousmediumflow/CMakeLists.txt | 5 +- .../compositional/CMakeLists.txt | 4 + .../constitutivelaws/CMakeLists.txt | 5 + .../box => constitutivelaws}/darcyslaw.hh | 176 ++++++++++++++- .../box => constitutivelaws}/fickslaw.hh | 142 +++++++++++- .../immiscible/CMakeLists.txt | 4 + .../implicit/cellcentered/tpfa/darcyslaw.hh | 210 ------------------ .../implicit/cellcentered/tpfa/fickslaw.hh | 178 --------------- 12 files changed, 360 insertions(+), 423 deletions(-) create mode 100644 dumux/porousmediumflow/compositional/CMakeLists.txt create mode 100644 dumux/porousmediumflow/constitutivelaws/CMakeLists.txt rename dumux/porousmediumflow/{implicit/box => constitutivelaws}/darcyslaw.hh (55%) rename dumux/porousmediumflow/{implicit/box => constitutivelaws}/fickslaw.hh (61%) create mode 100644 dumux/porousmediumflow/immiscible/CMakeLists.txt delete mode 100644 dumux/porousmediumflow/implicit/cellcentered/tpfa/darcyslaw.hh delete mode 100644 dumux/porousmediumflow/implicit/cellcentered/tpfa/fickslaw.hh diff --git a/dumux/implicit/box/propertydefaults.hh b/dumux/implicit/box/propertydefaults.hh index bc4eff8b9d..dd54544541 100644 --- a/dumux/implicit/box/propertydefaults.hh +++ b/dumux/implicit/box/propertydefaults.hh @@ -29,8 +29,6 @@ #include #include #include -#include -#include #include "elementboundarytypes.hh" #include "localresidual.hh" @@ -49,6 +47,9 @@ template class BoxFVElementGeometryVector; template class BoxStencilsVector; namespace Properties { +//! Set the corresponding discretization method property +SET_INT_PROP(BoxModel, DiscretizationMethod, GET_PROP(TypeTag, DiscretizationMethods)::Box); + //! Set the default for the FVElementGeometry vector SET_TYPE_PROP(BoxModel, FVElementGeometryVector, BoxFVElementGeometryVector); @@ -79,16 +80,6 @@ public: typedef Dumux::SubControlVolumeFace type; }; -//! The darcy flux variables -SET_TYPE_PROP(BoxModel, AdvectionType, Dumux::BoxDarcysLaw); - -// TODO: Actually implement the diffusion and energy flux variables -//! The diffusion flux variables -SET_TYPE_PROP(BoxModel, MolecularDiffusionType, Dumux::BoxFicksLaw); - -//! The energy flux variables -//SET_TYPE_PROP(BoxModel, HeatConductionType, BoxFouriersLaw); - //! Set the default for the ElementBoundaryTypes SET_TYPE_PROP(BoxModel, ElementBoundaryTypes, Dumux::BoxElementBoundaryTypes); diff --git a/dumux/implicit/cellcentered/tpfa/propertydefaults.hh b/dumux/implicit/cellcentered/tpfa/propertydefaults.hh index 3977efcfbb..ba64a98d76 100644 --- a/dumux/implicit/cellcentered/tpfa/propertydefaults.hh +++ b/dumux/implicit/cellcentered/tpfa/propertydefaults.hh @@ -32,8 +32,6 @@ #include #include #include -#include -#include namespace Dumux { @@ -41,6 +39,9 @@ namespace Dumux { template class CCElementBoundaryTypes; namespace Properties { +//! Set the corresponding discretization method property +SET_INT_PROP(CCTpfaModel, DiscretizationMethod, GET_PROP(TypeTag, DiscretizationMethods)::CCTpfa); + //! Set the default for the FVElementGeometry vector SET_TYPE_PROP(CCTpfaModel, FVElementGeometryVector, CCTpfaFVElementGeometryVector); @@ -68,16 +69,6 @@ public: //! The flux variables cache class, by default the one for porous media SET_TYPE_PROP(CCTpfaModel, FluxVariablesCache, Dumux::CCTpfaPorousMediumFluxVariablesCache); -//! The darcy flux variables -SET_TYPE_PROP(CCTpfaModel, AdvectionType, Dumux::CCTpfaDarcysLaw); - -// TODO: Actually implement the diffusion and energy flux variables -//! The diffusion flux variables -SET_TYPE_PROP(CCTpfaModel, MolecularDiffusionType, Dumux::CCTpfaFicksLaw); - -//! The energy flux variables -//SET_TYPE_PROP(CCTpfaModel, HeatConductionType, CCTpfaFouriersLaw); - } // namespace Properties } // namespace Dumux diff --git a/dumux/implicit/properties.hh b/dumux/implicit/properties.hh index cb9e36510f..f766aa411b 100644 --- a/dumux/implicit/properties.hh +++ b/dumux/implicit/properties.hh @@ -83,6 +83,9 @@ NEW_PROP_TAG(EnableFluxVariablesCache); //! specifies if data on flux vars shoul NEW_PROP_TAG(BoundaryVariables); //!< Data required to calculate fluxes over boundary faces in cc models(outflow) NEW_PROP_TAG(ConstantBoundaryConditions); //!< boundary data is stored in case the BC are constant +NEW_PROP_TAG(DiscretizationMethods); //!< Contains all the available discretization methods +NEW_PROP_TAG(DiscretizationMethod); //!< Property for the used discretization method + // Specify the forms of fluxes that should be considered in the model // also, specify their corresponding flux variables NEW_PROP_TAG(EnableAdvection); //! specifies if advection is considered in the model diff --git a/dumux/implicit/propertydefaults.hh b/dumux/implicit/propertydefaults.hh index 5bf7a7ddd2..3ba11dd9e2 100644 --- a/dumux/implicit/propertydefaults.hh +++ b/dumux/implicit/propertydefaults.hh @@ -38,6 +38,9 @@ #include #include +#include +#include + #include "properties.hh" #include "model.hh" #include "assembler.hh" @@ -58,6 +61,20 @@ namespace Properties { // Some defaults for very fundamental properties ////////////////////////////////////////////////////////////////// +//! All the available discretization methods +SET_PROP(ImplicitBase, DiscretizationMethods) +{ + // Box-Method + static const int Box = 0; + // CC-Tpfa Method + static const int CCTpfa = 1; + // TODO: implement the other methods + // CC-NLTPFA? + // static const int CCNlTpfa = 2; + // CC-MPFA + // static const int CCMpfa = 3; +}; + //! Set the default type for the time manager SET_TYPE_PROP(ImplicitBase, TimeManager, Dumux::TimeManager); @@ -118,6 +135,15 @@ public: typedef Dumux::PorousMediumFluxVariables type; }; +//! We use darcys law as the default for the advective flux calculation +SET_TYPE_PROP(ImplicitBase, AdvectionType, Dumux::DarcysLaw); + +//! We use darcys law as the default for the deffusive flux calculation +SET_TYPE_PROP(ImplicitBase, MolecularDiffusionType, Dumux::FicksLaw); + +//! TODO: IMPLEMENT The energy flux çalculation law +//SET_TYPE_PROP(ImplicitBase, HeatConductionType, FouriersLaw); + //! The type of a solution for the whole grid at a fixed time SET_TYPE_PROP(ImplicitBase, SolutionVector, diff --git a/dumux/porousmediumflow/CMakeLists.txt b/dumux/porousmediumflow/CMakeLists.txt index 643a57f0ee..d0f9ee759a 100644 --- a/dumux/porousmediumflow/CMakeLists.txt +++ b/dumux/porousmediumflow/CMakeLists.txt @@ -9,8 +9,11 @@ add_subdirectory("2pncmin") add_subdirectory("3p") add_subdirectory("3p3c") add_subdirectory("co2") +add_subdirectory("compositional") +add_subdirectory("constitutivelaws") +add_subdirectory("immiscible") add_subdirectory("implicit") add_subdirectory("mpnc") add_subdirectory("nonisothermal") add_subdirectory("richards") -add_subdirectory("sequential") +add_subdirectory("sequential") \ No newline at end of file diff --git a/dumux/porousmediumflow/compositional/CMakeLists.txt b/dumux/porousmediumflow/compositional/CMakeLists.txt new file mode 100644 index 0000000000..11ccea7975 --- /dev/null +++ b/dumux/porousmediumflow/compositional/CMakeLists.txt @@ -0,0 +1,4 @@ +#install headers +install(FILES +primaryvariableswitch.hh +DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dumux/porousmediumflow/compositional) \ No newline at end of file diff --git a/dumux/porousmediumflow/constitutivelaws/CMakeLists.txt b/dumux/porousmediumflow/constitutivelaws/CMakeLists.txt new file mode 100644 index 0000000000..e5e8f670be --- /dev/null +++ b/dumux/porousmediumflow/constitutivelaws/CMakeLists.txt @@ -0,0 +1,5 @@ +#install headers +install(FILES +darcyslaw.hh +fickslaw.hh +DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dumux/porousmediumflow/constitutivelaws) \ No newline at end of file diff --git a/dumux/porousmediumflow/implicit/box/darcyslaw.hh b/dumux/porousmediumflow/constitutivelaws/darcyslaw.hh similarity index 55% rename from dumux/porousmediumflow/implicit/box/darcyslaw.hh rename to dumux/porousmediumflow/constitutivelaws/darcyslaw.hh index 92c3c3a73f..1cbe6b33e1 100644 --- a/dumux/porousmediumflow/implicit/box/darcyslaw.hh +++ b/dumux/porousmediumflow/constitutivelaws/darcyslaw.hh @@ -20,10 +20,10 @@ * \file * \brief This file contains the data which is required to calculate * volume and mass fluxes of fluid phases over a face of a finite volume by means - * of the Darcy approximation. + * of the Darcy approximation. Specializations are provided for the different discretization methods. */ -#ifndef DUMUX_BOX_DARCYS_LAW_HH -#define DUMUX_BOX_DARCYS_LAW_HH +#ifndef DUMUX_IMPLICIT_DARCYS_LAW_HH +#define DUMUX_IMPLICIT_DARCYS_LAW_HH #include @@ -46,12 +46,174 @@ NEW_PROP_TAG(ProblemEnableGravity); } /*! - * \ingroup BoxModel + * \ingroup DarcysLaw * \brief Evaluates the normal component of the Darcy velocity - * on a (sub)control volume face. + * on a (sub)control volume face. Specializations are provided + * for the different discretization methods. */ +template +class DarcysLaw +{}; + +// Specialization for the CC-Tpfa method template -class BoxDarcysLaw +class DarcysLaw::type > +{ + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, SubControlVolume) SubControlVolume; + typedef typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace) SubControlVolumeFace; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GridView::IndexSet::IndexType IndexType; + typedef std::vector Stencil; + + using Element = typename GridView::template Codim<0>::Entity; + enum { dim = GridView::dimension} ; + enum { dimWorld = GridView::dimensionworld} ; + enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases)} ; + + typedef Dune::FieldMatrix DimWorldMatrix; + typedef Dune::FieldVector GlobalPosition; + +public: + + static Scalar flux(const Problem& problem, + const SubControlVolumeFace& scvFace, + const IndexType phaseIdx) + { + const auto& tij = getTransmissibilities(problem, scvFace); + + // Get the inside volume variables + const auto insideScvIdx = scvFace.insideScvIdx(); + const auto& insideScv = problem.model().fvGeometries().subControlVolume(insideScvIdx); + const auto& insideVolVars = problem.model().curVolVars(insideScv); + + // and the outside volume variables + const auto& outsideVolVars = problem.model().curVolVars(scvFace.outsideScvIdx()); + + auto hInside = insideVolVars.pressure(phaseIdx); + auto hOutside = outsideVolVars.pressure(phaseIdx); + + if (GET_PARAM_FROM_GROUP(TypeTag, bool, Problem, EnableGravity)) + { + // do averaging for the density + const auto rhoInside = insideVolVars.density(phaseIdx); + const auto rhoOutide = outsideVolVars.density(phaseIdx); + const auto rho = (rhoInside + rhoOutide)*0.5; + + + // ask for the gravitational acceleration in the inside neighbor + const auto xInside = insideScv.center(); + const auto gInside = problem.gravityAtPos(xInside); + + hInside -= rho*(gInside*xInside); + + // and the outside neighbor + if (scvFace.boundary()) + { + const auto xOutside = scvFace.center(); + const auto gOutside = problem.gravityAtPos(xOutside); + hOutside -= rho*(gOutside*xOutside); + } + else + { + const auto outsideScvIdx = scvFace.outsideScvIdx(); + const auto& outsideScv = problem.model().fvGeometries().subControlVolume(outsideScvIdx); + const auto xOutside = outsideScv.center(); + const auto gOutside = problem.gravityAtPos(xOutside); + hOutside -= rho*(gOutside*xOutside); + } + } + + return tij*(hInside - hOutside); + } + + static Stencil stencil(const Problem& problem, const SubControlVolumeFace& scvFace) + { + std::vector stencil; + if (!scvFace.boundary()) + { + stencil.push_back(scvFace.insideScvIdx()); + stencil.push_back(scvFace.outsideScvIdx()); + } + else + stencil.push_back(scvFace.insideScvIdx()); + + return stencil; + } + + template + static const typename std::enable_if::type& getTransmissibilities(const Problem& problem, const SubControlVolumeFace& scvFace) + { + return problem.model().fluxVarsCache(scvFace).tij(); + } + + template + static const typename std::enable_if::type getTransmissibilities(const Problem& problem, const SubControlVolumeFace& scvFace) + { + return calculateTransmissibilities(problem, scvFace); + } + + static Scalar calculateTransmissibilities(const Problem& problem, const SubControlVolumeFace& scvFace) + { + Scalar tij; + + const auto insideScvIdx = scvFace.insideScvIdx(); + const auto& insideScv = problem.model().fvGeometries().subControlVolume(insideScvIdx); + const auto insideK = problem.spatialParams().intrinsicPermeability(insideScv); + Scalar ti = calculateOmega_(problem, scvFace, insideK, insideScv); + + if (!scvFace.boundary()) + { + const auto outsideScvIdx = scvFace.outsideScvIdx(); + const auto& outsideScv = problem.model().fvGeometries().subControlVolume(outsideScvIdx); + const auto outsideK = problem.spatialParams().intrinsicPermeability(outsideScv); + Scalar tj = -1.0*calculateOmega_(problem, scvFace, outsideK, outsideScv); + + tij = scvFace.area()*(ti * tj)/(ti + tj); + } + else + { + tij = scvFace.area()*ti; + } + + return tij; + } + +private: + + static Scalar calculateOmega_(const Problem& problem, const SubControlVolumeFace& scvFace, const DimWorldMatrix &K, const SubControlVolume &scv) + { + GlobalPosition Knormal; + K.mv(scvFace.unitOuterNormal(), Knormal); + + auto distanceVector = scvFace.center(); + distanceVector -= scv.center(); + distanceVector /= distanceVector.two_norm2(); + + Scalar omega = Knormal * distanceVector; + omega *= problem.model().curVolVars(scv).extrusionFactor(); + + return omega; + } + + static Scalar calculateOmega_(const Problem& problem, const SubControlVolumeFace& scvFace, Scalar K, const SubControlVolume &scv) + { + auto distanceVector = scvFace.center(); + distanceVector -= scv.center(); + distanceVector /= distanceVector.two_norm2(); + + Scalar omega = K * (distanceVector * scvFace.unitOuterNormal()); + omega *= problem.model().curVolVars(scv).extrusionFactor(); + + return omega; + } +}; + +// Specialization for the Box Method +template +class DarcysLaw::type > { using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); using Problem = typename GET_PROP_TYPE(TypeTag, Problem); @@ -76,6 +238,8 @@ public: const Element& element, const SubControlVolumeFace& scvFace) { + DUNE_THROW(Dune::NotImplemented, "Darcy's law for the Box method is not yet implemented!"); + problemPtr_ = &problem; scvFacePtr_ = &scvFace; elementPtr_ = &element; diff --git a/dumux/porousmediumflow/implicit/box/fickslaw.hh b/dumux/porousmediumflow/constitutivelaws/fickslaw.hh similarity index 61% rename from dumux/porousmediumflow/implicit/box/fickslaw.hh rename to dumux/porousmediumflow/constitutivelaws/fickslaw.hh index 986239a1c2..148c80f224 100644 --- a/dumux/porousmediumflow/implicit/box/fickslaw.hh +++ b/dumux/porousmediumflow/constitutivelaws/fickslaw.hh @@ -21,8 +21,8 @@ * \brief This file contains the data which is required to calculate * diffusive mass fluxes due to molecular diffusion with Fick's law. */ -#ifndef DUMUX_BOX_FICKS_LAW_HH -#define DUMUX_BOX_FICKS_LAW_HH +#ifndef DUMUX_IMPLICIT_FICKS_LAW_HH +#define DUMUX_IMPLICIT_FICKS_LAW_HH #include @@ -44,11 +44,143 @@ NEW_PROP_TAG(EffectiveDiffusivityModel); } /*! - * \ingroup BoxModel + * \ingroup CCTpfaFicksLaw * \brief Evaluates the diffusive mass flux according to Fick's law */ +template +class FicksLaw +{}; + +// Specialization for the CC-Tpfa Method +template +class FicksLaw::type > +{ + 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, EffectiveDiffusivityModel) EffDiffModel; + typedef typename GET_PROP_TYPE(TypeTag, SubControlVolume) SubControlVolume; + typedef typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace) SubControlVolumeFace; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GridView::IndexSet::IndexType IndexType; + typedef typename std::vector Stencil; + + using Element = typename GridView::template Codim<0>::Entity; + + enum { dim = GridView::dimension} ; + enum { dimWorld = GridView::dimensionworld} ; + enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases)} ; + + typedef Dune::FieldMatrix DimWorldMatrix; + typedef Dune::FieldVector GlobalPosition; + +public: + + static Scalar flux(const Problem& problem, + const SubControlVolumeFace& scvFace, + const int phaseIdx, + const int compIdx) + { + // diffusion tensors are always solution dependent + Scalar tij = calculateTransmissibility_(problem, scvFace, phaseIdx, compIdx); + + // Get the inside volume variables + const auto insideScvIdx = scvFace.insideScvIdx(); + const auto& insideScv = problem.model().fvGeometries().subControlVolume(insideScvIdx); + const auto& insideVolVars = problem.model().curVolVars(insideScv); + + // and the outside volume variables + const auto& outsideVolVars = problem.model().curVolVars(scvFace.outsideScvIdx()); + + // compute the diffusive flux + const auto xInside = insideVolVars.moleFraction(phaseIdx, compIdx); + const auto xOutside = outsideVolVars.moleFraction(phaseIdx, compIdx); + const auto rho = 0.5*(insideVolVars.molarDensity(phaseIdx) + outsideVolVars.molarDensity(phaseIdx)); + + return rho*tij*(xInside - xOutside); + } + + static Stencil stencil(const Problem& problem, const SubControlVolumeFace& scvFace) + { + std::vector stencil; + stencil.clear(); + if (!scvFace.boundary()) + { + stencil.push_back(scvFace.insideScvIdx()); + stencil.push_back(scvFace.outsideScvIdx()); + } + else + stencil.push_back(scvFace.insideScvIdx()); + + return stencil; + } + +private: + + + static Scalar calculateTransmissibility_(const Problem& problem, const SubControlVolumeFace& scvFace, const int phaseIdx, const int compIdx) + { + Scalar tij; + + const auto insideScvIdx = scvFace.insideScvIdx(); + const auto& insideScv = problem.model().fvGeometries().subControlVolume(insideScvIdx); + const auto& insideVolVars = problem.model().curVolVars(insideScvIdx); + + auto insideD = insideVolVars.diffusionCoefficient(phaseIdx, compIdx); + insideD = EffDiffModel::effectiveDiffusivity(insideVolVars.porosity(), insideVolVars.saturation(phaseIdx), insideD); + Scalar ti = calculateOmega_(problem, scvFace, insideD, insideScv); + + if (!scvFace.boundary()) + { + const auto outsideScvIdx = scvFace.outsideScvIdx(); + const auto& outsideScv = problem.model().fvGeometries().subControlVolume(outsideScvIdx); + const auto& outsideVolVars = problem.model().curVolVars(outsideScvIdx); + + auto outsideD = outsideVolVars.diffusionCoefficient(phaseIdx, compIdx); + outsideD = EffDiffModel::effectiveDiffusivity(outsideVolVars.porosity(), outsideVolVars.saturation(phaseIdx), outsideD); + Scalar tj = -1.0*calculateOmega_(problem, scvFace, outsideD, outsideScv); + + tij = scvFace.area()*(ti * tj)/(ti + tj); + } + else + { + tij = scvFace.area()*ti; + } + + return tij; + } + + static Scalar calculateOmega_(const Problem& problem, const SubControlVolumeFace& scvFace, const DimWorldMatrix &D, const SubControlVolume &scv) + { + GlobalPosition Dnormal; + D.mv(scvFace.unitOuterNormal(), Dnormal); + + auto distanceVector = scvFace.center(); + distanceVector -= scv.center(); + distanceVector /= distanceVector.two_norm2(); + + Scalar omega = Dnormal * distanceVector; + omega *= problem.model().curVolVars(scv).extrusionFactor(); + + return omega; + } + + static Scalar calculateOmega_(const Problem& problem, const SubControlVolumeFace& scvFace, Scalar D, const SubControlVolume &scv) + { + auto distanceVector = scvFace.center(); + distanceVector -= scv.center(); + distanceVector /= distanceVector.two_norm2(); + + Scalar omega = D * (distanceVector * scvFace.unitOuterNormal()); + omega *= problem.model().curVolVars(scv).extrusionFactor(); + + return omega; + } +}; + +// Specialization for the Box Method template -class BoxFicksLaw +class FicksLaw::type > { using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); using Problem = typename GET_PROP_TYPE(TypeTag, Problem); @@ -76,6 +208,8 @@ public: const SubControlVolumeFace &scvFace, int phaseIdx, int compIdx) { + DUNE_THROW(Dune::NotImplemented, "Fick's law for the Box method is not yet implemented!"); + problemPtr_ = &problem; scvFacePtr_ = &scvFace; diff --git a/dumux/porousmediumflow/immiscible/CMakeLists.txt b/dumux/porousmediumflow/immiscible/CMakeLists.txt new file mode 100644 index 0000000000..e135fd5d78 --- /dev/null +++ b/dumux/porousmediumflow/immiscible/CMakeLists.txt @@ -0,0 +1,4 @@ +#install headers +install(FILES +localresidual.hh +DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dumux/porousmediumflow/immiscible) \ No newline at end of file diff --git a/dumux/porousmediumflow/implicit/cellcentered/tpfa/darcyslaw.hh b/dumux/porousmediumflow/implicit/cellcentered/tpfa/darcyslaw.hh deleted file mode 100644 index 49a35b14d0..0000000000 --- a/dumux/porousmediumflow/implicit/cellcentered/tpfa/darcyslaw.hh +++ /dev/null @@ -1,210 +0,0 @@ -// -*- 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 . * - *****************************************************************************/ -/*! - * \file - * \brief This file contains the data which is required to calculate - * volume and mass fluxes of fluid phases over a face of a finite volume by means - * of the Darcy approximation. - */ -#ifndef DUMUX_CC_TPFA_DARCYS_LAW_HH -#define DUMUX_CC_TPFA_DARCYS_LAW_HH - -#include - -#include - -#include -#include - -#include - - -namespace Dumux -{ - -namespace Properties -{ -// forward declaration of properties -NEW_PROP_TAG(NumPhases); -NEW_PROP_TAG(ProblemEnableGravity); -} - -/*! - * \ingroup CCTpfaDarcysLaw - * \brief Evaluates the normal component of the Darcy velocity - * on a (sub)control volume face. - */ -template -class CCTpfaDarcysLaw -{ - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, SubControlVolume) SubControlVolume; - typedef typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace) SubControlVolumeFace; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GridView::IndexSet::IndexType IndexType; - typedef std::vector Stencil; - - using Element = typename GridView::template Codim<0>::Entity; - enum { dim = GridView::dimension} ; - enum { dimWorld = GridView::dimensionworld} ; - enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases)} ; - - typedef Dune::FieldMatrix DimWorldMatrix; - typedef Dune::FieldVector GlobalPosition; - -public: - - static Scalar flux(const Problem& problem, - const SubControlVolumeFace& scvFace, - const IndexType phaseIdx) - { - const auto& tij = getTransmissibilities(problem, scvFace); - - // Get the inside volume variables - const auto insideScvIdx = scvFace.insideScvIdx(); - const auto& insideScv = problem.model().fvGeometries().subControlVolume(insideScvIdx); - const auto& insideVolVars = problem.model().curVolVars(insideScv); - - // and the outside volume variables - const auto& outsideVolVars = problem.model().curVolVars(scvFace.outsideScvIdx()); - - auto hInside = insideVolVars.pressure(phaseIdx); - auto hOutside = outsideVolVars.pressure(phaseIdx); - - if (GET_PARAM_FROM_GROUP(TypeTag, bool, Problem, EnableGravity)) - { - // do averaging for the density - const auto rhoInside = insideVolVars.density(phaseIdx); - const auto rhoOutide = outsideVolVars.density(phaseIdx); - const auto rho = (rhoInside + rhoOutide)*0.5; - - - // ask for the gravitational acceleration in the inside neighbor - const auto xInside = insideScv.center(); - const auto gInside = problem.gravityAtPos(xInside); - - hInside -= rho*(gInside*xInside); - - // and the outside neighbor - if (scvFace.boundary()) - { - const auto xOutside = scvFace.center(); - const auto gOutside = problem.gravityAtPos(xOutside); - hOutside -= rho*(gOutside*xOutside); - } - else - { - const auto outsideScvIdx = scvFace.outsideScvIdx(); - const auto& outsideScv = problem.model().fvGeometries().subControlVolume(outsideScvIdx); - const auto xOutside = outsideScv.center(); - const auto gOutside = problem.gravityAtPos(xOutside); - hOutside -= rho*(gOutside*xOutside); - } - } - - return tij*(hInside - hOutside); - } - - static Stencil stencil(const Problem& problem, const SubControlVolumeFace& scvFace) - { - std::vector stencil; - if (!scvFace.boundary()) - { - stencil.push_back(scvFace.insideScvIdx()); - stencil.push_back(scvFace.outsideScvIdx()); - } - else - stencil.push_back(scvFace.insideScvIdx()); - - return stencil; - } - - template - static const typename std::enable_if::type& getTransmissibilities(const Problem& problem, const SubControlVolumeFace& scvFace) - { - return problem.model().fluxVarsCache(scvFace).tij(); - } - - template - static const typename std::enable_if::type getTransmissibilities(const Problem& problem, const SubControlVolumeFace& scvFace) - { - return calculateTransmissibilities(problem, scvFace); - } - - static Scalar calculateTransmissibilities(const Problem& problem, const SubControlVolumeFace& scvFace) - { - Scalar tij; - - const auto insideScvIdx = scvFace.insideScvIdx(); - const auto& insideScv = problem.model().fvGeometries().subControlVolume(insideScvIdx); - const auto insideK = problem.spatialParams().intrinsicPermeability(insideScv); - Scalar ti = calculateOmega_(problem, scvFace, insideK, insideScv); - - if (!scvFace.boundary()) - { - const auto outsideScvIdx = scvFace.outsideScvIdx(); - const auto& outsideScv = problem.model().fvGeometries().subControlVolume(outsideScvIdx); - const auto outsideK = problem.spatialParams().intrinsicPermeability(outsideScv); - Scalar tj = -1.0*calculateOmega_(problem, scvFace, outsideK, outsideScv); - - tij = scvFace.area()*(ti * tj)/(ti + tj); - } - else - { - tij = scvFace.area()*ti; - } - - return tij; - } - -private: - - static Scalar calculateOmega_(const Problem& problem, const SubControlVolumeFace& scvFace, const DimWorldMatrix &K, const SubControlVolume &scv) - { - GlobalPosition Knormal; - K.mv(scvFace.unitOuterNormal(), Knormal); - - auto distanceVector = scvFace.center(); - distanceVector -= scv.center(); - distanceVector /= distanceVector.two_norm2(); - - Scalar omega = Knormal * distanceVector; - omega *= problem.model().curVolVars(scv).extrusionFactor(); - - return omega; - } - - static Scalar calculateOmega_(const Problem& problem, const SubControlVolumeFace& scvFace, Scalar K, const SubControlVolume &scv) - { - auto distanceVector = scvFace.center(); - distanceVector -= scv.center(); - distanceVector /= distanceVector.two_norm2(); - - Scalar omega = K * (distanceVector * scvFace.unitOuterNormal()); - omega *= problem.model().curVolVars(scv).extrusionFactor(); - - return omega; - } -}; - -} // end namespace - -#endif diff --git a/dumux/porousmediumflow/implicit/cellcentered/tpfa/fickslaw.hh b/dumux/porousmediumflow/implicit/cellcentered/tpfa/fickslaw.hh deleted file mode 100644 index 309e438e81..0000000000 --- a/dumux/porousmediumflow/implicit/cellcentered/tpfa/fickslaw.hh +++ /dev/null @@ -1,178 +0,0 @@ -// -*- 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 . * - *****************************************************************************/ -/*! - * \file - * \brief This file contains the data which is required to calculate - * diffusive mass fluxes due to molecular diffusion with Fick's law. - */ -#ifndef DUMUX_CC_TPFA_FICKS_LAW_HH -#define DUMUX_CC_TPFA_FICKS_LAW_HH - -#include - -#include -#include - -#include - - -namespace Dumux -{ - -namespace Properties -{ -// forward declaration of properties -NEW_PROP_TAG(NumPhases); -NEW_PROP_TAG(FluidSystem); -NEW_PROP_TAG(EffectiveDiffusivityModel); -} - -/*! - * \ingroup CCTpfaFicksLaw - * \brief Evaluates the diffusive mass flux according to Fick's law - */ -template -class CCTpfaFicksLaw -{ - 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, EffectiveDiffusivityModel) EffDiffModel; - typedef typename GET_PROP_TYPE(TypeTag, SubControlVolume) SubControlVolume; - typedef typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace) SubControlVolumeFace; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GridView::IndexSet::IndexType IndexType; - typedef typename std::vector Stencil; - - using Element = typename GridView::template Codim<0>::Entity; - - enum { dim = GridView::dimension} ; - enum { dimWorld = GridView::dimensionworld} ; - enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases)} ; - - typedef Dune::FieldMatrix DimWorldMatrix; - typedef Dune::FieldVector GlobalPosition; - -public: - - static Scalar flux(const Problem& problem, - const SubControlVolumeFace& scvFace, - const int phaseIdx, - const int compIdx) - { - // diffusion tensors are always solution dependent - Scalar tij = calculateTransmissibility_(problem, scvFace, phaseIdx, compIdx); - - // Get the inside volume variables - const auto insideScvIdx = scvFace.insideScvIdx(); - const auto& insideScv = problem.model().fvGeometries().subControlVolume(insideScvIdx); - const auto& insideVolVars = problem.model().curVolVars(insideScv); - - // and the outside volume variables - const auto& outsideVolVars = problem.model().curVolVars(scvFace.outsideScvIdx()); - - // compute the diffusive flux - const auto xInside = insideVolVars.moleFraction(phaseIdx, compIdx); - const auto xOutside = outsideVolVars.moleFraction(phaseIdx, compIdx); - const auto rho = 0.5*(insideVolVars.molarDensity(phaseIdx) + outsideVolVars.molarDensity(phaseIdx)); - - return rho*tij*(xInside - xOutside); - } - - static Stencil stencil(const Problem& problem, const SubControlVolumeFace& scvFace) - { - std::vector stencil; - stencil.clear(); - if (!scvFace.boundary()) - { - stencil.push_back(scvFace.insideScvIdx()); - stencil.push_back(scvFace.outsideScvIdx()); - } - else - stencil.push_back(scvFace.insideScvIdx()); - - return stencil; - } - -private: - - - static Scalar calculateTransmissibility_(const Problem& problem, const SubControlVolumeFace& scvFace, const int phaseIdx, const int compIdx) - { - Scalar tij; - - const auto insideScvIdx = scvFace.insideScvIdx(); - const auto& insideScv = problem.model().fvGeometries().subControlVolume(insideScvIdx); - const auto& insideVolVars = problem.model().curVolVars(insideScvIdx); - - auto insideD = insideVolVars.diffusionCoefficient(phaseIdx, compIdx); - insideD = EffDiffModel::effectiveDiffusivity(insideVolVars.porosity(), insideVolVars.saturation(phaseIdx), insideD); - Scalar ti = calculateOmega_(problem, scvFace, insideD, insideScv); - - if (!scvFace.boundary()) - { - const auto outsideScvIdx = scvFace.outsideScvIdx(); - const auto& outsideScv = problem.model().fvGeometries().subControlVolume(outsideScvIdx); - const auto& outsideVolVars = problem.model().curVolVars(outsideScvIdx); - - auto outsideD = outsideVolVars.diffusionCoefficient(phaseIdx, compIdx); - outsideD = EffDiffModel::effectiveDiffusivity(outsideVolVars.porosity(), outsideVolVars.saturation(phaseIdx), outsideD); - Scalar tj = -1.0*calculateOmega_(problem, scvFace, outsideD, outsideScv); - - tij = scvFace.area()*(ti * tj)/(ti + tj); - } - else - { - tij = scvFace.area()*ti; - } - - return tij; - } - - static Scalar calculateOmega_(const Problem& problem, const SubControlVolumeFace& scvFace, const DimWorldMatrix &D, const SubControlVolume &scv) - { - GlobalPosition Dnormal; - D.mv(scvFace.unitOuterNormal(), Dnormal); - - auto distanceVector = scvFace.center(); - distanceVector -= scv.center(); - distanceVector /= distanceVector.two_norm2(); - - Scalar omega = Dnormal * distanceVector; - omega *= problem.model().curVolVars(scv).extrusionFactor(); - - return omega; - } - - static Scalar calculateOmega_(const Problem& problem, const SubControlVolumeFace& scvFace, Scalar D, const SubControlVolume &scv) - { - auto distanceVector = scvFace.center(); - distanceVector -= scv.center(); - distanceVector /= distanceVector.two_norm2(); - - Scalar omega = D * (distanceVector * scvFace.unitOuterNormal()); - omega *= problem.model().curVolVars(scv).extrusionFactor(); - - return omega; - } -}; - -} // end namespace - -#endif -- GitLab From ac20ff2680d7b04348fdd5c5c99378e5287b717a Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Mon, 20 Jun 2016 16:50:28 +0200 Subject: [PATCH 04/45] [pmflow][constlaws] fix include-guards --- dumux/porousmediumflow/constitutivelaws/darcyslaw.hh | 4 ++-- dumux/porousmediumflow/constitutivelaws/fickslaw.hh | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dumux/porousmediumflow/constitutivelaws/darcyslaw.hh b/dumux/porousmediumflow/constitutivelaws/darcyslaw.hh index 1cbe6b33e1..bdd907a423 100644 --- a/dumux/porousmediumflow/constitutivelaws/darcyslaw.hh +++ b/dumux/porousmediumflow/constitutivelaws/darcyslaw.hh @@ -22,8 +22,8 @@ * volume and mass fluxes of fluid phases over a face of a finite volume by means * of the Darcy approximation. Specializations are provided for the different discretization methods. */ -#ifndef DUMUX_IMPLICIT_DARCYS_LAW_HH -#define DUMUX_IMPLICIT_DARCYS_LAW_HH +#ifndef DUMUX_POROUSMEDIUMFLOW_DARCYS_LAW_HH +#define DUMUX_POROUSMEDIUMFLOW_DARCYS_LAW_HH #include diff --git a/dumux/porousmediumflow/constitutivelaws/fickslaw.hh b/dumux/porousmediumflow/constitutivelaws/fickslaw.hh index 148c80f224..830fbab91a 100644 --- a/dumux/porousmediumflow/constitutivelaws/fickslaw.hh +++ b/dumux/porousmediumflow/constitutivelaws/fickslaw.hh @@ -21,8 +21,8 @@ * \brief This file contains the data which is required to calculate * diffusive mass fluxes due to molecular diffusion with Fick's law. */ -#ifndef DUMUX_IMPLICIT_FICKS_LAW_HH -#define DUMUX_IMPLICIT_FICKS_LAW_HH +#ifndef DUMUX_POROUSMEDIUMFLOW_FICKS_LAW_HH +#define DUMUX_POROUSMEDIUMFLOW_FICKS_LAW_HH #include -- GitLab From ea3719bf47bc55b2575fd56693eddd4d22475741 Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Mon, 20 Jun 2016 17:21:15 +0200 Subject: [PATCH 05/45] [geomechanics][elastic] implement elastic model in new structure This commit introduces the necessary changes and new classes for a cctpfa elastic model. Checking the results suggest, that a simple tpfa scheme is not suitable for linear elasticity, not even on structured grids. It is thus questionable wether or not this implementation will be deleted in the future. Note that it only works in 2d so far. --- dumux/geomechanics/CMakeLists.txt | 2 + .../constitutivelaws/CMakeLists.txt | 5 + .../constitutivelaws/hookeslaw.hh | 313 ++++++++++++++++++ dumux/geomechanics/elastic/localresidual.hh | 57 +--- dumux/geomechanics/elastic/model.hh | 124 +++---- dumux/geomechanics/elastic/properties.hh | 4 +- .../geomechanics/elastic/propertydefaults.hh | 46 ++- dumux/geomechanics/elastic/volumevariables.hh | 14 +- dumux/geomechanics/implicit/CMakeLists.txt | 4 + .../geomechanics/implicit/stressvariables.hh | 90 +++++ .../implicit/stressvariablescache.hh | 102 ++++++ .../elastic/elasticmatrixproblem.hh | 60 ++-- .../elastic/elasticspatialparams.hh | 29 +- .../elastic/grids/test_elastic.dgf | 6 +- test/geomechanics/elastic/test_elastic.input | 1 - 15 files changed, 675 insertions(+), 182 deletions(-) create mode 100644 dumux/geomechanics/constitutivelaws/CMakeLists.txt create mode 100644 dumux/geomechanics/constitutivelaws/hookeslaw.hh create mode 100644 dumux/geomechanics/implicit/CMakeLists.txt create mode 100644 dumux/geomechanics/implicit/stressvariables.hh create mode 100644 dumux/geomechanics/implicit/stressvariablescache.hh diff --git a/dumux/geomechanics/CMakeLists.txt b/dumux/geomechanics/CMakeLists.txt index 4b65e11703..317ac1cf35 100644 --- a/dumux/geomechanics/CMakeLists.txt +++ b/dumux/geomechanics/CMakeLists.txt @@ -1,3 +1,5 @@ add_subdirectory("el1p2c") add_subdirectory("el2p") add_subdirectory("elastic") +add_subdirectory("implicit") +add_subdirectory("constitutivelaws") \ No newline at end of file diff --git a/dumux/geomechanics/constitutivelaws/CMakeLists.txt b/dumux/geomechanics/constitutivelaws/CMakeLists.txt new file mode 100644 index 0000000000..513c666aee --- /dev/null +++ b/dumux/geomechanics/constitutivelaws/CMakeLists.txt @@ -0,0 +1,5 @@ + +#install headers +install(FILES +hokeslaw.hh +DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dumux/geomechanics/constitutivelaws) diff --git a/dumux/geomechanics/constitutivelaws/hookeslaw.hh b/dumux/geomechanics/constitutivelaws/hookeslaw.hh new file mode 100644 index 0000000000..8e425a76f5 --- /dev/null +++ b/dumux/geomechanics/constitutivelaws/hookeslaw.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 . * + *****************************************************************************/ +/*! + * \file + * \brief This file contains the data which is required to calculate + * the mechanic stresses according to Hooke's law. + */ +#ifndef DUMUX_GEOMECHANICS_HOOKES_LAW_HH +#define DUMUX_GEOMECHANICS_HOOKES_LAW_HH + +#include + +#include +#include + +#include + + +namespace Dumux +{ + +namespace Properties +{ +// forward declaration of properties +} + +/*! + * \ingroup CCTpfaHookesLaw + * \brief Evaluates the stresses, tractions and compressions on a face according to Hooke's law. + * Specializations are given for the different discretization methods. + */ +template +class HookesLaw +{}; + +template +class HookesLaw::type > +{ + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, SubControlVolume) SubControlVolume; + typedef typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace) SubControlVolumeFace; + typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; + typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GridView::IndexSet::IndexType IndexType; + typedef typename std::vector Stencil; + typedef typename GridView::template Codim<0>::Entity Element; + + enum { dim = GridView::dimension} ; + static constexpr int voigtDim = 0.5*(dim*dim+dim); + + typedef Dune::FieldMatrix StiffnessMatrix; + typedef Dune::FieldVector VoigtVector; + typedef Dune::FieldMatrix DimMatrix; + typedef Dune::FieldVector DimVector; + + struct FaceData + { + Scalar insideLambda, insideMu; + DimVector insideAlpha, insideN, insideU; + + Scalar outsideLambda, outsideMu; + DimVector outsideAlpha, outsideN, outsideU; + + bool valueSet; + + FaceData() + { + valueSet = false; + } + }; + +public: + + static DimVector stressVector(const Problem& problem, const SubControlVolumeFace& scvFace) + { + DimMatrix sigma = calculateSigma_(problem, scvFace); + + // calculate Sigma*n + DimVector stressVec(0.0); + sigma.mv(scvFace.unitOuterNormal(), stressVec); + stressVec *= scvFace.area(); + + return stressVec; + } + + static DimMatrix stressTensor(const Problem& problem, const SubControlVolumeFace& scvFace) + { + return calculateSigma_(problem, scvFace); + } + + static Stencil stencil(const Problem& problem, const SubControlVolumeFace& scvFace) + { + std::vector stencil; + if (!scvFace.boundary()) + { + stencil.push_back(scvFace.insideScvIdx()); + stencil.push_back(scvFace.outsideScvIdx()); + } + else + stencil.push_back(scvFace.insideScvIdx()); + + return stencil; + } + + static DimMatrix calculateInversA(const Problem& problem, const SubControlVolumeFace& scvFace) + { + FaceData faceData = obtainFaceData_(problem, scvFace); + + DimMatrix inversA(0.0); + addEntriesToMatrix_(faceData.insideLambda, faceData.insideMu, faceData.insideAlpha, faceData.insideN, inversA); + addEntriesToMatrix_(faceData.outsideLambda, faceData.outsideMu, faceData.outsideAlpha, faceData.outsideN, inversA); + inversA.invert(); + + return inversA; + } + + static DimVector interpolateFaceDisplacement(const Problem& problem, const SubControlVolumeFace& scvFace) + { + FaceData faceData = obtainFaceData_(problem, scvFace); + return interpolateFaceDisplacement_(problem, scvFace, faceData); + } + +private: + + static FaceData obtainFaceData_(const Problem& problem, const SubControlVolumeFace& scvFace) + { + FaceData container; + + const auto insideScvIdx = scvFace.insideScvIdx(); + const auto& insideScv = problem.model().fvGeometries().subControlVolume(insideScvIdx); + const auto& insideVolVars = problem.model().curVolVars(insideScvIdx); + container.insideU = insideVolVars.displacement(); + container.insideLambda = insideVolVars.lambda(); + container.insideMu = insideVolVars.mu(); + container.insideN = scvFace.unitOuterNormal(); + container.insideAlpha = scvFace.center(); + container.insideAlpha -= insideScv.center(); + container.insideAlpha /= container.insideAlpha.two_norm2(); + + const auto outsideScvIdx = scvFace.outsideScvIdx(); + const auto& outsideVolVars = problem.model().curVolVars(outsideScvIdx); + container.outsideU = outsideVolVars.displacement(); + container.outsideLambda = outsideVolVars.lambda(); + container.outsideMu = outsideVolVars.mu(); + container.outsideN = scvFace.unitOuterNormal(); + container.outsideN *= -1; + if (scvFace.boundary()) + container.outsideAlpha = 0.0; + else + { + const auto& outsideScv = problem.model().fvGeometries().subControlVolume(outsideScvIdx); + container.outsideAlpha = scvFace.center(); + container.outsideAlpha -= outsideScv.center(); + container.outsideAlpha /= container.outsideAlpha.two_norm2(); + } + + container.valueSet = true; + + return container; + } + + static DimMatrix calculateSigma_(const Problem& problem, const SubControlVolumeFace& scvFace) + { + DimMatrix sigma(0.0); + StiffnessMatrix C(0.0); + VoigtVector voigtStrain(0.0); + VoigtVector voigtSigma(0.0); + + FaceData faceData = obtainFaceData_(problem, scvFace); + DimVector faceU = interpolateFaceDisplacement_(problem, scvFace, faceData); + + fillStiffnessMatrix_(C, faceData.insideLambda, faceData.insideMu); + fillStrainVector_(voigtStrain, faceData.insideAlpha, faceData.insideU, faceU); + + C.mv(voigtStrain, voigtSigma); + + if (dim == 2) + { + sigma[0][0] = voigtSigma[0]; + sigma[0][1] = voigtSigma[2]; + sigma[1][0] = voigtSigma[2]; + sigma[1][1] = voigtSigma[1]; + } + else + DUNE_THROW(Dune::NotImplemented, "dim = " << dim << " is not implemented yet"); + + return sigma; + } + + static DimVector interpolateFaceDisplacement_(const Problem& problem, const SubControlVolumeFace& scvFace, const FaceData& faceData, const bool oldSol = false) + { + DimVector faceU(0.0); + + if (!scvFace.boundary()) + { + DimMatrix inversA(0.0); + DimMatrix insideB(0.0); + DimMatrix outsideB(0.0); + + getInversA_(problem, scvFace, faceData, inversA); + addEntriesToMatrix_(faceData.insideLambda, faceData.insideMu, faceData.insideAlpha, faceData.insideN, insideB); + addEntriesToMatrix_(faceData.outsideLambda, faceData.outsideMu, faceData.outsideAlpha, faceData.outsideN, outsideB); + + DimVector insideTmp(0.0); + DimVector outsideTmp(0.0); + insideB.mv(faceData.insideU, insideTmp); + outsideB.mv(faceData.outsideU, outsideTmp); + + insideTmp += outsideTmp; + + inversA.mv(insideTmp, faceU); + } + else + { + if (!oldSol) + { + try { return problem.model().curVolVars(scvFace.outsideScvIdx()).displacement(); } + catch (Dune::Exception& e) + { + DUNE_THROW(Dune::InvalidStateException, "Error ocurred during the displacement interpolation on a boundary scv face. Only call this method on inner scv faces or pure Dirichlet boundaries with the volvars bound to the element"); + } + } + else + { + // TODO + DUNE_THROW(Dune::NotImplemented, "Reconstruction of the previous boundary vol vars not yet implemented"); + } + } + + return faceU; + } + + template + static typename std::enable_if::type getInversA_(const Problem& problem, + const SubControlVolumeFace& scvFace, + const FaceData& faceData, + DimMatrix& inversA) + { inversA = problem.model().fluxVarsCache(scvFace).inversA(); } + + template + static typename std::enable_if::type getInversA_(const Problem& problem, + const SubControlVolumeFace& scvFace, + const FaceData& faceData, + DimMatrix& inversA) + { + addEntriesToMatrix_(faceData.insideLambda, faceData.insideMu, faceData.insideAlpha, faceData.insideN, inversA); + addEntriesToMatrix_(faceData.outsideLambda, faceData.outsideMu, faceData.outsideAlpha, faceData.outsideN, inversA); + inversA.invert(); + } + + static void addEntriesToMatrix_(const Scalar lambda, const Scalar mu, const DimVector& alpha, const DimVector& normal, DimMatrix& matrix) + { + if (dim == 2) + { + matrix[0][0] += (lambda + 2*mu)*alpha[0]*normal[0] + mu*alpha[1]*normal[1]; + matrix[0][1] += lambda*alpha[1]*normal[0] + mu*alpha[0]*normal[1]; + matrix[1][0] += mu*alpha[1]*normal[0] + lambda*alpha[0]*normal[1]; + matrix[1][1] += mu*alpha[0]*normal[0] + (lambda + 2*mu)*alpha[1]*normal[1]; + } + else + DUNE_THROW(Dune::NotImplemented, "dim = " << dim << " is not implemented yet"); + } + + static void fillStiffnessMatrix_(StiffnessMatrix& C, const Scalar lambda, const Scalar mu) + { + if (dim == 2) + { + C[0][0] = lambda + 2*mu; + C[0][1] = lambda; + C[0][2] = 0.0; + + C[1][0] = lambda; + C[1][1] = lambda + 2*mu; + C[1][2] = 0.0; + + C[2][0] = 0.0; + C[2][1] = 0.0; + C[2][2] = mu; + } + } + + static void fillStrainVector_(VoigtVector& strain, const DimVector& alpha, const DimVector& insideU, const DimVector& faceU) + { + if (dim == 2) + { + strain[0] = alpha[0]*(faceU[0] - insideU[0]); + strain[1] = alpha[1]*(faceU[1] - insideU[1]); + strain[2] = alpha[1]*(faceU[0] - insideU[0]) + alpha[0]*(faceU[1] - insideU[1]); + } + } +}; + +} // end namespace + +#endif diff --git a/dumux/geomechanics/elastic/localresidual.hh b/dumux/geomechanics/elastic/localresidual.hh index 02ea2af62d..9c8589d064 100644 --- a/dumux/geomechanics/elastic/localresidual.hh +++ b/dumux/geomechanics/elastic/localresidual.hh @@ -43,6 +43,7 @@ template class ElasticLocalResidual : public GET_PROP_TYPE(TypeTag, BaseLocalResidual) { protected: + typedef typename GET_PROP_TYPE(TypeTag, BaseLocalResidual) ParentType; typedef typename GET_PROP_TYPE(TypeTag, LocalResidual) Implementation; typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; @@ -52,8 +53,9 @@ protected: 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, PrimaryVariables) PrimaryVariables; + typedef typename GET_PROP_TYPE(TypeTag, SubControlVolume) SubControlVolume; + typedef typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace) SubControlVolumeFace; typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; @@ -66,10 +68,10 @@ public: * \param scvIdx The index of the considered face of the sub-control volume * \param usePrevSol Evaluate function with solution of current or previous time step */ - void computeStorage(PrimaryVariables &storage, const int scvIdx, const bool usePrevSol) const + PrimaryVariables computeStorage(const SubControlVolume& scv, const VolumeVariables& volVars) const { // quasistationary conditions assumed - storage = Scalar(0); + return PrimaryVariables(0.0); } /*! @@ -81,28 +83,11 @@ public: * \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 int fIdx, const bool onBoundary=false) const + PrimaryVariables computeFlux(const SubControlVolumeFace& scvFace) const { - flux = 0; FluxVariables fluxVars; - fluxVars.update(this->problem_(), - this->element_(), - this->fvGeometry_(), - fIdx, - this->curVolVars_(), - onBoundary); - - // get normal vector of current face - const DimVector &normal(this->fvGeometry_().subContVolFace[fIdx].normal); - DimVector tmp(0.0); - - // multiply stress tensor with normal vector of current face - fluxVars.sigma().mv(normal, tmp); - - for (int i=0; i < dim; ++i) - { - flux[Indices::momentum(i)] = tmp[i]; - } + fluxVars.initAndComputeFluxes(this->problem_(), this->element_(), scvFace); + return fluxVars.stressVector(); } /*! @@ -111,27 +96,21 @@ public: * \param scvIdx The index of the vertex of the sub control volume * */ - void computeSource(PrimaryVariables &source, const int scvIdx) + PrimaryVariables computeSource(const SubControlVolume& scv) { - const ElementVolumeVariables &elemVolVars = this->curVolVars_(); - const VolumeVariables &volVars = elemVolVars[scvIdx]; + PrimaryVariables source(0.0); - this->problem_().solDependentSource(source, - this->element_(), - this->fvGeometry_(), - scvIdx, - this->curVolVars_()); + source += ParentType::computeSource(scv); - DimVector tmp1(0.0); - // gravity term of the momentum balance - // gravity of solid matrix - tmp1 = this->problem_().gravity(); - tmp1 *= volVars.rockDensity(); + // gravity term of the solid matrix in the momentum balance + DimVector gravityTerm(0.0); + gravityTerm = this->problem_().gravity(); + gravityTerm *= this->problem_().model().curVolVars(scv).rockDensity(); for (int i = 0; i < dim; ++i) - { - source[Indices::momentum(i)] += tmp1[i]; - } + source[Indices::momentum(i)] += gravityTerm[i]; + + return source; } }; diff --git a/dumux/geomechanics/elastic/model.hh b/dumux/geomechanics/elastic/model.hh index 973b01e349..98e925e0a9 100644 --- a/dumux/geomechanics/elastic/model.hh +++ b/dumux/geomechanics/elastic/model.hh @@ -59,17 +59,15 @@ namespace Dumux template class ElasticModel : public GET_PROP_TYPE(TypeTag, BaseModel) { + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; 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 typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - enum { - dim = GridView::dimension - }; + enum { isBox = GET_PROP_VALUE(TypeTag, ImplicitIsBox) }; + enum { dim = GridView::dimension }; typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; typedef Dune::FieldMatrix DimMatrix; @@ -88,12 +86,12 @@ public: typedef Dune::BlockVector > VectorField; // create the required scalar fields - unsigned numScv = this->gridView_().size(dim); + unsigned numDofs = this->numDofs(); unsigned numElements = this->gridView_().size(0); - ScalarField &ux = *writer.allocateManagedBuffer(numScv); - ScalarField &uy = *writer.allocateManagedBuffer(numScv); - ScalarField &uz = *writer.allocateManagedBuffer(numScv); + ScalarField &ux = *writer.allocateManagedBuffer(numDofs); + ScalarField &uy = *writer.allocateManagedBuffer(numDofs); + ScalarField &uz = *writer.allocateManagedBuffer(numDofs); VectorField &sigmax = *writer.template allocateManagedBuffer(numElements); VectorField &sigmay = *writer.template allocateManagedBuffer(numElements); VectorField &sigmaz = *writer.template allocateManagedBuffer(numElements); @@ -114,84 +112,70 @@ public: ScalarField &rank = *writer.allocateManagedBuffer(numElements); - FVElementGeometry fvGeometry; - VolumeVariables volVars; - ElementBoundaryTypes elemBcTypes; - for (const auto& element : elements(this->gridView_())) { if(element.partitionType() == Dune::InteriorEntity) { - int eIdx = this->problem_().model().elementMapper().index(element); - rank[eIdx] = this->gridView_().comm().rank(); + int eIdx = this->problem_().model().elementMapper().index(element); + rank[eIdx] = this->gridView_().comm().rank(); - fvGeometry.update(this->gridView_(), element); - elemBcTypes.update(this->problem_(), element, fvGeometry); + // make sure FVElementGeometry and the volume variables are bound to the element + this->fvGeometries_().bind(element); + this->curVolVars_().bind(element); - for (int scvIdx = 0; scvIdx < fvGeometry.numScv; ++scvIdx) - { - int vIdxGlobal = this->dofMapper().subIndex(element, scvIdx, dim); + const auto& fvGeometry = this->fvGeometries(element); + for (const auto& scv : fvGeometry.scvs()) + { + int dofIdxGlobal = scv.dofIndex(); + const auto& volVars = this->curVolVars(scv); + + ux[dofIdxGlobal] = volVars.displacement(0); + if (dim >= 2) + uy[dofIdxGlobal] = volVars.displacement(1); + if (dim >= 3) + uz[dofIdxGlobal] = volVars.displacement(2); + } - volVars.update(sol[vIdxGlobal], - this->problem_(), - element, - fvGeometry, - scvIdx, - false); + // In the box method, the stress is evaluated on the FE-Grid. However, to get an + // average apparent stress for the cell, all contributing stresses have to be interpolated. + DimMatrix stress(0.0); + unsigned int counter = 0; - ux[vIdxGlobal] = volVars.displacement(0); - if (dim >= 2) - uy[vIdxGlobal] = volVars.displacement(1); - if (dim >= 3) - uz[vIdxGlobal] = volVars.displacement(2); - }; - - // In the box method, the stress is evaluated on the FE-Grid. However, to get an - // average apparent stress for the cell, all contributing stresses have to be interpolated. - DimMatrix stress; - - ElementVolumeVariables elemVolVars; - elemVolVars.update(this->problem_(), - element, - fvGeometry, - false /* isOldSol? */); - - // loop over the faces - for (int fIdx = 0; fIdx < fvGeometry.numScvf; fIdx++) - { - stress = 0.0; - //prepare the flux calculations (set up and prepare geometry, FE gradients) - FluxVariables fluxVars; - fluxVars.update(this->problem_(), - element, - fvGeometry, - fIdx, - elemVolVars); - - stress = fluxVars.sigma(); - stress /= fvGeometry.numScvf; - - // Add up stresses for each cell. - // Beware the sign convention applied here: compressive stresses are negative + // loop over the faces + for (const auto& scvFace : fvGeometry.scvfs()) + { + if (scvFace.boundary()) + { + BoundaryTypes bcTypes = this->problem_().boundaryTypes(element, scvFace); + if (bcTypes.hasNeumann()) + continue; + } + + //prepare the flux calculations (set up and prepare geometry, FE gradients) + FluxVariables fluxVars; + fluxVars.initAndComputeFluxes(this->problem_(), element, scvFace); + + // Add up stresses for each scv face. + // Beware the sign convention applied here: compressive stresses are negative + stress += fluxVars.stressTensor(); + counter++; + } + + // divide by the number of added stress tensors and add to container + stress /= counter; sigmax[eIdx] += stress[0]; if (dim >= 2) - { sigmay[eIdx] += stress[1]; - } if (dim == 3) - { sigmaz[eIdx] += stress[2]; - } - } } } - - writer.attachVertexData(ux, "ux"); + writer.attachDofData(ux, "ux", isBox); if (dim >= 2) - writer.attachVertexData(uy, "uy"); + writer.attachDofData(uy, "uy", isBox); if (dim == 3) - writer.attachVertexData(uz, "uz"); + writer.attachDofData(uz, "uz", isBox); writer.attachCellData(sigmax, "stress X", dim); if (dim >= 2) writer.attachCellData(sigmay, "stress Y", dim); diff --git a/dumux/geomechanics/elastic/properties.hh b/dumux/geomechanics/elastic/properties.hh index b51b424c93..36cddaf723 100644 --- a/dumux/geomechanics/elastic/properties.hh +++ b/dumux/geomechanics/elastic/properties.hh @@ -28,7 +28,9 @@ #ifndef DUMUX_ELASTIC_PROPERTIES_HH #define DUMUX_ELASTIC_PROPERTIES_HH +#include #include +#include namespace Dumux { @@ -40,7 +42,7 @@ namespace Properties ////////////////////////////////////////////////////////////////// //! The type tags for the implicit model for elastic deformations of the medium -NEW_TYPE_TAG(BoxElastic, INHERITS_FROM(BoxModel)); +NEW_TYPE_TAG(Elastic, INHERITS_FROM(ImplicitBase)); ////////////////////////////////////////////////////////////////// // Property tags diff --git a/dumux/geomechanics/elastic/propertydefaults.hh b/dumux/geomechanics/elastic/propertydefaults.hh index b7c1c3123f..5377f9d1ef 100644 --- a/dumux/geomechanics/elastic/propertydefaults.hh +++ b/dumux/geomechanics/elastic/propertydefaults.hh @@ -31,14 +31,14 @@ #define DUMUX_ELASTIC_PROPERTIES_DEFAULTS_HH #include "properties.hh" - #include "model.hh" #include "localresidual.hh" #include "volumevariables.hh" -#include "fluxvariables.hh" #include "indices.hh" - +#include +#include +#include namespace Dumux { @@ -50,7 +50,7 @@ namespace Properties ////////////////////////////////////////////////////////////////// //!< set the number of equations to the space dimension of the problem -SET_PROP(BoxElastic, NumEq) +SET_PROP(Elastic, NumEq) { private: typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; @@ -60,24 +60,46 @@ public: }; //! Use the linear elasticity local residual function for the elasticity model -SET_TYPE_PROP(BoxElastic, - LocalResidual, - ElasticLocalResidual); +SET_TYPE_PROP(Elastic, LocalResidual, ElasticLocalResidual); //! define the model -SET_TYPE_PROP(BoxElastic, Model, ElasticModel); +SET_TYPE_PROP(Elastic, Model, ElasticModel); //! define the VolumeVariables -SET_TYPE_PROP(BoxElastic, VolumeVariables, ElasticVolumeVariablesBase); +SET_TYPE_PROP(Elastic, VolumeVariables, ElasticVolumeVariablesBase); + +//! Disable advection +SET_BOOL_PROP(Elastic, EnableAdvection, false); + +//! Disable molecular diffusion +SET_BOOL_PROP(Elastic, EnableMolecularDiffusion, false); + +//! Isothermal model by default +SET_BOOL_PROP(Elastic, EnableEnergyBalance, false); //! define the FluxVariables -SET_TYPE_PROP(BoxElastic, FluxVariables, ElasticFluxVariablesBase); +SET_PROP(Elastic, FluxVariables) +{ +private: + static constexpr bool advection = GET_PROP_VALUE(TypeTag, EnableAdvection); + static constexpr bool diffusion = GET_PROP_VALUE(TypeTag, EnableMolecularDiffusion); + static constexpr bool energy = GET_PROP_VALUE(TypeTag, EnableEnergyBalance); +public: + typedef Dumux::StressVariables type; +}; //! Set the indices used by the linear elasticity model -SET_TYPE_PROP(BoxElastic, Indices, ElasticIndices<>); +SET_TYPE_PROP(Elastic, Indices, ElasticIndices<>); //! enable gravity by default -SET_BOOL_PROP(BoxElastic, ProblemEnableGravity, true); +SET_BOOL_PROP(Elastic, ProblemEnableGravity, true); + +//! The flux variables cache class +SET_TYPE_PROP(Elastic, FluxVariablesCache, Dumux::StressVariablesCache); + +//! The darcy flux variables +SET_TYPE_PROP(Elastic, MechanicalLawType, Dumux::HookesLaw); + } } diff --git a/dumux/geomechanics/elastic/volumevariables.hh b/dumux/geomechanics/elastic/volumevariables.hh index 1d1cf57490..c1e0ad3853 100644 --- a/dumux/geomechanics/elastic/volumevariables.hh +++ b/dumux/geomechanics/elastic/volumevariables.hh @@ -43,6 +43,7 @@ class ElasticVolumeVariablesBase : public ImplicitVolumeVariables typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) Implementation; typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename GET_PROP_TYPE(TypeTag, SubControlVolume) SubControlVolume; typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; @@ -61,16 +62,12 @@ public: void update(const PrimaryVariables &priVars, const Problem &problem, const Element &element, - const FVElementGeometry &fvGeometry, - const int scvIdx, - const bool isOldSol) + const SubControlVolume& scv) { ParentType::update(priVars, problem, element, - fvGeometry, - scvIdx, - isOldSol); + scv); primaryVars_ = priVars; @@ -78,11 +75,10 @@ public: displacement_[i] = priVars[Indices::u(i)]; // retrieve Lame parameters and rock density from spatialParams - const Dune::FieldVector &lameParams = - problem.spatialParams().lameParams(element, fvGeometry, scvIdx); + const Dune::FieldVector &lameParams = problem.spatialParams().lameParams(element, scv); lambda_ = lameParams[0]; mu_ = lameParams[1]; - rockDensity_ = problem.spatialParams().rockDensity(element, scvIdx); + rockDensity_ = problem.spatialParams().rockDensity(element, scv); } /*! diff --git a/dumux/geomechanics/implicit/CMakeLists.txt b/dumux/geomechanics/implicit/CMakeLists.txt new file mode 100644 index 0000000000..d41b715ec6 --- /dev/null +++ b/dumux/geomechanics/implicit/CMakeLists.txt @@ -0,0 +1,4 @@ +# install headers +install(FILES +stressvariables.hh +DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dumux/geomechanics/implicit) \ No newline at end of file diff --git a/dumux/geomechanics/implicit/stressvariables.hh b/dumux/geomechanics/implicit/stressvariables.hh new file mode 100644 index 0000000000..8e942038e0 --- /dev/null +++ b/dumux/geomechanics/implicit/stressvariables.hh @@ -0,0 +1,90 @@ +// -*- 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 . * + *****************************************************************************/ +/*! + * \file + * \brief The stress variables + */ +#ifndef DUMUX_GEOMECHANICS_IMPLICIT_STRESSVARIABLES_HH +#define DUMUX_GEOMECHANICS_IMPLICIT_STRESSVARIABLES_HH + +#include +#include + +namespace Dumux +{ + +namespace Properties +{ +NEW_PROP_TAG(MechanicalLawType); +} + +/*! + * \ingroup ImplicitModel + * \brief the flux variables class + * specializations are provided for combinations of physical processes + */ +template +class StressVariables {}; + +/*! + * \ingroup ImplicitModel + * \brief Base class for the flux variables + * Actual flux variables inherit from this class + */ +template +class StressVariables : public FluxVariablesBase> +{ + using ParentType = FluxVariablesBase>; + using Problem = typename GET_PROP_TYPE(TypeTag, Problem); + using GridView = typename GET_PROP_TYPE(TypeTag, GridView); + using Element = typename GridView::template Codim<0>::Entity; + using IndexType = typename GridView::IndexSet::IndexType; + using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Stencil = std::vector; + using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); + using MechanicalLawType = typename GET_PROP_TYPE(TypeTag, MechanicalLawType); + + enum{ enableFluxVarsCache = GET_PROP_VALUE(TypeTag, EnableFluxVariablesCache) }; + enum { dim = GridView::dimension} ; + + typedef Dune::FieldMatrix DimMatrix; + typedef Dune::FieldVector DimVector; + +public: + + void initAndComputeFluxes(const Problem& problem, + const Element& element, + const SubControlVolumeFace &scvFace) + { + ParentType::init(problem, element, scvFace); + } + + Stencil computeStencil(const Problem& problem, const SubControlVolumeFace& scvFace) + { return MechanicalLawType::stencil(problem, scvFace); } + + DimVector stressVector() + { return MechanicalLawType::stressVector(this->problem(), this->scvFace()); } + + DimMatrix stressTensor() + { return MechanicalLawType::stressTensor(this->problem(), this->scvFace()); } +}; + +} // end namespace + +#endif diff --git a/dumux/geomechanics/implicit/stressvariablescache.hh b/dumux/geomechanics/implicit/stressvariablescache.hh new file mode 100644 index 0000000000..67d978d339 --- /dev/null +++ b/dumux/geomechanics/implicit/stressvariablescache.hh @@ -0,0 +1,102 @@ +// -*- 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 . * + *****************************************************************************/ +/*! + * \file + * \brief Base class for the flux variables + */ +#ifndef DUMUX_GEOMECHANICS_IMPLICIT_STRESSVARIABLESCACHE_HH +#define DUMUX_GEOMECHANICS_IMPLICIT_STRESSVARIABLESCACHE_HH + +#include + +namespace Dumux +{ + +/*! + * \ingroup ImplicitModel + * \brief The stress variables cache classes + * stores matrices to recover the discplacement on a scv face and stencil + */ +template +class StressVariablesCache +{}; + +// specialization for the Box Method +template +class StressVariablesCache::type > +{ + using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Problem = typename GET_PROP_TYPE(TypeTag, Problem); + using GridView = typename GET_PROP_TYPE(TypeTag, GridView); + using FluxVariables = typename GET_PROP_TYPE(TypeTag, FluxVariables); + using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); + using MechanicalLawType = typename GET_PROP_TYPE(TypeTag, MechanicalLawType); + using Element = typename GridView::template Codim<0>::Entity; + using IndexType = typename GridView::IndexSet::IndexType; + using Stencil = std::vector; + +public: + void update(const Problem& problem, + const Element& element, + const SubControlVolumeFace &scvFace) + { + FluxVariables fluxVars; + stencil_ = fluxVars.computeStencil(problem, scvFace); + } + + const Stencil& stencil() const + { return stencil_; } + +private: + Stencil stencil_; +}; + +// specialization for the cell centered tpfa method +template +class StressVariablesCache::type > +{ + using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Problem = typename GET_PROP_TYPE(TypeTag, Problem); + using GridView = typename GET_PROP_TYPE(TypeTag, GridView); + using FluxVariables = typename GET_PROP_TYPE(TypeTag, FluxVariables); + using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); + using MechanicalLawType = typename GET_PROP_TYPE(TypeTag, MechanicalLawType); + using Element = typename GridView::template Codim<0>::Entity; + using IndexType = typename GridView::IndexSet::IndexType; + using Stencil = std::vector; + +public: + void update(const Problem& problem, + const Element& element, + const SubControlVolumeFace &scvFace) + { + FluxVariables fluxVars; + stencil_ = fluxVars.computeStencil(problem, scvFace); + } + + const Stencil& stencil() const + { return stencil_; } + +private: + Stencil stencil_; +}; + +} // end namespace + +#endif diff --git a/test/geomechanics/elastic/elasticmatrixproblem.hh b/test/geomechanics/elastic/elasticmatrixproblem.hh index db9111eceb..bc1c1ed9a9 100644 --- a/test/geomechanics/elastic/elasticmatrixproblem.hh +++ b/test/geomechanics/elastic/elasticmatrixproblem.hh @@ -39,10 +39,10 @@ class ElasticMatrixProblem; namespace Properties { -NEW_TYPE_TAG(ElasticMatrixProblem, INHERITS_FROM(BoxElastic,ElSpatialParams)); +NEW_TYPE_TAG(ElasticMatrixProblem, INHERITS_FROM(CCTpfaModel, Elastic, ElSpatialParams)); // Set the grid type -SET_TYPE_PROP(ElasticMatrixProblem, Grid, Dune::YaspGrid<3>); +SET_TYPE_PROP(ElasticMatrixProblem, Grid, Dune::YaspGrid<2>); // Set the problem property SET_TYPE_PROP(ElasticMatrixProblem, Problem, Dumux::ElasticMatrixProblem); @@ -88,6 +88,8 @@ class ElasticMatrixProblem: public ImplicitPorousMediaProblem typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes; typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; typedef typename GET_PROP_TYPE(TypeTag, TimeManager) TimeManager; + typedef typename GET_PROP_TYPE(TypeTag, SubControlVolume) SubControlVolume; + typedef typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace) SubControlVolumeFace; // copy some indices for convenience typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; @@ -146,18 +148,21 @@ public: * \param values The boundary types for the conservation equations * \param globalPos The global position */ - void boundaryTypesAtPos(BoundaryTypes &values, - const GlobalPosition &globalPos) const + BoundaryTypes boundaryTypesAtPos(const GlobalPosition &globalPos) const { + BoundaryTypes values; + values.setAllNeumann(); - values.setDirichlet(uyIdx); if(globalPos[0] < eps_) { + values.setDirichlet(uyIdx); values.setDirichlet(uxIdx); if(globalPos[2] < eps_) values.setDirichlet(uzIdx); } + + return values; } /*! @@ -169,9 +174,9 @@ public: * * For this method, the \a values parameter stores primary variables. */ - void dirichlet(PrimaryVariables &values, const Vertex &vertex) const + PrimaryVariables dirichletAtPos(const GlobalPosition& globalPos) const { - values = 0.0; + return PrimaryVariables(0.0); } /*! @@ -181,20 +186,18 @@ public: * For this method, the \a values parameter stores the mass flux * in normal direction of each phase. Negative values mean influx. */ - void neumann(PrimaryVariables &values, - const Element &element, - const FVElementGeometry &fvGeometry, - const Intersection &intersection, - int scvIdx, - int boundaryFaceIdx) const + PrimaryVariables neumann(const Element &element, const SubControlVolumeFace &scvFace) const { - values = 0.0; - // get Lame parameters + PrimaryVariables values(0.0); - Scalar lambda = this->spatialParams().lameParams(element, fvGeometry, scvIdx)[0]; - Scalar mu = this->spatialParams().lameParams(element, fvGeometry, scvIdx)[1]; - Scalar E = this->spatialParams().E(element, fvGeometry, scvIdx); - Scalar nu = this->spatialParams().nu(element, fvGeometry, scvIdx); + // inside scv + const auto& scv = this->model().fvGeometries().subControlVolume(scvFace.insideScvIdx()); + + // get Lame parameters + Scalar lambda = this->spatialParams().lameParams(element, scv)[0]; + Scalar mu = this->spatialParams().lameParams(element, scv)[1]; + Scalar E = this->spatialParams().E(element, scv); + Scalar nu = this->spatialParams().nu(element, scv); // calculate values of sigma in normal direction Dune::FieldMatrix sigma(0); @@ -205,11 +208,12 @@ public: sigma *= -1.0/E; // determine normal vector of current face - Dune::FieldVector localDimM1(0); - Dune::FieldVector normal = intersection.unitOuterNormal(localDimM1); + Dune::FieldVector normal = scvFace.unitOuterNormal(); // use stress in normal direction as boundary condition sigma.mv(normal, values); + + return values; } // \} @@ -227,10 +231,9 @@ public: * unit. Positive values mean that momentum is created, negative ones * mean that it vanishes. */ - void sourceAtPos(PrimaryVariables &priVars, - const GlobalPosition &globalPos) const + PrimaryVariables sourceAtPos(const GlobalPosition &globalPos) const { - priVars = Scalar(0.0); + return PrimaryVariables(0.0); } /*! @@ -242,9 +245,9 @@ public: * For this method, the \a values parameter stores primary * variables. */ - void initialAtPos(PrimaryVariables &values, const GlobalPosition &globalPos) const + PrimaryVariables initialAtPos(const GlobalPosition &globalPos) const { - initial_(values, globalPos); + return initial_(globalPos); } // \} @@ -252,10 +255,9 @@ public: private: // the internal method for the initial condition - void initial_(PrimaryVariables &priVars, - const GlobalPosition &globalPos) const + PrimaryVariables initial_(const GlobalPosition &globalPos) const { - priVars = 0.0; // initial condition for the solid displacement + return PrimaryVariables(0.0); // initial condition for the solid displacement } static constexpr Scalar eps_ = 3e-6; diff --git a/test/geomechanics/elastic/elasticspatialparams.hh b/test/geomechanics/elastic/elasticspatialparams.hh index 11bff53d07..7baaf1e70b 100644 --- a/test/geomechanics/elastic/elasticspatialparams.hh +++ b/test/geomechanics/elastic/elasticspatialparams.hh @@ -55,20 +55,20 @@ class ElSpatialParams { typedef typename GET_PROP_TYPE(TypeTag, Grid) Grid; 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, FVElementGeometry) FVElementGeometry; + typedef typename GET_PROP_TYPE(TypeTag, SubControlVolume) SubControlVolume; + typedef typename GridView::template Codim<0>::Entity Element; typedef typename Grid::ctype CoordScalar; - enum { - dimWorld=GridView::dimensionworld, - }; - typedef Dune::FieldVector GlobalPosition; + enum { dimWorld=GridView::dimensionworld }; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename GridView::template Codim<0>::Entity Element; + typedef Dune::FieldVector GlobalPosition; public: - ElSpatialParams(const GridView &gridView) + ElSpatialParams(const Problem& problem, const GridView &gridView) { // rock density rockDensity_ = 2650.0; @@ -90,8 +90,7 @@ public: * \param element The finite element * \param scvIdx The local index of the sub-control volume where */ - const Scalar rockDensity(const Element &element, - int scvIdx) const + const Scalar rockDensity(const Element &element, const SubControlVolume& scv) const { return rockDensity_; } @@ -113,9 +112,7 @@ public: * \param fvGeometry The current finite volume geometry of the element * \param scvIdx The local index of the sub-control volume where */ - const Dune::FieldVector lameParams(const Element &element, - const FVElementGeometry &fvGeometry, - int scvIdx) const + const Dune::FieldVector lameParams(const Element &element, const SubControlVolume& scv) const { // Lame parameters Dune::FieldVector param; @@ -133,9 +130,7 @@ public: * \param fvGeometry The current finite volume geometry of the element * \param scvIdx The local index of the sub-control volume where */ - const Scalar E(const Element &element, - const FVElementGeometry &fvGeometry, - int scvIdx) const + const Scalar E(const Element &element, const SubControlVolume& scv) const { return E_; } @@ -147,9 +142,7 @@ public: * \param fvGeometry The current finite volume geometry of the element * \param scvIdx The local index of the sub-control volume where */ - const Scalar nu(const Element &element, - const FVElementGeometry &fvGeometry, - int scvIdx) const + const Scalar nu(const Element &element, const SubControlVolume& scv) const { return nu_; } diff --git a/test/geomechanics/elastic/grids/test_elastic.dgf b/test/geomechanics/elastic/grids/test_elastic.dgf index ca6448bb2b..b889dc59d3 100644 --- a/test/geomechanics/elastic/grids/test_elastic.dgf +++ b/test/geomechanics/elastic/grids/test_elastic.dgf @@ -1,8 +1,8 @@ DGF Interval -0 0 0 % first corner -10 1 10 % second corner -10 10 10 % cells in x, y, z direction +0 0 % first corner +10 10 % second corner +25 25 % cells in x, y, z direction # BOUNDARYDOMAIN diff --git a/test/geomechanics/elastic/test_elastic.input b/test/geomechanics/elastic/test_elastic.input index 37d6ae168f..5e8921602a 100644 --- a/test/geomechanics/elastic/test_elastic.input +++ b/test/geomechanics/elastic/test_elastic.input @@ -7,4 +7,3 @@ EnableGravity = 0 [Grid] File = grids/test_elastic.dgf - -- GitLab From 51a3e6e18187079650cde83532656f47451dedff Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 21 Jun 2016 10:53:54 +0200 Subject: [PATCH 06/45] [box][fvgeomvector] fix comment --- dumux/implicit/box/fvelementgeometryvector.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dumux/implicit/box/fvelementgeometryvector.hh b/dumux/implicit/box/fvelementgeometryvector.hh index a5ba6ea2b3..8adad9b3f4 100644 --- a/dumux/implicit/box/fvelementgeometryvector.hh +++ b/dumux/implicit/box/fvelementgeometryvector.hh @@ -104,7 +104,7 @@ public: auto c = geometry.center(); - // procees according to number of corners + // proceed according to number of corners switch (geometry.corners()) { case 3: // triangle -- GitLab From 3c78c1a537f12dfec0f350c69b536f458b5770d8 Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 21 Jun 2016 11:38:27 +0200 Subject: [PATCH 07/45] [box][fvgeomvector] scv faces get global scv indices --- dumux/implicit/box/fvelementgeometryvector.hh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dumux/implicit/box/fvelementgeometryvector.hh b/dumux/implicit/box/fvelementgeometryvector.hh index 8adad9b3f4..0cb4ac71d1 100644 --- a/dumux/implicit/box/fvelementgeometryvector.hh +++ b/dumux/implicit/box/fvelementgeometryvector.hh @@ -486,10 +486,10 @@ public: // add this scvf to the element's scvf list scvfIndexSet.push_back(scvfIdx); - // find the scvs this scvf is belonging to + // find the global scv indices this scvf is belonging to std::vector scvIndices(2); - scvIndices[0] = referenceElement.subEntity(scvfLocalIdx, dim-1, 0, dim); - scvIndices[1] = referenceElement.subEntity(scvfLocalIdx, dim-1, 1, dim); + scvIndices[0] = scvIndexSet[referenceElement.subEntity(scvfLocalIdx, dim-1, 0, dim)]; + scvIndices[1] = scvIndexSet[referenceElement.subEntity(scvfLocalIdx, dim-1, 1, dim)]; // compute the scvf normal unit outer normal auto normal = BoxGeometryHelper::normal(elementGeometry, *scvfGeometry); @@ -522,7 +522,7 @@ public: scvfIndexSet.push_back(scvfIdx); // find the scvs this scvf is belonging to - std::vector scvIndices = {static_cast(referenceElement.subEntity(intersection.indexInInside(), 1, scvfLocalIdx++, dim))}; + std::vector scvIndices = {static_cast(scvIndexSet[referenceElement.subEntity(intersection.indexInInside(), 1, scvfLocalIdx++, dim)])}; // get the unit outer normal through the intersection auto normal = intersection.unitOuterNormal(isGeometry.local(scvfGeometry->center())); -- GitLab From 37fe7e77f08942394f0969dfdc532cada39e547f Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Mon, 4 Jul 2016 17:22:22 +0200 Subject: [PATCH 08/45] [box][assembler] fix endIndices() method --- dumux/implicit/box/assembler.hh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dumux/implicit/box/assembler.hh b/dumux/implicit/box/assembler.hh index a3911ad407..2ac4829559 100644 --- a/dumux/implicit/box/assembler.hh +++ b/dumux/implicit/box/assembler.hh @@ -86,9 +86,8 @@ class BoxAssembler : public ImplicitAssembler for (auto&& globalJ : stencil) this->matrix().addindex(globalI, globalJ); - - this->matrix().endindices(); } + this->matrix().endindices(); } }; -- GitLab From 85a98ffd9d7522fc69b1170c2fd8229cef32ac4a Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 5 Jul 2016 10:17:33 +0200 Subject: [PATCH 09/45] [implicit][assembler] remove assembleElement_() method The assemble_() method in the ImplicitAssembler now calls the assemble routine in the localjacobian directly. The global matrix and the residual are passed to that routine where the residua and derivatives are directly set in the global containers. That makes a specialized assembleElement_() method obsolete as the local matrix is no longer stored. --- dumux/implicit/assembler.hh | 2 +- dumux/implicit/box/assembler.hh | 19 ------------------- dumux/implicit/cellcentered/assembler.hh | 9 --------- 3 files changed, 1 insertion(+), 29 deletions(-) diff --git a/dumux/implicit/assembler.hh b/dumux/implicit/assembler.hh index dd5ffdd40a..c0e82f7c31 100644 --- a/dumux/implicit/assembler.hh +++ b/dumux/implicit/assembler.hh @@ -154,7 +154,7 @@ protected: // assemble the elements... for (const auto& element : elements(gridView_())) - asImp_().assembleElement_(element); + this->model_().localJacobian().assemble(element, this->matrix(), this->residual()); } protected: diff --git a/dumux/implicit/box/assembler.hh b/dumux/implicit/box/assembler.hh index 2ac4829559..33a18bc256 100644 --- a/dumux/implicit/box/assembler.hh +++ b/dumux/implicit/box/assembler.hh @@ -41,27 +41,8 @@ class BoxAssembler : public ImplicitAssembler typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GridView::template Codim<0>::Entity Element; typedef typename GridView::IndexSet::IndexType IndexType; - // assemble an interior element - void assembleElement_(const Element &element) - { - - this->model_().localJacobian().assemble(element, this->matrix()); - - for(int vIdxLocal = 0; vIdxLocal < element.subEntities(dim); ++vIdxLocal) - { - auto globalI = vertexMapper_().subIndex(element, dim, vIdxLocal); - - // update the right hand side - this->residual_[globalI] += this->model_().localJacobian().residual(vIdxLocal); - - for (int j = 0; j < residual_[globalI].dimension; ++j) - assert(std::isfinite(residual_[globalI][j])); - } - } - void setRowSizes_() { for (const auto& vertex : vertices(this->gridView_())) diff --git a/dumux/implicit/cellcentered/assembler.hh b/dumux/implicit/cellcentered/assembler.hh index 058e08e687..7295f086bd 100644 --- a/dumux/implicit/cellcentered/assembler.hh +++ b/dumux/implicit/cellcentered/assembler.hh @@ -44,15 +44,6 @@ class CCAssembler : public ImplicitAssembler typedef typename GridView::template Codim<0>::Entity Element; typedef typename GridView::IndexSet::IndexType IndexType; - // assemble an interior element - void assembleElement_(const Element &element) - { - auto globalI = this->elementMapper_().index(element); - - this->model_().localJacobian().assemble(element, this->matrix()); - this->residual_[globalI] = this->model_().localJacobian().residual(0); - } - void setRowSizes_() { for (const auto& element : elements(this->gridView_())) -- GitLab From 1fc91e056a2dbe57f80cc1c5a066c6b45e3c4793 Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 5 Jul 2016 10:23:40 +0200 Subject: [PATCH 10/45] [box][fvgeomvector] fix 3D scv and scvf creation --- dumux/implicit/box/fvelementgeometryvector.hh | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/dumux/implicit/box/fvelementgeometryvector.hh b/dumux/implicit/box/fvelementgeometryvector.hh index 0cb4ac71d1..9751b0cd7c 100644 --- a/dumux/implicit/box/fvelementgeometryvector.hh +++ b/dumux/implicit/box/fvelementgeometryvector.hh @@ -184,18 +184,18 @@ public: { // sub control volumes ScvGeometryVector scvGeometries(4); - scvGeometries[0] = std::make_shared(scvGeometryType, std::vector({v[0], e[0], e[1], f[0], e[3], f[1], f[2], c})); - scvGeometries[1] = std::make_shared(scvGeometryType, std::vector({e[0], v[1], f[0], e[2], f[1], e[4], c, f[3]})); - scvGeometries[2] = std::make_shared(scvGeometryType, std::vector({e[1], f[0], v[2], e[2], f[2], c, e[5], f[3]})); - scvGeometries[3] = std::make_shared(scvGeometryType, std::vector({e[3], f[1], f[2], c, v[3], e[4], e[5], f[3]})); + scvGeometries[0] = std::make_shared(scvGeometryType, std::vector({v[0], e[0], e[1], f[0], e[3], f[1], f[2], c})); + scvGeometries[1] = std::make_shared(scvGeometryType, std::vector({v[1], e[2], e[0], f[0], f[3], e[4], c, f[1]})); + scvGeometries[2] = std::make_shared(scvGeometryType, std::vector({v[2], e[1], e[2], f[0], e[5], f[2], f[3], c})); + scvGeometries[3] = std::make_shared(scvGeometryType, std::vector({v[3], e[3], e[5], f[2], e[4], f[1], f[3], c})); // sub control volume faces ScvfGeometryVector scvfGeometries(6); scvfGeometries[0] = std::make_shared(scvfGeometryType, std::vector({e[0], f[0], f[1], c})); - scvfGeometries[1] = std::make_shared(scvfGeometryType, std::vector({e[1], f[0], f[2], c})); + scvfGeometries[1] = std::make_shared(scvfGeometryType, std::vector({f[0], e[1], c, f[2]})); scvfGeometries[2] = std::make_shared(scvfGeometryType, std::vector({e[2], f[0], f[3], c})); - scvfGeometries[3] = std::make_shared(scvfGeometryType, std::vector({e[3], f[1], f[2], c})); - scvfGeometries[4] = std::make_shared(scvfGeometryType, std::vector({e[4], f[3], f[1], c})); + scvfGeometries[3] = std::make_shared(scvfGeometryType, std::vector({f[2], e[3], c, f[1]})); + scvfGeometries[4] = std::make_shared(scvfGeometryType, std::vector({f[3], c, e[4], f[1]})); scvfGeometries[5] = std::make_shared(scvfGeometryType, std::vector({e[5], f[2], f[3], c})); return std::make_pair(scvGeometries, scvfGeometries); @@ -208,24 +208,24 @@ public: scvGeometries[1] = std::make_shared(scvGeometryType, std::vector({e[6], v[1], f[4], e[5], f[2], e[1], c, f[1]})); scvGeometries[2] = std::make_shared(scvGeometryType, std::vector({e[4], f[4], v[2], e[7], f[0], c, e[2], f[3]})); scvGeometries[3] = std::make_shared(scvGeometryType, std::vector({f[4], e[5], e[7], v[3], c, f[1], f[3], e[3]})); - scvGeometries[4] = std::make_shared(scvGeometryType, std::vector({e[0], f[2], f[0], c, v[4], e[1], e[8], f[5]})); - scvGeometries[5] = std::make_shared(scvGeometryType, std::vector({f[2], e[1], c, f[1], e[1], v[5], f[5], e[9]})); - scvGeometries[6] = std::make_shared(scvGeometryType, std::vector({f[0], c, e[2], f[3], e[8], f[5], v[6], e[1]})); - scvGeometries[7] = std::make_shared(scvGeometryType, std::vector({c, f[1], f[3], e[3], f[5], e[9], e[1], v[7]})); + scvGeometries[4] = std::make_shared(scvGeometryType, std::vector({e[0], f[2], f[0], c, v[4], e[10], e[8], f[5]})); + scvGeometries[5] = std::make_shared(scvGeometryType, std::vector({f[2], e[1], c, f[1], e[10], v[5], f[5], e[9]})); + scvGeometries[6] = std::make_shared(scvGeometryType, std::vector({f[0], c, e[2], f[3], e[8], f[5], v[6], e[11]})); + scvGeometries[7] = std::make_shared(scvGeometryType, std::vector({c, f[1], f[3], e[3], f[5], e[9], e[11], v[7]})); // sub control volume faces ScvfGeometryVector scvfGeometries(12); - scvfGeometries[0] = std::make_shared(scvfGeometryType, std::vector({e[0], f[2], f[0], c})); - scvfGeometries[1] = std::make_shared(scvfGeometryType, std::vector({e[1], f[1], f[2], c})); - scvfGeometries[2] = std::make_shared(scvfGeometryType, std::vector({e[2], f[0], f[3], c})); + scvfGeometries[0] = std::make_shared(scvfGeometryType, std::vector({f[0], e[0], c, f[2]})); + scvfGeometries[1] = std::make_shared(scvfGeometryType, std::vector({f[1], c, e[1], f[2]})); + scvfGeometries[2] = std::make_shared(scvfGeometryType, std::vector({f[3], e[2], c, f[0]})); scvfGeometries[3] = std::make_shared(scvfGeometryType, std::vector({e[3], f[3], f[1], c})); - scvfGeometries[4] = std::make_shared(scvfGeometryType, std::vector({e[4], f[4], f[0], c})); + scvfGeometries[4] = std::make_shared(scvfGeometryType, std::vector({f[4], e[4], c, f[0]})); scvfGeometries[5] = std::make_shared(scvfGeometryType, std::vector({e[5], f[4], f[1], c})); scvfGeometries[6] = std::make_shared(scvfGeometryType, std::vector({e[6], f[4], f[2], c})); - scvfGeometries[7] = std::make_shared(scvfGeometryType, std::vector({e[7], f[4], f[3], c})); - scvfGeometries[8] = std::make_shared(scvfGeometryType, std::vector({e[8], f[5], f[0], c})); - scvfGeometries[9] = std::make_shared(scvfGeometryType, std::vector({e[9], f[5], f[1], c})); - scvfGeometries[10] = std::make_shared(scvfGeometryType, std::vector({e[10], f[5], f[2], c})); + scvfGeometries[7] = std::make_shared(scvfGeometryType, std::vector({f[4], e[7], c, f[3]})); + scvfGeometries[8] = std::make_shared(scvfGeometryType, std::vector({c, f[0], f[5], e[8]})); + scvfGeometries[9] = std::make_shared(scvfGeometryType, std::vector({e[9], f[1], f[5], c})); + scvfGeometries[10] = std::make_shared(scvfGeometryType, std::vector({e[10], f[2], f[5], c})); scvfGeometries[11] = std::make_shared(scvfGeometryType, std::vector({e[11], f[5], f[3], c})); return std::make_pair(scvGeometries, scvfGeometries); -- GitLab From d5a0c8f9aa87bb6ace98e45814b9e2825a50684f Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 5 Jul 2016 10:25:23 +0200 Subject: [PATCH 11/45] [box][fvgeomvector] fix 3D boundary scvf creation --- dumux/implicit/box/fvelementgeometryvector.hh | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/dumux/implicit/box/fvelementgeometryvector.hh b/dumux/implicit/box/fvelementgeometryvector.hh index 9751b0cd7c..b7e5a12ffc 100644 --- a/dumux/implicit/box/fvelementgeometryvector.hh +++ b/dumux/implicit/box/fvelementgeometryvector.hh @@ -60,6 +60,7 @@ private: using Intersection = typename GridView::Intersection; using ReferenceElements = typename Dune::ReferenceElements; + using FaceReferenceElements = typename Dune::ReferenceElements; public: //! get sub control volume geometries from element of dimension 1 @@ -257,22 +258,23 @@ public: static typename std::enable_if::type getBoundaryScvfGeometries(const typename Intersection::Geometry& geometry) { - // sub control volume face geometries in 2D are always lines - Dune::GeometryType scvfGeometryType; scvfGeometryType.makeLine(); + // sub control volume face geometries in 3D are always quadrilaterals + Dune::GeometryType scvfGeometryType; scvfGeometryType.makeQuadrilateral(); // extract the corners of the sub control volumes - const auto& referenceElement = ReferenceElements::general(geometry.type()); + const auto& referenceElement = FaceReferenceElements::general(geometry.type()); // vertices CornerList v; for (int i = 0; i < geometry.corners(); ++i) v.emplace_back(geometry.corner(i)); - // face midpoints - CornerList f; + // edge midpoints + CornerList e; for (int i = 0; i < referenceElement.size(1); ++i) - f.emplace_back(geometry.global(referenceElement.position(i, 1))); + e.emplace_back(geometry.global(referenceElement.position(i, 1))); + // face midpoint auto c = geometry.center(); // procees according to number of corners @@ -281,19 +283,19 @@ public: case 3: // triangle { ScvfGeometryVector scvfGeometries(3); - scvfGeometries[0] = std::make_shared(scvfGeometryType, std::vector({f[0], c})); - scvfGeometries[1] = std::make_shared(scvfGeometryType, std::vector({f[1], c})); - scvfGeometries[2] = std::make_shared(scvfGeometryType, std::vector({f[2], c})); + scvfGeometries[0] = std::make_shared(scvfGeometryType, std::vector({v[0], e[0], e[1], c})); + scvfGeometries[1] = std::make_shared(scvfGeometryType, std::vector({v[1], e[2], e[0], c})); + scvfGeometries[2] = std::make_shared(scvfGeometryType, std::vector({v[2], e[1], e[2], c})); return scvfGeometries; } case 4: // quadrilateral { ScvfGeometryVector scvfGeometries(4); - scvfGeometries[0] = std::make_shared(scvfGeometryType, std::vector({f[0], c})); - scvfGeometries[1] = std::make_shared(scvfGeometryType, std::vector({f[1], c})); - scvfGeometries[2] = std::make_shared(scvfGeometryType, std::vector({f[2], c})); - scvfGeometries[3] = std::make_shared(scvfGeometryType, std::vector({f[3], c})); + scvfGeometries[0] = std::make_shared(scvfGeometryType, std::vector({v[0], e[2], e[0], c})); + scvfGeometries[1] = std::make_shared(scvfGeometryType, std::vector({v[1], e[1], e[2], c})); + scvfGeometries[2] = std::make_shared(scvfGeometryType, std::vector({v[2], e[0], e[3], c})); + scvfGeometries[3] = std::make_shared(scvfGeometryType, std::vector({v[3], e[3], e[1], c})); return scvfGeometries; } -- GitLab From 3146097e93dfce10a75d269ac74d81bf95f40553 Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 5 Jul 2016 10:36:24 +0200 Subject: [PATCH 12/45] [implicit change caching property name and move files This commit introduces two things: 1. Renaming of the enableCache properties to enableGlobalCache. The cache classes will also be used to store temporary data in case the caching is disabled. Thus the properties should indicate that they switch on a GLOBAL caching. The commit further changes the corresponding properties set in the defaults. 2. The volume variables vector is now specialized for the box and cc methods. This commit thus also introduces the moving of the volvarvector file into the cc folder and renaming of the class --- .../implicit/cellcentered/propertydefaults.hh | 7 + .../cellcentered/tpfa/propertydefaults.hh | 2 +- .../volumevariablesvector.hh | 184 +++++++++--------- dumux/implicit/properties.hh | 6 +- dumux/implicit/propertydefaults.hh | 6 +- 5 files changed, 102 insertions(+), 103 deletions(-) rename dumux/implicit/{ => cellcentered}/volumevariablesvector.hh (69%) diff --git a/dumux/implicit/cellcentered/propertydefaults.hh b/dumux/implicit/cellcentered/propertydefaults.hh index fb686e5597..4bdb5b09a2 100644 --- a/dumux/implicit/cellcentered/propertydefaults.hh +++ b/dumux/implicit/cellcentered/propertydefaults.hh @@ -28,6 +28,7 @@ #define DUMUX_CC_PROPERTY_DEFAULTS_HH #include +#include "volumevariablesvector.hh" #include "elementboundarytypes.hh" #include "localresidual.hh" #include "properties.hh" @@ -60,6 +61,12 @@ SET_TYPE_PROP(CCModel, JacobianAssembler, Dumux::CCAssembler); //! The stencil container SET_TYPE_PROP(CCModel, StencilsVector, Dumux::CCStencilsVector); +//! The global current volume variables vector class +SET_TYPE_PROP(CCModel, CurrentVolumeVariablesVector, Dumux::CCVolumeVariablesVector); + +//! The global previous volume variables vector class +SET_TYPE_PROP(CCModel, PreviousVolumeVariablesVector, Dumux::CCVolumeVariablesVector); + //! Set the BaseLocalResidual to CCLocalResidual SET_TYPE_PROP(CCModel, BaseLocalResidual, Dumux::CCLocalResidual); diff --git a/dumux/implicit/cellcentered/tpfa/propertydefaults.hh b/dumux/implicit/cellcentered/tpfa/propertydefaults.hh index ba64a98d76..5744cc237a 100644 --- a/dumux/implicit/cellcentered/tpfa/propertydefaults.hh +++ b/dumux/implicit/cellcentered/tpfa/propertydefaults.hh @@ -43,7 +43,7 @@ namespace Properties { SET_INT_PROP(CCTpfaModel, DiscretizationMethod, GET_PROP(TypeTag, DiscretizationMethods)::CCTpfa); //! Set the default for the FVElementGeometry vector -SET_TYPE_PROP(CCTpfaModel, FVElementGeometryVector, CCTpfaFVElementGeometryVector); +SET_TYPE_PROP(CCTpfaModel, FVElementGeometryVector, CCTpfaFVElementGeometryVector); //! The sub control volume SET_PROP(CCTpfaModel, SubControlVolume) diff --git a/dumux/implicit/volumevariablesvector.hh b/dumux/implicit/cellcentered/volumevariablesvector.hh similarity index 69% rename from dumux/implicit/volumevariablesvector.hh rename to dumux/implicit/cellcentered/volumevariablesvector.hh index 45d99cd44a..bac9996b57 100644 --- a/dumux/implicit/volumevariablesvector.hh +++ b/dumux/implicit/cellcentered/volumevariablesvector.hh @@ -20,8 +20,8 @@ * \file * \brief Base class for the volume variables vector */ -#ifndef DUMUX_IMPLICIT_VOLVARSVECTOR_HH -#define DUMUX_IMPLICIT_VOLVARSVECTOR_HH +#ifndef DUMUX_IMPLICIT_CC_VOLVARSVECTOR_HH +#define DUMUX_IMPLICIT_CC_VOLVARSVECTOR_HH #include @@ -33,14 +33,14 @@ namespace Dumux * \brief Base class for the volume variables vector */ template -class VolumeVariablesVector +class CCVolumeVariablesVector {}; // specialization in case of storing the volume variables template -class VolumeVariablesVector : public std::vector +class CCVolumeVariablesVector : public std::vector { - friend VolumeVariablesVector; + friend CCVolumeVariablesVector; friend ImplicitModel; using Problem = typename GET_PROP_TYPE(TypeTag, Problem); using GridView = typename GET_PROP_TYPE(TypeTag, GridView); @@ -48,13 +48,13 @@ class VolumeVariablesVector : pu using VolumeVariables = typename GET_PROP_TYPE(TypeTag, VolumeVariables); using SubControlVolume = typename GET_PROP_TYPE(TypeTag, SubControlVolume); using IndexType = typename GridView::IndexSet::IndexType; - using Element = typename GridView::template Codim<0>::Entity; - enum{ isBox = GET_PROP_VALUE(TypeTag, ImplicitIsBox) }; + static const int dim = GridView::dimension; + using Element = typename GridView::template Codim<0>::Entity; - VolumeVariablesVector& operator= (const VolumeVariablesVector& other) = default; + CCVolumeVariablesVector& operator= (const CCVolumeVariablesVector& other) = default; - VolumeVariablesVector& operator= (const VolumeVariablesVector& other) + CCVolumeVariablesVector& operator= (const CCVolumeVariablesVector& other) { // do the copy numScvs_ = other.numScvs_; @@ -70,10 +70,7 @@ public: void update(Problem& problem, const SolutionVector& sol) { numScvs_ = problem.model().fvGeometries().numScv(); - if (!isBox) - numBoundaryScvs_ = problem.model().fvGeometries().numBoundaryScvf(); - else - numBoundaryScvs_ = 0; + numBoundaryScvs_ = problem.model().fvGeometries().numBoundaryScvf(); volumeVariables_.resize(numScvs_); boundaryVolumeVariables_.resize(numBoundaryScvs_); @@ -83,36 +80,42 @@ public: const auto& fvGeometry = problem.model().fvGeometries(element); for (const auto& scv : fvGeometry.scvs()) { - (*this)[scv.index()].update(sol[scv.dofIndex()], - problem, - element, - scv); + (*this)[scv].update(sol[scv.dofIndex()], + problem, + element, + scv); } - if (!isBox) + // handle the boundary volume variables + for (const auto& scvFace : fvGeometry.scvfs()) { - for (const auto& scvFace : fvGeometry.scvfs()) - { - // if we are not on a boundary, skip the rest - if (!scvFace.boundary()) - continue; - - // When complex boundary handling is inactive, we only use BC vol vars on pure Dirichlet boundaries - const auto bcTypes = problem.boundaryTypes(element, scvFace); - if (/*TODO !GET_PROP_VALUE(TypeTag, BoundaryReconstruction) && */!(bcTypes.hasDirichlet() && !bcTypes.hasNeumann())) - continue; - - const auto insideScvIdx = scvFace.insideScvIdx(); - const auto& insideScv = problem.model().fvGeometries().subControlVolume(insideScvIdx); - const auto dirichletPriVars = problem.dirichlet(element, scvFace); - - (*this)[scvFace.outsideScvIdx()].update(dirichletPriVars, problem, element, insideScv); - } + // if we are not on a boundary, skip the rest + if (!scvFace.boundary()) + continue; + + // When complex boundary handling is inactive, we only use BC vol vars on pure Dirichlet boundaries + const auto bcTypes = problem.boundaryTypes(element, scvFace); + if (/*TODO !GET_PROP_VALUE(TypeTag, BoundaryReconstruction) && */!(bcTypes.hasDirichlet() && !bcTypes.hasNeumann())) + continue; + + const auto insideScvIdx = scvFace.insideScvIdx(); + const auto& insideScv = problem.model().fvGeometries().subControlVolume(insideScvIdx); + const auto dirichletPriVars = problem.dirichlet(element, scvFace); + + (*this)[scvFace.outsideScvIdx()].update(dirichletPriVars, problem, element, insideScv); } } } - const VolumeVariables& operator [](IndexType scvIdx) const + const VolumeVariables& operator [](const SubControlVolume& scv) const + { return (*this)[scv.index()]; } + + VolumeVariables& operator [](const SubControlVolume& scv) + { return (*this)[scv.index()]; } + + // operator for the access with an index + // needed for cc methods for the access to the boundary volume variables + const VolumeVariables& operator [](const IndexType scvIdx) const { assert(scvIdx < numScvs_ + numBoundaryScvs_); @@ -122,7 +125,7 @@ public: return boundaryVolumeVariables_[scvIdx-numScvs_]; } - VolumeVariables& operator [](IndexType scvIdx) + VolumeVariables& operator [](const IndexType scvIdx) { assert(scvIdx < numScvs_ + numBoundaryScvs_); @@ -134,9 +137,9 @@ public: // For compatibility reasons with the case of not storing the vol vars. // function to be called before assembling an element, preparing the vol vars within the stencil - void bind(const Element& element) const {} + void bind(const Element& element) {} // function to prepare the vol vars within the element - void bindElement(const Element& element) const {} + void bindElement(const Element& element) {} private: IndexType numScvs_; @@ -148,10 +151,10 @@ private: // Specialization when the current volume variables are not stored template -class VolumeVariablesVector +class CCVolumeVariablesVector { // prev vol vars have to be a friend class in order for the assignment operator to work - friend VolumeVariablesVector; + friend CCVolumeVariablesVector; friend ImplicitModel; using Problem = typename GET_PROP_TYPE(TypeTag, Problem); using GridView = typename GET_PROP_TYPE(TypeTag, GridView); @@ -159,16 +162,19 @@ class VolumeVariablesVector::Entity; - VolumeVariablesVector& operator= (const VolumeVariablesVector& other) = default; + CCVolumeVariablesVector& operator= (const CCVolumeVariablesVector& other) = default; - void operator= (const VolumeVariablesVector& other) + // operator curVolVars = prevVolVars + void operator= (const CCVolumeVariablesVector& other) { eIdxBound_ = -1; } - VolumeVariablesVector() : problemPtr_(nullptr), eIdxBound_(-1) {} + CCVolumeVariablesVector() : problemPtr_(nullptr), eIdxBound_(-1) {} public: @@ -181,39 +187,28 @@ public: // Binding of an element, prepares the volume variables within the element stencil // called by the local jacobian to prepare element assembly - // specialization for cc models - template - typename std::enable_if::type - bind(const Element& element) + void bind(const Element& element) { - const auto eIdx = problem_().elementMapper().index(element); - if (eIdx == eIdxBound_ && volVarIndices_.size() > 1) - return; - - eIdxBound_ = eIdx; + eIdxBound_ = problem_().elementMapper().index(element); - // make sure the FVElementGeometry is bound to the element - problem_().model().fvGeometries_().bind(element); - const auto& fvGeometry = problem_().model().fvGeometries(eIdx); - - // get stencil information + // stencil information const auto& elementStencil = problem_().model().stencils(element).elementStencil(); const auto& neighborStencil = problem_().model().stencils(element).neighborStencil(); const auto numDofs = elementStencil.size(); - // resize volume variables to the required size + // resize local containers to the required size (for internal elements) volumeVariables_.resize(numDofs); volVarIndices_.resize(numDofs); int localIdx = 0; // update the volume variables of the element at hand - const auto& scvI = problem_().model().fvGeometries().subControlVolume(eIdx); - const auto& solI = problem_().model().curSol()[eIdx]; + const auto& scvI = problem_().model().fvGeometries().subControlVolume(eIdxBound_); + const auto& solI = problem_().model().curSol()[eIdxBound_]; volumeVariables_[localIdx].update(solI, problem_(), element, scvI); volVarIndices_[localIdx] = scvI.index(); localIdx++; - // Update the volume variables of the neighboring elements and the boundary + // Update the volume variables of the neighboring elements for (auto globalJ : neighborStencil) { const auto& elementJ = problem_().model().fvGeometries().element(globalJ); @@ -224,7 +219,8 @@ public: localIdx++; } - // Check for boundary volume variables + // Update boundary volume variables + const auto& fvGeometry = problem_().model().fvGeometries(element); for (const auto& scvFace : fvGeometry.scvfs()) { // if we are not on a boundary, skip the rest @@ -233,12 +229,12 @@ public: // When complex boundary handling is inactive, we only use BC vol vars on pure Dirichlet boundaries const auto bcTypes = problem_().boundaryTypes(element, scvFace); - if (/*TODO !GET_PROP_VALUE(TypeTag, BoundaryReconstruction) && */!(bcTypes.hasDirichlet() && !bcTypes.hasNeumann())) + if (/*TODO !GET_PROP_VALUE(TypeTag, BoundaryReconstruction) && */bcTypes.hasNeumann() || bcTypes.hasOutflow()) continue; + const auto dirichletPriVars = problem_().dirichlet(element, scvFace); volumeVariables_.resize(localIdx+1); volVarIndices_.resize(localIdx+1); - const auto dirichletPriVars = problem_().dirichlet(element, scvFace); volumeVariables_[localIdx].update(dirichletPriVars, problem_(), element, scvI); volVarIndices_[localIdx] = scvFace.outsideScvIdx(); localIdx++; @@ -247,28 +243,25 @@ public: // Binding of an element, prepares only the volume variables of the element // specialization for cc models - template - typename std::enable_if::type - bindElement(const Element& element) + void bindElement(const Element& element) { - const auto eIdx = problem_().elementMapper().index(element); - if (eIdx == eIdxBound_ || std::find(volVarIndices_.begin(), volVarIndices_.end(), eIdx) != volVarIndices_.end()) - return; - + eIdxBound_ = problem_().elementMapper().index(element); volumeVariables_.resize(1); volVarIndices_.resize(1); - eIdxBound_ = eIdx; - - // make sure the FVElementGeometry is bound to the element - problem_().model().fvGeometries_().bindElement(element); // update the volume variables of the element at hand - const auto& scv = problem_().model().fvGeometries().subControlVolume(eIdx); - const auto& sol = problem_().model().curSol()[eIdx]; + const auto& scv = problem_().model().fvGeometries().subControlVolume(eIdxBound_); + const auto& sol = problem_().model().curSol()[eIdxBound_]; volumeVariables_[0].update(sol, problem_(), element, scv); volVarIndices_[0] = scv.index(); } + const VolumeVariables& operator [](const SubControlVolume& scv) const + { return (*this)[scv.index()]; } + + VolumeVariables& operator [](const SubControlVolume& scv) + { return (*this)[scv.index()]; } + const VolumeVariables& operator [](IndexType scvIdx) const { return volumeVariables_[getLocalIdx_(scvIdx)]; @@ -309,10 +302,10 @@ private: // Specialization when the previous volume variables are not stored template -class VolumeVariablesVector +class CCVolumeVariablesVector { // current vol vars have to be a friend class in order for the assignment operator to work - friend VolumeVariablesVector; + friend CCVolumeVariablesVector; friend ImplicitModel; using Problem = typename GET_PROP_TYPE(TypeTag, Problem); using GridView = typename GET_PROP_TYPE(TypeTag, GridView); @@ -320,9 +313,12 @@ class VolumeVariablesVector::Entity; + using Vertex = typename GridView::template Codim::Entity; - VolumeVariablesVector& operator= (const VolumeVariablesVector& other) + CCVolumeVariablesVector& operator= (const CCVolumeVariablesVector& other) { release_(); problemPtr_ = other.problemPtr_; @@ -330,7 +326,7 @@ class VolumeVariablesVector - typename std::enable_if::type - bindElement(const Element& element) + void bindElement(const Element& element) { - const auto eIdx = problem_().elementMapper().index(element); - if (eIdx == eIdxBound_) - return; - + eIdxBound_ = problem_().elementMapper().index(element); volumeVariables_.resize(1); volVarIndices_.resize(1); - eIdxBound_ = eIdx; - - // make sure FVElementGeometry is bound to the element - problem_().model().fvGeometries_().bindElement(element); // update the volume variables of the element at hand - const auto& scv = problem_().model().fvGeometries().subControlVolume(eIdx); - const auto& sol = problem_().model().prevSol()[eIdx]; + const auto& scv = problem_().model().fvGeometries().subControlVolume(eIdxBound_); + const auto& sol = problem_().model().prevSol()[eIdxBound_]; volumeVariables_[0].update(sol, problem_(), element, scv); volVarIndices_[0] = scv.index(); } + const VolumeVariables& operator [](const SubControlVolume& scv) const + { return (*this)[scv.index()]; } + + VolumeVariables& operator [](const SubControlVolume& scv) + { return (*this)[scv.index()]; } + const VolumeVariables& operator [](IndexType scvIdx) const { return volumeVariables_[getLocalIdx_(scvIdx)]; diff --git a/dumux/implicit/properties.hh b/dumux/implicit/properties.hh index f766aa411b..c4effc39f9 100644 --- a/dumux/implicit/properties.hh +++ b/dumux/implicit/properties.hh @@ -61,7 +61,7 @@ NEW_PROP_TAG(SubControlVolume);//!< The type of the sub control volume NEW_PROP_TAG(SubControlVolumeFace); //!< The type of the sub control volume face NEW_PROP_TAG(FVElementGeometry); //!< The type of the finite volume geometry (iterators over scvs, scvfs) NEW_PROP_TAG(FVElementGeometryVector); //!< The type of the finite volume geometry vector -NEW_PROP_TAG(EnableFVElementGeometryCache); //! specifies if geometric data is be saved (faster, but more memory consuming) +NEW_PROP_TAG(EnableGlobalFVElementGeometryCache); //! specifies if geometric data is be saved (faster, but more memory consuming) NEW_PROP_TAG(JacobianAssembler); //!< Assembles the global jacobian matrix NEW_PROP_TAG(JacobianMatrix); //!< Type of the global jacobian matrix @@ -72,14 +72,14 @@ NEW_PROP_TAG(PrimaryVariables); //!< A vector of primary variables within a sub- NEW_PROP_TAG(SolutionVector); //!< Vector containing all primary variable vector of the grid NEW_PROP_TAG(ElementSolutionVector); //!< A vector of primary variables within a sub-control volume -NEW_PROP_TAG(EnableVolumeVariablesCache); //!< If disabled, the volume variables are not stored (reduces memory, but is slower) +NEW_PROP_TAG(EnableGlobalVolumeVariablesCache); //!< If disabled, the volume variables are not stored (reduces memory, but is slower) NEW_PROP_TAG(VolumeVariables); //!< The secondary variables within a sub-control volume NEW_PROP_TAG(CurrentVolumeVariablesVector); //!< The type for a container of current volume variables NEW_PROP_TAG(PreviousVolumeVariablesVector); //!< The type for a container of previous volume variables NEW_PROP_TAG(FluxVariables); //!< Container storing the different types of flux variables NEW_PROP_TAG(FluxVariablesCache); //!< Stores data associated with flux vars (if enabled) NEW_PROP_TAG(FluxVariablesCacheVector); //!< The global vector of flux variable containers -NEW_PROP_TAG(EnableFluxVariablesCache); //! specifies if data on flux vars should be saved (faster, but more memory consuming) +NEW_PROP_TAG(EnableGlobalFluxVariablesCache); //! specifies if data on flux vars should be saved (faster, but more memory consuming) NEW_PROP_TAG(BoundaryVariables); //!< Data required to calculate fluxes over boundary faces in cc models(outflow) NEW_PROP_TAG(ConstantBoundaryConditions); //!< boundary data is stored in case the BC are constant diff --git a/dumux/implicit/propertydefaults.hh b/dumux/implicit/propertydefaults.hh index 3ba11dd9e2..c6df857949 100644 --- a/dumux/implicit/propertydefaults.hh +++ b/dumux/implicit/propertydefaults.hh @@ -175,13 +175,13 @@ SET_BOOL_PROP(ImplicitBase, ImplicitEnableJacobianRecycling, false); SET_BOOL_PROP(ImplicitBase, ImplicitEnablePartialReassemble, false); //! We do not store the FVGeometry by default -SET_BOOL_PROP(ImplicitBase, EnableFVElementGeometryCache, false); +SET_BOOL_PROP(ImplicitBase, EnableGlobalFVElementGeometryCache, false); //! We do not store the volume variables by default -SET_BOOL_PROP(ImplicitBase, EnableVolumeVariablesCache, false); +SET_BOOL_PROP(ImplicitBase, EnableGlobalVolumeVariablesCache, false); //! disable flux variables data caching by default -SET_BOOL_PROP(ImplicitBase, EnableFluxVariablesCache, false); +SET_BOOL_PROP(ImplicitBase, EnableGlobalFluxVariablesCache, false); //! boundary conditions are not stationary by default SET_BOOL_PROP(ImplicitBase, ConstantBoundaryConditions, false); -- GitLab From 87e6b40f806aab6cf6986fad5046d35d2450acca Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 5 Jul 2016 11:03:36 +0200 Subject: [PATCH 13/45] [box][fvgeomvector] specialize class to enableGlobalCaching property --- dumux/implicit/box/fvelementgeometryvector.hh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/dumux/implicit/box/fvelementgeometryvector.hh b/dumux/implicit/box/fvelementgeometryvector.hh index b7e5a12ffc..486e886baa 100644 --- a/dumux/implicit/box/fvelementgeometryvector.hh +++ b/dumux/implicit/box/fvelementgeometryvector.hh @@ -358,8 +358,13 @@ public: * This builds up the sub control volumes and sub control volume faces * for each element. */ -template +template class BoxFVElementGeometryVector +{}; + +// specialization in case the FVElementGeometries are stored +template +class BoxFVElementGeometryVector { using Problem = typename GET_PROP_TYPE(TypeTag, Problem); using GridView = typename GET_PROP_TYPE(TypeTag, GridView); -- GitLab From 5468c285d3eb97fe2cf2f1cd74c30201a8d27df9 Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 5 Jul 2016 11:05:23 +0200 Subject: [PATCH 14/45] [tpfa][fvgeomvector] capitalize template parameter --- dumux/implicit/cellcentered/tpfa/fvelementgeometryvector.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dumux/implicit/cellcentered/tpfa/fvelementgeometryvector.hh b/dumux/implicit/cellcentered/tpfa/fvelementgeometryvector.hh index 96081fd91c..a705b9b4c3 100644 --- a/dumux/implicit/cellcentered/tpfa/fvelementgeometryvector.hh +++ b/dumux/implicit/cellcentered/tpfa/fvelementgeometryvector.hh @@ -39,7 +39,7 @@ namespace Dumux * This builds up the sub control volumes and sub control volume faces * for each element. */ -template +template class CCTpfaFVElementGeometryVector {}; -- GitLab From ea8296be5607ed71f7cf6cb71f2dd6e8b8489079 Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 5 Jul 2016 11:09:15 +0200 Subject: [PATCH 15/45] [tpfa][fvgeomvec] return fvgeoms only for elements --- dumux/implicit/cellcentered/localjacobian.hh | 10 ++-------- .../cellcentered/tpfa/fvelementgeometryvector.hh | 9 ++------- dumux/implicit/model.hh | 5 +---- 3 files changed, 5 insertions(+), 19 deletions(-) diff --git a/dumux/implicit/cellcentered/localjacobian.hh b/dumux/implicit/cellcentered/localjacobian.hh index 0cf4858490..41b4709569 100644 --- a/dumux/implicit/cellcentered/localjacobian.hh +++ b/dumux/implicit/cellcentered/localjacobian.hh @@ -124,8 +124,8 @@ public: assemblyMap_[globalI].reserve(neighborStencil.size()); for (auto globalJ : neighborStencil) { - const auto& fvGeometry = this->model_().fvGeometries(globalJ); const auto& elementJ = this->model_().fvGeometries().element(globalJ); + const auto& fvGeometry = this->model_().fvGeometries(elementJ); // find the flux vars needed for the calculation of the flux into element std::vector fluxVarIndices; @@ -166,7 +166,7 @@ public: // finite volume geometry globalI_ = this->problem_().elementMapper().index(element); - const auto& fvGeometry = fvElemGeom_(); + const auto& fvGeometry = this->model_().fvGeometries(element); bcTypes_.update(this->problem_(), element, fvGeometry); // calculate the local residual @@ -339,12 +339,6 @@ public: } } - - const FVElementGeometry& fvElemGeom_() const - { - return this->model_().fvGeometries(globalI_); - } - IndexType globalI_; ElementBoundaryTypes bcTypes_; diff --git a/dumux/implicit/cellcentered/tpfa/fvelementgeometryvector.hh b/dumux/implicit/cellcentered/tpfa/fvelementgeometryvector.hh index a705b9b4c3..d088663ff8 100644 --- a/dumux/implicit/cellcentered/tpfa/fvelementgeometryvector.hh +++ b/dumux/implicit/cellcentered/tpfa/fvelementgeometryvector.hh @@ -64,9 +64,9 @@ public: * \note The finite volume geometry offers iterators over the sub control volumes * and the sub control volume faces of an element. */ - const FVElementGeometry& fvGeometry(IndexType eIdx) const + const FVElementGeometry& fvGeometry(const Element& element) const { - return fvGeometries_[eIdx]; + return fvGeometries_[problem_().elementMapper().index(element)]; } //! Get a sub control volume with a global scv index @@ -197,11 +197,6 @@ public: * \note The finite volume geometry offers iterators over the sub control volumes * and the sub control volume faces of an element. */ - const FVElementGeometry& fvGeometry(IndexType eIdx) const - { - return fvGeometries_[getStencilScvIdx_(eIdx)]; - } - const FVElementGeometry& fvGeometry(const Element& element) const { return fvGeometries_[getStencilScvIdx_(problem_().elementMapper().index(element))]; diff --git a/dumux/implicit/model.hh b/dumux/implicit/model.hh index d666958efe..16e529f60f 100644 --- a/dumux/implicit/model.hh +++ b/dumux/implicit/model.hh @@ -806,10 +806,7 @@ public: { return *fvGeometryVector_; } const FVElementGeometry& fvGeometries(const Element& element) const - { return fvGeometryVector_->fvGeometry(elementMapper().index(element)); } - - const FVElementGeometry& fvGeometries(unsigned int eIdx) const - { return fvGeometryVector_->fvGeometry(eIdx); } + { return fvGeometryVector_->fvGeometry(element); } protected: -- GitLab From c796d330a094e44a7abc5d31d227478c6a890775 Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 5 Jul 2016 11:20:57 +0200 Subject: [PATCH 16/45] [cc][localjac] adapt interface to new call in assembler the local jacobian now also gets the global residual passed as argument for the assemble routine and stores the values in it. --- dumux/implicit/cellcentered/localjacobian.hh | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/dumux/implicit/cellcentered/localjacobian.hh b/dumux/implicit/cellcentered/localjacobian.hh index 41b4709569..7425039819 100644 --- a/dumux/implicit/cellcentered/localjacobian.hh +++ b/dumux/implicit/cellcentered/localjacobian.hh @@ -83,6 +83,7 @@ class CCLocalJacobian : public ImplicitLocalJacobian typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes; + typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector; typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; @@ -153,7 +154,7 @@ public: * * \param element The DUNE Codim<0> entity which we look at. */ - void assemble(const Element& element, JacobianMatrix& matrix) + void assemble(const Element& element, JacobianMatrix& matrix, SolutionVector& residual) { const bool isGhost = (element.partitionType() == Dune::GhostEntity); @@ -173,17 +174,20 @@ public: if (isGhost) { this->residual_ = 0.0; + residual[globalI_] = 0.0; } else { this->localResidual().eval(element, bcTypes_); this->residual_ = this->localResidual().residual(); + // store residual in global container as well + residual[globalI_] = this->localResidual().residual(0); } this->model_().updatePVWeights(fvGeometry); // calculate derivatives of all dofs in stencil with respect to the dofs in the element - evalPartialDerivatives_(element, matrix, isGhost); + evalPartialDerivatives_(element, matrix, residual, isGhost); // TODO: calculate derivatives in the case of an extended source stencil // const auto& extendedSourceStencil = model_().stencils(element).extendedSourceStencil(); @@ -200,7 +204,9 @@ public: // } } - void evalPartialDerivatives_(const Element& element, JacobianMatrix& matrix, const bool isGhost) + +private: + void evalPartialDerivatives_(const Element& element, JacobianMatrix& matrix, SolutionVector& residual, const bool isGhost) { // get stencil informations const auto& neighborStencil = this->model_().stencils(element).neighborStencil(); @@ -328,7 +334,7 @@ public: neighborDeriv /= delta; // restore the original state of the scv's volume variables - this->model_().curVolVars_(scv) = std::move(origVolVars); + this->model_().curVolVars_(scv) = origVolVars; // update the global jacobian matrix with the current partial derivatives this->updateGlobalJacobian_(matrix, globalI_, globalI_, pvIdx, partialDeriv); -- GitLab From 316f6eec8abe49ec9dc17a6a1eb437a545a01c35 Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 5 Jul 2016 11:22:57 +0200 Subject: [PATCH 17/45] [cc][localjac] remove unused typedefs --- dumux/implicit/cellcentered/localjacobian.hh | 2 -- 1 file changed, 2 deletions(-) diff --git a/dumux/implicit/cellcentered/localjacobian.hh b/dumux/implicit/cellcentered/localjacobian.hh index 7425039819..5f7e43a745 100644 --- a/dumux/implicit/cellcentered/localjacobian.hh +++ b/dumux/implicit/cellcentered/localjacobian.hh @@ -72,13 +72,11 @@ class CCLocalJacobian : public ImplicitLocalJacobian typedef typename GET_PROP_TYPE(TypeTag, LocalJacobian) Implementation; typedef typename GET_PROP_TYPE(TypeTag, LocalResidual) LocalResidual; typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, Model) Model; typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; typedef typename GET_PROP_TYPE(TypeTag, JacobianMatrix) JacobianMatrix; typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; typedef typename GET_PROP_TYPE(TypeTag, SubControlVolume) SubControlVolume; - typedef typename GET_PROP_TYPE(TypeTag, VertexMapper) VertexMapper; typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; -- GitLab From 10b0fff044d0cf65768447db37ae4f28b78cbb22 Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 5 Jul 2016 11:25:14 +0200 Subject: [PATCH 18/45] [cc][localjac] use compute stencil method in flux vars --- dumux/implicit/cellcentered/localjacobian.hh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dumux/implicit/cellcentered/localjacobian.hh b/dumux/implicit/cellcentered/localjacobian.hh index 5f7e43a745..109b1c9bf6 100644 --- a/dumux/implicit/cellcentered/localjacobian.hh +++ b/dumux/implicit/cellcentered/localjacobian.hh @@ -134,8 +134,7 @@ public: // if globalI is in flux var stencil, add to list FluxVariables fluxVars; - fluxVars.init(problem, elementJ, scvFaceJ); - const auto& fluxStencil = fluxVars.stencil(); + const auto fluxStencil = fluxVars.computeStencil(problem, elementJ, scvFaceJ); for (auto globalIdx : fluxStencil) if (globalIdx == globalI) fluxVarIndices.push_back(fluxVarsIdx); -- GitLab From 5f233e8f5d64f8c2e095ec464caf720b6305354d Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 5 Jul 2016 11:27:29 +0200 Subject: [PATCH 19/45] [cc][localjac] introduce return function for assembly map --- dumux/implicit/cellcentered/localjacobian.hh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dumux/implicit/cellcentered/localjacobian.hh b/dumux/implicit/cellcentered/localjacobian.hh index 109b1c9bf6..9767424060 100644 --- a/dumux/implicit/cellcentered/localjacobian.hh +++ b/dumux/implicit/cellcentered/localjacobian.hh @@ -201,6 +201,8 @@ public: // } } + const AssemblyMap& assemblyMap() const + { return assemblyMap_; } private: void evalPartialDerivatives_(const Element& element, JacobianMatrix& matrix, SolutionVector& residual, const bool isGhost) -- GitLab From 29115bf363db74b2610d0dff49ff33dc0cc9932d Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 5 Jul 2016 11:32:16 +0200 Subject: [PATCH 20/45] [implicit][fluxVarCacheVec] specialize flux var cache The flux var cache is now specialized for the box and cc methods and furthermore permits the binding of an element prior to flux calculations in order to recycle data later in the flux calculations when the global caching is disabled. --- .../cellcentered/fluxvariablescachevector.hh | 194 ++++++++++++++++++ dumux/implicit/cellcentered/localjacobian.hh | 7 +- dumux/implicit/fluxvariablescachevector.hh | 81 -------- .../constitutivelaws/darcyslaw.hh | 14 +- 4 files changed, 200 insertions(+), 96 deletions(-) create mode 100644 dumux/implicit/cellcentered/fluxvariablescachevector.hh delete mode 100644 dumux/implicit/fluxvariablescachevector.hh diff --git a/dumux/implicit/cellcentered/fluxvariablescachevector.hh b/dumux/implicit/cellcentered/fluxvariablescachevector.hh new file mode 100644 index 0000000000..ffae3dbf96 --- /dev/null +++ b/dumux/implicit/cellcentered/fluxvariablescachevector.hh @@ -0,0 +1,194 @@ +// -*- 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 . * + *****************************************************************************/ +/*! + * \file + * \brief Base class for the volume variables vector + */ +#ifndef DUMUX_IMPLICIT_CC_FLUXVARSCACHEVECTOR_HH +#define DUMUX_IMPLICIT_CC_FLUXVARSCACHEVECTOR_HH + +#include + +namespace Dumux +{ + +/*! + * \ingroup ImplicitModel + * \brief Base class for the flux variables cache vector, we store one cache per face + */ +template +class CCFluxVariablesCacheVector +{ + using Problem = typename GET_PROP_TYPE(TypeTag, Problem); + using GridView = typename GET_PROP_TYPE(TypeTag, GridView); + using IndexType = typename GridView::IndexSet::IndexType; + using Element = typename GridView::template Codim<0>::Entity; + using FluxVariablesCache = typename GET_PROP_TYPE(TypeTag, FluxVariablesCache); + using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); + +public: + // When global caching is enabled, precompute transmissibilities and stencils for all the scv faces + template + typename std::enable_if::type update(Problem& problem) + { + problemPtr_ = &problem; + + fluxVarsCache_.resize(problem.model().fvGeometries().numScvf()); + for (const auto& element : elements(problem.gridView())) + { + // Prepare the geometries within the elements of the stencil + problem.model().fvGeometries_().bind(element); + + const auto& fvGeometry = problem.model().fvGeometries(element); + for (const auto& scvf : fvGeometry.scvfs()) + { + (*this)[scvf].update(problem, element, scvf); + } + } + } + + // When global flux variables caching is disabled, we don't need to update the cache + template + typename std::enable_if::type update(Problem& problem) + { + problemPtr_ = &problem; + } + + // This function has to be called prior to flux calculations on the element. + // Prepares the transmissibilities of the scv faces in an element. The FvGeometry is assumed to be bound. + template + typename std::enable_if::type bindElement(const Element& element) + { + const auto& fvGeometry = problem_().model().fvGeometries(element); + + // resizing of the cache + const auto numScvf = fvGeometry.numScvf(); + fluxVarsCache_.resize(numScvf); + globalScvfIndices_.resize(numScvf); + IndexType localScvfIdx = 0; + + // fill the containers + for (const auto& scvf : fvGeometry.scvfs()) + { + fluxVarsCache_[localScvfIdx].update(problem_(), element, scvf); + globalScvfIndices_[localScvfIdx] = scvf.index(); + localScvfIdx++; + } + } + + // Specialization for the global caching being enabled - do nothing here + template + typename std::enable_if::type bindElement(const Element& element) {} + + // This function is called by the CCLocalResidual before flux calculations during assembly. + // Prepares the transmissibilities of the scv faces in the stencil. The FvGeometries are assumed to be bound. + template + typename std::enable_if::type bind(const Element& element) + { + const auto globalI = problem_().elementMapper().index(element); + const auto& fvGeometry = problem_().model().fvGeometries(element); + const auto& neighborStencil = problem_().model().stencils(element).neighborStencil(); + const auto numNeighbors = neighborStencil.size(); + + // find the number of scv faces that need to be prepared + IndexType numScvf = fvGeometry.numScvf(); + for (IndexType localIdxJ = 0; localIdxJ < numNeighbors; ++localIdxJ) + { + const auto& fluxVarIndicesJ = problem_().model().localJacobian().assemblyMap()[globalI][localIdxJ]; + numScvf += fluxVarIndicesJ.size(); + } + + // fill the containers with the data on the scv faces inside the actual element + fluxVarsCache_.resize(numScvf); + globalScvfIndices_.resize(numScvf); + IndexType localScvfIdx = 0; + for (const auto& scvf : fvGeometry.scvfs()) + { + fluxVarsCache_[localScvfIdx].update(problem_(), element, scvf); + globalScvfIndices_[localScvfIdx] = scvf.index(); + localScvfIdx++; + } + + // add required data on the scv faces in the neighboring elements + for (IndexType localIdxJ = 0; localIdxJ < numNeighbors; ++localIdxJ) + { + const auto& fluxVarIndicesJ = problem_().model().localJacobian().assemblyMap()[globalI][localIdxJ]; + const auto elementJ = problem_().model().fvGeometries().element(neighborStencil[localIdxJ]); + for (auto fluxVarIdx : fluxVarIndicesJ) + { + const auto& scvfJ = problem_().model().fvGeometries().subControlVolumeFace(fluxVarIdx); + fluxVarsCache_[localScvfIdx].update(problem_(), elementJ, scvfJ); + globalScvfIndices_[localScvfIdx] = scvfJ.index(); + localScvfIdx++; + } + } + } + + // Specialization for the global caching being enabled - do nothing here + template + typename std::enable_if::type bind(const Element& element) {} + + // access operators in the case of caching + template + const typename std::enable_if::type& + operator [](const SubControlVolumeFace& scvf) const + { return fluxVarsCache_[scvf.index()]; } + + template + typename std::enable_if::type& + operator [](const SubControlVolumeFace& scvf) + { return fluxVarsCache_[scvf.index()]; } + + // access operators in the case of no caching + template + const typename std::enable_if::type& + operator [](const SubControlVolumeFace& scvf) const + { return fluxVarsCache_[getLocalScvfIdx_(scvf.index())]; } + + template + typename std::enable_if::type& + operator [](const SubControlVolumeFace& scvf) + { return fluxVarsCache_[getLocalScvfIdx_(scvf.index())]; } + +private: + // get index of scvf in the local container + template + const typename std::enable_if::type + getLocalScvfIdx_(const int scvfIdx) const + { + auto it = std::find(globalScvfIndices_.begin(), globalScvfIndices_.end(), scvfIdx); + + if (it != globalScvfIndices_.end()) + return std::distance(globalScvfIndices_.begin(), it); + else + DUNE_THROW(Dune::InvalidStateException, "Could not find the flux vars cache for scvfIdx = " << scvfIdx); + } + + const Problem& problem_() const + { return *problemPtr_; } + + const Problem* problemPtr_; + + std::vector fluxVarsCache_; + std::vector globalScvfIndices_; +}; + +} // end namespace + +#endif diff --git a/dumux/implicit/cellcentered/localjacobian.hh b/dumux/implicit/cellcentered/localjacobian.hh index 9767424060..961f828d10 100644 --- a/dumux/implicit/cellcentered/localjacobian.hh +++ b/dumux/implicit/cellcentered/localjacobian.hh @@ -159,6 +159,7 @@ public: this->model_().fvGeometries_().bind(element); this->model_().curVolVars_().bind(element); this->model_().prevVolVars_().bindElement(element); + this->model_().fluxVariablesCache_().bind(element); // set the current grid element and update the element's // finite volume geometry @@ -259,8 +260,9 @@ private: priVars[pvIdx] += eps; delta += eps; - // update the volume variables + // update the volume variables and bind the flux var cache again this->model_().curVolVars_(scv).update(priVars, this->problem_(), element, scv); + this->model_().fluxVariablesCache_().bind(element); if (!isGhost) { @@ -297,8 +299,9 @@ private: priVars[pvIdx] -= delta + eps; delta += eps; - // update the volume variables + // update the volume variables and bind the flux var cache again this->model_().curVolVars_(scv).update(priVars, this->problem_(), element, scv); + this->model_().fluxVariablesCache_().bind(element); if (!isGhost) { diff --git a/dumux/implicit/fluxvariablescachevector.hh b/dumux/implicit/fluxvariablescachevector.hh deleted file mode 100644 index e426ac6dd2..0000000000 --- a/dumux/implicit/fluxvariablescachevector.hh +++ /dev/null @@ -1,81 +0,0 @@ -// -*- 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 . * - *****************************************************************************/ -/*! - * \file - * \brief Base class for the volume variables vector - */ -#ifndef DUMUX_IMPLICIT_FLUXVARSCACHEVECTOR_HH -#define DUMUX_IMPLICIT_FLUXVARSCACHEVECTOR_HH - -#include - -namespace Dumux -{ - -/*! - * \ingroup ImplicitModel - * \brief Base class for the flux variables cache vector, we store one cache per face - */ -template -class FluxVariablesCacheVector -{ - using Problem = typename GET_PROP_TYPE(TypeTag, Problem); - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using IndexType = typename GridView::IndexSet::IndexType; - using FluxVariablesCache = typename GET_PROP_TYPE(TypeTag, FluxVariablesCache); - using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); - -public: - template - typename std::enable_if::type update(Problem& problem) - { - fluxVarsCache_.resize(problem.model().fvGeometries().numScvf()); - for (const auto& element : elements(problem.gridView())) - { - // bind the geometries and volume variables to the element (all the elements in stencil) - problem.model().fvGeometries_().bind(element); - problem.model().curVolVars_().bind(element); - - const auto& fvGeometry = problem.model().fvGeometries(element); - for (const auto& scvf : fvGeometry.scvfs()) - { - (*this)[scvf.index()].update(problem, element, scvf); - } - } - } - - template - typename std::enable_if::type update(Problem& problem) - {} - - template - const typename std::enable_if::type& operator [](IndexType scvfIdx) const - { return fluxVarsCache_[scvfIdx]; } - - template - typename std::enable_if::type& operator [](IndexType scvfIdx) - { return fluxVarsCache_[scvfIdx]; } - -private: - std::vector fluxVarsCache_; -}; - -} // end namespace - -#endif diff --git a/dumux/porousmediumflow/constitutivelaws/darcyslaw.hh b/dumux/porousmediumflow/constitutivelaws/darcyslaw.hh index bdd907a423..91cb2e6869 100644 --- a/dumux/porousmediumflow/constitutivelaws/darcyslaw.hh +++ b/dumux/porousmediumflow/constitutivelaws/darcyslaw.hh @@ -82,7 +82,7 @@ public: const SubControlVolumeFace& scvFace, const IndexType phaseIdx) { - const auto& tij = getTransmissibilities(problem, scvFace); + const auto& tij = problem.model().fluxVarsCache(scvFace).tij(); // Get the inside volume variables const auto insideScvIdx = scvFace.insideScvIdx(); @@ -143,18 +143,6 @@ public: return stencil; } - template - static const typename std::enable_if::type& getTransmissibilities(const Problem& problem, const SubControlVolumeFace& scvFace) - { - return problem.model().fluxVarsCache(scvFace).tij(); - } - - template - static const typename std::enable_if::type getTransmissibilities(const Problem& problem, const SubControlVolumeFace& scvFace) - { - return calculateTransmissibilities(problem, scvFace); - } - static Scalar calculateTransmissibilities(const Problem& problem, const SubControlVolumeFace& scvFace) { Scalar tij; -- GitLab From 9fd106008664cf537d17380d39134fa19ef56c9e Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 5 Jul 2016 11:37:52 +0200 Subject: [PATCH 21/45] [implicit] reomve flux var vector This class has not been used since many commits ago. It was time to delete it. --- dumux/implicit/fluxvariablesvector.hh | 74 --------------------------- 1 file changed, 74 deletions(-) delete mode 100644 dumux/implicit/fluxvariablesvector.hh diff --git a/dumux/implicit/fluxvariablesvector.hh b/dumux/implicit/fluxvariablesvector.hh deleted file mode 100644 index 25547c8a5d..0000000000 --- a/dumux/implicit/fluxvariablesvector.hh +++ /dev/null @@ -1,74 +0,0 @@ -// -*- 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 . * - *****************************************************************************/ -/*! - * \file - * \brief Base class for the volume variables vector - */ -#ifndef DUMUX_IMPLICIT_FLUXVARSVECTOR_HH -#define DUMUX_IMPLICIT_FLUXVARSVECTOR_HH - -#include - -namespace Dumux -{ - -/*! - * \ingroup ImplicitModel - * \brief Base class for the flux variables vector, we always have darcy flux variables per face - */ -template -class FluxVariablesVector -{ - using Problem = typename GET_PROP_TYPE(TypeTag, Problem); - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using IndexType = typename GridView::IndexSet::IndexType; - using FluxVariables = typename GET_PROP_TYPE(TypeTag, FluxVariables); - using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); - -public: - void update(const Problem& problem) - { - fluxVars_.resize(problem.model().fvGeometries().numScvf()); - for (const auto& element : elements(problem.gridView())) - { - for (auto&& scvf : problem.model().fvGeometries(element).scvfs()) - { - (*this)[scvf.index()].update(problem, element, scvf); - } - - } - } - - const FluxVariables& operator [](IndexType scvfIdx) const - { - return fluxVars_[scvfIdx]; - } - - FluxVariables& operator [](IndexType scvfIdx) - { - return fluxVars_[scvfIdx]; - } - -private: - std::vector fluxVars_; -}; - -} // end namespace - -#endif -- GitLab From d082bad3ecf7169a1233b446336fa320fa3f40b9 Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 5 Jul 2016 11:42:55 +0200 Subject: [PATCH 22/45] [implicit][propdefaults] remove setting of vol var props --- dumux/implicit/propertydefaults.hh | 8 -------- 1 file changed, 8 deletions(-) diff --git a/dumux/implicit/propertydefaults.hh b/dumux/implicit/propertydefaults.hh index c6df857949..03b308d797 100644 --- a/dumux/implicit/propertydefaults.hh +++ b/dumux/implicit/propertydefaults.hh @@ -46,7 +46,6 @@ #include "assembler.hh" #include "localjacobian.hh" #include "volumevariables.hh" -#include "volumevariablesvector.hh" #include "fluxvariablescachevector.hh" #include "fvelementgeometry.hh" @@ -114,15 +113,8 @@ SET_TYPE_PROP(ImplicitBase, FVElementGeometry, Dumux::FVElementGeometry //! The volume variable class, to be overloaded by the model SET_TYPE_PROP(ImplicitBase, VolumeVariables, Dumux::ImplicitVolumeVariables); -//! The global current volume variables vector class -SET_TYPE_PROP(ImplicitBase, CurrentVolumeVariablesVector, Dumux::VolumeVariablesVector); - -//! The global previous volume variables vector class -SET_TYPE_PROP(ImplicitBase, PreviousVolumeVariablesVector, Dumux::VolumeVariablesVector); - //! The global flux variables cache vector class SET_TYPE_PROP(ImplicitBase, FluxVariablesCacheVector, Dumux::FluxVariablesCacheVector); - //! The class that contains the different flux variables (i.e. darcy, diffusion, energy) //! by default, we set the flux variables to ones for porous media SET_PROP(ImplicitBase, FluxVariables) -- GitLab From 6e433d083f1ff8598f0c96532a886a8a355c07bb Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 5 Jul 2016 11:51:22 +0200 Subject: [PATCH 23/45] [tpfa] restructure fv geometry vector --- .../tpfa/fvelementgeometryvector.hh | 153 ++++++++++-------- 1 file changed, 85 insertions(+), 68 deletions(-) diff --git a/dumux/implicit/cellcentered/tpfa/fvelementgeometryvector.hh b/dumux/implicit/cellcentered/tpfa/fvelementgeometryvector.hh index d088663ff8..1320104471 100644 --- a/dumux/implicit/cellcentered/tpfa/fvelementgeometryvector.hh +++ b/dumux/implicit/cellcentered/tpfa/fvelementgeometryvector.hh @@ -110,16 +110,28 @@ public: //! update all fvElementGeometries (do this again after grid adaption) void update(const Problem& problem) { + problemPtr_ = &problem; + + // clear containers (necessary after grid refinement) scvs_.clear(); scvfs_.clear(); fvGeometries_.clear(); elementMap_.clear(); - // Build the SCV and SCV faces + // determine size of containers + IndexType numScvs = gridView_.size(0); + IndexType numScvf = 0; + for (const auto& element : elements(gridView_)) + numScvf += element.subEntities(1); + + // reserve memory + elementMap_.resize(numScvs); + scvs_.resize(numScvs); + scvfs_.reserve(numScvf); + + // Build the scvs and scv faces IndexType scvfIdx = 0; numBoundaryScvf_ = 0; - elementMap_.resize(gridView_.size(0)); - scvs_.resize(gridView_.size(0)); for (const auto& element : elements(gridView_)) { auto eIdx = problem.elementMapper().index(element); @@ -129,31 +141,33 @@ public: elementMap_[eIdx] = element.seed(); // the element-wise index sets for finite volume geometry - std::vector scvfsIndexSet; + std::vector scvfsIndexSet(element.subEntities(1)); for (const auto& intersection : intersections(gridView_, element)) { // inner sub control volume faces if (intersection.neighbor()) { auto nIdx = problem.elementMapper().index(intersection.outside()); - scvfs_.push_back(SubControlVolumeFace(intersection.geometry(), - intersection.geometry().center(), - intersection.centerUnitOuterNormal(), - scvfIdx, - std::vector({eIdx, nIdx}), - false)); - scvfsIndexSet.push_back(scvfIdx++); + scvfs_.emplace_back(SubControlVolumeFace(intersection.geometry(), + intersection.geometry().center(), + intersection.centerUnitOuterNormal(), + scvfIdx, + intersection.indexInInside(), + std::vector({eIdx, nIdx}), + false)); + scvfsIndexSet[intersection.indexInInside()] = scvfIdx++; } // boundary sub control volume faces else if (intersection.boundary()) { - scvfs_.push_back(SubControlVolumeFace(intersection.geometry(), - intersection.geometry().center(), - intersection.centerUnitOuterNormal(), - scvfIdx, - std::vector({eIdx, gridView_.size(0) + numBoundaryScvf_++}), - true)); - scvfsIndexSet.push_back(scvfIdx++); + scvfs_.emplace_back(SubControlVolumeFace(intersection.geometry(), + intersection.geometry().center(), + intersection.centerUnitOuterNormal(), + scvfIdx, + intersection.indexInInside(), + std::vector({eIdx, gridView_.size(0) + numBoundaryScvf_++}), + true)); + scvfsIndexSet[intersection.indexInInside()] = scvfIdx++; } } @@ -168,6 +182,11 @@ public: void bindElement(const Element& element) {} private: + const Problem& problem_() const + { return *problemPtr_; } + + const Problem* problemPtr_; + GridView gridView_; Dumux::ElementMap elementMap_; std::vector> scvs_; @@ -199,19 +218,19 @@ public: */ const FVElementGeometry& fvGeometry(const Element& element) const { - return fvGeometries_[getStencilScvIdx_(problem_().elementMapper().index(element))]; + return fvGeometries_[getLocalScvIdx_(problem_().elementMapper().index(element), true)]; } //! Get a sub control volume with a global scv index const SubControlVolume& subControlVolume(IndexType scvIdx) const { - return stencilScvs_[getStencilScvIdx_(scvIdx)]; + return localSvs_[getLocalScvIdx_(scvIdx)]; } //! Get a sub control volume face with a global scvf index const SubControlVolumeFace& subControlVolumeFace(IndexType scvfIdx) const { - return stencilScvfs_[getStencilScvFaceIdx_(scvfIdx)]; + return localScvfs_[getLocalScvFaceIdx_(scvfIdx)]; } //! The total number of sub control volumes @@ -245,16 +264,17 @@ public: { problemPtr_ = &problem; elementMap_.clear(); - scvFaceToElementMap_.clear(); eIdxBound_ = -1; - // Build the SCV and SCV faces + // reserve memory or resize the containers + numScvs_ = gridView_.size(0); numScvf_ = 0; numBoundaryScvf_ = 0; - numScvs_ = gridView_.size(0); elementMap_.resize(numScvs_); scvFaceIndices_.resize(numScvs_); neighborVolVarIndices_.resize(numScvs_); + + // Build the SCV and SCV face for (const auto& element : elements(gridView_)) { auto eIdx = problem.elementMapper().index(element); @@ -263,24 +283,24 @@ public: elementMap_[eIdx] = element.seed(); // the element-wise index sets for finite volume geometry - std::vector scvfsIndexSet; - std::vector neighborVolVarIndexSet; + IndexType numLocalFaces = element.subEntities(1); + std::vector scvfsIndexSet(numLocalFaces); + std::vector neighborVolVarIndexSet(numLocalFaces); for (const auto& intersection : intersections(gridView_, element)) { + IndexType localFaceIdx = intersection.indexInInside(); // inner sub control volume faces if (intersection.neighbor()) { - scvFaceToElementMap_.push_back(eIdx); - scvfsIndexSet.push_back(numScvf_++); + scvfsIndexSet[localFaceIdx] = numScvf_++; auto nIdx = problem.elementMapper().index(intersection.outside()); - neighborVolVarIndexSet.push_back(nIdx); + neighborVolVarIndexSet[localFaceIdx] = nIdx; } // boundary sub control volume faces else if (intersection.boundary()) { - scvFaceToElementMap_.push_back(eIdx); - scvfsIndexSet.push_back(numScvf_++); - neighborVolVarIndexSet.push_back(numScvs_ + numBoundaryScvf_++); + scvfsIndexSet[localFaceIdx] = numScvf_++; + neighborVolVarIndexSet[localFaceIdx] = numScvs_ + numBoundaryScvf_++; } } @@ -294,13 +314,8 @@ public: // called by the local jacobian to prepare element assembly void bind(const Element& element) { - const auto eIdx = problem_().elementMapper().index(element); - if (eIdxBound_ == eIdx && fvGeometries_.size() > 1) - return; - + eIdxBound_ = problem_().elementMapper().index(element); release_(); - eIdxBound_ = eIdx; - makeElementGeometries_(element); for (const auto& intersection : intersections(gridView_, element)) { @@ -312,13 +327,8 @@ public: // Binding of an element preparing the geometries only inside the element void bindElement(const Element& element) { - const auto eIdx = problem_().elementMapper().index(element); - if (eIdx == eIdxBound_ || std::find(stencilScvIndices_.begin(), stencilScvIndices_.end(), eIdx) != stencilScvIndices_.end() ) - return; - + eIdxBound_ = problem_().elementMapper().index(element); release_(); - eIdxBound_ = eIdx; - makeElementGeometries_(element); } @@ -327,10 +337,10 @@ private: void release_() { - stencilScvs_.clear(); - stencilScvIndices_.clear(); - stencilScvfs_.clear(); - stencilScvFaceIndices_.clear(); + localSvs_.clear(); + localScvIndices_.clear(); + localScvfs_.clear(); + localScvfIndices_.clear(); fvGeometries_.clear(); } @@ -338,9 +348,9 @@ private: { const auto eIdx = problem_().elementMapper().index(element); - std::vector scv({SubControlVolume(element.geometry(), eIdx)}); - stencilScvs_.push_back(scv[0]); - stencilScvIndices_.push_back(eIdx); + SubControlVolume scv(element.geometry(), eIdx); + localSvs_.push_back(scv); + localScvIndices_.push_back(eIdx); const auto& scvFaceIndices = scvFaceIndices_[eIdx]; const auto& neighborVolVarIndices = neighborVolVarIndices_[eIdx]; @@ -350,14 +360,15 @@ private: { if (intersection.neighbor() || intersection.boundary()) { - stencilScvfs_.push_back(SubControlVolumeFace(intersection.geometry(), + localScvfs_.push_back(SubControlVolumeFace(intersection.geometry(), intersection.geometry().center(), intersection.centerUnitOuterNormal(), scvFaceIndices[scvfCounter], + intersection.indexInInside(), std::vector({eIdx, neighborVolVarIndices[scvfCounter]}), intersection.boundary())); - stencilScvFaceIndices_.push_back(scvFaceIndices[scvfCounter]); + localScvfIndices_.push_back(scvFaceIndices[scvfCounter]); scvfCounter++; } } @@ -366,24 +377,31 @@ private: fvGeometries_.push_back(FVElementGeometry(*this, {eIdx}, scvFaceIndices)); } - const int getStencilScvIdx_(const int scvIdx) const + const int getLocalScvIdx_(const int scvIdx, bool isElement = false) const { - auto it = std::find(stencilScvIndices_.begin(), stencilScvIndices_.end(), scvIdx); + auto it = std::find(localScvIndices_.begin(), localScvIndices_.end(), scvIdx); - if (it != stencilScvIndices_.end()) - return std::distance(stencilScvIndices_.begin(), it); + if (it != localScvIndices_.end()) + return std::distance(localScvIndices_.begin(), it); else - DUNE_THROW(Dune::InvalidStateException, + { + if (!isElement) + DUNE_THROW(Dune::InvalidStateException, "Could not find the sub control volume for scvIdx = " << scvIdx << ", make sure to properly bind the FVGeometries to the element before using them."); + else + DUNE_THROW(Dune::InvalidStateException, + "You are trying to get the fvgeometry of element with index " << scvIdx << + ", but bound is the element " << eIdxBound_ << ". Please bind element before using the fvgeometry."); + } } - const int getStencilScvFaceIdx_(const int scvfIdx) const + const int getLocalScvFaceIdx_(const int scvfIdx) const { - auto it = std::find(stencilScvFaceIndices_.begin(), stencilScvFaceIndices_.end(), scvfIdx); + auto it = std::find(localScvfIndices_.begin(), localScvfIndices_.end(), scvfIdx); - if (it != stencilScvFaceIndices_.end()) - return std::distance(stencilScvFaceIndices_.begin(), it); + if (it != localScvfIndices_.end()) + return std::distance(localScvfIndices_.begin(), it); else DUNE_THROW(Dune::InvalidStateException, "Could not find the sub control volume face for scvfIdx = " << scvfIdx << @@ -401,18 +419,17 @@ private: IndexType numScvf_; IndexType numBoundaryScvf_; - // vectors that stores global data + // vectors that store the global data Dumux::ElementMap elementMap_; std::vector> scvFaceIndices_; std::vector> neighborVolVarIndices_; - std::vector scvFaceToElementMap_; // vectors to store the geometries temporarily after binding an element IndexType eIdxBound_; - std::vector stencilScvs_; - std::vector stencilScvIndices_; - std::vector stencilScvfs_; - std::vector stencilScvFaceIndices_; + std::vector localSvs_; + std::vector localScvIndices_; + std::vector localScvfs_; + std::vector localScvfIndices_; std::vector fvGeometries_; }; -- GitLab From 49e3c026e598faa8e7b2efcede2029323e6dbef8 Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 5 Jul 2016 11:53:45 +0200 Subject: [PATCH 24/45] [cc][localJac] fix comment --- dumux/implicit/cellcentered/localjacobian.hh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dumux/implicit/cellcentered/localjacobian.hh b/dumux/implicit/cellcentered/localjacobian.hh index 961f828d10..a25bd4d8be 100644 --- a/dumux/implicit/cellcentered/localjacobian.hh +++ b/dumux/implicit/cellcentered/localjacobian.hh @@ -161,8 +161,7 @@ public: this->model_().prevVolVars_().bindElement(element); this->model_().fluxVariablesCache_().bind(element); - // set the current grid element and update the element's - // finite volume geometry + // set the actual dof index globalI_ = this->problem_().elementMapper().index(element); const auto& fvGeometry = this->model_().fvGeometries(element); -- GitLab From 22c9d3aa600ac78f78cd3dae03db9deb4c276fa8 Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 5 Jul 2016 11:54:09 +0200 Subject: [PATCH 25/45] [cc][localJac] use of convenience function --- dumux/implicit/cellcentered/localjacobian.hh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dumux/implicit/cellcentered/localjacobian.hh b/dumux/implicit/cellcentered/localjacobian.hh index a25bd4d8be..3786c0ae89 100644 --- a/dumux/implicit/cellcentered/localjacobian.hh +++ b/dumux/implicit/cellcentered/localjacobian.hh @@ -285,7 +285,7 @@ private: // to calculate f(x + \epsilon) and we can recycle the // (already calculated) residual f(x) if (!isGhost) - partialDeriv = this->residual_[0]; + partialDeriv = this->residual(0); neighborDeriv = origFlux; } @@ -324,7 +324,7 @@ private: // calculate f(x - \epsilon) and we can recycle the // (already calculated) residual f(x) if (!isGhost) - partialDeriv -= this->residual_[0]; + partialDeriv -= this->residual(0); neighborDeriv -= origFlux; } -- GitLab From 0c7536197377d40bc05d88375d35ade23acdd292 Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 5 Jul 2016 11:55:32 +0200 Subject: [PATCH 26/45] [cc][localres] change boundary treatment the boundary treatment is now performed after all the interior fluxes have been calculated. This corresponds more to the previous implementation and is assumend to be more correct for mixed BCs. --- dumux/implicit/cellcentered/localresidual.hh | 47 ++++++++++++++------ 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/dumux/implicit/cellcentered/localresidual.hh b/dumux/implicit/cellcentered/localresidual.hh index c9e0b970b9..0d04f04f67 100644 --- a/dumux/implicit/cellcentered/localresidual.hh +++ b/dumux/implicit/cellcentered/localresidual.hh @@ -53,7 +53,7 @@ class CCLocalResidual : public ImplicitLocalResidual enum { constantBC = GET_PROP_VALUE(TypeTag, ConstantBoundaryConditions) }; - enum { enableVolVarsCache = GET_PROP_VALUE(TypeTag, EnableVolumeVariablesCache) }; + enum { enableVolVarsCache = GET_PROP_VALUE(TypeTag, EnableGlobalVolumeVariablesCache) }; typedef typename GridView::template Codim<0>::Entity Element; typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; @@ -70,23 +70,44 @@ public: protected: + void evalFluxes_() + { + // calculate the mass flux over the scv faces + const auto& fvGeometry = this->fvGeometry_(); + for (const auto& scvf : fvGeometry.scvfs()) + { + this->residual_[0] += this->asImp_().computeFlux_(scvf); + } + } + PrimaryVariables computeFlux_(const SubControlVolumeFace &scvf) { if (!scvf.boundary() /*TODO: || GET_PROP_VALUE(TypeTag, BoundaryReconstruction)*/) return this->asImp_().computeFlux(scvf); else - return this->asImp_().evalBoundary_(scvf); + return PrimaryVariables(0.0); + } - PrimaryVariables evalBoundary_(const SubControlVolumeFace &scvf) + void evalBoundary_() { - PrimaryVariables flux = evalBoundaryFluxes_(scvf); + const auto& fvGeometry = this->fvGeometry_(); + + for (const auto& scvf : fvGeometry.scvfs()) + { + if (scvf.boundary()) + this->residual_[0] += evalBoundaryFluxes_(scvf); + } // additionally treat mixed D/N conditions in a strong sense if (this->bcTypes_().hasDirichlet()) - this->asImp_().evalDirichlet_(flux, scvf); - - return flux; + { + for (const auto& scvf : fvGeometry.scvfs()) + { + if (scvf.boundary()) + this->asImp_().evalDirichlet_(scvf); + } + } } /*! @@ -99,11 +120,11 @@ protected: // evaluate the Neumann conditions at the boundary face PrimaryVariables flux(0); - if (bcTypes.hasNeumann()) + if (bcTypes.hasNeumann() /*TODO: && !GET_PROP_VALUE(TypeTag, BoundaryReconstruction)*/) flux += this->asImp_().evalNeumannSegment_(scvf, bcTypes); // TODO: evaluate the outflow conditions at the boundary face - //if (bcTypes.hasOutflow()) + //if (bcTypes.hasOutflow() /*TODO: && !GET_PROP_VALUE(TypeTag, BoundaryReconstruction)*/) // flux += this->asImp_().evalOutflowSegment_(&intersection, bcTypes); // evaluate the pure Dirichlet conditions at the boundary face @@ -117,12 +138,12 @@ protected: * \brief Evaluate Dirichlet conditions on faces that have mixed * Dirichlet/Neumann boundary conditions. */ - void evalDirichlet_(PrimaryVariables &flux, const SubControlVolumeFace &scvf) + void evalDirichlet_(const SubControlVolumeFace &scvf) { BoundaryTypes bcTypes = this->problem_().boundaryTypes(this->element_(), scvf); if (bcTypes.hasDirichlet() && bcTypes.hasNeumann()) - this->asImp_().evalDirichletSegmentMixed_(flux, scvf, bcTypes); + this->asImp_().evalDirichletSegmentMixed_(scvf, bcTypes); } /*! @@ -240,8 +261,7 @@ protected: * \brief Treat Dirichlet boundary conditions in a strong sense for a * single intersection that has mixed D/N boundary conditions */ - void evalDirichletSegmentMixed_(PrimaryVariables &flux, - const SubControlVolumeFace &scvf, + void evalDirichletSegmentMixed_(const SubControlVolumeFace &scvf, const BoundaryTypes &bcTypes) { // temporary vector to store the Dirichlet values @@ -257,7 +277,6 @@ protected: { auto pvIdx = bcTypes.eqToDirichletIndex(eqIdx); this->residual_[0][eqIdx] = priVars[pvIdx] - dirichletValues[pvIdx]; - flux[eqIdx] = 0; } } } -- GitLab From fc1ad170cc55d4c7458e8285c631e8d18b1cbcf5 Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 5 Jul 2016 11:58:05 +0200 Subject: [PATCH 27/45] [cc][propdefaults] set correct flux var cache prop --- dumux/implicit/cellcentered/propertydefaults.hh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dumux/implicit/cellcentered/propertydefaults.hh b/dumux/implicit/cellcentered/propertydefaults.hh index 4bdb5b09a2..1a7e56eb27 100644 --- a/dumux/implicit/cellcentered/propertydefaults.hh +++ b/dumux/implicit/cellcentered/propertydefaults.hh @@ -28,6 +28,8 @@ #define DUMUX_CC_PROPERTY_DEFAULTS_HH #include + +#include "fluxvariablescachevector.hh" #include "volumevariablesvector.hh" #include "elementboundarytypes.hh" #include "localresidual.hh" @@ -67,6 +69,9 @@ SET_TYPE_PROP(CCModel, CurrentVolumeVariablesVector, Dumux::CCVolumeVariablesVec //! The global previous volume variables vector class SET_TYPE_PROP(CCModel, PreviousVolumeVariablesVector, Dumux::CCVolumeVariablesVector); +//! The global flux variables cache vector class +SET_TYPE_PROP(CCModel, FluxVariablesCacheVector, Dumux::CCFluxVariablesCacheVector); + //! Set the BaseLocalResidual to CCLocalResidual SET_TYPE_PROP(CCModel, BaseLocalResidual, Dumux::CCLocalResidual); -- GitLab From f1010815e5bcddc80512dcde9584309eaf6c061b Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 5 Jul 2016 12:02:16 +0200 Subject: [PATCH 28/45] [implicit][fluxvars] pass element into the routines of the laws --- dumux/implicit/cellcentered/stencils.hh | 4 +-- dumux/implicit/fluxvariablesbase.hh | 24 +++++++------ .../constitutivelaws/darcyslaw.hh | 36 +++++++++---------- .../implicit/fluxvariables.hh | 21 +++++------ 4 files changed, 44 insertions(+), 41 deletions(-) diff --git a/dumux/implicit/cellcentered/stencils.hh b/dumux/implicit/cellcentered/stencils.hh index c0dcfea856..34e156c31f 100644 --- a/dumux/implicit/cellcentered/stencils.hh +++ b/dumux/implicit/cellcentered/stencils.hh @@ -52,7 +52,7 @@ public: for (const auto& scvf : fvGeometry.scvfs()) { FluxVariables fluxVars; - const auto& stencil = fluxVars.computeStencil(problem, scvf); + const auto& stencil = fluxVars.computeStencil(problem, element, scvf); elementStencil_.insert(elementStencil_.end(), stencil.begin(), stencil.end()); } @@ -63,7 +63,7 @@ public: auto globalI = problem.elementMapper().index(element); neighborStencil_ = elementStencil_; - //remove the element itself and possible ghost neighbors from the stencil + // remove the element itself and possible ghost neighbors from the neighbor stencil auto pred = [&problem, globalI](const int i) -> bool { if (i == globalI) diff --git a/dumux/implicit/fluxvariablesbase.hh b/dumux/implicit/fluxvariablesbase.hh index 5ac578db94..6fe0a78696 100644 --- a/dumux/implicit/fluxvariablesbase.hh +++ b/dumux/implicit/fluxvariablesbase.hh @@ -44,7 +44,8 @@ class FluxVariablesBase using Stencil = std::vector; using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); - enum{ enableFluxVarsCache = GET_PROP_VALUE(TypeTag, EnableFluxVariablesCache) }; + enum{ enableFluxVarsCache = GET_PROP_VALUE(TypeTag, EnableGlobalFluxVariablesCache) }; + enum{ isBox = GET_PROP_VALUE(TypeTag, ImplicitIsBox) }; public: FluxVariablesBase() : problemPtr_(nullptr), scvFacePtr_(nullptr) @@ -55,32 +56,34 @@ public: const SubControlVolumeFace &scvFace) { problemPtr_ = &problem; + elementPtr_ = &element; scvFacePtr_ = &scvFace; // update the stencil if needed if (!enableFluxVarsCache) - stencil_ = asImp_().computeStencil(problem, scvFace); + stencil_ = asImp_().computeStencil(problem, element, scvFace); } // when caching is enabled, get the stencil from the cache class template - const typename std::enable_if::type& stencil() const + const typename std::enable_if::type& stencil() const { return problem().model().fluxVarsCache(scvFace()).stencil(); } // when caching is disabled, return the private stencil variable. The update(...) routine has to be called beforehand. template - const typename std::enable_if::type& stencil() + const typename std::enable_if::type& stencil() { return stencil_; } const Problem& problem() const { return *problemPtr_; } + const Element& element() const + { return *elementPtr_; } + const SubControlVolumeFace& scvFace() const - { - return *scvFacePtr_; - } + { return *scvFacePtr_; } - Stencil computeStencil(const Problem& problem, const SubControlVolumeFace& scvFace) + Stencil computeStencil(const Problem& problem, const Element& element, const SubControlVolumeFace& scvFace) { DUNE_THROW(Dune::InvalidStateException, "computeStencil() routine is not provided by the implementation."); } private: @@ -97,8 +100,9 @@ private: return *static_cast(this); } - const Problem *problemPtr_; //! Pointer to the problem - const SubControlVolumeFace *scvFacePtr_; //! Pointer to the sub control volume face for which the flux variables are created + const Problem* problemPtr_; //! Pointer to the problem + const Element* elementPtr_; //! Pointer to the element at hand + const SubControlVolumeFace* scvFacePtr_; //! Pointer to the sub control volume face for which the flux variables are created Stencil stencil_; //! The flux stencil }; } // end namespace diff --git a/dumux/porousmediumflow/constitutivelaws/darcyslaw.hh b/dumux/porousmediumflow/constitutivelaws/darcyslaw.hh index 91cb2e6869..38c154c3db 100644 --- a/dumux/porousmediumflow/constitutivelaws/darcyslaw.hh +++ b/dumux/porousmediumflow/constitutivelaws/darcyslaw.hh @@ -41,7 +41,6 @@ namespace Dumux namespace Properties { // forward declaration of properties -NEW_PROP_TAG(NumPhases); NEW_PROP_TAG(ProblemEnableGravity); } @@ -63,15 +62,14 @@ class DarcysLaw::Entity Element; typedef typename GridView::IndexSet::IndexType IndexType; typedef std::vector Stencil; - using Element = typename GridView::template Codim<0>::Entity; enum { dim = GridView::dimension} ; enum { dimWorld = GridView::dimensionworld} ; - enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases)} ; typedef Dune::FieldMatrix DimWorldMatrix; typedef Dune::FieldVector GlobalPosition; @@ -79,17 +77,15 @@ class DarcysLaw stencil; + Stencil stencil; if (!scvFace.boundary()) { stencil.push_back(scvFace.insideScvIdx()); @@ -143,21 +138,24 @@ public: return stencil; } - static Scalar calculateTransmissibilities(const Problem& problem, const SubControlVolumeFace& scvFace) + // The flux variables cache has to be bound to an element prior to flux calculations + // During the binding, the transmissibilities will be computed and stored using the method below. + static Scalar calculateTransmissibilities(const Problem& problem, const Element& element, const SubControlVolumeFace& scvFace) { Scalar tij; const auto insideScvIdx = scvFace.insideScvIdx(); const auto& insideScv = problem.model().fvGeometries().subControlVolume(insideScvIdx); const auto insideK = problem.spatialParams().intrinsicPermeability(insideScv); - Scalar ti = calculateOmega_(problem, scvFace, insideK, insideScv); + Scalar ti = calculateOmega_(problem, scvFace, insideK, element, insideScv); if (!scvFace.boundary()) { const auto outsideScvIdx = scvFace.outsideScvIdx(); const auto& outsideScv = problem.model().fvGeometries().subControlVolume(outsideScvIdx); + const auto outsideElement = problem.model().fvGeometries().element(outsideScvIdx); const auto outsideK = problem.spatialParams().intrinsicPermeability(outsideScv); - Scalar tj = -1.0*calculateOmega_(problem, scvFace, outsideK, outsideScv); + Scalar tj = -1.0*calculateOmega_(problem, scvFace, outsideK, outsideElement, outsideScv); tij = scvFace.area()*(ti * tj)/(ti + tj); } @@ -171,7 +169,7 @@ public: private: - static Scalar calculateOmega_(const Problem& problem, const SubControlVolumeFace& scvFace, const DimWorldMatrix &K, const SubControlVolume &scv) + static Scalar calculateOmega_(const Problem& problem, const SubControlVolumeFace& scvFace, const DimWorldMatrix &K, const Element& element, const SubControlVolume &scv) { GlobalPosition Knormal; K.mv(scvFace.unitOuterNormal(), Knormal); @@ -181,19 +179,19 @@ private: distanceVector /= distanceVector.two_norm2(); Scalar omega = Knormal * distanceVector; - omega *= problem.model().curVolVars(scv).extrusionFactor(); + omega *= problem.boxExtrusionFactor(element, scv); return omega; } - static Scalar calculateOmega_(const Problem& problem, const SubControlVolumeFace& scvFace, Scalar K, const SubControlVolume &scv) + static Scalar calculateOmega_(const Problem& problem, const SubControlVolumeFace& scvFace, const Scalar K, const Element& element, const SubControlVolume &scv) { auto distanceVector = scvFace.center(); distanceVector -= scv.center(); distanceVector /= distanceVector.two_norm2(); Scalar omega = K * (distanceVector * scvFace.unitOuterNormal()); - omega *= problem.model().curVolVars(scv).extrusionFactor(); + omega *= problem.boxExtrusionFactor(element, scv); return omega; } diff --git a/dumux/porousmediumflow/implicit/fluxvariables.hh b/dumux/porousmediumflow/implicit/fluxvariables.hh index 97e3d5629f..3038322ea0 100644 --- a/dumux/porousmediumflow/implicit/fluxvariables.hh +++ b/dumux/porousmediumflow/implicit/fluxvariables.hh @@ -57,11 +57,11 @@ class PorousMediumFluxVariables : public FluxVariab using Stencil = std::vector; using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); using AdvectionType = typename GET_PROP_TYPE(TypeTag, AdvectionType); + using VolumeVariables = typename GET_PROP_TYPE(TypeTag, VolumeVariables); enum { isBox = GET_PROP_VALUE(TypeTag, ImplicitIsBox), - enableFluxVarsCache = GET_PROP_VALUE(TypeTag, EnableFluxVariablesCache), constantBC = GET_PROP_VALUE(TypeTag, ConstantBoundaryConditions) }; @@ -77,9 +77,10 @@ public: template Scalar advectiveFlux(const int phaseIdx, const FunctionType upwindFunction) { - Scalar flux = AdvectionType::flux(this->problem(), this->scvFace(), phaseIdx); + Scalar flux = AdvectionType::flux(this->problem(), this->element(), this->scvFace(), phaseIdx); - const auto& insideVolVars = this->problem().model().curVolVars(this->scvFace().insideScvIdx()); + const auto& insideScv = this->problem().model().fvGeometries().subControlVolume(this->scvFace().insideScvIdx()); + const auto& insideVolVars = this->problem().model().curVolVars(insideScv); const auto& outsideVolVars = this->problem().model().curVolVars(this->scvFace().outsideScvIdx()); if (std::signbit(flux)) @@ -88,8 +89,8 @@ public: return flux*upwindFunction(insideVolVars, outsideVolVars); } - Stencil computeStencil(const Problem& problem, const SubControlVolumeFace& scvFace) - { return AdvectionType::stencil(problem, scvFace); } + Stencil computeStencil(const Problem& problem, const Element& element, const SubControlVolumeFace& scvFace) + { return AdvectionType::stencil(problem, element, scvFace); } }; @@ -124,14 +125,14 @@ public: ParentType::init(problem, element, scvFace); for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) - advectiveFluxes_[phaseIdx] = AdvectionType::flux(problem, scvFace, phaseIdx); + advectiveFluxes_[phaseIdx] = AdvectionType::flux(problem, element, scvFace, phaseIdx); } - Stencil computeStencil(const Problem& problem, const SubControlVolumeFace& scvFace) + Stencil computeStencil(const Problem& problem, const Element& element, const SubControlVolumeFace& scvFace) { // unifiy advective and diffusive stencil - Stencil stencil = AdvectionType::stencil(problem, scvFace); - Stencil diffusionStencil = MolecularDiffusionType::stencil(problem, scvFace); + Stencil stencil = AdvectionType::stencil(problem, element, scvFace); + Stencil diffusionStencil = MolecularDiffusionType::stencil(problem, element, scvFace); stencil.insert(stencil.end(), diffusionStencil.begin(), diffusionStencil.end()); std::sort(stencil.begin(), stencil.end()); @@ -154,7 +155,7 @@ public: Scalar molecularDiffusionFlux(const int phaseIdx, const int compIdx) { - Scalar flux = MolecularDiffusionType::flux(this->problem(), this->scvFace(), phaseIdx, compIdx); + Scalar flux = MolecularDiffusionType::flux(this->problem(), this->element(), this->scvFace(), phaseIdx, compIdx); return flux; } -- GitLab From b350688a3ab0e021d7bd2bd0114aa7aab3b036db Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 5 Jul 2016 12:05:59 +0200 Subject: [PATCH 29/45] [cc] specialize flux var cache to discretization method --- .../cellcentered/tpfa/propertydefaults.hh | 3 - dumux/implicit/propertydefaults.hh | 3 + .../implicit/fluxvariablescache.hh | 65 ++++++++++++------- 3 files changed, 44 insertions(+), 27 deletions(-) diff --git a/dumux/implicit/cellcentered/tpfa/propertydefaults.hh b/dumux/implicit/cellcentered/tpfa/propertydefaults.hh index 5744cc237a..48af42db4d 100644 --- a/dumux/implicit/cellcentered/tpfa/propertydefaults.hh +++ b/dumux/implicit/cellcentered/tpfa/propertydefaults.hh @@ -66,9 +66,6 @@ public: typedef Dumux::SubControlVolumeFace type; }; -//! The flux variables cache class, by default the one for porous media -SET_TYPE_PROP(CCTpfaModel, FluxVariablesCache, Dumux::CCTpfaPorousMediumFluxVariablesCache); - } // namespace Properties } // namespace Dumux diff --git a/dumux/implicit/propertydefaults.hh b/dumux/implicit/propertydefaults.hh index 03b308d797..dd24106871 100644 --- a/dumux/implicit/propertydefaults.hh +++ b/dumux/implicit/propertydefaults.hh @@ -127,6 +127,9 @@ public: typedef Dumux::PorousMediumFluxVariables type; }; +//! The flux variables cache class, by default the one for porous media +SET_TYPE_PROP(ImplicitBase, FluxVariablesCache, Dumux::PorousMediumFluxVariablesCache); + //! We use darcys law as the default for the advective flux calculation SET_TYPE_PROP(ImplicitBase, AdvectionType, Dumux::DarcysLaw); diff --git a/dumux/porousmediumflow/implicit/fluxvariablescache.hh b/dumux/porousmediumflow/implicit/fluxvariablescache.hh index 5212045676..3bf64405ee 100644 --- a/dumux/porousmediumflow/implicit/fluxvariablescache.hh +++ b/dumux/porousmediumflow/implicit/fluxvariablescache.hh @@ -24,28 +24,27 @@ #define DUMUX_POROUSMEDIUM_IMPLICIT_FLUXVARIABLESCACHE_HH #include +#include namespace Dumux { -namespace Properties -{ -NEW_PROP_TAG(NumPhases); -NEW_PROP_TAG(NumComponents); -} - /*! * \ingroup ImplicitModel - * \brief The flux variables cache classes - * stores the transmissibilities and stencils + * \brief The flux variables cache classes for porous media. + * Store flux stencils and data required for flux calculation */ +template +class PorousMediumFluxVariablesCache {}; + // specialization for the Box Method template -class BoxPorousMediumFluxVariablesCache +class PorousMediumFluxVariablesCache::type > { using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); using Problem = typename GET_PROP_TYPE(TypeTag, Problem); using GridView = typename GET_PROP_TYPE(TypeTag, GridView); + using FluxVariables = typename GET_PROP_TYPE(TypeTag, FluxVariables); using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); using AdvectionType = typename GET_PROP_TYPE(TypeTag, AdvectionType); using Element = typename GridView::template Codim<0>::Entity; @@ -53,34 +52,52 @@ class BoxPorousMediumFluxVariablesCache using Stencil = std::vector; using TransmissibilityVector = std::vector; + typedef typename GridView::ctype CoordScalar; + static const int dim = GridView::dimension; + typedef Dune::PQkLocalFiniteElementCache FeCache; + typedef typename FeCache::FiniteElementType::Traits::LocalBasisType FeLocalBasis; + typedef typename FeLocalBasis::Traits::JacobianType ShapeJacobian; + typedef typename Dune::FieldVector ShapeValue; + typedef typename Element::Geometry::JacobianInverseTransposed JacobianInverseTransposed; + public: + // stores required data for the flux calculation + struct FaceData + { + std::vector localJacobian; + std::vector shapeValues; + JacobianInverseTransposed jacInvT; + }; + void update(const Problem& problem, const Element& element, + const typename Element::Geometry& geometry, + const FeLocalBasis& localBasis, const SubControlVolumeFace &scvFace) { - stencil_ = AdvectionType::stencil(problem, scvFace); - volVarsStencil_ = AdvectionType::volVarsStencil(problem, element, scvFace); - tij_ = AdvectionType::calculateTransmissibilities(problem, scvFace); - } + faceData_ = AdvectionType::calculateFaceData(problem, element, geometry, localBasis, scvFace); - const Stencil& stencil() const - { return stencil_; } + // The stencil info is obsolete for the box method. + // It is here for compatibility with cc methods + stencil_ = Stencil(0); + } - const Stencil& darcyStencil() const - { return volVarsStencil_; } + const FaceData& faceData() const + { return faceData_; } - const TransmissibilityVector& tij() const - { return tij_; } + const Stencil& stencil() const + { + return stencil_; + } private: - Stencil volVarsStencil_; + FaceData faceData_; Stencil stencil_; - TransmissibilityVector tij_; }; // specialization for the cell centered tpfa method template -class CCTpfaPorousMediumFluxVariablesCache +class PorousMediumFluxVariablesCache::type > { using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); using Problem = typename GET_PROP_TYPE(TypeTag, Problem); @@ -98,8 +115,8 @@ public: const SubControlVolumeFace &scvFace) { FluxVariables fluxVars; - stencil_ = fluxVars.computeStencil(problem, scvFace); - tij_ = AdvectionType::calculateTransmissibilities(problem, scvFace); + stencil_ = fluxVars.computeStencil(problem, element, scvFace); + tij_ = AdvectionType::calculateTransmissibilities(problem, element, scvFace); } const Stencil& stencil() const -- GitLab From 1025be894947e219b6b0ac94d4410b69a44328fd Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 5 Jul 2016 12:06:59 +0200 Subject: [PATCH 30/45] [implicit][localjac] specialize updateGlobalJacobian routine to box or cc --- dumux/implicit/localjacobian.hh | 38 +++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/dumux/implicit/localjacobian.hh b/dumux/implicit/localjacobian.hh index 96c27d80f6..5b8890695e 100644 --- a/dumux/implicit/localjacobian.hh +++ b/dumux/implicit/localjacobian.hh @@ -225,13 +225,15 @@ protected: /*! * \brief Updates the current global Jacobian matrix with the * partial derivatives of all equations in regard to the - * primary variable 'pvIdx' at dof 'col' . + * primary variable 'pvIdx' at dof 'col'. Specialization for cc methods. */ - void updateGlobalJacobian_(JacobianMatrix& matrix, - const int globalI, - const int globalJ, - const int pvIdx, - const PrimaryVariables &partialDeriv) + template + typename std::enable_if::type + updateGlobalJacobian_(JacobianMatrix& matrix, + const int globalI, + const int globalJ, + const int pvIdx, + const PrimaryVariables &partialDeriv) { for (int eqIdx = 0; eqIdx < numEq; eqIdx++) { @@ -244,6 +246,30 @@ protected: } } + /*! + * \brief Updates the current global Jacobian matrix with the + * partial derivatives of all equations in regard to the + * primary variable 'pvIdx' at dof 'col'. Specialization for the box method. + */ + template + typename std::enable_if::type + updateGlobalJacobian_(JacobianMatrix& matrix, + const int globalI, + const int globalJ, + const int pvIdx, + const PrimaryVariables &partialDeriv) + { + for (int eqIdx = 0; eqIdx < numEq; eqIdx++) + { + // A[i][col][eqIdx][pvIdx] is the rate of change of + // the residual of equation 'eqIdx' at dof 'i' + // depending on the primary variable 'pvIdx' at dof + // 'col'. + matrix[globalI][globalJ][eqIdx][pvIdx] += partialDeriv[eqIdx]; + Valgrind::CheckDefined(matrix[globalI][globalJ][eqIdx][pvIdx]); + } + } + // The problem we would like to solve Problem *problemPtr_; -- GitLab From bb1f8c505fa11c0eaded1e0d6937b49f6c4a6ee0 Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 5 Jul 2016 12:08:07 +0200 Subject: [PATCH 31/45] [implicit][localresidual] remove evalFluxes_() method this method is now specialized by the boxlocaljacobian and the cclocaljacobian --- dumux/implicit/localresidual.hh | 30 +++++------------------------- 1 file changed, 5 insertions(+), 25 deletions(-) diff --git a/dumux/implicit/localresidual.hh b/dumux/implicit/localresidual.hh index 4f9502b9be..f630d9a53a 100644 --- a/dumux/implicit/localresidual.hh +++ b/dumux/implicit/localresidual.hh @@ -95,6 +95,7 @@ public: model_().fvGeometries_().bind(element); model_().curVolVars_().bind(element); model_().prevVolVars_().bindElement(element); + model_().fluxVariablesCache_().bindElement(element); ElementBoundaryTypes bcTypes; bcTypes.update(problem_(), element, fvGeometry_()); @@ -143,6 +144,7 @@ public: model_().fvGeometries_().bind(element); model_().curVolVars_().bind(element); model_().prevVolVars_().bindElement(element); + model_().fluxVariablesCache_().bindElement(element); ElementBoundaryTypes bcTypes; bcTypes.update(problem_(), element, fvGeometry_()); @@ -187,6 +189,7 @@ public: asImp_().evalFluxes_(); asImp_().evalVolumeTerms_(); + asImp_().evalBoundary_(); } /*! @@ -251,29 +254,6 @@ protected: return *static_cast(this); } - void evalFluxes_() - { - // calculate the mass flux over the scv faces and subtract - const auto& fvGeometry = fvGeometry_(); - for (const auto& scvf : fvGeometry.scvfs()) - { - auto flux = asImp_().computeFlux_(scvf); - - if (!isBox) - { - residual_[0] += flux; - } - else - { - const auto& insideScv = model_().fvGeometries().subControlVolume(scvf.insideScvIdx()); - const auto& outsideScv = model_().fvGeometries().subControlVolume(scvf.outsideScvIdx()); - - residual_[insideScv.indexInElement()] += flux; - residual_[outsideScv.indexInElement()] -= flux; - } - } - } - PrimaryVariables evalFlux_(const Element &element, const int scvfIdx) { const auto& scvf = model_().fvGeometries().subControlVolumeFace(scvfIdx); @@ -389,8 +369,8 @@ protected: prevStorage *= prevExtrusionFactor; curStorage *= curExtrusionFactor; - storageTerm_[scvIdx] = curStorage; - storageTerm_[scvIdx] -= prevStorage; + storageTerm_[scvIdx] = std::move(curStorage); + storageTerm_[scvIdx] -= std::move(prevStorage); storageTerm_[scvIdx] *= scv.volume(); storageTerm_[scvIdx] /= problem_().timeManager().timeStepSize(); -- GitLab From 7ca449f411cd36db81807229cae3e56ebbf760b7 Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 5 Jul 2016 12:10:27 +0200 Subject: [PATCH 32/45] [implicit] scvface gets its own local index --- dumux/implicit/subcontrolvolumeface.hh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/dumux/implicit/subcontrolvolumeface.hh b/dumux/implicit/subcontrolvolumeface.hh index d9261e819a..f0f964e81d 100644 --- a/dumux/implicit/subcontrolvolumeface.hh +++ b/dumux/implicit/subcontrolvolumeface.hh @@ -49,6 +49,7 @@ public: const GlobalPosition& ipGlobal, const GlobalPosition& unitOuterNormal, IndexType scvfIndex, + IndexType indexInElement, const std::vector& scvIndices, bool boundary = false) : geometry_(geometry), @@ -56,6 +57,7 @@ public: ipLocal_(geometry.local(ipGlobal)), unitOuterNormal_(unitOuterNormal), scvfIndex_(scvfIndex), + indexInElement_(indexInElement), scvIndices_(scvIndices), boundary_(boundary) {} @@ -121,12 +123,19 @@ public: return scvfIndex_; } + //! The global index of this sub control volume face + IndexType indexInElement() const + { + return indexInElement_; + } + private: Geometry geometry_; GlobalPosition ipGlobal_; LocalPosition ipLocal_; GlobalPosition unitOuterNormal_; IndexType scvfIndex_; + IndexType indexInElement_; std::vector scvIndices_; bool boundary_; }; -- GitLab From d8f31107cc1c3acc2500ddd584189e83cd86421d Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 5 Jul 2016 12:11:24 +0200 Subject: [PATCH 33/45] [implicit][model] adjust return functions --- dumux/implicit/model.hh | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/dumux/implicit/model.hh b/dumux/implicit/model.hh index 16e529f60f..cdab241d8f 100644 --- a/dumux/implicit/model.hh +++ b/dumux/implicit/model.hh @@ -31,7 +31,7 @@ #include #include #include - #include +#include namespace Dumux { @@ -784,23 +784,20 @@ public: // fvGeometry, scvIdx, fluidState); // } - const FluxVariablesCache& fluxVarsCache(const SubControlVolumeFace& scvf) const - { return fluxVarsCacheVector_[scvf.index()]; } + const FluxVariablesCacheVector& fluxVarsCache() const + { return fluxVarsCacheVector_; } - const FluxVariablesCache& fluxVarsCache(unsigned int scvfIdx) const - { return fluxVarsCacheVector_[scvfIdx]; } + const FluxVariablesCache& fluxVarsCache(const SubControlVolumeFace& scvf) const + { return fluxVarsCacheVector_[scvf]; } const VolumeVariables& curVolVars(const SubControlVolume& scv) const - { return curVolVarsVector_[scv.index()]; } - - const VolumeVariables& curVolVars(unsigned int scvIdx) const - { return curVolVarsVector_[scvIdx]; } + { return curVolVarsVector_[scv]; } const VolumeVariables& prevVolVars(const SubControlVolume& scv) const - { return prevVolVarsVector_[scv.index()]; } + { return prevVolVarsVector_[scv]; } - const VolumeVariables& prevVolVars(unsigned int scvIdx) const - { return prevVolVarsVector_[scvIdx]; } + const VolumeVariables& curVolVars(const unsigned int scvIdx) const + { return curVolVarsVector_[scvIdx]; } const FVElementGeometryVector& fvGeometries() const { return *fvGeometryVector_; } @@ -814,25 +811,22 @@ protected: { return curVolVarsVector_; } VolumeVariables& curVolVars_(const SubControlVolume& scv) - { return curVolVarsVector_[scv.index()]; } + { return curVolVarsVector_[scv]; } - VolumeVariables& curVolVars_(unsigned int scvIdx) + VolumeVariables& curVolVars_(const unsigned int scvIdx) { return curVolVarsVector_[scvIdx]; } PreviousVolumeVariablesVector& prevVolVars_() { return prevVolVarsVector_; } VolumeVariables& prevVolVars_(const SubControlVolume& scv) - { return prevVolVarsVector_[scv.index()]; } + { return prevVolVarsVector_[scv]; } - VolumeVariables& prevVolVars_(unsigned int scvIdx) - { return prevVolVarsVector_[scvIdx]; } + FluxVariablesCacheVector& fluxVariablesCache_() + { return fluxVarsCacheVector_; } FluxVariablesCache& fluxVarsCache_(const SubControlVolumeFace& scvf) - { return fluxVarsCacheVector_[scvf.index()]; } - - FluxVariablesCache& fluxVarsCache_(unsigned int scvfIdx) - { return fluxVarsCacheVector_[scvfIdx]; } + { return fluxVarsCacheVector_[scvf]; } FVElementGeometryVector& fvGeometries_() { return *fvGeometryVector_; } @@ -1001,6 +995,7 @@ protected: // the finite volume element geometries std::shared_ptr fvGeometryVector_; + // container to store the box volumes Dune::BlockVector > boxVolume_; public: -- GitLab From 6fc609c388622b3155b1fe9c86090982c8462228 Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 5 Jul 2016 12:12:07 +0200 Subject: [PATCH 34/45] [implicit][problem] fix indention --- dumux/implicit/problem.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dumux/implicit/problem.hh b/dumux/implicit/problem.hh index 899a869e8e..734030ea3a 100644 --- a/dumux/implicit/problem.hh +++ b/dumux/implicit/problem.hh @@ -191,7 +191,7 @@ public: * \param intersection The intersection for which the boundary type is set */ BoundaryTypes boundaryTypes(const Element &element, - const SubControlVolumeFace &scvFace) const + const SubControlVolumeFace &scvFace) const { if (isBox) DUNE_THROW(Dune::InvalidStateException, -- GitLab From a480e69239ea55bc2e7a5b3a135bc77e1b80ac84 Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 5 Jul 2016 12:12:56 +0200 Subject: [PATCH 35/45] [implicit][fickslaw] adapt interface --- dumux/porousmediumflow/constitutivelaws/fickslaw.hh | 1 + 1 file changed, 1 insertion(+) diff --git a/dumux/porousmediumflow/constitutivelaws/fickslaw.hh b/dumux/porousmediumflow/constitutivelaws/fickslaw.hh index 830fbab91a..a1829d1898 100644 --- a/dumux/porousmediumflow/constitutivelaws/fickslaw.hh +++ b/dumux/porousmediumflow/constitutivelaws/fickslaw.hh @@ -77,6 +77,7 @@ class FicksLaw Date: Tue, 5 Jul 2016 12:59:56 +0200 Subject: [PATCH 36/45] [implicit][propdefaults] do not set flux var cache vector property the flux var cache vector is now set specifically for box and cc methods --- dumux/implicit/propertydefaults.hh | 3 --- 1 file changed, 3 deletions(-) diff --git a/dumux/implicit/propertydefaults.hh b/dumux/implicit/propertydefaults.hh index dd24106871..79a9cb04b2 100644 --- a/dumux/implicit/propertydefaults.hh +++ b/dumux/implicit/propertydefaults.hh @@ -46,7 +46,6 @@ #include "assembler.hh" #include "localjacobian.hh" #include "volumevariables.hh" -#include "fluxvariablescachevector.hh" #include "fvelementgeometry.hh" namespace Dumux { @@ -113,8 +112,6 @@ SET_TYPE_PROP(ImplicitBase, FVElementGeometry, Dumux::FVElementGeometry //! The volume variable class, to be overloaded by the model SET_TYPE_PROP(ImplicitBase, VolumeVariables, Dumux::ImplicitVolumeVariables); -//! The global flux variables cache vector class -SET_TYPE_PROP(ImplicitBase, FluxVariablesCacheVector, Dumux::FluxVariablesCacheVector); //! The class that contains the different flux variables (i.e. darcy, diffusion, energy) //! by default, we set the flux variables to ones for porous media SET_PROP(ImplicitBase, FluxVariables) -- GitLab From 640de92b29c541b03588140d05a2d70e73ef051c Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 5 Jul 2016 13:01:00 +0200 Subject: [PATCH 37/45] [box] complete fvelemgeometry vector implementation --- dumux/implicit/box/fvelementgeometryvector.hh | 429 ++++++++++++++++-- 1 file changed, 394 insertions(+), 35 deletions(-) diff --git a/dumux/implicit/box/fvelementgeometryvector.hh b/dumux/implicit/box/fvelementgeometryvector.hh index 486e886baa..b2da799aca 100644 --- a/dumux/implicit/box/fvelementgeometryvector.hh +++ b/dumux/implicit/box/fvelementgeometryvector.hh @@ -393,21 +393,21 @@ public: * \note The finite volume geometry offers iterators over the sub control volumes * and the sub control volume faces of an element. */ - const FVElementGeometry& fvGeometry(IndexType eIdx) const + const FVElementGeometry& fvGeometry(const Element& element) const { - return fvGeometries_[eIdx]; + return fvGeometries_[problem_().elementMapper().index(element)]; } //! Get a sub control volume with a global scv index const SubControlVolume& subControlVolume(IndexType scvIdx) const { - return *scvs_[scvIdx]; + return *scvs_[globalScvIndices_[eIdxBound_][scvIdx]]; } //! Get a sub control volume face with a global scvf index const SubControlVolumeFace& subControlVolumeFace(IndexType scvfIdx) const { - return *scvfs_[scvfIdx]; + return *scvfs_[globalScvfIndices_[eIdxBound_][scvfIdx]]; } //! Get a local finite element basis @@ -428,6 +428,13 @@ public: return scvfs_.size(); } + //! The total number of boundary sub control volume faces + //! For compatibility reasons with cc methods + std::size_t numBoundaryScvf() const + { + return 0; + } + // Get an element from a sub control volume contained in it Element element(const SubControlVolume& scv) const { return elementMap_.element(scv.elementIndex()); } @@ -439,21 +446,43 @@ public: //! update all fvElementGeometries (do this again after grid adaption) void update(const Problem& problem) { + problemPtr_ = &problem; + scvs_.clear(); scvfs_.clear(); fvGeometries_.clear(); elementMap_.clear(); + IndexType numElements = gridView_.size(0); + IndexType numScvs = 0; + IndexType numScvfs = 0; + for (const auto& element : elements(gridView_)) + { + numScvs += element.subEntities(dim); + numScvfs += element.subEntities(dim-1); + + // add number of boundary faces + for (const auto& is : intersections(gridView_, element)) + { + if (is.boundary()) + numScvfs += is.geometry().corners(); + } + } + + scvs_.reserve(numScvs); + scvfs_.reserve(numScvfs); + globalScvIndices_.resize(numElements); + globalScvfIndices_.resize(numElements); + elementMap_.resize(numElements); + // Build the SCV and SCV faces IndexType scvIdx = 0; IndexType scvfIdx = 0; - elementMap_.resize(gridView_.size(0)); - for (const auto& element : elements(gridView_)) { // the element-wise index sets for finite volume geometry - std::vector scvIndexSet; - std::vector scvfIndexSet; + std::vector scvLocalIndexSet; + std::vector scvfLocalIndexSet; // fill the element map with seeds auto eIdx = problem.elementMapper().index(element); @@ -464,44 +493,48 @@ public: const auto& referenceElement = ReferenceElements::general(elementGeometry.type()); // get the sub control volume geometries of this element - auto boxGeometries = BoxGeometryHelper::getScvAndScvfGeometries(elementGeometry); + auto boxGeometries = std::move(BoxGeometryHelper::getScvAndScvfGeometries(elementGeometry)); // define some aliases auto& scvGeometries = boxGeometries.first; auto& scvfGeometries = boxGeometries.second; // construct the sub control volumes - scvIndexSet.reserve(scvGeometries.size()); - scvs_.reserve(scvs_.size() + scvGeometries.size()); + globalScvIndices_[eIdx].resize(scvGeometries.size()); + scvLocalIndexSet.reserve(scvGeometries.size()); IndexType scvLocalIdx = 0; for (auto&& scvGeometry : scvGeometries) { - scvIndexSet.push_back(scvIdx); - auto dofIdxGlobal = problem.vertexMapper().subIndex(element, dim, scvLocalIdx); + scvLocalIndexSet.push_back(scvLocalIdx); + auto dofIdxGlobal = problem.vertexMapper().subIndex(element, scvLocalIdx, dim); scvs_.emplace_back(std::make_shared(*scvGeometry, - scvIdx++, + scvIdx, eIdx, - scvLocalIdx++, + scvLocalIdx, dofIdxGlobal)); + + globalScvIndices_[eIdx][scvLocalIdx] = scvIdx; + + // increment local counters + scvIdx++; scvLocalIdx++; } // construct the sub control volume faces - scvfIndexSet.reserve(scvfGeometries.size()); - scvfs_.reserve(scvfs_.size() + scvfGeometries.size()); + globalScvfIndices_[eIdx].resize(scvfGeometries.size()); + scvfLocalIndexSet.reserve(scvfGeometries.size()); IndexType scvfLocalIdx = 0; for (auto&& scvfGeometry : scvfGeometries) { // add this scvf to the element's scvf list - scvfIndexSet.push_back(scvfIdx); + scvfLocalIndexSet.push_back(scvfLocalIdx); - // find the global scv indices this scvf is belonging to - std::vector scvIndices(2); - scvIndices[0] = scvIndexSet[referenceElement.subEntity(scvfLocalIdx, dim-1, 0, dim)]; - scvIndices[1] = scvIndexSet[referenceElement.subEntity(scvfLocalIdx, dim-1, 1, dim)]; + // find the global and local scv indices this scvf is belonging to + std::vector localScvIndices(2); + localScvIndices[0] = referenceElement.subEntity(scvfLocalIdx, dim-1, 0, dim); + localScvIndices[1] = referenceElement.subEntity(scvfLocalIdx, dim-1, 1, dim); // compute the scvf normal unit outer normal - auto normal = BoxGeometryHelper::normal(elementGeometry, *scvfGeometry); - - const auto v = elementGeometry.corner(scvIndices[1]) - elementGeometry.corner(scvIndices[0]); + auto normal = std::move(BoxGeometryHelper::normal(elementGeometry, *scvfGeometry)); + const auto v = elementGeometry.corner(localScvIndices[1]) - elementGeometry.corner(localScvIndices[0]); const auto s = v*normal; if (std::signbit(s)) normal *= -1; @@ -509,27 +542,33 @@ public: scvfs_.emplace_back(std::make_shared(*scvfGeometry, scvfGeometry->center(), normal, - scvfIdx++, - scvIndices, + scvfIdx, + scvfLocalIdx, + localScvIndices, false)); + + globalScvfIndices_[eIdx][scvfLocalIdx] = scvfIdx; + + // increment local counters + scvfIdx++; scvfLocalIdx++; } // construct the sub control volume faces on the domain boundary for (const auto& intersection : intersections(gridView_, element)) { - scvfLocalIdx = 0; if (intersection.boundary()) { auto isGeometry = intersection.geometry(); - auto boundaryScvfGeometries = BoxGeometryHelper::getBoundaryScvfGeometries(isGeometry); + auto boundaryScvfGeometries = std::move(BoxGeometryHelper::getBoundaryScvfGeometries(isGeometry)); - for (auto&& scvfGeometry : scvfGeometries) + IndexType isScvfLocalIdx = 0; + for (auto&& scvfGeometry : boundaryScvfGeometries) { // add this scvf to the element's scvf list - scvfIndexSet.push_back(scvfIdx); + scvfLocalIndexSet.push_back(scvfLocalIdx); // find the scvs this scvf is belonging to - std::vector scvIndices = {static_cast(scvIndexSet[referenceElement.subEntity(intersection.indexInInside(), 1, scvfLocalIdx++, dim)])}; + std::vector localScvIndices = {static_cast(referenceElement.subEntity(intersection.indexInInside(), 1, isScvfLocalIdx, dim))}; // get the unit outer normal through the intersection auto normal = intersection.unitOuterNormal(isGeometry.local(scvfGeometry->center())); @@ -537,27 +576,347 @@ public: scvfs_.emplace_back(std::make_shared(*scvfGeometry, scvfGeometry->center(), normal, - scvfIdx++, - scvIndices, + scvfIdx, + scvfLocalIdx++, + localScvIndices, true)); + + globalScvfIndices_[eIdx].push_back(scvfIdx++); } } } // Compute the finite volume element geometries - fvGeometries_.push_back(FVElementGeometry(*this, scvIndexSet, scvfIndexSet)); + fvGeometries_.push_back(FVElementGeometry(*this, scvLocalIndexSet, scvfLocalIndexSet)); } } + // Binding of an element, has to be called before using the fvgeometries + // Prepares all the volume variables within the element + // For compatibility reasons with the FVGeometry cache being disabled + void bindElement(const Element& element) + { + eIdxBound_ = problem_().elementMapper().index(element); + } + // this function is for compatibility reasons with cc methods + void bind(const Element& element) + { + bindElement(element); + } + private: + const Problem& problem_() const + { return *problemPtr_; } + + const Problem* problemPtr_; + + IndexType eIdxBound_; GridView gridView_; Dumux::ElementMap elementMap_; std::vector> scvs_; std::vector> scvfs_; std::vector fvGeometries_; + + std::vector> globalScvIndices_; + std::vector> globalScvfIndices_; const FeCache feCache_; }; +// specialization in case the FVElementGeometries are not stored +template +class BoxFVElementGeometryVector +{ + using Problem = typename GET_PROP_TYPE(TypeTag, Problem); + using GridView = typename GET_PROP_TYPE(TypeTag, GridView); + using IndexType = typename GridView::IndexSet::IndexType; + using SubControlVolume = typename GET_PROP_TYPE(TypeTag, SubControlVolume); + using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); + using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry); + + static const int dim = GridView::dimension; + static const int dimWorld = GridView::dimensionworld; + + using Element = typename GridView::template Codim<0>::Entity; + using Vertex = typename GridView::template Codim::Entity; + + using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using CoordScalar = typename GridView::ctype; + + using FeCache = Dune::PQkLocalFiniteElementCache; + using FeLocalBasis = typename FeCache::FiniteElementType::Traits::LocalBasisType; + using ReferenceElements = typename Dune::ReferenceElements; + +public: + //! Constructor + BoxFVElementGeometryVector(const GridView gridView) + : gridView_(gridView), elementMap_(gridView), eIdxBound_(-1) {} + + /* \brief Get the finite volume geometry of an element + * \note The finite volume geometry offers iterators over the sub control volumes + * and the sub control volume faces of an element. + */ + const FVElementGeometry& fvGeometry(const Element& element) const + { + auto eIdx = problem_().elementMapper().index(element); + if (eIdx != eIdxBound_) + DUNE_THROW(Dune::InvalidStateException, "Trying to get FVElementGeometry for element with index " << eIdx + << ", but bound is element " << eIdxBound_ << ". Please call bindElement() before using the fvGeometry."); + return fvGeometry_[0]; + } + + //! Get a sub control volume with a global scv index + const SubControlVolume& subControlVolume(IndexType scvIdx) const + { + return stencilScvs_[scvIdx]; + } + + //! Get a sub control volume face with a global scvf index + const SubControlVolumeFace& subControlVolumeFace(IndexType scvfIdx) const + { + return stencilScvfs_[scvfIdx]; + } + + //! Get a local finite element basis + const FeLocalBasis& feLocalBasis(const Dune::GeometryType& type) const + { + return feCache_.get(type).localBasis(); + } + + //! The total number of sub control volumes + std::size_t numScv() const + { + return numScvs_; + } + + //! The total number of sun control volume faces + std::size_t numScvf() const + { + return numScvf_; + } + + //! The total number of boundary sub control volume faces + //! For compatibility reasons with cc methods + std::size_t numBoundaryScvf() const + { + return 0; + } + + // Get an element from a sub control volume contained in it + Element element(const SubControlVolume& scv) const + { return elementMap_.element(scv.elementIndex()); } + + // Get an element from a global element index + Element element(IndexType eIdx) const + { return elementMap_.element(eIdx); } + + //! update all fvElementGeometries (do this again after grid adaption) + void update(const Problem& problem) + { + problemPtr_ = &problem; + elementMap_.clear(); + release_(); + eIdxBound_ = -1; + + auto numElems = gridView_.size(0); + elementMap_.resize(numElems); + scvIndices_.resize(numElems); + scvFaceIndices_.resize(numElems); + + // save data on the grid's scvs and scvfs + IndexType scvIdx = 0; + IndexType scvfIdx = 0; + for (const auto& element : elements(gridView_)) + { + // the element-wise index sets for finite volume geometry + std::vector scvIndexSet; + std::vector scvfIndexSet; + + // fill the element map with seeds + auto eIdx = problem.elementMapper().index(element); + elementMap_[eIdx] = element.seed(); + + // store scv indices of the element + for (int scvLocalIdx = 0; scvLocalIdx < element.subEntities(dim); ++scvLocalIdx) + scvIndexSet.push_back(scvIdx++); + + // store scv face indices of the element + for (int scvfLocalIdx = 0; scvfLocalIdx < element.subEntities(dim-1); ++scvfLocalIdx) + scvfIndexSet.push_back(scvfIdx++); + + // store the sub control volume face indices on the domain boundary + for (const auto& intersection : intersections(gridView_, element)) + { + if (intersection.boundary()) + { + for (int localNodeIdx = 0; localNodeIdx < intersection.geometry().corners(); ++localNodeIdx) + { + // add this scvf to the element's scvf list + scvfIndexSet.push_back(scvfIdx++); + } + } + } + + // store the sets of indices in the data containers + scvIndices_[eIdx] = scvIndexSet; + scvFaceIndices_[eIdx] = scvfIndexSet; + } + + numScvs_ = scvIdx; + numScvf_ = scvfIdx; + } + + // build the geometries inside an element + void bindElement(const Element& element) + { + eIdxBound_ = problem_().elementMapper().index(element); + release_(); + makeElementGeometries_(element); + } + + // for cc methods, this method binds all the elements in the stencil. + // Here, we simply forward to the bindElement() routine. + void bind(const Element& element) + { + bindElement(element); + } + +private: + void release_() + { + stencilScvs_.clear(); + stencilScvfs_.clear(); + fvGeometry_.clear(); + } + + void makeElementGeometries_(const Element& element) + { + const auto eIdx = problem_().elementMapper().index(element); + + // the element-wise index sets for finite volume geometry + auto scvIndexSet = scvIndices_[eIdx]; + auto scvfIndexSet = scvFaceIndices_[eIdx]; + std::vector localScvIndexSet; + std::vector localScvfIndexSet; + localScvIndexSet.reserve(scvIndexSet.size()); + localScvfIndexSet.reserve(scvfIndexSet.size()); + + // get the element geometry + auto elementGeometry = element.geometry(); + const auto& referenceElement = ReferenceElements::general(elementGeometry.type()); + + // get the sub control volume geometries of this element + auto boxGeometries = std::move(BoxGeometryHelper::getScvAndScvfGeometries(elementGeometry)); + // define some aliases + auto& scvGeometries = boxGeometries.first; + auto& scvfGeometries = boxGeometries.second; + + // construct the sub control volumes + IndexType scvLocalIdx = 0; + for (auto&& scvGeometry : scvGeometries) + { + localScvIndexSet.push_back(scvLocalIdx); + auto dofIdxGlobal = problem_().vertexMapper().subIndex(element, scvLocalIdx, dim); + + // add scv to the local container + stencilScvs_.emplace_back(SubControlVolume(*scvGeometry, + scvIndexSet[scvLocalIdx], + eIdx, + scvLocalIdx, + dofIdxGlobal)); + // increment local counter + scvLocalIdx++; + } + + // construct the sub control volume faces + IndexType scvfLocalIdx = 0; + for (auto&& scvfGeometry : scvfGeometries) + { + localScvfIndexSet.push_back(scvfLocalIdx); + + // find the local scv indices this scvf is connsected to + std::vector localScvIndices(2); + localScvIndices[0] = referenceElement.subEntity(scvfLocalIdx, dim-1, 0, dim); + localScvIndices[1] = referenceElement.subEntity(scvfLocalIdx, dim-1, 1, dim); + + // compute the scvf normal unit outer normal + auto normal = std::move(BoxGeometryHelper::normal(elementGeometry, *scvfGeometry)); + const auto v = elementGeometry.corner(localScvIndices[1]) - elementGeometry.corner(localScvIndices[0]); + const auto s = v*normal; + if (std::signbit(s)) + normal *= -1; + + stencilScvfs_.emplace_back(SubControlVolumeFace(*scvfGeometry, + scvfGeometry->center(), + normal, + scvfIndexSet[scvfLocalIdx], + scvfLocalIdx, + localScvIndices, + false)); + + // increment local counter + scvfLocalIdx++; + } + + // construct the sub control volume faces on the domain boundary + for (const auto& intersection : intersections(gridView_, element)) + { + if (intersection.boundary()) + { + auto isGeometry = intersection.geometry(); + auto boundaryScvfGeometries = std::move(BoxGeometryHelper::getBoundaryScvfGeometries(isGeometry)); + + IndexType boundaryFaceLocalIdx = 0; + for (auto&& scvfGeometry : boundaryScvfGeometries) + { + localScvfIndexSet.push_back(scvfLocalIdx); + + // find the scv this scvf is connected to + std::vector localScvIndices = {static_cast(referenceElement.subEntity(intersection.indexInInside(), 1, boundaryFaceLocalIdx++, dim))}; + + // get the unit outer normal through the intersection + auto normal = intersection.unitOuterNormal(isGeometry.local(scvfGeometry->center())); + + stencilScvfs_.emplace_back(SubControlVolumeFace(*scvfGeometry, + scvfGeometry->center(), + normal, + scvfIndexSet[scvfLocalIdx], + scvfLocalIdx, + localScvIndices, + true)); + + // increment local counter + scvfLocalIdx++; + } + } + } + + // Compute the finite volume element geometries + fvGeometry_.push_back(FVElementGeometry(*this, localScvIndexSet, localScvfIndexSet)); + } + + const Problem& problem_() const + { return *problemPtr_; } + + GridView gridView_; + const Problem* problemPtr_; + const FeCache feCache_; + + // Information on the global number of geometries + IndexType numScvs_; + IndexType numScvf_; + + // vectors that store the global data + Dumux::ElementMap elementMap_; + std::vector> scvIndices_; + std::vector> scvFaceIndices_; + + // vectors to store the geometries temporarily after binding an element + IndexType eIdxBound_; + std::vector stencilScvs_; + std::vector stencilScvfs_; + std::vector fvGeometry_; +}; + } // end namespace #endif -- GitLab From c36044b5fca660bbd1587a9fddb390205281d924 Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 5 Jul 2016 13:01:59 +0200 Subject: [PATCH 38/45] [box] implement new box assembly --- dumux/implicit/box/localjacobian.hh | 140 +++++++--------- dumux/implicit/box/localresidual.hh | 250 +++++++++++----------------- 2 files changed, 162 insertions(+), 228 deletions(-) diff --git a/dumux/implicit/box/localjacobian.hh b/dumux/implicit/box/localjacobian.hh index 7ce07c5560..14041d5f88 100644 --- a/dumux/implicit/box/localjacobian.hh +++ b/dumux/implicit/box/localjacobian.hh @@ -18,10 +18,10 @@ *****************************************************************************/ /*! * \file - * \brief Caculates the Jacobian of the local residual for fully-implicit models + * \brief Caculates the Jacobian of the local residual for fully-implicit box models */ -#ifndef DUMUX_IMPLICIT_LOCAL_JACOBIAN_HH -#define DUMUX_IMPLICIT_LOCAL_JACOBIAN_HH +#ifndef DUMUX_IMPLICIT_BOX_LOCAL_JACOBIAN_HH +#define DUMUX_IMPLICIT_BOX_LOCAL_JACOBIAN_HH #include #include @@ -82,18 +82,16 @@ class BoxLocalJacobian : public ImplicitLocalJacobian dim = GridView::dimension, }; + typedef typename GET_PROP_TYPE(TypeTag, JacobianMatrix) JacobianMatrix; + typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector; typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; typedef typename GET_PROP_TYPE(TypeTag, SubControlVolume) SubControlVolume; typedef typename GET_PROP_TYPE(TypeTag, VertexMapper) VertexMapper; typedef typename GET_PROP_TYPE(TypeTag, ElementSolutionVector) ElementSolutionVector; typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef Dune::FieldMatrix MatrixBlock; - typedef Dune::Matrix LocalBlockMatrix; public: BoxLocalJacobian() @@ -101,62 +99,56 @@ public: numericDifferenceMethod_ = GET_PARAM_FROM_GROUP(TypeTag, int, Implicit, NumericDifferenceMethod); } - /*! * \brief Assemble an element's local Jacobian matrix of the * defect. * * \param element The DUNE Codim<0> entity which we look at. */ - void assemble(const Element& element, JacobianMatrix& matrix) + void assemble(const Element& element, JacobianMatrix& matrix, SolutionVector& residual) { - // set the current grid element and update the element's - // finite volume geometry - elemPtr_ = &element; - reset_(); + // prepare the volvars/fvGeometries for the case when caching is disabled + this->model_().fvGeometries_().bind(element); + this->model_().curVolVars_().bind(element); + this->model_().prevVolVars_().bindElement(element); + this->model_().fluxVariablesCache_().bind(element); - bcTypes_.update(problem_(), element, fvElemGeom_()); + // the finite volume element geometry + const auto& fvGeometry = this->model_().fvGeometries(element); - // calculate the local residual + // the element boundary types + bcTypes_.update(this->problem_(), element, fvGeometry); + + // calculate the actual element residual this->localResidual().eval(element, bcTypes_); this->residual_ = this->localResidual().residual(); - this->model_().updatePVWeights(fvElemGeom_()); - - // get stencil informations - const auto& elementStencil = this->model_().stencils(element).elementStencil(); + this->model_().updatePVWeights(fvGeometry); - // calculate derivatives for the dofs inside the element - ElementSolutionVector partialDeriv(numRows); - for (auto&& scv : fvElemGeom_().scvs()) + // calculation of the derivatives + for (const auto& scv : fvGeometry.scvs()) { + // dof index and corresponding actual pri vars + const auto dofIdx = scv.dofIndex(); + const auto localScvIdx = scv.indexInElement(); + VolumeVariables origVolVars(this->model_().curVolVars(scv)); + + // add precalculated residual for this scv into the global container + residual[dofIdx] += this->residual_[localScvIdx]; + + // calculate derivatives w.r.t to the privars at the dof at hand for (int pvIdx = 0; pvIdx < numEq; pvIdx++) { - asImp_().evalPartialDerivative_(partialDeriv, element, scv, pvIdx); + evalPartialDerivative_(matrix, element, scv, pvIdx); - // update the local stiffness matrix with the current partial derivatives - for (auto&& scvJ : fvElemGeom_().scvs()) - this->updateGlobalJacobian_(matrix, scv.dofIndex(), scvJ.dofIndex(), pvIdx, partialDeriv[scvJ.indexInElement()]); + // restore the original state of the scv's volume variables + this->model_().curVolVars_(scv) = origVolVars; } - } - // TODO: calculate derivatives in the case of an extended source stencil - // const auto& extendedSourceStencil = model_().stencils(element).extendedSourceStencil(); - // for (auto&& globalJ : extendedSourceStencil) - // { - // for (int pvIdx = 0; pvIdx < numEq; pvIdx++) - // { - // evalPartialDerivativeSource_(partialDeriv, globalJ, pvIdx, fluxVarIndices); - - // // update the local stiffness matrix with the partial derivatives - // updateLocalJacobian_(j, pvIdx, partialDeriv); - // } - // ++j; - // } - - // for cellcentered methods, calculate the derivatives w.r.t cells in stencil + // TODO: what if we have an extended source stencil???? + } } - +protected: /*! * \brief Compute the partial derivatives to a primary variable at * an degree of freedom. @@ -193,6 +185,7 @@ public: * * \param partialDeriv The vector storing the partial derivatives of all * equations + * \param storageDeriv the mass matrix contributions * \param col The block column index of the degree of freedom * for which the partial derivative is calculated. * Box: a sub-control volume index. @@ -200,19 +193,19 @@ public: * \param pvIdx The index of the primary variable * for which the partial derivative is calculated */ - void evalPartialDerivative_(ElementSolutionVector &partialDeriv, + void evalPartialDerivative_(JacobianMatrix& matrix, const Element& element, - const SubControlVolume &scv, + const SubControlVolume& scv, const int pvIdx) { - auto dofIdxGlobal = scv.dofIndex(); + auto dofIdx = scv.dofIndex(); - PrimaryVariables priVars(model_().curSol()[dofIdxGlobal]); - VolumeVariables origVolVars(model_().curVolVars(scv)); - - Scalar eps = asImp_().numericEpsilon(scv, pvIdx); + ElementSolutionVector partialDeriv(element.subEntities(dim)); + PrimaryVariables priVars(this->model_().curSol()[dofIdx]); + Scalar eps = this->numericEpsilon(scv, pvIdx); Scalar delta = 0; + // calculate the residual with the forward deflected primary variables if (numericDifferenceMethod_ >= 0) { // we are not using backward differences, i.e. we need to @@ -222,21 +215,21 @@ public: priVars[pvIdx] += eps; delta += eps; - // update the volume variables - model_().curVolVars_(scv).update(priVars, problem_(), element, scv); + // update the volume variables connected to the dof + this->model_().curVolVars_(scv).update(priVars, this->problem_(), element, scv); - // calculate the residual with the deflected primary variables - localResidual().eval(element, bcTypes_); + // calculate the deflected residual + this->localResidual().eval(element, bcTypes_); - // store the residual and the storage term - partialDeriv = localResidual().residual(); + // store the residual + partialDeriv = this->localResidual().residual(); } else { // we are using backward differences, i.e. we don't need // to calculate f(x + \epsilon) and we can recycle the // (already calculated) residual f(x) - partialDeriv = residual_; + partialDeriv = this->residual_; } if (numericDifferenceMethod_ <= 0) @@ -248,45 +241,38 @@ public: priVars[pvIdx] -= delta + eps; delta += eps; - // update the volume variables - model_().curVolVars_(scv).update(priVars, problem_(), element, scv); + // update the volume variables connected to the dof + this->model_().curVolVars_(scv).update(priVars, this->problem_(), element, scv); - // calculate the residual with the deflected primary variables - localResidual().eval(element, bcTypes_); + // calculate the deflected residual + this->localResidual().eval(element, bcTypes_); // subtract the residual from the derivative storage - partialDeriv -= localResidual().residual(); + partialDeriv -= this->localResidual().residual(); } else { // we are using forward differences, i.e. we don't need to // calculate f(x - \epsilon) and we can recycle the // (already calculated) residual f(x) - partialDeriv -= residual_; + partialDeriv -= this->residual_; } // divide difference in residuals by the magnitude of the // deflections between the two function evaluation partialDeriv /= delta; - // restore the original state of the scv's volume variables - model_().curVolVars_(scv) = origVolVars; - -#if HAVE_VALGRIND - for (unsigned i = 0; i < partialDeriv.size(); ++i) - Valgrind::CheckDefined(partialDeriv[i]); -#endif + // update the global stiffness matrix with the current partial derivatives + const auto& fvGeometry = this->model_().fvGeometries(element); + for (const auto& scvJ : fvGeometry.scvs()) + this->updateGlobalJacobian_(matrix, scvJ.dofIndex(), dofIdx, pvIdx, partialDeriv[scvJ.indexInElement()]); } - const FVElementGeometry& fvElemGeom_() const - { - return model_().fvGeometries(eIdxGlobal_); - } - - IndexType eIdxGlobal_; - ElementBoundaryTypes bcTypes_; +private: int numericDifferenceMethod_; + + ElementBoundaryTypes bcTypes_; }; } diff --git a/dumux/implicit/box/localresidual.hh b/dumux/implicit/box/localresidual.hh index 4b69761d83..358fb52fe0 100644 --- a/dumux/implicit/box/localresidual.hh +++ b/dumux/implicit/box/localresidual.hh @@ -55,14 +55,10 @@ class BoxLocalResidual : public ImplicitLocalResidual }; typedef typename GridView::template Codim<0>::Entity Element; - - typedef typename GridView::Grid::ctype CoordScalar; - typedef typename Dune::ReferenceElements ReferenceElements; - typedef typename Dune::ReferenceElement ReferenceElement; - - typedef typename GET_PROP_TYPE(TypeTag, VertexMapper) VertexMapper; typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes; + typedef typename GET_PROP_TYPE(TypeTag, SubControlVolume) SubControlVolume; + typedef typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace) SubControlVolumeFace; // copying the local residual class is not a good idea BoxLocalResidual(const BoxLocalResidual &); @@ -72,116 +68,86 @@ public: { } protected: + + void evalFluxes_() + { + // calculate the mass flux over the scv faces and subtract + const auto& fvGeometry = this->fvGeometry_(); + for (const auto& scvf : fvGeometry.scvfs()) + { + if (!scvf.boundary()) + { + auto flux = this->asImp_().computeFlux(scvf); + const auto& insideScv = this->model_().fvGeometries().subControlVolume(scvf.insideScvIdx()); + const auto& outsideScv = this->model_().fvGeometries().subControlVolume(scvf.outsideScvIdx()); + + this->residual_[insideScv.indexInElement()] += flux; + this->residual_[outsideScv.indexInElement()] -= flux; + } + } + } + /*! * \brief Set the values of the Dirichlet boundary control volumes * of the current element. */ - void evalDirichlet_() + void evalDirichlet_(const SubControlVolume& scv, const BoundaryTypes& bcTypes) { - PrimaryVariables dirichletValues(0); - for (int scvIdx = 0; scvIdx < this->fvGeometry_().numScv; ++scvIdx) { - const BoundaryTypes &bcTypes = this->bcTypes_(scvIdx); - - if (bcTypes.hasDirichlet()) { - // ask the problem for the dirichlet values - Valgrind::SetUndefined(dirichletValues); - this->asImp_().problem_().dirichlet(dirichletValues, this->element_().template subEntity(scvIdx)); + PrimaryVariables dirichletValues = this->asImp_().problem_().dirichlet(this->element_(), scv); - // set the dirichlet conditions - for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) { - if (bcTypes.isDirichlet(eqIdx)) { - int pvIdx = bcTypes.eqToDirichletIndex(eqIdx); - assert(0 <= pvIdx && pvIdx < numEq); - Valgrind::CheckDefined(dirichletValues[pvIdx]); + // set the dirichlet conditions + for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) + { + if (bcTypes.isDirichlet(eqIdx)) + { + int pvIdx = bcTypes.eqToDirichletIndex(eqIdx); + assert(0 <= pvIdx && pvIdx < numEq); + Valgrind::CheckDefined(dirichletValues[pvIdx]); - this->residual_[scvIdx][eqIdx] = - this->curPriVar_(scvIdx, pvIdx) - dirichletValues[pvIdx]; + // get the primary variables + const auto& priVars = this->model_().curVolVars(scv).priVars(); - this->storageTerm_[scvIdx][eqIdx] = 0.0; - } - } + this->residual_[scv.indexInElement()][eqIdx] = priVars[pvIdx] - dirichletValues[pvIdx]; } } } /*! - * \brief Add all Neumann and outflow boundary conditions to the local - * residual. + * \brief Add all fluxes resulting from Neumann and outflow boundary conditions to the local residual. */ - void evalBoundaryFluxes_() + void evalBoundaryFluxes_(const SubControlVolumeFace &scvf, const SubControlVolume& insideScv, const BoundaryTypes& bcTypes) { - Dune::GeometryType geoType = this->element_().geometry().type(); - const ReferenceElement &refElement = ReferenceElements::general(geoType); - for (const auto& intersection : intersections(this->gridView_(), this->element_())) - { - // handle only faces on the boundary - if (intersection.boundary()) { - // Assemble the boundary for all vertices of the current - // face - int fIdx = intersection.indexInInside(); - int numFaceVerts = refElement.size(fIdx, 1, dim); - for (int faceVertexIdx = 0; - faceVertexIdx < numFaceVerts; - ++faceVertexIdx) - { - int scvIdx = refElement.subEntity(fIdx, - 1, - faceVertexIdx, - dim); - - int boundaryFaceIdx = - this->fvGeometry_().boundaryFaceIndex(fIdx, faceVertexIdx); + // evaluate the Neumann conditions at the boundary face + if (bcTypes.hasNeumann()) + this->residual_[insideScv.indexInElement()] += this->asImp_().evalNeumannSegment_(scvf, insideScv, bcTypes); - // add the residual of all vertices of the boundary - // segment - this->asImp_().evalNeumannSegment_(&intersection, - scvIdx, - boundaryFaceIdx); - // evaluate the outflow conditions at the boundary face - this->asImp_().evalOutflowSegment_(&intersection, - scvIdx, - boundaryFaceIdx); - } - } - } + // TODO: evaluate the outflow conditions at the boundary face + //if (bcTypes.hasOutflow()) + // flux += this->asImp_().evalOutflowSegment_(&intersection, bcTypes); } /*! - * \brief Add Neumann boundary conditions for a single sub-control - * volume face to the local residual. + * \brief Add Neumann boundary conditions for a single scv face */ - template - void evalNeumannSegment_(const IntersectionIterator &isIt, - const int scvIdx, - const int boundaryFaceIdx) + PrimaryVariables evalNeumannSegment_(const SubControlVolumeFace &scvf, + const SubControlVolume& insideScv, + const BoundaryTypes &bcTypes) { // temporary vector to store the neumann boundary fluxes - PrimaryVariables neumannFlux(0.0); - const BoundaryTypes &bcTypes = this->bcTypes_(scvIdx); + PrimaryVariables flux(0); - // deal with neumann boundaries - if (bcTypes.hasNeumann()) { - Valgrind::SetUndefined(neumannFlux); - this->problem_().solDependentNeumann(neumannFlux, - this->element_(), - this->fvGeometry_(), - *isIt, - scvIdx, - boundaryFaceIdx, - this->curVolVars_()); - neumannFlux *= - this->fvGeometry_().boundaryFace[boundaryFaceIdx].area - * this->curVolVars_(scvIdx).extrusionFactor(); - Valgrind::CheckDefined(neumannFlux); + auto neumannFluxes = this->problem_().neumann(this->element_(), scvf); - // set the neumann conditions - for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) { - if (!bcTypes.isNeumann(eqIdx)) - continue; - this->residual_[scvIdx][eqIdx] += neumannFlux[eqIdx]; - } - } + // multiply neumann fluxes with the area and the extrusion factor + neumannFluxes *= scvf.area()*this->problem_().model().curVolVars(insideScv).extrusionFactor(); + + // add fluxes to the temporary vector + for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) + if (bcTypes.isNeumann(eqIdx)) + flux[eqIdx] += neumannFluxes[eqIdx]; + + return flux; } /*! @@ -192,76 +158,58 @@ protected: * \param scvIdx The index of the considered face of the sub-control volume * \param boundaryFaceIdx The index of the considered boundary face of the sub control volume */ - template - void evalOutflowSegment_(const IntersectionIterator &isIt, - const int scvIdx, - const int boundaryFaceIdx) + // template + // void evalOutflowSegment_(const IntersectionIterator &isIt, + // const int scvIdx, + // const int boundaryFaceIdx) + // { + // const BoundaryTypes &bcTypes = this->bcTypes_(scvIdx); + // // deal with outflow boundaries + // if (bcTypes.hasOutflow()) + // { + // //calculate outflow fluxes + // PrimaryVariables values(0.0); + // this->asImp_().computeFlux(values, boundaryFaceIdx, true); + // Valgrind::CheckDefined(values); + + // for (int equationIdx = 0; equationIdx < numEq; ++equationIdx) + // { + // if (!bcTypes.isOutflow(equationIdx) ) + // continue; + // // deduce outflow + // this->residual_[scvIdx][equationIdx] += values[equationIdx]; + // } + // } + // } + + void evalBoundary_() { - const BoundaryTypes &bcTypes = this->bcTypes_(scvIdx); - // deal with outflow boundaries - if (bcTypes.hasOutflow()) + const auto& fvGeometry = this->fvGeometry_(); + if (this->bcTypes_().hasNeumann() || this->bcTypes_().hasOutflow()) { - //calculate outflow fluxes - PrimaryVariables values(0.0); - this->asImp_().computeFlux(values, boundaryFaceIdx, true); - Valgrind::CheckDefined(values); - - for (int equationIdx = 0; equationIdx < numEq; ++equationIdx) + for (const auto& scvf : fvGeometry.scvfs()) { - if (!bcTypes.isOutflow(equationIdx) ) - continue; - // deduce outflow - this->residual_[scvIdx][equationIdx] += values[equationIdx]; + if (scvf.boundary()) + { + const auto& scv = this->problem_().model().fvGeometries().subControlVolume(scvf.insideScvIdx()); + this->asImp_().evalBoundaryFluxes_(scvf, scv, this->bcTypes_(scv.indexInElement())); + } } } - } - /*! - * \brief Add the flux terms to the local residual of all - * sub-control volumes of the current element. - */ - void evalFluxes_() - { - // calculate the mass flux over the faces and subtract - // it from the local rates - for (int scvfIdx = 0; scvfIdx < this->fvGeometry_().numScvf; scvfIdx++) + // additionally treat mixed D/N conditions in a strong sense + if (this->bcTypes_().hasDirichlet()) { - int i = this->fvGeometry_().subContVolFace[scvfIdx].i; - int j = this->fvGeometry_().subContVolFace[scvfIdx].j; - - PrimaryVariables flux; - - Valgrind::SetUndefined(flux); - this->asImp_().computeFlux(flux, scvfIdx); - Valgrind::CheckDefined(flux); - - Scalar extrusionFactor = - (this->curVolVars_(i).extrusionFactor() - + this->curVolVars_(j).extrusionFactor()) - / 2; - flux *= extrusionFactor; + for (const auto& scv : fvGeometry.scvs()) + { + BoundaryTypes bcTypes = this->bcTypes_(scv.indexInElement()); + if (!bcTypes.hasDirichlet()) + continue; - // The balance equation for a finite volume is: - // - // dStorage/dt = Flux + Source - // - // where the 'Flux' and the 'Source' terms represent the - // mass per second which _ENTER_ the finite - // volume. Re-arranging this, we get - // - // dStorage/dt - Source - Flux = 0 - // - // Since the flux calculated by computeFlux() goes _OUT_ - // of sub-control volume i and _INTO_ sub-control volume - // j, we need to add the flux to finite volume i and - // subtract it from finite volume j - this->residual_[i] += flux; - this->residual_[j] -= flux; + this->asImp_().evalDirichlet_(scv, bcTypes); + } } } - - const VertexMapper &vertexMapper_() const - { return this->problem_().vertexMapper(); } }; } -- GitLab From b3d1e7f34a71b1bbb502652eb303e0f063eb3bf1 Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 5 Jul 2016 13:02:14 +0200 Subject: [PATCH 39/45] [box] set newly introduced property defaults --- dumux/implicit/box/propertydefaults.hh | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/dumux/implicit/box/propertydefaults.hh b/dumux/implicit/box/propertydefaults.hh index dd54544541..f077377c63 100644 --- a/dumux/implicit/box/propertydefaults.hh +++ b/dumux/implicit/box/propertydefaults.hh @@ -28,10 +28,15 @@ #include #include -#include +#include +#include "fluxvariablescachevector.hh" +#include "volumevariablesvector.hh" #include "elementboundarytypes.hh" +#include "fvelementgeometryvector.hh" #include "localresidual.hh" +#include "localjacobian.hh" +#include "assembler.hh" #include "properties.hh" #include "stencils.hh" @@ -43,15 +48,15 @@ namespace Dumux { // forward declarations template class BoxLocalResidual; template class BoxElementBoundaryTypes; -template class BoxFVElementGeometryVector; template class BoxStencilsVector; +template class BoxFVElementGeometryVector; namespace Properties { //! Set the corresponding discretization method property SET_INT_PROP(BoxModel, DiscretizationMethod, GET_PROP(TypeTag, DiscretizationMethods)::Box); //! Set the default for the FVElementGeometry vector -SET_TYPE_PROP(BoxModel, FVElementGeometryVector, BoxFVElementGeometryVector); +SET_TYPE_PROP(BoxModel, FVElementGeometryVector, BoxFVElementGeometryVector); //! The sub control volume SET_PROP(BoxModel, SubControlVolume) @@ -89,9 +94,24 @@ SET_TYPE_PROP(BoxModel, DofMapper, typename GET_PROP_TYPE(TypeTag, VertexMapper) //! The stencil container SET_TYPE_PROP(BoxModel, StencilsVector, Dumux::BoxStencilsVector); +//! The global current volume variables vector class +SET_TYPE_PROP(BoxModel, CurrentVolumeVariablesVector, Dumux::BoxVolumeVariablesVector); + +//! The global previous volume variables vector class +SET_TYPE_PROP(BoxModel, PreviousVolumeVariablesVector, Dumux::BoxVolumeVariablesVector); + +//! The global flux variables cache vector class +SET_TYPE_PROP(BoxModel, FluxVariablesCacheVector, Dumux::BoxFluxVariablesCacheVector); + //! Set the BaseLocalResidual to BoxLocalResidual SET_TYPE_PROP(BoxModel, BaseLocalResidual, Dumux::BoxLocalResidual); +//! Assembler for the global jacobian matrix +SET_TYPE_PROP(BoxModel, JacobianAssembler, Dumux::BoxAssembler); + +//! The local jacobian operator +SET_TYPE_PROP(BoxModel, LocalJacobian, Dumux::BoxLocalJacobian); + //! indicate that this is a box discretization SET_BOOL_PROP(BoxModel, ImplicitIsBox, true); -- GitLab From d3690110c09bcb6c0c7f87ed4e3b7c9afb157ad8 Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 5 Jul 2016 13:03:17 +0200 Subject: [PATCH 40/45] [box] complete the box stencils implementation --- dumux/implicit/box/stencils.hh | 59 ++++++++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 10 deletions(-) diff --git a/dumux/implicit/box/stencils.hh b/dumux/implicit/box/stencils.hh index 19ef1b63e7..3185f8a55f 100644 --- a/dumux/implicit/box/stencils.hh +++ b/dumux/implicit/box/stencils.hh @@ -43,14 +43,14 @@ class BoxElementStencils using IndexType = typename GridView::IndexSet::IndexType; using Element = typename GridView::template Codim<0>::Entity; // TODO a separate stencil class all stencils can derive from? - using Stencil = std::set; + using Stencil = std::vector; static const int dim = GridView::dimension; public: void update(const Problem& problem, const Element& element) { for(int vIdxLocal = 0; vIdxLocal < element.subEntities(dim); ++vIdxLocal) - elementStencil_.insert(problem.vertexMapper().subIndex(element, vIdxLocal, dim)); + elementStencil_.push_back(problem.vertexMapper().subIndex(element, vIdxLocal, dim)); } //! The full element stencil (all element this element is interacting with) @@ -75,7 +75,7 @@ class BoxVertexStencils using IndexType = typename GridView::IndexSet::IndexType; using Element = typename GridView::template Codim<0>::Entity; // TODO a separate stencil class all stencils can derive from? - using Stencil = std::set; + using Stencil = std::vector; public: //! The full vertex stencil (all vertices this vertex is interacting with) const Stencil& vertexStencil() const @@ -83,6 +83,18 @@ public: return vertexStencil_; } + //! The scv indices connected to a vertex + const Stencil& vertexScvs() const + { + return vertexScvs_; + } + + //! The element indices adjacent to the vertex + const Stencil& elementIndices() const + { + return elementIndices_; + } + private: //! The full vertex stencil (all vertices this vertex is interacting with) Stencil& vertexStencil() @@ -90,7 +102,19 @@ private: return vertexStencil_; } + Stencil& vertexScvs() + { + return vertexScvs_; + } + + Stencil& elementIndices() + { + return elementIndices_; + } + Stencil vertexStencil_; + Stencil vertexScvs_; + Stencil elementIndices_; }; /*! @@ -106,7 +130,7 @@ class BoxStencilsVector static const int dim = GridView::dimension; public: - void update(const Problem& problem) + void update(Problem& problem) { problemPtr_ = &problem; elementStencils_.resize(problem.gridView().size(0)); @@ -116,20 +140,35 @@ public: auto eIdx = problem.elementMapper().index(element); elementStencils_[eIdx].update(problem, element); - for (int vIdxLocalI = 0; vIdxLocalI < element.subEntities(dim); ++vIdxLocalI) + // bind the FvGeometry to the element before using it + problem.model().fvGeometries_().bindElement(element); + const auto& fvGeometry = problem.model().fvGeometries(element); + + for (const auto& scv : fvGeometry.scvs()) { - auto globalI = problem.vertexMapper().subIndex(element, vIdxLocalI, dim); - for (int vIdxLocalJ = vIdxLocalI; vIdxLocalJ < element.subEntities(dim); ++vIdxLocalJ) + auto vIdxGlobal = scv.dofIndex(); + vertexStencils_[vIdxGlobal].vertexScvs().push_back(scv.index()); + vertexStencils_[vIdxGlobal].elementIndices().push_back(eIdx); + + for (const auto& scvJ : fvGeometry.scvs()) { - auto globalJ = problem.vertexMapper().subIndex(element, vIdxLocalJ, dim); + auto vIdxGlobalJ = scvJ.dofIndex(); // make sure that vertex j is in the neighbor set // of vertex i and vice-versa - vertexStencils_[globalI].vertexStencil().insert(globalJ); - vertexStencils_[globalJ].vertexStencil().insert(globalI); + vertexStencils_[vIdxGlobal].vertexStencil().push_back(vIdxGlobalJ); + vertexStencils_[vIdxGlobalJ].vertexStencil().push_back(vIdxGlobal); } } } + + // The vertex indices in the stencils have to be made unique + for (auto& vertexStencil : vertexStencils_) + { + auto& vertStencil = vertexStencil.vertexStencil(); + std::sort(vertStencil.begin(), vertStencil.end()); + vertStencil.erase(std::unique(vertStencil.begin(), vertStencil.end()), vertStencil.end()); + } } //! overload for elements -- GitLab From d1dbf8c66439a003af052eafe4436c95f78b1509 Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 5 Jul 2016 13:03:42 +0200 Subject: [PATCH 41/45] [box] implement darcys law for the box method --- .../constitutivelaws/darcyslaw.hh | 208 ++++++------------ 1 file changed, 72 insertions(+), 136 deletions(-) diff --git a/dumux/porousmediumflow/constitutivelaws/darcyslaw.hh b/dumux/porousmediumflow/constitutivelaws/darcyslaw.hh index 38c154c3db..f5f6fb07fd 100644 --- a/dumux/porousmediumflow/constitutivelaws/darcyslaw.hh +++ b/dumux/porousmediumflow/constitutivelaws/darcyslaw.hh @@ -33,6 +33,7 @@ #include #include +#include namespace Dumux @@ -201,175 +202,110 @@ private: template class DarcysLaw::type > { - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - using Problem = typename GET_PROP_TYPE(TypeTag, Problem); - using SubControlVolume = typename GET_PROP_TYPE(TypeTag, SubControlVolume); - using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); - using VolumeVariables = typename GET_PROP_TYPE(TypeTag, VolumeVariables); - using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes); - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using IndexType = typename GridView::IndexSet::IndexType; - using Element = typename GridView::template Codim<0>::Entity; + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, SubControlVolume) SubControlVolume; + typedef typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace) SubControlVolumeFace; + typedef typename GET_PROP_TYPE(TypeTag, FluxVariablesCache) FluxVariablesCache; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + + typedef typename GridView::template Codim<0>::Entity Element; + typedef typename GridView::IndexSet::IndexType IndexType; + typedef typename GridView::ctype CoordScalar; + typedef std::vector Stencil; enum { dim = GridView::dimension} ; enum { dimWorld = GridView::dimensionworld} ; - enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases)} ; - - using DimWorldMatrix = Dune::FieldMatrix; - using GlobalPosition = Dune::FieldVector; - -public: - - void update(const Problem& problem, - const Element& element, - const SubControlVolumeFace& scvFace) - { - DUNE_THROW(Dune::NotImplemented, "Darcy's law for the Box method is not yet implemented!"); - - problemPtr_ = &problem; - scvFacePtr_ = &scvFace; - elementPtr_ = &element; - enableGravity_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Problem, EnableGravity); - updateTransmissibilities_(); - } + typedef Dune::FieldMatrix DimWorldMatrix; + typedef Dune::FieldVector DimVector; - void update(const Problem& problem, - const Element& element, - const SubControlVolumeFace &scvFace, - VolumeVariables* boundaryVolVars) - { - update(problem, element, scvFace); - } + typedef Dune::PQkLocalFiniteElementCache FeCache; + typedef typename FeCache::FiniteElementType::Traits::LocalBasisType FeLocalBasis; + typedef typename FluxVariablesCache::FaceData FaceData; - void updateTransmissibilities(const Problem &problem, const SubControlVolumeFace &scvFace) - { - updateTransmissibilities_(); - } +public: - void beginFluxComputation(bool boundaryVolVarsUpdated = false) + static Scalar flux(const Problem& problem, + const Element& element, + const SubControlVolumeFace& scvFace, + const IndexType phaseIdx) { - // Get the inside volume variables - const auto insideScvIdx = scvFace_().insideScvIdx(); - const auto& insideScv = problem_().model().fvGeometries().subControlVolume(insideScvIdx); - const auto* insideVolVars = &problem_().model().curVolVars(insideScv); + // get the precalculated local jacobian and shape values at the integration point + const auto& faceData = problem.model().fluxVarsCache()[scvFace].faceData(); - // and the outside volume variables - const VolumeVariables* outsideVolVars; - outsideVolVars = &problem_().model().curVolVars(scvFace_().outsideScvIdx()); + const auto& fvGeometry = problem.model().fvGeometries(element); + const auto& insideScv = problem.model().fvGeometries().subControlVolume(scvFace.insideScvIdx()); + const auto extrusionFactor = problem.model().curVolVars(insideScv).extrusionFactor(); + const auto K = problem.spatialParams().intrinsicPermeability(insideScv); - // loop over all phases to compute the volume flux - for (int phaseIdx = 0; phaseIdx < numPhases; phaseIdx++) + // evaluate gradP - rho*g at integration point + DimVector gradP(0.0); + for (const auto& scv : fvGeometry.scvs()) { - auto hInside = insideVolVars->pressure(phaseIdx); - auto hOutside = outsideVolVars->pressure(phaseIdx); - - if (enableGravity_) - { - // do averaging for the density - const auto rhoInside = insideVolVars->density(phaseIdx); - const auto rhoOutide = outsideVolVars->density(phaseIdx); - const auto rho = (rhoInside + rhoOutide)*0.5; + // the global shape function gradient + DimVector gradI; + faceData.jacInvT.mv(faceData.localJacobian[scv.indexInElement()][0], gradI); + gradI *= problem.model().curVolVars(scv).pressure(phaseIdx); + gradP += gradI; + } + if (GET_PARAM_FROM_GROUP(TypeTag, bool, Problem, EnableGravity)) + { + // gravitational acceleration + DimVector g(problem.gravityAtPos(scvFace.center())); - // ask for the gravitational acceleration in the inside neighbor - const auto xInside = insideScv.center(); - const auto gInside = problem_().gravityAtPos(xInside); - - hInside -= rho*(gInside*xInside); - - const auto outsideScvIdx = scvFace_().outsideScvIdx(); - const auto& outsideScv = problem_().model().fvGeometries().subControlVolume(outsideScvIdx); - const auto xOutside = outsideScv.center(); - const auto gOutside = problem_().gravityAtPos(xOutside); - hOutside -= rho*(gOutside*xOutside); - } + // interpolate the density at the IP + const auto& insideVolVars = problem.model().curVolVars(insideScv); + const auto& outsideScv = problem.model().fvGeometries().subControlVolume(scvFace.outsideScvIdx()); + const auto& outsideVolVars = problem.model().curVolVars(outsideScv); + Scalar rho = 0.5*(insideVolVars.density(phaseIdx) + outsideVolVars.density(phaseIdx)); - kGradPNormal_[phaseIdx] = tij_*(hInside - hOutside); + // turn gravity into a force + g *= rho; - if (std::signbit(kGradPNormal_[phaseIdx])) - { - upWindIndices_[phaseIdx] = std::make_pair(scvFace_().outsideScvIdx(), scvFace_().insideScvIdx()); - } - else - { - upWindIndices_[phaseIdx] = std::make_pair(scvFace_().insideScvIdx(), scvFace_().outsideScvIdx()); - } + // subtract from pressure gradient + gradP -= g; } - } - /*! - * \brief A function to calculate the mass flux over a sub control volume face - * - * \param phaseIdx The index of the phase of which the flux is to be calculated - * \param upwindFunction A function which does the upwinding - */ - template - Scalar flux(IndexType phaseIdx, FunctionType upwindFunction) const - { - return kGradPNormal_[phaseIdx]*upwindFunction(upVolVars(phaseIdx), dnVolVars(phaseIdx)); + // apply the permeability and return the flux + auto KGradP = applyPermeability(K, gradP); + return -1.0*(KGradP*scvFace.unitOuterNormal())*scvFace.area()*extrusionFactor; } - // for compatibility with cell-centered models - const std::set& stencil() const + static DimVector applyPermeability(const DimWorldMatrix& K, const DimVector& gradI) { - return std::set(); - } + DimVector result(0.0); + K.mv(gradI, result); - const VolumeVariables& upVolVars(IndexType phaseIdx) const - { - return problem_().model().curVolVars(upWindIndices_[phaseIdx].first); + return result; } - const VolumeVariables& dnVolVars(IndexType phaseIdx) const + static DimVector applyPermeability(const Scalar k, const DimVector& gradI) { - return problem_().model().curVolVars(upWindIndices_[phaseIdx].second); + DimVector result(gradI); + result *= k; + return result; } -private: - - void updateTransmissibilities_() + // This is for compatibility with the cc methods. The flux stencil info is obsolete for the box method. + static Stencil stencil(const Problem& problem, const Element& element, const SubControlVolumeFace& scvFace) { - const auto insideScvIdx = scvFace_().insideScvIdx(); - const auto& insideScv = problem_().model().fvGeometries().subControlVolume(insideScvIdx); - const auto insideK = problem_().spatialParams().intrinsicPermeability(insideScv); - Scalar ti = calculateOmega_(insideK, insideScv); - - const auto outsideScvIdx = scvFace_().outsideScvIdx(); - const auto& outsideScv = problem_().model().fvGeometries().subControlVolume(outsideScvIdx); - const auto outsideK = problem_().spatialParams().intrinsicPermeability(outsideScv); - Scalar tj = -1.0*calculateOmega_(outsideK, outsideScv); - - tij_ = scvFace_().area()*(ti * tj)/(ti + tj); + return Stencil(0); } - const Problem &problem_() const + static FaceData calculateFaceData(const Problem& problem, const Element& element, const typename Element::Geometry& geometry, const FeLocalBasis& localBasis, const SubControlVolumeFace& scvFace) { - return *problemPtr_; - } + FaceData faceData; - const SubControlVolumeFace& scvFace_() const - { - return *scvFacePtr_; - } + // evaluate shape functions and gradients at the integration point + const auto ipLocal = geometry.local(scvFace.center()); + faceData.jacInvT = geometry.jacobianInverseTransposed(ipLocal); + localBasis.evaluateJacobian(ipLocal, faceData.localJacobian); + localBasis.evaluateFunction(ipLocal, faceData.shapeValues); - const Element& element_() const - { - return *elementPtr_; + return std::move(faceData); } - - const Problem *problemPtr_; //! Pointer to the problem - const SubControlVolumeFace *scvFacePtr_; //! Pointer to the sub control volume face for which the flux variables are created - const Element *elementPtr_; //! Point to the element - bool enableGravity_; //! If we have a problem considering gravitational effects - - //! The upstream (first) and downstream (second) volume variable indices - std::array, numPhases> upWindIndices_; - Scalar tij_ = 0; - - //! Precomputed values - std::array kGradPNormal_; //! K(grad(p) - rho*g)*n - GlobalPosition normalK_; //! (K^T)n }; } // end namespace -- GitLab From efd46f06230ab2bb1922b0db1233378cb46557da Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 5 Jul 2016 13:06:28 +0200 Subject: [PATCH 42/45] [box] implement volume variables vector --- dumux/implicit/box/volumevariablesvector.hh | 521 ++++++++++++++++++++ 1 file changed, 521 insertions(+) create mode 100644 dumux/implicit/box/volumevariablesvector.hh diff --git a/dumux/implicit/box/volumevariablesvector.hh b/dumux/implicit/box/volumevariablesvector.hh new file mode 100644 index 0000000000..0b97fdd5c6 --- /dev/null +++ b/dumux/implicit/box/volumevariablesvector.hh @@ -0,0 +1,521 @@ +// -*- 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 . * + *****************************************************************************/ +/*! + * \file + * \brief Base class for the volume variables vector + */ +#ifndef DUMUX_IMPLICIT_BOX_VOLVARSVECTOR_HH +#define DUMUX_IMPLICIT_BOX_VOLVARSVECTOR_HH + +#include + +namespace Dumux +{ + +/*! + * \ingroup ImplicitModel + * \brief Base class for the volume variables vector + */ +template +class BoxVolumeVariablesVector +{}; + +// specialization in case of storing the volume variables +template +class BoxVolumeVariablesVector : public std::vector +{ + friend BoxVolumeVariablesVector; + friend ImplicitModel; + using Problem = typename GET_PROP_TYPE(TypeTag, Problem); + using GridView = typename GET_PROP_TYPE(TypeTag, GridView); + using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector); + using VolumeVariables = typename GET_PROP_TYPE(TypeTag, VolumeVariables); + using SubControlVolume = typename GET_PROP_TYPE(TypeTag, SubControlVolume); + using IndexType = typename GridView::IndexSet::IndexType; + + static const int dim = GridView::dimension; + using Element = typename GridView::template Codim<0>::Entity; + using Vertex = typename GridView::template Codim::Entity; + + enum{ isBox = GET_PROP_VALUE(TypeTag, ImplicitIsBox) }; + + BoxVolumeVariablesVector& operator= (const BoxVolumeVariablesVector& other) = default; + + BoxVolumeVariablesVector& operator= (const BoxVolumeVariablesVector& other) + { + // do the copy + numScvs_ = other.numScvs_; + volumeVariables_ = other.volumeVariables_; + + // return the existing object + return *this; + }; + +public: + void update(Problem& problem, const SolutionVector& sol) + { + problemPtr_ = &problem; + + numScvs_ = problem.model().fvGeometries().numScv(); + volumeVariables_.resize(numScvs_); + for (const auto& element : elements(problem.gridView())) + { + problem.model().fvGeometries_().bindElement(element); + const auto& fvGeometry = problem.model().fvGeometries(element); + + for (const auto& scv : fvGeometry.scvs()) + { + (*this)[scv].update(sol[scv.dofIndex()], + problem, + element, + scv); + } + } + } + + const VolumeVariables& operator [](IndexType scvIdx) const + { + const auto& scv = problem_().model().fvGeometries().subControlVolume(scvIdx); + return (*this)[scv]; + } + + VolumeVariables& operator [](IndexType scvIdx) + { + const auto& scv = problem_().model().fvGeometries().subControlVolume(scvIdx); + return (*this)[scv]; + } + + const VolumeVariables& operator [](const SubControlVolume& scv) const + { + return volumeVariables_[scv.index()]; + } + + VolumeVariables& operator [](const SubControlVolume& scv) + { + return volumeVariables_[scv.index()]; + } + + // For compatibility reasons with the case of not storing the vol vars. + // function to be called before assembling an element, preparing the vol vars within the stencil + void bind(const Element& element) {} + // In the box method, the vol vars within the elements adjacent to a vertex need to be bound + void bind(const Vertex& vertex) {} + // function to prepare the vol vars within the element + void bindElement(const Element& element) {} + +private: + const Problem& problem_() const + { return *problemPtr_; } + + const Problem* problemPtr_; + + IndexType eIdxBound_; + IndexType numScvs_; + std::vector volumeVariables_; +}; + + +// Specialization when the current volume variables are not stored +template +class BoxVolumeVariablesVector +{ + // prev vol vars have to be a friend class in order for the assignment operator to work + friend BoxVolumeVariablesVector; + friend ImplicitModel; + using Problem = typename GET_PROP_TYPE(TypeTag, Problem); + using GridView = typename GET_PROP_TYPE(TypeTag, GridView); + using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector); + using VolumeVariables = typename GET_PROP_TYPE(TypeTag, VolumeVariables); + using SubControlVolume = typename GET_PROP_TYPE(TypeTag, SubControlVolume); + using IndexType = typename GridView::IndexSet::IndexType; + + static const int dim = GridView::dimension; + using Element = typename GridView::template Codim<0>::Entity; + using Vertex = typename GridView::template Codim::Entity; + + BoxVolumeVariablesVector& operator= (const BoxVolumeVariablesVector& other) = default; + + // operator curVolVars = prevVolVars + void operator= (const BoxVolumeVariablesVector& other) + { + eIdxBound_ = -1; + } + + BoxVolumeVariablesVector() : problemPtr_(nullptr), eIdxBound_(-1) {} + + +public: + + void update(Problem& problem, const SolutionVector& sol) + { + problemPtr_ = &problem; + } + + + // Binding of an element, prepares the volume variables within the element stencil + // called by the local jacobian to prepare element assembly + // specialization for cc models + template + typename std::enable_if::type + bind(const Element& element) + { + const auto eIdx = problem_().elementMapper().index(element); + if (eIdx == eIdxBound_ && volVarIndices_.size() > 1) + return; + + eIdxBound_ = eIdx; + + // make sure the FVElementGeometry is bound to the element + problem_().model().fvGeometries_().bind(element); + const auto& fvGeometry = problem_().model().fvGeometries(eIdx); + + // stencil information + const auto& elementStencil = problem_().model().stencils(element).elementStencil(); + const auto& neighborStencil = problem_().model().stencils(element).neighborStencil(); + + // maximum number of possible vol vars to be created + const auto numDofs = elementStencil.size();;// + fvGeometry.numScvf(); + + // resize local containers to the required size + volumeVariables_.resize(numDofs); + volVarIndices_.resize(numDofs); + int localIdx = 0; + + // update the volume variables of the element at hand + const auto& scvI = problem_().model().fvGeometries().subControlVolume(eIdx); + const auto& solI = problem_().model().curSol()[eIdx]; + // VolumeVariables tmp; + // tmp.update(solI, problem_(), element, scvI); + volumeVariables_[localIdx].update(solI, problem_(), element, scvI); + volVarIndices_[localIdx] = scvI.index(); + // volumeVariables_.push_back(tmp); + // volVarIndices_.push_back(scvI.index()); + localIdx++; + + // Update the volume variables of the neighboring elements + for (auto globalJ : neighborStencil) + { + const auto& elementJ = problem_().model().fvGeometries().element(globalJ); + const auto& scvJ = problem_().model().fvGeometries().subControlVolume(globalJ); + const auto& solJ = problem_().model().curSol()[globalJ]; + // tmp.update(solJ, problem_(), elementJ, scvJ); + // volumeVariables_.push_back(tmp); + // volVarIndices_.push_back(scvJ.index()); + volumeVariables_[localIdx].update(solJ, problem_(), elementJ, scvJ); + volVarIndices_[localIdx] = scvJ.index(); + localIdx++; + } + + // Update boundary volume variables + for (const auto& scvFace : fvGeometry.scvfs()) + { + // if we are not on a boundary, skip the rest + if (!scvFace.boundary()) + continue; + + // When complex boundary handling is inactive, we only use BC vol vars on pure Dirichlet boundaries + const auto bcTypes = problem_().boundaryTypes(element, scvFace); + if (/*TODO !GET_PROP_VALUE(TypeTag, BoundaryReconstruction) && */bcTypes.hasNeumann() || bcTypes.hasOutflow()) + continue; + + const auto dirichletPriVars = problem_().dirichlet(element, scvFace); + // tmp.update(dirichletPriVars, problem_(), element, scvI); + // volumeVariables_.push_back(tmp); + // volVarIndices_.push_back(scvI.index()); + volumeVariables_.resize(localIdx+1); + volVarIndices_.resize(localIdx+1); + volumeVariables_[localIdx].update(dirichletPriVars, problem_(), element, scvI); + volVarIndices_[localIdx] = scvFace.outsideScvIdx(); + localIdx++; + } + } + + // specialization for box models, simply forwards to the bindElement method + template + typename std::enable_if::type + bind(const Element& element) + { + bindElement(element); + } + + // Binding of an element, prepares only the volume variables of the element + // specialization for cc models + template + typename std::enable_if::type + bindElement(const Element& element) + { + const auto eIdx = problem_().elementMapper().index(element); + if (eIdx == eIdxBound_ || std::find(volVarIndices_.begin(), volVarIndices_.end(), eIdx) != volVarIndices_.end()) + return; + + volumeVariables_.resize(1); + volVarIndices_.resize(1); + eIdxBound_ = eIdx; + + // make sure the FVElementGeometry is bound to the element + problem_().model().fvGeometries_().bindElement(element); + + // update the volume variables of the element at hand + const auto& scv = problem_().model().fvGeometries().subControlVolume(eIdx); + const auto& sol = problem_().model().curSol()[eIdx]; + volumeVariables_[0].update(sol, problem_(), element, scv); + volVarIndices_[0] = scv.index(); + } + + // In the box method, the vol vars within the elements adjacent to a vertex need to be bound (TODO: IMPLEMENT) + template + typename std::enable_if::type + bind(const Vertex& vertex) const {} + + // specialization for box models + template + typename std::enable_if::type + bindElement(const Element& element) + { + const auto eIdx = problem_().elementMapper().index(element); + if (eIdx == eIdxBound_) + return; + + eIdxBound_ = eIdx; + + // make sure the FVElementGeometry is bound to the element + problem_().model().fvGeometries_().bind(element); + const auto& fvGeometry = problem_().model().fvGeometries(element); + + // get stencil information + const auto numDofs = element.subEntities(dim); + + // resize volume variables to the required size + volumeVariables_.resize(numDofs); + // volVarIndices_.resize(numDofs); + + int localIdx = 0; + for (const auto& scv : fvGeometry.scvs()) + { + // std::cout << "scv index: " << scv.index() << ", dofIdx: " << scv.dofIndex() << ", localIdx: " << scv.indexInElement() << std::endl; + const auto& sol = problem_().model().curSol()[scv.dofIndex()]; + // let the interface solver update the volvars + // volVarIndices_[localIdx] = scv.index(); + // TODO: INTERFACE SOLVER + // problem_().model().boxInterfaceConditionSolver().updateScvVolVars(element, scv, sol); + volumeVariables_[scv.indexInElement()].update(sol, problem_(), element, scv); + localIdx++; + } + // std::cout << "finished\n"; + } + + const VolumeVariables& operator [](IndexType scvIdx) const + { + return volumeVariables_[scvIdx]; + } + + VolumeVariables& operator [](IndexType scvIdx) + { + return volumeVariables_[scvIdx]; + } + + const VolumeVariables& operator [](const SubControlVolume& scv) const + { + return volumeVariables_[scv.indexInElement()]; + } + + VolumeVariables& operator [](const SubControlVolume& scv) + { + return volumeVariables_[scv.indexInElement()]; + } + +private: + + void release_() + { + volumeVariables_.clear(); + volVarIndices_.clear(); + } + + const int getLocalIdx_(const int volVarIdx) const + { + auto it = std::find(volVarIndices_.begin(), volVarIndices_.end(), volVarIdx); + + if (it != volVarIndices_.end()) + return std::distance(volVarIndices_.begin(), it); + else + DUNE_THROW(Dune::InvalidStateException, "Could not find the current volume variables for volVarIdx = " << volVarIdx << + ", make sure to properly bind the volume variables to the element before using them"); + } + + Problem& problem_() const + { return *problemPtr_;} + + Problem* problemPtr_; + IndexType eIdxBound_; + std::vector volVarIndices_; + std::vector volumeVariables_; +}; + +// Specialization when the previous volume variables are not stored +template +class BoxVolumeVariablesVector +{ + // current vol vars have to be a friend class in order for the assignment operator to work + friend BoxVolumeVariablesVector; + friend ImplicitModel; + using Problem = typename GET_PROP_TYPE(TypeTag, Problem); + using GridView = typename GET_PROP_TYPE(TypeTag, GridView); + using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector); + using VolumeVariables = typename GET_PROP_TYPE(TypeTag, VolumeVariables); + using SubControlVolume = typename GET_PROP_TYPE(TypeTag, SubControlVolume); + using IndexType = typename GridView::IndexSet::IndexType; + + static const int dim = GridView::dimension; + using Element = typename GridView::template Codim<0>::Entity; + using Vertex = typename GridView::template Codim::Entity; + + BoxVolumeVariablesVector& operator= (const BoxVolumeVariablesVector& other) + { + release_(); + problemPtr_ = other.problemPtr_; + eIdxBound_ = -1; + return *this; + } + + BoxVolumeVariablesVector() : problemPtr_(nullptr), eIdxBound_(-1) {} + + +public: + + void update(const Problem& problem, const SolutionVector& sol) + { + problemPtr_ = &problem; + } + + // Binding of an element, prepares the volume variables of only the element + // specialization for cc models + template + typename std::enable_if::type + bindElement(const Element& element) + { + const auto eIdx = problem_().elementMapper().index(element); + if (eIdx == eIdxBound_) + return; + + volumeVariables_.resize(1); + volVarIndices_.resize(1); + eIdxBound_ = eIdx; + + // make sure FVElementGeometry is bound to the element + problem_().model().fvGeometries_().bindElement(element); + + // update the volume variables of the element at hand + const auto& scv = problem_().model().fvGeometries().subControlVolume(eIdx); + const auto& sol = problem_().model().prevSol()[eIdx]; + volumeVariables_[0].update(sol, problem_(), element, scv); + volVarIndices_[0] = scv.index(); + } + + // specialization for box models + template + typename std::enable_if::type + bindElement(const Element& element) + { + const auto eIdx = problem_().elementMapper().index(element); + if (eIdx == eIdxBound_) + return; + + eIdxBound_ = eIdx; + + // make sure the FVElementGeometry is bound to the element + problem_().model().fvGeometries_().bind(element); + const auto& fvGeometry = problem_().model().fvGeometries(element); + + // get stencil information + const auto numDofs = element.subEntities(dim); + + // resize volume variables to the required size + volumeVariables_.resize(numDofs); + // volVarIndices_.resize(numDofs); + + int localIdx = 0; + for (const auto& scv : fvGeometry.scvs()) + { + const auto& sol = problem_().model().prevSol()[scv.dofIndex()]; + // let the interface solver update the volvars + // volVarIndices_[localIdx] = scv.index(); + //TODO: INTERFACE SOLVER? + // problem_().model().boxInterfaceConditionSolver().updateScvVolVars(element, scv, sol); + volumeVariables_[localIdx].update(sol, problem_(), element, scv); + localIdx++; + } + } + + // In the box method, the vol vars within the elements adjacent to a vertex need to be bound (TODO: IMPLEMENT) + template + typename std::enable_if::type + bind(const Vertex& vertex) const {} + + // const VolumeVariables& operator [](IndexType scvIdx) const + // { + // return volumeVariables_[getLocalIdx_(scvIdx)]; + // } + + // VolumeVariables& operator [](IndexType scvIdx) + // { + // return volumeVariables_[getLocalIdx_(scvIdx)]; + // } + + const VolumeVariables& operator [](const SubControlVolume& scv) const + { + return volumeVariables_[scv.indexInElement()]; + } + + VolumeVariables& operator [](const SubControlVolume& scv) + { + return volumeVariables_[scv.indexInElement()]; + } + +private: + + void release_() + { + volumeVariables_.clear(); + volVarIndices_.clear(); + } + + const int getLocalIdx_(const int volVarIdx) const + { + auto it = std::find(volVarIndices_.begin(), volVarIndices_.end(), volVarIdx); + + if (it != volVarIndices_.end()) + return std::distance(volVarIndices_.begin(), it); + else + DUNE_THROW(Dune::InvalidStateException, "Could not find the previous volume variables for volVarIdx = " << volVarIdx << + ", make sure to properly bind the volume variables to the element before using them"); + } + + Problem& problem_() const + { return *problemPtr_;} + + Problem* problemPtr_; + IndexType eIdxBound_; + std::vector volVarIndices_; + std::vector volumeVariables_; +}; + +} // end namespace + +#endif -- GitLab From 6b6c71fb1535d311fed7bce1a756795b1d60b2f8 Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 5 Jul 2016 13:06:47 +0200 Subject: [PATCH 43/45] [box] implement flux var cache vector --- .../implicit/box/fluxvariablescachevector.hh | 131 ++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 dumux/implicit/box/fluxvariablescachevector.hh diff --git a/dumux/implicit/box/fluxvariablescachevector.hh b/dumux/implicit/box/fluxvariablescachevector.hh new file mode 100644 index 0000000000..1208662561 --- /dev/null +++ b/dumux/implicit/box/fluxvariablescachevector.hh @@ -0,0 +1,131 @@ +// -*- 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 . * + *****************************************************************************/ +/*! + * \file + * \brief Base class for the volume variables vector + */ +#ifndef DUMUX_IMPLICIT_BOX_FLUXVARSCACHEVECTOR_HH +#define DUMUX_IMPLICIT_BOX_FLUXVARSCACHEVECTOR_HH + +#include + +namespace Dumux +{ + +/*! + * \ingroup ImplicitModel + * \brief Base class for the flux variables cache vector, we store one cache per face + */ +template +class BoxFluxVariablesCacheVector +{ + using Problem = typename GET_PROP_TYPE(TypeTag, Problem); + using GridView = typename GET_PROP_TYPE(TypeTag, GridView); + using IndexType = typename GridView::IndexSet::IndexType; + using Element = typename GridView::template Codim<0>::Entity; + using FluxVariablesCache = typename GET_PROP_TYPE(TypeTag, FluxVariablesCache); + using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); + +public: + template + typename std::enable_if::type update(Problem& problem) + { + problemPtr_ = &problem; + fluxVarsCache_.resize(problem.model().fvGeometries().numScvf()); + for (const auto& element : elements(problem.gridView())) + { + // bind the geometries and volume variables to the element (all the elements in stencil) + problem.model().fvGeometries_().bind(element); + + const auto& elementGeometry = element.geometry(); + const auto& localBasis = problem.model().fvGeometries().feLocalBasis(elementGeometry.type()); + const auto& fvGeometry = problem.model().fvGeometries(element); + for (const auto& scvf : fvGeometry.scvfs()) + { + (*this)[scvf].update(problem, element, elementGeometry, localBasis, scvf); + } + } + } + + template + typename std::enable_if::type update(Problem& problem) + { + problemPtr_ = &problem; + } + + // Function is called by the BoxLocalJacobian prior to flux calculations on the element. + // We assume the FVGeometries to be bound at this point + void bind(const Element& element) + { + bindElement(element); + } + + template + typename std::enable_if::type + bindElement(const Element& element) + { + const auto& fvGeometry = problem_().model().fvGeometries(element); + const auto& elementGeometry = element.geometry(); + const auto& localBasis = problem_().model().fvGeometries().feLocalBasis(elementGeometry.type()); + + // temporary resizing of the cache + const auto numScvf = fvGeometry.numScvf(); + fluxVarsCache_.resize(numScvf); + IndexType localScvfIdx = 0; + for (const auto& scvf : fvGeometry.scvfs()) + fluxVarsCache_[localScvfIdx++].update(problem_(), element, elementGeometry, localBasis, scvf); + } + + template + typename std::enable_if::type + bindElement(const Element& element) {} + + // access operators in the case of caching + template + const typename std::enable_if::type& + operator [](const SubControlVolumeFace& scvf) const + { return fluxVarsCache_[scvf.index()]; } + + template + typename std::enable_if::type& + operator [](const SubControlVolumeFace& scvf) + { return fluxVarsCache_[scvf.index()]; } + + // access operators in the case of no caching + template + const typename std::enable_if::type& + operator [](const SubControlVolumeFace& scvf) const + { return fluxVarsCache_[scvf.indexInElement()]; } + + template + typename std::enable_if::type& + operator [](const SubControlVolumeFace& scvf) + { return fluxVarsCache_[scvf.indexInElement()]; } + +private: + const Problem& problem_() const + { return *problemPtr_; } + + const Problem* problemPtr_; + std::vector fluxVarsCache_; +}; + +} // end namespace + +#endif -- GitLab From 739298381d80e1e47cf6d6ffdbd423227b88fcdf Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 5 Jul 2016 19:15:14 +0200 Subject: [PATCH 44/45] introduce discretization folder A new folder named discretization is introduced on the /dumux level. In this folder there are all the geometry classes as well as vol vars, flux var cache and physical laws (darcy, fick etc), since they could be possibly reused in decoupled models and are not restricted to implicit models. NOTE: The fluxvariables and the flux variables cache are still in the folder /porousmediumflow/implicit/. It is to be discussed whether or not they should be moved into the discretization folder as well. --- dumux/CMakeLists.txt | 1 + dumux/discretization/CMakeLists.txt | 2 + dumux/discretization/box/CMakeLists.txt | 8 + dumux/discretization/box/darcyslaw.hh | 163 ++++++++ dumux/discretization/box/fickslaw.hh | 179 +++++++++ .../box/fluxvariablescachevector.hh | 4 +- .../box/fvelementgeometryvector.hh | 7 +- .../box/stencils.hh | 4 +- dumux/discretization/box/subcontrolvolume.hh | 84 ++++ .../box/subcontrolvolumeface.hh | 61 +++ .../box/volumevariablesvector.hh | 4 +- .../cellcentered/CMakeLists.txt | 7 + .../cellcentered/fluxvariablescachevector.hh | 4 +- .../cellcentered/stencils.hh | 4 +- .../cellcentered/tpfa/CMakeLists.txt | 5 + .../cellcentered/tpfa}/darcyslaw.hh | 123 +----- .../cellcentered/tpfa/fickslaw.hh | 178 ++++++++ .../tpfa/fvelementgeometryvector.hh | 26 +- .../cellcentered/tpfa/subcontrolvolume.hh | 73 ++++ .../cellcentered/tpfa/subcontrolvolumeface.hh | 62 +++ .../cellcentered/volumevariablesvector.hh | 4 +- dumux/discretization/darcyslaw.hh | 47 +++ dumux/discretization/fickslaw.hh | 59 +++ .../fluxvariablesbase.hh | 6 +- .../fvelementgeometry.hh | 9 +- .../subcontrolvolumebase.hh} | 0 .../subcontrolvolumefacebase.hh} | 23 +- .../volumevariables.hh | 6 +- dumux/implicit/box/propertydefaults.hh | 16 +- .../implicit/cellcentered/propertydefaults.hh | 6 +- .../cellcentered/tpfa/propertydefaults.hh | 9 +- dumux/implicit/propertydefaults.hh | 8 +- .../1p/implicit/volumevariables.hh | 2 +- .../2p/implicit/volumevariables.hh | 2 +- dumux/porousmediumflow/CMakeLists.txt | 3 +- .../constitutivelaws/CMakeLists.txt | 5 - .../constitutivelaws/fickslaw.hh | 379 ------------------ .../implicit/fluxvariables.hh | 2 +- 38 files changed, 1004 insertions(+), 581 deletions(-) create mode 100644 dumux/discretization/CMakeLists.txt create mode 100644 dumux/discretization/box/CMakeLists.txt create mode 100644 dumux/discretization/box/darcyslaw.hh create mode 100644 dumux/discretization/box/fickslaw.hh rename dumux/{implicit => discretization}/box/fluxvariablescachevector.hh (98%) rename dumux/{implicit => discretization}/box/fvelementgeometryvector.hh (99%) rename dumux/{implicit => discretization}/box/stencils.hh (98%) create mode 100644 dumux/discretization/box/subcontrolvolume.hh create mode 100644 dumux/discretization/box/subcontrolvolumeface.hh rename dumux/{implicit => discretization}/box/volumevariablesvector.hh (99%) create mode 100644 dumux/discretization/cellcentered/CMakeLists.txt rename dumux/{implicit => discretization}/cellcentered/fluxvariablescachevector.hh (98%) rename dumux/{implicit => discretization}/cellcentered/stencils.hh (98%) create mode 100644 dumux/discretization/cellcentered/tpfa/CMakeLists.txt rename dumux/{porousmediumflow/constitutivelaws => discretization/cellcentered/tpfa}/darcyslaw.hh (60%) create mode 100644 dumux/discretization/cellcentered/tpfa/fickslaw.hh rename dumux/{implicit => discretization}/cellcentered/tpfa/fvelementgeometryvector.hh (93%) create mode 100644 dumux/discretization/cellcentered/tpfa/subcontrolvolume.hh create mode 100644 dumux/discretization/cellcentered/tpfa/subcontrolvolumeface.hh rename dumux/{implicit => discretization}/cellcentered/volumevariablesvector.hh (99%) create mode 100644 dumux/discretization/darcyslaw.hh create mode 100644 dumux/discretization/fickslaw.hh rename dumux/{implicit => discretization}/fluxvariablesbase.hh (97%) rename dumux/{implicit => discretization}/fvelementgeometry.hh (97%) rename dumux/{implicit/subcontrolvolume.hh => discretization/subcontrolvolumebase.hh} (100%) rename dumux/{implicit/subcontrolvolumeface.hh => discretization/subcontrolvolumefacebase.hh} (87%) rename dumux/{implicit => discretization}/volumevariables.hh (97%) delete mode 100644 dumux/porousmediumflow/constitutivelaws/CMakeLists.txt delete mode 100644 dumux/porousmediumflow/constitutivelaws/fickslaw.hh diff --git a/dumux/CMakeLists.txt b/dumux/CMakeLists.txt index 93fa9f1ffe..abc88e3751 100644 --- a/dumux/CMakeLists.txt +++ b/dumux/CMakeLists.txt @@ -1,5 +1,6 @@ add_subdirectory("common") add_subdirectory("decoupled") +add_subdirectory("discretization") add_subdirectory("freeflow") add_subdirectory("geomechanics") add_subdirectory("implicit") diff --git a/dumux/discretization/CMakeLists.txt b/dumux/discretization/CMakeLists.txt new file mode 100644 index 0000000000..edb1a46d26 --- /dev/null +++ b/dumux/discretization/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory("box") +add_subdirectory("cellcentered") diff --git a/dumux/discretization/box/CMakeLists.txt b/dumux/discretization/box/CMakeLists.txt new file mode 100644 index 0000000000..b0883c5d5a --- /dev/null +++ b/dumux/discretization/box/CMakeLists.txt @@ -0,0 +1,8 @@ +install(FILES +fluxvariablescachevector.hh +fvelementgeometryvector.hh +stencils.hh +subcontrolvolumeface.hh +subcontrolvolume.hh +volumevariablesvector.hh +DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dumux/discretization/box) diff --git a/dumux/discretization/box/darcyslaw.hh b/dumux/discretization/box/darcyslaw.hh new file mode 100644 index 0000000000..d36eb7f0af --- /dev/null +++ b/dumux/discretization/box/darcyslaw.hh @@ -0,0 +1,163 @@ +// -*- 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 . * + *****************************************************************************/ +/*! + * \file + * \brief This file contains the data which is required to calculate + * volume and mass fluxes of fluid phases over a face of a finite volume by means + * of the Darcy approximation. Specializations are provided for the different discretization methods. + */ +#ifndef DUMUX_DISCRETIZATION_BOX_DARCYS_LAW_HH +#define DUMUX_DISCRETIZATION_BOX_DARCYS_LAW_HH + +#include + +#include + +#include +#include + +#include +#include + + +namespace Dumux +{ + +namespace Properties +{ +// forward declaration of properties +NEW_PROP_TAG(ProblemEnableGravity); +} + +/*! + * \ingroup DarcysLaw + * \brief Specialization of Darcy's Law for the box method. + */ +template +class DarcysLaw::type > +{ + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, SubControlVolume) SubControlVolume; + typedef typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace) SubControlVolumeFace; + typedef typename GET_PROP_TYPE(TypeTag, FluxVariablesCache) FluxVariablesCache; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + + typedef typename GridView::template Codim<0>::Entity Element; + typedef typename GridView::IndexSet::IndexType IndexType; + typedef typename GridView::ctype CoordScalar; + typedef std::vector Stencil; + + enum { dim = GridView::dimension} ; + enum { dimWorld = GridView::dimensionworld} ; + + typedef Dune::FieldMatrix DimWorldMatrix; + typedef Dune::FieldVector DimVector; + + typedef Dune::PQkLocalFiniteElementCache FeCache; + typedef typename FeCache::FiniteElementType::Traits::LocalBasisType FeLocalBasis; + typedef typename FluxVariablesCache::FaceData FaceData; + +public: + + static Scalar flux(const Problem& problem, + const Element& element, + const SubControlVolumeFace& scvFace, + const IndexType phaseIdx) + { + // get the precalculated local jacobian and shape values at the integration point + const auto& faceData = problem.model().fluxVarsCache()[scvFace].faceData(); + + const auto& fvGeometry = problem.model().fvGeometries(element); + const auto& insideScv = problem.model().fvGeometries().subControlVolume(scvFace.insideScvIdx()); + const auto extrusionFactor = problem.model().curVolVars(insideScv).extrusionFactor(); + const auto K = problem.spatialParams().intrinsicPermeability(insideScv); + + // evaluate gradP - rho*g at integration point + DimVector gradP(0.0); + for (const auto& scv : fvGeometry.scvs()) + { + // the global shape function gradient + DimVector gradI; + faceData.jacInvT.mv(faceData.localJacobian[scv.indexInElement()][0], gradI); + + gradI *= problem.model().curVolVars(scv).pressure(phaseIdx); + gradP += gradI; + } + if (GET_PARAM_FROM_GROUP(TypeTag, bool, Problem, EnableGravity)) + { + // gravitational acceleration + DimVector g(problem.gravityAtPos(scvFace.center())); + + // interpolate the density at the IP + const auto& insideVolVars = problem.model().curVolVars(insideScv); + const auto& outsideScv = problem.model().fvGeometries().subControlVolume(scvFace.outsideScvIdx()); + const auto& outsideVolVars = problem.model().curVolVars(outsideScv); + Scalar rho = 0.5*(insideVolVars.density(phaseIdx) + outsideVolVars.density(phaseIdx)); + + // turn gravity into a force + g *= rho; + + // subtract from pressure gradient + gradP -= g; + } + + // apply the permeability and return the flux + auto KGradP = applyPermeability(K, gradP); + return -1.0*(KGradP*scvFace.unitOuterNormal())*scvFace.area()*extrusionFactor; + } + + static DimVector applyPermeability(const DimWorldMatrix& K, const DimVector& gradI) + { + DimVector result(0.0); + K.mv(gradI, result); + + return result; + } + + static DimVector applyPermeability(const Scalar k, const DimVector& gradI) + { + DimVector result(gradI); + result *= k; + return result; + } + + // This is for compatibility with the cc methods. The flux stencil info is obsolete for the box method. + static Stencil stencil(const Problem& problem, const Element& element, const SubControlVolumeFace& scvFace) + { + return Stencil(0); + } + + static FaceData calculateFaceData(const Problem& problem, const Element& element, const typename Element::Geometry& geometry, const FeLocalBasis& localBasis, const SubControlVolumeFace& scvFace) + { + FaceData faceData; + + // evaluate shape functions and gradients at the integration point + const auto ipLocal = geometry.local(scvFace.center()); + faceData.jacInvT = geometry.jacobianInverseTransposed(ipLocal); + localBasis.evaluateJacobian(ipLocal, faceData.localJacobian); + localBasis.evaluateFunction(ipLocal, faceData.shapeValues); + + return std::move(faceData); + } +}; + +} // end namespace + +#endif diff --git a/dumux/discretization/box/fickslaw.hh b/dumux/discretization/box/fickslaw.hh new file mode 100644 index 0000000000..8406f61411 --- /dev/null +++ b/dumux/discretization/box/fickslaw.hh @@ -0,0 +1,179 @@ +// -*- 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 . * + *****************************************************************************/ +/*! + * \file + * \brief This file contains the data which is required to calculate + * diffusive mass fluxes due to molecular diffusion with Fick's law. + */ +#ifndef DUMUX_DISCRETIZATION_BOX_FICKS_LAW_HH +#define DUMUX_DISCRETIZATION_BOX_FICKS_LAW_HH + +#include + +#include +#include + +#include + + +namespace Dumux +{ + +namespace Properties +{ +// forward declaration of properties +NEW_PROP_TAG(NumPhases); +NEW_PROP_TAG(FluidSystem); +NEW_PROP_TAG(EffectiveDiffusivityModel); +} + +/*! + * \ingroup CCTpfaFicksLaw + * \brief Specialization of Fick's Law for the box method. + */ +template +class FicksLaw::type > +{ + 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, EffectiveDiffusivityModel) EffDiffModel; + typedef typename GET_PROP_TYPE(TypeTag, SubControlVolume) SubControlVolume; + typedef typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace) SubControlVolumeFace; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GridView::IndexSet::IndexType IndexType; + typedef typename std::vector Stencil; + + using Element = typename GridView::template Codim<0>::Entity; + + enum { dim = GridView::dimension} ; + enum { dimWorld = GridView::dimensionworld} ; + enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases)} ; + + typedef Dune::FieldMatrix DimWorldMatrix; + typedef Dune::FieldVector GlobalPosition; + +public: + + static Scalar flux(const Problem& problem, + const Element& element, + const SubControlVolumeFace& scvFace, + const int phaseIdx, + const int compIdx) + { + // diffusion tensors are always solution dependent + Scalar tij = calculateTransmissibility_(problem, scvFace, phaseIdx, compIdx); + + // Get the inside volume variables + const auto insideScvIdx = scvFace.insideScvIdx(); + const auto& insideScv = problem.model().fvGeometries().subControlVolume(insideScvIdx); + const auto& insideVolVars = problem.model().curVolVars(insideScv); + + // and the outside volume variables + const auto& outsideVolVars = problem.model().curVolVars(scvFace.outsideScvIdx()); + + // compute the diffusive flux + const auto xInside = insideVolVars.moleFraction(phaseIdx, compIdx); + const auto xOutside = outsideVolVars.moleFraction(phaseIdx, compIdx); + const auto rho = 0.5*(insideVolVars.molarDensity(phaseIdx) + outsideVolVars.molarDensity(phaseIdx)); + + return rho*tij*(xInside - xOutside); + } + + static Stencil stencil(const Problem& problem, const SubControlVolumeFace& scvFace) + { + std::vector stencil; + stencil.clear(); + if (!scvFace.boundary()) + { + stencil.push_back(scvFace.insideScvIdx()); + stencil.push_back(scvFace.outsideScvIdx()); + } + else + stencil.push_back(scvFace.insideScvIdx()); + + return stencil; + } + +private: + + + static Scalar calculateTransmissibility_(const Problem& problem, const SubControlVolumeFace& scvFace, const int phaseIdx, const int compIdx) + { + Scalar tij; + + const auto insideScvIdx = scvFace.insideScvIdx(); + const auto& insideScv = problem.model().fvGeometries().subControlVolume(insideScvIdx); + const auto& insideVolVars = problem.model().curVolVars(insideScvIdx); + + auto insideD = insideVolVars.diffusionCoefficient(phaseIdx, compIdx); + insideD = EffDiffModel::effectiveDiffusivity(insideVolVars.porosity(), insideVolVars.saturation(phaseIdx), insideD); + Scalar ti = calculateOmega_(problem, scvFace, insideD, insideScv); + + if (!scvFace.boundary()) + { + const auto outsideScvIdx = scvFace.outsideScvIdx(); + const auto& outsideScv = problem.model().fvGeometries().subControlVolume(outsideScvIdx); + const auto& outsideVolVars = problem.model().curVolVars(outsideScvIdx); + + auto outsideD = outsideVolVars.diffusionCoefficient(phaseIdx, compIdx); + outsideD = EffDiffModel::effectiveDiffusivity(outsideVolVars.porosity(), outsideVolVars.saturation(phaseIdx), outsideD); + Scalar tj = -1.0*calculateOmega_(problem, scvFace, outsideD, outsideScv); + + tij = scvFace.area()*(ti * tj)/(ti + tj); + } + else + { + tij = scvFace.area()*ti; + } + + return tij; + } + + static Scalar calculateOmega_(const Problem& problem, const SubControlVolumeFace& scvFace, const DimWorldMatrix &D, const SubControlVolume &scv) + { + GlobalPosition Dnormal; + D.mv(scvFace.unitOuterNormal(), Dnormal); + + auto distanceVector = scvFace.center(); + distanceVector -= scv.center(); + distanceVector /= distanceVector.two_norm2(); + + Scalar omega = Dnormal * distanceVector; + omega *= problem.model().curVolVars(scv).extrusionFactor(); + + return omega; + } + + static Scalar calculateOmega_(const Problem& problem, const SubControlVolumeFace& scvFace, Scalar D, const SubControlVolume &scv) + { + auto distanceVector = scvFace.center(); + distanceVector -= scv.center(); + distanceVector /= distanceVector.two_norm2(); + + Scalar omega = D * (distanceVector * scvFace.unitOuterNormal()); + omega *= problem.model().curVolVars(scv).extrusionFactor(); + + return omega; + } +}; + +} // end namespace + +#endif diff --git a/dumux/implicit/box/fluxvariablescachevector.hh b/dumux/discretization/box/fluxvariablescachevector.hh similarity index 98% rename from dumux/implicit/box/fluxvariablescachevector.hh rename to dumux/discretization/box/fluxvariablescachevector.hh index 1208662561..83e69beb5d 100644 --- a/dumux/implicit/box/fluxvariablescachevector.hh +++ b/dumux/discretization/box/fluxvariablescachevector.hh @@ -20,8 +20,8 @@ * \file * \brief Base class for the volume variables vector */ -#ifndef DUMUX_IMPLICIT_BOX_FLUXVARSCACHEVECTOR_HH -#define DUMUX_IMPLICIT_BOX_FLUXVARSCACHEVECTOR_HH +#ifndef DUMUX_DISCRETIZATION_BOX_FLUXVARSCACHEVECTOR_HH +#define DUMUX_DISCRETIZATION_BOX_FLUXVARSCACHEVECTOR_HH #include diff --git a/dumux/implicit/box/fvelementgeometryvector.hh b/dumux/discretization/box/fvelementgeometryvector.hh similarity index 99% rename from dumux/implicit/box/fvelementgeometryvector.hh rename to dumux/discretization/box/fvelementgeometryvector.hh index b2da799aca..48c11d229f 100644 --- a/dumux/implicit/box/fvelementgeometryvector.hh +++ b/dumux/discretization/box/fvelementgeometryvector.hh @@ -22,17 +22,14 @@ * This builds up the sub control volumes and sub control volume faces * for each element. */ -#ifndef DUMUX_IMPLICIT_BOX_FV_GEOMETRY_VECTOR_HH -#define DUMUX_IMPLICIT_BOX_FV_GEOMETRY_VECTOR_HH +#ifndef DUMUX_DISCRETIZATION_BOX_FV_GEOMETRY_VECTOR_HH +#define DUMUX_DISCRETIZATION_BOX_FV_GEOMETRY_VECTOR_HH #include #include #include #include -#include -#include -#include #include #include diff --git a/dumux/implicit/box/stencils.hh b/dumux/discretization/box/stencils.hh similarity index 98% rename from dumux/implicit/box/stencils.hh rename to dumux/discretization/box/stencils.hh index 3185f8a55f..8b67b95636 100644 --- a/dumux/implicit/box/stencils.hh +++ b/dumux/discretization/box/stencils.hh @@ -20,8 +20,8 @@ * \file * \brief Implements the notion of stencils for vertex-centered models */ -#ifndef DUMUX_BOX_STENCILS_HH -#define DUMUX_BOX_STENCILS_HH +#ifndef DUMUX_DISCRETIZATION_BOX_STENCILS_HH +#define DUMUX_DISCRETIZATION_BOX_STENCILS_HH #include #include diff --git a/dumux/discretization/box/subcontrolvolume.hh b/dumux/discretization/box/subcontrolvolume.hh new file mode 100644 index 0000000000..df886d74d3 --- /dev/null +++ b/dumux/discretization/box/subcontrolvolume.hh @@ -0,0 +1,84 @@ +// -*- 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 . * + *****************************************************************************/ +/*! + * \file + * \brief Base class for a sub control volume + */ +#ifndef DUMUX_DISCRETIZATION_BOX_SUBCONTROLVOLUME_HH +#define DUMUX_DISCRETIZATION_BOX_SUBCONTROLVOLUME_HH + +#include +#include + +namespace Dumux +{ +template +class BoxSubControlVolume : public SubControlVolumeBase +{ +public: + // exported types + using Geometry = G; + using IndexType = I; + +private: + using Scalar = typename Geometry::ctype; + enum { dimworld = Geometry::coorddimension }; + using GlobalPosition = Dune::FieldVector; + +public: + // the contructor in the box case + BoxSubControlVolume(Geometry geometry, + IndexType scvIdx, + IndexType elementIndex, + IndexType indexInElement, + IndexType dofIndex) + : SubControlVolumeBase(std::move(geometry), std::move(elementIndex)), + scvIdx_(scvIdx), indexInElement_(std::move(indexInElement)), + dofIndex_(std::move(dofIndex)) {} + + IndexType indexInElement() const + { + return indexInElement_; + } + + //! The global index of this scv + IndexType index() const + { + return scvIdx_; + } + + IndexType dofIndex() const + { + return dofIndex_; + } + + GlobalPosition dofPosition() const + { + return this->geometry().corner(indexInElement_); + } + +private: + IndexType scvIdx_; + IndexType indexInElement_; + IndexType dofIndex_; +}; + +} // end namespace + +#endif diff --git a/dumux/discretization/box/subcontrolvolumeface.hh b/dumux/discretization/box/subcontrolvolumeface.hh new file mode 100644 index 0000000000..b96d5085c5 --- /dev/null +++ b/dumux/discretization/box/subcontrolvolumeface.hh @@ -0,0 +1,61 @@ +// -*- 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 . * + *****************************************************************************/ +/*! + * \file + * \brief Base class for a sub control volume face + */ +#ifndef DUMUX_DISCRETIZATION_BOX_SUBCONTROLVOLUMEFACE_HH +#define DUMUX_DISCRETIZATION_BOX_SUBCONTROLVOLUMEFACE_HH + +#include +#include +#include + +namespace Dumux +{ + +/*! + * \ingroup Discretization + * \brief Class for a sub control volume face in the box method, i.e a part of the boundary + * of a sub control volume we compute fluxes on. We simply use the base class here. + */ +template +class BoxSubControlVolumeFace : public SubControlVolumeFaceBase +{ + using Scalar = typename Geometry::ctype; + static const int dim = Geometry::mydimension; + static const int dimworld = Geometry::coorddimension; + + using GlobalPosition = Dune::FieldVector; + using LocalPosition = Dune::FieldVector; + +public: + BoxSubControlVolumeFace(const Geometry& geometry, + const GlobalPosition& ipGlobal, + const GlobalPosition& unitOuterNormal, + IndexType scvfIndex, + IndexType indexInElement, + const std::vector& scvIndices, + bool boundary = false) + : SubControlVolumeFaceBase(geometry, ipGlobal, unitOuterNormal, scvfIndex, indexInElement, scvIndices, boundary) {} +}; + +} // end namespace + +#endif diff --git a/dumux/implicit/box/volumevariablesvector.hh b/dumux/discretization/box/volumevariablesvector.hh similarity index 99% rename from dumux/implicit/box/volumevariablesvector.hh rename to dumux/discretization/box/volumevariablesvector.hh index 0b97fdd5c6..4d5e15a686 100644 --- a/dumux/implicit/box/volumevariablesvector.hh +++ b/dumux/discretization/box/volumevariablesvector.hh @@ -20,8 +20,8 @@ * \file * \brief Base class for the volume variables vector */ -#ifndef DUMUX_IMPLICIT_BOX_VOLVARSVECTOR_HH -#define DUMUX_IMPLICIT_BOX_VOLVARSVECTOR_HH +#ifndef DUMUX_DISCRETIZATION_BOX_VOLVARSVECTOR_HH +#define DUMUX_DISCRETIZATION_BOX_VOLVARSVECTOR_HH #include diff --git a/dumux/discretization/cellcentered/CMakeLists.txt b/dumux/discretization/cellcentered/CMakeLists.txt new file mode 100644 index 0000000000..313cc2adfa --- /dev/null +++ b/dumux/discretization/cellcentered/CMakeLists.txt @@ -0,0 +1,7 @@ +add_subdirectory("tpfa") + +install(FILES +fluxvariablescachevector.hh +stencils.hh +volumevariablesvector.hh +DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dumux/discretization/cellcentered) \ No newline at end of file diff --git a/dumux/implicit/cellcentered/fluxvariablescachevector.hh b/dumux/discretization/cellcentered/fluxvariablescachevector.hh similarity index 98% rename from dumux/implicit/cellcentered/fluxvariablescachevector.hh rename to dumux/discretization/cellcentered/fluxvariablescachevector.hh index ffae3dbf96..13026e45e9 100644 --- a/dumux/implicit/cellcentered/fluxvariablescachevector.hh +++ b/dumux/discretization/cellcentered/fluxvariablescachevector.hh @@ -20,8 +20,8 @@ * \file * \brief Base class for the volume variables vector */ -#ifndef DUMUX_IMPLICIT_CC_FLUXVARSCACHEVECTOR_HH -#define DUMUX_IMPLICIT_CC_FLUXVARSCACHEVECTOR_HH +#ifndef DUMUX_DISCRETIZATION_CC_FLUXVARSCACHEVECTOR_HH +#define DUMUX_DISCRETIZATION_CC_FLUXVARSCACHEVECTOR_HH #include diff --git a/dumux/implicit/cellcentered/stencils.hh b/dumux/discretization/cellcentered/stencils.hh similarity index 98% rename from dumux/implicit/cellcentered/stencils.hh rename to dumux/discretization/cellcentered/stencils.hh index 34e156c31f..b5de5588ef 100644 --- a/dumux/implicit/cellcentered/stencils.hh +++ b/dumux/discretization/cellcentered/stencils.hh @@ -20,8 +20,8 @@ * \file * \brief Implements the notion of stencils for cell-centered models */ -#ifndef DUMUX_CC_STENCILS_HH -#define DUMUX_CC_STENCILS_HH +#ifndef DUMUX_DISCRETIZATION_CC_STENCILS_HH +#define DUMUX_DISCRETIZATION_CC_STENCILS_HH #include #include diff --git a/dumux/discretization/cellcentered/tpfa/CMakeLists.txt b/dumux/discretization/cellcentered/tpfa/CMakeLists.txt new file mode 100644 index 0000000000..ff7ebeb2ba --- /dev/null +++ b/dumux/discretization/cellcentered/tpfa/CMakeLists.txt @@ -0,0 +1,5 @@ +install(FILES +fvelementgeometryvector.hh +subcontrolvolumeface.hh +subcontrolvolume.hh +DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dumux/discretization/cellcentered/tpfa) \ No newline at end of file diff --git a/dumux/porousmediumflow/constitutivelaws/darcyslaw.hh b/dumux/discretization/cellcentered/tpfa/darcyslaw.hh similarity index 60% rename from dumux/porousmediumflow/constitutivelaws/darcyslaw.hh rename to dumux/discretization/cellcentered/tpfa/darcyslaw.hh index f5f6fb07fd..c24d224618 100644 --- a/dumux/porousmediumflow/constitutivelaws/darcyslaw.hh +++ b/dumux/discretization/cellcentered/tpfa/darcyslaw.hh @@ -22,8 +22,8 @@ * volume and mass fluxes of fluid phases over a face of a finite volume by means * of the Darcy approximation. Specializations are provided for the different discretization methods. */ -#ifndef DUMUX_POROUSMEDIUMFLOW_DARCYS_LAW_HH -#define DUMUX_POROUSMEDIUMFLOW_DARCYS_LAW_HH +#ifndef DUMUX_DISCRETIZATION_CC_TPFA_DARCYS_LAW_HH +#define DUMUX_DISCRETIZATION_CC_TPFA_DARCYS_LAW_HH #include @@ -47,15 +47,8 @@ NEW_PROP_TAG(ProblemEnableGravity); /*! * \ingroup DarcysLaw - * \brief Evaluates the normal component of the Darcy velocity - * on a (sub)control volume face. Specializations are provided - * for the different discretization methods. + * \brief Specialization of Darcy's Law for the CCTpfa method. */ -template -class DarcysLaw -{}; - -// Specialization for the CC-Tpfa method template class DarcysLaw::type > { @@ -198,116 +191,6 @@ private: } }; -// Specialization for the Box Method -template -class DarcysLaw::type > -{ - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, SubControlVolume) SubControlVolume; - typedef typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace) SubControlVolumeFace; - typedef typename GET_PROP_TYPE(TypeTag, FluxVariablesCache) FluxVariablesCache; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - - typedef typename GridView::template Codim<0>::Entity Element; - typedef typename GridView::IndexSet::IndexType IndexType; - typedef typename GridView::ctype CoordScalar; - typedef std::vector Stencil; - - enum { dim = GridView::dimension} ; - enum { dimWorld = GridView::dimensionworld} ; - - typedef Dune::FieldMatrix DimWorldMatrix; - typedef Dune::FieldVector DimVector; - - typedef Dune::PQkLocalFiniteElementCache FeCache; - typedef typename FeCache::FiniteElementType::Traits::LocalBasisType FeLocalBasis; - typedef typename FluxVariablesCache::FaceData FaceData; - -public: - - static Scalar flux(const Problem& problem, - const Element& element, - const SubControlVolumeFace& scvFace, - const IndexType phaseIdx) - { - // get the precalculated local jacobian and shape values at the integration point - const auto& faceData = problem.model().fluxVarsCache()[scvFace].faceData(); - - const auto& fvGeometry = problem.model().fvGeometries(element); - const auto& insideScv = problem.model().fvGeometries().subControlVolume(scvFace.insideScvIdx()); - const auto extrusionFactor = problem.model().curVolVars(insideScv).extrusionFactor(); - const auto K = problem.spatialParams().intrinsicPermeability(insideScv); - - // evaluate gradP - rho*g at integration point - DimVector gradP(0.0); - for (const auto& scv : fvGeometry.scvs()) - { - // the global shape function gradient - DimVector gradI; - faceData.jacInvT.mv(faceData.localJacobian[scv.indexInElement()][0], gradI); - - gradI *= problem.model().curVolVars(scv).pressure(phaseIdx); - gradP += gradI; - } - if (GET_PARAM_FROM_GROUP(TypeTag, bool, Problem, EnableGravity)) - { - // gravitational acceleration - DimVector g(problem.gravityAtPos(scvFace.center())); - - // interpolate the density at the IP - const auto& insideVolVars = problem.model().curVolVars(insideScv); - const auto& outsideScv = problem.model().fvGeometries().subControlVolume(scvFace.outsideScvIdx()); - const auto& outsideVolVars = problem.model().curVolVars(outsideScv); - Scalar rho = 0.5*(insideVolVars.density(phaseIdx) + outsideVolVars.density(phaseIdx)); - - // turn gravity into a force - g *= rho; - - // subtract from pressure gradient - gradP -= g; - } - - // apply the permeability and return the flux - auto KGradP = applyPermeability(K, gradP); - return -1.0*(KGradP*scvFace.unitOuterNormal())*scvFace.area()*extrusionFactor; - } - - static DimVector applyPermeability(const DimWorldMatrix& K, const DimVector& gradI) - { - DimVector result(0.0); - K.mv(gradI, result); - - return result; - } - - static DimVector applyPermeability(const Scalar k, const DimVector& gradI) - { - DimVector result(gradI); - result *= k; - return result; - } - - // This is for compatibility with the cc methods. The flux stencil info is obsolete for the box method. - static Stencil stencil(const Problem& problem, const Element& element, const SubControlVolumeFace& scvFace) - { - return Stencil(0); - } - - static FaceData calculateFaceData(const Problem& problem, const Element& element, const typename Element::Geometry& geometry, const FeLocalBasis& localBasis, const SubControlVolumeFace& scvFace) - { - FaceData faceData; - - // evaluate shape functions and gradients at the integration point - const auto ipLocal = geometry.local(scvFace.center()); - faceData.jacInvT = geometry.jacobianInverseTransposed(ipLocal); - localBasis.evaluateJacobian(ipLocal, faceData.localJacobian); - localBasis.evaluateFunction(ipLocal, faceData.shapeValues); - - return std::move(faceData); - } -}; - } // end namespace #endif diff --git a/dumux/discretization/cellcentered/tpfa/fickslaw.hh b/dumux/discretization/cellcentered/tpfa/fickslaw.hh new file mode 100644 index 0000000000..cddca62731 --- /dev/null +++ b/dumux/discretization/cellcentered/tpfa/fickslaw.hh @@ -0,0 +1,178 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *****************************************************************************/ +/*! + * \file + * \brief This file contains the data which is required to calculate + * diffusive mass fluxes due to molecular diffusion with Fick's law. + */ +#ifndef DUMUX_DISCRETIZATION_CC_TPFA_FICKS_LAW_HH +#define DUMUX_DISCRETIZATION_CC_TPFA_FICKS_LAW_HH + +#include + +#include +#include + +#include + + +namespace Dumux +{ + +namespace Properties +{ +// forward declaration of properties +NEW_PROP_TAG(NumPhases); +NEW_PROP_TAG(FluidSystem); +NEW_PROP_TAG(EffectiveDiffusivityModel); +} + +/*! + * \ingroup CCTpfaFicksLaw + * \brief Specialization of Fick's Law for the CCTpfa method. + */ +template +class FicksLaw::type > +{ + 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, EffectiveDiffusivityModel) EffDiffModel; + typedef typename GET_PROP_TYPE(TypeTag, SubControlVolume) SubControlVolume; + typedef typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace) SubControlVolumeFace; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GridView::IndexSet::IndexType IndexType; + typedef typename std::vector Stencil; + + using Element = typename GridView::template Codim<0>::Entity; + + enum { dim = GridView::dimension} ; + enum { dimWorld = GridView::dimensionworld} ; + enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases)} ; + + typedef Dune::FieldMatrix DimWorldMatrix; + typedef Dune::FieldVector GlobalPosition; + +public: + + static Scalar flux(const Problem& problem, + const Element& element, + const SubControlVolumeFace& scvFace, + const int phaseIdx, + const int compIdx) + { + // diffusion tensors are always solution dependent + Scalar tij = calculateTransmissibility_(problem, element, scvFace, phaseIdx, compIdx); + + // Get the inside volume variables + const auto insideScvIdx = scvFace.insideScvIdx(); + const auto& insideScv = problem.model().fvGeometries().subControlVolume(insideScvIdx); + const auto& insideVolVars = problem.model().curVolVars(insideScv); + + // and the outside volume variables + const auto& outsideVolVars = problem.model().curVolVars(scvFace.outsideScvIdx()); + + // compute the diffusive flux + const auto xInside = insideVolVars.moleFraction(phaseIdx, compIdx); + const auto xOutside = outsideVolVars.moleFraction(phaseIdx, compIdx); + const auto rho = 0.5*(insideVolVars.molarDensity(phaseIdx) + outsideVolVars.molarDensity(phaseIdx)); + + return rho*tij*(xInside - xOutside); + } + + static Stencil stencil(const Problem& problem, const Element& element, const SubControlVolumeFace& scvFace) + { + std::vector stencil; + stencil.clear(); + if (!scvFace.boundary()) + { + stencil.push_back(scvFace.insideScvIdx()); + stencil.push_back(scvFace.outsideScvIdx()); + } + else + stencil.push_back(scvFace.insideScvIdx()); + + return stencil; + } + +private: + + + static Scalar calculateTransmissibility_(const Problem& problem, const Element& element, const SubControlVolumeFace& scvFace, const int phaseIdx, const int compIdx) + { + Scalar tij; + + const auto insideScvIdx = scvFace.insideScvIdx(); + const auto& insideScv = problem.model().fvGeometries().subControlVolume(insideScvIdx); + const auto& insideVolVars = problem.model().curVolVars(insideScvIdx); + + auto insideD = insideVolVars.diffusionCoefficient(phaseIdx, compIdx); + insideD = EffDiffModel::effectiveDiffusivity(insideVolVars.porosity(), insideVolVars.saturation(phaseIdx), insideD); + Scalar ti = calculateOmega_(problem, element, scvFace, insideD, insideScv); + + if (!scvFace.boundary()) + { + const auto outsideScvIdx = scvFace.outsideScvIdx(); + const auto& outsideScv = problem.model().fvGeometries().subControlVolume(outsideScvIdx); + const auto& outsideVolVars = problem.model().curVolVars(outsideScvIdx); + + auto outsideD = outsideVolVars.diffusionCoefficient(phaseIdx, compIdx); + outsideD = EffDiffModel::effectiveDiffusivity(outsideVolVars.porosity(), outsideVolVars.saturation(phaseIdx), outsideD); + Scalar tj = -1.0*calculateOmega_(problem, element, scvFace, outsideD, outsideScv); + + tij = scvFace.area()*(ti * tj)/(ti + tj); + } + else + { + tij = scvFace.area()*ti; + } + + return tij; + } + + static Scalar calculateOmega_(const Problem& problem, const Element& element, const SubControlVolumeFace& scvFace, const DimWorldMatrix &D, const SubControlVolume &scv) + { + GlobalPosition Dnormal; + D.mv(scvFace.unitOuterNormal(), Dnormal); + + auto distanceVector = scvFace.center(); + distanceVector -= scv.center(); + distanceVector /= distanceVector.two_norm2(); + + Scalar omega = Dnormal * distanceVector; + omega *= problem.boxExtrusionFactor(element, scv); + + return omega; + } + + static Scalar calculateOmega_(const Problem& problem, const Element& element, const SubControlVolumeFace& scvFace, Scalar D, const SubControlVolume &scv) + { + auto distanceVector = scvFace.center(); + distanceVector -= scv.center(); + distanceVector /= distanceVector.two_norm2(); + + Scalar omega = D * (distanceVector * scvFace.unitOuterNormal()); + omega *= problem.boxExtrusionFactor(element, scv); + + return omega; + } +}; +} // end namespace + +#endif diff --git a/dumux/implicit/cellcentered/tpfa/fvelementgeometryvector.hh b/dumux/discretization/cellcentered/tpfa/fvelementgeometryvector.hh similarity index 93% rename from dumux/implicit/cellcentered/tpfa/fvelementgeometryvector.hh rename to dumux/discretization/cellcentered/tpfa/fvelementgeometryvector.hh index 1320104471..1a239b4e38 100644 --- a/dumux/implicit/cellcentered/tpfa/fvelementgeometryvector.hh +++ b/dumux/discretization/cellcentered/tpfa/fvelementgeometryvector.hh @@ -22,12 +22,10 @@ * This builds up the sub control volumes and sub control volume faces * for each element. */ -#ifndef DUMUX_IMPLICIT_TPFA_FV_GEOMETRY_VECTOR_HH -#define DUMUX_IMPLICIT_TPFA_FV_GEOMETRY_VECTOR_HH +#ifndef DUMUX_DISCRETIZATION_CCTPFA_FV_GEOMETRY_VECTOR_HH +#define DUMUX_DISCRETIZATION_CCTPFA_FV_GEOMETRY_VECTOR_HH -#include -#include -#include +#include #include namespace Dumux @@ -286,21 +284,21 @@ public: IndexType numLocalFaces = element.subEntities(1); std::vector scvfsIndexSet(numLocalFaces); std::vector neighborVolVarIndexSet(numLocalFaces); + IndexType localFaceIdx = 0; for (const auto& intersection : intersections(gridView_, element)) { - IndexType localFaceIdx = intersection.indexInInside(); // inner sub control volume faces if (intersection.neighbor()) { scvfsIndexSet[localFaceIdx] = numScvf_++; auto nIdx = problem.elementMapper().index(intersection.outside()); - neighborVolVarIndexSet[localFaceIdx] = nIdx; + neighborVolVarIndexSet[localFaceIdx++] = nIdx; } // boundary sub control volume faces else if (intersection.boundary()) { scvfsIndexSet[localFaceIdx] = numScvf_++; - neighborVolVarIndexSet[localFaceIdx] = numScvs_ + numBoundaryScvf_++; + neighborVolVarIndexSet[localFaceIdx++] = numScvs_ + numBoundaryScvf_++; } } @@ -361,12 +359,12 @@ private: if (intersection.neighbor() || intersection.boundary()) { localScvfs_.push_back(SubControlVolumeFace(intersection.geometry(), - intersection.geometry().center(), - intersection.centerUnitOuterNormal(), - scvFaceIndices[scvfCounter], - intersection.indexInInside(), - std::vector({eIdx, neighborVolVarIndices[scvfCounter]}), - intersection.boundary())); + intersection.geometry().center(), + intersection.centerUnitOuterNormal(), + scvFaceIndices[scvfCounter], + intersection.indexInInside(), + std::vector({eIdx, neighborVolVarIndices[scvfCounter]}), + intersection.boundary())); localScvfIndices_.push_back(scvFaceIndices[scvfCounter]); scvfCounter++; diff --git a/dumux/discretization/cellcentered/tpfa/subcontrolvolume.hh b/dumux/discretization/cellcentered/tpfa/subcontrolvolume.hh new file mode 100644 index 0000000000..aaba6ee555 --- /dev/null +++ b/dumux/discretization/cellcentered/tpfa/subcontrolvolume.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 . * + *****************************************************************************/ +/*! + * \file + * \brief Base class for a sub control volume + */ +#ifndef DUMUX_DISCRETIZATION_CC_TPFA_SUBCONTROLVOLUME_HH +#define DUMUX_DISCRETIZATION_CC_TPFA_SUBCONTROLVOLUME_HH + +#include +#include + +namespace Dumux +{ +template +class CCTpfaSubControlVolume : public SubControlVolumeBase +{ +public: + // exported types + using Geometry = G; + using IndexType = I; + +private: + using Scalar = typename Geometry::ctype; + enum { dimworld = Geometry::coorddimension }; + using GlobalPosition = Dune::FieldVector; + +public: + // the contructor in the cc case + CCTpfaSubControlVolume(Geometry geometry, + IndexType elementIndex) + : SubControlVolumeBase(std::move(geometry), std::move(elementIndex)) {} + + IndexType indexInElement() const + { + return IndexType(0); + } + + //! The global index of this scv + IndexType index() const + { + return this->elementIndex(); + } + + IndexType dofIndex() const + { + return this->elementIndex(); + } + + GlobalPosition dofPosition() const + { + return this->geometry().center(); + } +}; +} // end namespace + +#endif diff --git a/dumux/discretization/cellcentered/tpfa/subcontrolvolumeface.hh b/dumux/discretization/cellcentered/tpfa/subcontrolvolumeface.hh new file mode 100644 index 0000000000..9a3d763c5c --- /dev/null +++ b/dumux/discretization/cellcentered/tpfa/subcontrolvolumeface.hh @@ -0,0 +1,62 @@ +// -*- 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 . * + *****************************************************************************/ +/*! + * \file + * \brief Base class for a sub control volume face + */ +#ifndef DUMUX_DISCRETIZATION_CC_TPFA_SUBCONTROLVOLUMEFACE_HH +#define DUMUX_DISCRETIZATION_CC_TPFA_SUBCONTROLVOLUMEFACE_HH + +#include +#include +#include + +namespace Dumux +{ + +/*! + * \ingroup Discretization + * \brief Class for a sub control volume face in the box method, i.e a part of the boundary + * of a sub control volume we compute fluxes on. We simply use the base class here. + */ +template +class CCTpfaSubControlVolumeFace : public SubControlVolumeFaceBase +{ + using Scalar = typename Geometry::ctype; + static const int dim = Geometry::mydimension; + static const int dimworld = Geometry::coorddimension; + + using GlobalPosition = Dune::FieldVector; + using LocalPosition = Dune::FieldVector; + +public: + CCTpfaSubControlVolumeFace(const Geometry& geometry, + const GlobalPosition& ipGlobal, + const GlobalPosition& unitOuterNormal, + IndexType scvfIndex, + IndexType indexInElement, + const std::vector& scvIndices, + bool boundary = false) + : SubControlVolumeFaceBase(geometry, ipGlobal, unitOuterNormal, scvfIndex, indexInElement, scvIndices, boundary) + {} +}; + +} // end namespace + +#endif diff --git a/dumux/implicit/cellcentered/volumevariablesvector.hh b/dumux/discretization/cellcentered/volumevariablesvector.hh similarity index 99% rename from dumux/implicit/cellcentered/volumevariablesvector.hh rename to dumux/discretization/cellcentered/volumevariablesvector.hh index bac9996b57..85534726f1 100644 --- a/dumux/implicit/cellcentered/volumevariablesvector.hh +++ b/dumux/discretization/cellcentered/volumevariablesvector.hh @@ -20,8 +20,8 @@ * \file * \brief Base class for the volume variables vector */ -#ifndef DUMUX_IMPLICIT_CC_VOLVARSVECTOR_HH -#define DUMUX_IMPLICIT_CC_VOLVARSVECTOR_HH +#ifndef DUMUX_DISCRETIZATION_CC_VOLVARSVECTOR_HH +#define DUMUX_DISCRETIZATION_CC_VOLVARSVECTOR_HH #include diff --git a/dumux/discretization/darcyslaw.hh b/dumux/discretization/darcyslaw.hh new file mode 100644 index 0000000000..14e35ee628 --- /dev/null +++ b/dumux/discretization/darcyslaw.hh @@ -0,0 +1,47 @@ +// -*- 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 . * + *****************************************************************************/ +/*! + * \file + * \brief This file contains the data which is required to calculate + * volume and mass fluxes of fluid phases over a face of a finite volume by means + * of the Darcy approximation. Specializations are provided for the different discretization methods. + */ +#ifndef DUMUX_DISCRETIZATION_DARCYS_LAW_HH +#define DUMUX_DISCRETIZATION_DARCYS_LAW_HH + +namespace Dumux +{ + +/*! + * \ingroup DarcysLaw + * \brief Evaluates the normal component of the Darcy velocity + * on a (sub)control volume face. Specializations are provided + * for the different discretization methods. These specializations + * are found in the headers included below. + */ +template +class DarcysLaw +{}; + +} // end namespace + +#include +#include + +#endif diff --git a/dumux/discretization/fickslaw.hh b/dumux/discretization/fickslaw.hh new file mode 100644 index 0000000000..a1de3ebc2d --- /dev/null +++ b/dumux/discretization/fickslaw.hh @@ -0,0 +1,59 @@ +// -*- 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 . * + *****************************************************************************/ +/*! + * \file + * \brief This file contains the data which is required to calculate + * diffusive mass fluxes due to molecular diffusion with Fick's law. + */ +#ifndef DUMUX_DISCRETIZATION_FICKS_LAW_HH +#define DUMUX_DISCRETIZATION_FICKS_LAW_HH + +#include + +#include +#include + +#include + + +namespace Dumux +{ + +namespace Properties +{ +// forward declaration of properties +NEW_PROP_TAG(NumPhases); +NEW_PROP_TAG(FluidSystem); +NEW_PROP_TAG(EffectiveDiffusivityModel); +} + +/*! + * \ingroup CCTpfaFicksLaw + * \brief Evaluates the diffusive mass flux according to Fick's law + */ +template +class FicksLaw +{}; + +} // end namespace + +#include +#include + +#endif diff --git a/dumux/implicit/fluxvariablesbase.hh b/dumux/discretization/fluxvariablesbase.hh similarity index 97% rename from dumux/implicit/fluxvariablesbase.hh rename to dumux/discretization/fluxvariablesbase.hh index 6fe0a78696..de8061254d 100644 --- a/dumux/implicit/fluxvariablesbase.hh +++ b/dumux/discretization/fluxvariablesbase.hh @@ -20,8 +20,8 @@ * \file * \brief Base class for the flux variables */ -#ifndef DUMUX_IMPLICIT_FLUXVARIABLESBASE_HH -#define DUMUX_IMPLICIT_FLUXVARIABLESBASE_HH +#ifndef DUMUX_DISCRETIZATION_FLUXVARIABLESBASE_HH +#define DUMUX_DISCRETIZATION_FLUXVARIABLESBASE_HH #include @@ -29,7 +29,7 @@ namespace Dumux { /*! - * \ingroup ImplicitModel + * \ingroup Discretization * \brief Base class for the flux variables * Actual flux variables inherit from this class */ diff --git a/dumux/implicit/fvelementgeometry.hh b/dumux/discretization/fvelementgeometry.hh similarity index 97% rename from dumux/implicit/fvelementgeometry.hh rename to dumux/discretization/fvelementgeometry.hh index df59ef883b..b2b5cf8e9b 100644 --- a/dumux/implicit/fvelementgeometry.hh +++ b/dumux/discretization/fvelementgeometry.hh @@ -21,15 +21,12 @@ * \brief Class providing iterators over sub control volumes and sub control * volume faces of an element. */ -#ifndef DUMUX_FV_ELEMENTGEOMETRY_HH -#define DUMUX_FV_ELEMENTGEOMETRY_HH +#ifndef DUMUX_DISCRETIZATION_FV_ELEMENTGEOMETRY_HH +#define DUMUX_DISCRETIZATION_FV_ELEMENTGEOMETRY_HH #include #include -#include -#include - namespace Dumux { namespace Properties @@ -41,7 +38,7 @@ NEW_PROP_TAG(FVElementGeometryVector); } /*! - * \ingroup ImplcititModel + * \ingroup Discretization * \brief An iterator over sub control volumes */ template diff --git a/dumux/implicit/subcontrolvolume.hh b/dumux/discretization/subcontrolvolumebase.hh similarity index 100% rename from dumux/implicit/subcontrolvolume.hh rename to dumux/discretization/subcontrolvolumebase.hh diff --git a/dumux/implicit/subcontrolvolumeface.hh b/dumux/discretization/subcontrolvolumefacebase.hh similarity index 87% rename from dumux/implicit/subcontrolvolumeface.hh rename to dumux/discretization/subcontrolvolumefacebase.hh index f0f964e81d..ab732275d7 100644 --- a/dumux/implicit/subcontrolvolumeface.hh +++ b/dumux/discretization/subcontrolvolumefacebase.hh @@ -20,8 +20,8 @@ * \file * \brief Base class for a sub control volume face */ -#ifndef DUMUX_SUBCONTROLVOLUMEFACE_HH -#define DUMUX_SUBCONTROLVOLUMEFACE_HH +#ifndef DUMUX_DISCRETIZATION_SUBCONTROLVOLUMEFACEBASE_HH +#define DUMUX_DISCRETIZATION_SUBCONTROLVOLUMEFACEBASE_HH #include #include @@ -30,12 +30,12 @@ namespace Dumux { /*! - * \ingroup ImplicitModel + * \ingroup Discretization * \brief Base class for a sub control volume face, i.e a part of the boundary * of a sub control volume we computing a flux on. */ template -class SubControlVolumeFace +class SubControlVolumeFaceBase { using Scalar = typename Geometry::ctype; static const int dim = Geometry::mydimension; @@ -45,13 +45,13 @@ class SubControlVolumeFace using LocalPosition = Dune::FieldVector; public: - SubControlVolumeFace(const Geometry& geometry, - const GlobalPosition& ipGlobal, - const GlobalPosition& unitOuterNormal, - IndexType scvfIndex, - IndexType indexInElement, - const std::vector& scvIndices, - bool boundary = false) + SubControlVolumeFaceBase(const Geometry& geometry, + const GlobalPosition& ipGlobal, + const GlobalPosition& unitOuterNormal, + IndexType scvfIndex, + IndexType indexInElement, + const std::vector& scvIndices, + bool boundary = false) : geometry_(geometry), ipGlobal_(ipGlobal), ipLocal_(geometry.local(ipGlobal)), @@ -142,4 +142,5 @@ private: } // end namespace + #endif diff --git a/dumux/implicit/volumevariables.hh b/dumux/discretization/volumevariables.hh similarity index 97% rename from dumux/implicit/volumevariables.hh rename to dumux/discretization/volumevariables.hh index fe3b89b594..7acd2069a9 100644 --- a/dumux/implicit/volumevariables.hh +++ b/dumux/discretization/volumevariables.hh @@ -21,10 +21,10 @@ * \brief Base class for the model specific class which provides * access to all volume averaged quantities. */ -#ifndef DUMUX_IMPLICIT_VOLUME_VARIABLES_HH -#define DUMUX_IMPLICIT_VOLUME_VARIABLES_HH +#ifndef DUMUX_DISCRETIZATION_VOLUME_VARIABLES_HH +#define DUMUX_DISCRETIZATION_VOLUME_VARIABLES_HH -#include "properties.hh" +#include #include diff --git a/dumux/implicit/box/propertydefaults.hh b/dumux/implicit/box/propertydefaults.hh index f077377c63..05aae91d44 100644 --- a/dumux/implicit/box/propertydefaults.hh +++ b/dumux/implicit/box/propertydefaults.hh @@ -27,18 +27,20 @@ #define DUMUX_BOX_PROPERTY_DEFAULTS_HH #include -#include +#include +#include +#include +#include +#include +#include +#include #include -#include "fluxvariablescachevector.hh" -#include "volumevariablesvector.hh" #include "elementboundarytypes.hh" -#include "fvelementgeometryvector.hh" #include "localresidual.hh" #include "localjacobian.hh" #include "assembler.hh" #include "properties.hh" -#include "stencils.hh" namespace Dumux { @@ -69,7 +71,7 @@ private: using ScvGeometry = Dune::MultiLinearGeometry; using IndexType = typename GridView::IndexSet::IndexType; public: - typedef Dumux::SubControlVolume type; + typedef Dumux::BoxSubControlVolume type; }; SET_PROP(BoxModel, SubControlVolumeFace) @@ -82,7 +84,7 @@ private: using ScvfGeometry = Dune::MultiLinearGeometry; using IndexType = typename GridView::IndexSet::IndexType; public: - typedef Dumux::SubControlVolumeFace type; + typedef Dumux::BoxSubControlVolumeFace type; }; //! Set the default for the ElementBoundaryTypes diff --git a/dumux/implicit/cellcentered/propertydefaults.hh b/dumux/implicit/cellcentered/propertydefaults.hh index 1a7e56eb27..113aad3b18 100644 --- a/dumux/implicit/cellcentered/propertydefaults.hh +++ b/dumux/implicit/cellcentered/propertydefaults.hh @@ -28,13 +28,13 @@ #define DUMUX_CC_PROPERTY_DEFAULTS_HH #include +#include +#include +#include -#include "fluxvariablescachevector.hh" -#include "volumevariablesvector.hh" #include "elementboundarytypes.hh" #include "localresidual.hh" #include "properties.hh" -#include "stencils.hh" #include "localjacobian.hh" #include "assembler.hh" diff --git a/dumux/implicit/cellcentered/tpfa/propertydefaults.hh b/dumux/implicit/cellcentered/tpfa/propertydefaults.hh index 48af42db4d..cc904e2b56 100644 --- a/dumux/implicit/cellcentered/tpfa/propertydefaults.hh +++ b/dumux/implicit/cellcentered/tpfa/propertydefaults.hh @@ -28,9 +28,10 @@ #define DUMUX_CCTPFA_PROPERTY_DEFAULTS_HH #include -#include #include -#include +#include +#include +#include #include namespace Dumux { @@ -53,7 +54,7 @@ private: using ScvGeometry = typename Grid::template Codim<0>::Geometry; using IndexType = typename Grid::LeafGridView::IndexSet::IndexType; public: - typedef Dumux::SubControlVolume type; + typedef Dumux::CCTpfaSubControlVolume type; }; SET_PROP(CCTpfaModel, SubControlVolumeFace) @@ -63,7 +64,7 @@ private: using ScvfGeometry = typename Grid::template Codim<1>::Geometry; using IndexType = typename Grid::LeafGridView::IndexSet::IndexType; public: - typedef Dumux::SubControlVolumeFace type; + typedef Dumux::CCTpfaSubControlVolumeFace type; }; } // namespace Properties diff --git a/dumux/implicit/propertydefaults.hh b/dumux/implicit/propertydefaults.hh index 79a9cb04b2..76b1bb9e6f 100644 --- a/dumux/implicit/propertydefaults.hh +++ b/dumux/implicit/propertydefaults.hh @@ -38,15 +38,15 @@ #include #include -#include -#include +#include +#include +#include +#include #include "properties.hh" #include "model.hh" #include "assembler.hh" #include "localjacobian.hh" -#include "volumevariables.hh" -#include "fvelementgeometry.hh" namespace Dumux { diff --git a/dumux/porousmediumflow/1p/implicit/volumevariables.hh b/dumux/porousmediumflow/1p/implicit/volumevariables.hh index f834115929..d888b631cd 100644 --- a/dumux/porousmediumflow/1p/implicit/volumevariables.hh +++ b/dumux/porousmediumflow/1p/implicit/volumevariables.hh @@ -25,7 +25,7 @@ #define DUMUX_1P_VOLUME_VARIABLES_HH #include "properties.hh" -#include +#include #include diff --git a/dumux/porousmediumflow/2p/implicit/volumevariables.hh b/dumux/porousmediumflow/2p/implicit/volumevariables.hh index dde02a31a3..78731df5f3 100644 --- a/dumux/porousmediumflow/2p/implicit/volumevariables.hh +++ b/dumux/porousmediumflow/2p/implicit/volumevariables.hh @@ -27,7 +27,7 @@ #include "properties.hh" -#include +#include #include diff --git a/dumux/porousmediumflow/CMakeLists.txt b/dumux/porousmediumflow/CMakeLists.txt index d0f9ee759a..cd06f40100 100644 --- a/dumux/porousmediumflow/CMakeLists.txt +++ b/dumux/porousmediumflow/CMakeLists.txt @@ -10,10 +10,9 @@ add_subdirectory("3p") add_subdirectory("3p3c") add_subdirectory("co2") add_subdirectory("compositional") -add_subdirectory("constitutivelaws") add_subdirectory("immiscible") add_subdirectory("implicit") add_subdirectory("mpnc") add_subdirectory("nonisothermal") add_subdirectory("richards") -add_subdirectory("sequential") \ No newline at end of file +add_subdirectory("sequential") diff --git a/dumux/porousmediumflow/constitutivelaws/CMakeLists.txt b/dumux/porousmediumflow/constitutivelaws/CMakeLists.txt deleted file mode 100644 index e5e8f670be..0000000000 --- a/dumux/porousmediumflow/constitutivelaws/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -#install headers -install(FILES -darcyslaw.hh -fickslaw.hh -DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dumux/porousmediumflow/constitutivelaws) \ No newline at end of file diff --git a/dumux/porousmediumflow/constitutivelaws/fickslaw.hh b/dumux/porousmediumflow/constitutivelaws/fickslaw.hh deleted file mode 100644 index a1829d1898..0000000000 --- a/dumux/porousmediumflow/constitutivelaws/fickslaw.hh +++ /dev/null @@ -1,379 +0,0 @@ -// -*- 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 . * - *****************************************************************************/ -/*! - * \file - * \brief This file contains the data which is required to calculate - * diffusive mass fluxes due to molecular diffusion with Fick's law. - */ -#ifndef DUMUX_POROUSMEDIUMFLOW_FICKS_LAW_HH -#define DUMUX_POROUSMEDIUMFLOW_FICKS_LAW_HH - -#include - -#include -#include - -#include - - -namespace Dumux -{ - -namespace Properties -{ -// forward declaration of properties -NEW_PROP_TAG(NumPhases); -NEW_PROP_TAG(FluidSystem); -NEW_PROP_TAG(EffectiveDiffusivityModel); -} - -/*! - * \ingroup CCTpfaFicksLaw - * \brief Evaluates the diffusive mass flux according to Fick's law - */ -template -class FicksLaw -{}; - -// Specialization for the CC-Tpfa Method -template -class FicksLaw::type > -{ - 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, EffectiveDiffusivityModel) EffDiffModel; - typedef typename GET_PROP_TYPE(TypeTag, SubControlVolume) SubControlVolume; - typedef typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace) SubControlVolumeFace; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GridView::IndexSet::IndexType IndexType; - typedef typename std::vector Stencil; - - using Element = typename GridView::template Codim<0>::Entity; - - enum { dim = GridView::dimension} ; - enum { dimWorld = GridView::dimensionworld} ; - enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases)} ; - - typedef Dune::FieldMatrix DimWorldMatrix; - typedef Dune::FieldVector GlobalPosition; - -public: - - static Scalar flux(const Problem& problem, - const Element& element, - const SubControlVolumeFace& scvFace, - const int phaseIdx, - const int compIdx) - { - // diffusion tensors are always solution dependent - Scalar tij = calculateTransmissibility_(problem, scvFace, phaseIdx, compIdx); - - // Get the inside volume variables - const auto insideScvIdx = scvFace.insideScvIdx(); - const auto& insideScv = problem.model().fvGeometries().subControlVolume(insideScvIdx); - const auto& insideVolVars = problem.model().curVolVars(insideScv); - - // and the outside volume variables - const auto& outsideVolVars = problem.model().curVolVars(scvFace.outsideScvIdx()); - - // compute the diffusive flux - const auto xInside = insideVolVars.moleFraction(phaseIdx, compIdx); - const auto xOutside = outsideVolVars.moleFraction(phaseIdx, compIdx); - const auto rho = 0.5*(insideVolVars.molarDensity(phaseIdx) + outsideVolVars.molarDensity(phaseIdx)); - - return rho*tij*(xInside - xOutside); - } - - static Stencil stencil(const Problem& problem, const SubControlVolumeFace& scvFace) - { - std::vector stencil; - stencil.clear(); - if (!scvFace.boundary()) - { - stencil.push_back(scvFace.insideScvIdx()); - stencil.push_back(scvFace.outsideScvIdx()); - } - else - stencil.push_back(scvFace.insideScvIdx()); - - return stencil; - } - -private: - - - static Scalar calculateTransmissibility_(const Problem& problem, const SubControlVolumeFace& scvFace, const int phaseIdx, const int compIdx) - { - Scalar tij; - - const auto insideScvIdx = scvFace.insideScvIdx(); - const auto& insideScv = problem.model().fvGeometries().subControlVolume(insideScvIdx); - const auto& insideVolVars = problem.model().curVolVars(insideScvIdx); - - auto insideD = insideVolVars.diffusionCoefficient(phaseIdx, compIdx); - insideD = EffDiffModel::effectiveDiffusivity(insideVolVars.porosity(), insideVolVars.saturation(phaseIdx), insideD); - Scalar ti = calculateOmega_(problem, scvFace, insideD, insideScv); - - if (!scvFace.boundary()) - { - const auto outsideScvIdx = scvFace.outsideScvIdx(); - const auto& outsideScv = problem.model().fvGeometries().subControlVolume(outsideScvIdx); - const auto& outsideVolVars = problem.model().curVolVars(outsideScvIdx); - - auto outsideD = outsideVolVars.diffusionCoefficient(phaseIdx, compIdx); - outsideD = EffDiffModel::effectiveDiffusivity(outsideVolVars.porosity(), outsideVolVars.saturation(phaseIdx), outsideD); - Scalar tj = -1.0*calculateOmega_(problem, scvFace, outsideD, outsideScv); - - tij = scvFace.area()*(ti * tj)/(ti + tj); - } - else - { - tij = scvFace.area()*ti; - } - - return tij; - } - - static Scalar calculateOmega_(const Problem& problem, const SubControlVolumeFace& scvFace, const DimWorldMatrix &D, const SubControlVolume &scv) - { - GlobalPosition Dnormal; - D.mv(scvFace.unitOuterNormal(), Dnormal); - - auto distanceVector = scvFace.center(); - distanceVector -= scv.center(); - distanceVector /= distanceVector.two_norm2(); - - Scalar omega = Dnormal * distanceVector; - omega *= problem.model().curVolVars(scv).extrusionFactor(); - - return omega; - } - - static Scalar calculateOmega_(const Problem& problem, const SubControlVolumeFace& scvFace, Scalar D, const SubControlVolume &scv) - { - auto distanceVector = scvFace.center(); - distanceVector -= scv.center(); - distanceVector /= distanceVector.two_norm2(); - - Scalar omega = D * (distanceVector * scvFace.unitOuterNormal()); - omega *= problem.model().curVolVars(scv).extrusionFactor(); - - return omega; - } -}; - -// Specialization for the Box Method -template -class FicksLaw::type > -{ - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - using Problem = typename GET_PROP_TYPE(TypeTag, Problem); - using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem); - using EffDiffModel = typename GET_PROP_TYPE(TypeTag, EffectiveDiffusivityModel); - using SubControlVolume = typename GET_PROP_TYPE(TypeTag, SubControlVolume); - using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); - using VolumeVariables = typename GET_PROP_TYPE(TypeTag, VolumeVariables); - using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes); - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using IndexType = typename GridView::IndexSet::IndexType; - using Element = typename GridView::template Codim<0>::Entity; - - enum { dim = GridView::dimension} ; - enum { dimWorld = GridView::dimensionworld} ; - enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases)} ; - - using DimWorldMatrix = Dune::FieldMatrix; - using GlobalPosition = Dune::FieldVector; - -public: - - void update(const Problem &problem, - const Element& element, - const SubControlVolumeFace &scvFace, - int phaseIdx, int compIdx) - { - DUNE_THROW(Dune::NotImplemented, "Fick's law for the Box method is not yet implemented!"); - - problemPtr_ = &problem; - scvFacePtr_ = &scvFace; - - phaseIdx_ = phaseIdx; - compIdx_ = compIdx; - - updateStencil_(); - - // TODO for non solution dependent diffusion tensors... - } - - void update(const Problem &problem, const SubControlVolumeFace &scvFace, - int phaseIdx, int compIdx, - VolumeVariables* boundaryVolVars) - { - boundaryVolVars_ = boundaryVolVars; - update(problem, scvFace, phaseIdx, compIdx); - } - - void beginFluxComputation(bool boundaryVolVarsUpdated = false) - { - // diffusion tensors are always solution dependent - updateTransmissibilities_(); - - // Get the inside volume variables - const auto insideScvIdx = scvFace_().insideScvIdx(); - const auto& insideScv = problem_().model().fvGeometries().subControlVolume(insideScvIdx); - const auto* insideVolVars = &problem_().model().curVolVars(insideScv); - - // and the outside volume variables - const VolumeVariables* outsideVolVars; - if (!scvFace_().boundary()) - outsideVolVars = &problem_().model().curVolVars(scvFace_().outsideScvIdx()); - else - { - outsideVolVars = boundaryVolVars_; - if (!boundaryVolVarsUpdated) - { - // update the boudary volvars for Dirichlet boundaries - const auto element = problem_().model().fvGeometries().element(insideScv); - const auto dirichletPriVars = problem_().dirichlet(element, scvFace_()); - boundaryVolVars_->update(dirichletPriVars, problem_(), element, insideScv); - } - } - - // compute the diffusive flux - const auto xInside = insideVolVars->moleFraction(phaseIdx_, compIdx_); - const auto xOutside = outsideVolVars->moleFraction(phaseIdx_, compIdx_); - const auto rho = 0.5*(insideVolVars->molarDensity(phaseIdx_) + outsideVolVars->molarDensity(phaseIdx_)); - - rhoDGradXNormal_ = rho*tij_*(xInside - xOutside); - } - - - - /*! - * \brief A function to calculate the mass flux over a sub control volume face - * - * \param phaseIdx The index of the phase of which the flux is to be calculated - * \param compIdx The index of the transported component - */ - Scalar flux() const - { - return rhoDGradXNormal_; - } - - std::set stencil() const - { - return stencil_; - } - -protected: - - - void updateTransmissibilities_() - { - const auto insideScvIdx = scvFace_().insideScvIdx(); - const auto& insideScv = problem_().model().fvGeometries().subControlVolume(insideScvIdx); - const auto& insideVolVars = problem_().model().curVolVars(insideScvIdx); - - auto insideD = insideVolVars.diffusionCoefficient(phaseIdx_, compIdx_); - insideD = EffDiffModel::effectiveDiffusivity(insideVolVars.porosity(), insideVolVars.saturation(phaseIdx_), insideD); - Scalar ti = calculateOmega_(insideD, insideScv); - - if (!scvFace_().boundary()) - { - const auto outsideScvIdx = scvFace_().outsideScvIdx(); - const auto& outsideScv = problem_().model().fvGeometries().subControlVolume(outsideScvIdx); - const auto& outsideVolVars = problem_().model().curVolVars(outsideScvIdx); - - auto outsideD = outsideVolVars.diffusionCoefficient(phaseIdx_, compIdx_); - outsideD = EffDiffModel::effectiveDiffusivity(outsideVolVars.porosity(), outsideVolVars.saturation(phaseIdx_), outsideD); - Scalar tj = -1.0*calculateOmega_(outsideD, outsideScv); - - tij_ = scvFace_().area()*(ti * tj)/(ti + tj); - } - else - { - tij_ = scvFace_().area()*ti; - } - } - - void updateStencil_() - { - // fill the stencil - if (!scvFace_().boundary()) - stencil_= {scvFace_().insideScvIdx(), scvFace_().outsideScvIdx()}; - else - // fill the stencil - stencil_ = {scvFace_().insideScvIdx()}; - } - - Scalar calculateOmega_(const DimWorldMatrix &D, const SubControlVolume &scv) const - { - GlobalPosition Dnormal; - D.mv(scvFace_().unitOuterNormal(), Dnormal); - - auto distanceVector = scvFace_().center(); - distanceVector -= scv.center(); - distanceVector /= distanceVector.two_norm2(); - - Scalar omega = Dnormal * distanceVector; - omega *= problem_().model().curVolVars(scv).extrusionFactor(); - - return omega; - } - - Scalar calculateOmega_(Scalar D, const SubControlVolume &scv) const - { - auto distanceVector = scvFace_().center(); - distanceVector -= scv.center(); - distanceVector /= distanceVector.two_norm2(); - - Scalar omega = D * (distanceVector * scvFace_().unitOuterNormal()); - omega *= problem_().model().curVolVars(scv).extrusionFactor(); - - return omega; - } - - const Problem &problem_() const - { - return *problemPtr_; - } - - const SubControlVolumeFace& scvFace_() const - { - return *scvFacePtr_; - } - - const Problem *problemPtr_; - const SubControlVolumeFace *scvFacePtr_; //!< Pointer to the sub control volume face for which the flux variables are created - std::set stencil_; //!< Indices of the cells of which the pressure is needed for the flux calculation - - //! Boundary volume variables (they only get updated on Dirichlet boundaries) - VolumeVariables* boundaryVolVars_; - - IndexType phaseIdx_; - IndexType compIdx_; - //! Precomputed values - Scalar tij_; //!< transmissibility for the flux calculation - Scalar rhoDGradXNormal_; //! rho*D(grad(x))*n -}; - -} // end namespace - -#endif diff --git a/dumux/porousmediumflow/implicit/fluxvariables.hh b/dumux/porousmediumflow/implicit/fluxvariables.hh index 3038322ea0..a528cd9872 100644 --- a/dumux/porousmediumflow/implicit/fluxvariables.hh +++ b/dumux/porousmediumflow/implicit/fluxvariables.hh @@ -24,7 +24,7 @@ #define DUMUX_POROUSMEDIUMFLOW_IMPLICIT_FLUXVARIABLES_HH #include -#include +#include namespace Dumux { -- GitLab From 54964327f55ac58e38818a3ed7b61eac5d34f4ab Mon Sep 17 00:00:00 2001 From: DennisGlaeser Date: Tue, 5 Jul 2016 19:43:58 +0200 Subject: [PATCH 45/45] [discretization][fickslaw] remove unnecessary stuff --- dumux/discretization/fickslaw.hh | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/dumux/discretization/fickslaw.hh b/dumux/discretization/fickslaw.hh index a1de3ebc2d..91824def43 100644 --- a/dumux/discretization/fickslaw.hh +++ b/dumux/discretization/fickslaw.hh @@ -24,25 +24,8 @@ #ifndef DUMUX_DISCRETIZATION_FICKS_LAW_HH #define DUMUX_DISCRETIZATION_FICKS_LAW_HH -#include - -#include -#include - -#include - - namespace Dumux { - -namespace Properties -{ -// forward declaration of properties -NEW_PROP_TAG(NumPhases); -NEW_PROP_TAG(FluidSystem); -NEW_PROP_TAG(EffectiveDiffusivityModel); -} - /*! * \ingroup CCTpfaFicksLaw * \brief Evaluates the diffusive mass flux according to Fick's law -- GitLab