diff --git a/dumux/assembly/CMakeLists.txt b/dumux/assembly/CMakeLists.txt index f7ea8bb601bd42ca26054537cdfdf28f24bcaf70..c8210e26b71d2cb8abd48c67ee76b5e36395c934 100644 --- a/dumux/assembly/CMakeLists.txt +++ b/dumux/assembly/CMakeLists.txt @@ -6,7 +6,9 @@ cclocalassembler.hh cclocalresidual.hh diffmethod.hh fvassembler.hh +fvlocalassemblerbase.hh fvlocalresidual.hh +jacobianpattern.hh staggeredfvassembler.hh staggeredlocalassembler.hh staggeredlocalresidual.hh diff --git a/dumux/assembly/boxlocalassembler.hh b/dumux/assembly/boxlocalassembler.hh index 9487428f95ef5381fd0ae9118cd6f782b80f256e..9c9a3df0b383a9af57d7d4ad96b8513d05f70b7a 100644 --- a/dumux/assembly/boxlocalassembler.hh +++ b/dumux/assembly/boxlocalassembler.hh @@ -30,6 +30,7 @@ #include <dumux/common/properties.hh> #include <dumux/common/parameters.hh> +#include <dumux/common/numericdifferentiation.hh> #include <dumux/assembly/diffmethod.hh> #include <dumux/assembly/fvlocalassemblerbase.hh> @@ -205,6 +206,8 @@ class BoxLocalAssembler<TypeTag, Assembler, DiffMethod::numeric, /*implicit=*/tr using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables); using VolumeVariables = typename GET_PROP_TYPE(TypeTag, VolumeVariables); using JacobianMatrix = typename GET_PROP_TYPE(TypeTag, JacobianMatrix); + using LocalResidual = typename GET_PROP_TYPE(TypeTag, LocalResidual); + using ElementResidualVector = typename LocalResidual::ElementResidualVector; enum { numEq = GET_PROP_VALUE(TypeTag, NumEq) }; enum { dim = GET_PROP_TYPE(TypeTag, GridView)::dimension }; @@ -221,7 +224,7 @@ public: * * \return The element residual at the current solution. */ - auto assembleJacobianAndResidualImpl(JacobianMatrix& A, GridVariables& gridVariables) + ElementResidualVector assembleJacobianAndResidualImpl(JacobianMatrix& A, GridVariables& gridVariables) { // get some aliases for convenience const auto& element = this->element(); @@ -243,7 +246,7 @@ public: // create the element solution ElementSolutionVector elemSol(element, curSol, fvGeometry); - using ElementResidualVector = std::decay_t<decltype(origResiduals)>; + // create the vector storing the partial derivatives ElementResidualVector partialDerivs(element.subEntities(dim)); // calculation of the derivatives @@ -268,7 +271,8 @@ public: }; // derive the residuals numerically - NumericDifferentiation::partialDerivative(evalResiduals, elemSol[scv.indexInElement()][pvIdx], partialDerivs, origResiduals); + static const int numDiffMethod = getParamFromGroup<int>(GET_PROP_VALUE(TypeTag, ModelParameterGroup), "Assembly.NumericDifferenceMethod"); + NumericDifferentiation::partialDerivative(evalResiduals, elemSol[scv.indexInElement()][pvIdx], partialDerivs, origResiduals, numDiffMethod); // update the global stiffness matrix with the current partial derivatives for (auto&& scvJ : scvs(fvGeometry)) @@ -313,6 +317,8 @@ class BoxLocalAssembler<TypeTag, Assembler, DiffMethod::numeric, /*implicit=*/fa using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables); using VolumeVariables = typename GET_PROP_TYPE(TypeTag, VolumeVariables); using JacobianMatrix = typename GET_PROP_TYPE(TypeTag, JacobianMatrix); + using LocalResidual = typename GET_PROP_TYPE(TypeTag, LocalResidual); + using ElementResidualVector = typename LocalResidual::ElementResidualVector; enum { numEq = GET_PROP_VALUE(TypeTag, NumEq) }; enum { dim = GET_PROP_TYPE(TypeTag, GridView)::dimension }; @@ -327,7 +333,7 @@ public: * * \return The element residual at the current solution. */ - auto assembleJacobianAndResidualImpl(JacobianMatrix& A, GridVariables& gridVariables) + ElementResidualVector assembleJacobianAndResidualImpl(JacobianMatrix& A, GridVariables& gridVariables) { // get some aliases for convenience const auto& element = this->element(); @@ -349,7 +355,7 @@ public: // create the element solution ElementSolutionVector elemSol(element, curSol, fvGeometry); - using ElementResidualVector = std::decay_t<decltype(origResiduals)>; + // create the vector storing the partial derivatives ElementResidualVector partialDerivs(element.subEntities(dim)); // calculation of the derivatives @@ -374,7 +380,8 @@ public: }; // derive the residuals numerically - NumericDifferentiation::partialDerivative(evalStorage, elemSol[scv.indexInElement()][pvIdx], partialDerivs, origResiduals); + static const int numDiffMethod = getParamFromGroup<int>(GET_PROP_VALUE(TypeTag, ModelParameterGroup), "Assembly.NumericDifferenceMethod"); + NumericDifferentiation::partialDerivative(evalStorage, elemSol[scv.indexInElement()][pvIdx], partialDerivs, origResiduals, numDiffMethod); // update the global stiffness matrix with the current partial derivatives for (int eqIdx = 0; eqIdx < numEq; eqIdx++) @@ -412,6 +419,8 @@ class BoxLocalAssembler<TypeTag, Assembler, DiffMethod::analytic, /*implicit=*/t using ParentType = BoxLocalAssemblerBase<TypeTag, Assembler, ThisType, true>; using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables); using JacobianMatrix = typename GET_PROP_TYPE(TypeTag, JacobianMatrix); + using LocalResidual = typename GET_PROP_TYPE(TypeTag, LocalResidual); + using ElementResidualVector = typename LocalResidual::ElementResidualVector; public: @@ -423,7 +432,7 @@ public: * * \return The element residual at the current solution. */ - auto assembleJacobianAndResidualImpl(JacobianMatrix& A, GridVariables& gridVariables) + ElementResidualVector assembleJacobianAndResidualImpl(JacobianMatrix& A, GridVariables& gridVariables) { // get some aliases for convenience const auto& element = this->element(); @@ -524,6 +533,8 @@ class BoxLocalAssembler<TypeTag, Assembler, DiffMethod::analytic, /*implicit=*/f using ParentType = BoxLocalAssemblerBase<TypeTag, Assembler, ThisType, false>; using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables); using JacobianMatrix = typename GET_PROP_TYPE(TypeTag, JacobianMatrix); + using LocalResidual = typename GET_PROP_TYPE(TypeTag, LocalResidual); + using ElementResidualVector = typename LocalResidual::ElementResidualVector; public: @@ -535,7 +546,7 @@ public: * * \return The element residual at the current solution. */ - auto assembleJacobianAndResidualImpl(JacobianMatrix& A, GridVariables& gridVariables) + ElementResidualVector assembleJacobianAndResidualImpl(JacobianMatrix& A, GridVariables& gridVariables) { // get some aliases for convenience const auto& element = this->element(); diff --git a/dumux/assembly/cclocalassembler.hh b/dumux/assembly/cclocalassembler.hh index 00d9c51e2d82bf7b0d11df075241cce916f99710..49774a6c97302b5086ad947d1576bc762bc3294e 100644 --- a/dumux/assembly/cclocalassembler.hh +++ b/dumux/assembly/cclocalassembler.hh @@ -32,8 +32,8 @@ #include <dumux/common/reservedblockvector.hh> #include <dumux/common/properties.hh> #include <dumux/common/parameters.hh> +#include <dumux/common/numericdifferentiation.hh> #include <dumux/assembly/diffmethod.hh> -#include <dumux/assembly/numericdifferentiation.hh> #include <dumux/assembly/fvlocalassemblerbase.hh> #include <dumux/discretization/fluxstencil.hh> @@ -245,7 +245,8 @@ public: }; // derive the residuals numerically - NumericDifferentiation::partialDerivative(evalResiduals, elemSol[0][pvIdx], partialDerivs, origResiduals); + static const int numDiffMethod = getParamFromGroup<int>(GET_PROP_VALUE(TypeTag, ModelParameterGroup), "Assembly.NumericDifferenceMethod"); + NumericDifferentiation::partialDerivative(evalResiduals, elemSol[0][pvIdx], partialDerivs, origResiduals, numDiffMethod); // add the current partial derivatives to the global jacobian matrix for (int eqIdx = 0; eqIdx < numEq; eqIdx++) @@ -363,7 +364,10 @@ public: // for non-ghosts compute the derivative numerically if (!this->elementIsGhost()) - NumericDifferentiation::partialDerivative(evalStorage, elemSol[0][pvIdx], partialDeriv, residual); + { + static const int numDiffMethod = getParamFromGroup<int>(GET_PROP_VALUE(TypeTag, ModelParameterGroup), "Assembly.NumericDifferenceMethod"); + NumericDifferentiation::partialDerivative(evalStorage, elemSol[0][pvIdx], partialDeriv, residual, numDiffMethod); + } // for ghost elements we assemble a 1.0 where the primary variable and zero everywhere else // as we always solve for a delta of the solution with repect to the initial solution this diff --git a/dumux/assembly/fvassembler.hh b/dumux/assembly/fvassembler.hh index 4310071b2a7d97005dc21e045ac3cd38a330c8a6..abeeb48e597ae5335e52e7f881cee5f92451dfa3 100644 --- a/dumux/assembly/fvassembler.hh +++ b/dumux/assembly/fvassembler.hh @@ -33,6 +33,7 @@ #include <dumux/discretization/methods.hh> #include <dumux/parallel/vertexhandles.hh> +#include "jacobianpattern.hh" #include "diffmethod.hh" #include "boxlocalassembler.hh" #include "cclocalassembler.hh" @@ -227,11 +228,7 @@ public: jacobian_->setSize(numDofs, numDofs); // create occupation pattern of the jacobian - Dune::MatrixIndexSet occupationPattern; - occupationPattern.resize(numDofs, numDofs); - - // set the jacobian pattern depending on space and time discretization - setJacobianPattern_(occupationPattern, numDofs); + const auto occupationPattern = getJacobianPattern<isImplicit>(fvGridGeometry()); // export pattern to jacobian occupationPattern.exportIdx(*jacobian_); @@ -336,65 +333,6 @@ private: DUNE_THROW(Dune::InvalidStateException, "Assembling instationary problem but previous solution was not set!"); } - //! Implicit jacobian pattern for cell-centered fv schemes - template<class T = TypeTag, typename std::enable_if_t<GET_PROP_VALUE(T, DiscretizationMethod) != DiscretizationMethods::Box, int> = 0> - void setJacobianPattern_(Dune::MatrixIndexSet& pattern, std::size_t numDofs) - { - // matrix pattern for implicit Jacobians - if (isImplicit) - { - for (unsigned int globalI = 0; globalI < numDofs; ++globalI) - { - pattern.add(globalI, globalI); - for (const auto& dataJ : fvGridGeometry().connectivityMap()[globalI]) - pattern.add(dataJ.globalJ, globalI); - - // reserve index for additional user defined DOF dependencies - // const auto& additionalDofDependencies = problem().getAdditionalDofDependencies(globalI); - // for (auto globalJ : additionalDofDependencies) - // pattern.add(globalI, globalJ); - } - } - - // matrix pattern for explicit Jacobians -> diagonal matrix - else - { - for (unsigned int globalI = 0; globalI < numDofs; ++globalI) - pattern.add(globalI, globalI); - } - } - - //! Implicit jacobian pattern for vertex-centered fv schemes - template<class T = TypeTag, typename std::enable_if_t<GET_PROP_VALUE(T, DiscretizationMethod) == DiscretizationMethods::Box, int> = 0> - void setJacobianPattern_(Dune::MatrixIndexSet& pattern, std::size_t numDofs) - { - // matrix pattern for implicit Jacobians - if (isImplicit) - { - static constexpr int dim = GridView::dimension; - for (const auto& element : elements(fvGridGeometry().gridView())) - { - for (unsigned int vIdx = 0; vIdx < element.subEntities(dim); ++vIdx) - { - const auto globalI = fvGridGeometry().vertexMapper().subIndex(element, vIdx, dim); - for (unsigned int vIdx2 = vIdx; vIdx2 < element.subEntities(dim); ++vIdx2) - { - const auto globalJ = fvGridGeometry().vertexMapper().subIndex(element, vIdx2, dim); - pattern.add(globalI, globalJ); - pattern.add(globalJ, globalI); - } - } - } - } - - // matrix pattern for explicit Jacobians -> diagonal matrix - else - { - for (unsigned int globalI = 0; globalI < numDofs; ++globalI) - pattern.add(globalI, globalI); - } - } - /*! * \brief A method assembling something per element * \note Handles exceptions for parallel runs diff --git a/dumux/assembly/fvlocalassemblerbase.hh b/dumux/assembly/fvlocalassemblerbase.hh index dbae670f0b5ca590c0bb6867d820e56afccde073..7758e8af9b06a12c8e160bb2f2422d474d6ea149 100644 --- a/dumux/assembly/fvlocalassemblerbase.hh +++ b/dumux/assembly/fvlocalassemblerbase.hh @@ -32,7 +32,6 @@ #include <dumux/common/properties.hh> #include <dumux/common/parameters.hh> #include <dumux/assembly/diffmethod.hh> -#include <dumux/assembly/numericdifferentiation.hh> namespace Dumux { @@ -41,13 +40,14 @@ namespace Dumux { * \brief A base class for all local assemblers * \tparam TypeTag The TypeTag * \tparam Assembler The assembler type - * \tparam implicit Specifies whether the time discretization is implicit or not not (i.e. explicit) + * \tparam isImplicit Specifies whether the time discretization is implicit or not not (i.e. explicit) */ -template<class TypeTag, class Assembler, class Implementation, bool implicit> +template<class TypeTag, class Assembler, class Implementation, bool isImplicit> class FVLocalAssemblerBase { using Problem = typename GET_PROP_TYPE(TypeTag, Problem); using LocalResidual = typename GET_PROP_TYPE(TypeTag, LocalResidual); + using ElementResidualVector = typename LocalResidual::ElementResidualVector; using GridView = typename GET_PROP_TYPE(TypeTag, GridView); using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); using JacobianMatrix = typename GET_PROP_TYPE(TypeTag, JacobianMatrix); @@ -86,30 +86,28 @@ public: * \brief Convenience function to evaluate the complete local residual for the current element. Automatically chooses the the appropriate * element volume variables. */ - auto evalLocalResidual() const + ElementResidualVector evalLocalResidual() const { - if(this->assembler().isStationaryProblem() && !isImplicit()) - DUNE_THROW(Dune::InvalidStateException, "Using explicit jacobian assembler with stationary local residual"); + if (!isImplicit) + if (this->assembler().isStationaryProblem()) + DUNE_THROW(Dune::InvalidStateException, "Using explicit jacobian assembler with stationary local residual"); - if(elementIsGhost()) - { - using ResdiualType = decltype(evalLocalResidual(std::declval<ElementVolumeVariables>())); - return ResdiualType(0.0); - } + if (elementIsGhost()) + return ElementResidualVector(0.0); - return isImplicit() ? evalLocalResidual(curElemVolVars()) - : evalLocalResidual(prevElemVolVars()); + return isImplicit ? evalLocalResidual(curElemVolVars()) + : evalLocalResidual(prevElemVolVars()); } /*! * \brief Evaluates the complete local residual for the current element. * \param elemVolVars The element volume variables */ - auto evalLocalResidual(const ElementVolumeVariables& elemVolVars) const + ElementResidualVector evalLocalResidual(const ElementVolumeVariables& elemVolVars) const { if (!assembler().isStationaryProblem()) { - auto residual = evalLocalFluxAndSourceResidual(elemVolVars); + ElementResidualVector residual = evalLocalFluxAndSourceResidual(elemVolVars); residual += evalLocalStorageResidual(); return residual; } @@ -122,10 +120,10 @@ public: * of the local residual for the current element. Automatically chooses the the appropriate * element volume variables. */ - auto evalLocalFluxAndSourceResidual() const + ElementResidualVector evalLocalFluxAndSourceResidual() const { - return isImplicit() ? evalLocalFluxAndSourceResidual(curElemVolVars()) - : evalLocalFluxAndSourceResidual(prevElemVolVars()); + return isImplicit ? evalLocalFluxAndSourceResidual(curElemVolVars()) + : evalLocalFluxAndSourceResidual(prevElemVolVars()); } /*! @@ -134,9 +132,9 @@ public: * * \param elemVolVars The element volume variables */ - auto evalLocalFluxAndSourceResidual(const ElementVolumeVariables& elemVolVars) const + ElementResidualVector evalLocalFluxAndSourceResidual(const ElementVolumeVariables& elemVolVars) const { - return localResidual_.evalFluxSource(element_, fvGeometry_, elemVolVars, elemFluxVarsCache_, elemBcTypes_); + return localResidual_.evalFluxAndSource(element_, fvGeometry_, elemVolVars, elemFluxVarsCache_, elemBcTypes_); } /*! @@ -144,7 +142,7 @@ public: * of the local residual for the current element. Automatically chooses the the appropriate * element volume variables. */ - auto evalLocalStorageResidual() const + ElementResidualVector evalLocalStorageResidual() const { return localResidual_.evalStorage(element_, fvGeometry_, prevElemVolVars_, curElemVolVars_); } @@ -167,7 +165,7 @@ public: // bind the caches fvGeometry.bind(element); - if(isImplicit()) + if (isImplicit) { curElemVolVars.bind(element, fvGeometry, curSol); elemFluxVarsCache.bind(element, fvGeometry, curElemVolVars); @@ -250,9 +248,6 @@ public: const LocalResidual& localResidual() const { return localResidual_; } - constexpr bool isImplicit() const - { return implicit; } - protected: Implementation &asImp_() { return *static_cast<Implementation*>(this); } diff --git a/dumux/assembly/fvlocalresidual.hh b/dumux/assembly/fvlocalresidual.hh index 3e06c94d388f9e506e94027724775678c5d5f0d1..a26e90e227ffbccf9e57a3481c359aa802629e12 100644 --- a/dumux/assembly/fvlocalresidual.hh +++ b/dumux/assembly/fvlocalresidual.hh @@ -144,7 +144,7 @@ public: * \param bcTypes The types of the boundary conditions for all boundary entities of an element * \param elemFluxVarsCache The flux variable caches for the element stencil */ - DUNE_DEPRECATED_MSG("eval is deprecated because it doesn't allow to specify on which time level to evaluate. Use evalFluxSource, and evalStorage instead!") + DUNE_DEPRECATED_MSG("eval is deprecated because it doesn't allow to specify on which time level to evaluate. Use evalFluxAndSource, and evalStorage instead!") ElementResidualVector eval(const Problem& problem, const Element& element, const FVElementGeometry& fvGeometry, @@ -219,7 +219,7 @@ public: * \param bcTypes The types of the boundary conditions for all boundary entities of an element * \param elemFluxVarsCache The flux variable caches for the element stencil */ - DUNE_DEPRECATED_MSG("Use evalFluxSource instead!") + DUNE_DEPRECATED_MSG("Use evalFluxAndSource instead!") ElementResidualVector eval(const Problem& problem, const Element& element, const FVElementGeometry& fvGeometry, @@ -227,14 +227,14 @@ public: const ElementBoundaryTypes &bcTypes, const ElementFluxVariablesCache& elemFluxVarsCache) const { - return evalFluxSource(element, fvGeometry, curElemVolVars, elemFluxVarsCache, bcTypes); + return evalFluxAndSource(element, fvGeometry, curElemVolVars, elemFluxVarsCache, bcTypes); } - ElementResidualVector evalFluxSource(const Element& element, - const FVElementGeometry& fvGeometry, - const ElementVolumeVariables& elemVolVars, - const ElementFluxVariablesCache& elemFluxVarsCache, - const ElementBoundaryTypes &bcTypes) const + ElementResidualVector evalFluxAndSource(const Element& element, + const FVElementGeometry& fvGeometry, + const ElementVolumeVariables& elemVolVars, + const ElementFluxVariablesCache& elemFluxVarsCache, + const ElementBoundaryTypes &bcTypes) const { // initialize the residual vector for all scvs in this element ElementResidualVector residual(fvGeometry.numScv()); diff --git a/dumux/assembly/jacobianpattern.hh b/dumux/assembly/jacobianpattern.hh new file mode 100644 index 0000000000000000000000000000000000000000..1847c116213aafef95713ded2028032301323ec7 --- /dev/null +++ b/dumux/assembly/jacobianpattern.hh @@ -0,0 +1,110 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \file + * \ingroup Assembly + * \brief Helper function to generate Jacobian pattern for different discretization methods + */ +#ifndef DUMUX_JACOBIAN_PATTERN_HH +#define DUMUX_JACOBIAN_PATTERN_HH + +#include <type_traits> +#include <dune/istl/matrixindexset.hh> +#include <dumux/discretization/methods.hh> + +namespace Dumux { + +/*! + * \ingroup Assembly + * \brief Helper function to generate Jacobian pattern for the box method + */ +template<bool isImplicit, class GridGeometry, + typename std::enable_if_t<(GridGeometry::discretizationMethod == DiscretizationMethods::Box), int> = 0> +Dune::MatrixIndexSet getJacobianPattern(const GridGeometry& gridGeometry) +{ + const auto numDofs = gridGeometry.numDofs(); + Dune::MatrixIndexSet pattern; + pattern.resize(numDofs, numDofs); + + // matrix pattern for implicit Jacobians + if (isImplicit) + { + static constexpr int dim = std::decay_t<decltype(gridGeometry.gridView())>::dimension; + for (const auto& element : elements(gridGeometry.gridView())) + { + for (unsigned int vIdx = 0; vIdx < element.subEntities(dim); ++vIdx) + { + const auto globalI = gridGeometry.vertexMapper().subIndex(element, vIdx, dim); + for (unsigned int vIdx2 = vIdx; vIdx2 < element.subEntities(dim); ++vIdx2) + { + const auto globalJ = gridGeometry.vertexMapper().subIndex(element, vIdx2, dim); + pattern.add(globalI, globalJ); + pattern.add(globalJ, globalI); + } + } + } + } + + // matrix pattern for explicit Jacobians -> diagonal matrix + else + { + for (unsigned int globalI = 0; globalI < numDofs; ++globalI) + pattern.add(globalI, globalI); + } + + return pattern; +} + +/*! + * \ingroup Assembly + * \brief Helper function to generate Jacobian pattern for cell-centered methods + */ +template<bool isImplicit, class GridGeometry, + typename std::enable_if_t<( (GridGeometry::discretizationMethod == DiscretizationMethods::CCTpfa) + || (GridGeometry::discretizationMethod == DiscretizationMethods::CCMpfa) ), int> = 0> +Dune::MatrixIndexSet getJacobianPattern(const GridGeometry& gridGeometry) +{ + const auto numDofs = gridGeometry.numDofs(); + Dune::MatrixIndexSet pattern; + pattern.resize(numDofs, numDofs); + + // matrix pattern for implicit Jacobians + if (isImplicit) + { + for (unsigned int globalI = 0; globalI < numDofs; ++globalI) + { + pattern.add(globalI, globalI); + for (const auto& dataJ : gridGeometry.connectivityMap()[globalI]) + pattern.add(dataJ.globalJ, globalI); + } + } + + // matrix pattern for explicit Jacobians -> diagonal matrix + else + { + for (unsigned int globalI = 0; globalI < numDofs; ++globalI) + pattern.add(globalI, globalI); + } + + return pattern; +} + +} // namespace Dumux + +#endif diff --git a/dumux/common/CMakeLists.txt b/dumux/common/CMakeLists.txt index 445c4932df251ead8bd512527abc8b4a9c52093c..8addc554443d474c48b85f7377b9512f369fb8fd 100644 --- a/dumux/common/CMakeLists.txt +++ b/dumux/common/CMakeLists.txt @@ -22,6 +22,7 @@ loggingparametertree.hh math.hh matrixvectorhelper.hh optional.hh +numericdifferentiation.hh parameters.hh pointsource.hh properties.hh diff --git a/dumux/assembly/numericdifferentiation.hh b/dumux/common/numericdifferentiation.hh similarity index 91% rename from dumux/assembly/numericdifferentiation.hh rename to dumux/common/numericdifferentiation.hh index cdf0ee3f1bb810e5a3d1d4f0196e2baad6c87332..fdc34ffa6b3c81e5f1ab4fd1e5e74018adc66531 100644 --- a/dumux/assembly/numericdifferentiation.hh +++ b/dumux/common/numericdifferentiation.hh @@ -27,7 +27,6 @@ #include <cmath> #include <limits> -#include <dumux/common/parameters.hh> namespace Dumux { @@ -61,8 +60,9 @@ public: template<class Function, class Scalar, class FunctionEvalType> static void partialDerivative(const Function& function, Scalar x0, FunctionEvalType& derivative, - const FunctionEvalType& fx0) - { partialDerivative(function, x0, derivative, fx0, epsilon(x0)); } + const FunctionEvalType& fx0, + const int numericDifferenceMethod = 1) + { partialDerivative(function, x0, derivative, fx0, epsilon(x0), numericDifferenceMethod); } /*! * \brief Computes the derivative of a function with repect to a function parameter @@ -71,15 +71,16 @@ public: * \param derivative The partial derivative (output) * \param fx0 The result of the function evaluated at x0 * \param eps The numeric epsilon used in the differentiation + * \param numericDifferenceMethod The numeric difference method + * (1: foward differences (default), 0: central differences, -1: backward differences) */ template<class Function, class Scalar, class FunctionEvalType> static void partialDerivative(const Function& function, Scalar x0, FunctionEvalType& derivative, const FunctionEvalType& fx0, - const Scalar eps) + const Scalar eps, + const int numericDifferenceMethod = 1) { - static const int numericDifferenceMethod = numDiffMethod(); - Scalar delta = 0.0; // we are using forward or central differences, i.e. we need to calculate f(x + \epsilon) if (numericDifferenceMethod >= 0) @@ -112,13 +113,6 @@ public: // deflections between the two function evaluation derivative /= delta; } - - static int numDiffMethod() - { - static const int numericDifferenceMethod - = getParam<int>("Assembly.NumericDifferenceMethod", 1); - return numericDifferenceMethod; - } }; } // end namespace Dumux diff --git a/dumux/common/parameters.hh b/dumux/common/parameters.hh index d81b5fd1b209fe4528a3ddbc8183933c8561e70e..7ffe4836518eb806fc3818320609556b316a0f73 100644 --- a/dumux/common/parameters.hh +++ b/dumux/common/parameters.hh @@ -354,7 +354,9 @@ private: params["Implicit.UpwindWeight"] = "1.0"; params["Implicit.EnablePartialReassemble"] = "false"; params["Implicit.EnableJacobianRecycling"] = "false"; - params["Implicit.NumericDifferenceMethod"] = "1"; + + // parameters in the assembly group + params["Assembly.NumericDifferenceMethod"] = "1"; // parameters in the linear solver group params["LinearSolver.GMResRestart"] = "10"; diff --git a/dumux/discretization/box/fvgridgeometry.hh b/dumux/discretization/box/fvgridgeometry.hh index e3b457bebea5fa0230ab8c757d40cc9884fdf58f..71ea05f596b0285cb446132659b122a2beb95e32 100644 --- a/dumux/discretization/box/fvgridgeometry.hh +++ b/dumux/discretization/box/fvgridgeometry.hh @@ -28,6 +28,7 @@ #include <dune/geometry/referenceelements.hh> #include <dune/localfunctions/lagrange/pqkfactory.hh> +#include <dumux/discretization/methods.hh> #include <dumux/discretization/basefvgridgeometry.hh> #include <dumux/discretization/box/boxgeometryhelper.hh> #include <dumux/discretization/box/fvelementgeometry.hh> @@ -71,6 +72,9 @@ class BoxFVGridGeometry<TypeTag, true> : public BaseFVGridGeometry<TypeTag> using GeometryHelper = BoxGeometryHelper<GridView, dim, SubControlVolume, SubControlVolumeFace>; public: + //! export discretization method + static constexpr DiscretizationMethods discretizationMethod = DiscretizationMethods::Box; + //! Constructor BoxFVGridGeometry(const GridView gridView) : ParentType(gridView) {} @@ -263,6 +267,9 @@ class BoxFVGridGeometry<TypeTag, false> : public BaseFVGridGeometry<TypeTag> using ReferenceElements = typename Dune::ReferenceElements<CoordScalar, dim>; public: + //! export discretization method + static constexpr DiscretizationMethods discretizationMethod = DiscretizationMethods::Box; + //! Constructor BoxFVGridGeometry(const GridView gridView) : ParentType(gridView) {} diff --git a/dumux/discretization/cellcentered/mpfa/fvgridgeometry.hh b/dumux/discretization/cellcentered/mpfa/fvgridgeometry.hh index dfba3592e209700e45d4642e397f517b5433f180..248c0129d9739c625ab49c728ab6f79c0414d3da 100644 --- a/dumux/discretization/cellcentered/mpfa/fvgridgeometry.hh +++ b/dumux/discretization/cellcentered/mpfa/fvgridgeometry.hh @@ -32,6 +32,7 @@ #include <dumux/common/properties.hh> #include <dumux/common/parameters.hh> +#include <dumux/discretization/methods.hh> #include <dumux/discretization/basefvgridgeometry.hh> #include <dumux/discretization/cellcentered/mpfa/fvelementgeometry.hh> #include <dumux/discretization/cellcentered/mpfa/connectivitymap.hh> @@ -87,6 +88,9 @@ class CCMpfaFVGridGeometry<TypeTag, true> : public BaseFVGridGeometry<TypeTag> using ReferenceElements = typename Dune::ReferenceElements<CoordScalar, dim>; public: + //! export discretization method + static constexpr DiscretizationMethods discretizationMethod = DiscretizationMethods::CCMpfa; + using SecondaryIvIndicatorType = std::function<bool(const Element&, const Intersection&, bool)>; //! Constructor without indicator function for secondary interaction volumes @@ -429,6 +433,9 @@ class CCMpfaFVGridGeometry<TypeTag, false> : public BaseFVGridGeometry<TypeTag> using ReferenceElements = typename Dune::ReferenceElements<CoordScalar, dim>; public: + //! export discretization method + static constexpr DiscretizationMethods discretizationMethod = DiscretizationMethods::CCMpfa; + using SecondaryIvIndicator = std::function<bool(const Element&, const Intersection&, bool)>; //! Constructor without indicator function for secondary interaction volumes diff --git a/dumux/discretization/cellcentered/mpfa/properties.hh b/dumux/discretization/cellcentered/mpfa/properties.hh index 3a20ad88449e6cfb1d6809240a930c123f73a2a1..ce805e818a37a5fa7f8c5395f284b6fd4d15a26f 100644 --- a/dumux/discretization/cellcentered/mpfa/properties.hh +++ b/dumux/discretization/cellcentered/mpfa/properties.hh @@ -81,7 +81,7 @@ private: public: // Per default, we allow for 8 neighbors on network/surface grids - static const std::size_t value = dim < dimWorld ? 9 : 2; + static constexpr std::size_t value = dim < dimWorld ? 9 : 2; }; //! Set the index set type used on the dual grid nodes diff --git a/dumux/discretization/cellcentered/tpfa/fvgridgeometry.hh b/dumux/discretization/cellcentered/tpfa/fvgridgeometry.hh index f71a30ea60989698801ff931a22dad27b616e5a4..9d38e45f97d540192eec3a8dcf194fdddbce4ba2 100644 --- a/dumux/discretization/cellcentered/tpfa/fvgridgeometry.hh +++ b/dumux/discretization/cellcentered/tpfa/fvgridgeometry.hh @@ -28,6 +28,7 @@ #include <dune/common/version.hh> +#include <dumux/discretization/methods.hh> #include <dumux/discretization/basefvgridgeometry.hh> #include <dumux/discretization/cellcentered/tpfa/fvelementgeometry.hh> #include <dumux/discretization/cellcentered/connectivitymap.hh> @@ -74,6 +75,9 @@ class CCTpfaFVGridGeometry<TypeTag, true> : public BaseFVGridGeometry<TypeTag> friend typename GET_PROP_TYPE(TypeTag, FVElementGeometry); public: + //! export discretization method + static constexpr DiscretizationMethods discretizationMethod = DiscretizationMethods::CCTpfa; + //! Constructor CCTpfaFVGridGeometry(const GridView& gridView) : ParentType(gridView) @@ -331,6 +335,9 @@ class CCTpfaFVGridGeometry<TypeTag, false> : public BaseFVGridGeometry<TypeTag> using GlobalPosition = Dune::FieldVector<CoordScalar, dimWorld>; public: + //! export discretization method + static constexpr DiscretizationMethods discretizationMethod = DiscretizationMethods::CCTpfa; + //! Constructor CCTpfaFVGridGeometry(const GridView& gridView) : ParentType(gridView) diff --git a/dumux/discretization/cellcentered/tpfa/properties.hh b/dumux/discretization/cellcentered/tpfa/properties.hh index 3710cf0fa7f339df01da81fc79ae8b570dac3f81..c9262c4b141561ec9b65bdec6de69c0019461f51 100644 --- a/dumux/discretization/cellcentered/tpfa/properties.hh +++ b/dumux/discretization/cellcentered/tpfa/properties.hh @@ -92,7 +92,7 @@ private: public: // Per default, we allow for 8 neighbors on network/surface grids - static const std::size_t value = dim < dimWorld ? 9 : 2; + static constexpr std::size_t value = dim < dimWorld ? 9 : 2; }; //! The sub control volume diff --git a/dumux/porousmediumflow/1p/incompressiblelocalresidual.hh b/dumux/porousmediumflow/1p/incompressiblelocalresidual.hh index dfdc173f082d9f9aced2fd6b416775cca63f27c4..1a0f1177ca8b88f7634b6c7458b54117124d8759 100644 --- a/dumux/porousmediumflow/1p/incompressiblelocalresidual.hh +++ b/dumux/porousmediumflow/1p/incompressiblelocalresidual.hh @@ -44,7 +44,6 @@ class OnePIncompressibleLocalResidual : public ImmiscibleLocalResidual<TypeTag> using Problem = typename GET_PROP_TYPE(TypeTag, Problem); using VolumeVariables = typename GET_PROP_TYPE(TypeTag, VolumeVariables); using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables); - using ElementResidualVector = typename GET_PROP_TYPE(TypeTag, ElementSolutionVector); using FluxVariables = typename GET_PROP_TYPE(TypeTag, FluxVariables); using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem); using ElementFluxVariablesCache = typename GET_PROP_TYPE(TypeTag, ElementFluxVariablesCache); diff --git a/dumux/porousmediumflow/2p/incompressiblelocalresidual.hh b/dumux/porousmediumflow/2p/incompressiblelocalresidual.hh index 60ee8808597d7ca8c116c615a4035266cf236e04..73affdffac48d9ffdedaa9c69635e0dffd5f8760 100644 --- a/dumux/porousmediumflow/2p/incompressiblelocalresidual.hh +++ b/dumux/porousmediumflow/2p/incompressiblelocalresidual.hh @@ -47,7 +47,7 @@ class TwoPIncompressibleLocalResidual : public ImmiscibleLocalResidual<TypeTag> using Problem = typename GET_PROP_TYPE(TypeTag, Problem); using VolumeVariables = typename GET_PROP_TYPE(TypeTag, VolumeVariables); using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables); - using ElementResidualVector = typename GET_PROP_TYPE(TypeTag, ElementSolutionVector); + using ElementSolutionVector = typename GET_PROP_TYPE(TypeTag, ElementSolutionVector); using FluxVariables = typename GET_PROP_TYPE(TypeTag, FluxVariables); using ElementFluxVariablesCache = typename GET_PROP_TYPE(TypeTag, ElementFluxVariablesCache); using SubControlVolume = typename GET_PROP_TYPE(TypeTag, SubControlVolume); @@ -188,10 +188,10 @@ public: const auto& outsideVolVars = curElemVolVars[outsideScvIdx]; const auto& insideMaterialParams = problem.spatialParams().materialLawParams(element, insideScv, - ElementResidualVector({insideVolVars.priVars()})); + ElementSolutionVector({insideVolVars.priVars()})); const auto& outsideMaterialParams = problem.spatialParams().materialLawParams(outsideElement, outsideScv, - ElementResidualVector({outsideVolVars.priVars()})); + ElementSolutionVector({outsideVolVars.priVars()})); // get references to the two participating derivative matrices auto& dI_dI = derivativeMatrices[insideScvIdx]; @@ -303,7 +303,7 @@ public: const auto& outsideVolVars = curElemVolVars[outsideScv]; // we need the element solution for the material parameters - ElementResidualVector elemSol(fvGeometry.numScv()); + ElementSolutionVector elemSol(fvGeometry.numScv()); for (const auto& scv : scvs(fvGeometry)) elemSol[scv.indexInElement()] = curElemVolVars[scv].priVars(); const auto& insideMaterialParams = problem.spatialParams().materialLawParams(element, insideScv, elemSol); const auto& outsideMaterialParams = problem.spatialParams().materialLawParams(element, outsideScv, elemSol); @@ -449,7 +449,7 @@ public: const auto& outsideVolVars = curElemVolVars[scvf.outsideScvIdx()]; const auto& insideMaterialParams = problem.spatialParams().materialLawParams(element, insideScv, - ElementResidualVector({insideVolVars.priVars()})); + ElementSolutionVector({insideVolVars.priVars()})); // some quantities to be reused (rho & mu are constant and thus equal for all cells) static const auto rho_w = insideVolVars.density(FluidSystem::wPhaseIdx); diff --git a/dumux/porousmediumflow/mpnc/localresidual.hh b/dumux/porousmediumflow/mpnc/localresidual.hh index d982de82f85d55f6c8ae25fa820ff196f0967036..737b507b71e7c23231995d98e480a2b8192ab4a7 100644 --- a/dumux/porousmediumflow/mpnc/localresidual.hh +++ b/dumux/porousmediumflow/mpnc/localresidual.hh @@ -60,13 +60,13 @@ public: using typename ParentType::ElementResidualVector; - ElementResidualVector evalFluxSource(const Element& element, - const FVElementGeometry& fvGeometry, - const ElementVolumeVariables& elemVolVars, - const ElementFluxVariablesCache& elemFluxVarsCache, - const ElementBoundaryTypes &bcTypes) const + ElementResidualVector evalFluxAndSource(const Element& element, + const FVElementGeometry& fvGeometry, + const ElementVolumeVariables& elemVolVars, + const ElementFluxVariablesCache& elemFluxVarsCache, + const ElementBoundaryTypes &bcTypes) const { - ElementResidualVector residual = ParentType::evalFluxSource(element, fvGeometry, elemVolVars, elemFluxVarsCache, bcTypes); + ElementResidualVector residual = ParentType::evalFluxAndSource(element, fvGeometry, elemVolVars, elemFluxVarsCache, bcTypes); for (auto&& scv : scvs(fvGeometry)) { diff --git a/test/porousmediumflow/3p3c/implicit/test_3p3c_fv.input b/test/porousmediumflow/3p3c/implicit/test_3p3c_fv.input index ef445b1a852b728898f0ae79c34506e0d9d8c446..d910fd45112ccb392383ce3737ace10045a15e58 100644 --- a/test/porousmediumflow/3p3c/implicit/test_3p3c_fv.input +++ b/test/porousmediumflow/3p3c/implicit/test_3p3c_fv.input @@ -9,7 +9,7 @@ Cells = 40 4 [Problem] Name = infiltration -[Implicit] +[Assembly] NumericDifferenceMethod = 0 # -1 backward differences, 0: central differences, +1: forward differences [Newton] diff --git a/test/porousmediumflow/3p3c/implicit/test_columnxylol_fv.input b/test/porousmediumflow/3p3c/implicit/test_columnxylol_fv.input index c1848acdb19e54f7bc697e71ff5daf79569d8ea3..80efdf4037028cba0518be7849c1d6a4d7d0d54f 100644 --- a/test/porousmediumflow/3p3c/implicit/test_columnxylol_fv.input +++ b/test/porousmediumflow/3p3c/implicit/test_columnxylol_fv.input @@ -10,5 +10,5 @@ Cells = 1 120 [Problem] Name = columnxylol # name passed to the output routines -[Implicit] +[Assembly] NumericDifferenceMethod = 0 # -1 backward differences, 0: central differences, +1: forward differences diff --git a/test/porousmediumflow/3p3c/implicit/test_kuvette_fv.input b/test/porousmediumflow/3p3c/implicit/test_kuvette_fv.input index 1738b0ae022d312f8d7a7c9cc4c9e6077951bd03..e48af1cd0e96d072b820eb0b3925fb5cf1ee53dc 100644 --- a/test/porousmediumflow/3p3c/implicit/test_kuvette_fv.input +++ b/test/porousmediumflow/3p3c/implicit/test_kuvette_fv.input @@ -11,7 +11,7 @@ Cells = 15 8 [Problem] Name = kuevette # name passed to the output routines -[Implicit] +[Assembly] NumericDifferenceMethod = 0 # use central differences (backward -1, forward +1) [Newton]