From 72925210b18d5a27c538ae341e2e81d9882899c9 Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Fri, 10 Apr 2020 18:14:35 +0000 Subject: [PATCH 01/57] Merge branch 'cleanup/doxygen_mainbranch' into 'master' Cleanup doxygen Closes #835 See merge request dumux-repositories/dumux!1964 (cherry picked from commit 73cbb603ab1db4beccf063f3d4adcdd33c859c33) 8a37683f [doxygen] Temporarily remove copydoc and copydetails with file paths. Copydoc... 9064179e [doxygen] Correct copydocs without backslash. 1068eb21 [doxygen] Remove copydoc of something that does not exist. 7a26b0ff [doxygen] Fix link to parameterlist.txt. 06de8c79 [doxygen] Fix parameters which are not documented or do not exist. 2c465c69 Increase DOT_GRAPH_MAX_NODES. Default value of 50 is sometimes exceeded by Dumux. de8d9f48 Use the doxygen command \deprecated nowhere. Deprecated stuff is already in... c9c87ff0 [doxygen] Improve ingroups. 44a43db1 [docu] Correct dimWorld. 80aa104a [doxygen] Changes to stop things appearing as description of Dumux namespace. ba332bb6 [doxygen] Add comment about nicer file names for the website. ed560ce0 [doxygen][cleanup] We don't use the Dune depreaceted macro anymore --- doc/doxygen/Doxylocal | 10 +- doc/doxygen/README.md | 3 + doc/doxygen/modules.txt | 146 +++++++++--------- dumux/common/boundaryflag.hh | 2 +- dumux/common/doubleexpintegrationconstants.hh | 6 +- dumux/common/doubleexpintegrator.hh | 6 +- dumux/common/staggeredfvproblem.hh | 2 + dumux/common/timemanager.hh | 1 - dumux/discretization/basegridgeometry.hh | 2 +- .../box/gridfluxvariablescache.hh | 2 +- .../discretization/box/gridvolumevariables.hh | 2 +- .../cellcentered/gridvolumevariables.hh | 2 +- .../mpfa/gridfluxvariablescache.hh | 2 +- .../cellcentered/mpfa/helper.hh | 2 +- .../cellcentered/mpfa/localassemblerbase.hh | 2 + .../tpfa/gridfluxvariablescache.hh | 2 +- .../staggered/freeflow/gridvolumevariables.hh | 2 +- .../staggered/gridfacevariables.hh | 2 +- .../staggered/gridfluxvariablescache.hh | 2 +- dumux/flux/box/fourierslawnonequilibrium.hh | 2 +- dumux/flux/fluxvariablescaching.hh | 2 +- .../freeflow/compositional/kepsilonncmodel.hh | 2 +- dumux/freeflow/compositional/komegancmodel.hh | 2 +- .../compositional/lowrekepsilonncmodel.hh | 2 +- .../compositional/navierstokesncmodel.hh | 6 +- dumux/freeflow/compositional/oneeqncmodel.hh | 2 +- dumux/freeflow/compositional/zeroeqncmodel.hh | 3 +- dumux/freeflow/rans/twoeq/indices.hh | 4 +- dumux/freeflow/staggeredupwindmethods.hh | 25 ++- dumux/geomechanics/elastic/indices.hh | 4 +- dumux/geomechanics/elastic/localresidual.hh | 4 +- dumux/geomechanics/elastic/model.hh | 6 +- dumux/geomechanics/elastic/volumevariables.hh | 4 +- .../poroelastic/couplingmanager.hh | 4 +- dumux/geomechanics/poroelastic/iofields.hh | 4 +- .../geomechanics/poroelastic/localresidual.hh | 4 +- dumux/geomechanics/poroelastic/model.hh | 4 +- .../poroelastic/volumevariables.hh | 4 +- dumux/io/grid/gridmanager_alu.hh | 5 + dumux/io/grid/gridmanager_base.hh | 1 + dumux/io/grid/gridmanager_foam.hh | 2 + dumux/io/grid/gridmanager_mmesh.hh | 1 + dumux/io/grid/gridmanager_oned.hh | 1 + dumux/io/grid/gridmanager_sp.hh | 1 + dumux/io/grid/gridmanager_ug.hh | 1 + dumux/io/grid/gridmanager_yasp.hh | 2 + dumux/material/components/ammonia.hh | 4 + dumux/material/components/base.hh | 12 ++ dumux/material/components/chlorideion.hh | 4 + dumux/material/components/componenttraits.hh | 4 + dumux/material/components/glucose.hh | 4 + dumux/material/components/n2.hh | 2 +- dumux/material/components/sodiumion.hh | 5 +- dumux/material/components/solid.hh | 4 + dumux/material/components/urea.hh | 3 + .../diffusivityconstanttortuosity.hh | 3 +- .../diffusivitymillingtonquirk.hh | 3 +- .../multidomain/facet/codimonegridadapter.hh | 2 +- dumux/multidomain/facet/enrichmenthelper.hh | 2 +- dumux/multidomain/facet/vertexmapper.hh | 2 +- dumux/nonlinear/findscalarroot.hh | 8 +- dumux/parallel/vectorcommdatahandle.hh | 4 +- dumux/parallel/vertexhandles.hh | 2 +- .../2p/boxmaterialinterfaceparams.hh | 2 +- .../2p/saturationreconstruction.hh | 2 +- .../2p2c/sequential/celldatamultiphysics.hh | 2 +- dumux/porousmediumflow/mpnc/model.hh | 4 - .../1p_1p/convergencetest/problem_darcy.hh | 6 +- .../1p_1p/convergencetest/problem_stokes.hh | 1 - .../2p/implicit/adaptive/main.cc | 4 +- .../2p/implicit/boxdfm/spatialparams.hh | 1 + .../2p/implicit/cornerpoint/spatialparams.hh | 1 + .../implicit/incompressible/spatialparams.hh | 1 + .../3p/implicit/convection/problem.hh | 2 +- .../tracer/multiphase/problem.hh | 1 + 75 files changed, 238 insertions(+), 157 deletions(-) diff --git a/doc/doxygen/Doxylocal b/doc/doxygen/Doxylocal index 4c08490489..9b85a30f9f 100644 --- a/doc/doxygen/Doxylocal +++ b/doc/doxygen/Doxylocal @@ -14,8 +14,7 @@ INPUT += @srcdir@/mainpage.txt \ @srcdir@/modules.txt \ @top_srcdir@/dumux \ @top_srcdir@/test \ - # @srcdir@/extradoc/parameterlist.txt \ # we currently do not have a parameter list. Should be back for 3.1 - # @srcdir@/extradoc/featurelist.txt # we currently do not have a feature list. Should be back for 3.1 + @srcdir@/extradoc/parameterlist.txt EXAMPLE_PATH += @srcdir@/extradoc @@ -43,5 +42,8 @@ CITE_BIB_FILES = @top_srcdir@/doc/handbook/dumux-handbook.bib # enable macro expansion only for specified macros MACRO_EXPANSION = YES EXPAND_ONLY_PREDEF = YES -PREDEFINED += "DUNE_DEPRECATED:=/** \deprecated */" \ - "DUNE_DEPRECATED_MSG(A):=/** \deprecated A */" + +DOT_GRAPH_MAX_NODES = 100 + +# uncomment for the website +# SHORT_NAMES = NO diff --git a/doc/doxygen/README.md b/doc/doxygen/README.md index 11b1a83d1b..8eaa6f37da 100644 --- a/doc/doxygen/README.md +++ b/doc/doxygen/README.md @@ -60,3 +60,6 @@ If there are **function-arguments** that are not self-explanatory, they should b **Always explain all params or no params at all!** Otherwise Doxygen will throw an error. Template parameters are documented with `\tparam`. Additional Doxygen-commands that might be useful are `\note` for giving an important note/hint on what the function does as well as `\return` which specifies the return value (if applicable). + +April 2020 note: `\copydoc`,`\copybrief` and `\copydetails`, as well as `@copydoc`,`@copybrief` and `@copydetails` do not work with filenames in the current doxygen version. +The bug is reported and has been fixed in doxygen pull request #7693. (It will work again in doxygen 1_8_18, probably at the end of 2020.) diff --git a/doc/doxygen/modules.txt b/doc/doxygen/modules.txt index 13cde77a34..053abe0624 100644 --- a/doc/doxygen/modules.txt +++ b/doc/doxygen/modules.txt @@ -14,7 +14,7 @@ * \ingroup PorousmediumflowModels * \defgroup OnePModel 1p * \brief Single-phase (immiscible) Darcy flow - * \copydetails ./porousmediumflow/1p/model.hh + * For a detailed model decription see porousmediumflow/1p/model.hh */ /*! * \ingroup OnePModel @@ -31,19 +31,19 @@ * \ingroup PorousmediumflowModels * \defgroup OnePNCModel 1pnc * \brief Single-phase, multi-component Darcy flow - * \copydetails ./porousmediumflow/1pnc/model.hh + * For a detailed model decription see porousmediumflow/1pnc/model.hh */ /*! * \ingroup PorousmediumflowModels * \defgroup OnePNCMinModel 1pncmin * \brief Single-phase, multi-component Darcy flow with mineralization - * \copydetails ./porousmediumflow/1pncmin/model.hh + * For a detailed model decription see porousmediumflow/1pncmin/model.hh */ /*! * \ingroup PorousmediumflowModels * \defgroup TwoPModel 2p * \brief Two-phase (immiscible) Darcy flow - * \copydetails ./porousmediumflow/2p/model.hh + * For a detailed model decription see porousmediumflow/2p/model.hh */ /*! * \ingroup TwoPModel @@ -60,13 +60,13 @@ * \ingroup PorousmediumflowModels * \defgroup TwoPOneCModel 2p1c * \brief Two-phase, one-component Darcy flow - * \copydetails ./porousmediumflow/2p1c/model.hh + * For a detailed model decription see porousmediumflow/2p1c/model.hh */ /*! * \ingroup PorousmediumflowModels * \defgroup TwoPTwoCModel 2p2c * \brief Two-phase, two-component Darcy flow - * \copydetails ./porousmediumflow/2p2c/model.hh + * For a detailed model decription see porousmediumflow/2p2c/model.hh */ /*! * \ingroup TwoPTwoCModel @@ -83,100 +83,100 @@ * \ingroup PorousmediumflowModels * \defgroup TwoPNCModel 2pnc * \brief two-phase, multi-component Darcy flow - * \copydetails ./porousmediumflow/2pnc/model.hh + * For a detailed model decription see porousmediumflow/2pnc/model.hh */ /*! * \ingroup PorousmediumflowModels * \defgroup TwoPNCMinModel 2pncmin * \brief Two-phase, multi-component Darcy flow with mineralization - * \copydetails ./porousmediumflow/2pncmin/model.hh + * For a detailed model decription see porousmediumflow/2pncmin/model.hh */ /*! * \ingroup PorousmediumflowModels * \defgroup ThreePModel 3p * \brief Three-phase (immiscible) Darcy flow - * \copydetails ./porousmediumflow/3p/model.hh + * For a detailed model decription see porousmediumflow/3p/model.hh */ /*! * \ingroup PorousmediumflowModels * \defgroup ThreePThreeCModel 3p3c * \brief Three-phase, three-component Darcy flow - * \copydetails ./porousmediumflow/3p3c/model.hh + * For a detailed model decription see porousmediumflow/3p3c/model.hh */ /*! * \ingroup PorousmediumflowModels * \defgroup ThreePWaterOilModel 3pwateroil * \brief Three-phase, two-component Darcy flow with water (liquid & gas) and oil - * \copydetails ./porousmediumflow/3pwateroil/model.hh + * For a detailed model decription see porousmediumflow/3pwateroil/model.hh */ /*! * \ingroup PorousmediumflowModels * \defgroup BoxDFMModel boxdfm * \brief Vertex-centered, continuous-pressure, conforming lower-dimensional discrete-fracture model - * \copydetails ./porousmediumflow/boxdfm/model.hh + * For a detailed model decription see porousmediumflow/boxdfm/model.hh */ /*! * \ingroup PorousmediumflowModels * \defgroup CO2Model CO2 * \brief Two-phase, two-component Darcy flow specialized for supercritical CO2 storage - * \copydetails ./porousmediumflow/co2/model.hh + * For a detailed model decription see porousmediumflow/co2/model.hh */ /*! * \ingroup PorousmediumflowModels * \defgroup MineralizationModel mineralization * \brief Model adding components that can precipitate as a solid phase to a standard Darcy flow model * - * \copydetails ./porousmediumflow/mineralization/model.hh + * For a detailed model decription see porousmediumflow/mineralization/model.hh */ /*! * \ingroup PorousmediumflowModels * \defgroup MPNCModel mpnc * \brief Generalized multi-phase, multi-component Darcy flow * - * \copydetails ./porousmediumflow/mpnc/model.hh + * For a detailed model decription see porousmediumflow/mpnc/model.hh */ /*! * \ingroup PorousmediumflowModels * \defgroup NonEquilibriumModel NonEquilibrium * \brief Model that adds nonequilibrium equations to another porous medium flow model (only used in MPNCModel currently) - * \copydetails ./porousmediumflow/nonequilibrium/model.hh + * For a detailed model decription see porousmediumflow/nonequilibrium/model.hh */ /*! * \ingroup NonEquilibriumModel * \defgroup ThermalNonEquilibriumModel ThermalNonEquilibrium * \brief Model that adapts the energy localresidual to thermal nonequilibrium - * \copydetails ./porousmediumflow/nonequilibrium/thermal/localresidual.hh + * For a detailed model decription see porousmediumflow/nonequilibrium/thermal/localresidual.hh */ /*! * \ingroup PorousmediumflowModels * \defgroup NIModel nonisothermal * \brief Model that adds an energy equation (thermal equilibrium) to another porous medium flow model * - * \copydetails ./porousmediumflow/nonisothermal/model.hh + * For a detailed model decription see porousmediumflow/nonisothermal/model.hh */ /*! * \ingroup PorousmediumflowModels * \defgroup RichardsModel Richards * \brief Richards flow - * \copydetails ./porousmediumflow/richards/model.hh + * For a detailed model decription see porousmediumflow/richards/model.hh */ /*! * \ingroup PorousmediumflowModels * \defgroup RichardsNCModel Richards nc * \brief Richards multi-component flow - * \copydetails ./porousmediumflow/richardsnc/model.hh + * For a detailed model decription see porousmediumflow/richardsnc/model.hh */ /*! * \ingroup PorousmediumflowModels * \defgroup SolidEnergyModel Solid energy * \brief Energy equation for the solid (general heat equation) - * \copydetails ./porousmediumflow/solidenergy/model.hh + * For a detailed model decription see porousmediumflow/solidenergy/model.hh */ /*! * \ingroup PorousmediumflowModels * \defgroup TracerModel Tracer * \brief Multi-component advection-diffusion-reaction model with given velocity field - * \copydetails ./porousmediumflow/tracer/model.hh + * For a detailed model decription see porousmediumflow/tracer/model.hh */ /* ***************** FreeflowModels ******************/ @@ -188,66 +188,66 @@ * \ingroup FreeflowModels * \defgroup NavierStokesModel Navier-Stokes * \brief Single-phase Navier-Stokes flow - * \copydetails ./freeflow/navierstokes/model.hh + * For a detailed model decription see freeflow/navierstokes/model.hh */ /*! * \ingroup FreeflowModels * \defgroup RANSModel Reynolds-Averaged Navier-Stokes * \brief Single-phase Reynolds-Averaged Navier-Stokes flow - * \copydetails ./freeflow/rans/model.hh + * For a detailed model decription see freeflow/rans/model.hh */ /*! * \ingroup RANSModel * \defgroup ZeroEqModel 0-Eq. Models * \brief Zero-equation or algebraic turbulence models - * \copydetails ./freeflow/rans/zeroeq/model.hh + * For a detailed model decription see freeflow/rans/zeroeq/model.hh */ /*! * \ingroup RANSModel * \defgroup OneEqModel 1-Eq. Models * \brief One-equation turbulence model by Spalart-Allmaras - * \copydetails ./freeflow/rans/oneeq/model.hh + * For a detailed model decription see freeflow/rans/oneeq/model.hh */ /*! * \ingroup RANSModel * \defgroup TwoEqModel 2-Eq. Models * \brief Two-equation turbulence models */ - /*! - * \ingroup TwoEqModel - * \defgroup KEpsilonModel K-epsilon model - * \brief K-epsilon model - * \copydetails ./freeflow/rans/twoeq/kepsilon/model.hh - */ - /*! - * \ingroup TwoEqModel - * \defgroup KOmegaModel K-omega model - * \brief K-omega model - * \copydetails ./freeflow/rans/twoeq/komega/model.hh - */ - /*! - * \ingroup TwoEqModel - * \defgroup LowReKEpsilonModel Low-Re k-epsilon model - * \brief Low-Re k-epsilon model - * \copydetails ./freeflow/rans/twoeq/lowrekepsilon/model.hh - */ + /*! + * \ingroup TwoEqModel + * \defgroup KEpsilonModel K-epsilon model + * \brief K-epsilon model + * For a detailed model decription see freeflow/rans/twoeq/kepsilon/model.hh + */ + /*! + * \ingroup TwoEqModel + * \defgroup KOmegaModel K-omega model + * \brief K-omega model + * For a detailed model decription see freeflow/rans/twoeq/komega/model.hh + */ + /*! + * \ingroup TwoEqModel + * \defgroup LowReKEpsilonModel Low-Re k-epsilon model + * \brief Low-Re k-epsilon model + * For a detailed model decription see freeflow/rans/twoeq/lowrekepsilon/model.hh + */ /*! * \ingroup FreeflowModels * \defgroup FreeflowNCModel Compositional * \brief Single-phase multi-component free-flow flow models - * \copydetails ./freeflow/compositional/navierstokesncmodel.hh + * For a detailed model decription see freeflow/compositional/navierstokesncmodel.hh */ /*! * \ingroup FreeflowModels * \defgroup FreeflowNIModel Nonisothermal * \brief An energy equation adaptor for isothermal free-flow models - * \copydetails ./freeflow/nonisothermal/model.hh + * For a detailed model decription see freeflow/nonisothermal/model.hh */ /*! * \ingroup FreeflowModels * \defgroup ShallowWaterModel 2D shallow water model * \brief Two-dimensional shallow water flow (depth-averaged) - * \copydetails ./freeflow/shallowwater/model.hh + * For a detailed model decription see freeflow/shallowwater/model.hh */ /*! * \defgroup Geomechanics Geomechanics Models @@ -257,13 +257,13 @@ * \ingroup Geomechanics * \defgroup Elastic Solid mechanics w/o fluid pressure * \brief Models linear elastic deformation of a solid. Disregards fluid pressure. - * \copydetails ./geomechanics/elastic/model.hh + * For a detailed model decription see geomechanics/elastic/model.hh */ /*! * \ingroup Geomechanics * \defgroup PoroElastic Solid mechanics with fluid pressure * \brief Models linear elastic deformation of a solid. Takes fluid pressure into account. - * \copydetails ./geomechanics/poroelastic/model.hh + * For a detailed model decription see geomechanics/poroelastic/model.hh */ /* ***************** Benchmarks and Tests ******************/ @@ -351,6 +351,11 @@ * \defgroup RichardsNCTests Richards multi-component benchmarks and tests * \brief A multi-component transport problem in the unsaturated zone using the RichardsNCModel. The files are listed below. */ + /*! + * \ingroup SolidEnergyTests + * \defgroup SolidEnergyTests Solid energy tests + * \brief Tests for the solid energy model. + */ /*! * \ingroup PorousmediumflowTests * \defgroup TracerTests Tracer benchmarks and tests @@ -464,7 +469,7 @@ */ /*! * \ingroup Flux - * \defgroup BoxFlux Flux related to the Box scheme + * \defgroup BoxFlux Flux related to the box scheme * \brief Flux related to the box scheme */ /*! @@ -654,27 +659,26 @@ * \defgroup AssemblyAndSolvers Assembly and Solvers * \brief Assembling matrices and vectors, solvers for linear and nonlinear equations */ - -/* ***************** Assembly ******************/ -/*! - * \ingroup AssemblyAndSolvers - * \defgroup Assembly Assembly - * \brief Assembly of linear systems (Jacobian and residual) - */ - -/* ***************** Linear ******************/ -/*! - * \ingroup AssemblyAndSolvers - * \defgroup Linear Linear - * \brief Linear solvers and helpers - */ - -/* ***************** Nonlinear ******************/ -/*! - * \ingroup AssemblyAndSolvers - * \defgroup Nonlinear Nonlinear - * \brief Nonlinear solvers: Newton method - */ + /*! + * \ingroup AssemblyAndSolvers + * \defgroup Assembly Assembly + * \brief Assembly of linear systems (Jacobian and residual) + */ + /*! + * \ingroup AssemblyAndSolvers + * \defgroup Linear Linear + * \brief Linear solvers and helpers + */ + /*! + * \ingroup AssemblyAndSolvers + * \defgroup Nonlinear Nonlinear + * \brief Nonlinear solvers: Newton method + */ + /*! + * \ingroup AssemblyAndSolvers + * \defgroup Parallel Parallel + * \brief Files for communication of parallel solvers + */ /* ***************** Common ******************/ /*! diff --git a/dumux/common/boundaryflag.hh b/dumux/common/boundaryflag.hh index 49b7770b13..8429f47ee1 100644 --- a/dumux/common/boundaryflag.hh +++ b/dumux/common/boundaryflag.hh @@ -30,7 +30,7 @@ namespace Dumux { /*! - * \ingroup InputOutput + * \ingroup Common * \brief Class for accessing boundary flags * \note this works for all grid managers with gmsh meshes. */ diff --git a/dumux/common/doubleexpintegrationconstants.hh b/dumux/common/doubleexpintegrationconstants.hh index 9c5fdaee4d..be4b5f8f58 100644 --- a/dumux/common/doubleexpintegrationconstants.hh +++ b/dumux/common/doubleexpintegrationconstants.hh @@ -48,7 +48,11 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ - +/*! + * \file + * \ingroup Common + * \brief Exponential integration abcissas + */ #ifndef DUMUX_COMMON_DOUBLEEXP_INTEGRATION_CONSTANTS_HH #define DUMUX_COMMON_DOUBLEEXP_INTEGRATION_CONSTANTS_HH diff --git a/dumux/common/doubleexpintegrator.hh b/dumux/common/doubleexpintegrator.hh index 0b4ba4c848..3591e82a01 100644 --- a/dumux/common/doubleexpintegrator.hh +++ b/dumux/common/doubleexpintegrator.hh @@ -48,7 +48,11 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ - +/*! + * \file + * \ingroup Common + * \brief A double exponential integrator + */ #ifndef DUMUX_COMMON_DOUBLEEXP_INTEGRATOR_HH #define DUMUX_COMMON_DOUBLEEXP_INTEGRATOR_HH diff --git a/dumux/common/staggeredfvproblem.hh b/dumux/common/staggeredfvproblem.hh index a0ffc55ed3..c74db38cfa 100644 --- a/dumux/common/staggeredfvproblem.hh +++ b/dumux/common/staggeredfvproblem.hh @@ -19,6 +19,7 @@ /*! * \file * \ingroup Common + * \ingroup StaggeredDiscretization * \brief Base class for all staggered fv problems */ #ifndef DUMUX_STAGGERD_FV_PROBLEM_HH @@ -33,6 +34,7 @@ namespace Dumux { /*! * \ingroup Common + * \ingroup StaggeredDiscretization * \brief Base class for all staggered finite-volume problems * * \note All quantities (regarding the units) are specified assuming a diff --git a/dumux/common/timemanager.hh b/dumux/common/timemanager.hh index 9e53d104b8..6581bfa90f 100644 --- a/dumux/common/timemanager.hh +++ b/dumux/common/timemanager.hh @@ -39,7 +39,6 @@ namespace Dumux { /*! * \ingroup Common - * \deprecated * \brief Manages the handling of time dependent problems. * * This class facilitates the time management of the simulation. diff --git a/dumux/discretization/basegridgeometry.hh b/dumux/discretization/basegridgeometry.hh index 3e5ac51d5e..5d8c58ff2c 100644 --- a/dumux/discretization/basegridgeometry.hh +++ b/dumux/discretization/basegridgeometry.hh @@ -33,7 +33,7 @@ #include #include -//! make the local view function available whenever we use the grid geometry +// make the local view function available whenever we use the grid geometry #include namespace Dumux { diff --git a/dumux/discretization/box/gridfluxvariablescache.hh b/dumux/discretization/box/gridfluxvariablescache.hh index 90d6079e80..7f884e145b 100644 --- a/dumux/discretization/box/gridfluxvariablescache.hh +++ b/dumux/discretization/box/gridfluxvariablescache.hh @@ -24,7 +24,7 @@ #ifndef DUMUX_DISCRETIZATION_BOX_GRID_FLUXVARSCACHE_HH #define DUMUX_DISCRETIZATION_BOX_GRID_FLUXVARSCACHE_HH -//! make the local view function available whenever we use this class +// make the local view function available whenever we use this class #include #include diff --git a/dumux/discretization/box/gridvolumevariables.hh b/dumux/discretization/box/gridvolumevariables.hh index 9a54ece6e4..7fb514100b 100644 --- a/dumux/discretization/box/gridvolumevariables.hh +++ b/dumux/discretization/box/gridvolumevariables.hh @@ -26,7 +26,7 @@ #include -//! make the local view function available whenever we use this class +// make the local view function available whenever we use this class #include #include #include diff --git a/dumux/discretization/cellcentered/gridvolumevariables.hh b/dumux/discretization/cellcentered/gridvolumevariables.hh index 62897f109b..fddd114a4e 100644 --- a/dumux/discretization/cellcentered/gridvolumevariables.hh +++ b/dumux/discretization/cellcentered/gridvolumevariables.hh @@ -27,7 +27,7 @@ #include #include -//! make the local view function available whenever we use this class +// make the local view function available whenever we use this class #include #include diff --git a/dumux/discretization/cellcentered/mpfa/gridfluxvariablescache.hh b/dumux/discretization/cellcentered/mpfa/gridfluxvariablescache.hh index 0b1a77744d..3bfc795c63 100644 --- a/dumux/discretization/cellcentered/mpfa/gridfluxvariablescache.hh +++ b/dumux/discretization/cellcentered/mpfa/gridfluxvariablescache.hh @@ -24,7 +24,7 @@ #ifndef DUMUX_DISCRETIZATION_CCMPFA_GRID_FLUXVARSCACHE_HH #define DUMUX_DISCRETIZATION_CCMPFA_GRID_FLUXVARSCACHE_HH -//! make the local view function available whenever we use this class +// make the local view function available whenever we use this class #include #include diff --git a/dumux/discretization/cellcentered/mpfa/helper.hh b/dumux/discretization/cellcentered/mpfa/helper.hh index e44bff5a29..bf04356571 100644 --- a/dumux/discretization/cellcentered/mpfa/helper.hh +++ b/dumux/discretization/cellcentered/mpfa/helper.hh @@ -196,7 +196,7 @@ public: /*! * \ingroup CCMpfaDiscretization - * \brief Dimension-specific mpfa helper class for dim == 2 & dimWorld == 2. + * \brief Dimension-specific mpfa helper class for dim == 2 & dimWorld == 3. * Reuses some functionality of the specialization for dim = dimWorld = 2 */ template diff --git a/dumux/discretization/cellcentered/mpfa/localassemblerbase.hh b/dumux/discretization/cellcentered/mpfa/localassemblerbase.hh index d1f7682204..20558faa90 100644 --- a/dumux/discretization/cellcentered/mpfa/localassemblerbase.hh +++ b/dumux/discretization/cellcentered/mpfa/localassemblerbase.hh @@ -90,6 +90,7 @@ class InteractionVolumeAssemblerBase * expressions and the local system of equations * within an mpfa interaction volume. * + * \tparam DataHandle The data handle * \tparam IV The interaction volume type implementation * \tparam TensorFunc Lambda to obtain the tensor w.r.t. * which the local system is to be solved @@ -97,6 +98,7 @@ class InteractionVolumeAssemblerBase * \param handle The data handle in which the matrices are stored * \param iv The interaction volume * \param getT Lambda to evaluate the scv-wise tensors + * \param wijZeroThresh the zero threshold wij */ template< class DataHandle, class IV, class TensorFunc > void assembleMatrices(DataHandle& handle, IV& iv, const TensorFunc& getT, Scalar wijZeroThresh = 0.0) diff --git a/dumux/discretization/cellcentered/tpfa/gridfluxvariablescache.hh b/dumux/discretization/cellcentered/tpfa/gridfluxvariablescache.hh index f368da20db..f40853ed12 100644 --- a/dumux/discretization/cellcentered/tpfa/gridfluxvariablescache.hh +++ b/dumux/discretization/cellcentered/tpfa/gridfluxvariablescache.hh @@ -24,7 +24,7 @@ #ifndef DUMUX_DISCRETIZATION_CCTPFA_GRID_FLUXVARSCACHE_HH #define DUMUX_DISCRETIZATION_CCTPFA_GRID_FLUXVARSCACHE_HH -//! make the local view function available whenever we use this class +// make the local view function available whenever we use this class #include #include diff --git a/dumux/discretization/staggered/freeflow/gridvolumevariables.hh b/dumux/discretization/staggered/freeflow/gridvolumevariables.hh index badedcf287..85534fa69c 100644 --- a/dumux/discretization/staggered/freeflow/gridvolumevariables.hh +++ b/dumux/discretization/staggered/freeflow/gridvolumevariables.hh @@ -27,7 +27,7 @@ #include #include -//! make the local view function available whenever we use this class +// make the local view function available whenever we use this class #include #include #include diff --git a/dumux/discretization/staggered/gridfacevariables.hh b/dumux/discretization/staggered/gridfacevariables.hh index ccc8859b48..f968199a1c 100644 --- a/dumux/discretization/staggered/gridfacevariables.hh +++ b/dumux/discretization/staggered/gridfacevariables.hh @@ -24,7 +24,7 @@ #ifndef DUMUX_DISCRETIZATION_STAGGERED_GRID_FACEVARIABLES_HH #define DUMUX_DISCRETIZATION_STAGGERED_GRID_FACEVARIABLES_HH -//! make the local view function available whenever we use this class +// make the local view function available whenever we use this class #include #include #include diff --git a/dumux/discretization/staggered/gridfluxvariablescache.hh b/dumux/discretization/staggered/gridfluxvariablescache.hh index b78cbe7503..ccef6e2e20 100644 --- a/dumux/discretization/staggered/gridfluxvariablescache.hh +++ b/dumux/discretization/staggered/gridfluxvariablescache.hh @@ -24,7 +24,7 @@ #ifndef DUMUX_DISCRETIZATION_STAGGERED_GRID_FLUXVARSCACHE_HH #define DUMUX_DISCRETIZATION_STAGGERED_GRID_FLUXVARSCACHE_HH -//! make the local view function available whenever we use this class +// make the local view function available whenever we use this class #include #include diff --git a/dumux/flux/box/fourierslawnonequilibrium.hh b/dumux/flux/box/fourierslawnonequilibrium.hh index ce61739057..8add74d130 100644 --- a/dumux/flux/box/fourierslawnonequilibrium.hh +++ b/dumux/flux/box/fourierslawnonequilibrium.hh @@ -41,7 +41,7 @@ template class FouriersLawNonEquilibriumImplementation; /*! - * \ingroup BoxFouriersLaw + * \ingroup BoxFlux * \brief Specialization of Fourier's Law for the box method for thermal nonequilibrium models. */ template diff --git a/dumux/flux/fluxvariablescaching.hh b/dumux/flux/fluxvariablescaching.hh index 680b3ce2ab..1c63433b15 100644 --- a/dumux/flux/fluxvariablescaching.hh +++ b/dumux/flux/fluxvariablescaching.hh @@ -57,7 +57,7 @@ struct _EmptyCache #endif // DOXYGEN /*! - * \ingroup Discretization + * \ingroup Flux * \brief Empty caches to use in a constitutive flux law/process, e.g. Darcy's law */ struct EmptyAdvectionCache : public _EmptyCache {}; diff --git a/dumux/freeflow/compositional/kepsilonncmodel.hh b/dumux/freeflow/compositional/kepsilonncmodel.hh index f0f4b971fa..b66f570c88 100644 --- a/dumux/freeflow/compositional/kepsilonncmodel.hh +++ b/dumux/freeflow/compositional/kepsilonncmodel.hh @@ -22,7 +22,7 @@ * * \brief A single-phase, multi-component k-epsilon model * - * \copydoc dumux/freeflow/compositional/navierstokesncmodel.hh + * For a detailed model decription see dumux/freeflow/compositional/navierstokesncmodel.hh */ #ifndef DUMUX_KEPSILON_NC_MODEL_HH diff --git a/dumux/freeflow/compositional/komegancmodel.hh b/dumux/freeflow/compositional/komegancmodel.hh index 1a4c22f8fd..0aa09c71ae 100644 --- a/dumux/freeflow/compositional/komegancmodel.hh +++ b/dumux/freeflow/compositional/komegancmodel.hh @@ -22,7 +22,7 @@ * * \brief A single-phase, multi-component k-omega model * - * \copydoc dumux/freeflow/compositional/navierstokesncmodel.hh + * For a detailed model decription see dumux/freeflow/compositional/navierstokesncmodel.hh */ #ifndef DUMUX_KOMEGA_NC_MODEL_HH diff --git a/dumux/freeflow/compositional/lowrekepsilonncmodel.hh b/dumux/freeflow/compositional/lowrekepsilonncmodel.hh index 3b5059b804..1c78eb69a8 100644 --- a/dumux/freeflow/compositional/lowrekepsilonncmodel.hh +++ b/dumux/freeflow/compositional/lowrekepsilonncmodel.hh @@ -22,7 +22,7 @@ * * \brief A single-phase, multi-component low-Re k-epsilon model * - * \copydoc dumux/freeflow/compositional/navierstokesncmodel.hh + * For a detailed model decription see dumux/freeflow/compositional/navierstokesncmodel.hh */ #ifndef DUMUX_LOWREKEPSILON_NC_MODEL_HH diff --git a/dumux/freeflow/compositional/navierstokesncmodel.hh b/dumux/freeflow/compositional/navierstokesncmodel.hh index 8879363a58..63a26feb04 100644 --- a/dumux/freeflow/compositional/navierstokesncmodel.hh +++ b/dumux/freeflow/compositional/navierstokesncmodel.hh @@ -20,9 +20,11 @@ * \file * \ingroup FreeflowNCModel * - * \copydoc dumux/freeflow/navierstokes/model.hh + * \brief A single-phase, multi-component free-flow model * - * The system is closed by a component mass/mole balance equation for each component \f$\kappa\f$: + * For an equations not specific to multiple components see dumux/freeflow/navierstokes/model.hh + * + * The multi-component system is closed by a component mass/mole balance equation for each component \f$\kappa\f$: * \f[ * \frac{\partial \left(\varrho X^\kappa\right)}{\partial t} * + \nabla \cdot \left( \varrho {\boldsymbol{v}} X^\kappa diff --git a/dumux/freeflow/compositional/oneeqncmodel.hh b/dumux/freeflow/compositional/oneeqncmodel.hh index 411124141a..01a96fcb40 100644 --- a/dumux/freeflow/compositional/oneeqncmodel.hh +++ b/dumux/freeflow/compositional/oneeqncmodel.hh @@ -22,7 +22,7 @@ * * \brief A single-phase, multi-component one-equation model * - * \copydoc dumux/freeflow/compositional/navierstokesncmodel.hh + * For a detailed model decription see dumux/freeflow/compositional/navierstokesncmodel.hh */ #ifndef DUMUX_ONEEQ_NC_MODEL_HH diff --git a/dumux/freeflow/compositional/zeroeqncmodel.hh b/dumux/freeflow/compositional/zeroeqncmodel.hh index 498f00ec59..8d0ee38b41 100644 --- a/dumux/freeflow/compositional/zeroeqncmodel.hh +++ b/dumux/freeflow/compositional/zeroeqncmodel.hh @@ -22,7 +22,7 @@ * * \brief A single-phase, multi-component Reynolds-Averaged Navier-Stokes 0-Eq. model * - * \copydoc dumux/freeflow/compositional/navierstokesncmodel.hh + * For a detailed model decription see dumux/freeflow/compositional/navierstokesncmodel.hh */ #ifndef DUMUX_ZEROEQ_NC_MODEL_HH @@ -57,6 +57,7 @@ struct ZeroEqNC { using InheritsFrom = std::tuple; }; /////////////////////////////////////////////////////////////////////////// /*! + * \ingroup FreeflowNCModel * \ingroup ZeroEqModel * \brief Traits for the Reynolds-averaged Navier-Stokes 0-Eq. model */ diff --git a/dumux/freeflow/rans/twoeq/indices.hh b/dumux/freeflow/rans/twoeq/indices.hh index 3ce7ab167f..484830c58c 100644 --- a/dumux/freeflow/rans/twoeq/indices.hh +++ b/dumux/freeflow/rans/twoeq/indices.hh @@ -18,7 +18,7 @@ *****************************************************************************/ /*! * \file - * \ingroup RANSModel + * \ingroup TwoEqModel * \copydoc Dumux::RANSTwoEqIndices */ #ifndef DUMUX_RANS_TWO_EQ_INDICES_HH @@ -30,7 +30,7 @@ namespace Dumux { // \{ /*! - * \ingroup RANSModel + * \ingroup TwoEqModel * \brief The common indices for isothermal two-equation RANS models. * * \tparam dimension The dimension of the problem diff --git a/dumux/freeflow/staggeredupwindmethods.hh b/dumux/freeflow/staggeredupwindmethods.hh index 28ff9e223f..bc1d606568 100644 --- a/dumux/freeflow/staggeredupwindmethods.hh +++ b/dumux/freeflow/staggeredupwindmethods.hh @@ -16,9 +16,11 @@ * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * *****************************************************************************/ -/** \file - * \brief This file contains different higher order methods for approximating the velocity. - */ +/*! + * \file + * \ingroup FreeflowModels + * \brief This file contains different higher order methods for approximating the velocity. + */ #ifndef DUMUX_UPWINDING_METHODS_HH #define DUMUX_UPWINDING_METHODS_HH @@ -33,21 +35,28 @@ namespace Dumux { -//! \brief Available Tvd approaches +/*! + * \ingroup FreeflowModels + * \brief Available Tvd approaches + */ enum class TvdApproach { none, uniform, li, hou }; -//! \brief Available differencing schemes +/*! + * \ingroup FreeflowModels + * \brief Available differencing schemes + */ enum class DifferencingScheme { none, vanleer, vanalbada, minmod, superbee, umist, mclimiter, wahyd }; -/** - * \brief This file contains different higher order methods for approximating the velocity. - */ +/*! + * \ingroup FreeflowModels + * \brief This file contains different higher order methods for approximating the velocity. + */ template class StaggeredUpwindMethods { diff --git a/dumux/geomechanics/elastic/indices.hh b/dumux/geomechanics/elastic/indices.hh index be7411a149..892b21d155 100644 --- a/dumux/geomechanics/elastic/indices.hh +++ b/dumux/geomechanics/elastic/indices.hh @@ -18,7 +18,7 @@ *****************************************************************************/ /*! * \file - * \ingroup Geomechanics + * \ingroup Elastic * \brief Defines the indices for the elastic model */ #ifndef DUMUX_ELASTIC_INDICES_HH @@ -27,7 +27,7 @@ namespace Dumux { /*! - * \ingroup Geomechanics + * \ingroup Elastic * \brief The indices for the linear elasticity model. */ struct ElasticIndices diff --git a/dumux/geomechanics/elastic/localresidual.hh b/dumux/geomechanics/elastic/localresidual.hh index 0c1a3eb6af..cf4bc3972c 100644 --- a/dumux/geomechanics/elastic/localresidual.hh +++ b/dumux/geomechanics/elastic/localresidual.hh @@ -18,7 +18,7 @@ *****************************************************************************/ /*! * \file - * \ingroup Geomechanics + * \ingroup Elastic * \brief Element-wise calculation of the local residual for problems * using the elastic model considering linear elasticity. */ @@ -32,7 +32,7 @@ namespace Dumux { /*! - * \ingroup Geomechanics + * \ingroup Elastic * \brief Element-wise calculation of the local residual for problems * using the elastic model considering linear elasticity. */ diff --git a/dumux/geomechanics/elastic/model.hh b/dumux/geomechanics/elastic/model.hh index 05c041dbf9..82614c943f 100644 --- a/dumux/geomechanics/elastic/model.hh +++ b/dumux/geomechanics/elastic/model.hh @@ -18,7 +18,7 @@ *****************************************************************************/ /*! * \file - * \ingroup Geomechanics + * \ingroup Elastic * \brief Defines a type tag and some properties for the elastic geomechanical model */ #ifndef DUMUX_GEOMECHANICS_ELASTIC_MODEL_HH @@ -39,7 +39,7 @@ namespace Dumux { /*! - * \ingroup Geomechanics + * \ingroup Elastic * \brief Specifies a number properties of the elastic model */ template< int dim, int numSolidComp > @@ -61,7 +61,7 @@ struct ElasticModelTraits }; /*! - * \ingroup Geomechanics + * \ingroup Elastic * \brief Traits class for the volume variables of the elastic model. * * \tparam PV The type used for primary variables diff --git a/dumux/geomechanics/elastic/volumevariables.hh b/dumux/geomechanics/elastic/volumevariables.hh index fe8836e17a..add72433a1 100644 --- a/dumux/geomechanics/elastic/volumevariables.hh +++ b/dumux/geomechanics/elastic/volumevariables.hh @@ -18,7 +18,7 @@ *****************************************************************************/ /*! * \file - * \ingroup Geomechanics + * \ingroup Elastic * \brief Quantities required by the elastic model defined on a sub-control volume. */ #ifndef DUMUX_ELASTIC_VOLUME_VARIABLES_HH @@ -33,7 +33,7 @@ namespace Dumux { /*! - * \ingroup Geomechanics + * \ingroup Elastic * \brief Contains the quantities which are constant within a * finite volume in the elastic model. * diff --git a/dumux/geomechanics/poroelastic/couplingmanager.hh b/dumux/geomechanics/poroelastic/couplingmanager.hh index 498477afc2..a49e3e79e4 100644 --- a/dumux/geomechanics/poroelastic/couplingmanager.hh +++ b/dumux/geomechanics/poroelastic/couplingmanager.hh @@ -18,7 +18,7 @@ *****************************************************************************/ /*! * \file - * \ingroup Geomechanics + * \ingroup PoroElastic * \brief Coupling manager for porous medium flow problems coupled to a poro-mechanical problem */ @@ -37,7 +37,7 @@ namespace Dumux { /*! * \file - * \ingroup Geomechanics + * \ingroup PoroElastic * \brief Coupling manager for porous medium flow problems coupled to a poro-mechanical problem * * Coupling manager for porous medium flow problems coupled to a poro-mechanical diff --git a/dumux/geomechanics/poroelastic/iofields.hh b/dumux/geomechanics/poroelastic/iofields.hh index 3127c3a21f..3d05389956 100644 --- a/dumux/geomechanics/poroelastic/iofields.hh +++ b/dumux/geomechanics/poroelastic/iofields.hh @@ -18,7 +18,7 @@ *****************************************************************************/ /*! * \file - * \ingroup Geomechanics + * \ingroup PoroElastic * \brief Adds I/O fields specific to the poro-elastic model */ #ifndef DUMUX_POROELASTIC_IO_FIELDS_HH @@ -29,7 +29,7 @@ namespace Dumux { /*! - * \ingroup Geomechanics + * \ingroup PoroElastic * \brief Adds I/O fields specific to the poro-elastic model */ class PoroElasticIOFields diff --git a/dumux/geomechanics/poroelastic/localresidual.hh b/dumux/geomechanics/poroelastic/localresidual.hh index 26f8f0c53a..9ee1188a70 100644 --- a/dumux/geomechanics/poroelastic/localresidual.hh +++ b/dumux/geomechanics/poroelastic/localresidual.hh @@ -18,7 +18,7 @@ *****************************************************************************/ /*! * \file - * \ingroup Geomechanics + * \ingroup PoroElastic * \brief Element-wise calculation of the local residual * for problems using the poroelastic model. */ @@ -31,7 +31,7 @@ namespace Dumux { /*! - * \ingroup Geomechanics + * \ingroup PoroElastic * \brief Element-wise calculation of the local residual * for problems using the poroelastic model. */ diff --git a/dumux/geomechanics/poroelastic/model.hh b/dumux/geomechanics/poroelastic/model.hh index cea6945b12..68334dd6e7 100644 --- a/dumux/geomechanics/poroelastic/model.hh +++ b/dumux/geomechanics/poroelastic/model.hh @@ -18,7 +18,7 @@ *****************************************************************************/ /*! * \file - * \ingroup Geomechanics + * \ingroup PoroElastic * \brief Defines a type tag and some properties for the poroelastic geomechanical model */ #ifndef DUMUX_GEOMECHANICS_POROELASTIC_MODEL_HH @@ -40,7 +40,7 @@ namespace Dumux { /*! - * \ingroup Geomechanics + * \ingroup PoroElastic * \brief Specifies a number properties of the poroelastic model */ template< int dim, int numSC, int numFP, int numFC > diff --git a/dumux/geomechanics/poroelastic/volumevariables.hh b/dumux/geomechanics/poroelastic/volumevariables.hh index 3b94dd5ac7..682e7fbf8b 100644 --- a/dumux/geomechanics/poroelastic/volumevariables.hh +++ b/dumux/geomechanics/poroelastic/volumevariables.hh @@ -18,7 +18,7 @@ *****************************************************************************/ /*! * \file - * \ingroup Geomechanics + * \ingroup PoroElastic * \brief Quantities required by the poroelastic model defined on a sub-control volume. */ #ifndef DUMUX_POROELASTIC_VOLUME_VARIABLES_HH @@ -29,7 +29,7 @@ namespace Dumux { /*! - * \ingroup Geomechanics + * \ingroup PoroElastic * \brief Contains the quantities which are constant within a * finite volume in the poroelastic model. * diff --git a/dumux/io/grid/gridmanager_alu.hh b/dumux/io/grid/gridmanager_alu.hh index cdf03c364e..1a6906d9ac 100644 --- a/dumux/io/grid/gridmanager_alu.hh +++ b/dumux/io/grid/gridmanager_alu.hh @@ -43,6 +43,7 @@ namespace Dumux { #if HAVE_DUNE_ALUGRID /*! + * \ingroup InputOutput * \brief Provides a grid manager for Dune ALUGrids * from information in the input file * @@ -231,6 +232,10 @@ public: } }; +/*! + * \ingroup InputOutput + * \brief Boundary flag + */ //! alu uses boundary id template class BoundaryFlag> diff --git a/dumux/io/grid/gridmanager_base.hh b/dumux/io/grid/gridmanager_base.hh index c3ee66b62f..78f56e1c99 100644 --- a/dumux/io/grid/gridmanager_base.hh +++ b/dumux/io/grid/gridmanager_base.hh @@ -55,6 +55,7 @@ namespace Dumux { /*! + * \ingroup InputOutput * \brief The grid manager (this is the class used by the user) for all supported grid managers that constructs a grid * from information in the input file and handles the data. * \note This class is specialised below for all supported grid managers. It inherits the functionality of the base class Dumux::GridManagerBase. diff --git a/dumux/io/grid/gridmanager_foam.hh b/dumux/io/grid/gridmanager_foam.hh index b591c5be6c..8ca5a56332 100644 --- a/dumux/io/grid/gridmanager_foam.hh +++ b/dumux/io/grid/gridmanager_foam.hh @@ -39,6 +39,7 @@ namespace Dumux { #if HAVE_DUNE_FOAMGRID /*! + * \ingroup InputOutput * \brief Provides a grid manager for FoamGrids * from information in the input file * @@ -95,6 +96,7 @@ public: }; /*! + * \ingroup InputOutput * \brief Provides a grid manager for FoamGrids of dim 1 * from information in the input file * diff --git a/dumux/io/grid/gridmanager_mmesh.hh b/dumux/io/grid/gridmanager_mmesh.hh index 2ef9d76547..fc69fcbe59 100644 --- a/dumux/io/grid/gridmanager_mmesh.hh +++ b/dumux/io/grid/gridmanager_mmesh.hh @@ -37,6 +37,7 @@ namespace Dumux { #if HAVE_DUNE_MMESH /*! + * \ingroup InputOutput * \brief Provides a grid manager for Dune MMesh * from information in the input file * diff --git a/dumux/io/grid/gridmanager_oned.hh b/dumux/io/grid/gridmanager_oned.hh index 0ae0026e9b..75cbdba920 100644 --- a/dumux/io/grid/gridmanager_oned.hh +++ b/dumux/io/grid/gridmanager_oned.hh @@ -34,6 +34,7 @@ namespace Dumux { /*! + * \ingroup InputOutput * \brief Provides a grid manager for OneDGrids * from information in the input file * diff --git a/dumux/io/grid/gridmanager_sp.hh b/dumux/io/grid/gridmanager_sp.hh index 95b132053c..645f306b48 100644 --- a/dumux/io/grid/gridmanager_sp.hh +++ b/dumux/io/grid/gridmanager_sp.hh @@ -39,6 +39,7 @@ namespace Dumux { #if HAVE_DUNE_SPGRID /*! + * \ingroup InputOutput * \brief Provides a grid manager for SPGrid * * The following keys are recognized: diff --git a/dumux/io/grid/gridmanager_ug.hh b/dumux/io/grid/gridmanager_ug.hh index 6ede5af6bf..a112d97c53 100644 --- a/dumux/io/grid/gridmanager_ug.hh +++ b/dumux/io/grid/gridmanager_ug.hh @@ -38,6 +38,7 @@ namespace Dumux { #if HAVE_UG /*! + * \ingroup InputOutput * \brief Provides a grid manager for UGGrids * from information in the input file * diff --git a/dumux/io/grid/gridmanager_yasp.hh b/dumux/io/grid/gridmanager_yasp.hh index 2f5d6aae94..5ffbbbc4b3 100644 --- a/dumux/io/grid/gridmanager_yasp.hh +++ b/dumux/io/grid/gridmanager_yasp.hh @@ -34,6 +34,7 @@ namespace Dumux { /*! + * \ingroup InputOutput * \brief Provides a grid manager for YaspGrids * from information in the input file * @@ -173,6 +174,7 @@ private: }; /*! + * \ingroup InputOutput * \brief Provides a grid manager for YaspGrids with different zones and grading * * All keys are expected to be in group GridParameterGroup. diff --git a/dumux/material/components/ammonia.hh b/dumux/material/components/ammonia.hh index 22ab1ea141..4f30f7a165 100644 --- a/dumux/material/components/ammonia.hh +++ b/dumux/material/components/ammonia.hh @@ -29,6 +29,10 @@ namespace Dumux { namespace Components { +/*! + * \ingroup Components + * \brief A class for the Ammonia (NH3) component properties + */ template class Ammonia : public Components::Base > diff --git a/dumux/material/components/base.hh b/dumux/material/components/base.hh index 23e84bac9c..14aa6e29a3 100644 --- a/dumux/material/components/base.hh +++ b/dumux/material/components/base.hh @@ -39,9 +39,21 @@ namespace Dumux { namespace Components { +/*! + * \ingroup Components + * \brief IsAqueous struct + */ template struct IsAqueous : public std::false_type {}; +/*! + * \ingroup Components + * \brief Base class for all components + * Components provide the thermodynamic relations for the liquid, + * gaseous and/or solid state of a single + * chemical species or a _fixed_ mixture of species. + * Fluid systems use components to compute thermodynamic quantities of phases. + */ template class Base { diff --git a/dumux/material/components/chlorideion.hh b/dumux/material/components/chlorideion.hh index 57ffb73fd7..f4981b4f76 100644 --- a/dumux/material/components/chlorideion.hh +++ b/dumux/material/components/chlorideion.hh @@ -30,6 +30,10 @@ namespace Dumux { namespace Components { +/*! + * \ingroup Components + * \brief A class for the Cl- (Chloride ion) component properties + */ template class ChlorideIon : public Components::Base > diff --git a/dumux/material/components/componenttraits.hh b/dumux/material/components/componenttraits.hh index dc6563fdcb..70d515725f 100644 --- a/dumux/material/components/componenttraits.hh +++ b/dumux/material/components/componenttraits.hh @@ -34,6 +34,10 @@ namespace Dumux { +/*! + * \ingroup Components + * \brief Component traits, i.e. information extracted from components + */ template struct ComponentTraits { diff --git a/dumux/material/components/glucose.hh b/dumux/material/components/glucose.hh index 4db90784ab..17e304537e 100644 --- a/dumux/material/components/glucose.hh +++ b/dumux/material/components/glucose.hh @@ -30,6 +30,10 @@ namespace Dumux { namespace Components { +/*! + * \ingroup Components + * \brief A class for the Glucose component properties + */ template class Glucose : public Components::Base > diff --git a/dumux/material/components/n2.hh b/dumux/material/components/n2.hh index e4f248b40d..accec3a4dc 100644 --- a/dumux/material/components/n2.hh +++ b/dumux/material/components/n2.hh @@ -35,7 +35,7 @@ namespace Dumux { namespace Components { /*! - * \ingroup Componentss + * \ingroup Components * \brief Properties of pure molecular nitrogen \f$N_2\f$. * * \tparam Scalar The type used for scalar values diff --git a/dumux/material/components/sodiumion.hh b/dumux/material/components/sodiumion.hh index 4304df7203..c588992493 100644 --- a/dumux/material/components/sodiumion.hh +++ b/dumux/material/components/sodiumion.hh @@ -30,7 +30,10 @@ namespace Dumux { namespace Components { - +/*! + * \ingroup Components + * \brief A class for the Na+ (Sodium ion) component properties + */ template class SodiumIon : public Components::Base > diff --git a/dumux/material/components/solid.hh b/dumux/material/components/solid.hh index 0581330f6b..4030fed68a 100644 --- a/dumux/material/components/solid.hh +++ b/dumux/material/components/solid.hh @@ -32,6 +32,10 @@ namespace Dumux { namespace Components { +/*! + * \ingroup Components + * \brief Interface for components that have a solid state + */ template class Solid { diff --git a/dumux/material/components/urea.hh b/dumux/material/components/urea.hh index 37d0787299..5f27451a38 100644 --- a/dumux/material/components/urea.hh +++ b/dumux/material/components/urea.hh @@ -30,6 +30,9 @@ namespace Dumux { namespace Components { +/*! \ingroup Components + * \brief A class for the Urea component properties + */ template class Urea : public Components::Base > diff --git a/dumux/material/fluidmatrixinteractions/diffusivityconstanttortuosity.hh b/dumux/material/fluidmatrixinteractions/diffusivityconstanttortuosity.hh index 774ac531c9..292bee588b 100644 --- a/dumux/material/fluidmatrixinteractions/diffusivityconstanttortuosity.hh +++ b/dumux/material/fluidmatrixinteractions/diffusivityconstanttortuosity.hh @@ -69,7 +69,8 @@ public: * on a constant tortuosity value * \param volVars The Volume Variables * \param phaseIdx the index of the phase - * \param compIdx the component index + * \param compIdxI the component index i + * \param compIdxJ the component index j */ template static Scalar effectiveDiffusionCoefficient(const VolumeVariables& volVars, diff --git a/dumux/material/fluidmatrixinteractions/diffusivitymillingtonquirk.hh b/dumux/material/fluidmatrixinteractions/diffusivitymillingtonquirk.hh index 806d9fafbc..3255db5353 100644 --- a/dumux/material/fluidmatrixinteractions/diffusivitymillingtonquirk.hh +++ b/dumux/material/fluidmatrixinteractions/diffusivitymillingtonquirk.hh @@ -75,7 +75,8 @@ public: * * \param volVars The Volume Variables * \param phaseIdx the index of the phase - * \param compIdx the component index + * \param compIdxI the component index i + * \param compIdxJ the component index j */ template static Scalar effectiveDiffusionCoefficient(const VolumeVariables& volVars, diff --git a/dumux/multidomain/facet/codimonegridadapter.hh b/dumux/multidomain/facet/codimonegridadapter.hh index fceeec3bc7..98be2a3be5 100644 --- a/dumux/multidomain/facet/codimonegridadapter.hh +++ b/dumux/multidomain/facet/codimonegridadapter.hh @@ -20,7 +20,7 @@ /*! * \file * \ingroup FacetCoupling - * \brief copydoc Dumux::CodimOneGridAdapter + * \copydoc Dumux::CodimOneGridAdapter */ #ifndef DUMUX_FACETCOUPLING_CODIM_ONE_GRID_ADAPTER_HH #define DUMUX_FACETCOUPLING_CODIM_ONE_GRID_ADAPTER_HH diff --git a/dumux/multidomain/facet/enrichmenthelper.hh b/dumux/multidomain/facet/enrichmenthelper.hh index 1e93d97016..17fefcf892 100644 --- a/dumux/multidomain/facet/enrichmenthelper.hh +++ b/dumux/multidomain/facet/enrichmenthelper.hh @@ -20,7 +20,7 @@ /*! * \file * \ingroup FacetCoupling - * \brief copydoc Dumux::VertexEnrichmentHelper + * \copydoc Dumux::VertexEnrichmentHelper */ #ifndef DUMUX_VERTEX_ENRICHMENT_HELPER_HH #define DUMUX_VERTEX_ENRICHMENT_HELPER_HH diff --git a/dumux/multidomain/facet/vertexmapper.hh b/dumux/multidomain/facet/vertexmapper.hh index c3afdf141e..5b67f39076 100644 --- a/dumux/multidomain/facet/vertexmapper.hh +++ b/dumux/multidomain/facet/vertexmapper.hh @@ -20,7 +20,7 @@ /*! * \file * \ingroup FacetCoupling - * \brief copydoc Dumux::EnrichedVertexDofMapper + * \copydoc Dumux::EnrichedVertexDofMapper */ #ifndef DUMUX_ENRICHED_VERTEX_DOF_MAPPER_HH #define DUMUX_ENRICHED_VERTEX_DOF_MAPPER_HH diff --git a/dumux/nonlinear/findscalarroot.hh b/dumux/nonlinear/findscalarroot.hh index 9eff421612..20bb5c65d1 100644 --- a/dumux/nonlinear/findscalarroot.hh +++ b/dumux/nonlinear/findscalarroot.hh @@ -18,7 +18,7 @@ *****************************************************************************/ /*! * \file - * \ingroup Common + * \ingroup Nonlinear * \brief Root finding algorithms for scalar functions */ #ifndef DUMUX_COMMON_SCALAR_ROOT_FINDING_HH @@ -35,7 +35,7 @@ namespace Dumux { /*! - * \ingroup Common + * \ingroup Nonlinear * \brief Newton's root finding algorithm for scalar functions (secant method) * \param xOld initial guess * \param residual Residual function @@ -76,7 +76,7 @@ Scalar findScalarRootNewton(Scalar xOld, const ResFunc& residual, const DerivFun } /*! - * \ingroup Common + * \ingroup Nonlinear * \brief Newton's root finding algorithm for scalar functions (secant method) * \note The derivative is numerically computed. If the derivative is know use signature with derivative function. * \param xOld initial guess @@ -95,7 +95,7 @@ Scalar findScalarRootNewton(Scalar xOld, const ResFunc& residual, } /*! - * \ingroup Common + * \ingroup Nonlinear * \brief Brent's root finding algorithm for scalar functions * \note Modified from pseudo-code on wikipedia: https://en.wikipedia.org/wiki/Brent%27s_method * \note See also R.P. Brent "An algorithm with guaranteed convergence for finding a zero of a function", The Computer Journal (1971). diff --git a/dumux/parallel/vectorcommdatahandle.hh b/dumux/parallel/vectorcommdatahandle.hh index e2bc4c4f34..74122a6ec7 100644 --- a/dumux/parallel/vectorcommdatahandle.hh +++ b/dumux/parallel/vectorcommdatahandle.hh @@ -18,7 +18,7 @@ *****************************************************************************/ /*! * \file - * \ingroup Linear + * \ingroup Parallel * \brief Contains a class to exchange entries of a vector */ #ifndef DUMUX_VECTOR_COMM_DATA_HANDLE_HH @@ -69,7 +69,7 @@ namespace Detail { } // end namespace Detail /*! - * \ingroup Linear + * \ingroup Parallel * \brief A data handle class to exchange entries of a vector */ template diff --git a/dumux/parallel/vertexhandles.hh b/dumux/parallel/vertexhandles.hh index 0faa96649f..e6b014acca 100644 --- a/dumux/parallel/vertexhandles.hh +++ b/dumux/parallel/vertexhandles.hh @@ -18,7 +18,7 @@ *****************************************************************************/ /*! * \file - * \ingroup Assembly + * \ingroup Parallel * \brief Provides data handles for parallel communication which operate on vertices * \note This is useful for schemes with degrees of freedom on vertices (box scheme) */ diff --git a/dumux/porousmediumflow/2p/boxmaterialinterfaceparams.hh b/dumux/porousmediumflow/2p/boxmaterialinterfaceparams.hh index 63dad808af..5dcb9055d4 100644 --- a/dumux/porousmediumflow/2p/boxmaterialinterfaceparams.hh +++ b/dumux/porousmediumflow/2p/boxmaterialinterfaceparams.hh @@ -19,7 +19,7 @@ /*! * \file * \ingroup TwoPModel - * \brief copydoc Dumux::BoxMaterialInterfaceParams + * \copydoc Dumux::BoxMaterialInterfaceParams */ #ifndef DUMUX_2P_BOX_MATERIAL_INTERFACE_PARAMS_HH diff --git a/dumux/porousmediumflow/2p/saturationreconstruction.hh b/dumux/porousmediumflow/2p/saturationreconstruction.hh index 07365f6fe7..7398f0d6ce 100644 --- a/dumux/porousmediumflow/2p/saturationreconstruction.hh +++ b/dumux/porousmediumflow/2p/saturationreconstruction.hh @@ -19,7 +19,7 @@ /*! * \file * \ingroup TwoPModel - * \brief copydoc Dumux::TwoPScvSaturationReconstruction + * \copydoc Dumux::TwoPScvSaturationReconstruction */ #ifndef DUMUX_2P_SCV_SATURATION_RECONSTRUCTION_HH diff --git a/dumux/porousmediumflow/2p2c/sequential/celldatamultiphysics.hh b/dumux/porousmediumflow/2p2c/sequential/celldatamultiphysics.hh index 5fc987ea18..3d0d06a9a3 100644 --- a/dumux/porousmediumflow/2p2c/sequential/celldatamultiphysics.hh +++ b/dumux/porousmediumflow/2p2c/sequential/celldatamultiphysics.hh @@ -95,7 +95,7 @@ public: else return this->fluidState_->pressure(phaseIdx); } - //! \copydoc CellData2P2C::setPressure() + //! DOC ME! void setPressure(int phaseIdx, Scalar value) { if(fluidStateType_ == simple) diff --git a/dumux/porousmediumflow/mpnc/model.hh b/dumux/porousmediumflow/mpnc/model.hh index 4d2ed7d63e..0f3e397778 100644 --- a/dumux/porousmediumflow/mpnc/model.hh +++ b/dumux/porousmediumflow/mpnc/model.hh @@ -119,10 +119,6 @@ #include "localresidual.hh" #include "pressureformulation.hh" -/*! - * \ingroup MPNCModel - * \brief Defines the properties required for the MpNc fully implicit model. - */ namespace Dumux { diff --git a/test/multidomain/boundary/stokesdarcy/1p_1p/convergencetest/problem_darcy.hh b/test/multidomain/boundary/stokesdarcy/1p_1p/convergencetest/problem_darcy.hh index 2b92475b44..8312e44e9b 100644 --- a/test/multidomain/boundary/stokesdarcy/1p_1p/convergencetest/problem_darcy.hh +++ b/test/multidomain/boundary/stokesdarcy/1p_1p/convergencetest/problem_darcy.hh @@ -221,10 +221,7 @@ public: * \brief Evaluates the source term for all phases within a given * sub control volume. * - * \param element The element for which the source term is set - * \param fvGeometry The fvGeometry - * \param elemVolVars The element volume variables - * \param scv The sub control volume + * \param globalPos The global position */ NumEqVector sourceAtPos(const GlobalPosition& globalPos) const { @@ -260,7 +257,6 @@ public: * \brief Returns the analytical solution of the problem at a given position. * * \param globalPos The global position - * \param time The current simulation time */ auto analyticalSolution(const GlobalPosition& globalPos) const { diff --git a/test/multidomain/boundary/stokesdarcy/1p_1p/convergencetest/problem_stokes.hh b/test/multidomain/boundary/stokesdarcy/1p_1p/convergencetest/problem_stokes.hh index 3a02f723dd..25cd89a662 100644 --- a/test/multidomain/boundary/stokesdarcy/1p_1p/convergencetest/problem_stokes.hh +++ b/test/multidomain/boundary/stokesdarcy/1p_1p/convergencetest/problem_stokes.hh @@ -266,7 +266,6 @@ public: * \brief Returns the analytical solution of the problem at a given position. * * \param globalPos The global position - * \param time The current simulation time */ PrimaryVariables analyticalSolution(const GlobalPosition& globalPos) const { diff --git a/test/porousmediumflow/2p/implicit/adaptive/main.cc b/test/porousmediumflow/2p/implicit/adaptive/main.cc index 2e9778f507..44512751dd 100644 --- a/test/porousmediumflow/2p/implicit/adaptive/main.cc +++ b/test/porousmediumflow/2p/implicit/adaptive/main.cc @@ -56,12 +56,12 @@ #include #include -//! Use the incompressible or point source problem for this adaptive test +// Use the incompressible or point source problem for this adaptive test #include #include "pointsourceproblem.hh" #include "problem.hh" -//! Type tags for the adaptive versions of the two-phase incompressible problem +// Type tags for the adaptive versions of the two-phase incompressible problem namespace Dumux { namespace Properties { //! Type Tags for the adaptive tests diff --git a/test/porousmediumflow/2p/implicit/boxdfm/spatialparams.hh b/test/porousmediumflow/2p/implicit/boxdfm/spatialparams.hh index 21e983c73e..5d0455254f 100644 --- a/test/porousmediumflow/2p/implicit/boxdfm/spatialparams.hh +++ b/test/porousmediumflow/2p/implicit/boxdfm/spatialparams.hh @@ -17,6 +17,7 @@ * along with this program. If not, see . * *****************************************************************************/ /*! + * \file * \ingroup TwoPTests * \brief The spatial params for the incompressible 2p test. */ diff --git a/test/porousmediumflow/2p/implicit/cornerpoint/spatialparams.hh b/test/porousmediumflow/2p/implicit/cornerpoint/spatialparams.hh index e01602f206..22d56066ea 100644 --- a/test/porousmediumflow/2p/implicit/cornerpoint/spatialparams.hh +++ b/test/porousmediumflow/2p/implicit/cornerpoint/spatialparams.hh @@ -17,6 +17,7 @@ * along with this program. If not, see . * *****************************************************************************/ /*! + * \file * \ingroup TwoPTests * \brief The spatial params for the 2p cornerpoint test. */ diff --git a/test/porousmediumflow/2p/implicit/incompressible/spatialparams.hh b/test/porousmediumflow/2p/implicit/incompressible/spatialparams.hh index d0912b6fee..1232ca5d2b 100644 --- a/test/porousmediumflow/2p/implicit/incompressible/spatialparams.hh +++ b/test/porousmediumflow/2p/implicit/incompressible/spatialparams.hh @@ -17,6 +17,7 @@ * along with this program. If not, see . * *****************************************************************************/ /*! + * \file * \ingroup TwoPTests * \brief The spatial params for the incompressible 2p test. */ diff --git a/test/porousmediumflow/3p/implicit/convection/problem.hh b/test/porousmediumflow/3p/implicit/convection/problem.hh index 4ec0fbc1cd..d712c39d1d 100644 --- a/test/porousmediumflow/3p/implicit/convection/problem.hh +++ b/test/porousmediumflow/3p/implicit/convection/problem.hh @@ -38,7 +38,7 @@ #include #include -#include "../conduction/spatialparams.hh" //! reuse the conduction spatialParams +#include "../conduction/spatialparams.hh" // reuse the conduction spatialParams namespace Dumux { /** diff --git a/test/porousmediumflow/tracer/multiphase/problem.hh b/test/porousmediumflow/tracer/multiphase/problem.hh index 09cb2bf7ee..3188361b54 100644 --- a/test/porousmediumflow/tracer/multiphase/problem.hh +++ b/test/porousmediumflow/tracer/multiphase/problem.hh @@ -104,6 +104,7 @@ public: * \param element The finite element * \param fvGeometry The finite-volume geometry * \param elemVolVars All volume variables for the element + * \param elemFluxVarsCache Flux variables caches for all faces in stencil * \param scvf The sub control volume face * * Negative values mean influx. -- GitLab From 5ce482f13c9c6adf195362e0a28e02f8d12215fb Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Tue, 14 Apr 2020 10:10:48 +0000 Subject: [PATCH 02/57] Merge branch 'fix/headercheck_3.2' into 'master' [cleanup] fix headercheck errors See merge request dumux-repositories/dumux!1970 (cherry picked from commit edd814416baef3be01fdb54507c04b51718d54f5) c396f0c5 [cleanup] fix headercheck errors --- dumux/common/pdesolver.hh | 2 ++ dumux/linear/preconditioners.hh | 1 + test/multidomain/facet/1pnc_1pnc/properties_bulk.hh | 4 ++++ test/multidomain/facet/1pnc_1pnc/properties_facet.hh | 6 +++++- 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/dumux/common/pdesolver.hh b/dumux/common/pdesolver.hh index c86d1f5ed7..9b02b124bc 100644 --- a/dumux/common/pdesolver.hh +++ b/dumux/common/pdesolver.hh @@ -26,6 +26,8 @@ #include +#include + #include #include diff --git a/dumux/linear/preconditioners.hh b/dumux/linear/preconditioners.hh index c0fc457a07..bbfa48cad7 100644 --- a/dumux/linear/preconditioners.hh +++ b/dumux/linear/preconditioners.hh @@ -28,6 +28,7 @@ #include #include #include +#include #include #if HAVE_UMFPACK diff --git a/test/multidomain/facet/1pnc_1pnc/properties_bulk.hh b/test/multidomain/facet/1pnc_1pnc/properties_bulk.hh index 8ec238392f..b483c0cb29 100644 --- a/test/multidomain/facet/1pnc_1pnc/properties_bulk.hh +++ b/test/multidomain/facet/1pnc_1pnc/properties_bulk.hh @@ -24,6 +24,10 @@ #ifndef DUMUX_TEST_FACETCOUPLING_ONEPNC_BULK_PROPERTIES_HH #define DUMUX_TEST_FACETCOUPLING_ONEPNC_BULK_PROPERTIES_HH +#ifndef DIMWORLD +#define DIMWORLD 2 +#endif + #include #include diff --git a/test/multidomain/facet/1pnc_1pnc/properties_facet.hh b/test/multidomain/facet/1pnc_1pnc/properties_facet.hh index 9faac2df95..53d3b195f7 100644 --- a/test/multidomain/facet/1pnc_1pnc/properties_facet.hh +++ b/test/multidomain/facet/1pnc_1pnc/properties_facet.hh @@ -24,6 +24,10 @@ #ifndef DUMUX_TEST_FACETCOUPLING_ONEPNC_FACET_PROPERTIES_HH #define DUMUX_TEST_FACETCOUPLING_ONEPNC_FACET_PROPERTIES_HH +#ifndef DIMWORLD +#define DIMWORLD 2 +#endif + #include #include @@ -31,7 +35,7 @@ #include #include -#include +#include #include "problem_facet.hh" #include "spatialparams.hh" -- GitLab From 372b85c436fd2081825d611a8f92fc3484e2473c Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Thu, 16 Apr 2020 08:26:15 +0000 Subject: [PATCH 03/57] Merge branch 'fix/parameters-include' into 'master' [common] Fix missing include in parameters See merge request dumux-repositories/dumux!1987 (cherry picked from commit 2a9a2dfef075df785100bed7e95a85dbdd7edbac) 9b4c2f53 [common] Fix missing include in parameters --- dumux/common/parameters.hh | 1 + 1 file changed, 1 insertion(+) diff --git a/dumux/common/parameters.hh b/dumux/common/parameters.hh index a3949028bc..9dee178993 100644 --- a/dumux/common/parameters.hh +++ b/dumux/common/parameters.hh @@ -29,6 +29,7 @@ #include #include #include +#include #include #include -- GitLab From 61b3ad7cb7609bc545b953325c8b7cb98df52add Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Sat, 18 Apr 2020 20:56:16 +0000 Subject: [PATCH 04/57] Merge branch 'feature/test-runtest-script-python3' into 'master' [test] Update shebang to python3 See merge request dumux-repositories/dumux!1998 (cherry picked from commit bc2e7c85368605adf19dd09ebd684708a01a73aa) e2c5e645 [test] Update shebang to python3 --- bin/testing/runtest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/testing/runtest.py b/bin/testing/runtest.py index 4f1b301b78..b1bc1eabb6 100755 --- a/bin/testing/runtest.py +++ b/bin/testing/runtest.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import argparse import shlex import os, sys -- GitLab From 9f2e74b934272abd012c110d27d41b07729d101f Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Sun, 19 Apr 2020 09:38:29 +0000 Subject: [PATCH 05/57] Merge branch 'feature/test-remove-python2' into 'master' [test] Remove Python 2/3 compatibility See merge request dumux-repositories/dumux!2000 (cherry picked from commit 962675237906c5c67ecc7703508df565e28bad20) 4517ddb2 [test] Remove Python 2/3 compatibility --- bin/testing/fuzzycomparevtu.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/bin/testing/fuzzycomparevtu.py b/bin/testing/fuzzycomparevtu.py index 44aa601585..7241b08c27 100644 --- a/bin/testing/fuzzycomparevtu.py +++ b/bin/testing/fuzzycomparevtu.py @@ -5,16 +5,12 @@ for all VTK style formats like VTK files. Fuzzy compares numbers by using absolute and/or relative difference comparison. """ -from __future__ import print_function -from __future__ import absolute_import import argparse import xml.etree.ElementTree as ET from operator import attrgetter, itemgetter import json import sys import math -from six.moves import range -from six.moves import zip import os import re import glob -- GitLab From f96ad774215778d6f843f1287f56a35e9c70d59e Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Mon, 20 Apr 2020 09:27:32 +0200 Subject: [PATCH 06/57] [vtkfunction] Fix compiler warning about missing `override` This has been already fixed on master in !1971. --- dumux/io/vtkfunction.hh | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/dumux/io/vtkfunction.hh b/dumux/io/vtkfunction.hh index 6da7340f7d..a4c4a5ae07 100644 --- a/dumux/io/vtkfunction.hh +++ b/dumux/io/vtkfunction.hh @@ -54,18 +54,18 @@ struct VectorP0VTKFunction : Dune::VTKFunction public: //! return number of components - virtual int ncomps() const { return nComps_; } + int ncomps() const final { return nComps_; } //! get name - virtual std::string name() const { return name_; } + std::string name() const final { return name_; } //! evaluate - virtual double evaluate(int mycomp, const Element& e, const Dune::FieldVector&) const + double evaluate(int mycomp, const Element& e, const Dune::FieldVector&) const final { return accessChooser_(mycomp, mapper_.index(e), IsIndexable()); } #if DUNE_VERSION_GTE(DUNE_GRID, 2, 7) //! get output precision for the field - Dumux::Vtk::Precision precision() const override + Dumux::Vtk::Precision precision() const final { return precision_; } #endif @@ -123,13 +123,13 @@ struct VectorP1VTKFunction : Dune::VTKFunction public: //! return number of components - virtual int ncomps() const { return nComps_; } + int ncomps() const final { return nComps_; } //! get name - virtual std::string name() const { return name_; } + std::string name() const final { return name_; } //! evaluate - virtual double evaluate(int mycomp, const Element& e, const Dune::FieldVector& xi) const + double evaluate(int mycomp, const Element& e, const Dune::FieldVector& xi) const final { const unsigned int dim = Element::mydimension; const unsigned int nVertices = e.subEntities(dim); @@ -145,7 +145,7 @@ public: #if DUNE_VERSION_GTE(DUNE_GRID, 2, 7) //! get output precision for the field - Dumux::Vtk::Precision precision() const override + Dumux::Vtk::Precision precision() const final { return precision_; } #endif @@ -207,13 +207,13 @@ struct VectorP1NonConformingVTKFunction : Dune::VTKFunction public: //! return number of components - virtual int ncomps() const { return nComps_; } + int ncomps() const final { return nComps_; } //! get name - virtual std::string name() const { return name_; } + std::string name() const final { return name_; } //! evaluate - virtual double evaluate(int mycomp, const Element& e, const Dune::FieldVector& xi) const + double evaluate(int mycomp, const Element& e, const Dune::FieldVector& xi) const final { const unsigned int dim = Element::mydimension; const unsigned int nVertices = e.subEntities(dim); @@ -229,7 +229,7 @@ public: #if DUNE_VERSION_GTE(DUNE_GRID, 2, 7) //! get output precision for the field - Dumux::Vtk::Precision precision() const override + Dumux::Vtk::Precision precision() const final { return precision_; } #endif @@ -307,16 +307,14 @@ public: DUNE_THROW(Dune::NotImplemented, "Only element or vertex quantities allowed."); } - virtual ~Field() {} - //! return the name of this field - virtual std::string name () const { return field_->name(); } + std::string name () const { return field_->name(); } //! return the number of components of this field - virtual int ncomps() const { return field_->ncomps(); } + int ncomps() const { return field_->ncomps(); } //! return the precision of this field - virtual Dumux::Vtk::Precision precision() const + Dumux::Vtk::Precision precision() const { #if DUNE_VERSION_LT(DUNE_GRID, 2, 7) return Dumux::Vtk::Precision::float32; @@ -329,9 +327,9 @@ public: int codim() const { return codim_; } //! element-local evaluation of the field - virtual double evaluate(int mycomp, - const Element &element, - const Dune::FieldVector< ctype, dim > &xi) const + double evaluate(int mycomp, + const Element &element, + const Dune::FieldVector< ctype, dim > &xi) const { return field_->evaluate(mycomp, element, xi); } //! returns the underlying vtk function -- GitLab From 9734b519df888d73632dc8c482e3652992dd07a6 Mon Sep 17 00:00:00 2001 From: Ned Coltman Date: Mon, 20 Apr 2020 13:36:06 +0000 Subject: [PATCH 07/57] Merge branch 'cleanup/docu-handbook' into 'master' update handbook for 3.2 See merge request dumux-repositories/dumux!1901 (cherry picked from commit 32db16a914646ef6064dc6547e4e3dbb5307c6d1) 685278de [Handbook] add date in title page of handbook ca3e2217 [Handbook] Add section on Backwards-compatibility c26e125b [Handbook] change references from 3.1 to 3.2 and update dune versions b901ef88 [Handbook] update section on restart with double precision bca81cef [cleanup][Handbook] remove list of examples and add url to example list --- doc/handbook/0_dumux-handbook.tex | 3 +- doc/handbook/1_introduction.tex | 8 ++--- doc/handbook/3_detailedinstall.tex | 46 +++++++++++++++++---------- doc/handbook/4_course.tex | 4 +-- doc/handbook/4_examples.tex | 19 +++++------ doc/handbook/5_restartsimulations.tex | 3 +- doc/handbook/6_stepsofasimulation.tex | 2 +- 7 files changed, 50 insertions(+), 35 deletions(-) diff --git a/doc/handbook/0_dumux-handbook.tex b/doc/handbook/0_dumux-handbook.tex index 2b3ed2d412..ecc2362996 100644 --- a/doc/handbook/0_dumux-handbook.tex +++ b/doc/handbook/0_dumux-handbook.tex @@ -87,7 +87,8 @@ \author{} -\date{Version \DumuxVersion} +\date{Version \DumuxVersion, \\ +Handbook version from \today} \publishers{% \vspace{10mm} diff --git a/doc/handbook/1_introduction.tex b/doc/handbook/1_introduction.tex index 4dfd1ed2d8..e661e5a062 100644 --- a/doc/handbook/1_introduction.tex +++ b/doc/handbook/1_introduction.tex @@ -74,11 +74,11 @@ spatial and temporal discretization schemes as well as nonlinear solvers, to general concepts for model coupling. Moreover, \Dumux includes ready to use numerical models and a few example applications. -This is the handbook to a new minor version update of \Dumux: version 3.1. -The release contains improvements and new features compared to the 3.0 version. -The update is backwards compatible with the last release 3.0. +This is the handbook to a new minor version update of \Dumux: version 3.2. +The release contains improvements and new features compared to the 3.1 version. +The update is backwards compatible with the last release 3.1. To facilitate the transition for our users, we have created a changelog -helping to update programs from version 3.0 to version 3.1, and giving an overview over new capabilities. +helping to update programs from version 3.1 to version 3.2, and giving an overview over new capabilities. It is available online: \url{https://git.iws.uni-stuttgart.de/dumux-repositories/dumux/blob/master/CHANGELOG.md}. We highly recommend all our users to transition with us to the most recent version of \Dumux diff --git a/doc/handbook/3_detailedinstall.tex b/doc/handbook/3_detailedinstall.tex index e45ef829b1..0328e42a96 100644 --- a/doc/handbook/3_detailedinstall.tex +++ b/doc/handbook/3_detailedinstall.tex @@ -15,8 +15,8 @@ Details regarding the installation of \Dune are provided on the \Dune website \c \section{Obtaining Source Code for \Dune and \Dumux} \label{sc:ObtainingSourceCode} The \Dumux release and trunk (developer tree) are based on the most recent -\Dune release 2.6, comprising the core modules \texttt{dune-common}, \texttt{dune-geometry}, -\texttt{dune-grid}, \texttt{dune-istl} and \texttt{dune-localfunctions}. +\Dune release 2.7, comprising the core modules \texttt{dune-common}, \texttt{dune-geometry}, +\texttt{dune-grid}, \texttt{dune-istl} and \texttt{dune-localfunctions}. We also support the previous \Dune release 2.6. For working with \Dumux, these modules are required. All \Dune modules, including the \Dumux module, get extracted into a common root directory, as it is done in an ordinary \Dune installation. @@ -42,7 +42,7 @@ The slightly old-fashionedly named tape-archive-file, shortly named tar file or tarball, is a common file format for distributing collections of files contained within these archives. The extraction from the tar files is done as follows: -Download the tarballs from the respective \Dune (version 2.6) and \Dumux websites +Download the tarballs from the respective \Dune (version 2.6 or version 2.7) and \Dumux websites to a certain folder in your file system. Create the common root directory, named \texttt{DUMUX} in the example below. Then extract the content of the tar files, e.\,g. with the command-line program @@ -55,12 +55,12 @@ After extraction, the actual name of the dumux subdirectory is \texttt{dumux-\Du \begin{lstlisting}[style=Bash] $ mkdir DUMUX $ cd DUMUX -$ tar xzvf path_to_tarball_of/dune-common-2.6.0.tar.gz -$ tar xzvf path_to_tarball_of/dune-geometry-2.6.0.tar.gz -$ tar xzvf path_to_tarball_of/dune-grid-2.6.0.tar.gz -$ tar xzvf path_to_tarball_of/dune-istl-2.6.0.tar.gz -$ tar xzvf path_to_tarball_of/dune-localfunctions-2.6.0.tar.gz -$ tar xzvf path_to_tarball_of/dumux-3.1.tar.gz +$ tar xzvf path_to_tarball_of/dune-common-2.7.0.tar.gz +$ tar xzvf path_to_tarball_of/dune-geometry-2.7.0.tar.gz +$ tar xzvf path_to_tarball_of/dune-grid-2.7.0.tar.gz +$ tar xzvf path_to_tarball_of/dune-istl-2.7.0.tar.gz +$ tar xzvf path_to_tarball_of/dune-localfunctions-2.7.0.tar.gz +$ tar xzvf path_to_tarball_of/dumux-3.2.tar.gz \end{lstlisting} Furthermore, if you wish to install the optional \Dune Grid-Howto which provides a tutorial @@ -87,17 +87,17 @@ one for \Dune and one for \Dumux. \begin{lstlisting}[style=Bash] $ mkdir DUMUX $ cd DUMUX -$ git clone -b releases/2.6 https://gitlab.dune-project.org/core/dune-common.git -$ git clone -b releases/2.6 https://gitlab.dune-project.org/core/dune-geometry.git -$ git clone -b releases/2.6 https://gitlab.dune-project.org/core/dune-grid.git -$ git clone -b releases/2.6 https://gitlab.dune-project.org/core/dune-istl.git -$ git clone -b releases/2.6 https://gitlab.dune-project.org/core/dune-localfunctions.git -$ git clone -b releases/3.1 https://git.iws.uni-stuttgart.de/dumux-repositories/dumux.git +$ git clone -b releases/2.7 https://gitlab.dune-project.org/core/dune-common.git +$ git clone -b releases/2.7 https://gitlab.dune-project.org/core/dune-geometry.git +$ git clone -b releases/2.7 https://gitlab.dune-project.org/core/dune-grid.git +$ git clone -b releases/2.7 https://gitlab.dune-project.org/core/dune-istl.git +$ git clone -b releases/2.7 https://gitlab.dune-project.org/core/dune-localfunctions.git +$ git clone -b releases/3.2 https://git.iws.uni-stuttgart.de/dumux-repositories/dumux.git \end{lstlisting} The newest and maybe unstable developments of \Dune and \Dumux are also provided in these repositories and can be found in the \emph{master} branch. Please check the \Dune website \cite{DUNE-HP} for further information on the \Dune development. We always try to keep up with the latest developments of \Dune. -However, the current \Dumux release is based on the stable 2.6 release and it might not compile without further adaptations using the newest versions of \Dune. +However, the current \Dumux release is based on the stable 2.7 release and it might not compile without further adaptations using the newest versions of \Dune. Furthermore, if you wish to install the optional \Dune Grid-Howto which provides a tutorial on the Dune grid interface, act similar. @@ -303,3 +303,17 @@ depending on which modules of \Dune and which external libraries you use. Intel \Cplusplus compiler. C and Fortran compilers are needed for some external libraries. As code of different compilers is linked together, they have to be be compatible with each other. \end{itemize} + +\section{Backwards Compatibility} +\label{sec:backwardscompatibility} + +Dumux Releases are split into major (e.g. 2.0, 3.0) and minor (e.g. 3.1, 3.2, 3.3) releases. +Major releases are not required to maintain backwards compatibility, +but would provide a detailed guide on how to update dependent modules. +For each minor release, maintaining backwards compatibility is strongly encouraged and recommended. + +Maintaining backwards compatibility means for all changes made to the dumux master, each tests and all dumux dependent modules should still compile. In addition, the user should be warned at compile time of any relevant interface changes. This can be done by deprecating the old method with a deprecation message and forwarding it to the new method. Examples of this are shown in the \href{https://git.iws.uni-stuttgart.de/dumux-repositories/dumux/blob/master/CONTRIBUTING.md}{contribution guide}. Each of these deprecation messages should also include the release in which the interface will be removed, and all changes should be documented thoroughly in the \href{https://git.iws.uni-stuttgart.de/dumux-repositories/dumux/-/blob/master/CHANGELOG.md}{changelog.md}. + +Despite the goal of maintaining backwards compatibility across minor releases, +for more complicated changes, this is to be decided upon on a case-by-case basis, due to limited developer resources. +In the case that implementing full backwards compatibility for an update is not feasible, or would require unreasonable resources, the degree of backwards compatibility be decided by a vote in one of the monthly core developer meetings. diff --git a/doc/handbook/4_course.tex b/doc/handbook/4_course.tex index 0d6c3df8f1..17016c5bbc 100644 --- a/doc/handbook/4_course.tex +++ b/doc/handbook/4_course.tex @@ -21,12 +21,12 @@ The \Dumux course material is available online: In order to download this repository, which acts as an additional module to the \Dumux base, you can download an installation script with the following command: \begin{lstlisting}[style=Bash] -$ wget https://git.iws.uni-stuttgart.de/dumux-repositories/dumux-course/raw/releases/3.1/scripts/install.sh +$ wget https://git.iws.uni-stuttgart.de/dumux-repositories/dumux-course/raw/releases/3.2/scripts/install.sh \end{lstlisting} This script will install \texttt{dumux}, it's Dune dependencies, and the \texttt{dumux-course} repository. Within the directory \texttt{dumux-course} there are a series of exercises and slides describing the previously described examples. \par % The \Dumux course will be updated with each \Dumux release. -The above script will download the correct version (\textbf{releases/3.1}) of both +The above script will download the correct version (\textbf{releases/3.2}) of both the \texttt{dumux} and \texttt{dumux-course} module. diff --git a/doc/handbook/4_examples.tex b/doc/handbook/4_examples.tex index 24a8f08299..9ebb322b9b 100644 --- a/doc/handbook/4_examples.tex +++ b/doc/handbook/4_examples.tex @@ -1,10 +1,11 @@ \section{Experience \Dumux by reading -- the \Dumux examples} -As an alternative to going through exercises, you can have a look at our well-documented \Dumux examples. They show how to apply \Dumux to typical physical problems. In the \texttt{README.md} files, the setup is explained, the used code is presented and documented and images resulting from the simulation are included. The \texttt{README.md} files are located directly in the subfolders of \texttt{examples} and can be displayed by web browsers. - -We currently have the examples -\begin{itemize} - \item \texttt{1ptracer}: one-phase groundwater flow including a tracer - \item \texttt{2pinfiltration}: two-phase infiltration problem - \item \texttt{shallowwaterfriction}: steady subcritical shallow water flow including bottom friction -\end{itemize} -The number of examples is continuously growing. \ No newline at end of file +As an alternative to going through exercises, you can have a look at our well-documented \Dumux examples in \Dumux's \texttt{examples} directory. They show how to apply \Dumux models to typical physical problems. In the \texttt{README.md} files, the setup is explained, the used code is presented and documented and images resulting from the simulation are included. The \texttt{README.md} files are located directly in the subfolders of \texttt{examples} and can be displayed by web browsers. The number of examples is continuously growing. +You can find a list of current examples under: \url{https://git.iws.uni-stuttgart.de/dumux-repositories/dumux/-/tree/releases/3.2/examples}. +%We currently have the following examples: +%\begin{itemize} +% \item \texttt{1ptracer}: one-phase groundwater flow including a tracer +% \item \texttt{2pinfiltration}: two-phase infiltration problem +% \item \texttt{shallowwaterfriction}: steady subcritical shallow water flow including bottom friction +% \item \texttt{freeflowchannel}: A free-flow problem for flow between two plates +% \item \texttt{1protationsymmetry}: A 1D rotation-symmetric problem single phase flow problem with a convergence test. +%\end{itemize} diff --git a/doc/handbook/5_restartsimulations.tex b/doc/handbook/5_restartsimulations.tex index 80b769da42..3eda5d6244 100644 --- a/doc/handbook/5_restartsimulations.tex +++ b/doc/handbook/5_restartsimulations.tex @@ -11,8 +11,7 @@ a restart using \texttt{BackupRestoreFacility} with plain Dune. For VTK files the output can be read with the free function \texttt{loadSolution}. Grids can be read with the \texttt{Dumux::VTKReader} or you can simply recreate the grid as you did in the first simulation run. -Unfortunately, writing double-precision floating point numbers to VTK files is only available with Dune master (will be in 2.7). -That's why we currently only support single precision restart, meaning some information will be lost if you are computing +Writing double-precision floating point numbers to VTK files is available with the newest \Dune release 2.7. If you are using that version, it is now possible to specify output precision in the input file using \texttt{Vtk.Precision} followed by either \texttt{Float32}, \texttt{Float64}, \texttt{UInt32}, \texttt{UInt8} or \texttt{Int32}. \texttt{Float32} is set as the default. We especially advice the use of \texttt{Float64} when working with restart files. If you are working with the \Dune release 2.6 we only support single precision restart, meaning some information will be lost if you are computing in double precision. The restart capabilities will hopefully be improved in future versions of \Dumux-3. diff --git a/doc/handbook/6_stepsofasimulation.tex b/doc/handbook/6_stepsofasimulation.tex index c078583155..a820e5f73d 100644 --- a/doc/handbook/6_stepsofasimulation.tex +++ b/doc/handbook/6_stepsofasimulation.tex @@ -61,4 +61,4 @@ solution scheme is illustrated down to the element level. \subsection{Structure -- by Implementation} A possible starting point to understand how the above mentioned algorithm is implemented within \Dumux, is the example main file -\url{https://git.iws.uni-stuttgart.de/dumux-repositories/dumux-course/releases/3.1/exercises/exercise-mainfile/exercise_1p_a.cc} +\url{https://git.iws.uni-stuttgart.de/dumux-repositories/dumux-course/releases/3.2/exercises/exercise-mainfile/exercise_1p_a.cc} -- GitLab From 7e13c0fdef7c8bdd2d1cf881b916290f92cd5935 Mon Sep 17 00:00:00 2001 From: Kilian Weishaupt Date: Mon, 20 Apr 2020 15:12:16 +0200 Subject: [PATCH 08/57] [linear][istlsolverfactory] Adapt for releases/3.2 and dune-2.7 * preconditioners: fix registry and adapt to work with dune-2.7 * istlsolverfactorybackend: change version and make compile with dune-2.7 * linearsolverparameters: include AMG.MaxLevel as default * sincos test: make compile with dune-2.7 * istlsoverregistry: remove superfluous version check --- dumux/linear/istlsolverfactorybackend.hh | 10 ++++++++-- dumux/linear/istlsolverregistry.hh | 4 ---- dumux/linear/linearsolverparameters.hh | 1 + dumux/linear/preconditioners.hh | 13 +++++++++---- test/freeflow/navierstokes/sincos/CMakeLists.txt | 2 +- test/freeflow/navierstokes/sincos/main.cc | 2 +- 6 files changed, 20 insertions(+), 12 deletions(-) diff --git a/dumux/linear/istlsolverfactorybackend.hh b/dumux/linear/istlsolverfactorybackend.hh index 2de5db9694..b1cc3501dd 100644 --- a/dumux/linear/istlsolverfactorybackend.hh +++ b/dumux/linear/istlsolverfactorybackend.hh @@ -26,9 +26,11 @@ #ifndef DUMUX_LINEAR_ISTL_SOLVERFACTORYBACKEND_HH #define DUMUX_LINEAR_ISTL_SOLVERFACTORYBACKEND_HH +#include #include -#if DUNE_VERSION_NEWER_REV(DUNE_ISTL,2,7,1) +#if DUNE_VERSION_GTE(DUNE_ISTL,2,7) +#include #include #include @@ -70,7 +72,11 @@ int initSolverFactoriesForMultiTypeBlockMatrix() using TL = Dune::TypeList; auto& dsfac = Dune::DirectSolverFactory::instance(); Dune::addRegistryToFactory(dsfac, Dumux::MultiTypeBlockMatrixDirectSolverTag{}); +#if DUNE_VERSION_GT(DUNE_ISTL,2,7) auto& pfac = Dune::PreconditionerFactory::instance(); +#else + auto& pfac = Dune::PreconditionerFactory::instance(); +#endif Dune::addRegistryToFactory(pfac, Dumux::MultiTypeBlockMatrixPreconditionerTag{}); using TLS = Dune::TypeList; auto& isfac = Dune::IterativeSolverFactory::instance(); @@ -293,6 +299,6 @@ private: } // end namespace Dumux #else -#warning "Generic dune-istl solver factory backend needs dune-istl >= 2.7.1!" +#warning "Generic dune-istl solver factory backend needs dune-istl >= 2.7!" #endif // DUNE version check #endif // header guard diff --git a/dumux/linear/istlsolverregistry.hh b/dumux/linear/istlsolverregistry.hh index 6caa4c4b25..a74f37ea02 100644 --- a/dumux/linear/istlsolverregistry.hh +++ b/dumux/linear/istlsolverregistry.hh @@ -25,11 +25,8 @@ #ifndef DUMUX_LINEAR_ISTL_SOLVER_REGISTRY_HH #define DUMUX_LINEAR_ISTL_SOLVER_REGISTRY_HH -#include -#if DUNE_VERSION_NEWER_REV(DUNE_ISTL,2,7,1) #include -#include /*! * \brief Register a Dumux preconditioner @@ -52,5 +49,4 @@ struct MultiTypeBlockMatrixDirectSolverTag {}; } // end namespace } // end namespace Dumux -#endif // DUNE version check #endif // DUMUX_LINEAR_ISTL_SOLVER_REGISTRY_HH diff --git a/dumux/linear/linearsolverparameters.hh b/dumux/linear/linearsolverparameters.hh index a3d8164aa7..bf33ed39e3 100644 --- a/dumux/linear/linearsolverparameters.hh +++ b/dumux/linear/linearsolverparameters.hh @@ -63,6 +63,7 @@ public: params["preconditioner.verbosity"] = "0"; params["preconditioner.defaultAggregationSizeMode"] = "isotropic"; params["preconditioner.defaultAggregationDimension"] = std::to_string(LinearSolverTraits::GridView::dimension); + params["preconditioner.maxLevel"] = "100"; params["ParameterGroup"] = paramGroup; params["preconditioner.ParameterGroup"] = paramGroup; } diff --git a/dumux/linear/preconditioners.hh b/dumux/linear/preconditioners.hh index bbfa48cad7..4986ae0e7e 100644 --- a/dumux/linear/preconditioners.hh +++ b/dumux/linear/preconditioners.hh @@ -38,7 +38,7 @@ #include #include -#if DUNE_VERSION_NEWER_REV(DUNE_ISTL,2,7,1) +#if DUNE_VERSION_GTE(DUNE_ISTL,2,7) #include #endif @@ -111,8 +111,13 @@ public: * \param mat The matrix to operate on. * \param params Collection of paramters. */ - SeqUzawa(const std::shared_ptr>& mat, const Dune::ParameterTree& params) - : matrix_(mat->getmat()) +#if DUNE_VERSION_GT(DUNE_ISTL,2,7) + SeqUzawa(const std::shared_ptr>& op, const Dune::ParameterTree& params) + : matrix_(op->getmat()) +#else + SeqUzawa(const M& mat, const Dune::ParameterTree& params) + : matrix_(mat) +#endif , numIterations_(params.get("iterations")) , relaxationFactor_(params.get("relaxation")) , verbosity_(params.get("verbosity")) @@ -331,7 +336,7 @@ private: }; #endif // DUNE_VERSION_GTE(DUNE_ISTL,2,7) -#if DUNE_VERSION_NEWER_REV(DUNE_ISTL,2,7,1) +#if DUNE_VERSION_GTE(DUNE_ISTL,2,7) DUMUX_REGISTER_PRECONDITIONER("uzawa", Dumux::MultiTypeBlockMatrixPreconditionerTag, Dune::defaultPreconditionerBlockLevelCreator()); #endif diff --git a/test/freeflow/navierstokes/sincos/CMakeLists.txt b/test/freeflow/navierstokes/sincos/CMakeLists.txt index 2be99bb669..46b21e9f59 100644 --- a/test/freeflow/navierstokes/sincos/CMakeLists.txt +++ b/test/freeflow/navierstokes/sincos/CMakeLists.txt @@ -35,7 +35,7 @@ dumux_add_test(NAME test_ff_navierstokes_sincos_uzawapreconditioner_factory SOURCES main.cc LABELS freeflow TIMEOUT 5000 - CMAKE_GUARD "( HAVE_UMFPACK AND DUNE_ISTL_VERSION GREATER_EQUAL 2.7 )" + CMAKE_GUARD "( HAVE_UMFPACK AND ( ( DUNE_ISTL_VERSION VERSION_GREATER 2.7 ) OR ( DUNE_ISTL_VERSION VERSION_EQUAL 2.7 ) ) )" COMPILE_DEFINITIONS LINEARSOLVER=IstlSolverFactoryBackend> COMMAND ${CMAKE_SOURCE_DIR}/bin/testing/runtest.py CMD_ARGS --script fuzzy diff --git a/test/freeflow/navierstokes/sincos/main.cc b/test/freeflow/navierstokes/sincos/main.cc index 12f0bc9fac..1da94763ac 100644 --- a/test/freeflow/navierstokes/sincos/main.cc +++ b/test/freeflow/navierstokes/sincos/main.cc @@ -47,7 +47,7 @@ #include #include -#if DUNE_VERSION_NEWER_REV(DUNE_ISTL,2,7,1) +#if DUNE_VERSION_GTE(DUNE_ISTL,2,7) #include #endif -- GitLab From 0a7a4447cb3c78bc09f0f2c40533f7f30bf3abc5 Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Sun, 19 Apr 2020 15:37:48 +0200 Subject: [PATCH 09/57] [comm] Get rid of deprecation warning with dune 2.7 --- dumux/io/grid/gmshgriddatahandle.hh | 4 ++-- dumux/io/loadsolution.hh | 2 +- dumux/linear/parallelhelpers.hh | 18 +++++++++--------- dumux/parallel/vectorcommdatahandle.hh | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/dumux/io/grid/gmshgriddatahandle.hh b/dumux/io/grid/gmshgriddatahandle.hh index 49646d789e..8a81145d08 100644 --- a/dumux/io/grid/gmshgriddatahandle.hh +++ b/dumux/io/grid/gmshgriddatahandle.hh @@ -103,7 +103,7 @@ struct GmshGridDataHandle : public Dune::CommDataHandleIF, GridFactory, Data> bool contains (int dim, int codim) const { return codim == 0 || codim == 1; } -#if DUNE_VERSION_GT(DUNE_GRID,2,7) +#if DUNE_VERSION_GTE(DUNE_GRID,2,7) //! returns true if size per entity of given dim and codim is a constant bool fixedSize(int dim, int codim) const { return true; } diff --git a/dumux/io/loadsolution.hh b/dumux/io/loadsolution.hh index c53517ce18..1037932bba 100644 --- a/dumux/io/loadsolution.hh +++ b/dumux/io/loadsolution.hh @@ -67,7 +67,7 @@ public: bool contains(int dim, int cd) const { return cd == codim; } -#if DUNE_VERSION_GT(DUNE_GRID,2,7) +#if DUNE_VERSION_GTE(DUNE_GRID,2,7) //! returns true if size per entity of given dim and codim is a constant bool fixedSize(int dim, int cd) const { return true; } diff --git a/dumux/linear/parallelhelpers.hh b/dumux/linear/parallelhelpers.hh index 23e7fbca2e..d8999b9926 100644 --- a/dumux/linear/parallelhelpers.hh +++ b/dumux/linear/parallelhelpers.hh @@ -65,7 +65,7 @@ class ParallelISTLHelper bool contains(int dim, int codim) const { return dofCodim == codim; } -#if DUNE_VERSION_GT(DUNE_GRID,2,7) +#if DUNE_VERSION_GTE(DUNE_GRID,2,7) //! returns true if size per entity of given dim and codim is a constant bool fixedSize(int dim, int codim) const { return true; } @@ -98,7 +98,7 @@ class ParallelISTLHelper public: using DataType = typename V::block_type; using BaseGatherScatter::contains; -#if DUNE_VERSION_GT(DUNE_GRID,2,7) +#if DUNE_VERSION_GTE(DUNE_GRID,2,7) using BaseGatherScatter::fixedSize; #else using BaseGatherScatter::fixedsize; @@ -140,7 +140,7 @@ class ParallelISTLHelper public: using DataType = std::size_t; using BaseGatherScatter::contains; -#if DUNE_VERSION_GT(DUNE_GRID,2,7) +#if DUNE_VERSION_GTE(DUNE_GRID,2,7) using BaseGatherScatter::fixedSize; #else using BaseGatherScatter::fixedsize; @@ -186,7 +186,7 @@ class ParallelISTLHelper public: using DataType = std::size_t; using BaseGatherScatter::contains; -#if DUNE_VERSION_GT(DUNE_GRID,2,7) +#if DUNE_VERSION_GTE(DUNE_GRID,2,7) using BaseGatherScatter::fixedSize; #else using BaseGatherScatter::fixedsize; @@ -229,7 +229,7 @@ class ParallelISTLHelper { using DataType = int; using BaseGatherScatter::contains; -#if DUNE_VERSION_GT(DUNE_GRID,2,7) +#if DUNE_VERSION_GTE(DUNE_GRID,2,7) using BaseGatherScatter::fixedSize; #else using BaseGatherScatter::fixedsize; @@ -269,7 +269,7 @@ class ParallelISTLHelper { using DataType = int; using BaseGatherScatter::contains; -#if DUNE_VERSION_GT(DUNE_GRID,2,7) +#if DUNE_VERSION_GTE(DUNE_GRID,2,7) using BaseGatherScatter::fixedSize; #else using BaseGatherScatter::fixedsize; @@ -310,7 +310,7 @@ class ParallelISTLHelper { using DataType = GlobalIndex; using BaseGatherScatter::contains; -#if DUNE_VERSION_GT(DUNE_GRID,2,7) +#if DUNE_VERSION_GTE(DUNE_GRID,2,7) using BaseGatherScatter::fixedSize; #else using BaseGatherScatter::fixedsize; @@ -567,7 +567,7 @@ class ParallelMatrixHelper bool contains (int dim, int codim) const { return (codim == dofCodim); } -#if DUNE_VERSION_GT(DUNE_GRID,2,7) +#if DUNE_VERSION_GTE(DUNE_GRID,2,7) //! returns true if size per entity of given dim and codim is a constant bool fixedSize(int dim, int codim) const { return false; } @@ -668,7 +668,7 @@ class ParallelMatrixHelper bool contains(int dim, int codim) const { return (codim == dofCodim); } -#if DUNE_VERSION_GT(DUNE_GRID,2,7) +#if DUNE_VERSION_GTE(DUNE_GRID,2,7) //! returns true if size per entity of given dim and codim is a constant bool fixedSize(int dim, int codim) const { return false; } diff --git a/dumux/parallel/vectorcommdatahandle.hh b/dumux/parallel/vectorcommdatahandle.hh index 74122a6ec7..caf8b9ffc4 100644 --- a/dumux/parallel/vectorcommdatahandle.hh +++ b/dumux/parallel/vectorcommdatahandle.hh @@ -89,7 +89,7 @@ public: bool contains(int dim, int codim) const { return (codim == entityCodim); } -#if DUNE_VERSION_GT(DUNE_GRID,2,7) +#if DUNE_VERSION_GTE(DUNE_GRID,2,7) //! returns true if size per entity of given dim and codim is a constant bool fixedSize(int dim, int codim) const { return true; } -- GitLab From 596be7b97cc0bd279e7305cae9535ae6bdb66d06 Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Tue, 21 Apr 2020 11:18:52 +0000 Subject: [PATCH 10/57] Merge branch 'fix/solver-factory-dune27' into 'master' [linear][istlsolverfactorybackend] Fix compiler error for dune-2.7 and BCRS matrices Closes #868 See merge request dumux-repositories/dumux!2017 (cherry picked from commit c211d012451bbef2f36d567a8c7a049fc9e59a56) dccae09f [linear][istlsolverfactorybackend] Fix compiler error for dune-2.7 and BCRS matrices --- dumux/linear/istlsolverfactorybackend.hh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/dumux/linear/istlsolverfactorybackend.hh b/dumux/linear/istlsolverfactorybackend.hh index b1cc3501dd..2fda1567de 100644 --- a/dumux/linear/istlsolverfactorybackend.hh +++ b/dumux/linear/istlsolverfactorybackend.hh @@ -97,7 +97,15 @@ void initSolverFactories() if constexpr (isMultiTypeBlockMatrix::value) initSolverFactoriesForMultiTypeBlockMatrix(); else +#if DUNE_VERSION_GT(DUNE_ISTL,2,7) Dune::initSolverFactories(); +#else + { + using X = typename LinearOperator::range_type; + using Y = typename LinearOperator::domain_type; + Dune::initSolverFactories(); + } +#endif } /*! -- GitLab From 6fe6842dff5378bec5ed7aa1b011b3daa0a2c88c Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Sat, 18 Apr 2020 10:35:43 +0200 Subject: [PATCH 11/57] Merge branch 'cleanup/example-2pinfiltration' into 'master' [examples] Improve 2pinfiltration example documentation Closes #862 and #854 See merge request dumux-repositories/dumux!1979 (cherry picked from commit b8c744dc570e94c8022fdec537ef8d60625821e5) --- examples/2pinfiltration/.doc_config | 28 +- examples/2pinfiltration/README.md | 1052 +---------------- examples/2pinfiltration/doc/2p.md | 533 +++++++++ examples/2pinfiltration/doc/2p_intro.md | 7 + .../doc/{intro.md => _intro.md} | 6 +- examples/2pinfiltration/doc/main.md | 388 ++++++ examples/2pinfiltration/doc/main_intro.md | 8 + examples/2pinfiltration/main.cc | 139 ++- examples/2pinfiltration/params.input | 2 - examples/2pinfiltration/problem.hh | 41 +- examples/2pinfiltration/properties.hh | 8 +- examples/2pinfiltration/spatialparams.hh | 31 +- 12 files changed, 1100 insertions(+), 1143 deletions(-) create mode 100644 examples/2pinfiltration/doc/2p.md create mode 100644 examples/2pinfiltration/doc/2p_intro.md rename examples/2pinfiltration/doc/{intro.md => _intro.md} (96%) create mode 100644 examples/2pinfiltration/doc/main.md create mode 100644 examples/2pinfiltration/doc/main_intro.md diff --git a/examples/2pinfiltration/.doc_config b/examples/2pinfiltration/.doc_config index a8f7fb29c6..2329831e93 100644 --- a/examples/2pinfiltration/.doc_config +++ b/examples/2pinfiltration/.doc_config @@ -1,9 +1,29 @@ { "README.md" : [ - "doc/intro.md", - "spatialparams.hh", - "problem.hh", + "doc/_intro.md" + ], + + "doc/2p.md" : [ + "doc/2p_intro.md", "properties.hh", + "problem.hh", + "spatialparams.hh" + ], + + "doc/main.md" : [ + "doc/main_intro.md", "main.cc" - ] + ], + + "navigation" : { + "mainpage" : "README.md", + "subpages" : [ + "doc/2p.md", + "doc/main.md" + ], + "subtitles" : [ + "Two-phase infiltration set-up", + "Main program flow" + ] + } } diff --git a/examples/2pinfiltration/README.md b/examples/2pinfiltration/README.md index 3ba9f6e4f4..371f6944d0 100644 --- a/examples/2pinfiltration/README.md +++ b/examples/2pinfiltration/README.md @@ -6,10 +6,11 @@ __In this example, you will learn how to__ * solve a two-phase flow in porous media problem with two immiscible phases * set boundary conditions and a simple injection well -* specify a lens with different porous material parameters -* use adaptive grid refinement around the saturation front * specify a point source * read the initial solution from a text file +* specify a lens with different porous material parameters +* use adaptive grid refinement around the saturation front + __Prerequisites__. You need [dune-alugrid](https://gitlab.dune-project.org/extensions/dune-alugrid) in order to compile and run this example. @@ -71,1048 +72,15 @@ For more information about the discretization please have a look at the [handboo ├── spatialparams.hh -> spatial parameter fields └── initialsolutioncc.txt -> text file with initial solution ``` +In the documentations behind the links provided in the following, you will find a detailed description how the the above mentioned set-up is realized in this example. +## Part 1: Two-phase infiltration set-up -## The file `spatialparams.hh` - -
-Click to hide/show the file documentation (or inspect the [source code](spatialparams.hh)) - - -### Includes -we include the basic spatial parameters for finite volumes file from which we will inherit - -```cpp -#include -``` - -we include all laws which are needed to define the interaction between the solid matrix and the fluids, e.g. laws for capillary pressure saturation relationships. - -```cpp -#include -#include - -namespace Dumux { -``` - -In the TwoPTestSpatialParams class we define all functions needed to describe the porous matrix, e.g. porosity and permeability - -```cpp -template -class TwoPTestSpatialParams -: public FVSpatialParams> -{ -``` - -we introduce using declarations that are derived from the property system which we need in this class - -```cpp - using GridView = typename GridGeometry::GridView; - using Element = typename GridView::template Codim<0>::Entity; - using FVElementGeometry = typename GridGeometry::LocalView; - using SubControlVolume = typename FVElementGeometry::SubControlVolume; - using ThisType = TwoPTestSpatialParams; - using ParentType = FVSpatialParams; - - static constexpr int dimWorld = GridView::dimensionworld; - using GlobalPosition = typename Element::Geometry::GlobalCoordinate; - - using EffectiveLaw = RegularizedVanGenuchten; - -public: - using MaterialLaw = EffToAbsLaw; - using MaterialLawParams = typename MaterialLaw::Params; - using PermeabilityType = Scalar; - - TwoPTestSpatialParams(std::shared_ptr gridGeometry) - : ParentType(gridGeometry) - { -``` - -we get the position of the lens from the params.input file. The lens is defined by the position of the lower left and the upper right corner - -```cpp - lensLowerLeft_ = getParam("SpatialParams.LensLowerLeft"); - lensUpperRight_ = getParam("SpatialParams.LensUpperRight"); -``` - -we set the parameters for the material law (here Van-Genuchten Law). First we set the residual saturations for the wetting phase and the non-wetting phase. lensMaterialParams_ define the material parameters for the lens while outerMaterialParams_ define material params for the rest of the domain. - -```cpp - lensMaterialParams_.setSwr(0.18); - lensMaterialParams_.setSnr(0.0); - outerMaterialParams_.setSwr(0.05); - outerMaterialParams_.setSnr(0.0); -``` - -we set the parameters for the Van Genuchten law alpha and n - -```cpp - lensMaterialParams_.setVgAlpha(0.00045); - lensMaterialParams_.setVgn(7.3); - outerMaterialParams_.setVgAlpha(0.0037); - outerMaterialParams_.setVgn(4.7); -``` - -here we get the permeabilities from the params.input file. In case that no parameter is set, the default parameters (9.05e-12 and 4.6e-10) are used - -```cpp - lensK_ = getParam("SpatialParams.lensK", 9.05e-12); - outerK_ = getParam("SpatialParams.outerK", 4.6e-10); - } -``` - -We define the (intrinsic) permeability $`[m^2]`$. In this test, we use element-wise distributed permeabilities. - -```cpp - template - PermeabilityType permeability(const Element& element, - const SubControlVolume& scv, - const ElementSolution& elemSol) const - { - if (isInLens_(element.geometry().center())) - return lensK_; - return outerK_; - } -``` - -We set the porosity $`[-]`$ depending on the position - -```cpp - Scalar porosityAtPos(const GlobalPosition& globalPos) const - { - if (isInLens_(globalPos)) - return 0.2; - return 0.4; - } -``` - -We set the parameter object for the Van Genuchten material law. - -```cpp - template - const MaterialLawParams& materialLawParams(const Element& element, - const SubControlVolume& scv, - const ElementSolution& elemSol) const - { - if (isInLens_(element.geometry().center())) - return lensMaterialParams_; - return outerMaterialParams_; - } -``` - -Here we can define which phase is to be considered as the wetting phase. Here the wetting phase is the the first phase of the fluidsystem. In this case that is water. - -```cpp - template - int wettingPhaseAtPos(const GlobalPosition& globalPos) const - { return FluidSystem::phase0Idx; } - -private: -``` - -we have a convenience definition of the position of the lens - -```cpp - bool isInLens_(const GlobalPosition &globalPos) const - { - for (int i = 0; i < dimWorld; ++i) { - if (globalPos[i] < lensLowerLeft_[i] + eps_ || globalPos[i] > lensUpperRight_[i] - eps_) - return false; - } - return true; - } - - GlobalPosition lensLowerLeft_; - GlobalPosition lensUpperRight_; - - Scalar lensK_; - Scalar outerK_; - MaterialLawParams lensMaterialParams_; - MaterialLawParams outerMaterialParams_; - - static constexpr Scalar eps_ = 1.5e-7; -}; - -} // end namespace Dumux -``` - - -
- - - -## The file `problem.hh` - -
-Click to hide/show the file documentation (or inspect the [source code](problem.hh)) - - -### Includes -We start with includes for `PorousMediumFlowProblem` and `readFileToContainer` (used below). - -```cpp -#include -#include -``` - -### Problem class -The problem class `PointSourceProblem` implements boundary and initial conditions. -It derives from the `PorousMediumFlowProblem` class. - -```cpp -namespace Dumux { - -template -class PointSourceProblem : public PorousMediumFlowProblem -{ -``` - -The class implementation starts with some alias declarations and index definitions for convenience -
Click to show local alias declarations and indices - -```cpp - using ParentType = PorousMediumFlowProblem; - using GridView = typename GetPropType::GridView; - using Element = typename GridView::template Codim<0>::Entity; - using Vertex = typename GridView::template Codim::Entity; - using Scalar = GetPropType; - using FluidSystem = GetPropType; - using PrimaryVariables = GetPropType; - using GridGeometry = GetPropType; - using PointSource = GetPropType; - using BoundaryTypes = GetPropType; - using GlobalPosition = typename Element::Geometry::GlobalCoordinate; - using NumEqVector = GetPropType; - using Indices = typename GetPropType::Indices; - - enum { - pressureH2OIdx = Indices::pressureIdx, - saturationDNAPLIdx = Indices::saturationIdx, - contiDNAPLEqIdx = Indices::conti0EqIdx + FluidSystem::comp1Idx, - waterPhaseIdx = FluidSystem::phase0Idx, - dnaplPhaseIdx = FluidSystem::phase1Idx - }; -``` - -
- -In the constructor of the class, we call the parent type's constructor -and read the intial values for the primary variables from a text file. -The function `readFileToContainer` is implemented in the header `dumux/io/container.hh`. - -```cpp -public: - PointSourceProblem(std::shared_ptr gridGeometry) - : ParentType(gridGeometry) - { - initialValues_ = readFileToContainer>("initialsolutioncc.txt"); - } -``` - -For isothermal problems, Dumux requires problem classes to implement a `temperature()` -member function. Fluid properties that depend on temperature will be calculated with the specified temperature. - -```cpp - Scalar temperature() const - { - return 293.15; // 10°C - } -``` - -### 1. Boundary types -We define the type of boundary conditions depending on location. Two types of boundary conditions -can be specified: Dirichlet or Neumann boundary condition. On a Dirichlet boundary, the values of the -primary variables need to be fixed. On a Neumann boundary condition, values for derivatives need to be fixed. -Mixed boundary conditions (different types for different equations on the same boundary) are not accepted. - -```cpp - BoundaryTypes boundaryTypesAtPos(const GlobalPosition &globalPos) const - { - BoundaryTypes values; - // Dirichlet boundaries on the left and right hand side of the domain - if (onLeftBoundary_(globalPos) || onRightBoundary_(globalPos)) - values.setAllDirichlet(); - // and Neumann boundaries otherwise (top and bottom of the domain) - else - values.setAllNeumann(); - return values; - } -``` - -### 2. Dirichlet boundaries -We specify the values for the Dirichlet boundaries, depending on location. -We need to fix values for the two primary variables: the water pressure -and the DNAPL saturation. - -```cpp - PrimaryVariables dirichletAtPos(const GlobalPosition &globalPos) const - { - // To determine the density of water for a given state, we build a fluid state with the given conditions: - PrimaryVariables values; - GetPropType fluidState; - fluidState.setTemperature(temperature()); - fluidState.setPressure(waterPhaseIdx, /*pressure=*/1e5); - fluidState.setPressure(dnaplPhaseIdx, /*pressure=*/1e5); - - // The density is then calculated by the fluid system: - Scalar densityW = FluidSystem::density(fluidState, waterPhaseIdx); - - // The water phase pressure is the hydrostatic pressure, scaled with a factor: - Scalar height = this->gridGeometry().bBoxMax()[1] - this->gridGeometry().bBoxMin()[1]; - Scalar depth = this->gridGeometry().bBoxMax()[1] - globalPos[1]; - Scalar alpha = 1 + 1.5/height; - Scalar width = this->gridGeometry().bBoxMax()[0] - this->gridGeometry().bBoxMin()[0]; - Scalar factor = (width*alpha + (1.0 - alpha)*globalPos[0])/width; - - values[pressureH2OIdx] = 1e5 - factor*densityW*this->spatialParams().gravity(globalPos)[1]*depth; - // The saturation of the DNAPL Trichlorethene is zero on our Dirichlet boundary: - values[saturationDNAPLIdx] = 0.0; - - return values; - } -``` - -### 3. Neumann boundaries -In our case, we need to specify mass fluxes for our two liquid phases. -Negative sign means influx and the unit of the boundary flux is $`kg/(m^2 s)`$. -On the inlet area, we set a DNAPL influx of $`0.04 kg/(m^2 s)`$. On all other -Neumann boundaries, the boundary flux is zero. - -```cpp - NumEqVector neumannAtPos(const GlobalPosition &globalPos) const - { - NumEqVector values(0.0); - if (onInlet_(globalPos)) - values[contiDNAPLEqIdx] = -0.04; - - return values; - } -``` - -### 4. Initial conditions -The initial condition needs to be set for all primary variables. -Here, we take the data from the file that we read in previously. - -```cpp - PrimaryVariables initial(const Element& element) const - { - // The input data is written for a uniform grid with discretization length delta. - // Accordingly, we need to find the index of our cells, depending on the x and y coordinates, - // that corresponds to the indices of the input data set. - const auto delta = 0.0625; - unsigned int cellsX = this->gridGeometry().bBoxMax()[0]/delta; - const auto globalPos = element.geometry().center(); - - unsigned int dataIdx = std::trunc(globalPos[1]/delta) * cellsX + std::trunc(globalPos[0]/delta); - return initialValues_[dataIdx]; - } -``` - -### 5. Point source -In this scenario, we set a point source (e.g. modeling a well). The point source value can be solution dependent. -Point sources are added by pushing them into the vector `pointSources`. -The `PointSource` constructor takes two arguments. -The first argument is a coordinate array containing the position in space, -the second argument is an array of source value for each equation (in units of $`kg/s`$). -Recall that the first eqution is the water phase mass balance -and the second equation is the DNAPL phase mass balance. - -```cpp - void addPointSources(std::vector& pointSources) const - { - pointSources.push_back(PointSource({0.502, 3.02}, {0, 0.1})); - } -``` - -In the private part of the class, we define some helper functions for -the boundary conditions and local variables. -
Click to show private data members and functions - -```cpp -private: - bool onLeftBoundary_(const GlobalPosition &globalPos) const - { return globalPos[0] < this->gridGeometry().bBoxMin()[0] + eps_; } - - bool onRightBoundary_(const GlobalPosition &globalPos) const - { return globalPos[0] > this->gridGeometry().bBoxMax()[0] - eps_; } - - bool onUpperBoundary_(const GlobalPosition &globalPos) const - { return globalPos[1] > this->gridGeometry().bBoxMax()[1] - eps_; } - - bool onInlet_(const GlobalPosition &globalPos) const - { - Scalar width = this->gridGeometry().bBoxMax()[0] - this->gridGeometry().bBoxMin()[0]; - Scalar lambda = (this->gridGeometry().bBoxMax()[0] - globalPos[0])/width; - return onUpperBoundary_(globalPos) && 0.5 < lambda && lambda < 2.0/3.0; - } - - static constexpr Scalar eps_ = 1e-6; - std::vector initialValues_; -}; - -} // end namespace Dumux -``` - -
- -
- - - -## The file `properties.hh` - -
-Click to hide/show the file documentation (or inspect the [source code](properties.hh)) - - -### Includes -The header includes will be mentioned in the text below. -
Click to show the header includes - -```cpp -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include "spatialparams.hh" -#include "problem.hh" -``` - -
- -All properties are defined in the (nested) namespace -`Dumux::Properties`. To get and set properties, we need the definitions and implementations from the -header `dumux/common/properties.hh` included above. - -```cpp -namespace Dumux::Properties { -``` - -First, a so-called TypeTag is created. Properties are traits specialized for this TypeTag (a simple `struct`). - ->>> -:white_check_mark: The properties of other TypeTags are inherited if the alias `InheritsFrom` is present. -These other TypeTags are listed in form of a `std::tuple` in order of importance. ->>> - -Here, properties from the two-phase flow model (`TTag::Twop`) and the -cell-centered finite volume scheme with two-point-flux approximation (`TTag::CCTpfaModel`) -are inherited. These other TypeTag definitions can be found in the included -headers `dumux/porousmediumflow/2p/model.hh` and `dumux/discretization/cctpfa.hh`. - -```cpp -namespace TTag { -struct PointSourceExample { using InheritsFrom = std::tuple; }; -} -``` - -Next, we specialize the properties `Problem` and `SpatialParams` for our new TypeTag and -set the type to our problem and spatial parameter classes implemented -in `problem.hh` and `spatialparams.hh`. - -```cpp -template -struct Problem -{ using type = PointSourceProblem; }; - -template -struct SpatialParams -{ - // two local aliases for convenience and readability - using GridGeometry = GetPropType; - using Scalar = GetPropType; - - using type = TwoPTestSpatialParams; -}; -``` - -The `Grid` property tells the -simulator to use ALUGrid - an unstructured grid manager - here -configured for grid and coordinate dimensions `2`, -hexahedral element types (`Dune::cube`) and non-conforming refinement mode. -`Dune::ALUGrid` is declared in the included header `dune/alugrid/grid.hh` -from the Dune module `dune-alugrid`. - -```cpp -template -struct Grid -{ using type = Dune::ALUGrid<2, 2, Dune::cube, Dune::nonconforming>; }; -``` - -The `FluidSystem` property specifies which fluids are used. -This fluid system is composed of two immiscible liquid phases which are made up -entirely of its respective main components `SimpleH2O` (a water component with constant properties) -and `Trichloroethene` (a DNAPL). The components, phases, and the fluid system are implemented in -the headers `dumux/material/components/simpleh2o.hh`, -`dumux/material/components/trichloroethene.hh`, -`dumux/material/fluidsystems/1pliquid.hh`, -`dumux/material/fluidsystems/2pimmiscible.hh` -included above. - -```cpp -template -struct FluidSystem -{ - using Scalar = GetPropType; - using WettingPhase = FluidSystems::OnePLiquid >; - using NonwettingPhase = FluidSystems::OnePLiquid >; - - using type = FluidSystems::TwoPImmiscible; -}; -``` - -The two-phase model implements different primary variable formulations. -Here we choose the pressure of the first phase and the saturation of the second phase. -The order of phases is specified by the fluid system. -In this case that means that the primary variables are water pressure and DNAPL saturation. - -```cpp -template -struct Formulation -{ static constexpr auto value = TwoPFormulation::p0s1; }; - -} // end namespace Dumux::Properties -``` - - -
- - - -## The file `main.cc` - -
-Click to hide/show the file documentation (or inspect the [source code](main.cc)) - - -This is the main file for the 2pinfiltration example. Here we can see the programme sequence and how the system is solved using Newton's method -### Includes - -```cpp -#include -``` - -Standard header file for C++, to get time and date information. - -```cpp -#include -``` - -Standard header file for C++, for in- and output. - -```cpp -#include -``` - -Dumux is based on DUNE, the Distributed and Unified Numerics Environment, which provides several grid managers and linear solvers. So we need some includes from that. - -```cpp -#include -#include -#include -#include -#include -``` - -In Dumux, a property system is used to specify the model. For this, different properties are defined containing type definitions, values and methods. All properties are declared in the file properties.hh. - -```cpp -#include -``` - -The following file contains the parameter class, which manages the definition of input parameters by a default value, the inputfile or the command line. - -```cpp -#include -``` - -The file dumuxmessage.hh contains the class defining the start and end message of the simulation. - -```cpp -#include -#include -``` - -we include the linear solver to be used to solve the linear system - -```cpp -#include -#include -``` - -we include the nonlinear Newton's method - -```cpp -#include -``` - -Further, we include assembler, which assembles the linear systems for finite volume schemes (box-scheme, tpfa-approximation, mpfa-approximation). - -```cpp -#include -``` - -The containing class in the following file defines the different differentiation methods used to compute the derivatives of the residual. - -```cpp -#include -``` - -we include the spatial discretization methods available in Dumux - -```cpp -#include -``` - -We need the following class to simplify the writing of dumux simulation data to VTK format. - -```cpp -#include -``` - -The gridmanager constructs a grid from the information in the input or grid file. There is a specification for the different supported grid managers. - -```cpp -#include -``` - -We include several files which are needed for the adaptive grid - -```cpp -#include -#include -#include -#include -#include -``` - -Finally, we include the properties which configure the simulation - -```cpp -#include "properties.hh" -``` - -### Beginning of the main function - -```cpp -int main(int argc, char** argv) try -{ - using namespace Dumux; -``` - -we define the type tag for this problem - -```cpp - using TypeTag = Properties::TTag::PointSourceExample; -``` - -We initialize MPI, finalize is done automatically on exit - -```cpp - const auto& mpiHelper = Dune::MPIHelper::instance(argc, argv); -``` - -We print dumux start message - -```cpp - if (mpiHelper.rank() == 0) - DumuxMessage::print(/*firstCall=*/true); -``` - -We parse command line arguments and input file - -```cpp - Parameters::init(argc, argv); -``` - -### Create the grid -A gridmanager tries to create the grid either from a grid file or the input file. - -```cpp - GridManager> gridManager; - gridManager.init(); -``` - -The instationary non-linear problem is run on this grid. - -we compute on the leaf grid view - -```cpp - const auto& leafGridView = gridManager.grid().leafGridView(); -``` - -### Set-up and solving of the problem - -#### Set-up -We create and initialize the finite volume grid geometry, the problem, the linear system, including the jacobian matrix, the residual and the solution vector and the gridvariables. - -We need the finite volume geometry to build up the subcontrolvolumes (scv) and subcontrolvolume faces (scvf) for each element of the grid partition. - -```cpp - using GridGeometry = GetPropType; - auto gridGeometry = std::make_shared(leafGridView); - gridGeometry->update(); -``` - -In the problem, we define the boundary and initial conditions. - -```cpp - using Problem = GetPropType; - auto problem = std::make_shared(gridGeometry); -``` - -We call the `computePointSourceMap` method to compute the point sources. The `computePointSourceMap` method is inherited from the fvproblem and therefore specified in the `dumux/common/fvproblem.hh`. It calls the `addPointSources` method specified in the `problem.hh` file. - -```cpp - problem->computePointSourceMap(); -``` - -We initialize the solution vector, - -```cpp - using SolutionVector = GetPropType; - SolutionVector x(gridGeometry->numDofs()); - problem->applyInitialSolution(x); - auto xOld = x; -``` - -and then use the solution vector to intialize the `gridVariables`. - -```cpp - using GridVariables = GetPropType; - auto gridVariables = std::make_shared(problem, gridGeometry); - gridVariables->init(x); -``` - -We instantiate the indicator for grid adaption & the data transfer, we read some parameters for indicator from the input file. - -```cpp - using Scalar = GetPropType; - const Scalar refineTol = getParam("Adaptive.RefineTolerance"); - const Scalar coarsenTol = getParam("Adaptive.CoarsenTolerance"); -``` - -We use an indicator for a two-phase flow problem that is saturation-dependent and defined in the file `dumux/porousmediumflow/2p/gridadaptindicator.hh.` It allows to set the minimum and maximum allowed refinement levels via the input parameters. - -```cpp - TwoPGridAdaptIndicator indicator(gridGeometry); -``` - -The data transfer performs the transfer of data on a grid from before to after adaptation and is defined in the file `dumux/porousmediumflow/2p/griddatatransfer.hh`. Its main functions are to store and reconstruct the primary variables. - -```cpp - TwoPGridDataTransfer dataTransfer(problem, gridGeometry, gridVariables, x); -``` - -We do an initial refinement around sources/BCs. We use the `GridAdaptInitializationIndicator` defined in `dumux/adaptive/initializationindicator.hh` for that. - -```cpp - GridAdaptInitializationIndicator initIndicator(problem, gridGeometry, gridVariables); -``` - -We refine up to the maximum level. For every level, the indicator used for the refinement/coarsening is calculated. If any grid cells have to be adapted, the gridvariables and the pointsourcemap are updated. - -```cpp - const auto maxLevel = getParam("Adaptive.MaxLevel", 0); - for (std::size_t i = 0; i < maxLevel; ++i) - { -``` - -we calculate the initial indicator for adaption for each grid cell using the initial solution x - -```cpp - initIndicator.calculate(x); -``` - -and then we mark the elements that were adapted. - -```cpp - bool wasAdapted = false; - if (markElements(gridManager.grid(), initIndicator)) - wasAdapted = adapt(gridManager.grid(), dataTransfer); -``` - -In case of a grid adaptation, the gridvariables and the pointsourcemap are updated. - -```cpp - if (wasAdapted) - { -``` - -We overwrite the old solution with the new (resized & interpolated) one - -```cpp - xOld = x; -``` - -We initialize the secondary variables to the new (and "new old") solution - -```cpp - gridVariables->updateAfterGridAdaption(x); -``` - -we update the point source map after adaption - -```cpp - problem->computePointSourceMap(); - } - } -``` - -Depending on the initial conditions, another grid adaptation might be necessary. The gridadaptindicator uses the input parameters `Adaptive.RefineTolerance` and `Adaptive.CoarsenTolerance` for this step. - -```cpp - indicator.calculate(x, refineTol, coarsenTol); -``` - -we mark the elements that were adapted - -```cpp - bool wasAdapted = false; - if (markElements(gridManager.grid(), indicator)) - wasAdapted = adapt(gridManager.grid(), dataTransfer); -``` - -In case of an additional grid adaptation, the gridvariables and the pointsourcemap are updated again. - -```cpp - if (wasAdapted) - { -``` - -Overwrite the old solution with the new (resized & interpolated) one - -```cpp - xOld = x; -``` - -Initialize the secondary variables to the new (and "new old") solution - -```cpp - gridVariables->updateAfterGridAdaption(x); -``` - -Update the point source map - -```cpp - problem->computePointSourceMap(); - } -``` - -We get some time loop parameters from the input file params.input - -```cpp - using Scalar = GetPropType; - const auto tEnd = getParam("TimeLoop.TEnd"); - const auto maxDt = getParam("TimeLoop.MaxTimeStepSize"); - auto dt = getParam("TimeLoop.DtInitial"); -``` - -and initialize the vtkoutput. Each model has a predefined model specific output with relevant parameters for that model. - -```cpp - using IOFields = GetPropType; - VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); - using VelocityOutput = GetPropType; - vtkWriter.addVelocityOutput(std::make_shared(*gridVariables)); - IOFields::initOutputModule(vtkWriter); // Add model specific output fields - vtkWriter.write(0.0); -``` - -we instantiate the time loop - -```cpp - auto timeLoop = std::make_shared>(0, dt, tEnd); - timeLoop->setMaxTimeStepSize(maxDt); -``` - -we set the assembler with the time loop because we have an instationary problem - -```cpp - using Assembler = FVAssembler; - auto assembler = std::make_shared(problem, gridGeometry, gridVariables, timeLoop); -``` - -we set the linear solver - -```cpp - using LinearSolver = AMGBiCGSTABBackend>; - auto linearSolver = std::make_shared(leafGridView, gridGeometry->dofMapper()); -``` - -additionally we set the non-linear solver. - -```cpp - using NewtonSolver = Dumux::NewtonSolver; - NewtonSolver nonLinearSolver(assembler, linearSolver); -``` - -we start the time loop. In each time step before we start calculating a new solution we check if we have to refine the mesh again based on the solution of the previous time step. - -```cpp - timeLoop->start(); do - { -``` - -We only want to refine/coarsen after first time step is finished, not before. The initial refinement was already done before the start of the time loop. This means we only refine when the time is greater than 0. - -```cpp - if (timeLoop->time() > 0) - { -``` - -again we compute the refinement indicator with the `TwoPGridAdaptIndicator` - -```cpp - indicator.calculate(x, refineTol, coarsenTol); -``` - -we mark elements and adapt grid if necessary - -```cpp - wasAdapted = false; - if (markElements(gridManager.grid(), indicator)) - wasAdapted = adapt(gridManager.grid(), dataTransfer); -``` - -In case of a grid adaptation, the gridvariables and the pointsourcemap are updated again. - -```cpp - if (wasAdapted) - { -``` - -We overwrite the old solution with the new (resized & interpolated) one - -```cpp - xOld = x; -``` - -We tell the assembler to resize the matrix and set pattern - -```cpp - assembler->setJacobianPattern(); -``` - -We tell the assembler to resize the residual - -```cpp - assembler->setResidualSize(); -``` - -We initialize the secondary variables to the new (and "new old") solution - -```cpp - gridVariables->updateAfterGridAdaption(x); -``` - -We update the point source map - -```cpp - problem->computePointSourceMap(); - } -``` - -we leave the refinement step - -```cpp - } -``` - -Now, we start to calculate the new solution of that time step. First, we define the old solution as the solution of the previous time step for storage evaluations. - -```cpp - assembler->setPreviousSolution(xOld); -``` - -We solve the non-linear system with time step control. - -```cpp - nonLinearSolver.solve(x, *timeLoop); -``` - -We make the new solution the old solution. - -```cpp - xOld = x; - gridVariables->advanceTimeStep(); -``` - -We advance to the time loop to the next step. - -```cpp - timeLoop->advanceTimeStep(); -``` - -We write vtk output for each time step - -```cpp - vtkWriter.write(timeLoop->time()); -``` - -We report statistics of this time step - -```cpp - timeLoop->reportTimeStep(); -``` - -We set a new dt as suggested by the newton solver for the next time step - -```cpp - timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize())); - - } while (!timeLoop->finished()); - - timeLoop->finalize(leafGridView.comm()); -``` - -### Final Output - -print dumux end message - -```cpp - if (mpiHelper.rank() == 0) - { - Parameters::print(); - DumuxMessage::print(/*firstCall=*/false); - } - - return 0; -} // end main -catch (Dumux::ParameterException &e) -{ - std::cerr << std::endl << e << " ---> Abort!" << std::endl; - return 1; -} -catch (Dune::DGFException & e) -{ - std::cerr << "DGF exception thrown (" << e << - "). Most likely, the DGF file name is wrong " - "or the DGF file is corrupted, " - "e.g. missing hash at end of file or wrong number (dimensions) of entries." - << " ---> Abort!" << std::endl; - return 2; -} -catch (Dune::Exception &e) -{ - std::cerr << "Dune reported error: " << e << " ---> Abort!" << std::endl; - return 3; -} -catch (...) -{ - std::cerr << "Unknown exception thrown! ---> Abort!" << std::endl; - return 4; -} -``` +| [:arrow_right: Click to continue with part 1 of the documentation](doc/2p.md) | +|---:| -
+## Part 2: Main program flow +| [:arrow_right: Click to continue with part 2 of the documentation](doc/main.md) | +|---:| \ No newline at end of file diff --git a/examples/2pinfiltration/doc/2p.md b/examples/2pinfiltration/doc/2p.md new file mode 100644 index 0000000000..380e780662 --- /dev/null +++ b/examples/2pinfiltration/doc/2p.md @@ -0,0 +1,533 @@ + + + +| [:arrow_left: Back to the main documentation](../README.md) | [:arrow_right: Continue with part 2](main.md) | +|---|---:| + +# Part 1: Implementation of the 2p set-up + +The two-phase flow set-up is implemented in the files `properties.hh`, +`problem.hh` and `spatialparams.hh`. In the file `problem.hh` a description of the boundary and initial conditions can be found. Additionally, you can see how to implement an injection well as a point source and how to read the initial solution from a text file. In the file `spatialparams.hh` we create a lens within the porous medium, that has different spatial parameters than the surrounding material and set the parameters for the +$`p_c - S_w`$ relationship. + +[[_TOC_]] + + +## The file `properties.hh` + +
+Click to hide/show the file documentation (or inspect the [source code](../properties.hh)) + + +### Includes +The header includes will be mentioned in the text below. +
Click to show header includes + +```cpp + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include "spatialparams.hh" +#include "problem.hh" +``` + +
+ +### Type tag definition +All properties are defined in the (nested) namespace +`Dumux::Properties`. To get and set properties, we need the definitions and implementations from the +header `dumux/common/properties.hh` included above. + +```cpp +namespace Dumux::Properties { +``` + +First, a so-called TypeTag is created. Properties are traits specialized for this TypeTag (a simple `struct`). + +>>> +:white_check_mark: The properties of other TypeTags are inherited if the alias `InheritsFrom` is present. +These other TypeTags are listed in form of a `std::tuple` in order of importance. +>>> + +Here, properties from the two-phase flow model (`TTag::Twop`) and the +cell-centered finite volume scheme with two-point-flux approximation (`TTag::CCTpfaModel`) +are inherited. These other TypeTag definitions can be found in the included +headers `dumux/porousmediumflow/2p/model.hh` and `dumux/discretization/cctpfa.hh`. + +```cpp +namespace TTag { +struct PointSourceExample { using InheritsFrom = std::tuple; }; +} +``` + +### Property specializations +Next, we specialize the properties `Problem` and `SpatialParams` for our new TypeTag and +set the type to our problem and spatial parameter classes implemented +in `problem.hh` and `spatialparams.hh`. + +```cpp +template +struct Problem +{ using type = PointSourceProblem; }; + +template +struct SpatialParams +{ + // two local aliases for convenience and readability + using GridGeometry = GetPropType; + using Scalar = GetPropType; + + using type = TwoPTestSpatialParams; +}; +``` + +The `Grid` property tells the +simulator to use ALUGrid - an unstructured grid manager - here +configured for grid and coordinate dimensions `2`, +hexahedral element types (`Dune::cube`) and non-conforming refinement mode. +`Dune::ALUGrid` is declared in the included header `dune/alugrid/grid.hh` +from the Dune module `dune-alugrid`. + +```cpp +template +struct Grid +{ using type = Dune::ALUGrid<2, 2, Dune::cube, Dune::nonconforming>; }; +``` + +The `FluidSystem` property specifies which fluids are used. +This fluid system is composed of two immiscible liquid phases which are made up +entirely of its respective main components `SimpleH2O` (a water component with constant properties) +and `Trichloroethene` (a DNAPL). The components, phases, and the fluid system are implemented in +the headers `dumux/material/components/simpleh2o.hh`, +`dumux/material/components/trichloroethene.hh`, +`dumux/material/fluidsystems/1pliquid.hh`, +`dumux/material/fluidsystems/2pimmiscible.hh` +included above. + +```cpp +template +struct FluidSystem +{ + using Scalar = GetPropType; + using WettingPhase = FluidSystems::OnePLiquid >; + using NonwettingPhase = FluidSystems::OnePLiquid >; + + using type = FluidSystems::TwoPImmiscible; +}; +``` + +The two-phase model implements different primary variable formulations. +Here we choose the pressure of the first phase and the saturation of the second phase. +The order of phases is specified by the fluid system. +In this case that means that the primary variables are water pressure and DNAPL saturation. + +```cpp +template +struct Formulation +{ static constexpr auto value = TwoPFormulation::p0s1; }; + +} // end namespace Dumux::Properties +``` + + +
+ + + +## The file `problem.hh` + +
+Click to hide/show the file documentation (or inspect the [source code](../problem.hh)) + + +### Includes +We start with includes for `PorousMediumFlowProblem`, `readFileToContainer` and `GetPropType` (used below). + +```cpp +#include +#include +#include +``` + +### Problem class +The problem class `PointSourceProblem` implements boundary and initial conditions. +It derives from the `PorousMediumFlowProblem` class. + +```cpp +namespace Dumux { + +template +class PointSourceProblem : public PorousMediumFlowProblem +{ +``` + +The class implementation starts with some alias declarations and index definitions for convenience +
Click to show local alias declarations and indices + +```cpp + + using ParentType = PorousMediumFlowProblem; + using GridGeometry = GetPropType; + using GridView = typename GridGeometry::GridView; + using Element = typename GridView::template Codim<0>::Entity; + using Vertex = typename GridView::template Codim::Entity; + using Scalar = GetPropType; + using FluidSystem = GetPropType; + using PrimaryVariables = GetPropType; + using PointSource = GetPropType; + using BoundaryTypes = GetPropType; + using GlobalPosition = typename Element::Geometry::GlobalCoordinate; + using NumEqVector = GetPropType; + using Indices = typename GetPropType::Indices; + + enum { + pressureH2OIdx = Indices::pressureIdx, + saturationDNAPLIdx = Indices::saturationIdx, + contiDNAPLEqIdx = Indices::conti0EqIdx + FluidSystem::comp1Idx, + waterPhaseIdx = FluidSystem::phase0Idx, + dnaplPhaseIdx = FluidSystem::phase1Idx + }; +``` + +
+ +In the constructor of the class, we call the parent type's constructor +and read the intial values for the primary variables from a text file. +The function `readFileToContainer` is implemented in the header `dumux/io/container.hh`. + +```cpp +public: + PointSourceProblem(std::shared_ptr gridGeometry) + : ParentType(gridGeometry) + { + initialValues_ = readFileToContainer>("initialsolutioncc.txt"); + } +``` + +For isothermal problems, Dumux requires problem classes to implement a `temperature()` +member function. Fluid properties that depend on temperature will be calculated with the specified temperature. + +```cpp + Scalar temperature() const + { + return 293.15; // 10°C + } +``` + +#### Boundary types +We define the type of boundary conditions depending on location. Two types of boundary conditions +can be specified: Dirichlet or Neumann boundary condition. On a Dirichlet boundary, the values of the +primary variables need to be fixed. On a Neumann boundary condition, values for derivatives need to be fixed. +Mixed boundary conditions (different types for different equations on the same boundary) are not accepted. + +```cpp + BoundaryTypes boundaryTypesAtPos(const GlobalPosition &globalPos) const + { + BoundaryTypes values; + // Dirichlet boundaries on the left and right hand side of the domain + if (onLeftBoundary_(globalPos) || onRightBoundary_(globalPos)) + values.setAllDirichlet(); + // and Neumann boundaries otherwise (top and bottom of the domain) + else + values.setAllNeumann(); + return values; + } +``` + +#### Dirichlet boundaries +We specify the values for the Dirichlet boundaries, depending on location. +We need to fix values for the two primary variables: the water pressure +and the DNAPL saturation. + +```cpp + PrimaryVariables dirichletAtPos(const GlobalPosition &globalPos) const + { + // To determine the density of water for a given state, we build a fluid state with the given conditions: + PrimaryVariables values; + GetPropType fluidState; + fluidState.setTemperature(temperature()); + fluidState.setPressure(waterPhaseIdx, /*pressure=*/1e5); + fluidState.setPressure(dnaplPhaseIdx, /*pressure=*/1e5); + + // The density is then calculated by the fluid system: + const Scalar densityW = FluidSystem::density(fluidState, waterPhaseIdx); + + // The water phase pressure is the hydrostatic pressure, scaled with a factor: + const Scalar height = this->gridGeometry().bBoxMax()[1] - this->gridGeometry().bBoxMin()[1]; + const Scalar depth = this->gridGeometry().bBoxMax()[1] - globalPos[1]; + const Scalar alpha = 1 + 1.5/height; + const Scalar width = this->gridGeometry().bBoxMax()[0] - this->gridGeometry().bBoxMin()[0]; + const Scalar factor = (width*alpha + (1.0 - alpha)*globalPos[0])/width; + + values[pressureH2OIdx] = 1e5 - factor*densityW*this->spatialParams().gravity(globalPos)[1]*depth; + // The saturation of the DNAPL Trichlorethene is zero on our Dirichlet boundary: + values[saturationDNAPLIdx] = 0.0; + + return values; + } +``` + +#### Neumann boundaries +In our case, we need to specify mass fluxes for our two liquid phases. +Negative sign means influx and the unit of the boundary flux is $`kg/(m^2 s)`$. +On the inlet area, we set a DNAPL influx of $`0.04 kg/(m^2 s)`$. On all other +Neumann boundaries, the boundary flux is zero. + +```cpp + NumEqVector neumannAtPos(const GlobalPosition &globalPos) const + { + NumEqVector values(0.0); + if (onInlet_(globalPos)) + values[contiDNAPLEqIdx] = -0.04; + + return values; + } +``` + +#### Initial conditions +The initial condition needs to be set for all primary variables. +Here, we take the data from the file that we read in previously. + +```cpp + PrimaryVariables initial(const Element& element) const + { + // The input data is written for a uniform grid with discretization length delta. + // Accordingly, we need to find the index of our cells, depending on the x and y coordinates, + // that corresponds to the indices of the input data set. + const auto delta = 0.0625; + const unsigned int cellsX = this->gridGeometry().bBoxMax()[0]/delta; + const auto globalPos = element.geometry().center(); + + const unsigned int dataIdx = std::trunc(globalPos[1]/delta) * cellsX + std::trunc(globalPos[0]/delta); + return initialValues_[dataIdx]; + } +``` + +#### Point source +In this scenario, we set a point source (e.g. modeling a well). The point source value can be solution dependent. +Point sources are added by pushing them into the vector `pointSources`. +The `PointSource` constructor takes two arguments. +The first argument is a coordinate array containing the position in space, +the second argument is an array of source value for each equation (in units of $`kg/s`$). +Recall that the first eqution is the water phase mass balance +and the second equation is the DNAPL phase mass balance. + +```cpp + void addPointSources(std::vector& pointSources) const + { + pointSources.push_back(PointSource({0.502, 3.02}, {0, 0.1})); + } +``` + +In the private part of the class, we define some helper functions for +the boundary conditions and local variables. +
Click to show private data members and functions + +```cpp + +private: + bool onLeftBoundary_(const GlobalPosition &globalPos) const + { return globalPos[0] < this->gridGeometry().bBoxMin()[0] + eps_; } + + bool onRightBoundary_(const GlobalPosition &globalPos) const + { return globalPos[0] > this->gridGeometry().bBoxMax()[0] - eps_; } + + bool onUpperBoundary_(const GlobalPosition &globalPos) const + { return globalPos[1] > this->gridGeometry().bBoxMax()[1] - eps_; } + + bool onInlet_(const GlobalPosition &globalPos) const + { + Scalar width = this->gridGeometry().bBoxMax()[0] - this->gridGeometry().bBoxMin()[0]; + Scalar lambda = (this->gridGeometry().bBoxMax()[0] - globalPos[0])/width; + return onUpperBoundary_(globalPos) && 0.5 < lambda && lambda < 2.0/3.0; + } + + static constexpr Scalar eps_ = 1e-6; + std::vector initialValues_; +}; + +} // end namespace Dumux +``` + +
+ +
+ + + +## The file `spatialparams.hh` + +
+Click to hide/show the file documentation (or inspect the [source code](../spatialparams.hh)) + + +### Includes +We include the basic spatial parameters for finite volumes file from which we will inherit + +```cpp +#include +``` + +We include all laws which are needed to define the interaction between the solid matrix and the fluids, e.g. laws for capillary pressure saturation relationships. + +```cpp +#include +#include +``` + +### The spatial parameters class +In the TwoPTestSpatialParams class we define all functions needed to describe the porous matrix, e.g. porosity and permeability. We inherit from the `FVSpatialParams` class, which is the base class for multiphase porous medium flow applications. + +```cpp +namespace Dumux { + +template +class TwoPTestSpatialParams +: public FVSpatialParams> +{ + //we introduce using declarations that are derived from the property system which we need in this class + using GridView = typename GridGeometry::GridView; + using Element = typename GridView::template Codim<0>::Entity; + using FVElementGeometry = typename GridGeometry::LocalView; + using SubControlVolume = typename FVElementGeometry::SubControlVolume; + using ThisType = TwoPTestSpatialParams; + using ParentType = FVSpatialParams; + + static constexpr int dimWorld = GridView::dimensionworld; + using GlobalPosition = typename Element::Geometry::GlobalCoordinate; + + using EffectiveLaw = RegularizedVanGenuchten; + +public: + using MaterialLaw = EffToAbsLaw; + using MaterialLawParams = typename MaterialLaw::Params; + using PermeabilityType = Scalar; +``` + +Here, we get parameters for the position of the lens and porosity and permeability from the input file. Additionally, we set the parameters for the Van-Genuchten relationship. + +```cpp + TwoPTestSpatialParams(std::shared_ptr gridGeometry) + : ParentType(gridGeometry) + { + // We get the position of the lens from the params.input file. + // The lens is defined by the position of the lower left and the upper right corner + lensLowerLeft_ = getParam("SpatialParams.LensLowerLeft"); + lensUpperRight_ = getParam("SpatialParams.LensUpperRight"); + + // We set the parameters for the material law (here Van-Genuchten Law). + // First we set the residual saturations for the wetting phase and the non-wetting phase. + // lensMaterialParams_ define the material parameters for the lens while + // outerMaterialParams_ define material params for the rest of the domain. + lensMaterialParams_.setSwr(0.18); + lensMaterialParams_.setSnr(0.0); + outerMaterialParams_.setSwr(0.05); + outerMaterialParams_.setSnr(0.0); + + //We set the parameters for the Van Genuchten law alpha and n + lensMaterialParams_.setVgAlpha(0.00045); + lensMaterialParams_.setVgn(7.3); + outerMaterialParams_.setVgAlpha(0.0037); + outerMaterialParams_.setVgn(4.7); + + //Here, we get the permeabilities from the params.input file. + //In case that no parameter is set, the default parameters (9.05e-12 and 4.6e-10) are used + lensK_ = getParam("SpatialParams.lensK", 9.05e-12); + outerK_ = getParam("SpatialParams.outerK", 4.6e-10); + } +``` + +We define the (intrinsic) permeability $`[m^2]`$. In this test, we use element-wise distributed permeabilities. + +```cpp + template + PermeabilityType permeability(const Element& element, + const SubControlVolume& scv, + const ElementSolution& elemSol) const + { + if (isInLens_(element.geometry().center())) + return lensK_; + return outerK_; + } +``` + +We set the porosity $`[-]`$ depending on the position + +```cpp + Scalar porosityAtPos(const GlobalPosition& globalPos) const + { + if (isInLens_(globalPos)) + return 0.2; + return 0.4; + } +``` + +We set the parameter object for the Van Genuchten material law. + +```cpp + template + const MaterialLawParams& materialLawParams(const Element& element, + const SubControlVolume& scv, + const ElementSolution& elemSol) const + { + if (isInLens_(element.geometry().center())) + return lensMaterialParams_; + return outerMaterialParams_; + } +``` + +Here we can define which phase is to be considered as the wetting phase. Here the wetting phase is the the first phase of the fluidsystem. In this case that is water. + +```cpp + template + int wettingPhaseAtPos(const GlobalPosition& globalPos) const + { return FluidSystem::phase0Idx; } +``` + +The remainder of this class contains a convenient function to determine if +a position is inside the lens and defines the data members. +
Click to show private data members and member functions + +```cpp +private: + // we have a convenience definition of the position of the lens + bool isInLens_(const GlobalPosition &globalPos) const + { + for (int i = 0; i < dimWorld; ++i) { + if (globalPos[i] < lensLowerLeft_[i] + eps_ || globalPos[i] > lensUpperRight_[i] - eps_) + return false; + } + return true; + } + + GlobalPosition lensLowerLeft_; + GlobalPosition lensUpperRight_; + + Scalar lensK_; + Scalar outerK_; + MaterialLawParams lensMaterialParams_; + MaterialLawParams outerMaterialParams_; + + static constexpr Scalar eps_ = 1.5e-7; +}; + +} // end namespace Dumux +``` + +
+ +
+ + +| [:arrow_left: Back to the main documentation](../README.md) | [:arrow_right: Continue with part 2](main.md) | +|---|---:| + diff --git a/examples/2pinfiltration/doc/2p_intro.md b/examples/2pinfiltration/doc/2p_intro.md new file mode 100644 index 0000000000..235417ffed --- /dev/null +++ b/examples/2pinfiltration/doc/2p_intro.md @@ -0,0 +1,7 @@ +# Part 1: Implementation of the 2p set-up + +The two-phase flow set-up is implemented in the files `properties.hh`, +`problem.hh` and `spatialparams.hh`. In the file `problem.hh` a description of the boundary and initial conditions can be found. Additionally, you can see how to implement an injection well as a point source and how to read the initial solution from a text file. In the file `spatialparams.hh` we create a lens within the porous medium, that has different spatial parameters than the surrounding material and set the parameters for the +$`p_c - S_w`$ relationship. + +[[_TOC_]] diff --git a/examples/2pinfiltration/doc/intro.md b/examples/2pinfiltration/doc/_intro.md similarity index 96% rename from examples/2pinfiltration/doc/intro.md rename to examples/2pinfiltration/doc/_intro.md index d16dd16e1c..6ed89c3a77 100644 --- a/examples/2pinfiltration/doc/intro.md +++ b/examples/2pinfiltration/doc/_intro.md @@ -4,10 +4,11 @@ __In this example, you will learn how to__ * solve a two-phase flow in porous media problem with two immiscible phases * set boundary conditions and a simple injection well -* specify a lens with different porous material parameters -* use adaptive grid refinement around the saturation front * specify a point source * read the initial solution from a text file +* specify a lens with different porous material parameters +* use adaptive grid refinement around the saturation front + __Prerequisites__. You need [dune-alugrid](https://gitlab.dune-project.org/extensions/dune-alugrid) in order to compile and run this example. @@ -69,3 +70,4 @@ For more information about the discretization please have a look at the [handboo ├── spatialparams.hh -> spatial parameter fields └── initialsolutioncc.txt -> text file with initial solution ``` +In the documentations behind the links provided in the following, you will find a detailed description how the the above mentioned set-up is realized in this example. diff --git a/examples/2pinfiltration/doc/main.md b/examples/2pinfiltration/doc/main.md new file mode 100644 index 0000000000..e1295b8b9a --- /dev/null +++ b/examples/2pinfiltration/doc/main.md @@ -0,0 +1,388 @@ + + + +| [:arrow_left: Back to the main documentation](../README.md) | [:arrow_left: Go back to part 1](2p.md) | +|---|---:| + +# Part 2: Main program flow + +This main program flow is implemented in the `main()` function +of the program which is defined in the file `main.cc` described below. Additionally, we can see how to implement an adaptive grid with a saturation dependent indicator. + +The code documentation is structured as follows: + +[[_TOC_]] + + +## The file `main.cc` + +
+Click to hide/show the file documentation (or inspect the [source code](../main.cc)) + + +This is the main file for the 2pinfiltration example. Here we can see the programme sequence and how the system is solved using Newton's method +### Included header files +
Click to show includes + +```cpp +#include + +// Standard header file for C++, for in- and output. +#include +``` + +A Dune helper class for enabling parallel simulations with MPI + +```cpp +#include +``` + +In Dumux, a property system is used to specify the model. For this, different properties are defined containing type definitions, values and methods. All properties are declared in the file properties.hh. Additionally, we include the parameter class, which manages the definition of input parameters by a default value, the inputfile or the command line. + +```cpp +#include +#include +``` + +We include the linear solver to be used to solve the linear system and the nonlinear Newton's method + +```cpp +#include +#include +#include +``` + +Further, we include assembler, which assembles the linear systems for finite volume schemes (box-scheme, tpfa-approximation, mpfa-approximation) and a file that defines the different differentiation methods used to compute the derivatives of the residual + +```cpp +#include +#include +``` + +We need the following class to simplify the writing of dumux simulation data to VTK format. + +```cpp +#include +``` + +The gridmanager constructs a grid from the information in the input or grid file. + +```cpp +#include +``` + +We include several files which are needed for the adaptive grid + +```cpp +#include +#include +#include +#include +#include +``` + +Finally, we include the properties which configure the simulation + +```cpp +#include "properties.hh" +``` + +
+ +### The main function +At the beginning of the simulation, we create a type tag with a suitable alias for our problem. // This will contain all the properties that are needed to define the problem set-up and the model we use. Additionally, we have to create an instance of `Dune::MPIHelper` and parse the run-time arguments: + +```cpp +int main(int argc, char** argv) try +{ + using namespace Dumux; + + // we define the type tag for this problem + using TypeTag = Properties::TTag::PointSourceExample; + + //We initialize MPI, finalize is done automatically on exit + const auto& mpiHelper = Dune::MPIHelper::instance(argc, argv); + + //We parse command line arguments and input file + Parameters::init(argc, argv); +``` + +#### Create the grid +A gridmanager tries to create the grid either from a grid file or the input file. + +```cpp + GridManager> gridManager; + gridManager.init(); + + // The instationary non-linear problem is run on this grid. + // + // we compute on the leaf grid view + const auto& leafGridView = gridManager.grid().leafGridView(); +``` + +#### Set-up of the problem + +We create and initialize the finite volume grid geometry, the problem, the linear system, including the jacobian matrix, the residual and the solution vector and the gridvariables. + +We need the finite volume geometry to build up the subcontrolvolumes (scv) and subcontrolvolume faces (scvf) for each element of the grid partition. + +```cpp + using GridGeometry = GetPropType; + auto gridGeometry = std::make_shared(leafGridView); + gridGeometry->update(); +``` + +In the problem, we define the boundary and initial conditions and compute the point sources. The `computePointSourceMap` method is inherited from the fvproblem and therefore specified in the `dumux/common/fvproblem.hh`. It calls the `addPointSources` method specified in the `problem.hh` file. + +```cpp + using Problem = GetPropType; + auto problem = std::make_shared(gridGeometry); + // We call the `computePointSourceMap` method to compute the point sources. + problem->computePointSourceMap(); +``` + +We initialize the solution vector and then use the solution vector to intialize the `gridVariables`. + +```cpp + using SolutionVector = GetPropType; + SolutionVector x; + problem->applyInitialSolution(x); + auto xOld = x; + + using GridVariables = GetPropType; + auto gridVariables = std::make_shared(problem, gridGeometry); + gridVariables->init(x); +``` + +##### Grid adaption +We instantiate the indicator for grid adaption & the data transfer, we read some parameters for indicator from the input file. + +```cpp + using Scalar = GetPropType; + const Scalar refineTol = getParam("Adaptive.RefineTolerance"); + const Scalar coarsenTol = getParam("Adaptive.CoarsenTolerance"); + // We use an indicator for a two-phase flow problem that is saturation-dependent. + // It is defined in the file `dumux/porousmediumflow/2p/gridadaptindicator.hh.` + // and allows to set the minimum and maximum allowed refinement levels via the input parameters. + TwoPGridAdaptIndicator indicator(gridGeometry); + // The data transfer performs the transfer of data on a grid from before to after adaptation + // and is defined in the file `dumux/porousmediumflow/2p/griddatatransfer.hh`. + // Its main functions are to store and reconstruct the primary variables. + TwoPGridDataTransfer dataTransfer(problem, gridGeometry, gridVariables, x); +``` + +We do an initial refinement around sources/BCs. We use the `GridAdaptInitializationIndicator` defined in `dumux/adaptive/initializationindicator.hh` for that. + +```cpp + GridAdaptInitializationIndicator initIndicator(problem, gridGeometry, gridVariables); +``` + +We refine up to the maximum level. For every level, the indicator used for the refinement/coarsening is calculated. If any grid cells have to be adapted, the gridvariables and the pointsourcemap are updated. + +```cpp + const auto maxLevel = getParam("Adaptive.MaxLevel", 0); + for (std::size_t i = 0; i < maxLevel; ++i) + { + //we calculate the initial indicator for adaption for each grid cell using the initial solution x + initIndicator.calculate(x); + + //and then we mark the elements that were adapted. + bool wasAdapted = false; + if (markElements(gridManager.grid(), initIndicator)) + wasAdapted = adapt(gridManager.grid(), dataTransfer); + + // In case of a grid adaptation, the gridvariables and the pointsourcemap are updated. + if (wasAdapted) + { + // We overwrite the old solution with the new (resized & interpolated) one + xOld = x; + //We initialize the secondary variables to the new (and "new old") solution + gridVariables->updateAfterGridAdaption(x); + // we update the point source map after adaption + problem->computePointSourceMap(); + } + } +``` + +Depending on the initial conditions, another grid adaptation might be necessary. +The gridadaptindicator uses the input parameters `Adaptive.RefineTolerance` and `Adaptive.CoarsenTolerance` for this step. +Again, if elements were adapted, we mark them and update gridvariables and the pointsourcemap accordingly. + +```cpp + indicator.calculate(x, refineTol, coarsenTol); + + //we mark the elements that were adapted + bool wasAdapted = false; + if (markElements(gridManager.grid(), indicator)) + wasAdapted = adapt(gridManager.grid(), dataTransfer); + + // In case of an additional grid adaptation, the gridvariables and the pointsourcemap are updated again. + if (wasAdapted) + { + // Overwrite the old solution with the new (resized & interpolated) one + xOld = x; + // Initialize the secondary variables to the new (and "new old") solution + gridVariables->updateAfterGridAdaption(x); + // Update the point source map + problem->computePointSourceMap(); + } +``` + +#### Solving the problem +We get some time loop parameters from the input file params.input + +```cpp + using Scalar = GetPropType; + const auto tEnd = getParam("TimeLoop.TEnd"); + const auto maxDt = getParam("TimeLoop.MaxTimeStepSize"); + const auto dt = getParam("TimeLoop.DtInitial"); +``` + +and initialize the vtkoutput. Each model has a predefined model specific output with relevant parameters for that model. + +```cpp + using IOFields = GetPropType; + VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); + using VelocityOutput = GetPropType; + vtkWriter.addVelocityOutput(std::make_shared(*gridVariables)); + IOFields::initOutputModule(vtkWriter); // Add model specific output fields + vtkWriter.write(0.0); +``` + +We instantiate the time loop + +```cpp + auto timeLoop = std::make_shared>(0, dt, tEnd); + timeLoop->setMaxTimeStepSize(maxDt); +``` + +and set the assembler with the time loop because we have an instationary problem + +```cpp + using Assembler = FVAssembler; + auto assembler = std::make_shared(problem, gridGeometry, gridVariables, timeLoop, xOld); +``` + +We set the linear solver and the non-linear solver + +```cpp + using LinearSolver = AMGBiCGSTABBackend>; + auto linearSolver = std::make_shared(leafGridView, gridGeometry->dofMapper()); + + using NewtonSolver = Dumux::NewtonSolver; + NewtonSolver nonLinearSolver(assembler, linearSolver); +``` + +##### The time loop +We start the time loop. In each time step before we start calculating a new solution we check if we have to refine the mesh again based on the solution of the previous time step. If the grid is adapted we update the gridvariables and the pointsourcemap. Afterwards, the solution of that time step is calculated. + +```cpp + timeLoop->start(); do + { + // We only want to refine/coarsen after first time step is finished, not before. + //The initial refinement was already done before the start of the time loop. + //This means we only refine when the time is greater than 0. + if (timeLoop->time() > 0) + { + // again we compute the refinement indicator with the `TwoPGridAdaptIndicator` + indicator.calculate(x, refineTol, coarsenTol); + + //we mark elements and adapt grid if necessary + wasAdapted = false; + if (markElements(gridManager.grid(), indicator)) + wasAdapted = adapt(gridManager.grid(), dataTransfer); + + //In case of a grid adaptation, the gridvariables and the pointsourcemap are updated again. + if (wasAdapted) + { + // We overwrite the old solution with the new (resized & interpolated) one + xOld = x; + // We tell the assembler to resize the matrix and set pattern + assembler->setJacobianPattern(); + // We tell the assembler to resize the residual + assembler->setResidualSize(); + // We initialize the secondary variables to the new (and "new old") solution + gridVariables->updateAfterGridAdaption(x); + // We update the point source map + problem->computePointSourceMap(); + } + // we leave the refinement step + } + + // We solve the non-linear system with time step control. + nonLinearSolver.solve(x, *timeLoop); + + //We make the new solution the old solution. + xOld = x; + gridVariables->advanceTimeStep(); + + //We advance to the time loop to the next step. + timeLoop->advanceTimeStep(); + + //We write vtk output for each time step + vtkWriter.write(timeLoop->time()); + + //We report statistics of this time step + timeLoop->reportTimeStep(); + + //We set a new dt as suggested by the newton solver for the next time step + timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize())); + + } while (!timeLoop->finished()); +``` + +The following piece of code prints a final status report of the time loop +before the program is terminated and we print he dumux end message + +```cpp + timeLoop->finalize(leafGridView.comm()); + + // print dumux end message + if (mpiHelper.rank() == 0) + Parameters::print(); + + return 0; +} // end main +``` + +### Exception handling +In this part of the main file we catch and print possible exceptions that could +occur during the simulation. +
Click to show exception handler + +```cpp +// errors related to run-time parameters +catch (const Dumux::ParameterException &e) +{ + std::cerr << std::endl << e << " ---> Abort!" << std::endl; + return 1; +} +catch (const Dune::DGFException & e) +{ + std::cerr << "DGF exception thrown (" << e << + "). Most likely, the DGF file name is wrong " + "or the DGF file is corrupted, " + "e.g. missing hash at end of file or wrong number (dimensions) of entries." + << " ---> Abort!" << std::endl; + return 2; +} +catch (const Dune::Exception &e) +{ + std::cerr << "Dune reported error: " << e << " ---> Abort!" << std::endl; + return 3; +} +catch (...) +{ + std::cerr << "Unknown exception thrown! ---> Abort!" << std::endl; + return 4; +} +``` + +
+ +
+ + +| [:arrow_left: Back to the main documentation](../README.md) | [:arrow_left: Go back to part 1](2p.md) | +|---|---:| + diff --git a/examples/2pinfiltration/doc/main_intro.md b/examples/2pinfiltration/doc/main_intro.md new file mode 100644 index 0000000000..cb7b9fef0f --- /dev/null +++ b/examples/2pinfiltration/doc/main_intro.md @@ -0,0 +1,8 @@ +# Part 2: Main program flow + +This main program flow is implemented in the `main()` function +of the program which is defined in the file `main.cc` described below. Additionally, we can see how to implement an adaptive grid with a saturation dependent indicator. + +The code documentation is structured as follows: + +[[_TOC_]] diff --git a/examples/2pinfiltration/main.cc b/examples/2pinfiltration/main.cc index 32b1fbbc18..80458c97f4 100644 --- a/examples/2pinfiltration/main.cc +++ b/examples/2pinfiltration/main.cc @@ -20,46 +20,35 @@ // [[content]] // // This is the main file for the 2pinfiltration example. Here we can see the programme sequence and how the system is solved using Newton's method -// ### Includes +// ### Included header files +// [[details]] includes +// [[codeblock]] #include - -// Standard header file for C++, to get time and date information. -#include - // Standard header file for C++, for in- and output. #include +// [[/codeblock]] -// Dumux is based on DUNE, the Distributed and Unified Numerics Environment, which provides several grid managers and linear solvers. So we need some includes from that. +// A Dune helper class for enabling parallel simulations with MPI #include -#include -#include -#include -#include -// In Dumux, a property system is used to specify the model. For this, different properties are defined containing type definitions, values and methods. All properties are declared in the file properties.hh. +// In Dumux, a property system is used to specify the model. For this, different properties are defined containing type definitions, values and methods. All properties are declared in the file properties.hh. Additionally, we include the parameter class, which manages the definition of input parameters by a default value, the inputfile or the command line. #include -// The following file contains the parameter class, which manages the definition of input parameters by a default value, the inputfile or the command line. #include -// The file dumuxmessage.hh contains the class defining the start and end message of the simulation. -#include -#include -//we include the linear solver to be used to solve the linear system +//We include the linear solver to be used to solve the linear system and the nonlinear Newton's method #include #include -//we include the nonlinear Newton's method #include -// Further, we include assembler, which assembles the linear systems for finite volume schemes (box-scheme, tpfa-approximation, mpfa-approximation). + +// Further, we include assembler, which assembles the linear systems for finite volume schemes (box-scheme, tpfa-approximation, mpfa-approximation) and a file that defines the different differentiation methods used to compute the derivatives of the residual #include -// The containing class in the following file defines the different differentiation methods used to compute the derivatives of the residual. #include -// we include the spatial discretization methods available in Dumux -#include + // We need the following class to simplify the writing of dumux simulation data to VTK format. #include -// The gridmanager constructs a grid from the information in the input or grid file. There is a specification for the different supported grid managers. -#include +// The gridmanager constructs a grid from the information in the input or grid file. +#include //We include several files which are needed for the adaptive grid #include @@ -70,8 +59,12 @@ // Finally, we include the properties which configure the simulation #include "properties.hh" +// [[/details]] +// -// ### Beginning of the main function +// ### The main function +// At the beginning of the simulation, we create a type tag with a suitable alias for our problem. // This will contain all the properties that are needed to define the problem set-up and the model we use. Additionally, we have to create an instance of `Dune::MPIHelper` and parse the run-time arguments: +// [[codeblock]] int main(int argc, char** argv) try { using namespace Dumux; @@ -82,15 +75,13 @@ int main(int argc, char** argv) try //We initialize MPI, finalize is done automatically on exit const auto& mpiHelper = Dune::MPIHelper::instance(argc, argv); - //We print dumux start message - if (mpiHelper.rank() == 0) - DumuxMessage::print(/*firstCall=*/true); - //We parse command line arguments and input file Parameters::init(argc, argv); + // [[/codeblock]] - // ### Create the grid + // #### Create the grid // A gridmanager tries to create the grid either from a grid file or the input file. + // [[codeblock]] GridManager> gridManager; gridManager.init(); @@ -98,10 +89,10 @@ int main(int argc, char** argv) try // // we compute on the leaf grid view const auto& leafGridView = gridManager.grid().leafGridView(); + // [[/codeblock]] - // ### Set-up and solving of the problem + // #### Set-up of the problem // - // #### Set-up // We create and initialize the finite volume grid geometry, the problem, the linear system, including the jacobian matrix, the residual and the solution vector and the gridvariables. // // We need the finite volume geometry to build up the subcontrolvolumes (scv) and subcontrolvolume faces (scvf) for each element of the grid partition. @@ -109,36 +100,45 @@ int main(int argc, char** argv) try auto gridGeometry = std::make_shared(leafGridView); gridGeometry->update(); - // In the problem, we define the boundary and initial conditions. + // In the problem, we define the boundary and initial conditions and compute the point sources. The `computePointSourceMap` method is inherited from the fvproblem and therefore specified in the `dumux/common/fvproblem.hh`. It calls the `addPointSources` method specified in the `problem.hh` file. + // [[codeblock]] using Problem = GetPropType; auto problem = std::make_shared(gridGeometry); - // We call the `computePointSourceMap` method to compute the point sources. The `computePointSourceMap` method is inherited from the fvproblem and therefore specified in the `dumux/common/fvproblem.hh`. It calls the `addPointSources` method specified in the `problem.hh` file. + // We call the `computePointSourceMap` method to compute the point sources. problem->computePointSourceMap(); + // [[/codeblock]] - // We initialize the solution vector, + // We initialize the solution vector and then use the solution vector to intialize the `gridVariables`. using SolutionVector = GetPropType; - SolutionVector x(gridGeometry->numDofs()); + SolutionVector x; problem->applyInitialSolution(x); auto xOld = x; - // and then use the solution vector to intialize the `gridVariables`. using GridVariables = GetPropType; auto gridVariables = std::make_shared(problem, gridGeometry); gridVariables->init(x); - //We instantiate the indicator for grid adaption & the data transfer, we read some parameters for indicator from the input file. + // ##### Grid adaption + // We instantiate the indicator for grid adaption & the data transfer, we read some parameters for indicator from the input file. + // [[codeblock]] using Scalar = GetPropType; const Scalar refineTol = getParam("Adaptive.RefineTolerance"); const Scalar coarsenTol = getParam("Adaptive.CoarsenTolerance"); - // We use an indicator for a two-phase flow problem that is saturation-dependent and defined in the file `dumux/porousmediumflow/2p/gridadaptindicator.hh.` It allows to set the minimum and maximum allowed refinement levels via the input parameters. + // We use an indicator for a two-phase flow problem that is saturation-dependent. + // It is defined in the file `dumux/porousmediumflow/2p/gridadaptindicator.hh.` + // and allows to set the minimum and maximum allowed refinement levels via the input parameters. TwoPGridAdaptIndicator indicator(gridGeometry); - // The data transfer performs the transfer of data on a grid from before to after adaptation and is defined in the file `dumux/porousmediumflow/2p/griddatatransfer.hh`. Its main functions are to store and reconstruct the primary variables. + // The data transfer performs the transfer of data on a grid from before to after adaptation + // and is defined in the file `dumux/porousmediumflow/2p/griddatatransfer.hh`. + // Its main functions are to store and reconstruct the primary variables. TwoPGridDataTransfer dataTransfer(problem, gridGeometry, gridVariables, x); + // [[/codeblock]] // We do an initial refinement around sources/BCs. We use the `GridAdaptInitializationIndicator` defined in `dumux/adaptive/initializationindicator.hh` for that. GridAdaptInitializationIndicator initIndicator(problem, gridGeometry, gridVariables); //We refine up to the maximum level. For every level, the indicator used for the refinement/coarsening is calculated. If any grid cells have to be adapted, the gridvariables and the pointsourcemap are updated. + // [[codeblock]] const auto maxLevel = getParam("Adaptive.MaxLevel", 0); for (std::size_t i = 0; i < maxLevel; ++i) { @@ -161,8 +161,12 @@ int main(int argc, char** argv) try problem->computePointSourceMap(); } } + // [[/codeblock]] - // Depending on the initial conditions, another grid adaptation might be necessary. The gridadaptindicator uses the input parameters `Adaptive.RefineTolerance` and `Adaptive.CoarsenTolerance` for this step. + // Depending on the initial conditions, another grid adaptation might be necessary. + //The gridadaptindicator uses the input parameters `Adaptive.RefineTolerance` and `Adaptive.CoarsenTolerance` for this step. + //Again, if elements were adapted, we mark them and update gridvariables and the pointsourcemap accordingly. + // [[codeblock]] indicator.calculate(x, refineTol, coarsenTol); //we mark the elements that were adapted @@ -170,7 +174,7 @@ int main(int argc, char** argv) try if (markElements(gridManager.grid(), indicator)) wasAdapted = adapt(gridManager.grid(), dataTransfer); - //In case of an additional grid adaptation, the gridvariables and the pointsourcemap are updated again. + // In case of an additional grid adaptation, the gridvariables and the pointsourcemap are updated again. if (wasAdapted) { // Overwrite the old solution with the new (resized & interpolated) one @@ -180,14 +184,17 @@ int main(int argc, char** argv) try // Update the point source map problem->computePointSourceMap(); } + // [[/codeblock]] + + // #### Solving the problem - //We get some time loop parameters from the input file params.input + // We get some time loop parameters from the input file params.input using Scalar = GetPropType; const auto tEnd = getParam("TimeLoop.TEnd"); const auto maxDt = getParam("TimeLoop.MaxTimeStepSize"); - auto dt = getParam("TimeLoop.DtInitial"); + const auto dt = getParam("TimeLoop.DtInitial"); - //and initialize the vtkoutput. Each model has a predefined model specific output with relevant parameters for that model. + // and initialize the vtkoutput. Each model has a predefined model specific output with relevant parameters for that model. using IOFields = GetPropType; VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); using VelocityOutput = GetPropType; @@ -195,26 +202,29 @@ int main(int argc, char** argv) try IOFields::initOutputModule(vtkWriter); // Add model specific output fields vtkWriter.write(0.0); - //we instantiate the time loop + // We instantiate the time loop auto timeLoop = std::make_shared>(0, dt, tEnd); timeLoop->setMaxTimeStepSize(maxDt); - //we set the assembler with the time loop because we have an instationary problem + // and set the assembler with the time loop because we have an instationary problem using Assembler = FVAssembler; - auto assembler = std::make_shared(problem, gridGeometry, gridVariables, timeLoop); + auto assembler = std::make_shared(problem, gridGeometry, gridVariables, timeLoop, xOld); - // we set the linear solver + // We set the linear solver and the non-linear solver using LinearSolver = AMGBiCGSTABBackend>; auto linearSolver = std::make_shared(leafGridView, gridGeometry->dofMapper()); - // additionally we set the non-linear solver. using NewtonSolver = Dumux::NewtonSolver; NewtonSolver nonLinearSolver(assembler, linearSolver); - //we start the time loop. In each time step before we start calculating a new solution we check if we have to refine the mesh again based on the solution of the previous time step. + // ##### The time loop + // We start the time loop. In each time step before we start calculating a new solution we check if we have to refine the mesh again based on the solution of the previous time step. If the grid is adapted we update the gridvariables and the pointsourcemap. Afterwards, the solution of that time step is calculated. + // [[codeblock]] timeLoop->start(); do { - // We only want to refine/coarsen after first time step is finished, not before. The initial refinement was already done before the start of the time loop. This means we only refine when the time is greater than 0. + // We only want to refine/coarsen after first time step is finished, not before. + //The initial refinement was already done before the start of the time loop. + //This means we only refine when the time is greater than 0. if (timeLoop->time() > 0) { // again we compute the refinement indicator with the `TwoPGridAdaptIndicator` @@ -242,9 +252,6 @@ int main(int argc, char** argv) try // we leave the refinement step } - // Now, we start to calculate the new solution of that time step. First, we define the old solution as the solution of the previous time step for storage evaluations. - assembler->setPreviousSolution(xOld); - // We solve the non-linear system with time step control. nonLinearSolver.solve(x, *timeLoop); @@ -265,26 +272,32 @@ int main(int argc, char** argv) try timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize())); } while (!timeLoop->finished()); + // [[/codeblock]] + // The following piece of code prints a final status report of the time loop + // before the program is terminated and we print he dumux end message + // [[codeblock]] timeLoop->finalize(leafGridView.comm()); - // ### Final Output - // // print dumux end message if (mpiHelper.rank() == 0) - { Parameters::print(); - DumuxMessage::print(/*firstCall=*/false); - } return 0; } // end main -catch (Dumux::ParameterException &e) +//[[/codeblock]] +// ### Exception handling +// In this part of the main file we catch and print possible exceptions that could +// occur during the simulation. +// [[details]] exception handler +// [[codeblock]] +// errors related to run-time parameters +catch (const Dumux::ParameterException &e) { std::cerr << std::endl << e << " ---> Abort!" << std::endl; return 1; } -catch (Dune::DGFException & e) +catch (const Dune::DGFException & e) { std::cerr << "DGF exception thrown (" << e << "). Most likely, the DGF file name is wrong " @@ -293,7 +306,7 @@ catch (Dune::DGFException & e) << " ---> Abort!" << std::endl; return 2; } -catch (Dune::Exception &e) +catch (const Dune::Exception &e) { std::cerr << "Dune reported error: " << e << " ---> Abort!" << std::endl; return 3; @@ -303,4 +316,6 @@ catch (...) std::cerr << "Unknown exception thrown! ---> Abort!" << std::endl; return 4; } +// [[/codeblock]] +// [[/details]] // [[/content]] diff --git a/examples/2pinfiltration/params.input b/examples/2pinfiltration/params.input index 1da8c17073..e49c6f4dd3 100644 --- a/examples/2pinfiltration/params.input +++ b/examples/2pinfiltration/params.input @@ -6,8 +6,6 @@ TEnd = 500 # [s] UpperRight = 6 4 Cells = 48 32 Refinement = 1 -CellType = Cube -ClosureType = Green [SpatialParams] LensLowerLeft = 1.0 2.0 # [m] coordinates of the lower left lens corner diff --git a/examples/2pinfiltration/problem.hh b/examples/2pinfiltration/problem.hh index 8fb6e92095..8cb927a672 100644 --- a/examples/2pinfiltration/problem.hh +++ b/examples/2pinfiltration/problem.hh @@ -24,9 +24,10 @@ // [[content]] // // ### Includes -// We start with includes for `PorousMediumFlowProblem` and `readFileToContainer` (used below). +// We start with includes for `PorousMediumFlowProblem`, `readFileToContainer` and `GetPropType` (used below). #include #include +#include // ### Problem class // The problem class `PointSourceProblem` implements boundary and initial conditions. @@ -37,15 +38,15 @@ template class PointSourceProblem : public PorousMediumFlowProblem { // The class implementation starts with some alias declarations and index definitions for convenience - //
Click to show local alias declarations and indices + // [[details]] local alias declarations and indices using ParentType = PorousMediumFlowProblem; - using GridView = typename GetPropType::GridView; + using GridGeometry = GetPropType; + using GridView = typename GridGeometry::GridView; using Element = typename GridView::template Codim<0>::Entity; using Vertex = typename GridView::template Codim::Entity; using Scalar = GetPropType; using FluidSystem = GetPropType; using PrimaryVariables = GetPropType; - using GridGeometry = GetPropType; using PointSource = GetPropType; using BoundaryTypes = GetPropType; using GlobalPosition = typename Element::Geometry::GlobalCoordinate; @@ -59,7 +60,7 @@ class PointSourceProblem : public PorousMediumFlowProblem waterPhaseIdx = FluidSystem::phase0Idx, dnaplPhaseIdx = FluidSystem::phase1Idx }; - //
+ // [[/details]] // // In the constructor of the class, we call the parent type's constructor // and read the intial values for the primary variables from a text file. @@ -78,7 +79,7 @@ public: return 293.15; // 10°C } - // ### 1. Boundary types + // #### Boundary types // We define the type of boundary conditions depending on location. Two types of boundary conditions // can be specified: Dirichlet or Neumann boundary condition. On a Dirichlet boundary, the values of the // primary variables need to be fixed. On a Neumann boundary condition, values for derivatives need to be fixed. @@ -97,7 +98,7 @@ public: } // [[/codeblock]] - // ### 2. Dirichlet boundaries + // #### Dirichlet boundaries // We specify the values for the Dirichlet boundaries, depending on location. // We need to fix values for the two primary variables: the water pressure // and the DNAPL saturation. @@ -112,14 +113,14 @@ public: fluidState.setPressure(dnaplPhaseIdx, /*pressure=*/1e5); // The density is then calculated by the fluid system: - Scalar densityW = FluidSystem::density(fluidState, waterPhaseIdx); + const Scalar densityW = FluidSystem::density(fluidState, waterPhaseIdx); // The water phase pressure is the hydrostatic pressure, scaled with a factor: - Scalar height = this->gridGeometry().bBoxMax()[1] - this->gridGeometry().bBoxMin()[1]; - Scalar depth = this->gridGeometry().bBoxMax()[1] - globalPos[1]; - Scalar alpha = 1 + 1.5/height; - Scalar width = this->gridGeometry().bBoxMax()[0] - this->gridGeometry().bBoxMin()[0]; - Scalar factor = (width*alpha + (1.0 - alpha)*globalPos[0])/width; + const Scalar height = this->gridGeometry().bBoxMax()[1] - this->gridGeometry().bBoxMin()[1]; + const Scalar depth = this->gridGeometry().bBoxMax()[1] - globalPos[1]; + const Scalar alpha = 1 + 1.5/height; + const Scalar width = this->gridGeometry().bBoxMax()[0] - this->gridGeometry().bBoxMin()[0]; + const Scalar factor = (width*alpha + (1.0 - alpha)*globalPos[0])/width; values[pressureH2OIdx] = 1e5 - factor*densityW*this->spatialParams().gravity(globalPos)[1]*depth; // The saturation of the DNAPL Trichlorethene is zero on our Dirichlet boundary: @@ -129,7 +130,7 @@ public: } // [[/codeblock]] - // ### 3. Neumann boundaries + // #### Neumann boundaries // In our case, we need to specify mass fluxes for our two liquid phases. // Negative sign means influx and the unit of the boundary flux is $`kg/(m^2 s)`$. // On the inlet area, we set a DNAPL influx of $`0.04 kg/(m^2 s)`$. On all other @@ -145,7 +146,7 @@ public: } // [[/codeblock]] - // ### 4. Initial conditions + // #### Initial conditions // The initial condition needs to be set for all primary variables. // Here, we take the data from the file that we read in previously. // [[codeblock]] @@ -155,15 +156,15 @@ public: // Accordingly, we need to find the index of our cells, depending on the x and y coordinates, // that corresponds to the indices of the input data set. const auto delta = 0.0625; - unsigned int cellsX = this->gridGeometry().bBoxMax()[0]/delta; + const unsigned int cellsX = this->gridGeometry().bBoxMax()[0]/delta; const auto globalPos = element.geometry().center(); - unsigned int dataIdx = std::trunc(globalPos[1]/delta) * cellsX + std::trunc(globalPos[0]/delta); + const unsigned int dataIdx = std::trunc(globalPos[1]/delta) * cellsX + std::trunc(globalPos[0]/delta); return initialValues_[dataIdx]; } // [[/codeblock]] - // ### 5. Point source + // #### Point source // In this scenario, we set a point source (e.g. modeling a well). The point source value can be solution dependent. // Point sources are added by pushing them into the vector `pointSources`. // The `PointSource` constructor takes two arguments. @@ -178,7 +179,7 @@ public: // In the private part of the class, we define some helper functions for // the boundary conditions and local variables. - //
Click to show private data members and functions + // [[details]] private data members and functions private: bool onLeftBoundary_(const GlobalPosition &globalPos) const { return globalPos[0] < this->gridGeometry().bBoxMin()[0] + eps_; } @@ -201,6 +202,6 @@ private: }; } // end namespace Dumux -//
+// [[/details]] // [[/content]] #endif diff --git a/examples/2pinfiltration/properties.hh b/examples/2pinfiltration/properties.hh index 31a977f215..29bce1bc00 100644 --- a/examples/2pinfiltration/properties.hh +++ b/examples/2pinfiltration/properties.hh @@ -25,7 +25,7 @@ // // ### Includes // The header includes will be mentioned in the text below. -//
Click to show the header includes +// [[details]] header includes #include #include @@ -39,9 +39,9 @@ #include "spatialparams.hh" #include "problem.hh" -//
+// [[/details]] // - +// ### Type tag definition // All properties are defined in the (nested) namespace // `Dumux::Properties`. To get and set properties, we need the definitions and implementations from the // header `dumux/common/properties.hh` included above. @@ -61,7 +61,7 @@ namespace Dumux::Properties { namespace TTag { struct PointSourceExample { using InheritsFrom = std::tuple; }; } - +// ### Property specializations // Next, we specialize the properties `Problem` and `SpatialParams` for our new TypeTag and // set the type to our problem and spatial parameter classes implemented // in `problem.hh` and `spatialparams.hh`. diff --git a/examples/2pinfiltration/spatialparams.hh b/examples/2pinfiltration/spatialparams.hh index 14cd6a117e..ee1a68c240 100644 --- a/examples/2pinfiltration/spatialparams.hh +++ b/examples/2pinfiltration/spatialparams.hh @@ -24,16 +24,18 @@ // [[content]] // // ### Includes -// we include the basic spatial parameters for finite volumes file from which we will inherit +// We include the basic spatial parameters for finite volumes file from which we will inherit #include -// we include all laws which are needed to define the interaction between the solid matrix and the fluids, e.g. laws for capillary pressure saturation relationships. +// We include all laws which are needed to define the interaction between the solid matrix and the fluids, e.g. laws for capillary pressure saturation relationships. #include #include +// ### The spatial parameters class +// In the TwoPTestSpatialParams class we define all functions needed to describe the porous matrix, e.g. porosity and permeability. We inherit from the `FVSpatialParams` class, which is the base class for multiphase porous medium flow applications. +// [[codeblock]] namespace Dumux { -// In the TwoPTestSpatialParams class we define all functions needed to describe the porous matrix, e.g. porosity and permeability template class TwoPTestSpatialParams : public FVSpatialParams> @@ -55,30 +57,39 @@ public: using MaterialLaw = EffToAbsLaw; using MaterialLawParams = typename MaterialLaw::Params; using PermeabilityType = Scalar; + // [[/codeblock]] + //Here, we get parameters for the position of the lens and porosity and permeability from the input file. Additionally, we set the parameters for the Van-Genuchten relationship. + // [[codeblock]] TwoPTestSpatialParams(std::shared_ptr gridGeometry) : ParentType(gridGeometry) { - //we get the position of the lens from the params.input file. The lens is defined by the position of the lower left and the upper right corner + // We get the position of the lens from the params.input file. + // The lens is defined by the position of the lower left and the upper right corner lensLowerLeft_ = getParam("SpatialParams.LensLowerLeft"); lensUpperRight_ = getParam("SpatialParams.LensUpperRight"); - //we set the parameters for the material law (here Van-Genuchten Law). First we set the residual saturations for the wetting phase and the non-wetting phase. lensMaterialParams_ define the material parameters for the lens while outerMaterialParams_ define material params for the rest of the domain. + // We set the parameters for the material law (here Van-Genuchten Law). + // First we set the residual saturations for the wetting phase and the non-wetting phase. + // lensMaterialParams_ define the material parameters for the lens while + // outerMaterialParams_ define material params for the rest of the domain. lensMaterialParams_.setSwr(0.18); lensMaterialParams_.setSnr(0.0); outerMaterialParams_.setSwr(0.05); outerMaterialParams_.setSnr(0.0); - //we set the parameters for the Van Genuchten law alpha and n + //We set the parameters for the Van Genuchten law alpha and n lensMaterialParams_.setVgAlpha(0.00045); lensMaterialParams_.setVgn(7.3); outerMaterialParams_.setVgAlpha(0.0037); outerMaterialParams_.setVgn(4.7); - //here we get the permeabilities from the params.input file. In case that no parameter is set, the default parameters (9.05e-12 and 4.6e-10) are used + //Here, we get the permeabilities from the params.input file. + //In case that no parameter is set, the default parameters (9.05e-12 and 4.6e-10) are used lensK_ = getParam("SpatialParams.lensK", 9.05e-12); outerK_ = getParam("SpatialParams.outerK", 4.6e-10); } + // [[/codeblock]] // We define the (intrinsic) permeability $`[m^2]`$. In this test, we use element-wise distributed permeabilities. template @@ -116,6 +127,10 @@ public: int wettingPhaseAtPos(const GlobalPosition& globalPos) const { return FluidSystem::phase0Idx; } + // The remainder of this class contains a convenient function to determine if + // a position is inside the lens and defines the data members. + // [[details]] private data members and member functions + // [[codeblock]] private: // we have a convenience definition of the position of the lens bool isInLens_(const GlobalPosition &globalPos) const @@ -139,5 +154,7 @@ private: }; } // end namespace Dumux +// [[/codeblock]] +// [[/details]] // [[/content]] #endif -- GitLab From 8ac386b6597e98eb2626243a6a5a67cbdc02daff Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Sat, 18 Apr 2020 10:06:12 +0200 Subject: [PATCH 12/57] Merge branch 'feature/improve-ff-example' into 'master' Improve free-flow example Closes #855 See merge request dumux-repositories/dumux!1976 (cherry picked from commit 2c74b446d04242ae019ebdaece1641fbb2183b59) --- examples/freeflowchannel/.doc_config | 2 +- examples/freeflowchannel/README.md | 523 ++++++++++++++----------- examples/freeflowchannel/doc/_intro.md | 65 +++ examples/freeflowchannel/doc/intro.md | 45 --- examples/freeflowchannel/main.cc | 208 +++++----- examples/freeflowchannel/params.input | 2 +- examples/freeflowchannel/problem.hh | 160 ++++---- examples/freeflowchannel/properties.hh | 81 +++- 8 files changed, 591 insertions(+), 495 deletions(-) create mode 100644 examples/freeflowchannel/doc/_intro.md delete mode 100644 examples/freeflowchannel/doc/intro.md diff --git a/examples/freeflowchannel/.doc_config b/examples/freeflowchannel/.doc_config index ad433016f2..6994794918 100644 --- a/examples/freeflowchannel/.doc_config +++ b/examples/freeflowchannel/.doc_config @@ -1,6 +1,6 @@ { "README.md" : [ - "doc/intro.md", + "doc/_intro.md", "properties.hh", "problem.hh", "main.cc" diff --git a/examples/freeflowchannel/README.md b/examples/freeflowchannel/README.md index d7221b3877..8a767204bf 100644 --- a/examples/freeflowchannel/README.md +++ b/examples/freeflowchannel/README.md @@ -1,10 +1,10 @@ -# Freeflow through a channel +# Free flow through a channel __You learn how to__ -* solve a free flow channel problem +* solve a free-flow channel problem * set outflow boundary conditions in the free-flow context __Results__. In this example we will obtain the following stationary velocity profile: @@ -16,22 +16,42 @@ __Table of contents__. This description is structured as follows: [[_TOC_]] ## Mathematical model -The Stokes model without gravitation and without sources or sinks for a stationary, incompressible, laminar, single phase, one-component, isothermal ($`T=10^\circ C`$) flow is considered assuming a Newtonian fluid of constant density $` \varrho = 1~\frac{\text{kg}}{\text{m}^3} `$ and constant kinematic viscosity $` \nu = 1~\frac{\text{m}^2}{\text{s}} `$. The momentum balance +In this example, the Stokes model for stationary and incompressible single phase flow is considered. +Thus, the momentum balance equations + ```math - \nabla\cdot\left(\mu\left(\nabla\boldsymbol{u}+\nabla\boldsymbol{u}^{\text{T}}\right)\right)+ \nabla p = 0 ``` -with density $`\varrho`$, velocity $`\boldsymbol{u}`$, dynamic viscosity $`\mu=\varrho\nu`$ and pressure $`p`$ and the mass balance + +and the mass balance + ```math -\nabla \cdot \left(\varrho\boldsymbol{u}\right) =0 +\nabla \cdot \left(\boldsymbol{u}\right) =0 ``` -are discretized using a staggered-grid finite-volume scheme as spatial discretization with pressures and velocity components as primary variables. For details on the discretization scheme, have a look at the Dumux [handbook](https://dumux.org/handbook). -## Problem set-up -This example contains a stationary free flow of a fluid through two parallel solid plates in two dimensions from left to right. The figure below shows the simulation set-up. The fluid flows into the system at the left with a constant velocity of $` v = 1~\frac{\text{m}}{\text{s}} `$. The inflow velocity profile is a block profile. Due to the no-slip, no-flow boundary conditions at the top and bottom plate, the velocity profile gradually assumes a parabolic shape along the channel. At the outlet, the pressure is fixed and a zero velocity gradient in x-direction is assumed. The physical domain, which is modeled is the rectangular domain $`x\in[0,10],~y\in[0,1]`$. +are solved, where $`\varrho`$ and $`\mu`$ are the density and viscosity of the fluid, +$`\boldsymbol{u}`$ is the fluid velocity and $`p`$ is the pressure. Here, we use constant fluid +properties with $`\varrho = 1~\frac{\text{kg}}{\text{m}^3}`$ and $`\mu = 1~\text{Pa}\text{s}`$. +Furthermore, isothermal conditions with a homogeneous temperature distribution of $`T=10^\circ C`$ are assumed. -![](./img/setup.png) +All equations are discretized with the staggered-grid finite-volume scheme as spatial discretization +with pressures and velocity components as primary variables. For details on the discretization scheme, +have a look at the Dumux [handbook](https://dumux.org/handbook). -In the following, we take a close look at the files containing the set-up: At first, boundary conditions are set in `problem.hh` for the Navier-Stokes model. Afterwards, we show the different steps for solving the model in the source file `main.cc`. +## Problem set-up +This example considers stationary flow of a fluid between two parallel solid plates in two dimensions. +Flow is enforced from left to right by prescribing an inflow velocity of $` v = 1~\frac{\text{m}}{\text{s}} `$ +on the left boundary, while a fixed pressure of $`p = 1.1 \text{bar}`$ and a zero velocity gradient +in x-direction are prescribed on the right boundary. On the top and bottom boundaries, no-slip +conditions are applied, which cause a parabolic velocity profile to develop along the channel. +Take a look at Figure 1 for an illustration of the domain and the boundary conditions. + +
+
+ Free-flow setup +
Fig.1 - Setup for the free flow problem.
+
+
# Implementation @@ -47,95 +67,163 @@ In the following, we take a close look at the files containing the set-up: At fi ``` -## The file `properties.hh` -In the following, we set the properties for our simulation -(click [here](https://git.iws.uni-stuttgart.de/dumux-repositories/dumux-course/blob/master/slides/dumux-course-properties.pdf) for DuMux course slides on the property system). -We start with includes -
Click to show the header includes +## Compile-time settings (`properties.hh`) + +In this file, the type tag used for this simulation is defined, +for which we then specialize properties (compile time options) to the needs of the desired setup. + + +
+Click to hide/show the file documentation (or inspect the [source code](properties.hh)) + + +### Includes +
Click to show includes + +The `NavierStokes` type tag specializes most of the properties required for Navier- +Stokes single-phase flow simulations in DuMuX. We will use this in the following to inherit the +respective properties and subsequently specialize those properties for our +type tag, which we want to modify or for which no meaningful default can be set. + +```cpp +#include +``` + +We want to use `YaspGrid`, an implementation of the dune grid interface for structured grids: ```cpp #include +``` -#include +In this example, we want to discretize the equations with the staggered-grid +scheme which is so far the only available option for free-flow models in DuMux: + +```cpp #include -#include +``` + +The fluid properties are specified in the following headers (we use a liquid with constant properties as the fluid phase): + +```cpp #include #include +``` +We include the problem header used for this simulation. + +```cpp #include "problem.hh" ```
-Then we start setting the properties. -1. For every test problem, a new `TypeTag` has to be created, which is done within the namespace `TTag` (subnamespace of `Properties`). It inherits from the Navier-Stokes flow model and the staggered-grid discretization scheme. -2. The grid is chosen to be a two-dimensional Cartesian structured grid (`YaspGrid`). -3. We set the `FluidSystem` to be a one-phase liquid with a single component. The class `Component::Constant` refers to a component with constant fluid properties (density, viscosity, ...) that can be set via the input file in the group `[0.Component]` where the number is the identifier given as template argument to the class template `Component::Constant`. -4. The problem class `ChannelExampleProblem`, which is forward declared before we enter `namespace Dumux` and defined later in this file, is defined to be the problem used in this test problem (charaterized by the TypeTag `ChannelExample`). The fluid system, which contains information about the properties such as density, viscosity or diffusion coefficient of the fluid we're simulating, is set to a constant one phase liquid. -5. We enable caching for the following classes (which stores values that were already calculated for later usage and thus results in higher memory usage but improved CPU speed): the grid volume variables, the grid flux variables, the finite volume grid geometry. +### Type tag definition + +We define a type tag for our simulation with the name `ChannelExample` +and inherit the properties specialized for the type tags `NavierStokes` and `StaggeredFreeFlowModel`. +This way, most of the properties required for Navier-Stokes single-phase flow simulations +using the staggered-grid scheme are conveniently specialized for our new type tag. +However, some properties depend on user choices and no meaningful default value can be set. +Those properties will be addressed later in this file. +Please note that, in this example, we actually want to solve the Stokes instead of the +Navier-Stokes equations. This can be achieved at runtime by setting the parameter +`Problem.EnableInertiaTerms = false`. Have a look at the input file `params.input` +to see how this is done in this example. ```cpp +// We enter the namespace Dumux::Properties in order to import the entire Dumux namespace for general use: namespace Dumux::Properties { +// declaration of the `ChannelExample` type tag for the single-phase flow problem namespace TTag { struct ChannelExample { using InheritsFrom = std::tuple; }; } // namespace TTag +``` + +### Property specializations + +In the following piece of code, mandatory properties for which no meaningful +default can be set, are specialized for our type tag `ChannelExample`. +```cpp +// This sets the grid type used for the simulation. Here, we use a structured 2D grid. template struct Grid { using type = Dune::YaspGrid<2>; }; +// This sets our problem class (see problem.hh) containing initial and boundary conditions. template struct Problem { using type = Dumux::ChannelExampleProblem ; }; +// This sets the fluid system to be used. Here, we use a liquid with constant properties as fluid phase. template struct FluidSystem { using Scalar = GetPropType; using type = FluidSystems::OnePLiquid >; }; +``` + +We also set some properties related to memory management +throughout the simulation. +
Click to show caching properties +In Dumux, one has the option to activate/deactivate the grid-wide caching of +geometries and variables. If active, the CPU time can be significantly reduced +as less dynamic memory allocation procedures are necessary. Per default, grid-wide +caching is disabled to ensure minimal memory requirements, however, in this example we +want to active all available caches, which significantly increases the memory +demand but makes the simulation faster. + + +```cpp +// This enables grid-wide caching of the volume variables. template struct EnableGridVolumeVariablesCache { static constexpr bool value = true; }; - +//This enables grid wide caching for the flux variables. template struct EnableGridFluxVariablesCache { static constexpr bool value = true; }; - +// This enables grid-wide caching for the finite volume grid geometry template struct EnableGridGeometryCache { static constexpr bool value = true; }; } // end namespace Dumux::Properties ``` +
+
-## The file `problem.hh` +## Initial and boundary conditions (`problem.hh`) + +This file contains the __problem class__ which defines the initial and boundary +conditions for the Navier-Stokes single-phase flow simulation. + + +
+Click to hide/show the file documentation (or inspect the [source code](problem.hh)) -### The problem class -We enter the problem class where all necessary initial and boundary conditions are set for our simulation. -As this is a Stokes problem, we inherit from the basic NavierStokesProblem. -
Toggle to show code: +### Include files + +The only include we need here is the `NavierStokesProblem` class, the base +class from which we will derive. ```cpp -#include #include +``` +### The problem class +We enter the problem class where all necessary boundary conditions and initial conditions are set for our simulation. +As we are solving a problem related to free flow, we inherit from the base class `NavierStokesProblem`. + +```cpp namespace Dumux { template class ChannelExampleProblem : public NavierStokesProblem { -``` - -
- -We use convenient declarations that we derive from the property system. -
-Toggle to show code (convenient declarations) - - -```cpp + // A few convenience aliases used throughout this class. using ParentType = NavierStokesProblem; using BoundaryTypes = GetPropType; using GridGeometry = GetPropType; @@ -150,18 +238,9 @@ We use convenient declarations that we derive from the property system. using GlobalPosition = typename Element::Geometry::GlobalCoordinate; public: -``` - -
- -There follows the constructor of our problem class: -Within the constructor, we set the inlet velocity to a run-time specified value. -As no run-time value is specified, we set the outlet pressure to 1.1e5 Pa. -
-Toggle to expand code (constructor) - - -```cpp + // This is the constructor of our problem class: + // Within the constructor, we set the inlet velocity to a run-time specified value. + // If no run-time value is specified, we set the outlet pressure to 1.1e5 Pa. ChannelExampleProblem(std::shared_ptr gridGeometry) : ParentType(gridGeometry) { @@ -170,39 +249,34 @@ As no run-time value is specified, we set the outlet pressure to 1.1e5 Pa. } ``` -
- -Now, we define the type of initial and boundary conditions depending on location. -Two types of boundary conditions can be specified: Dirichlet and Neumann. On a Dirichlet boundary, -the values of the primary variables need to be fixed. -On a Neumann boundary condition, values for derivatives need to be fixed. -When Dirichlet conditions are set for the pressure, the derivative of the velocity -vector with respect to the direction normal to the boundary is automatically set to -zero. This boundary condition is called in-/outflow boundary condition in Dumux. -In the following we specify Dirichlet boundaries for velocity on the left of our domain -if isInlet_ is true, Dirichlet boundaries for pressure on the right of our domain -if isOutlet_ is true and specify Dirichlet boundaries for velocity on the top and bottom -of our domain else. -
-Toggle to expand code (boundaryTypesAtPos) - +#### Boundary conditions +With the following function we define the __type of boundary conditions__ depending on the location. +Three types of boundary conditions can be specified: Dirichlet, Neumann or outflow boundary conditions. On +Dirichlet boundaries, the values of the primary variables need to be fixed. On a Neumann boundaries, +values for derivatives need to be fixed. Outflow conditions set a gradient of zero in normal direction towards the boundary +for the respective primary variables (excluding pressure). +When Dirichlet conditions are set for the pressure, the velocity gradient +with respect to the direction normal to the boundary is automatically set to zero. ```cpp - BoundaryTypes boundaryTypesAtPos(const GlobalPosition &globalPos) const + BoundaryTypes boundaryTypesAtPos(const GlobalPosition& globalPos) const { BoundaryTypes values; - if(isInlet_(globalPos)) + if (isInlet_(globalPos)) { + // We specify Dirichlet boundary conditions for the velocity on the left of our domain values.setDirichlet(Indices::velocityXIdx); values.setDirichlet(Indices::velocityYIdx); } - else if(isOutlet_(globalPos)) + else if (isOutlet_(globalPos)) { + // We fix the pressure on the right side of the domain values.setDirichlet(Indices::pressureIdx); } else { + // We specify Dirichlet boundary conditions for the velocity on the remaining boundaries (lower and upper wall) values.setDirichlet(Indices::velocityXIdx); values.setDirichlet(Indices::velocityYIdx); } @@ -211,42 +285,31 @@ of our domain else. } ``` -
- -Second, we specify the values for the Dirichlet boundaries. We need to fix the values of our primary variables. -To ensure a no-slip boundary condition at the top and bottom of the channel, the Dirichlet velocity -in x-direction is set to zero if not at the inlet. -
-Toggle to expand code (dirichletAtPos) - +The following function specifies the __values on Dirichlet boundaries__. +We need to define values for the primary variables (velocity and pressure). ```cpp - PrimaryVariables dirichletAtPos(const GlobalPosition &globalPos) const + PrimaryVariables dirichletAtPos(const GlobalPosition& globalPos) const { + // Use the initial values as default Dirichlet values PrimaryVariables values = initialAtPos(globalPos); - if(!isInlet_(globalPos)) - { + // Set a no-slip condition at the top and bottom wall of the channel + if (!isInlet_(globalPos)) values[Indices::velocityXIdx] = 0.0; - } return values; } ``` -
- -We specify the values for the initial conditions. -We assign constant values for pressure and velocity components. -
-Toggle to expand code (initialAtPos) - +The following function defines the initial conditions. ```cpp - PrimaryVariables initialAtPos(const GlobalPosition &globalPos) const + PrimaryVariables initialAtPos(const GlobalPosition& globalPos) const { PrimaryVariables values; + // Set the pressure and velocity values values[Indices::pressureIdx] = outletPressure_; values[Indices::velocityXIdx] = inletVelocity_; values[Indices::velocityYIdx] = 0.0; @@ -255,219 +318,201 @@ We assign constant values for pressure and velocity components. } ``` -
- +#### Temperature distribution We need to specify a constant temperature for our isothermal problem. -We set it to 10°C. -
-Toggle to expand code (temperature) - +Fluid properties that depend on temperature will be calculated with this value. +This would be important if another fluidsystem was used. ```cpp Scalar temperature() const { return 273.15 + 10; } -private: ``` -
- -The inlet is at the left side of the physical domain. -
-Toggle to expand code (isInlet_) - +The inlet is on the left side of the physical domain. ```cpp +private: bool isInlet_(const GlobalPosition& globalPos) const - { - return globalPos[0] < eps_; - } + { return globalPos[0] < eps_; } ``` -
- -The outlet is at the right side of the physical domain. -
-Toggle to expand code (isOutlet_) - +The outlet is on the right side of the physical domain. ```cpp bool isOutlet_(const GlobalPosition& globalPos) const - { - return globalPos[0] > this->gridGeometry().bBoxMax()[0] - eps_; - } + { return globalPos[0] > this->gridGeometry().bBoxMax()[0] - eps_; } ``` -
- Finally, private variables are declared: -
-Toggle to expand code (private variables) - ```cpp - static constexpr Scalar eps_=1e-6; + static constexpr Scalar eps_ = 1e-6; Scalar inletVelocity_; Scalar outletPressure_; -}; -} -``` - -
- - - - -## The file `main.cc` +}; // end class definition of ChannelExampleProblem +} // end namespace Dumux +``` -We look now at the main file for the channel problem. -### Includes -Necessary files are included. -
-Toggle to expand details -First, the Dune configuration file is include, the standard header file for C++ to get time and date information -and another standard header for in- and output. +
-
-Toggle to expand code (includes of problem file and of standard headers) -```cpp -#include +## The main file (`main.cc`) -#include -#include -``` +
+Click to hide/show the file documentation (or inspect the [source code](main.cc)) -
- -Dumux is based on DUNE, the Distributed and Unified Numerics Environment, which provides several grid managers and -linear solvers. So we need some includes from that. -
-Toggle to expand code (dune includes) +### Included header files +
Click to show includes +These are DUNE helper classes related to parallel computations and file I/O ```cpp #include -#include #include -#include -#include ``` -
- -In Dumux, a property system is used to specify the model. For this, different properties are defined containing -type definitions, values and methods. All properties are declared in the file `properties.hh`. -The file `parameters.hh` contains the parameter class, which manages the definition of input parameters by a default -value, the inputfile or the command line. -The file `dumuxmessage.hh` contains the class defining the start and end message of the simulation. - -The file `seqsolverbackend.hh` contains the class, which defines the sequential linear solver backends. -The nonlinear Newton's method is included, as well as the assembler, which assembles the linear systems for staggered-grid finite volume schemes. -The containing class in the file `diffmethod.hh` defines the different differentiation methods used to compute the derivatives of the residual. - -We need the class in `staggeredvtkoutputmodule.hh` to simplify the writing of dumux simulation data to VTK format. -The gridmanager constructs a grid from the information in the input or grid file. There is a specification for the -different supported grid managers. - -The following class contains functionality for additional flux output to the console. -
-Toggle to expand code (dumux includes) - +The following headers include functionality related to property definition or retrieval, as well as +the retrieval of input parameters specified in the input file or via the command line. ```cpp #include #include -#include -#include +``` -#include +The following files contain the non-linear Newton solver, the available linear solver backends and the assembler for the linear +systems arising from the staggered-grid discretization. + +```cpp #include +#include #include -#include +#include // analytic or numeric differentiation +``` + +The following class provides a convenient way of writing of dumux simulation results to VTK format. +```cpp #include +``` + +The gridmanager constructs a grid from the information in the input or grid file. +Many different Dune grid implementations are supported, of which a list can be found +in `gridmanager.hh`. + +```cpp #include +``` +This class contains functionality for additional flux output. + +```cpp #include +``` +In this header, a `TypeTag` is defined, which collects +the properties that are required for the simulation. +It also contains the actual problem with initial and boundary conditions. +For detailed information, please have a look +at the documentation provided therein. + +```cpp #include "properties.hh" ``` -
-### Beginning of the main function -We begin the main function by making the type tag `ChannelExample`, that we defined in `problem.hh` for this test problem available here. -Then we initializing the message passing interface (MPI), even if we do not plan to run the application in parallel. Finalizing of the MPI is done automatically on exit. -We continue by printing the dumux start message and parsing the command line arguments and runtimeparameters from the input file in the init function. - +### The main function +We will now discuss the main program flow implemented within the `main` function. +At the beginning of each program using Dune, an instance of `Dune::MPIHelper` has to +be created. Moreover, we parse the run-time arguments from the command line and the +input file: ```cpp int main(int argc, char** argv) try { using namespace Dumux; - using TypeTag = Properties::TTag::ChannelExample; - + // The Dune MPIHelper must be instantiated for each program using Dune const auto& mpiHelper = Dune::MPIHelper::instance(argc, argv); - if (mpiHelper.rank() == 0) - DumuxMessage::print(/*firstCall=*/true); - + // parse command line arguments and input file Parameters::init(argc, argv); ``` +We define a convenience alias for the type tag of the problem. The type +tag contains all the properties that are needed to define the model and the problem +setup. Throughout the main file, we will obtain types defined for this type tag +using the property system, i.e. with `GetPropType`. -### Set-up and solving of the problem - -A gridmanager tries to create the grid either from a grid file or the input file. You can learn more about grids in -Dumux in the [grid exercise](https://git.iws.uni-stuttgart.de/dumux-repositories/dumux-course/-/tree/master/exercises/exercise-grids). -Then, we compute the leaf grid view, which is the overlap of all grid levels in hierarchical grids. -We create (`std::make_shared`) and initialize (`update`) the finite volume geometry to build up the subcontrolvolumes -and subcontrolvolume faces for each element of the grid partition. -In the problem, we define the boundary and initial conditions. -We set a solution vector which has a part (indexed by `cellCenterIdx`) for degrees of freedom (`dofs`) living -in grid cell centers - pressures - and a part (indexed by `faceIdx`) for degrees of freedom livin on grid cell faces. -We initialize the solution vector by what was defined as the initial solution in `problem.hh` (`applyInitialSolution`) -and then use the solution vector to intialize the `gridVariables`. Grid variables in general contain the s -primary variables (velocities, pressures) as well as secondary variables (density, viscosity, ...). -We then initialize the vtkoutput. Each model has a predefined model-specific output with relevant parameters -for that model. Here, it is pressure, velocity, density and process rank (relevant in the case of parallelisation). +```cpp + using TypeTag = Properties::TTag::ChannelExample; +``` +#### Step 1: Create the grid +The `GridManager` class creates the grid from information given in the input file. +This can either be a grid file, or in the case of structured grids, one can specify the coordinates +of the corners of the grid and the number of cells to be used to discretize each spatial direction. ```cpp GridManager> gridManager; gridManager.init(); + // We compute on the leaf grid view. const auto& leafGridView = gridManager.grid().leafGridView(); +``` + +#### Step 2: Setting up and solving the problem +First, a finite volume grid geometry is constructed from the grid that was created above. +This builds the sub-control volumes (scv) and sub-control volume faces (scvf) for each element +of the grid partition. +```cpp using GridGeometry = GetPropType; auto gridGeometry = std::make_shared(leafGridView); gridGeometry->update(); +``` + +We now instantiate the problem, in which we define the boundary and initial conditions. +```cpp using Problem = GetPropType; auto problem = std::make_shared(gridGeometry); +``` + +We set a solution vector which consist of two parts: one part (indexed by `cellCenterIdx`) +is for the pressure degrees of freedom (`dofs`) living in grid cell centers. Another part +(indexed by `faceIdx`) is for degrees of freedom defining the normal velocities on grid cell faces. +We initialize the solution vector by what was defined as the initial solution of the the problem. +```cpp using SolutionVector = GetPropType; SolutionVector x; x[GridGeometry::cellCenterIdx()].resize(gridGeometry->numCellCenterDofs()); x[GridGeometry::faceIdx()].resize(gridGeometry->numFaceDofs()); problem->applyInitialSolution(x); +``` + +The grid variables are used store variables (primary and secondary variables) on sub-control volumes and faces (volume and flux variables). +```cpp using GridVariables = GetPropType; auto gridVariables = std::make_shared(problem, gridGeometry); gridVariables->init(x); +``` + +We then initialize the predefined model-specific output vtk output. +```cpp using IOFields = GetPropType; StaggeredVtkOutputModule vtkWriter(*gridVariables, x, problem->name()); IOFields::initOutputModule(vtkWriter); // Add model specific output fields vtkWriter.write(0.0); ``` - +
Click to show calculation of surface fluxes We set up two surfaces over which fluxes are calculated. We determine the extensions [xMin,xMax]x[yMin,yMax] of the physical domain. The first surface (added by the first call of addSurface) shall be placed at the middle of the channel. @@ -477,7 +522,6 @@ In this case, we add half a cell-width to the x-position in order to make sure t the cell faces lie on the surface. This assumes a regular cartesian grid. The second surface (second call of addSurface) is placed at the outlet of the channel. - ```cpp FluxOverSurface -Toggle to expand code (assembly, solution process, postprocessing) - +
+We create and initialize the assembler for the stationary problem. +This is where the Jacobian matrix for the Newton solver is assembled. ```cpp using Assembler = StaggeredFVAssembler; auto assembler = std::make_shared(problem, gridGeometry, gridVariables); +``` + +We use UMFPack as direct linear solver within each Newton iteration. +```cpp using LinearSolver = Dumux::UMFPackBackend; auto linearSolver = std::make_shared(); +``` + +This example considers a linear problem (incompressible Stokes flow), therefore +the non-linear Newton solver is not really necessary. +For sake of generality, we nevertheless use it here such that the example can be easily +changed to a non-linear problem by switching on the inertia terms in the input file or by choosing a compressible fluid. +In the following piece of code we instantiate the non-linear newton solver and let it solve +the problem. +```cpp + // alias for and instantiation of the newton solver using NewtonSolver = Dumux::NewtonSolver; NewtonSolver nonLinearSolver(assembler, linearSolver); + // Solve the (potentially non-linear) system. nonLinearSolver.solve(x); +``` + +In the following we calculate mass and volume fluxes over the planes specified above +(you have to click to unfold the code showing how to set up the surface fluxes). +```cpp flux.calculateMassOrMoleFluxes(); flux.calculateVolumeFluxes(); ``` -
- -### Final Output -We write the vtk output and print the mass/energy/volume fluxes over the planes. -We conclude by printing the dumux end message. After the end of the main function, -possibly catched error messages are printed. -
-Toggle to expand code (final output) - +#### Final Output +We write the VTK output and print the mass/energy/volume fluxes over the planes. +We conclude by printing the dumux end message. ```cpp vtkWriter.write(1.0); - if(GetPropType::enableEnergyBalance()) + if (GetPropType::enableEnergyBalance()) { std::cout << "mass / energy flux at middle is: " << flux.netFlux("middle") << std::endl; std::cout << "mass / energy flux at outlet is: " << flux.netFlux("outlet") << std::endl; @@ -569,18 +620,25 @@ possibly catched error messages are printed. std::cout << "volume flux at outlet is: " << flux.netFlux("outlet")[0] << std::endl; if (mpiHelper.rank() == 0) - { Parameters::print(); - DumuxMessage::print(/*firstCall=*/false); - } return 0; } // end main +``` + +#### Exception handling +In this part of the main file we catch and print possible exceptions that could +occur during the simulation. +
Click to show exception handler + +```cpp +// errors related to run-time parameters catch (Dumux::ParameterException &e) { std::cerr << std::endl << e << " ---> Abort!" << std::endl; return 1; } +// errors related to the parsing of Dune grid files catch (Dune::DGFException & e) { std::cerr << "DGF exception thrown (" << e << @@ -590,11 +648,13 @@ catch (Dune::DGFException & e) << " ---> Abort!" << std::endl; return 2; } +// generic error handling with Dune::Exception catch (Dune::Exception &e) { std::cerr << "Dune reported error: " << e << " ---> Abort!" << std::endl; return 3; } +// other exceptions catch (...) { std::cerr << "Unknown exception thrown! ---> Abort!" << std::endl; @@ -604,4 +664,5 @@ catch (...)
+
diff --git a/examples/freeflowchannel/doc/_intro.md b/examples/freeflowchannel/doc/_intro.md new file mode 100644 index 0000000000..4007f34ec7 --- /dev/null +++ b/examples/freeflowchannel/doc/_intro.md @@ -0,0 +1,65 @@ +# Free flow through a channel + +__You learn how to__ + +* solve a free-flow channel problem +* set outflow boundary conditions in the free-flow context + +__Results__. In this example we will obtain the following stationary velocity profile: + +![](./img/velocity.png) + +__Table of contents__. This description is structured as follows: + +[[_TOC_]] + +## Mathematical model +In this example, the Stokes model for stationary and incompressible single phase flow is considered. +Thus, the momentum balance equations + +```math +- \nabla\cdot\left(\mu\left(\nabla\boldsymbol{u}+\nabla\boldsymbol{u}^{\text{T}}\right)\right)+ \nabla p = 0 +``` + +and the mass balance + +```math +\nabla \cdot \left(\boldsymbol{u}\right) =0 +``` + +are solved, where $`\varrho`$ and $`\mu`$ are the density and viscosity of the fluid, +$`\boldsymbol{u}`$ is the fluid velocity and $`p`$ is the pressure. Here, we use constant fluid +properties with $`\varrho = 1~\frac{\text{kg}}{\text{m}^3}`$ and $`\mu = 1~\text{Pa}\text{s}`$. +Furthermore, isothermal conditions with a homogeneous temperature distribution of $`T=10^\circ C`$ are assumed. + +All equations are discretized with the staggered-grid finite-volume scheme as spatial discretization +with pressures and velocity components as primary variables. For details on the discretization scheme, +have a look at the Dumux [handbook](https://dumux.org/handbook). + +## Problem set-up +This example considers stationary flow of a fluid between two parallel solid plates in two dimensions. +Flow is enforced from left to right by prescribing an inflow velocity of $` v = 1~\frac{\text{m}}{\text{s}} `$ +on the left boundary, while a fixed pressure of $`p = 1.1 \text{bar}`$ and a zero velocity gradient +in x-direction are prescribed on the right boundary. On the top and bottom boundaries, no-slip +conditions are applied, which cause a parabolic velocity profile to develop along the channel. +Take a look at Figure 1 for an illustration of the domain and the boundary conditions. + +
+
+ Free-flow setup +
Fig.1 - Setup for the free flow problem.
+
+
+ +# Implementation + +## Folder layout and files + +``` +└── freeflowchannel/ + ├── CMakeLists.txt -> build system file + ├── main.cc -> main program flow + ├── params.input -> runtime parameters + ├── properties.hh -> compile time configuration + └── problem.hh -> boundary & initial conditions +``` diff --git a/examples/freeflowchannel/doc/intro.md b/examples/freeflowchannel/doc/intro.md deleted file mode 100644 index baec2112c9..0000000000 --- a/examples/freeflowchannel/doc/intro.md +++ /dev/null @@ -1,45 +0,0 @@ -# Freeflow through a channel - -__You learn how to__ - -* solve a free flow channel problem -* set outflow boundary conditions in the free-flow context - -__Results__. In this example we will obtain the following stationary velocity profile: - -![](./img/velocity.png) - -__Table of contents__. This description is structured as follows: - -[[_TOC_]] - -## Mathematical model -The Stokes model without gravitation and without sources or sinks for a stationary, incompressible, laminar, single phase, one-component, isothermal ($`T=10^\circ C`$) flow is considered assuming a Newtonian fluid of constant density $` \varrho = 1~\frac{\text{kg}}{\text{m}^3} `$ and constant kinematic viscosity $` \nu = 1~\frac{\text{m}^2}{\text{s}} `$. The momentum balance -```math -- \nabla\cdot\left(\mu\left(\nabla\boldsymbol{u}+\nabla\boldsymbol{u}^{\text{T}}\right)\right)+ \nabla p = 0 -``` -with density $`\varrho`$, velocity $`\boldsymbol{u}`$, dynamic viscosity $`\mu=\varrho\nu`$ and pressure $`p`$ and the mass balance -```math -\nabla \cdot \left(\varrho\boldsymbol{u}\right) =0 -``` -are discretized using a staggered-grid finite-volume scheme as spatial discretization with pressures and velocity components as primary variables. For details on the discretization scheme, have a look at the Dumux [handbook](https://dumux.org/handbook). - -## Problem set-up -This example contains a stationary free flow of a fluid through two parallel solid plates in two dimensions from left to right. The figure below shows the simulation set-up. The fluid flows into the system at the left with a constant velocity of $` v = 1~\frac{\text{m}}{\text{s}} `$. The inflow velocity profile is a block profile. Due to the no-slip, no-flow boundary conditions at the top and bottom plate, the velocity profile gradually assumes a parabolic shape along the channel. At the outlet, the pressure is fixed and a zero velocity gradient in x-direction is assumed. The physical domain, which is modeled is the rectangular domain $`x\in[0,10],~y\in[0,1]`$. - -![](./img/setup.png) - -In the following, we take a close look at the files containing the set-up: At first, boundary conditions are set in `problem.hh` for the Navier-Stokes model. Afterwards, we show the different steps for solving the model in the source file `main.cc`. - -# Implementation - -## Folder layout and files - -``` -└── freeflowchannel/ - ├── CMakeLists.txt -> build system file - ├── main.cc -> main program flow - ├── params.input -> runtime parameters - ├── properties.hh -> compile time configuration - └── problem.hh -> boundary & initial conditions -``` diff --git a/examples/freeflowchannel/main.cc b/examples/freeflowchannel/main.cc index d42b694d71..ee74271e2f 100644 --- a/examples/freeflowchannel/main.cc +++ b/examples/freeflowchannel/main.cc @@ -17,138 +17,123 @@ * along with this program. If not, see . * *****************************************************************************/ -// ## The file `main.cc` -// -// -// We look now at the main file for the channel problem. -// ### Includes -// Necessary files are included. -//
-// Toggle to expand details -// -// First, the Dune configuration file is include, the standard header file for C++ to get time and date information -// and another standard header for in- and output. -// -//
-// Toggle to expand code (includes of problem file and of standard headers) -// + // ## The main file (`main.cc`) + // [[content]] + // + // ### Included header files + // [[details]] includes + // [[exclude]] + // Some generic includes. #include - #include #include -//
-// -// Dumux is based on DUNE, the Distributed and Unified Numerics Environment, which provides several grid managers and -// linear solvers. So we need some includes from that. -//
-// Toggle to expand code (dune includes) -// +// [[/exclude]] + +// These are DUNE helper classes related to parallel computations and file I/O #include -#include #include -#include -#include -//
-// -// In Dumux, a property system is used to specify the model. For this, different properties are defined containing -// type definitions, values and methods. All properties are declared in the file `properties.hh`. -// The file `parameters.hh` contains the parameter class, which manages the definition of input parameters by a default -// value, the inputfile or the command line. -// The file `dumuxmessage.hh` contains the class defining the start and end message of the simulation. -// -// The file `seqsolverbackend.hh` contains the class, which defines the sequential linear solver backends. -// The nonlinear Newton's method is included, as well as the assembler, which assembles the linear systems for staggered-grid finite volume schemes. -// The containing class in the file `diffmethod.hh` defines the different differentiation methods used to compute the derivatives of the residual. -// -// We need the class in `staggeredvtkoutputmodule.hh` to simplify the writing of dumux simulation data to VTK format. -// The gridmanager constructs a grid from the information in the input or grid file. There is a specification for the -// different supported grid managers. -// -// The following class contains functionality for additional flux output to the console. -//
-// Toggle to expand code (dumux includes) -// + +// The following headers include functionality related to property definition or retrieval, as well as +// the retrieval of input parameters specified in the input file or via the command line. #include #include -#include -#include -#include +// The following files contain the non-linear Newton solver, the available linear solver backends and the assembler for the linear +// systems arising from the staggered-grid discretization. #include +#include #include -#include +#include // analytic or numeric differentiation +// The following class provides a convenient way of writing of dumux simulation results to VTK format. #include +// The gridmanager constructs a grid from the information in the input or grid file. +// Many different Dune grid implementations are supported, of which a list can be found +// in `gridmanager.hh`. #include +// This class contains functionality for additional flux output. #include + +// In this header, a `TypeTag` is defined, which collects +// the properties that are required for the simulation. +// It also contains the actual problem with initial and boundary conditions. +// For detailed information, please have a look +// at the documentation provided therein. #include "properties.hh" -//
-//
+// [[/details]] // -// ### Beginning of the main function -// We begin the main function by making the type tag `ChannelExample`, that we defined in `problem.hh` for this test problem available here. -// Then we initializing the message passing interface (MPI), even if we do not plan to run the application in parallel. Finalizing of the MPI is done automatically on exit. -// We continue by printing the dumux start message and parsing the command line arguments and runtimeparameters from the input file in the init function. -// +// ### The main function +// We will now discuss the main program flow implemented within the `main` function. +// At the beginning of each program using Dune, an instance of `Dune::MPIHelper` has to +// be created. Moreover, we parse the run-time arguments from the command line and the +// input file: +// [[codeblock]] int main(int argc, char** argv) try { using namespace Dumux; - using TypeTag = Properties::TTag::ChannelExample; - + // The Dune MPIHelper must be instantiated for each program using Dune const auto& mpiHelper = Dune::MPIHelper::instance(argc, argv); - if (mpiHelper.rank() == 0) - DumuxMessage::print(/*firstCall=*/true); - + // parse command line arguments and input file Parameters::init(argc, argv); - // - // ### Set-up and solving of the problem - // - // A gridmanager tries to create the grid either from a grid file or the input file. You can learn more about grids in - // Dumux in the [grid exercise](https://git.iws.uni-stuttgart.de/dumux-repositories/dumux-course/-/tree/master/exercises/exercise-grids). - // Then, we compute the leaf grid view, which is the overlap of all grid levels in hierarchical grids. - // We create (`std::make_shared`) and initialize (`update`) the finite volume geometry to build up the subcontrolvolumes - // and subcontrolvolume faces for each element of the grid partition. - // In the problem, we define the boundary and initial conditions. - // We set a solution vector which has a part (indexed by `cellCenterIdx`) for degrees of freedom (`dofs`) living - // in grid cell centers - pressures - and a part (indexed by `faceIdx`) for degrees of freedom livin on grid cell faces. - // We initialize the solution vector by what was defined as the initial solution in `problem.hh` (`applyInitialSolution`) - // and then use the solution vector to intialize the `gridVariables`. Grid variables in general contain the s - // primary variables (velocities, pressures) as well as secondary variables (density, viscosity, ...). - // We then initialize the vtkoutput. Each model has a predefined model-specific output with relevant parameters - // for that model. Here, it is pressure, velocity, density and process rank (relevant in the case of parallelisation). - // + // [[/codeblock]] + + // We define a convenience alias for the type tag of the problem. The type + // tag contains all the properties that are needed to define the model and the problem + // setup. Throughout the main file, we will obtain types defined for this type tag + // using the property system, i.e. with `GetPropType`. + using TypeTag = Properties::TTag::ChannelExample; + + // #### Step 1: Create the grid + // The `GridManager` class creates the grid from information given in the input file. + // This can either be a grid file, or in the case of structured grids, one can specify the coordinates + // of the corners of the grid and the number of cells to be used to discretize each spatial direction. + // [[codeblock]] GridManager> gridManager; gridManager.init(); + // We compute on the leaf grid view. const auto& leafGridView = gridManager.grid().leafGridView(); + // [[/codeblock]] + // #### Step 2: Setting up and solving the problem + // First, a finite volume grid geometry is constructed from the grid that was created above. + // This builds the sub-control volumes (scv) and sub-control volume faces (scvf) for each element + // of the grid partition. using GridGeometry = GetPropType; auto gridGeometry = std::make_shared(leafGridView); gridGeometry->update(); + // We now instantiate the problem, in which we define the boundary and initial conditions. using Problem = GetPropType; auto problem = std::make_shared(gridGeometry); + // We set a solution vector which consist of two parts: one part (indexed by `cellCenterIdx`) + // is for the pressure degrees of freedom (`dofs`) living in grid cell centers. Another part + // (indexed by `faceIdx`) is for degrees of freedom defining the normal velocities on grid cell faces. + // We initialize the solution vector by what was defined as the initial solution of the the problem. using SolutionVector = GetPropType; SolutionVector x; x[GridGeometry::cellCenterIdx()].resize(gridGeometry->numCellCenterDofs()); x[GridGeometry::faceIdx()].resize(gridGeometry->numFaceDofs()); problem->applyInitialSolution(x); + // The grid variables are used store variables (primary and secondary variables) on sub-control volumes and faces (volume and flux variables). using GridVariables = GetPropType; auto gridVariables = std::make_shared(problem, gridGeometry); gridVariables->init(x); + // We then initialize the predefined model-specific output vtk output. using IOFields = GetPropType; StaggeredVtkOutputModule vtkWriter(*gridVariables, x, problem->name()); IOFields::initOutputModule(vtkWriter); // Add model specific output fields vtkWriter.write(0.0); - // + + // [[details]] calculation of surface fluxes // We set up two surfaces over which fluxes are calculated. // We determine the extensions [xMin,xMax]x[yMin,yMax] of the physical domain. // The first surface (added by the first call of addSurface) shall be placed at the middle of the channel. @@ -157,7 +142,6 @@ int main(int argc, char** argv) try // In this case, we add half a cell-width to the x-position in order to make sure that // the cell faces lie on the surface. This assumes a regular cartesian grid. // The second surface (second call of addSurface) is placed at the outlet of the channel. - // FluxOverSurface, @@ -191,41 +175,43 @@ int main(int argc, char** argv) try const auto p0outlet = GlobalPosition{xMax, yMin}; const auto p1outlet = GlobalPosition{xMax, yMax}; flux.addSurface("outlet", p0outlet, p1outlet); - // - // The incompressible Stokes equation depends only linearly on the velocity, so we could use a linear solver to solve the problem. - // Here, we use the show the more general case which would also work for incompressible fluids or the - // Navier-Stokes equation. We use non-linear Newton solver for the solution. - // In each step of the Newton solver, we assemble the respective linear system, including the jacobian matrix and the residual by the - // `assembler`. The linear systems are here solved by the direct linear solver `UMFPack`. - // As a postprocessing, we calculate mass and volume fluxes over the planes specified above. - //
- // Toggle to expand code (assembly, solution process, postprocessing) - // + // [[/details]] + + // We create and initialize the assembler for the stationary problem. + // This is where the Jacobian matrix for the Newton solver is assembled. using Assembler = StaggeredFVAssembler; auto assembler = std::make_shared(problem, gridGeometry, gridVariables); + // We use UMFPack as direct linear solver within each Newton iteration. using LinearSolver = Dumux::UMFPackBackend; auto linearSolver = std::make_shared(); + // This example considers a linear problem (incompressible Stokes flow), therefore + // the non-linear Newton solver is not really necessary. + // For sake of generality, we nevertheless use it here such that the example can be easily + // changed to a non-linear problem by switching on the inertia terms in the input file or by choosing a compressible fluid. + // In the following piece of code we instantiate the non-linear newton solver and let it solve + // the problem. + // [[codeblock]] + // alias for and instantiation of the newton solver using NewtonSolver = Dumux::NewtonSolver; NewtonSolver nonLinearSolver(assembler, linearSolver); + // Solve the (potentially non-linear) system. nonLinearSolver.solve(x); - + // [[/codeblock]] + // In the following we calculate mass and volume fluxes over the planes specified above + // (you have to click to unfold the code showing how to set up the surface fluxes). flux.calculateMassOrMoleFluxes(); flux.calculateVolumeFluxes(); - //
- // - // ### Final Output - // We write the vtk output and print the mass/energy/volume fluxes over the planes. - // We conclude by printing the dumux end message. After the end of the main function, - // possibly catched error messages are printed. - //
- // Toggle to expand code (final output) - // + + // #### Final Output + // We write the VTK output and print the mass/energy/volume fluxes over the planes. + // We conclude by printing the dumux end message. + // [[codeblock]] vtkWriter.write(1.0); - if(GetPropType::enableEnergyBalance()) + if (GetPropType::enableEnergyBalance()) { std::cout << "mass / energy flux at middle is: " << flux.netFlux("middle") << std::endl; std::cout << "mass / energy flux at outlet is: " << flux.netFlux("outlet") << std::endl; @@ -240,18 +226,23 @@ int main(int argc, char** argv) try std::cout << "volume flux at outlet is: " << flux.netFlux("outlet")[0] << std::endl; if (mpiHelper.rank() == 0) - { Parameters::print(); - DumuxMessage::print(/*firstCall=*/false); - } return 0; } // end main +// [[/codeblock]] +// #### Exception handling +// In this part of the main file we catch and print possible exceptions that could +// occur during the simulation. +// [[details]] exception handler +// [[codeblock]] +// errors related to run-time parameters catch (Dumux::ParameterException &e) { std::cerr << std::endl << e << " ---> Abort!" << std::endl; return 1; } +// errors related to the parsing of Dune grid files catch (Dune::DGFException & e) { std::cerr << "DGF exception thrown (" << e << @@ -261,15 +252,18 @@ catch (Dune::DGFException & e) << " ---> Abort!" << std::endl; return 2; } +// generic error handling with Dune::Exception catch (Dune::Exception &e) { std::cerr << "Dune reported error: " << e << " ---> Abort!" << std::endl; return 3; } +// other exceptions catch (...) { std::cerr << "Unknown exception thrown! ---> Abort!" << std::endl; return 4; } -//
-// +// [[/codeblock]] +// [[/details]] +// [[/content]] diff --git a/examples/freeflowchannel/params.input b/examples/freeflowchannel/params.input index 4f1d82a9bc..623d2f8e56 100644 --- a/examples/freeflowchannel/params.input +++ b/examples/freeflowchannel/params.input @@ -6,7 +6,7 @@ Cells = 100 50 # [m] Name = example_ff_channel # name passed to the output routines InletVelocity = 1 # [m/s] EnableGravity = false -EnableInertiaTerms = false # Stokes, not Navier Stokes, in this example +EnableInertiaTerms = false # only consider the Stokes equations in this example [Component] LiquidDensity = 1.0 # [kg/m^3] diff --git a/examples/freeflowchannel/problem.hh b/examples/freeflowchannel/problem.hh index 927dcf023b..2707c73767 100644 --- a/examples/freeflowchannel/problem.hh +++ b/examples/freeflowchannel/problem.hh @@ -20,28 +20,29 @@ #ifndef DUMUX_EXAMPLES_FREEFLOW_CHANNEL_PROBLEM_HH #define DUMUX_EXAMPLES_FREEFLOW_CHANNEL_PROBLEM_HH -// ## The file `problem.hh` +// ## Initial and boundary conditions (`problem.hh`) // +// This file contains the __problem class__ which defines the initial and boundary +// conditions for the Navier-Stokes single-phase flow simulation. // -// ### The problem class -// We enter the problem class where all necessary initial and boundary conditions are set for our simulation. +// [[content]] +// +// ### Include files // -// As this is a Stokes problem, we inherit from the basic NavierStokesProblem. -//
Toggle to show code: -#include +// The only include we need here is the `NavierStokesProblem` class, the base +// class from which we will derive. #include +// ### The problem class +// We enter the problem class where all necessary boundary conditions and initial conditions are set for our simulation. +// As we are solving a problem related to free flow, we inherit from the base class `NavierStokesProblem`. +// [[codeblock]] namespace Dumux { template class ChannelExampleProblem : public NavierStokesProblem { - //
- // - // We use convenient declarations that we derive from the property system. - //
- // Toggle to show code (convenient declarations) - // + // A few convenience aliases used throughout this class. using ParentType = NavierStokesProblem; using BoundaryTypes = GetPropType; using GridGeometry = GetPropType; @@ -56,134 +57,109 @@ class ChannelExampleProblem : public NavierStokesProblem using GlobalPosition = typename Element::Geometry::GlobalCoordinate; public: - //
- // - // There follows the constructor of our problem class: + // This is the constructor of our problem class: // Within the constructor, we set the inlet velocity to a run-time specified value. - // As no run-time value is specified, we set the outlet pressure to 1.1e5 Pa. - //
- // Toggle to expand code (constructor) - // + // If no run-time value is specified, we set the outlet pressure to 1.1e5 Pa. ChannelExampleProblem(std::shared_ptr gridGeometry) : ParentType(gridGeometry) { inletVelocity_ = getParam("Problem.InletVelocity"); outletPressure_ = getParam("Problem.OutletPressure", 1.1e5); } - //
- // - // Now, we define the type of initial and boundary conditions depending on location. - // Two types of boundary conditions can be specified: Dirichlet and Neumann. On a Dirichlet boundary, - // the values of the primary variables need to be fixed. - // On a Neumann boundary condition, values for derivatives need to be fixed. - // When Dirichlet conditions are set for the pressure, the derivative of the velocity - // vector with respect to the direction normal to the boundary is automatically set to - // zero. This boundary condition is called in-/outflow boundary condition in Dumux. - // In the following we specify Dirichlet boundaries for velocity on the left of our domain - // if isInlet_ is true, Dirichlet boundaries for pressure on the right of our domain - // if isOutlet_ is true and specify Dirichlet boundaries for velocity on the top and bottom - // of our domain else. - //
- // Toggle to expand code (boundaryTypesAtPos) - // - BoundaryTypes boundaryTypesAtPos(const GlobalPosition &globalPos) const + // [[/codeblock]] + + // #### Boundary conditions + // With the following function we define the __type of boundary conditions__ depending on the location. + // Three types of boundary conditions can be specified: Dirichlet, Neumann or outflow boundary conditions. On + // Dirichlet boundaries, the values of the primary variables need to be fixed. On a Neumann boundaries, + // values for derivatives need to be fixed. Outflow conditions set a gradient of zero in normal direction towards the boundary + // for the respective primary variables (excluding pressure). + // When Dirichlet conditions are set for the pressure, the velocity gradient + // with respect to the direction normal to the boundary is automatically set to zero. + // [[codeblock]] + BoundaryTypes boundaryTypesAtPos(const GlobalPosition& globalPos) const { BoundaryTypes values; - if(isInlet_(globalPos)) + if (isInlet_(globalPos)) { + // We specify Dirichlet boundary conditions for the velocity on the left of our domain values.setDirichlet(Indices::velocityXIdx); values.setDirichlet(Indices::velocityYIdx); } - else if(isOutlet_(globalPos)) + else if (isOutlet_(globalPos)) { + // We fix the pressure on the right side of the domain values.setDirichlet(Indices::pressureIdx); } else { + // We specify Dirichlet boundary conditions for the velocity on the remaining boundaries (lower and upper wall) values.setDirichlet(Indices::velocityXIdx); values.setDirichlet(Indices::velocityYIdx); } return values; } - //
- // - // Second, we specify the values for the Dirichlet boundaries. We need to fix the values of our primary variables. - // To ensure a no-slip boundary condition at the top and bottom of the channel, the Dirichlet velocity - // in x-direction is set to zero if not at the inlet. - //
- // Toggle to expand code (dirichletAtPos) - // - PrimaryVariables dirichletAtPos(const GlobalPosition &globalPos) const + // [[/codeblock]] + + // The following function specifies the __values on Dirichlet boundaries__. + // We need to define values for the primary variables (velocity and pressure). + // [[codeblock]] + PrimaryVariables dirichletAtPos(const GlobalPosition& globalPos) const { + // Use the initial values as default Dirichlet values PrimaryVariables values = initialAtPos(globalPos); - if(!isInlet_(globalPos)) - { + // Set a no-slip condition at the top and bottom wall of the channel + if (!isInlet_(globalPos)) values[Indices::velocityXIdx] = 0.0; - } return values; } - //
- // - // We specify the values for the initial conditions. - // We assign constant values for pressure and velocity components. - //
- // Toggle to expand code (initialAtPos) - // - PrimaryVariables initialAtPos(const GlobalPosition &globalPos) const + // [[/codeblock]] + + // The following function defines the initial conditions. + // [[codeblock]] + PrimaryVariables initialAtPos(const GlobalPosition& globalPos) const { PrimaryVariables values; + // Set the pressure and velocity values values[Indices::pressureIdx] = outletPressure_; values[Indices::velocityXIdx] = inletVelocity_; values[Indices::velocityYIdx] = 0.0; return values; } - //
- // + // [[/codeblock]] + + // #### Temperature distribution // We need to specify a constant temperature for our isothermal problem. - // We set it to 10°C. - //
- // Toggle to expand code (temperature) - // + // Fluid properties that depend on temperature will be calculated with this value. + // This would be important if another fluidsystem was used. Scalar temperature() const { return 273.15 + 10; } + +// The inlet is on the left side of the physical domain. +// [[codeblock]] private: - //
- // - // The inlet is at the left side of the physical domain. - //
- // Toggle to expand code (isInlet_) - // bool isInlet_(const GlobalPosition& globalPos) const - { - return globalPos[0] < eps_; - } - //
- // - // The outlet is at the right side of the physical domain. - //
- // Toggle to expand code (isOutlet_) - // + { return globalPos[0] < eps_; } + // [[/codeblock]] + + // The outlet is on the right side of the physical domain. bool isOutlet_(const GlobalPosition& globalPos) const - { - return globalPos[0] > this->gridGeometry().bBoxMax()[0] - eps_; - } - //
- // + { return globalPos[0] > this->gridGeometry().bBoxMax()[0] - eps_; } + // Finally, private variables are declared: - //
- // Toggle to expand code (private variables) - // - static constexpr Scalar eps_=1e-6; + // [[codeblock]] + static constexpr Scalar eps_ = 1e-6; Scalar inletVelocity_; Scalar outletPressure_; -}; -} + +}; // end class definition of ChannelExampleProblem +} // end namespace Dumux +// [[/codeblock]] +// [[/content]] #endif -//
-// diff --git a/examples/freeflowchannel/properties.hh b/examples/freeflowchannel/properties.hh index 06dc602b5c..56e717db39 100644 --- a/examples/freeflowchannel/properties.hh +++ b/examples/freeflowchannel/properties.hh @@ -20,57 +20,102 @@ #ifndef DUMUX_EXAMPLES_FREEFLOW_CHANNEL_PROPERTIES_HH #define DUMUX_EXAMPLES_FREEFLOW_CHANNEL_PROPERTIES_HH -// ## The file `properties.hh` -// In the following, we set the properties for our simulation -// (click [here](https://git.iws.uni-stuttgart.de/dumux-repositories/dumux-course/blob/master/slides/dumux-course-properties.pdf) for DuMux course slides on the property system). -// We start with includes -//
Click to show the header includes -#include +// ## Compile-time settings (`properties.hh`) +// +// In this file, the type tag used for this simulation is defined, +// for which we then specialize properties (compile time options) to the needs of the desired setup. +// +// [[content]] +// +// ### Includes +// [[details]] includes +// +// The `NavierStokes` type tag specializes most of the properties required for Navier- +// Stokes single-phase flow simulations in DuMuX. We will use this in the following to inherit the +// respective properties and subsequently specialize those properties for our +// type tag, which we want to modify or for which no meaningful default can be set. +#include -#include +// We want to use `YaspGrid`, an implementation of the dune grid interface for structured grids: +#include +// In this example, we want to discretize the equations with the staggered-grid +// scheme which is so far the only available option for free-flow models in DuMux: #include -#include +// The fluid properties are specified in the following headers (we use a liquid with constant properties as the fluid phase): #include #include +// We include the problem header used for this simulation. #include "problem.hh" -//
+// [[/details]] // -// Then we start setting the properties. -// 1. For every test problem, a new `TypeTag` has to be created, which is done within the namespace `TTag` (subnamespace of `Properties`). It inherits from the Navier-Stokes flow model and the staggered-grid discretization scheme. -// 2. The grid is chosen to be a two-dimensional Cartesian structured grid (`YaspGrid`). -// 3. We set the `FluidSystem` to be a one-phase liquid with a single component. The class `Component::Constant` refers to a component with constant fluid properties (density, viscosity, ...) that can be set via the input file in the group `[0.Component]` where the number is the identifier given as template argument to the class template `Component::Constant`. -// 4. The problem class `ChannelExampleProblem`, which is forward declared before we enter `namespace Dumux` and defined later in this file, is defined to be the problem used in this test problem (charaterized by the TypeTag `ChannelExample`). The fluid system, which contains information about the properties such as density, viscosity or diffusion coefficient of the fluid we're simulating, is set to a constant one phase liquid. -// 5. We enable caching for the following classes (which stores values that were already calculated for later usage and thus results in higher memory usage but improved CPU speed): the grid volume variables, the grid flux variables, the finite volume grid geometry. +// ### Type tag definition +// +// We define a type tag for our simulation with the name `ChannelExample` +// and inherit the properties specialized for the type tags `NavierStokes` and `StaggeredFreeFlowModel`. +// This way, most of the properties required for Navier-Stokes single-phase flow simulations +// using the staggered-grid scheme are conveniently specialized for our new type tag. +// However, some properties depend on user choices and no meaningful default value can be set. +// Those properties will be addressed later in this file. +// Please note that, in this example, we actually want to solve the Stokes instead of the +// Navier-Stokes equations. This can be achieved at runtime by setting the parameter +// `Problem.EnableInertiaTerms = false`. Have a look at the input file `params.input` +// to see how this is done in this example. // [[codeblock]] +// We enter the namespace Dumux::Properties in order to import the entire Dumux namespace for general use: namespace Dumux::Properties { +// declaration of the `ChannelExample` type tag for the single-phase flow problem namespace TTag { struct ChannelExample { using InheritsFrom = std::tuple; }; } // namespace TTag +// [[/codeblock]] +// ### Property specializations +// +// In the following piece of code, mandatory properties for which no meaningful +// default can be set, are specialized for our type tag `ChannelExample`. +// [[codeblock]] +// This sets the grid type used for the simulation. Here, we use a structured 2D grid. template struct Grid { using type = Dune::YaspGrid<2>; }; +// This sets our problem class (see problem.hh) containing initial and boundary conditions. template struct Problem { using type = Dumux::ChannelExampleProblem ; }; +// This sets the fluid system to be used. Here, we use a liquid with constant properties as fluid phase. template struct FluidSystem { using Scalar = GetPropType; using type = FluidSystems::OnePLiquid >; }; +// [[/codeblock]] +// We also set some properties related to memory management +// throughout the simulation. +// [[details]] caching properties +// +// In Dumux, one has the option to activate/deactivate the grid-wide caching of +// geometries and variables. If active, the CPU time can be significantly reduced +// as less dynamic memory allocation procedures are necessary. Per default, grid-wide +// caching is disabled to ensure minimal memory requirements, however, in this example we +// want to active all available caches, which significantly increases the memory +// demand but makes the simulation faster. +// +// [[codeblock]] +// This enables grid-wide caching of the volume variables. template struct EnableGridVolumeVariablesCache { static constexpr bool value = true; }; - +//This enables grid wide caching for the flux variables. template struct EnableGridFluxVariablesCache { static constexpr bool value = true; }; - +// This enables grid-wide caching for the finite volume grid geometry template struct EnableGridGeometryCache { static constexpr bool value = true; }; } // end namespace Dumux::Properties // [[/codeblock]] - +// [[/details]] +// [[/content]] #endif -- GitLab From 7f58eb70dc5c4cc7dd9fea6f8a18f4fb3b9eae98 Mon Sep 17 00:00:00 2001 From: Martin Utz Date: Wed, 1 Apr 2020 14:02:47 +0200 Subject: [PATCH 13/57] [examples][shallowwater] Improve example structure (cherry picked from commit 8732166adba7bc898bcac9bf5cc0968716f53511) --- examples/README.md | 2 +- examples/shallowwaterfriction/.doc_config | 26 +- examples/shallowwaterfriction/README.md | 1032 ++--------------- examples/shallowwaterfriction/doc/_intro.md | 139 +++ examples/shallowwaterfriction/doc/intro.md | 97 -- examples/shallowwaterfriction/doc/main.md | 298 +++++ .../shallowwaterfriction/doc/main_intro.md | 12 + examples/shallowwaterfriction/doc/swe.md | 570 +++++++++ .../shallowwaterfriction/doc/swe_intro.md | 17 + examples/shallowwaterfriction/img/domain.png | Bin 18385 -> 0 bytes examples/shallowwaterfriction/img/result.png | Bin 35503 -> 0 bytes .../shallowwaterfriction/img/swe_result.png | Bin 0 -> 117570 bytes examples/shallowwaterfriction/main.cc | 190 +-- examples/shallowwaterfriction/problem.hh | 180 +-- examples/shallowwaterfriction/properties.hh | 51 +- .../shallowwaterfriction/spatialparams.hh | 74 +- ...example_shallowwaterfriction-reference.vtu | 418 +++---- 17 files changed, 1651 insertions(+), 1455 deletions(-) create mode 100644 examples/shallowwaterfriction/doc/_intro.md delete mode 100644 examples/shallowwaterfriction/doc/intro.md create mode 100644 examples/shallowwaterfriction/doc/main.md create mode 100644 examples/shallowwaterfriction/doc/main_intro.md create mode 100644 examples/shallowwaterfriction/doc/swe.md create mode 100644 examples/shallowwaterfriction/doc/swe_intro.md delete mode 100644 examples/shallowwaterfriction/img/domain.png delete mode 100644 examples/shallowwaterfriction/img/result.png create mode 100644 examples/shallowwaterfriction/img/swe_result.png diff --git a/examples/README.md b/examples/README.md index 9d3e0ba9a2..cff9e3ed7c 100644 --- a/examples/README.md +++ b/examples/README.md @@ -29,7 +29,7 @@ You learn how to ### [:open_file_folder: Example 3: Shallow water model](shallowwaterfriction/README.md) -The shallow water flow model is applied to simulate steady subcritical flow in a river including a bottom friction model. +The shallow water flow model is applied to simulate steady subcritical flow in a channel including a bottom friction model. You learn how to * solve a shallow water flow problem including bottom friction diff --git a/examples/shallowwaterfriction/.doc_config b/examples/shallowwaterfriction/.doc_config index 7ac7201b34..d5233fd849 100644 --- a/examples/shallowwaterfriction/.doc_config +++ b/examples/shallowwaterfriction/.doc_config @@ -1,9 +1,29 @@ { "README.md" : [ - "doc/intro.md", + "doc/_intro.md" + ], + + "doc/swe.md" : [ + "doc/swe_intro.md", "properties.hh", - "spatialparams.hh", "problem.hh", + "spatialparams.hh" + ], + + "doc/main.md" : [ + "doc/main_intro.md", "main.cc" - ] + ], + + "navigation" : { + "mainpage" : "README.md", + "subpages" : [ + "doc/swe.md", + "doc/main.md" + ], + "subtitles" : [ + "Shallow water flow simulation setup", + "Main program flow" + ] + } } diff --git a/examples/shallowwaterfriction/README.md b/examples/shallowwaterfriction/README.md index e71e3b5460..29cb808d13 100644 --- a/examples/shallowwaterfriction/README.md +++ b/examples/shallowwaterfriction/README.md @@ -1,25 +1,60 @@ # Shallow water flow with bottom friction -This example shows how the shallow water flow model can be -applied to simulate steady subcritical flow including -bottom friction (bed shear stress). +In this example, the shallow water flow model is applied to simulate +a steady subcritical flow including bottom friction (bed shear stress). __You will learn how to__ * solve a shallow water flow problem including bottom friction * compute and output (VTK) an analytical reference solution -__Result__. The numerical and analytical solutions for the problem will look like this: +__Result__. The numerical and analytical solutions for the free surface will look like this: -![Result Logo](img/result.png) +
+
+ Shallow water result +
Fig.1 - Setup and result for the shallow water problem with bottom friction.
+
+
__Table of contents__. This description is structured as follows: [[_TOC_]] -## Mathematical model -The 2D shallow water equations (SWEs) are given by +## Problem set-up +### Model domain +The model domain is given by a rough channel with a slope of 0.001. +The domain is 500 meters long and 5 meters wide. +The bottom altitude is 10 m at the inflow and hence 9.5 m at the outflow. +Bottom friction is considered by applying +Manning's law ($`n`$ = 0.025). + +### Boundary conditions +At the lateral sides a no-flow boundary condition is applied. Also no friction is +considered there and therefore a no slip boundary +condition is applied. These are the default boundary condition for the shallow +water model. At the left border a discharge boundary condition +is applied as inflow boundary condition with $`q = -1.0 m^2 s^{-1}`$. +At the right border a fixed water depth boundary condition +is applied for the outflow. Normal flow is assumed, therefore the water +depth at the right border is calculated using the equation +of Gauckler, Manning and Strickler. + +### Initial conditons +The initial water depth is set to 1 m, which is slightly higher than the normal flow +water depth (0.87 m). Therefore, we expect a decreasing +water level during the simulation until the normal flow condition is reached in +the entire model domain. The inital velocity is set to zero. + +## Model description +As mentioned above, this examples uses the shallow water equations (SWEs) to solve the problem. +These are a depth averaged simplification of the Navier-Stokes equations. To calculate the +bottom friction Manning's law is used. An alternative is Nikuradse's law, which is also implemented +in DuMux. + +### Shallow water model +The shallow water equations are given as: ```math \frac{\partial \mathbf{U}}{\partial t} + @@ -35,54 +70,61 @@ where $`\mathbf{U}`$, $`\mathbf{F}`$ and $`\mathbf{G}`$ defined as \mathbf{G} = \begin{bmatrix} hv \\ huv \\ hv^2 + \frac{1}{2} gh^2 \end{bmatrix} ``` -$`Z`$ is the bedSurface, $`h`$ the water depth, $`u`$ the velocity in -x-direction and $`v`$ the velocity in y-direction, $`g`$ is the constant of gravity. +$`h`$ the water depth, $`u`$ the velocity in x-direction and $`v`$ the velocity in y-direction, +$`g`$ is the constant of gravity. -The source terms for the bed friction $`\mathbf{S_b}`$ and bed slope +The source terms for the bed slope $`\mathbf{S_b}`$ and friction $`\mathbf{S_f}`$ are given as ```math \mathbf{S_b} = \begin{bmatrix} 0 \\ -gh \frac{\partial z}{\partial x} \\ -gh \frac{\partial z}{\partial y}\end{bmatrix}, -\mathbf{S_f} = \begin{bmatrix} 0 \\ -ghS_{fx} \\ -ghS_{fy}\end{bmatrix}. +\mathbf{S_f} = \begin{bmatrix} 0 \\ghS_{fx} \\ghS_{fy}\end{bmatrix}. ``` -For this example, a cell-centered finite volume method (`cctpfa`) is applied to solve the SWEs -in combination with a fully-implicit time discretization. For cases where no sharp fronts or -traveling waves occur it is possible to apply time steps larger than CFL number = 1 to reduce -the computation time. Even if a steady state solution is considered, an implicit time stepping method -is applied. +with the bedSurface $`z`$. $`S_{fx}`$ and $`S_{fy}`$ are the bed shear stess +components in x- and y-direction, which are calculated by Manning's law. -## Problem set-up +### Mannings law +The empirical Manning model specifies the bed shear stress by the following equations: -The model domain is given by a rough channel with a slope of 0.001. -The domain is 500 meters long and 10 meters wide. -![Domain](img/domain.png). +```math +S_{fx} = \frac{n^2u}{R_{hy}^{4/3}} \sqrt(u^2 + v^2), -Bottom friction is considered by applying -the friction law of Manning (Manning n = 0.025). At the lateral sides no friction is considered and a -no-flow no slip boundary condition is applied. This is the default boundary condition for the shallow water model. +S_{fy} = \frac{n^2v}{R_{hy}^{4/3}} \sqrt(u^2 + v^2) +``` + +$`n`$ is Manning's friction value and $`R_{hy}`$ is the hydraulic radius, +which is assumed to be equal to the water depth $`h`$. -At the left border a discharge boundary condition -is applied as inflow boundary condition with q = -1.0 ($`m^2 s^{-1}`$). At the right border a water fixed depth boundary condition -is applied for the outflow. Normal flow is assumed, therefore the water depth at the right border is calculated after -the of Gaukler-Manning-Strickler equation: +### Analytical solution +Since normal flow conditions are assumed, the analytic solution is calculated using the equation +of Gauckler, Manning and Strickler: ```math v_m = n^{-1} R_{hy}^{2/3} I_s^{1/2} ``` -Where the mean velocity $`v_m`$ is given as $`v_m = \frac{q}{h}`$, -$`n`$ is the friction value after Manning. $`R_{hy}`$ the hydraulic radius, which is assumed to be equal to -the water depth. $`I_s`$ is the bed slope and $`q`$ the unity inflow discharge +Where the mean velocity $`v_m`$ is given as + +```math +v_m = \frac{q}{h} +``` + +$`I_s`$ is the bed slope and $`q`$ the unity inflow discharge. + +Hence, the water depth $`h`$ can be calculated by -The water depth h can be calculated as ```math h = \left(\frac{n q}{\sqrt{I_s}} \right)^{3/5} ``` -The formula of Gaukler Manning and Strickler is also used to calculate the analytic solution. All parameters -for the simulation are given in the file `params.input`. +### Discretisation +For this example, a cell-centered finite volume method (cctpfa) is applied to solve the SWEs +in combination with a fully-implicit time discretization. For cases where no sharp fronts or +traveling waves occur it is possible to apply time steps larger than CFL number = 1 to reduce +the computation time. Even if a steady state solution is considered, an implicit time stepping method +is applied. # Implementation @@ -98,925 +140,13 @@ for the simulation are given in the file `params.input`. └── spatialparams.hh -> spatial parameter fields ``` +## Part 1: Shallow water flow simulation setup -## The file `properties.hh` - -The header includes will be mentioned in the text below. -
Click to show the header includes - -```cpp -#include - -#include -#include -#include - -#include "spatialparams.hh" -#include "problem.hh" -``` - -
- -Let's define the properties for our simulation - -```cpp -namespace Dumux::Properties { -``` - -First, a so-called TypeTag is created. Properties are traits specialized for this TypeTag (a simple `struct`). -The properties of two other TypeTags are inherited by adding the alias `InheritsFrom`. -Here, properties from the shallow water model (`TTag::ShallowWater`) and the -cell-centered finite volume scheme with two-point-flux approximation (`TTag::CCTpfaModel`) -are inherited. These other TypeTag definitions can be found in the included -headers `dumux/freeflow/shallowwater/model.hh` and `dumux/discretization/cctpfa.hh`. - -```cpp -namespace TTag { -struct RoughChannel { using InheritsFrom = std::tuple; }; -} -``` - -We use a structured Cartesian grid with tensor product structure. -`Dune::YaspGrid` (Yet Another Structure Parallel Grid) is defined in `dune/grid/yaspgrid.hh` -in the Dune module `dune-grid`. - -```cpp -template -struct Grid -{ using type = Dune::YaspGrid<2, Dune::TensorProductCoordinates, 2> >; }; -``` - -Next, we specialize the properties `Problem` and `SpatialParams` for our new TypeTag and -set the type to our problem and spatial parameter classes implemented -in `problem.hh` and `spatialparams.hh`. - -```cpp -template -struct Problem -{ using type = Dumux::RoughChannelProblem; }; - -template -struct SpatialParams -{ - using GridGeometry = GetPropType; - using Scalar = GetPropType; - using ElementVolumeVariables = typename GetPropType::LocalView; - using VolumeVariables = typename ElementVolumeVariables::VolumeVariables; - - using type = RoughChannelSpatialParams; -}; -``` - -Finally, we enable caching for the grid geometry. The cache -stores values that were already calculated for later usage. -This makes the simulation run faster but it uses more memory. - -```cpp -template -struct EnableGridGeometryCache -{ static constexpr bool value = true; }; - -} // end namespace Dumux::Properties -``` - - - - -## The file `spatialparams.hh` - - -We include the basic spatial parameters for finite volumes file from which we will inherit - -```cpp -#include -``` - -The parameters header is needed to retrieve run-time parameters. - -```cpp -#include -``` - -We include all friction laws, between we can choose for the calculation of the bottom friction source. - -```cpp -#include -#include -#include -``` - -We enter the namespace Dumux. All Dumux functions and classes are in a namespace Dumux, to make sure they don`t clash with symbols from other libraries you may want to use in conjunction with Dumux. - -```cpp -namespace Dumux { -``` - -In the RoughChannelSpatialParams class we define all functions needed to describe the spatial distributed parameters. - -```cpp -template -class RoughChannelSpatialParams -: public FVSpatialParams> -{ -``` - -We introduce using declarations that are derived from the property system which we need in this class - -```cpp - using ThisType = RoughChannelSpatialParams; - using ParentType = FVSpatialParams; - using GridView = typename GridGeometry::GridView; - using FVElementGeometry = typename GridGeometry::LocalView; - using SubControlVolume = typename FVElementGeometry::SubControlVolume; - using Element = typename GridView::template Codim<0>::Entity; - using GlobalPosition = typename Element::Geometry::GlobalCoordinate; - -public: -``` - -In the constructor be read some values from the `params.input` and initialize the friciton law. - -```cpp - RoughChannelSpatialParams(std::shared_ptr gridGeometry) - : ParentType(gridGeometry) - { - gravity_ = getParam("Problem.Gravity"); - bedSlope_ = getParam("Problem.BedSlope"); - frictionLawType_ = getParam("Problem.FrictionLaw"); - initFrictionLaw(); - } -``` - -We initialize the friction law based on the law specified in `params.input`. - -```cpp - void initFrictionLaw() - { - if (frictionLawType_ == "Manning") - { - Scalar manningN = getParam("Problem.ManningN"); - frictionLaw_ = std::make_unique>(gravity_, manningN); - } - else if (frictionLawType_ == "Nikuradse") - { - Scalar ks = getParam("Problem.Ks"); - frictionLaw_ = std::make_unique>(ks); - } - else - { - std::cout<<"The FrictionLaw in params.input is unknown. Valid entries are `Manning` and `Nikuradse`!"<& frictionLaw(const Element& element, - const SubControlVolume& scv) const - { - return *frictionLaw_; - } -``` - -Define the bed surface based on the `bedSlope_`. - -```cpp - Scalar bedSurface(const Element& element, - const SubControlVolume& scv) const - { - return 10.0 - element.geometry().center()[0] * bedSlope_; - } - -private: - Scalar gravity_; - Scalar bedSlope_; - std::string frictionLawType_; - std::unique_ptr> frictionLaw_; -}; -``` - -end of namespace Dumux. - -```cpp -} -``` - - - - -## The file `problem.hh` -We start with includes - -```cpp -#include -#include -#include -#include -``` - -We enter the problem class where all necessary boundary conditions and initial conditions are set for our simulation. -As this is a shallow water problem, we inherit from the basic ShallowWaterProblem. - -```cpp -namespace Dumux { - -template -class RoughChannelProblem : public ShallowWaterProblem -{ -``` - -We use convenient declarations that we derive from the property system. - -```cpp - using ParentType = ShallowWaterProblem; - using PrimaryVariables = GetPropType; - using BoundaryTypes = GetPropType; - using Scalar = GetPropType; - using Indices = typename GetPropType::Indices; - using GridGeometry = GetPropType; - using NeumannFluxes = GetPropType; - using ElementVolumeVariables = typename GetPropType::LocalView; - using GridVariables = GetPropType; - using ElementFluxVariablesCache = typename GridVariables::GridFluxVariablesCache::LocalView; - using VolumeVariables = typename ElementVolumeVariables::VolumeVariables; - using FVElementGeometry = typename GetPropType::LocalView; - using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace; - using GridView = typename GetPropType::GridView; - using Element = typename GridView::template Codim<0>::Entity; - using GlobalPosition = typename Element::Geometry::GlobalCoordinate; - using NumEqVector = GetPropType; - using SubControlVolume = typename FVElementGeometry::SubControlVolume; - -public: -``` - -This is the constructor of our problem class. - -```cpp - RoughChannelProblem(std::shared_ptr gridGeometry) - : ParentType(gridGeometry) - { -``` - -We read the parameters from the params.input file. - -```cpp - name_ = getParam("Problem.Name"); - constManningN_ = getParam("Problem.ManningN"); - bedSlope_ = getParam("Problem.BedSlope"); - discharge_ = getParam("Problem.Discharge"); -``` - -We calculate the outflow boundary condition using the Gauckler-Manning-Strickler formula. - -```cpp - hBoundary_ = this->gauklerManningStrickler(discharge_,constManningN_,bedSlope_); -``` - -We initialize the analytic solution to a verctor of the appropriate size filled with zeros. - -```cpp - exactWaterDepth_.resize(gridGeometry->numDofs(), 0.0); - exactVelocityX_.resize(gridGeometry->numDofs(), 0.0); - } -``` - -Get the analytical water depth - -```cpp - const std::vector& getExactWaterDepth() - { - return exactWaterDepth_; - } -``` - -Get the analytical velocity - -```cpp - const std::vector& getExactVelocityX() - { - return exactVelocityX_; - } -``` - -Get the water depth with Gauckler-Manning-Strickler - -```cpp - Scalar gauklerManningStrickler(Scalar discharge, Scalar manningN, Scalar bedSlope) - { - using std::pow; - using std::abs; - using std::sqrt; - - return pow(abs(discharge)*manningN/sqrt(bedSlope), 0.6); - } -``` - -Get the analytical solution - -```cpp - void analyticalSolution() - { - using std::abs; - - for (const auto& element : elements(this->gridGeometry().gridView())) - { - const Scalar h = this->gauklerManningStrickler(discharge_,constManningN_,bedSlope_); - const Scalar u = abs(discharge_)/h; - - const auto eIdx = this->gridGeometry().elementMapper().index(element); - exactWaterDepth_[eIdx] = h; - exactVelocityX_[eIdx] = u; - } - } -``` - -Get the problem name. It is used as a prefix for files generated by the simulation. - -```cpp - const std::string& name() const - { - return name_; - } -``` - -Get the source term. - -```cpp - NumEqVector source(const Element& element, - const FVElementGeometry& fvGeometry, - const ElementVolumeVariables& elemVolVars, - const SubControlVolume &scv) const - { - - NumEqVector source (0.0); -``` - -In this model the bottom friction is the only source. - -```cpp - source += bottomFrictionSource(element, fvGeometry, elemVolVars, scv); - - return source; - } -``` - -Get the source term due to bottom friction. - -```cpp - NumEqVector bottomFrictionSource(const Element& element, - const FVElementGeometry& fvGeometry, - const ElementVolumeVariables& elemVolVars, - const SubControlVolume &scv) const - { - NumEqVector bottomFrictionSource(0.0); - const auto& volVars = elemVolVars[scv]; -``` - -For the calculation of the source term due to bottom friction the two-dimensional bottom shear stess vector is needed. This is the force per area, which works between the flow and the bed. It is calculated within the `FrictionLaw`, which is a spatialParameter. In this model the `FrictionLawManning` is used (see `params.input`). - -```cpp - Dune::FieldVector bottomShearStress = this->spatialParams().frictionLaw(element, scv).shearStress(volVars); -``` - -The bottom shear stress causes a pure loss of momentum. Thus the first entry of the `bottomFrictionSource`, which is related to the mass balance equation is zero. The second entry of the `bottomFricitonSource` corresponds to the momentum equation in x-direction and is therefore equal to the first, the x-component, of the `bottomShearStress`. Accordingly the third entry of the `bottomFrictionSource` is equal to the second component of the `bottomShearStress`. - -```cpp - bottomFrictionSource[0] = 0.0; - bottomFrictionSource[1] = bottomShearStress[0]; - bottomFrictionSource[2] = bottomShearStress[1]; - - return bottomFrictionSource; - } -``` - -We specify the boundary condition type. - -```cpp - BoundaryTypes boundaryTypesAtPos(const GlobalPosition &globalPos) const - { - BoundaryTypes bcTypes; -``` - -Since we use a weak imposition all boundary conditions are of Neumann type. - -```cpp - bcTypes.setAllNeumann(); - return bcTypes; - } -``` - -We specify the neumann boundary. Due to the weak imposition we calculate the flux at the -boundary, with a Rieman solver. For this the state of a virtual cell outside of the boundary -is needed (`boundaryStateVariables`), wich is calculated with the Riemann invariants -(see Yoon and Kang, Finite Volume Model for Two-Dimensional Shallow Water Flows on Unstructured Grids). -The calculation of the Riemann invariants differ depending on the type of the boundary (h, q or no-flow boundary). - -```cpp - NeumannFluxes neumann(const Element& element, - const FVElementGeometry& fvGeometry, - const ElementVolumeVariables& elemVolVars, - const ElementFluxVariablesCache& elemFluxVarsCache, - const SubControlVolumeFace& scvf) const - { - NeumannFluxes values(0.0); - - const auto& insideScv = fvGeometry.scv(scvf.insideScvIdx()); - const auto& insideVolVars = elemVolVars[insideScv]; - const auto& nxy = scvf.unitOuterNormal(); - const auto gravity = this->spatialParams().gravity(scvf.center()); - std::array boundaryStateVariables; -``` - -Calculate the rieman invariants for imposed discharge at the left side. - -```cpp - if (scvf.center()[0] < 0.0 + eps_) - { - boundaryStateVariables = ShallowWater::fixedDischargeBoundary(discharge_, - insideVolVars.waterDepth(), - insideVolVars.velocity(0), - insideVolVars.velocity(1), - gravity, - nxy); - } -``` - -Calculate the rieman invariants for impose water depth at the right side. - -```cpp - else if (scvf.center()[0] > 100.0 - eps_) - { - boundaryStateVariables = ShallowWater::fixedWaterDepthBoundary(hBoundary_, - insideVolVars.waterDepth(), - insideVolVars.velocity(0), - insideVolVars.velocity(1), - gravity, - nxy); - } -``` - -Calculate the rieman invarianty for the no-flow boundary. - -```cpp - else - { - boundaryStateVariables[0] = insideVolVars.waterDepth(); - boundaryStateVariables[1] = -insideVolVars.velocity(0); - boundaryStateVariables[2] = -insideVolVars.velocity(1); - } -``` - -We calculate the boundary fluxes based on a Riemann problem. - -```cpp - auto riemannFlux = ShallowWater::riemannProblem(insideVolVars.waterDepth(), - boundaryStateVariables[0], - insideVolVars.velocity(0), - boundaryStateVariables[1], - insideVolVars.velocity(1), - boundaryStateVariables[2], - insideVolVars.bedSurface(), - insideVolVars.bedSurface(), - gravity, - nxy); - - values[Indices::massBalanceIdx] = riemannFlux[0]; - values[Indices::velocityXIdx] = riemannFlux[1]; - values[Indices::velocityYIdx] = riemannFlux[2]; - - return values; - } -``` - -We set the initial conditions. In this example constant initial conditions are used. Therefore the argument `globalPos` is not needed. If you want to impose spatial variable initial conditions, you have to use the `globalPos`. - -```cpp - PrimaryVariables initialAtPos(const GlobalPosition &globalPos) const - { - PrimaryVariables values(0.0); -``` - -We set the initial water depth to one meter. +| [:arrow_right: Click to continue with part 1 of the documentation](doc/swe.md) | +|---:| -```cpp - values[0] = 1.0; -``` - -We set the x-component of the initial velocity to zero. - -```cpp - values[1] = 0.0; -``` - -We set the y-component of the initial velocity to zero. - -```cpp - values[2] = 0.0; - - return values; - }; -``` - -\} - -```cpp - -private: -``` - -We declare the private variables of the problem. They are initialized in the problems constructor. -We declare the variable for the analytic solution. - -```cpp - std::vector exactWaterDepth_; - std::vector exactVelocityX_; -``` - -constant friction value. An analytic solution is only available for const friction. If you want to run the simulation with a non constant friciton value (specified in the spatialParams) you have to remove the analytic solution. - -```cpp - Scalar constManningN_; -``` - -The constant bed slope. - -```cpp - Scalar bedSlope_; -``` - -The water depth at the outflow boundary. - -```cpp - Scalar hBoundary_; -``` - -The discharge at the inflow boundary. - -```cpp - Scalar discharge_; -``` - -eps is used as a small value for the definition of the boundry conditions - -```cpp - static constexpr Scalar eps_ = 1.0e-6; - std::string name_; -}; - -} // end namespace Dumux -``` - - - - -## The file `main.cc` - - -This is the main file for the shallow water example. Here we can see the programme sequence and how the system is solved using newton's method. -### Includes - -```cpp -#include -``` - -Standard header file for C++, to get time and date information. - -```cpp -#include -``` - -Standard header file for C++, for in- and output. - -```cpp -#include -``` - -Dumux is based on DUNE, the Distributed and Unified Numerics Environment, which provides several grid managers and linear solvers. So we need some includes from that. - -```cpp -#include -#include -#include -#include -``` - -We need the following class to simplify the writing of dumux simulation data to VTK format. - -```cpp -#include -``` - -In Dumux a property system is used to specify the model. For this, different properties are defined containing type definitions, values and methods. All properties are declared in the file properties.hh. - -```cpp -#include -``` - -The following file contains the parameter class, which manages the definition of input parameters by a default value, the inputfile or the command line. - -```cpp -#include -``` - -The file dumuxmessage.hh contains the class defining the start and end message of the simulation. - -```cpp -#include -#include -``` - -The gridmanager constructs a grid from the information in the input or grid file. There is a specification for the different supported grid managers. - -```cpp -#include -``` - -We include the linear solver to be used to solve the linear system - -```cpp -#include -#include -``` - -We include the nonlinear newtons method - -```cpp -#include -``` - -Further we include assembler, which assembles the linear systems for finite volume schemes (box-scheme, tpfa-approximation, mpfa-approximation) - -```cpp -#include -``` - -We include the properties - -```cpp -#include "properties.hh" -``` - -### Beginning of the main function - -```cpp -int main(int argc, char** argv) try -{ - using namespace Dumux; -``` - -We define the type tag for this problem - -```cpp - using TypeTag = Properties::TTag::RoughChannel; -``` - -We initialize MPI, finalize is done automatically on exit - -```cpp - const auto& mpiHelper = Dune::MPIHelper::instance(argc, argv); -``` - -We print dumux start message - -```cpp - if (mpiHelper.rank() == 0) - DumuxMessage::print(/*firstCall=*/true); -``` - -We parse command line arguments and input file - -```cpp - Parameters::init(argc, argv); -``` - -### Create the grid -A gridmanager tries to create the grid either from a grid file or the input file. - -```cpp - GridManager> gridManager; - gridManager.init(); -``` - -We compute on the leaf grid view - -```cpp - const auto& leafGridView = gridManager.grid().leafGridView(); -``` - -### Setup and solving of the problem -#### Setup -We create and initialize the finite volume grid geometry, the problem, the linear system, including the jacobian matrix, the residual and the solution vector and the gridvariables. -We need the finite volume geometry to build up the subcontrolvolumes (scv) and subcontrolvolume faces (scvf) for each element of the grid partition. - -```cpp - using GridGeometry = GetPropType; - auto gridGeometry = std::make_shared(leafGridView); - gridGeometry->update(); -``` - -In the problem, we define the boundary and initial conditions. - -```cpp - using Problem = GetPropType; - auto problem = std::make_shared(gridGeometry); -``` - -We initialize the solution vector - -```cpp - using SolutionVector = GetPropType; - SolutionVector x(gridGeometry->numDofs()); - problem->applyInitialSolution(x); - auto xOld = x; -``` - -And then use the solutionvector to intialize the gridVariables. - -```cpp - using GridVariables = GetPropType; - auto gridVariables = std::make_shared(problem, gridGeometry); - gridVariables->init(x); -``` - -We get some time loop parameters from the input file. - -```cpp - using Scalar = GetPropType; - const auto tEnd = getParam("TimeLoop.TEnd"); - const auto maxDt = getParam("TimeLoop.MaxTimeStepSize"); - auto dt = getParam("TimeLoop.DtInitial"); -``` - -We intialize the vtk output module. Each model has a predefined model specific output with relevant parameters for that model. - -```cpp - using IOFields = GetPropType; - VtkOutputModule vtkWriter(*gridVariables,x, problem->name()); -``` - -We add the analytical solution ("exactWaterDepth" and "exactVelocityX") to the predefined specific output. - -```cpp - vtkWriter.addField(problem->getExactWaterDepth(), "exactWaterDepth"); - vtkWriter.addField(problem->getExactVelocityX(), "exactVelocityX"); -``` - -We calculate the analytic solution. - -```cpp - problem->analyticalSolution(); - IOFields::initOutputModule(vtkWriter); - vtkWriter.write(0.0); -``` - -We instantiate time loop. - -```cpp - auto timeLoop = std::make_shared>(0, dt, tEnd); - timeLoop->setMaxTimeStepSize(maxDt); -``` - -we set the assembler with the time loop because we have an instationary problem. - -```cpp - using Assembler = FVAssembler; - auto assembler = std::make_shared(problem, gridGeometry, gridVariables, timeLoop); -``` - -We set the linear solver. - -```cpp - using LinearSolver = AMGBiCGSTABBackend>; - auto linearSolver = std::make_shared(leafGridView, gridGeometry->dofMapper()); -``` - -Additionaly, we set the non-linear solver. - -```cpp - using NewtonSolver = Dumux::NewtonSolver; - NewtonSolver nonLinearSolver(assembler, linearSolver); -``` - -We set some check point at the end of the time loop. The check point is used to trigger the vtk output. - -```cpp - timeLoop->setCheckPoint(tEnd); -``` - -We start the time loop. - -```cpp - timeLoop->start(); do - { -``` - -We start to calculate the new solution of that time step. First we define the old solution as the solution of the previous time step for storage evaluations. - -```cpp - assembler->setPreviousSolution(xOld); -``` - -We solve the non-linear system with time step control. - -```cpp - nonLinearSolver.solve(x,*timeLoop); -``` - -We make the new solution the old solution. - -```cpp - xOld = x; - gridVariables->advanceTimeStep(); -``` - -We advance to the time loop to the next step. - -```cpp - timeLoop->advanceTimeStep(); -``` - -We write vtk output, if we reached the check point (end of time loop) - -```cpp - if (timeLoop->isCheckPoint()) - vtkWriter.write(timeLoop->time()); -``` - -We report statistics of this time step. - -```cpp - timeLoop->reportTimeStep(); -``` - -We set new dt as suggested by newton controller for the next time step. - -```cpp - timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize())); - - - } while (!timeLoop->finished()); - - timeLoop->finalize(leafGridView.comm()); -``` - -### Final Output -We print dumux end message. - -```cpp - if (mpiHelper.rank() == 0) - { - Parameters::print(); - DumuxMessage::print(/*firstCall=*/false); - } - - return 0; -} // end main - -catch (const Dumux::ParameterException &e) -{ - std::cerr << std::endl << e << " ---> Abort!" << std::endl; - return 1; -} -catch (const Dune::DGFException & e) -{ - std::cerr << "DGF exception thrown (" << e << - "). Most likely, the DGF file name is wrong " - "or the DGF file is corrupted, " - "e.g. missing hash at end of file or wrong number (dimensions) of entries." - << " ---> Abort!" << std::endl; - return 2; -} -catch (const Dune::Exception &e) -{ - std::cerr << "Dune reported error: " << e << " ---> Abort!" << std::endl; - return 3; -} -catch (...) -{ - std::cerr << "Unknown exception thrown! ---> Abort!" << std::endl; - return 4; -} -``` +## Part 2: Main program flow +| [:arrow_right: Click to continue with part 2 of the documentation](doc/main.md) | +|---:| \ No newline at end of file diff --git a/examples/shallowwaterfriction/doc/_intro.md b/examples/shallowwaterfriction/doc/_intro.md new file mode 100644 index 0000000000..172ca8fb06 --- /dev/null +++ b/examples/shallowwaterfriction/doc/_intro.md @@ -0,0 +1,139 @@ +# Shallow water flow with bottom friction +In this example, the shallow water flow model is applied to simulate +a steady subcritical flow including bottom friction (bed shear stress). + +__You will learn how to__ + +* solve a shallow water flow problem including bottom friction +* compute and output (VTK) an analytical reference solution + +__Result__. The numerical and analytical solutions for the free surface will look like this: + +
+
+ Shallow water result +
Fig.1 - Setup and result for the shallow water problem with bottom friction.
+
+
+ +__Table of contents__. This description is structured as follows: + +[[_TOC_]] + +## Problem set-up +### Model domain +The model domain is given by a rough channel with a slope of 0.001. +The domain is 500 meters long and 5 meters wide. +The bottom altitude is 10 m at the inflow and hence 9.5 m at the outflow. +Bottom friction is considered by applying +Manning's law ($`n`$ = 0.025). + +### Boundary conditions +At the lateral sides a no-flow boundary condition is applied. Also no friction is +considered there and therefore a no slip boundary +condition is applied. These are the default boundary condition for the shallow +water model. At the left border a discharge boundary condition +is applied as inflow boundary condition with $`q = -1.0 m^2 s^{-1}`$. +At the right border a fixed water depth boundary condition +is applied for the outflow. Normal flow is assumed, therefore the water +depth at the right border is calculated using the equation +of Gauckler, Manning and Strickler. + +### Initial conditons +The initial water depth is set to 1 m, which is slightly higher than the normal flow +water depth (0.87 m). Therefore, we expect a decreasing +water level during the simulation until the normal flow condition is reached in +the entire model domain. The inital velocity is set to zero. + +## Model description +As mentioned above, this examples uses the shallow water equations (SWEs) to solve the problem. +These are a depth averaged simplification of the Navier-Stokes equations. To calculate the +bottom friction Manning's law is used. An alternative is Nikuradse's law, which is also implemented +in DuMux. + +### Shallow water model +The shallow water equations are given as: + +```math +\frac{\partial \mathbf{U}}{\partial t} + +\frac{\partial \mathbf{F}}{\partial x} + +\frac{\partial \mathbf{G}}{\partial y} - \mathbf{S_b} - \mathbf{S_f} = 0 +``` + +where $`\mathbf{U}`$, $`\mathbf{F}`$ and $`\mathbf{G}`$ defined as + +```math +\mathbf{U} = \begin{bmatrix} h \\ uh \\ vh \end{bmatrix}, +\mathbf{F} = \begin{bmatrix} hu \\ hu^2 + \frac{1}{2} gh^2 \\ huv \end{bmatrix}, +\mathbf{G} = \begin{bmatrix} hv \\ huv \\ hv^2 + \frac{1}{2} gh^2 \end{bmatrix} +``` + +$`h`$ the water depth, $`u`$ the velocity in x-direction and $`v`$ the velocity in y-direction, +$`g`$ is the constant of gravity. + +The source terms for the bed slope $`\mathbf{S_b}`$ and friction +$`\mathbf{S_f}`$ are given as + +```math +\mathbf{S_b} = \begin{bmatrix} 0 \\ -gh \frac{\partial z}{\partial x} + \\ -gh \frac{\partial z}{\partial y}\end{bmatrix}, +\mathbf{S_f} = \begin{bmatrix} 0 \\ghS_{fx} \\ghS_{fy}\end{bmatrix}. +``` + +with the bedSurface $`z`$. $`S_{fx}`$ and $`S_{fy}`$ are the bed shear stess +components in x- and y-direction, which are calculated by Manning's law. + +### Mannings law +The empirical Manning model specifies the bed shear stress by the following equations: + +```math +S_{fx} = \frac{n^2u}{R_{hy}^{4/3}} \sqrt(u^2 + v^2), + +S_{fy} = \frac{n^2v}{R_{hy}^{4/3}} \sqrt(u^2 + v^2) +``` + +$`n`$ is Manning's friction value and $`R_{hy}`$ is the hydraulic radius, +which is assumed to be equal to the water depth $`h`$. + +### Analytical solution +Since normal flow conditions are assumed, the analytic solution is calculated using the equation +of Gauckler, Manning and Strickler: + +```math +v_m = n^{-1} R_{hy}^{2/3} I_s^{1/2} +``` + +Where the mean velocity $`v_m`$ is given as + +```math +v_m = \frac{q}{h} +``` + +$`I_s`$ is the bed slope and $`q`$ the unity inflow discharge. + +Hence, the water depth $`h`$ can be calculated by + +```math +h = \left(\frac{n q}{\sqrt{I_s}} \right)^{3/5} +``` + +### Discretisation +For this example, a cell-centered finite volume method (cctpfa) is applied to solve the SWEs +in combination with a fully-implicit time discretization. For cases where no sharp fronts or +traveling waves occur it is possible to apply time steps larger than CFL number = 1 to reduce +the computation time. Even if a steady state solution is considered, an implicit time stepping method +is applied. + +# Implementation + +## Folder layout and files + +``` +└── shallowwaterfriction/ + ├── CMakeLists.txt -> build system file + ├── main.cc -> main program flow + ├── params.input -> runtime parameters + ├── properties.hh -> compile time configuration + ├── problem.hh -> boundary & initial conditions + └── spatialparams.hh -> spatial parameter fields +``` diff --git a/examples/shallowwaterfriction/doc/intro.md b/examples/shallowwaterfriction/doc/intro.md deleted file mode 100644 index f0f5e0a155..0000000000 --- a/examples/shallowwaterfriction/doc/intro.md +++ /dev/null @@ -1,97 +0,0 @@ -# Shallow water flow with bottom friction -This example shows how the shallow water flow model can be -applied to simulate steady subcritical flow including -bottom friction (bed shear stress). - -__You will learn how to__ - -* solve a shallow water flow problem including bottom friction -* compute and output (VTK) an analytical reference solution - -__Result__. The numerical and analytical solutions for the problem will look like this: - -![Result Logo](img/result.png) - -__Table of contents__. This description is structured as follows: - -[[_TOC_]] - -## Mathematical model -The 2D shallow water equations (SWEs) are given by - -```math -\frac{\partial \mathbf{U}}{\partial t} + -\frac{\partial \mathbf{F}}{\partial x} + -\frac{\partial \mathbf{G}}{\partial y} - \mathbf{S_b} - \mathbf{S_f} = 0 -``` - -where $`\mathbf{U}`$, $`\mathbf{F}`$ and $`\mathbf{G}`$ defined as - -```math -\mathbf{U} = \begin{bmatrix} h \\ uh \\ vh \end{bmatrix}, -\mathbf{F} = \begin{bmatrix} hu \\ hu^2 + \frac{1}{2} gh^2 \\ huv \end{bmatrix}, -\mathbf{G} = \begin{bmatrix} hv \\ huv \\ hv^2 + \frac{1}{2} gh^2 \end{bmatrix} -``` - -$`Z`$ is the bedSurface, $`h`$ the water depth, $`u`$ the velocity in -x-direction and $`v`$ the velocity in y-direction, $`g`$ is the constant of gravity. - -The source terms for the bed friction $`\mathbf{S_b}`$ and bed slope -$`\mathbf{S_f}`$ are given as - -```math -\mathbf{S_b} = \begin{bmatrix} 0 \\ -gh \frac{\partial z}{\partial x} - \\ -gh \frac{\partial z}{\partial y}\end{bmatrix}, -\mathbf{S_f} = \begin{bmatrix} 0 \\ -ghS_{fx} \\ -ghS_{fy}\end{bmatrix}. -``` - -For this example, a cell-centered finite volume method (`cctpfa`) is applied to solve the SWEs -in combination with a fully-implicit time discretization. For cases where no sharp fronts or -traveling waves occur it is possible to apply time steps larger than CFL number = 1 to reduce -the computation time. Even if a steady state solution is considered, an implicit time stepping method -is applied. - -## Problem set-up - -The model domain is given by a rough channel with a slope of 0.001. -The domain is 500 meters long and 10 meters wide. -![Domain](img/domain.png). - -Bottom friction is considered by applying -the friction law of Manning (Manning n = 0.025). At the lateral sides no friction is considered and a -no-flow no slip boundary condition is applied. This is the default boundary condition for the shallow water model. - -At the left border a discharge boundary condition -is applied as inflow boundary condition with q = -1.0 ($`m^2 s^{-1}`$). At the right border a water fixed depth boundary condition -is applied for the outflow. Normal flow is assumed, therefore the water depth at the right border is calculated after -the of Gaukler-Manning-Strickler equation: - -```math -v_m = n^{-1} R_{hy}^{2/3} I_s^{1/2} -``` - -Where the mean velocity $`v_m`$ is given as $`v_m = \frac{q}{h}`$, -$`n`$ is the friction value after Manning. $`R_{hy}`$ the hydraulic radius, which is assumed to be equal to -the water depth. $`I_s`$ is the bed slope and $`q`$ the unity inflow discharge - -The water depth h can be calculated as -```math -h = \left(\frac{n q}{\sqrt{I_s}} \right)^{3/5} -``` - -The formula of Gaukler Manning and Strickler is also used to calculate the analytic solution. All parameters -for the simulation are given in the file `params.input`. - -# Implementation - -## Folder layout and files - -``` -└── shallowwaterfriction/ - ├── CMakeLists.txt -> build system file - ├── main.cc -> main program flow - ├── params.input -> runtime parameters - ├── properties.hh -> compile time configuration - ├── problem.hh -> boundary & initial conditions - └── spatialparams.hh -> spatial parameter fields -``` diff --git a/examples/shallowwaterfriction/doc/main.md b/examples/shallowwaterfriction/doc/main.md new file mode 100644 index 0000000000..a15f2bbd19 --- /dev/null +++ b/examples/shallowwaterfriction/doc/main.md @@ -0,0 +1,298 @@ + + + +| [:arrow_left: Back to the main documentation](../README.md) | [:arrow_left: Go back to part 1](swe.md) | +|---|---:| + +# Part 2: Main program flow + +We want to solve a shallow water flow problem in a rough +channel to obtain the water table and +compare it to the analytic solution. This is done with the +`main()` function +of the program which is defined in the file `main.cc` described below. + +The code documentation is structured as follows: + +[[_TOC_]] + + + +## The main file `main.cc` + +
+Click to hide/show the file documentation (or inspect the [source code](../main.cc)) + + +### Included header files +
Click to show includes + +DUNE helper class for MPI + +```cpp +#include +``` + +The following headers include functionality related to property definition or retrieval, as well as +the retrieval of input parameters specified in the input file or via the command line. + +```cpp +#include +#include +``` + +The following files contains the available linear solver backends, the non linear Newton Solver +and the assembler for the linear systems arising from finite volume discretizations +(box-scheme, tpfa-approximation, mpfa-approximation). + +```cpp +#include +#include +#include +``` + +The following class provides a convenient way of writing of dumux simulation results to VTK format. + +```cpp +#include +``` + +The gridmanager constructs a grid from the information in the input or grid file. +Many different Dune grid implementations are supported, of which a list can be found +in `gridmanager.hh`. + +```cpp +#include +``` + +We include the header file specifing the properties of this example + +```cpp +#include "properties.hh" +``` + +
+ +### The main function +We will now discuss the main program flow implemented within the `main` function. +At the beginning of each program using Dune, an instance of `Dune::MPIHelper` has to +be created. Moreover, we parse the run-time arguments from the command line and the +input file: + +```cpp +int main(int argc, char** argv) try +{ + using namespace Dumux; + + // The Dune MPIHelper must be instantiated for each program using Dune + Dune::MPIHelper::instance(argc, argv); + + // We parse command line arguments and input file + Parameters::init(argc, argv); +``` + +We define a convenience alias for the type tag of the problem. The type +tag contains all the properties that are needed to define the model and the problem +setup. Throughout the main file, we will obtain types defined for these type tag +using the property system, i.e. with `GetPropType`. + +```cpp + using TypeTag = Properties::TTag::RoughChannel; +``` + +#### Step 1: Create the grid +The `GridManager` class creates the grid from information given in the input file. +This can either be a grid file or, in the case of structured grids, one can specify the coordinates +of the corners of the grid and the number of cells to be used to discretize each spatial direction. + +```cpp + GridManager> gridManager; + gridManager.init(); + + // We compute on the leaf grid view + const auto& leafGridView = gridManager.grid().leafGridView(); +``` + +#### Step 2: Solving the shallow water problem +First, a finite volume grid geometry is constructed from the grid that was created above. +This builds the sub-control volumes (scv) and sub-control volume faces (scvf) for each element +of the grid partition. + +```cpp + using GridGeometry = GetPropType; + auto gridGeometry = std::make_shared(leafGridView); + gridGeometry->update(); +``` + +We now instantiate the problem, in which we define the boundary and initial conditions. + +```cpp + using Problem = GetPropType; + auto problem = std::make_shared(gridGeometry); +``` + +We initialize the solution vector. The shallow water problem is transient, +therefore the initial solution defined in the problem is applied to the +solution vector. On the basis of this solution, we initialize then the grid variables. + +```cpp + using SolutionVector = GetPropType; + SolutionVector x(gridGeometry->numDofs()); + problem->applyInitialSolution(x); + auto xOld = x; + + using GridVariables = GetPropType; + auto gridVariables = std::make_shared(problem, gridGeometry); + gridVariables->init(x); +``` + +Let us now instantiate the time loop. Therefore, we read in some time loop parameters from the input file. +The parameter `tEnd` defines the duration of the simulation, `dt` the initial time step size and `maxDt` the maximal time step size. +Moreover, we define the end of the simulation `tEnd` as check point in the time loop at which we will write the solution to vtk files. + +```cpp + using Scalar = GetPropType; // type for scalar values + const auto tEnd = getParam("TimeLoop.TEnd"); + const auto maxDt = getParam("TimeLoop.MaxTimeStepSize"); + auto dt = getParam("TimeLoop.DtInitial"); + + // We instantiate time loop. + auto timeLoop = std::make_shared>(0.0, dt, tEnd); + timeLoop->setMaxTimeStepSize(maxDt); + timeLoop->setCheckPoint(tEnd); +``` + +We initialize the assembler with a time loop for the transient problem. +Within the time loop, we will use this assembler in each time step to assemble the linear system. + +```cpp + using Assembler = FVAssembler; + auto assembler = std::make_shared(problem, gridGeometry, gridVariables, timeLoop); +``` + +We initialize the linear solver. + +```cpp + using LinearSolver = AMGBiCGSTABBackend>; + auto linearSolver = std::make_shared(leafGridView, gridGeometry->dofMapper()); +``` + +We initialize the non-linear solver. + +```cpp + using NewtonSolver = Dumux::NewtonSolver; + NewtonSolver nonLinearSolver(assembler, linearSolver); +``` + +The following lines of code initialize the vtk output module, add the velocity output facility +and write out the initial solution. At each checkpoint, we will use the output module to write +the solution of a time step into a corresponding vtk file. + +```cpp + VtkOutputModule vtkWriter(*gridVariables,x, problem->name()); + + // add model-specific output fields to the writer + using IOFields = GetPropType; + IOFields::initOutputModule(vtkWriter); + + // We add the analytical solution ("exactWaterDepth" and "exactVelocityX") to the predefined specific output. + vtkWriter.addField(problem->getExactWaterDepth(), "exactWaterDepth"); + vtkWriter.addField(problem->getExactVelocityX(), "exactVelocityX"); + + // We calculate the analytic solution. + problem->analyticalSolution(); + + // write initial solution (including the above calculated analytical solution. + vtkWriter.write(0.0); +``` + +##### The time loop +We start the time loop and solve a new time step as long as `tEnd` is not reached. In every time step, +the problem is assembled and solved, the solution is updated, and when a checkpoint is reached the solution +is written to a new vtk file. In addition, statistics related to CPU time, the current simulation time +and the time step sizes used is printed to the terminal. + +```cpp + timeLoop->start(); do + { + // First we define the old solution as the solution of the previous time step for storage evaluations. + assembler->setPreviousSolution(xOld); + + // We solve the non-linear system with time step control, using Newthon's method. + nonLinearSolver.solve(x,*timeLoop); + + // We make the new solution the old solution. + xOld = x; + gridVariables->advanceTimeStep(); + + // We advance to the time loop to the next step. + timeLoop->advanceTimeStep(); + + // We write vtk output, if we reached the check point (end of time loop) + if (timeLoop->isCheckPoint()) + vtkWriter.write(timeLoop->time()); + + // We report statistics of this time step. + timeLoop->reportTimeStep(); + + // We set new dt as suggested by newton controller for the next time step. + timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize())); + + + } while (!timeLoop->finished()); +``` + +The following piece of code prints a final status report of the time loop +before the program is terminated. + +```cpp + timeLoop->finalize(leafGridView.comm()); + + return 0; +} +``` + +#### Exception handling +In this part of the main file we catch and print possible exceptions that could +occur during the simulation. +
Click to show exception handler + +```cpp +// errors related to run-time parameters +catch (const Dumux::ParameterException &e) +{ + std::cerr << std::endl << e << " ---> Abort!" << std::endl; + return 1; +} +// errors related to the parsing of Dune grid files +catch (const Dune::DGFException & e) +{ + std::cerr << "DGF exception thrown (" << e << + "). Most likely, the DGF file name is wrong " + "or the DGF file is corrupted, " + "e.g. missing hash at end of file or wrong number (dimensions) of entries." + << " ---> Abort!" << std::endl; + return 2; +} +// generic error handling with Dune::Exception +catch (const Dune::Exception &e) +{ + std::cerr << "Dune reported error: " << e << " ---> Abort!" << std::endl; + return 3; +} +// other exceptions +catch (...) +{ + std::cerr << "Unknown exception thrown! ---> Abort!" << std::endl; + return 4; +} +``` + +
+ +
+ + +| [:arrow_left: Back to the main documentation](../README.md) | [:arrow_left: Go back to part 1](swe.md) | +|---|---:| + diff --git a/examples/shallowwaterfriction/doc/main_intro.md b/examples/shallowwaterfriction/doc/main_intro.md new file mode 100644 index 0000000000..15c6b8515d --- /dev/null +++ b/examples/shallowwaterfriction/doc/main_intro.md @@ -0,0 +1,12 @@ +# Part 2: Main program flow + +We want to solve a shallow water flow problem in a rough +channel to obtain the water table and +compare it to the analytic solution. This is done with the +`main()` function +of the program which is defined in the file `main.cc` described below. + +The code documentation is structured as follows: + +[[_TOC_]] + diff --git a/examples/shallowwaterfriction/doc/swe.md b/examples/shallowwaterfriction/doc/swe.md new file mode 100644 index 0000000000..5d67d1bb1e --- /dev/null +++ b/examples/shallowwaterfriction/doc/swe.md @@ -0,0 +1,570 @@ + + + +| [:arrow_left: Back to the main documentation](../README.md) | [:arrow_right: Continue with part 2](main.md) | +|---|---:| + +# Part 1: Implementation of the shallow water flow simulation setup + +The shallow water flow setup, including the bottom friction, +is implemented in the files `properties.hh`, +`problem.hh` and `spatialparams.hh`. In the first of these files, a new +type tag is declared for this problem. This allows the specialization +of DuMux `properties` for this type tag, which can be used to customize compile-time +settings for the simulation. Two exemplary `properties`, that are mandatory to be +specialized, are `Problem` and `SpatialParams`. With the first, one sets the +`Problem` class to be used, in which users can define initial and boundary conditions. +Similarly, in the `SpatialParams` class one implements the parameter distributions +(e.g. friction value) that should be used by the model. + +The documentation provided in the sequel is structured as follows: + +[[_TOC_]] + + + +## Compile-time settings (`properties.hh`) + +In this file, the type tag used for the shallow water flow simulation is defined, +for which we then specialize `properties` to the needs of the desired setup. + + +
+Click to hide/show the file documentation (or inspect the [source code](../properties.hh)) + + +### Includes +
Click to show include files + +The `ShallowWater` type tag specializes most of the `properties` required for a +shallow water flow simulation in DuMux. We will use this in the following to inherit the +respective properties and subsequently specialize those `properties` for our +type tag, which we want to modify or for which no meaningful default can be set. + +```cpp +#include +``` + +We want to use `YaspGrid`, an implementation of the dune grid interface for structured grids: + +```cpp +#include +``` + +In this example, we want to discretize the equations with the cell centered finite volume +scheme using two-point-flux approximation: + +```cpp +#include +``` + +We include the problem and spatial parameters headers used for this simulation. + +```cpp +#include "problem.hh" +#include "spatialparams.hh" +``` + +
+ +### Type tag definition + +First, a so-called type tag is created. Properties are traits specialized for this type tag (a simple `struct`). +The properties of two other type tags are inherited by adding the alias `InheritsFrom`. +Here, properties from the shallow water model (`TTag::ShallowWater`) and the +cell-centered finite volume scheme with two-point-flux approximation (`TTag::CCTpfaModel`) +are inherited. These other type tag definitions can be found in the included +headers `dumux/freeflow/shallowwater/model.hh` and `dumux/discretization/cctpfa.hh`. + +```cpp +// We enter the namespace Dumux::Properties in order to import the entire Dumux namespace for general use: +namespace Dumux::Properties { + +namespace TTag { +struct RoughChannel { using InheritsFrom = std::tuple; }; +} +``` + +### Property specializations + +We use a structured Cartesian grid with tensor product structure. +`Dune::YaspGrid` (Yet Another Structure Parallel Grid) is defined in `dune/grid/yaspgrid.hh` +in the Dune module `dune-grid`. + +```cpp +template +struct Grid +{ using type = Dune::YaspGrid<2, Dune::TensorProductCoordinates, 2> >; }; +``` + +Next, we specialize the properties `Problem` and `SpatialParams` for our new type tag and +set the type to our problem and spatial parameter classes implemented +in `problem.hh` and `spatialparams.hh`. + +```cpp +template +struct Problem +{ using type = Dumux::RoughChannelProblem; }; + +template +struct SpatialParams +{ + using GridGeometry = GetPropType; + using Scalar = GetPropType; + using ElementVolumeVariables = typename GetPropType::LocalView; + using VolumeVariables = typename ElementVolumeVariables::VolumeVariables; + + using type = RoughChannelSpatialParams; +}; +``` + +Finally, we enable caching for the grid geometry. The cache +stores values that were already calculated for later usage. +This makes the simulation run faster but it uses more memory. + +```cpp +template +struct EnableGridGeometryCache +{ static constexpr bool value = true; }; + +} // end namespace Dumux::Properties +``` + + +
+ + + +## The problem file (`problem.hh`) + +This file contains the __problem class__ which defines the initial and boundary +conditions for the shallow water flow simulation with bottom friction. +In addition, the analytical solution is defined here. + + +
+Click to hide/show the file documentation (or inspect the [source code](../problem.hh)) + + +### Include files + +The first include we need here is the `ShallowWaterProblem` class, the base +class from which we will derive. + +```cpp +#include +``` + +In addition, we need the boundaryflux header, which handels the flux over +the model boundaries. + +```cpp +#include +``` + +### The problem class +We enter the problem class where all necessary boundary conditions and initial conditions are set for our simulation. +In addition the analytical solution of the problem is calculated. +As this is a shallow water problem, we inherit from the basic ShallowWaterProblem. + +```cpp +namespace Dumux { + +template +class RoughChannelProblem : public ShallowWaterProblem +{ + // A few convenience aliases used throughout this class. + using ParentType = ShallowWaterProblem; + using PrimaryVariables = GetPropType; + using BoundaryTypes = GetPropType; + using Scalar = GetPropType; + using Indices = typename GetPropType::Indices; + using GridGeometry = GetPropType; + using NeumannFluxes = GetPropType; + using ElementVolumeVariables = typename GetPropType::LocalView; + using GridVariables = GetPropType; + using ElementFluxVariablesCache = typename GridVariables::GridFluxVariablesCache::LocalView; + using FVElementGeometry = typename GetPropType::LocalView; + using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace; + using GridView = typename GetPropType::GridView; + using Element = typename GridView::template Codim<0>::Entity; + using GlobalPosition = typename Element::Geometry::GlobalCoordinate; + using NumEqVector = GetPropType; + using SubControlVolume = typename FVElementGeometry::SubControlVolume; + +public: + // This is the constructor of our problem class. + RoughChannelProblem(std::shared_ptr gridGeometry) + : ParentType(gridGeometry) + { + // We read the parameters from the params.input file. + constManningN_ = getParam("Problem.ManningN"); + bedSlope_ = getParam("Problem.BedSlope"); + discharge_ = getParam("Problem.Discharge"); + // We calculate the outflow boundary condition using the Gauckler-Manning-Strickler formula. + hBoundary_ = this->gaucklerManningStrickler(discharge_,constManningN_,bedSlope_); + // We initialize the analytic solution to a verctor of the appropriate size filled with zeros. + exactWaterDepth_.resize(gridGeometry->numDofs(), 0.0); + exactVelocityX_.resize(gridGeometry->numDofs(), 0.0); + } +``` + +#### Analytical Solution + +The analytical solution is calculated using the equation of Gauckler, Manning and Strickler. + +```cpp + + // Equation of Gauckler, Manning and Strickler + Scalar gaucklerManningStrickler(Scalar discharge, Scalar manningN, Scalar bedSlope) + { + using std::pow; + using std::abs; + using std::sqrt; + + return pow(abs(discharge)*manningN/sqrt(bedSlope), 0.6); + } + + // Calculate the analytical solution + void analyticalSolution() + { + using std::abs; + + for (const auto& element : elements(this->gridGeometry().gridView())) + { + const Scalar h = this->gaucklerManningStrickler(discharge_,constManningN_,bedSlope_); + const Scalar u = abs(discharge_)/h; + + const auto eIdx = this->gridGeometry().elementMapper().index(element); + exactWaterDepth_[eIdx] = h; + exactVelocityX_[eIdx] = u; + } + } + + // Getter function for the analytical solution of the water depth + const std::vector& getExactWaterDepth() + { + return exactWaterDepth_; + } + + // Getter function for the analytical solution of the velocity in x-direction + const std::vector& getExactVelocityX() + { + return exactVelocityX_; + } +``` + +#### Bottom friction + +The bottom friction is a source term and therefore handled by the `source` function. + +```cpp + NumEqVector source(const Element& element, + const FVElementGeometry& fvGeometry, + const ElementVolumeVariables& elemVolVars, + const SubControlVolume &scv) const + { + + NumEqVector source (0.0); + + // Since the bed slope source term is handels within the flux computation, + // in this model the bottom friction is the only source term. + source += bottomFrictionSource(element, fvGeometry, elemVolVars, scv); + + return source; + } +``` + +The calculation of the source term due to bottom friction needs the bottom shear stess. +This is the force per area, which works between the flow and the channel bed +(1D vector with two entries) and is calculated within the `FrictionLaw` class. +The bottom friction causes a loss of momentum. Thus the first entry of the `bottomFrictionSource`, +which is related to the mass balance equation is zero. +The second entry of the `bottomFricitonSource` corresponds to the momentum equation in x-direction +and is therefore equal to the first, the x-component, of the `bottomShearStress`. +Accordingly, the third entry of the `bottomFrictionSource` is equal to the second component of the `bottomShearStress`. + +```cpp + NumEqVector bottomFrictionSource(const Element& element, + const FVElementGeometry& fvGeometry, + const ElementVolumeVariables& elemVolVars, + const SubControlVolume &scv) const + { + NumEqVector bottomFrictionSource(0.0); + const auto& volVars = elemVolVars[scv]; + + // bottom shear stress vector + Dune::FieldVector bottomShearStress = this->spatialParams().frictionLaw(element, scv).shearStress(volVars); + + // source term due to bottom friction + bottomFrictionSource[0] = 0.0; + bottomFrictionSource[1] = bottomShearStress[0]; + bottomFrictionSource[2] = bottomShearStress[1]; + + return bottomFrictionSource; + } +``` + +#### Boundary conditions + +We define the __type of all boundary conditions__ as neumann-type, +because we use a weak imposition. + +```cpp + BoundaryTypes boundaryTypesAtPos(const GlobalPosition &globalPos) const + { + BoundaryTypes bcTypes; + bcTypes.setAllNeumann(); + return bcTypes; + } +``` + +In the following function we implement the __Neumann boundary conditions__. +Due to the weak imposition we calculate the flux at the boundary with a Riemann solver. +This needs the state of a virtual cell outside of the boundary (`boundaryStateVariables`), +wich is calculated with the Riemann invariants +(see: Yoon and Kang, "Finite Volume Model for Two-Dimensional Shallow Water Flows on Unstructured Grids"). + +```cpp + NeumannFluxes neumann(const Element& element, + const FVElementGeometry& fvGeometry, + const ElementVolumeVariables& elemVolVars, + const ElementFluxVariablesCache& elemFluxVarsCache, + const SubControlVolumeFace& scvf) const + { + NeumannFluxes values(0.0); + + const auto& insideScv = fvGeometry.scv(scvf.insideScvIdx()); + const auto& insideVolVars = elemVolVars[insideScv]; + const auto& nxy = scvf.unitOuterNormal(); + const auto gravity = this->spatialParams().gravity(scvf.center()); + std::array boundaryStateVariables; + + // Calculate the Riemann invariants for imposed discharge at the left side. + if (scvf.center()[0] < this->gridGeometry().bBoxMin()[0] + eps_) + { + boundaryStateVariables = ShallowWater::fixedDischargeBoundary(discharge_, + insideVolVars.waterDepth(), + insideVolVars.velocity(0), + insideVolVars.velocity(1), + gravity, + nxy); + } + // Calculate the Riemann invariants for imposed water depth at the right side. + else if (scvf.center()[0] > this->gridGeometry().bBoxMax()[0] - eps_) + { + boundaryStateVariables = ShallowWater::fixedWaterDepthBoundary(hBoundary_, + insideVolVars.waterDepth(), + insideVolVars.velocity(0), + insideVolVars.velocity(1), + gravity, + nxy); + } + // Calculate the Riemann invariants for the no-flow boundary. + else + { + boundaryStateVariables[0] = insideVolVars.waterDepth(); + boundaryStateVariables[1] = -insideVolVars.velocity(0); + boundaryStateVariables[2] = -insideVolVars.velocity(1); + } + // Calculate the boundary fluxes based on a Riemann problem. + auto riemannFlux = ShallowWater::riemannProblem(insideVolVars.waterDepth(), + boundaryStateVariables[0], + insideVolVars.velocity(0), + boundaryStateVariables[1], + insideVolVars.velocity(1), + boundaryStateVariables[2], + insideVolVars.bedSurface(), + insideVolVars.bedSurface(), + gravity, + nxy); + + values[Indices::massBalanceIdx] = riemannFlux[0]; + values[Indices::velocityXIdx] = riemannFlux[1]; + values[Indices::velocityYIdx] = riemannFlux[2]; + + return values; + } +``` + +#### Initial conditions + +We specify the initial conditions for the primary variables (water depth, velocity in y-direction +and velocity in x-direction). In this example constant initial conditions are used. Therefore the +argument `globalPos` is not needed. If you want to impose spatial variable initial conditions, +you have to use the `globalPos` argument. + +```cpp + PrimaryVariables initialAtPos(const GlobalPosition &globalPos) const + { + PrimaryVariables initialValues(0.0); + // We set the initial water depth to one meter. + initialValues[0] = 1.0; + // We set the x-component of the initial velocity to zero. + initialValues[1] = 0.0; + // We set the y-component of the initial velocity to zero. + initialValues[2] = 0.0; + + return initialValues; + } +``` + +We declare the private variables of the problem. + +```cpp +private: + // variables for the analytic solution. + std::vector exactWaterDepth_; + std::vector exactVelocityX_; + // constant friction value (an analytic solution is only available for const friction). + Scalar constManningN_; + // The constant channel bed slope. + Scalar bedSlope_; + // The water depth at the outflow boundary. + Scalar hBoundary_; + // The discharge at the inflow boundary. + Scalar discharge_; + // We assign a private global variable for the epsilon: + static constexpr Scalar eps_ = 1.0e-6; + +}; // end class definition RoughChannelProblem +} // end namespace Dumux +``` + + +
+ + + +## Parameter distributions (`spatialparams.hh`) + +This file contains the __spatial parameters class__ which defines the +the friction law, including it's friction parameter, the acceleration +due to gravity and the altitude of the channel bed surface. In this example only the bed +surface has a non constant distribution. + + +
+Click to hide/show the file documentation (or inspect the [source code](../spatialparams.hh)) + + +### Include files +We include the basic spatial parameters file for finite volumes, from which we will inherit. + +```cpp +#include +``` + +We include all friction laws. + +```cpp +#include +#include +#include +#include +``` + +### The spatial parameters class + +In the `RoughChannelSpatialParams` class, we define all functions needed to describe +the rough channel for the shallow water problem. +We inherit from the `FVSpatialParams` class, which is the base class +for spatial parameters in the context of +applications using finite volume discretization schemes. + +```cpp +namespace Dumux { + +template +class RoughChannelSpatialParams +: public FVSpatialParams> +{ + // This convenience aliases will be used throughout this class + using ThisType = RoughChannelSpatialParams; + using ParentType = FVSpatialParams; + using GridView = typename GridGeometry::GridView; + using FVElementGeometry = typename GridGeometry::LocalView; + using SubControlVolume = typename FVElementGeometry::SubControlVolume; + using Element = typename GridView::template Codim<0>::Entity; + using GlobalPosition = typename Element::Geometry::GlobalCoordinate; +``` + +In the following, the properties of the the rough channel are set. Namely, these are +the friction law, including it's friction parameter, the acceleration +due to gravity and the altitude of the channel bed surface. + +```cpp +public: + // In the constructor we read some values from the `params.input` and initialize the friciton law. + RoughChannelSpatialParams(std::shared_ptr gridGeometry) + : ParentType(gridGeometry) + { + gravity_ = getParam("Problem.Gravity"); + bedSlope_ = getParam("Problem.BedSlope"); + frictionLawType_ = getParam("Problem.FrictionLaw"); + initFrictionLaw(); + } + + // This function handles the initialization of the friction law based on the settings + // specified in `params.input`. + void initFrictionLaw() + { + if (frictionLawType_ == "Manning") + { + Scalar manningN = getParam("Problem.ManningN"); + frictionLaw_ = std::make_unique>(gravity_, manningN); + } + else if (frictionLawType_ == "Nikuradse") + { + Scalar ks = getParam("Problem.Ks"); + frictionLaw_ = std::make_unique>(ks); + } + else if (frictionLawType_ == "None") + { + frictionLaw_ = std::make_unique>(); + } + else + { + std::cout<<"The FrictionLaw in params.input is unknown. Valid entries are `Manning`," + " `Nikuradse` and `None`!"<& frictionLaw(const Element& element, + const SubControlVolume& scv) const + { + return *frictionLaw_; + } + + // This function returns the acceleration due to gravity. + Scalar gravity(const GlobalPosition& globalPos) const + { + return gravity_; + } + + // Define the bed surface based on the bed slope and the bed level at the inflow (10 m). + Scalar bedSurface(const Element& element, + const SubControlVolume& scv) const + { + return 10.0 - element.geometry().center()[0] * bedSlope_; + } + +// We declare the private variables of the problem. +private: + Scalar gravity_; + Scalar bedSlope_; + std::string frictionLawType_; + std::unique_ptr> frictionLaw_; +}; // end class definition of RoughChannelSpatialParams +} // end of namespace Dumux. +``` + + +
+ + +| [:arrow_left: Back to the main documentation](../README.md) | [:arrow_right: Continue with part 2](main.md) | +|---|---:| + diff --git a/examples/shallowwaterfriction/doc/swe_intro.md b/examples/shallowwaterfriction/doc/swe_intro.md new file mode 100644 index 0000000000..c0e5511287 --- /dev/null +++ b/examples/shallowwaterfriction/doc/swe_intro.md @@ -0,0 +1,17 @@ +# Part 1: Implementation of the shallow water flow simulation setup + +The shallow water flow setup, including the bottom friction, +is implemented in the files `properties.hh`, +`problem.hh` and `spatialparams.hh`. In the first of these files, a new +type tag is declared for this problem. This allows the specialization +of DuMux `properties` for this type tag, which can be used to customize compile-time +settings for the simulation. Two exemplary `properties`, that are mandatory to be +specialized, are `Problem` and `SpatialParams`. With the first, one sets the +`Problem` class to be used, in which users can define initial and boundary conditions. +Similarly, in the `SpatialParams` class one implements the parameter distributions +(e.g. friction value) that should be used by the model. + +The documentation provided in the sequel is structured as follows: + +[[_TOC_]] + diff --git a/examples/shallowwaterfriction/img/domain.png b/examples/shallowwaterfriction/img/domain.png deleted file mode 100644 index 27029ab28e1de01c7736fb54be698db508f5777f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18385 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 mqqfICzyFuF$-ix}3&izjJZNvyxm_x diff --git a/examples/shallowwaterfriction/img/result.png b/examples/shallowwaterfriction/img/result.png deleted file mode 100644 index 1ef7c2c9798930cfd4d6b1b8a98b78e0cb718406..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 35503 zcmeFZXH=A1w-7nsE_%^`YDxW20s*W ze4y^AVq@&+tZ#3Gu+n$5wX|`xG&5j$V`T4OW@F93$Hl|N$H8Fg=x8g-&HW!2aM{?K za3|npBqImg6x&QKCFKurXLeW&iuH1 zvi?l*#}Ltt7n`z`Vpw}!_Rk4!us!GS-esVA5O@XaionN*%j+j+ftegvh=ds?tCPZ- zCF#1HtNC_fwDl)EYWNEL&0<*?;cJ>-E4>^+3}0o%q=*Nyva<0Z*k1$T>$5U~6n<=X z_o_GMLdAzz&*0I9R#wD&cvP73;yui>ZYLvHF)#D_|2_Ht%!UccB2Kp3xtDs9aeI1t zDExo_O?k4mA}=rRvYOXyiYn!ml$4Z}ljC#Q)FYr3b?iB=%bF1<(XP@bXdbkOagGKbqGV{fRPQFgeLl$2^K{P23R*?15&#xKe3*zoK1T0b%G zF88lgdKO!cwRH+jbex@{e<>$F^z+mxu~xW$AKPJ}tEi+uM>k2Q%8l3ac$ZzL1mdP; zZ`z*%tMbM0@GynHw4R=x-%4q;_aOpv{x98Bk$lxOGQ znB8ioU#Lc}*H28;)JZmn(KnkHT_+}<`a?%d{ClcCpu1w@`*+6o@87Ss3&wrO%;dO# z|2_}?Ok2D+yo}b%RI^WUaZel_`MJ1i+VgUQkF_t>e)@F%5;-d{gB$QIfN>33nu{bILbKA+ zDQAyOOz2_~arV+oN0iMN5f%?OcbF%7e>kf5@83s?iY&sy(Tj_w>tzdcZ&rtX-%j%I z={GM5TfK;jJF~t{a4$_UVR5WNDEZ+BY`v4iEqp5ez%QJde~Ya&$31ow?%usi!E4Y^ zBqa^09d5Dcf7yGq*lK2f)TV?xDaN1n?(54cX^KX}`9=tSi-8XP3a6EUo^LX^i03LQ zBFK|cPwn%wQxUuA3rZ4uq%kou{N{aubL~+i)YR^g-49_4ewdHhc4Jj0&d$yf5fR;c z^QJh}8$idJ==iK!`XS)Yg-lg;*yESl{w+@326>aq%gcR(huRoSYPrS$_v(vF`28_; zc-z+gKFgguZAfl!;pYHUWnHhbR0-(B14~MT^!4?r`iaUAz5HxkT=NjpKT=YZ(-djb zJcoAtFz}_d0QtnD@Hsb^r?Rp#y__a|B{3?B+}hfDb)qI|dfGr-LL#I5$4V$;9=z*) zCNIXwH02t+-U_Dw26eOPi+{f17&eDiO{2AQ^|0Q)eXHhC6S*}XXLFr|#5Xt?FQ;-_ zKC+L&o_Uc9kTP7prL|SR@27G{tUz$JC;B=O(X)Q$AT2=*jE3X!D3E0I%RhX03GN-` zx{x6I;K56$SB&Q*3RuB`EiY9xG}?YDCtt?Lzjf=@yT_kdM8w;3OG~4#kgz<<(h%_Q z@Gu=K7g!n0aUN>+xrhgsUK$@C-(4SzBe|`pwHe*m*cd`3@c!pdR=BgE;9$e!-6h12 zv@}DCORcS~`)3dpbv*cJyTKgYFnx+lt+G!L6w^~vzr{8xWoDW_UC^p#^|7tJ zJ!VEmA8Fr9A}5Z&TKc~d-y;sE4l#?3m-H-`4_#YZ^L*^g#I05O5isauXPi)h)u^C9 zA-$rdB?qC@2@ir$d=s&>v{ZS1h6d~_c-?v(GNx&Ltm2nS8bO?pjqy;fzW4#kVRxxF z;0C)Yk5O9$9-YJf>M)09aR|J^$A9t=3zFHkbwO0W?t+fn67%%T%+~Ji>`u2-8i1AM zaK2x3G(}xq-Qjx0#^QLDShx5Neqv%G2ds-u!Y$XNo6fxNCsys`Z{OiUGm-+6?o_kh zREVu%935k0mY|>@@srJZ%=!BGVAHv;@*eN4G>;TnaF-c}%k$0U8=08IdB-FqX!oZC zwrr?NOTUfz^vQsXlr%ckEY{W4mE{?84uqrpU_x}X=|GO|MB%XIesMFMdq<{jO|@BU zYMIT1WG@f?PLwXvZYUcPaUP&Xp_jk&Ee>w%Sh+31Vwjx0Mq4u^ix1c*l9z!l$)b<&MAVi^ZJR`LXyoIoEs^#=c79ICRB} zV6I4%aEB|Z+?@P8lRUN`7g!8t6IkIA(C}b6bSFxXi-&3rm3dirrEb{t_L1fS&YExp3*y^vX(mnAF)L$PxrZtvUx8 zWEwjPiQZq!)GXDQYzfyF+f0Nu8rZ2X ztgPVKzN+zz|M>Bqh6YuV=RReU*O|!a@m?|ng2!%;+_rbwfT*vL4P;?+fcnq6D>{lFr0b4p1^B z)?+PgZHyco_^cKC*{(bD2m+yZTIo5}$M3(%1pKXVwn1!fZ$DB}D#@_{QULGIU47^S zha5F3dGqGm2f<{-VLvOe);`+| zkm3PGLB_4~6gEV&#M%gsf=6v^Vuyx74{f8ylO)(OlHiSpKE_?wmJkBOE%F(X+F! z;a`nFI|4e53v$8$kXk<8#HSVvNqG|W>C2ZU$ebex5iAN3`&+MGy~3vv{>Z6Wya}0F zVBUYn{~EP_zj@Vaxh&VeNNINLZ(m%MXU}ReG^8b*iBiIizdnGlBqvGAOA_kE{Q23& z`A@YRI_C*bAwUZj7M4q_75Yak6{zJ6t}E}J8B+g+4?{`~rtD_00S zA=BF71nZf?#OoA<#v1AgrJh0@BY@3W4&`D2%)^x*s05~avUZt z!;X-+A<4kty}D|7a(bFkPD6Z@aEF8A7ANP2SOJUarKMN>bAc!#uHA))6BATe|6=E& z|J&@`{-xvMpSO92&8p>IaL4}oALHXa9voC4Pu=kAC;NV>EUY;kZt9miF8PFo5kj4d z96#8zuJ^yjZ;hf55)yLTTYlL;*W%Prl#WM496piO7)(AhKd-uU#>>n5+SvFy71h;< zizTBrH3^?@D~Z0#e==rcR0+WYk9~@de|qm;?Ts<#msC@2I{BgFGTiO4r5%O-cZeLem}}NT>J`rN@t3ZxAM`wZ~|vsHjl#8eHhl zP|I2VG%K3SrU#nlPFF(uhv49uvV}xLs1b)pM?g`pVWsKk)= zUn;mj+JRD(E+o3sEW6J|s?i(^Sqy|gRU3)w&f5DHKnKfGj2Hf$t6$H9?|TuCOs`18 zb@MmwuU7>u@Pd6AYGFY5i?k$cs`kjPQ42QI*ZV@1fB1pQNH;1Wp>uPp{t6*s^Tb3_ zD6LpN;J19uguUl83}KQ^;NqHfw7Z#VHZm%onG(;%^`o@#M_sjGuWGi9vYB1VvCb7f zldc~|?O#?=WuN8fT;EBZE-7KseeSrip&=JG0|6yg#@N`{Px|6lpd)EX$XKB9d5%lZ z|Ni~EdNcbjhy!_mvPB>kWiwA>?)pJV$#*}nh7^AIPt61#8DceBoCg>aN+WW=26?(V z3TP2@w6nnHyslM!e&*ivfx7whV4|B`*F$+~tHf%wDVo>NW%*ayP=N^{yK3fF;J=aC zHQzOo+?Lty^6_mQ94tht>D=Vw`wXJQuweM7PL(J<^6(~r(bGinn3}V_9FN1Pfc?`B zz{_wZxw{^Rwr@7ZJM)d&e`;3Ww6G&{w<-VZI%*-d*uhKuV zMRAIWjb7+jU0qG*dLWBzzIyd)M??f^!Pl>~->O=JPdiz-_l1;Z&-b1G#Kn=tDd?=) zC~EU|f7|HfCKQaT9GVb!Sq`jPOR!3c#XKf?)@m709h4*STF^DGrtCo7ziKU6J4x4m z3`oU%a+svKZs>;(0vk2wNOXRuF<*UseP@}&LM+s1Gcz+5y>(PsFTX;sR*7}Om1wB( zm6OQsBBORP5*`N!2kz3Og1yz@UYfhF17)c7APxq;t+n1x;;(qKw*2SKWGxm6&%x@j z;r!fO46vPf*lpTl@xw{q`P#QQ?Be_19|S-30$OqVc3RzDUS8gOJ9o|MpMgR%6^FJ6 zHuB7Veg&W$weeD3NI$g1Ot>5!FH~d;-O$ib!6cXIpsVQYR|QSG2M0oUczCoU7X9f) zU2#G=byn$ZM`x($)an|bFizJnsm`Ym%b#~%qE8|F@S)CMN2>>K)={mHCXYeau(RXE zWm(SNWnzNdqB>DRTMy@_)Nk*vjlO~c<|p*xM{4S)gaieB{hQk5j&|y5T3Szc<~!NN zA4YL$2Y&d#EGd}?G^8g>Q^@UL{XXRAzb3M>4q@<+J;7J9>od{vK zUDf~s+V8-zZdg}%qTfKR1%YN~%FW8kARw^!X*n`I1&j}S-w}ReEQF3V-G1@6EVs>o zcVf0qdBVHe2QA_V@iEkz)oGkliqcG|x)x2&C5^Mqcze$c>u8q;=8^|2SL=CJ->%uu zE-dsGS*Vr2S!=7pymL7Q=W@2IH3izOw)mLNd#kf+D?D@diVZo5nWqBE>E z&fWG_)?{iZj=6L5n(Ll90?r5d2=gM1?$L#2daqePJn{3B9Z&%XqrpCHPDmRLjlw{9 zZ!PWin%mc?_-g^5LPGGbld#jrYHMpRq00CY#GH*GkbvOjzgg1&VIl)t0NQcC8q_kd zYi-q2UC+H6B`ABmF!623n$>VISn>4qw0eQ@hf|jL0_Iz{Y@tGFX={VDsmP?7J^mVZ z595E3Qd0-(Q+RB*-lh?I69TNn-V+%7+lmS?DEm_jNnXaFWW`T+d)2a10R}!rMm9ps z!_V-f&QJJ2+!#R3P|s35IXOApNjmQ+wVP2dwY>=i2!n_v&8-YZ|VQ|lWP9DRn5`kX> zST6rDS?>GQ5ijz2xWJ^qc|!*y;^Re(lIvibQsH{=T!JIn)jlOAc0r=X@SFX8d2QT& zjtx|8i_*Z^hN#P)QrhCpJBGy^p5EqAhjf;PoNb(!aN3z3fN+zlPC zQzt4x%NA|tvBvQ#_qX|MXz&brt3BN@RRY8cC669P{ekAxQdM{^fWL#n!~5~q-rgQe zSq3pNYA>(zbS^nrWZG3cyvI+TBpY|ey10EwO1u%i{ePM(jk)f03IQnpZfx{Z({W8n zZ!f!p3|labWdXu@TUZzvKbSDtKtRN`GBCbsc){H4ERT5~D=g~4M78IY%a?yHf66YM zSP{uq&x4a8%LSqZO7zOLYgw45VSLotSXM5srm?Zp@2B9%u(GjDb%|}pY4!koDeljW}H+R!K!9OriWeMyIaD@y&A-wbV2h))pkzY_iDd{0R zH8q71Cm<$)v|o%k9YdAc86sfGy!gJmyN(FSvqM8Lt=^`k-3Bs*iNC*ppQE>cJbn-w z{|aWo;o;$C2VXbhBZX}Ap1a}olH6}X7e;Elq$J#S8CY2_)6>&qq7N$l+TO)Wmqd4U%N^PL z^@pO^)15$-gwRRE0%GCUGjMScuu|Ws1TApoA0MV-y*wDUKH!vI+~p${&Ltumnh>DK zpj2K%<=NjON3YKP#aMJwQc0-_aoZynISJ05P8!BYfM(Vb|+6w%XQqU3uuD4iN{${@7D+Vt0{sz0S z{p@APWp=eRSUw1(c|UTU$zN%S24FuThAaiwOJ@iKtx+wQ`Xn!Z6{G9Of-icHRXBf+ zh>%T^^gINI@MzMP@bGvghf=`&h2KW&Q5Ufu#5;y(K@Dh;jOI1_duzTssT)=1aCC;= zpcJyEIhgR0!dL?LQo6S+ndCx${QMcnU32mYUYO6Y3E#uhlY6N^qGSNDaHmg2Ng137 zxLHg|d$vz2fjn`+c+Vh>Z0+p6Id6=^O8+H_pFW-a^Gyb0{Qw!|1+xcz+=kq@H?t08 zn-p6w^@Z=5$`#yeR2THl)eMX%{iR>Oo;`ma8~7-aVlOO5Bu34#GmLt6<+laln8wms zk;NcpLvp!uv@5>A(j0admBq!y5iWqE>JTdsRm7O=zjf<^H#myuiJoprGzT~p!ZQB& zSZxox5;17{G`co|O=T5b17(0h&@$T7b$hlI+`LVcL-+9LxZ4V+fq}u{Qd-ha%@QsI zh6rsyOp8|Tk5~Zg`g3WQZ^D5Wzd3zRHAqfKwj{I|bL9&t_a4&3nfo)TF(o<*Us^ zH33t2)G|r~3kqJYItRf*Ux|%wz}neSx7T$#Iz>2ojBcGcKND&Wr8Qg`$hv@wi(_;? z5wASlt;5xMjTn*hrLt1oz|b&HBMU?9F@gXhF{#8$S(*63gPK#nxX+&*INL~x*%n^w z5H~yIoIgmQ8i1; zOqs9pj~{=_&HW?kiF{~hmv@Rz&tGsU2A5+qP3ko0Wrk``nS;sk{+i~xL}{N!_iX`z zNHEbq*;F6-&oqaP%IyOpoA&)A1_z4YW*kL#*7Xu|^B;OI)y7$uw<2jDDk>5{xxceE zQe-%otqmM3t(g^_XY;*lGQsCjQ|%TB%cKbV$hch&kTY7KzmA!Jlr zmYDmytnV{>i#@(zNkojUuf}nARSkn4bbq$By)9~^Z4$cGEOizROOMc01L(%HcF%sl zjC%-P%rDif*!prlrk{}#%>@#>e`J79Zb5A212M!br6Yz9W0G)jaYd&t{i*r!WA=Md zqEZ;01iqk**2arC zL`%58@f&>_FC4x#(>xmGU~j)VXa#KkNz~nI?h=n5J(>g+T3TK{VsriH>Kpg{Rl8`a z%+)u+WSoouscM7m=r)VLKd#^s(ur?4nghm70E{sYs#5-EzDUBp>QJ^oK|)d=NX!I1 ziVMIsW-%)TUd+P55rRT#ZSU-?-Q2KGT5z6jxPnO%3KyID9=#nNEl((nvw#J z4gvJ2ERxbe_6R^b;AAhy%LpL(1U+$X{M+YZ)Jv~t&xmf`yjgiPAGbPM5(YpgivI(F zaobv29)YjZ2n6g9Q0G;lDRG>j6*kv-K@^?};v~{677W{SrSACa(7WKn_x&I7wRq=> zA3ttkYPV{RjskE&j4cRdno&@2-={e^G}IV;Bp}$pOE5VF-Uure7FKELi!*lHp6?F| z&HLYjxBV9^X~0iCLN$QJsbKDEy^ZlI)SFQ&NWgeV&h7V}Nf;K7(e}{cRH;FF!V4aP zQ2{o|yirnezq!$DOL!mjB4I0(!Dq%$PK1xIuj|2>^Q&qP5#SZ`RR`nj2kP-{_I7qt z;5L|mh{d$8>}Hy_rh~afckP^=P5RScz6%KGt#Ws!60%;kjoO=ox}xvzx-NU}#QIMo z4(m^)s{@d|#;&+;xE#!wkUW)cRHa-`KBa@>@pxeo`_r@J%0r zf#%ft`4O}BV)uvY8k>(62#i|-E3wv<bMdfBDkLp z{x8o0WS3!VZ1CzbknwASUpqi4!2(Wnt}=_orXC zaB38Og_C%x{V6^G)3BUPKLqO>(~XBR`|jPlKTtCOe%@}Y)Iv{QZ+EdLgjVben8RT1 zxqxD5?e1Q9i%VDA-5mxkm;A9pGAP4$koRI zYU<+dPC`m53${0SQy1D&+jXItfN8#MZ-0lI!1P0r#&j1#|QBcOm$zkC)l2kLIaCV#`2VvbD4GVjDJN?a9#&L`5NY4)i@CIg_BG zf>fyk3a$>FT@0B+0FRLLJO=502n}8rjOK-D3@-KdjGXE=6(xxWu<5j+PV-f^PEJMu zX&rGwguVP_z`R5}4tb!7fI$-=dw+hZ+|JL>zw>gYO#aD}rTz?Z*d7n4A(kVBK`_Rk z%X3d{76k(o|8`C3fvZ;@FJ~aYz`=k3#`q!Q(rSUWVhoSIkEaxr2#hlcK%H;a%L20? z7EmeP_M2bS`}^Z@N0L+$_=MX4XMENu;dSs2s}HAxpQNiHjoOUbySfCi_{792(w~5B zp9f7#K4#`d4pvrMt*z?|UYyJ8LkBlDb`CtHdh#|V?z68uUjY$fjcx4a=H|B&fKO=v zgtNCg9=er4U$ge-K=$=EH#gJpn|`d~E4nY;2nS3h3PKtmYK6 zsia23V-hwADJdzbNl8gZFyApcig19b5`t6fiZ#I9G-vMIxN>sCXxxb5V< z0+0|l_B-3#`6MJHI-yR87E1lw8%51mdRag9^omP0TgLSG%cfz{Mjlu@1{lCIaa

{aVd7}+N-3ZhGhMR*50*hb7^Ozr8 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 ix#3#>Z~SxT8R{;HNko{;X`*7&g<;DME~bD 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. * *****************************************************************************/ -// ## The file `main.cc` +// ## The main file `main.cc` +// [[content]] // -// -// This is the main file for the shallow water example. Here we can see the programme sequence and how the system is solved using newton's method. -// ### Includes +// ### Included header files +// [[details]] includes +// [[exclude]] +// Some generic includes. #include - -// Standard header file for C++, to get time and date information. -#include - -// Standard header file for C++, for in- and output. #include - -// Dumux is based on DUNE, the Distributed and Unified Numerics Environment, which provides several grid managers and linear solvers. So we need some includes from that. +// [[/exclude]] +// +// DUNE helper class for MPI #include -#include -#include -#include -// We need the following class to simplify the writing of dumux simulation data to VTK format. -#include -// In Dumux a property system is used to specify the model. For this, different properties are defined containing type definitions, values and methods. All properties are declared in the file properties.hh. +// The following headers include functionality related to property definition or retrieval, as well as +// the retrieval of input parameters specified in the input file or via the command line. #include -// The following file contains the parameter class, which manages the definition of input parameters by a default value, the inputfile or the command line. #include -// The file dumuxmessage.hh contains the class defining the start and end message of the simulation. -#include -#include -// The gridmanager constructs a grid from the information in the input or grid file. There is a specification for the different supported grid managers. -#include -// We include the linear solver to be used to solve the linear system + +// The following files contains the available linear solver backends, the non linear Newton Solver +// and the assembler for the linear systems arising from finite volume discretizations +// (box-scheme, tpfa-approximation, mpfa-approximation). #include -#include -// We include the nonlinear newtons method #include -// Further we include assembler, which assembles the linear systems for finite volume schemes (box-scheme, tpfa-approximation, mpfa-approximation) #include -// We include the properties + +// The following class provides a convenient way of writing of dumux simulation results to VTK format. +#include +// The gridmanager constructs a grid from the information in the input or grid file. +// Many different Dune grid implementations are supported, of which a list can be found +// in `gridmanager.hh`. +#include + +// We include the header file specifing the properties of this example #include "properties.hh" +// [[/details]] +// -// ### Beginning of the main function +// ### The main function +// We will now discuss the main program flow implemented within the `main` function. +// At the beginning of each program using Dune, an instance of `Dune::MPIHelper` has to +// be created. Moreover, we parse the run-time arguments from the command line and the +// input file: +// [[codeblock]] int main(int argc, char** argv) try { using namespace Dumux; - // We define the type tag for this problem - using TypeTag = Properties::TTag::RoughChannel; - - // We initialize MPI, finalize is done automatically on exit - const auto& mpiHelper = Dune::MPIHelper::instance(argc, argv); - - // We print dumux start message - if (mpiHelper.rank() == 0) - DumuxMessage::print(/*firstCall=*/true); + // The Dune MPIHelper must be instantiated for each program using Dune + Dune::MPIHelper::instance(argc, argv); // We parse command line arguments and input file Parameters::init(argc, argv); + // [[/codeblock]] - // ### Create the grid - // A gridmanager tries to create the grid either from a grid file or the input file. + // We define a convenience alias for the type tag of the problem. The type + // tag contains all the properties that are needed to define the model and the problem + // setup. Throughout the main file, we will obtain types defined for these type tag + // using the property system, i.e. with `GetPropType`. + using TypeTag = Properties::TTag::RoughChannel; + + // #### Step 1: Create the grid + // The `GridManager` class creates the grid from information given in the input file. + // This can either be a grid file or, in the case of structured grids, one can specify the coordinates + // of the corners of the grid and the number of cells to be used to discretize each spatial direction. + //[[codeblock]] GridManager> gridManager; gridManager.init(); // We compute on the leaf grid view const auto& leafGridView = gridManager.grid().leafGridView(); + //[[/codeblock]] - // ### Setup and solving of the problem - // #### Setup - // We create and initialize the finite volume grid geometry, the problem, the linear system, including the jacobian matrix, the residual and the solution vector and the gridvariables. - // We need the finite volume geometry to build up the subcontrolvolumes (scv) and subcontrolvolume faces (scvf) for each element of the grid partition. + // #### Step 2: Solving the shallow water problem + // First, a finite volume grid geometry is constructed from the grid that was created above. + // This builds the sub-control volumes (scv) and sub-control volume faces (scvf) for each element + // of the grid partition. using GridGeometry = GetPropType; auto gridGeometry = std::make_shared(leafGridView); gridGeometry->update(); - // In the problem, we define the boundary and initial conditions. + // We now instantiate the problem, in which we define the boundary and initial conditions. using Problem = GetPropType; auto problem = std::make_shared(gridGeometry); - // We initialize the solution vector + // We initialize the solution vector. The shallow water problem is transient, + // therefore the initial solution defined in the problem is applied to the + // solution vector. On the basis of this solution, we initialize then the grid variables. using SolutionVector = GetPropType; SolutionVector x(gridGeometry->numDofs()); problem->applyInitialSolution(x); auto xOld = x; - // And then use the solutionvector to intialize the gridVariables. using GridVariables = GetPropType; auto gridVariables = std::make_shared(problem, gridGeometry); gridVariables->init(x); - // We get some time loop parameters from the input file. - using Scalar = GetPropType; + // Let us now instantiate the time loop. Therefore, we read in some time loop parameters from the input file. + // The parameter `tEnd` defines the duration of the simulation, `dt` the initial time step size and `maxDt` the maximal time step size. + // Moreover, we define the end of the simulation `tEnd` as check point in the time loop at which we will write the solution to vtk files. + // [[codeblock]] + using Scalar = GetPropType; // type for scalar values const auto tEnd = getParam("TimeLoop.TEnd"); const auto maxDt = getParam("TimeLoop.MaxTimeStepSize"); auto dt = getParam("TimeLoop.DtInitial"); - // We intialize the vtk output module. Each model has a predefined model specific output with relevant parameters for that model. - using IOFields = GetPropType; - VtkOutputModule vtkWriter(*gridVariables,x, problem->name()); - // We add the analytical solution ("exactWaterDepth" and "exactVelocityX") to the predefined specific output. - vtkWriter.addField(problem->getExactWaterDepth(), "exactWaterDepth"); - vtkWriter.addField(problem->getExactVelocityX(), "exactVelocityX"); - // We calculate the analytic solution. - problem->analyticalSolution(); - IOFields::initOutputModule(vtkWriter); - vtkWriter.write(0.0); - // We instantiate time loop. - auto timeLoop = std::make_shared>(0, dt, tEnd); + auto timeLoop = std::make_shared>(0.0, dt, tEnd); timeLoop->setMaxTimeStepSize(maxDt); + timeLoop->setCheckPoint(tEnd); + // [[/codeblock]] - //we set the assembler with the time loop because we have an instationary problem. + // We initialize the assembler with a time loop for the transient problem. + // Within the time loop, we will use this assembler in each time step to assemble the linear system. using Assembler = FVAssembler; auto assembler = std::make_shared(problem, gridGeometry, gridVariables, timeLoop); - // We set the linear solver. + // We initialize the linear solver. using LinearSolver = AMGBiCGSTABBackend>; auto linearSolver = std::make_shared(leafGridView, gridGeometry->dofMapper()); - // Additionaly, we set the non-linear solver. + // We initialize the non-linear solver. using NewtonSolver = Dumux::NewtonSolver; NewtonSolver nonLinearSolver(assembler, linearSolver); - // We set some check point at the end of the time loop. The check point is used to trigger the vtk output. - timeLoop->setCheckPoint(tEnd); + // The following lines of code initialize the vtk output module, add the velocity output facility + // and write out the initial solution. At each checkpoint, we will use the output module to write + // the solution of a time step into a corresponding vtk file. + // [[codeblock]] + VtkOutputModule vtkWriter(*gridVariables,x, problem->name()); + + // add model-specific output fields to the writer + using IOFields = GetPropType; + IOFields::initOutputModule(vtkWriter); + + // We add the analytical solution ("exactWaterDepth" and "exactVelocityX") to the predefined specific output. + vtkWriter.addField(problem->getExactWaterDepth(), "exactWaterDepth"); + vtkWriter.addField(problem->getExactVelocityX(), "exactVelocityX"); + + // We calculate the analytic solution. + problem->analyticalSolution(); - // We start the time loop. + // write initial solution (including the above calculated analytical solution. + vtkWriter.write(0.0); + // [[/codeblock]] + + // ##### The time loop + // We start the time loop and solve a new time step as long as `tEnd` is not reached. In every time step, + // the problem is assembled and solved, the solution is updated, and when a checkpoint is reached the solution + // is written to a new vtk file. In addition, statistics related to CPU time, the current simulation time + // and the time step sizes used is printed to the terminal. + // [[codeblock]] timeLoop->start(); do { - // We start to calculate the new solution of that time step. First we define the old solution as the solution of the previous time step for storage evaluations. + // First we define the old solution as the solution of the previous time step for storage evaluations. assembler->setPreviousSolution(xOld); - // We solve the non-linear system with time step control. + // We solve the non-linear system with time step control, using Newthon's method. nonLinearSolver.solve(x,*timeLoop); // We make the new solution the old solution. @@ -170,25 +196,26 @@ int main(int argc, char** argv) try } while (!timeLoop->finished()); + // [[/codeblock]] + // The following piece of code prints a final status report of the time loop + // before the program is terminated. timeLoop->finalize(leafGridView.comm()); - // ### Final Output - // We print dumux end message. - if (mpiHelper.rank() == 0) - { - Parameters::print(); - DumuxMessage::print(/*firstCall=*/false); - } - return 0; -} // end main - +} +// #### Exception handling +// In this part of the main file we catch and print possible exceptions that could +// occur during the simulation. +// [[details]] exception handler +// [[codeblock]] +// errors related to run-time parameters catch (const Dumux::ParameterException &e) { std::cerr << std::endl << e << " ---> Abort!" << std::endl; return 1; } +// errors related to the parsing of Dune grid files catch (const Dune::DGFException & e) { std::cerr << "DGF exception thrown (" << e << @@ -198,13 +225,18 @@ catch (const Dune::DGFException & e) << " ---> Abort!" << std::endl; return 2; } +// generic error handling with Dune::Exception catch (const Dune::Exception &e) { std::cerr << "Dune reported error: " << e << " ---> Abort!" << std::endl; return 3; } +// other exceptions catch (...) { std::cerr << "Unknown exception thrown! ---> Abort!" << std::endl; return 4; } +// [[/codeblock]] +// [[/details]] +// [[/content]] diff --git a/examples/shallowwaterfriction/problem.hh b/examples/shallowwaterfriction/problem.hh index 12bfbe3261..aa32e22df7 100644 --- a/examples/shallowwaterfriction/problem.hh +++ b/examples/shallowwaterfriction/problem.hh @@ -20,21 +20,34 @@ #ifndef DUMUX_EXAMPLE_SHALLOWWATER_FRICTION_PROBLEM_HH #define DUMUX_EXAMPLE_SHALLOWWATER_FRICTION_PROBLEM_HH -// ## The file `problem.hh` -// We start with includes -#include -#include +// ## The problem file (`problem.hh`) +// +// This file contains the __problem class__ which defines the initial and boundary +// conditions for the shallow water flow simulation with bottom friction. +// In addition, the analytical solution is defined here. +// +// [[content]] +// +// ### Include files +// +// The first include we need here is the `ShallowWaterProblem` class, the base +// class from which we will derive. #include +// In addition, we need the boundaryflux header, which handels the flux over +// the model boundaries. #include +// ### The problem class // We enter the problem class where all necessary boundary conditions and initial conditions are set for our simulation. +// In addition the analytical solution of the problem is calculated. // As this is a shallow water problem, we inherit from the basic ShallowWaterProblem. +// [[codeblock]] namespace Dumux { template class RoughChannelProblem : public ShallowWaterProblem { - // We use convenient declarations that we derive from the property system. + // A few convenience aliases used throughout this class. using ParentType = ShallowWaterProblem; using PrimaryVariables = GetPropType; using BoundaryTypes = GetPropType; @@ -45,7 +58,6 @@ class RoughChannelProblem : public ShallowWaterProblem using ElementVolumeVariables = typename GetPropType::LocalView; using GridVariables = GetPropType; using ElementFluxVariablesCache = typename GridVariables::GridFluxVariablesCache::LocalView; - using VolumeVariables = typename ElementVolumeVariables::VolumeVariables; using FVElementGeometry = typename GetPropType::LocalView; using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace; using GridView = typename GetPropType::GridView; @@ -60,31 +72,24 @@ public: : ParentType(gridGeometry) { // We read the parameters from the params.input file. - name_ = getParam("Problem.Name"); constManningN_ = getParam("Problem.ManningN"); bedSlope_ = getParam("Problem.BedSlope"); discharge_ = getParam("Problem.Discharge"); // We calculate the outflow boundary condition using the Gauckler-Manning-Strickler formula. - hBoundary_ = this->gauklerManningStrickler(discharge_,constManningN_,bedSlope_); + hBoundary_ = this->gaucklerManningStrickler(discharge_,constManningN_,bedSlope_); // We initialize the analytic solution to a verctor of the appropriate size filled with zeros. exactWaterDepth_.resize(gridGeometry->numDofs(), 0.0); exactVelocityX_.resize(gridGeometry->numDofs(), 0.0); } + // [[/codeblock]] - // Get the analytical water depth - const std::vector& getExactWaterDepth() - { - return exactWaterDepth_; - } - - // Get the analytical velocity - const std::vector& getExactVelocityX() - { - return exactVelocityX_; - } + // #### Analytical Solution + // + // The analytical solution is calculated using the equation of Gauckler, Manning and Strickler. + // [[codeblock]] - // Get the water depth with Gauckler-Manning-Strickler - Scalar gauklerManningStrickler(Scalar discharge, Scalar manningN, Scalar bedSlope) + // Equation of Gauckler, Manning and Strickler + Scalar gaucklerManningStrickler(Scalar discharge, Scalar manningN, Scalar bedSlope) { using std::pow; using std::abs; @@ -93,14 +98,14 @@ public: return pow(abs(discharge)*manningN/sqrt(bedSlope), 0.6); } - // Get the analytical solution + // Calculate the analytical solution void analyticalSolution() { using std::abs; for (const auto& element : elements(this->gridGeometry().gridView())) { - const Scalar h = this->gauklerManningStrickler(discharge_,constManningN_,bedSlope_); + const Scalar h = this->gaucklerManningStrickler(discharge_,constManningN_,bedSlope_); const Scalar u = abs(discharge_)/h; const auto eIdx = this->gridGeometry().elementMapper().index(element); @@ -109,61 +114,87 @@ public: } } - // Get the problem name. It is used as a prefix for files generated by the simulation. - const std::string& name() const + // Getter function for the analytical solution of the water depth + const std::vector& getExactWaterDepth() { - return name_; + return exactWaterDepth_; } - // Get the source term. - NumEqVector source(const Element& element, - const FVElementGeometry& fvGeometry, - const ElementVolumeVariables& elemVolVars, - const SubControlVolume &scv) const + // Getter function for the analytical solution of the velocity in x-direction + const std::vector& getExactVelocityX() + { + return exactVelocityX_; + } + // [[/codeblock]] + + // #### Bottom friction + // + // The bottom friction is a source term and therefore handled by the `source` function. + // [[codeblock]] + NumEqVector source(const Element& element, + const FVElementGeometry& fvGeometry, + const ElementVolumeVariables& elemVolVars, + const SubControlVolume &scv) const { NumEqVector source (0.0); - // In this model the bottom friction is the only source. + // Since the bed slope source term is handels within the flux computation, + // in this model the bottom friction is the only source term. source += bottomFrictionSource(element, fvGeometry, elemVolVars, scv); return source; } - - // Get the source term due to bottom friction. - NumEqVector bottomFrictionSource(const Element& element, + // [[/codeblock]] + + // The calculation of the source term due to bottom friction needs the bottom shear stess. + // This is the force per area, which works between the flow and the channel bed + // (1D vector with two entries) and is calculated within the `FrictionLaw` class. + // The bottom friction causes a loss of momentum. Thus the first entry of the `bottomFrictionSource`, + // which is related to the mass balance equation is zero. + // The second entry of the `bottomFricitonSource` corresponds to the momentum equation in x-direction + // and is therefore equal to the first, the x-component, of the `bottomShearStress`. + // Accordingly, the third entry of the `bottomFrictionSource` is equal to the second component of the `bottomShearStress`. + // [[codeblock]] + NumEqVector bottomFrictionSource(const Element& element, const FVElementGeometry& fvGeometry, const ElementVolumeVariables& elemVolVars, const SubControlVolume &scv) const - { + { NumEqVector bottomFrictionSource(0.0); const auto& volVars = elemVolVars[scv]; - // For the calculation of the source term due to bottom friction the two-dimensional bottom shear stess vector is needed. This is the force per area, which works between the flow and the bed. It is calculated within the `FrictionLaw`, which is a spatialParameter. In this model the `FrictionLawManning` is used (see `params.input`). + // bottom shear stress vector Dune::FieldVector bottomShearStress = this->spatialParams().frictionLaw(element, scv).shearStress(volVars); - // The bottom shear stress causes a pure loss of momentum. Thus the first entry of the `bottomFrictionSource`, which is related to the mass balance equation is zero. The second entry of the `bottomFricitonSource` corresponds to the momentum equation in x-direction and is therefore equal to the first, the x-component, of the `bottomShearStress`. Accordingly the third entry of the `bottomFrictionSource` is equal to the second component of the `bottomShearStress`. + // source term due to bottom friction bottomFrictionSource[0] = 0.0; bottomFrictionSource[1] = bottomShearStress[0]; bottomFrictionSource[2] = bottomShearStress[1]; return bottomFrictionSource; - } + } + // [[/codeblock]] - // We specify the boundary condition type. + // #### Boundary conditions + // + // We define the __type of all boundary conditions__ as neumann-type, + // because we use a weak imposition. + // [[codeblock]] BoundaryTypes boundaryTypesAtPos(const GlobalPosition &globalPos) const { BoundaryTypes bcTypes; - // Since we use a weak imposition all boundary conditions are of Neumann type. bcTypes.setAllNeumann(); return bcTypes; } - - // We specify the neumann boundary. Due to the weak imposition we calculate the flux at the - // boundary, with a Rieman solver. For this the state of a virtual cell outside of the boundary - // is needed (`boundaryStateVariables`), wich is calculated with the Riemann invariants - // (see Yoon and Kang, Finite Volume Model for Two-Dimensional Shallow Water Flows on Unstructured Grids). - // The calculation of the Riemann invariants differ depending on the type of the boundary (h, q or no-flow boundary). + // [[/codeblock]] + + // In the following function we implement the __Neumann boundary conditions__. + // Due to the weak imposition we calculate the flux at the boundary with a Riemann solver. + // This needs the state of a virtual cell outside of the boundary (`boundaryStateVariables`), + // wich is calculated with the Riemann invariants + // (see: Yoon and Kang, "Finite Volume Model for Two-Dimensional Shallow Water Flows on Unstructured Grids"). + // [[codeblock]] NeumannFluxes neumann(const Element& element, const FVElementGeometry& fvGeometry, const ElementVolumeVariables& elemVolVars, @@ -178,8 +209,8 @@ public: const auto gravity = this->spatialParams().gravity(scvf.center()); std::array boundaryStateVariables; - // Calculate the rieman invariants for imposed discharge at the left side. - if (scvf.center()[0] < 0.0 + eps_) + // Calculate the Riemann invariants for imposed discharge at the left side. + if (scvf.center()[0] < this->gridGeometry().bBoxMin()[0] + eps_) { boundaryStateVariables = ShallowWater::fixedDischargeBoundary(discharge_, insideVolVars.waterDepth(), @@ -188,8 +219,8 @@ public: gravity, nxy); } - // Calculate the rieman invariants for impose water depth at the right side. - else if (scvf.center()[0] > 100.0 - eps_) + // Calculate the Riemann invariants for imposed water depth at the right side. + else if (scvf.center()[0] > this->gridGeometry().bBoxMax()[0] - eps_) { boundaryStateVariables = ShallowWater::fixedWaterDepthBoundary(hBoundary_, insideVolVars.waterDepth(), @@ -198,14 +229,14 @@ public: gravity, nxy); } - // Calculate the rieman invarianty for the no-flow boundary. + // Calculate the Riemann invariants for the no-flow boundary. else { boundaryStateVariables[0] = insideVolVars.waterDepth(); boundaryStateVariables[1] = -insideVolVars.velocity(0); boundaryStateVariables[2] = -insideVolVars.velocity(1); } - // We calculate the boundary fluxes based on a Riemann problem. + // Calculate the boundary fluxes based on a Riemann problem. auto riemannFlux = ShallowWater::riemannProblem(insideVolVars.waterDepth(), boundaryStateVariables[0], insideVolVars.velocity(0), @@ -223,41 +254,48 @@ public: return values; } - - // We set the initial conditions. In this example constant initial conditions are used. Therefore the argument `globalPos` is not needed. If you want to impose spatial variable initial conditions, you have to use the `globalPos`. + // [[/codeblock]] + + // #### Initial conditions + // + // We specify the initial conditions for the primary variables (water depth, velocity in y-direction + // and velocity in x-direction). In this example constant initial conditions are used. Therefore the + //argument `globalPos` is not needed. If you want to impose spatial variable initial conditions, + // you have to use the `globalPos` argument. + // [[codeblock]] PrimaryVariables initialAtPos(const GlobalPosition &globalPos) const { - PrimaryVariables values(0.0); + PrimaryVariables initialValues(0.0); // We set the initial water depth to one meter. - values[0] = 1.0; + initialValues[0] = 1.0; // We set the x-component of the initial velocity to zero. - values[1] = 0.0; + initialValues[1] = 0.0; // We set the y-component of the initial velocity to zero. - values[2] = 0.0; - - return values; - }; + initialValues[2] = 0.0; - // \} + return initialValues; + } + // [[/codeblock]] +// We declare the private variables of the problem. +// [[codeblock]] private: - // We declare the private variables of the problem. They are initialized in the problems constructor. - // We declare the variable for the analytic solution. + // variables for the analytic solution. std::vector exactWaterDepth_; std::vector exactVelocityX_; - // constant friction value. An analytic solution is only available for const friction. If you want to run the simulation with a non constant friciton value (specified in the spatialParams) you have to remove the analytic solution. + // constant friction value (an analytic solution is only available for const friction). Scalar constManningN_; - // The constant bed slope. + // The constant channel bed slope. Scalar bedSlope_; // The water depth at the outflow boundary. Scalar hBoundary_; // The discharge at the inflow boundary. Scalar discharge_; - // eps is used as a small value for the definition of the boundry conditions + // We assign a private global variable for the epsilon: static constexpr Scalar eps_ = 1.0e-6; - std::string name_; -}; +}; // end class definition RoughChannelProblem } // end namespace Dumux - +// [[/codeblock]] +// [[/content]] #endif diff --git a/examples/shallowwaterfriction/properties.hh b/examples/shallowwaterfriction/properties.hh index d1e87e9aa4..86e03e69c1 100644 --- a/examples/shallowwaterfriction/properties.hh +++ b/examples/shallowwaterfriction/properties.hh @@ -20,34 +20,53 @@ #ifndef DUMUX_EXAMPLE_SHALLOWWATER_FRICTION_PROPERTIES_HH #define DUMUX_EXAMPLE_SHALLOWWATER_FRICTION_PROPERTIES_HH -// ## The file `properties.hh` +// ## Compile-time settings (`properties.hh`) // -// The header includes will be mentioned in the text below. -//
Click to show the header includes +// In this file, the type tag used for the shallow water flow simulation is defined, +// for which we then specialize `properties` to the needs of the desired setup. +// +// [[content]] +// +// ### Includes +// [[details]] include files +// +// The `ShallowWater` type tag specializes most of the `properties` required for a +// shallow water flow simulation in DuMux. We will use this in the following to inherit the +// respective properties and subsequently specialize those `properties` for our +// type tag, which we want to modify or for which no meaningful default can be set. +#include + +// We want to use `YaspGrid`, an implementation of the dune grid interface for structured grids: #include -#include +// In this example, we want to discretize the equations with the cell centered finite volume +// scheme using two-point-flux approximation: #include -#include -#include "spatialparams.hh" +// We include the problem and spatial parameters headers used for this simulation. #include "problem.hh" -//
+#include "spatialparams.hh" +// [[/details]] // - -// Let's define the properties for our simulation -namespace Dumux::Properties { - -// First, a so-called TypeTag is created. Properties are traits specialized for this TypeTag (a simple `struct`). -// The properties of two other TypeTags are inherited by adding the alias `InheritsFrom`. +// ### Type tag definition +// +// First, a so-called type tag is created. Properties are traits specialized for this type tag (a simple `struct`). +// The properties of two other type tags are inherited by adding the alias `InheritsFrom`. // Here, properties from the shallow water model (`TTag::ShallowWater`) and the // cell-centered finite volume scheme with two-point-flux approximation (`TTag::CCTpfaModel`) -// are inherited. These other TypeTag definitions can be found in the included +// are inherited. These other type tag definitions can be found in the included // headers `dumux/freeflow/shallowwater/model.hh` and `dumux/discretization/cctpfa.hh`. +// [[codeblock]] +// We enter the namespace Dumux::Properties in order to import the entire Dumux namespace for general use: +namespace Dumux::Properties { + namespace TTag { struct RoughChannel { using InheritsFrom = std::tuple; }; } +// [[/codeblock]] +// ### Property specializations +// // We use a structured Cartesian grid with tensor product structure. // `Dune::YaspGrid` (Yet Another Structure Parallel Grid) is defined in `dune/grid/yaspgrid.hh` // in the Dune module `dune-grid`. @@ -55,7 +74,7 @@ template struct Grid { using type = Dune::YaspGrid<2, Dune::TensorProductCoordinates, 2> >; }; -// Next, we specialize the properties `Problem` and `SpatialParams` for our new TypeTag and +// Next, we specialize the properties `Problem` and `SpatialParams` for our new type tag and // set the type to our problem and spatial parameter classes implemented // in `problem.hh` and `spatialparams.hh`. // [[codeblock]] @@ -83,5 +102,5 @@ struct EnableGridGeometryCache { static constexpr bool value = true; }; } // end namespace Dumux::Properties - +// [[/content]] #endif diff --git a/examples/shallowwaterfriction/spatialparams.hh b/examples/shallowwaterfriction/spatialparams.hh index 1638ce5c31..68f188781d 100644 --- a/examples/shallowwaterfriction/spatialparams.hh +++ b/examples/shallowwaterfriction/spatialparams.hh @@ -20,28 +20,40 @@ #ifndef DUMUX_ROUGH_CHANNEL_SPATIAL_PARAMETERS_HH #define DUMUX_ROUGH_CHANNEL_SPATIAL_PARAMETERS_HH -// ## The file `spatialparams.hh` +// ## Parameter distributions (`spatialparams.hh`) // +// This file contains the __spatial parameters class__ which defines the +// the friction law, including it's friction parameter, the acceleration +// due to gravity and the altitude of the channel bed surface. In this example only the bed +// surface has a non constant distribution. // -// We include the basic spatial parameters for finite volumes file from which we will inherit +// [[content]] +// +// ### Include files +// We include the basic spatial parameters file for finite volumes, from which we will inherit. #include -// The parameters header is needed to retrieve run-time parameters. -#include -// We include all friction laws, between we can choose for the calculation of the bottom friction source. +// We include all friction laws. #include #include #include +#include -// We enter the namespace Dumux. All Dumux functions and classes are in a namespace Dumux, to make sure they don`t clash with symbols from other libraries you may want to use in conjunction with Dumux. +// ### The spatial parameters class +// +// In the `RoughChannelSpatialParams` class, we define all functions needed to describe +// the rough channel for the shallow water problem. +// We inherit from the `FVSpatialParams` class, which is the base class +// for spatial parameters in the context of +// applications using finite volume discretization schemes. +// [[codeblock]] namespace Dumux { -//In the RoughChannelSpatialParams class we define all functions needed to describe the spatial distributed parameters. template class RoughChannelSpatialParams : public FVSpatialParams> { - // We introduce using declarations that are derived from the property system which we need in this class + // This convenience aliases will be used throughout this class using ThisType = RoughChannelSpatialParams; using ParentType = FVSpatialParams; using GridView = typename GridGeometry::GridView; @@ -49,9 +61,14 @@ class RoughChannelSpatialParams using SubControlVolume = typename FVElementGeometry::SubControlVolume; using Element = typename GridView::template Codim<0>::Entity; using GlobalPosition = typename Element::Geometry::GlobalCoordinate; + // [[/codeblock]] + // In the following, the properties of the the rough channel are set. Namely, these are + // the friction law, including it's friction parameter, the acceleration + // due to gravity and the altitude of the channel bed surface. + // [[codeblock]] public: - // In the constructor be read some values from the `params.input` and initialize the friciton law. + // In the constructor we read some values from the `params.input` and initialize the friciton law. RoughChannelSpatialParams(std::shared_ptr gridGeometry) : ParentType(gridGeometry) { @@ -61,7 +78,8 @@ public: initFrictionLaw(); } - // We initialize the friction law based on the law specified in `params.input`. + // This function handles the initialization of the friction law based on the settings + // specified in `params.input`. void initFrictionLaw() { if (frictionLawType_ == "Manning") @@ -74,45 +92,45 @@ public: Scalar ks = getParam("Problem.Ks"); frictionLaw_ = std::make_unique>(ks); } + else if (frictionLawType_ == "None") + { + frictionLaw_ = std::make_unique>(); + } else { - std::cout<<"The FrictionLaw in params.input is unknown. Valid entries are `Manning` and `Nikuradse`!"<& frictionLaw(const Element& element, + const SubControlVolume& scv) const { - return gravity_; + return *frictionLaw_; } - // Use this function for a constant gravity. - Scalar gravity() const + // This function returns the acceleration due to gravity. + Scalar gravity(const GlobalPosition& globalPos) const { return gravity_; } - // This function returns an object of the friction law class, which is initialized with the appropriate friction values. If you want to use different friciton values or laws, you have to use a vector of unique_ptr for `frictionLaw_` and pick the right friction law instances via the `element` argument. - const FrictionLaw& frictionLaw(const Element& element, - const SubControlVolume& scv) const - { - return *frictionLaw_; - } - - // Define the bed surface based on the `bedSlope_`. + // Define the bed surface based on the bed slope and the bed level at the inflow (10 m). Scalar bedSurface(const Element& element, const SubControlVolume& scv) const { return 10.0 - element.geometry().center()[0] * bedSlope_; } +// We declare the private variables of the problem. private: Scalar gravity_; Scalar bedSlope_; std::string frictionLawType_; std::unique_ptr> frictionLaw_; -}; -// end of namespace Dumux. -} - +}; // end class definition of RoughChannelSpatialParams +} // end of namespace Dumux. +// [[/codeblock]] +// [[/content]] #endif diff --git a/test/references/example_shallowwaterfriction-reference.vtu b/test/references/example_shallowwaterfriction-reference.vtu index 1606356123..8303c07ab3 100644 --- a/test/references/example_shallowwaterfriction-reference.vtu +++ b/test/references/example_shallowwaterfriction-reference.vtu @@ -426,215 +426,215 @@ 1.1501 1.14964 1.14894 1.14788 - -2.38291e-16 2.35473e-17 -3.16973e-17 1.99134e-16 -4.20757e-16 2.80256e-17 2.62202e-17 -7.4529e-17 3.38053e-16 3.09022e-16 -1.8063e-17 3.37965e-16 - -1.83492e-16 -3.11575e-16 -2.36764e-16 1.92653e-16 1.2055e-16 1.11044e-16 -1.28378e-16 -7.48221e-17 1.50381e-16 -1.6962e-16 8.40331e-17 2.07255e-16 - 1.3602e-16 7.04744e-17 1.29869e-16 -1.75806e-16 -9.90514e-17 6.90237e-17 2.40888e-16 2.53866e-16 -4.38853e-17 3.486e-17 8.80998e-17 -1.03105e-16 - -3.45051e-16 -1.48763e-17 -3.39481e-17 2.48967e-17 -2.38087e-16 -4.2009e-16 1.54106e-17 1.39631e-16 1.0035e-16 4.95547e-16 5.23122e-16 1.79671e-16 - 5.87306e-16 9.4771e-16 1.56791e-15 2.26488e-15 4.21647e-15 6.46285e-15 9.40868e-15 1.44873e-14 2.20202e-14 3.38868e-14 5.17514e-14 7.90881e-14 - 1.21506e-13 1.8643e-13 2.86106e-13 4.39301e-13 6.74126e-13 1.03446e-12 1.58763e-12 2.437e-12 3.74236e-12 5.74573e-12 8.82192e-12 1.3545e-11 - 2.07984e-11 3.19361e-11 4.90399e-11 7.53065e-11 1.15646e-10 1.776e-10 2.72755e-10 4.18908e-10 6.43399e-10 9.88231e-10 1.51794e-09 2.33167e-09 - 3.58176e-09 5.5023e-09 8.453e-09 1.29866e-08 1.99526e-08 3.06565e-08 4.71049e-08 7.23817e-08 1.11227e-07 1.70929e-07 2.62688e-07 4.03727e-07 - 6.2052e-07 9.53777e-07 1.46609e-06 2.2537e-06 8.95533e-06 1.14973e-05 1.24345e-05 1.27318e-05 1.27703e-05 1.27039e-05 1.25955e-05 1.24707e-05 - 1.23402e-05 1.22083e-05 1.20767e-05 1.19461e-05 1.18169e-05 1.16892e-05 1.1563e-05 1.14382e-05 1.1315e-05 1.11931e-05 1.10728e-05 1.09539e-05 - 1.08363e-05 1.07202e-05 1.06055e-05 1.04921e-05 1.038e-05 1.02693e-05 1.01598e-05 1.00517e-05 9.94484e-06 9.83923e-06 9.73487e-06 9.63172e-06 - 9.52979e-06 9.42905e-06 9.32949e-06 9.2311e-06 9.13385e-06 9.03774e-06 8.94275e-06 8.84887e-06 8.75607e-06 8.66436e-06 8.57371e-06 8.48411e-06 - 8.39555e-06 8.30802e-06 8.2215e-06 8.13597e-06 8.05144e-06 7.96788e-06 7.88528e-06 7.80363e-06 7.72292e-06 7.64314e-06 7.56427e-06 7.48631e-06 - 7.40924e-06 7.33305e-06 7.25773e-06 7.18327e-06 7.10966e-06 7.03688e-06 6.96494e-06 6.89381e-06 6.82349e-06 6.75397e-06 6.68523e-06 6.61727e-06 - 6.55008e-06 6.48365e-06 6.41797e-06 6.35303e-06 6.28882e-06 6.22533e-06 6.16255e-06 6.10048e-06 6.0391e-06 5.97841e-06 5.9184e-06 5.85906e-06 - 5.80038e-06 5.74235e-06 5.68497e-06 5.62823e-06 5.57212e-06 5.51663e-06 5.46176e-06 5.40749e-06 5.35383e-06 5.30075e-06 5.24826e-06 5.19635e-06 - 5.14502e-06 5.09424e-06 5.04403e-06 4.99436e-06 4.94524e-06 4.89666e-06 4.8486e-06 4.80108e-06 4.75407e-06 4.70757e-06 4.66158e-06 4.61609e-06 - 4.57109e-06 4.52658e-06 4.48256e-06 4.439e-06 4.39593e-06 4.35331e-06 4.31116e-06 4.26946e-06 4.2282e-06 4.1874e-06 4.14703e-06 4.10709e-06 - 4.06758e-06 4.02849e-06 3.98982e-06 3.95157e-06 3.91372e-06 3.87627e-06 3.83923e-06 3.80258e-06 3.76631e-06 3.73043e-06 3.69493e-06 3.65981e-06 - 3.62506e-06 3.59067e-06 3.55665e-06 3.52299e-06 3.48968e-06 3.45672e-06 3.4241e-06 3.39183e-06 3.3599e-06 3.3283e-06 3.29703e-06 3.26608e-06 - 3.23546e-06 3.20516e-06 3.17518e-06 3.1455e-06 3.11614e-06 3.08708e-06 3.05832e-06 3.02985e-06 3.00168e-06 2.97381e-06 2.94622e-06 2.91891e-06 - 2.89189e-06 2.86514e-06 2.83867e-06 2.81247e-06 2.78654e-06 2.76087e-06 2.73547e-06 2.71033e-06 2.68544e-06 2.66081e-06 2.63643e-06 2.61229e-06 - 2.58841e-06 2.56476e-06 2.54135e-06 2.51819e-06 2.49525e-06 2.47255e-06 2.45008e-06 2.42783e-06 2.40581e-06 2.38401e-06 2.36243e-06 2.34106e-06 - 2.31991e-06 2.29898e-06 2.27825e-06 2.25773e-06 2.23742e-06 2.2173e-06 2.19739e-06 2.17768e-06 2.15816e-06 2.13884e-06 2.11971e-06 2.10077e-06 - 2.08202e-06 2.06345e-06 2.04507e-06 2.02686e-06 2.00884e-06 1.991e-06 1.97333e-06 1.95583e-06 1.93851e-06 1.92136e-06 1.90437e-06 1.88755e-06 - 1.8709e-06 1.85441e-06 1.83808e-06 1.82191e-06 1.80589e-06 1.79003e-06 1.77433e-06 1.75878e-06 1.74338e-06 1.72812e-06 1.71302e-06 1.69806e-06 - 1.68325e-06 1.66857e-06 1.65404e-06 1.63965e-06 1.6254e-06 1.61128e-06 1.5973e-06 1.58345e-06 1.56973e-06 1.55614e-06 1.54269e-06 1.52936e-06 - 1.51616e-06 1.50308e-06 1.49012e-06 1.47729e-06 1.46458e-06 1.45199e-06 1.43952e-06 1.42716e-06 1.41492e-06 1.40279e-06 1.39078e-06 1.37888e-06 - 1.36709e-06 1.35541e-06 1.34383e-06 1.33237e-06 1.32101e-06 1.30975e-06 1.2986e-06 1.28755e-06 1.2766e-06 1.26575e-06 1.255e-06 1.24435e-06 - 1.2338e-06 1.22334e-06 1.21298e-06 1.20271e-06 1.19253e-06 1.18244e-06 1.17245e-06 1.16254e-06 1.15272e-06 1.14299e-06 1.13335e-06 1.12379e-06 - 1.11431e-06 1.10492e-06 1.09562e-06 1.08639e-06 1.07724e-06 1.06818e-06 1.05919e-06 1.05028e-06 1.04145e-06 1.0327e-06 1.02402e-06 1.01541e-06 - 1.00688e-06 9.98425e-07 9.90039e-07 9.81724e-07 9.73479e-07 9.65305e-07 9.57199e-07 9.49161e-07 9.4119e-07 9.33285e-07 9.25447e-07 9.17673e-07 - 9.09964e-07 9.02318e-07 8.94734e-07 8.87213e-07 8.79753e-07 8.72353e-07 8.65014e-07 8.57733e-07 8.50511e-07 8.43347e-07 8.3624e-07 8.2919e-07 - 8.22195e-07 8.15255e-07 8.0837e-07 8.01539e-07 7.94761e-07 7.88036e-07 7.81363e-07 7.74741e-07 7.6817e-07 7.61649e-07 7.55178e-07 7.48756e-07 - 7.42382e-07 7.36056e-07 7.29778e-07 7.23546e-07 7.17361e-07 7.11221e-07 7.05126e-07 6.99076e-07 6.9307e-07 6.87108e-07 6.81189e-07 6.75312e-07 - 6.69477e-07 6.63684e-07 6.57932e-07 6.5222e-07 6.46549e-07 6.40917e-07 6.35324e-07 6.2977e-07 6.24255e-07 6.18777e-07 6.13336e-07 6.07933e-07 - 6.02565e-07 5.97234e-07 5.91939e-07 5.86679e-07 5.81454e-07 5.76263e-07 5.71106e-07 5.65983e-07 5.60893e-07 5.55836e-07 5.50812e-07 5.45819e-07 - 5.40858e-07 5.35929e-07 5.3103e-07 5.26162e-07 5.21324e-07 5.16515e-07 5.11734e-07 5.06982e-07 5.02256e-07 4.97555e-07 4.92877e-07 4.8822e-07 - 4.83579e-07 4.7895e-07 4.74324e-07 4.69689e-07 4.65029e-07 4.6032e-07 4.55525e-07 4.50592e-07 4.45442e-07 4.39963e-07 4.33984e-07 4.27257e-07 - 4.19413e-07 4.099e-07 3.97897e-07 3.82162e-07 3.60809e-07 3.30922e-07 2.87927e-07 2.24481e-07 1.28472e-07 -2.06911e-08 -2.592e-07 -6.42549e-07 - -1.22958e-06 -2.08322e-06 -3.31172e-06 -5.07651e-06 -7.61214e-06 -1.12572e-05 -1.65001e-05 -2.40445e-05 -3.49049e-05 -5.05442e-05 -7.30717e-05 -0.00010553 - -0.00015231 -0.000219745 -0.000316978 -0.000457204 -0.000659466 -0.000951239 -0.00137214 -0.00197924 3.10951e-16 -1.70797e-16 -4.79546e-17 -1.89656e-16 - -1.03959e-16 -4.39736e-17 5.0084e-17 1.37004e-17 1.38963e-16 2.36263e-16 -4.00373e-16 1.09326e-16 -4.24871e-17 1.72725e-16 -5.00329e-16 -3.54806e-16 - 2.36801e-17 2.25226e-16 -2.09413e-16 -4.16962e-16 -4.364e-16 -2.52914e-16 -3.99816e-16 1.94499e-16 -1.49064e-16 2.03925e-16 -1.14494e-16 -1.65575e-16 - -9.84151e-17 -1.69559e-16 -1.73048e-16 3.45214e-19 -2.09769e-16 2.46203e-16 1.48909e-16 -2.38171e-16 -9.28863e-17 -1.1426e-16 1.46575e-16 5.92439e-17 - 1.13785e-16 1.62163e-16 4.51641e-16 1.54598e-16 3.52772e-16 4.57638e-16 7.3225e-17 4.58909e-16 1.02146e-15 1.291e-15 2.37515e-15 3.35379e-15 - 6.11332e-15 9.55661e-15 1.43805e-14 2.18051e-14 3.2809e-14 5.04613e-14 7.71293e-14 1.18175e-13 1.80706e-13 2.77876e-13 4.25506e-13 6.52472e-13 - 9.98886e-13 1.5304e-12 2.3456e-12 3.59296e-12 5.50488e-12 8.4337e-12 1.29206e-11 1.97947e-11 3.03255e-11 4.64572e-11 7.11696e-11 1.09025e-10 - 1.67014e-10 2.5584e-10 3.91901e-10 6.00311e-10 9.19532e-10 1.40848e-09 2.15736e-09 3.30436e-09 5.06107e-09 7.75154e-09 1.1872e-08 1.81823e-08 - 2.78461e-08 4.26451e-08 6.53075e-08 1.00011e-07 1.5315e-07 2.34519e-07 3.59108e-07 5.49871e-07 8.41946e-07 1.28912e-06 1.97375e-06 3.02187e-06 - 6.59015e-06 8.18959e-06 8.80927e-06 8.99479e-06 8.99665e-06 8.92285e-06 8.81874e-06 8.70315e-06 8.58386e-06 8.46405e-06 8.34504e-06 8.22733e-06 - 8.11114e-06 7.99654e-06 7.88353e-06 7.77211e-06 7.66226e-06 7.55397e-06 7.4472e-06 7.34196e-06 7.2382e-06 7.13591e-06 7.03507e-06 6.93565e-06 - 6.83765e-06 6.74103e-06 6.64578e-06 6.55188e-06 6.45931e-06 6.36805e-06 6.27808e-06 6.18938e-06 6.10195e-06 6.01574e-06 5.93076e-06 5.84698e-06 - 5.76439e-06 5.68297e-06 5.6027e-06 5.52356e-06 5.44555e-06 5.36864e-06 5.29281e-06 5.21806e-06 5.14437e-06 5.07172e-06 5.0001e-06 4.92949e-06 - 4.85989e-06 4.79126e-06 4.72361e-06 4.65691e-06 4.59116e-06 4.52634e-06 4.46243e-06 4.39943e-06 4.33732e-06 4.27609e-06 4.21572e-06 4.15621e-06 - 4.09754e-06 4.0397e-06 3.98268e-06 3.92646e-06 3.87104e-06 3.8164e-06 3.76253e-06 3.70943e-06 3.65707e-06 3.60546e-06 3.55457e-06 3.5044e-06 - 3.45495e-06 3.40619e-06 3.35812e-06 3.31072e-06 3.264e-06 3.21794e-06 3.17253e-06 3.12776e-06 3.08362e-06 3.04011e-06 2.99721e-06 2.95491e-06 - 2.91321e-06 2.8721e-06 2.83157e-06 2.79162e-06 2.75222e-06 2.71339e-06 2.6751e-06 2.63735e-06 2.60013e-06 2.56344e-06 2.52726e-06 2.4916e-06 - 2.45644e-06 2.42177e-06 2.38759e-06 2.3539e-06 2.32068e-06 2.28793e-06 2.25563e-06 2.2238e-06 2.19241e-06 2.16147e-06 2.13096e-06 2.10088e-06 - 2.07123e-06 2.04199e-06 2.01316e-06 1.98474e-06 1.95672e-06 1.9291e-06 1.90186e-06 1.87501e-06 1.84854e-06 1.82243e-06 1.7967e-06 1.77133e-06 - 1.74631e-06 1.72165e-06 1.69734e-06 1.67336e-06 1.64973e-06 1.62643e-06 1.60345e-06 1.5808e-06 1.55847e-06 1.53645e-06 1.51474e-06 1.49334e-06 - 1.47223e-06 1.45143e-06 1.43092e-06 1.41069e-06 1.39076e-06 1.3711e-06 1.35172e-06 1.33261e-06 1.31377e-06 1.29519e-06 1.27688e-06 1.25883e-06 - 1.24103e-06 1.22348e-06 1.20617e-06 1.18912e-06 1.1723e-06 1.15572e-06 1.13937e-06 1.12325e-06 1.10736e-06 1.09169e-06 1.07625e-06 1.06102e-06 - 1.04601e-06 1.0312e-06 1.01661e-06 1.00222e-06 9.88041e-07 9.74057e-07 9.60271e-07 9.46679e-07 9.33279e-07 9.20068e-07 9.07044e-07 8.94204e-07 - 8.81546e-07 8.69066e-07 8.56763e-07 8.44634e-07 8.32676e-07 8.20887e-07 8.09265e-07 7.97808e-07 7.86513e-07 7.75377e-07 7.64399e-07 7.53577e-07 - 7.42908e-07 7.32391e-07 7.22022e-07 7.118e-07 7.01723e-07 6.91789e-07 6.81996e-07 6.72342e-07 6.62825e-07 6.53443e-07 6.44194e-07 6.35076e-07 - 6.26088e-07 6.17227e-07 6.08493e-07 5.99882e-07 5.91393e-07 5.83026e-07 5.74777e-07 5.66645e-07 5.58629e-07 5.50726e-07 5.42936e-07 5.35257e-07 - 5.27687e-07 5.20224e-07 5.12867e-07 5.05615e-07 4.98466e-07 4.91419e-07 4.84471e-07 4.77622e-07 4.70871e-07 4.64215e-07 4.57653e-07 4.51185e-07 - 4.44808e-07 4.38522e-07 4.32325e-07 4.26216e-07 4.20193e-07 4.14255e-07 4.08401e-07 4.0263e-07 3.9694e-07 3.91331e-07 3.858e-07 3.80348e-07 - 3.74972e-07 3.69672e-07 3.64447e-07 3.59294e-07 3.54214e-07 3.49205e-07 3.44266e-07 3.39397e-07 3.34595e-07 3.29859e-07 3.2519e-07 3.20586e-07 - 3.16045e-07 3.11567e-07 3.07151e-07 3.02796e-07 2.98501e-07 2.94265e-07 2.90087e-07 2.85966e-07 2.81901e-07 2.77892e-07 2.73937e-07 2.70035e-07 - 2.66187e-07 2.6239e-07 2.58644e-07 2.54948e-07 2.51301e-07 2.47703e-07 2.44153e-07 2.4065e-07 2.37192e-07 2.33781e-07 2.30413e-07 2.2709e-07 - 2.2381e-07 2.20572e-07 2.17375e-07 2.1422e-07 2.11105e-07 2.08029e-07 2.04992e-07 2.01993e-07 1.99032e-07 1.96108e-07 1.93219e-07 1.90367e-07 - 1.87549e-07 1.84765e-07 1.82015e-07 1.79298e-07 1.76614e-07 1.73961e-07 1.7134e-07 1.68749e-07 1.66189e-07 1.63658e-07 1.61156e-07 1.58683e-07 - 1.56237e-07 1.53819e-07 1.51428e-07 1.49063e-07 1.46725e-07 1.44411e-07 1.42123e-07 1.39859e-07 1.37619e-07 1.35402e-07 1.33209e-07 1.31038e-07 - 1.28889e-07 1.26762e-07 1.24657e-07 1.22572e-07 1.20508e-07 1.18464e-07 1.16439e-07 1.14434e-07 1.12448e-07 1.1048e-07 1.08531e-07 1.06599e-07 - 1.04685e-07 1.02788e-07 1.00908e-07 9.90438e-08 9.71961e-08 9.53642e-08 9.35478e-08 9.17466e-08 8.99602e-08 8.81885e-08 8.6431e-08 8.46876e-08 - 8.29579e-08 8.12417e-08 7.95386e-08 7.78486e-08 7.61712e-08 7.45063e-08 7.28536e-08 7.12129e-08 6.9584e-08 6.79665e-08 6.63604e-08 6.47655e-08 - 6.31814e-08 6.16079e-08 6.0045e-08 5.84924e-08 5.69499e-08 5.54174e-08 5.38945e-08 5.23812e-08 5.08772e-08 4.93823e-08 4.78963e-08 4.64188e-08 - 4.49497e-08 4.34883e-08 4.20343e-08 4.05868e-08 3.91448e-08 3.77069e-08 3.62711e-08 3.48343e-08 3.33922e-08 3.19386e-08 3.04644e-08 2.89562e-08 - 2.73944e-08 2.57503e-08 2.39816e-08 2.20267e-08 1.97948e-08 1.71529e-08 1.39058e-08 9.76748e-09 4.31913e-09 -3.05211e-09 -1.32412e-08 -2.7552e-08 - -4.78773e-08 -7.69503e-08 -1.18687e-07 -1.78629e-07 -2.64476e-07 -3.86599e-07 -5.58248e-07 -7.97726e-07 -1.13709e-06 -1.62594e-06 -2.32736e-06 -3.33132e-06 - -4.76671e-06 -6.81766e-06 -9.74666e-06 -1.39274e-05 -1.98914e-05 -2.83939e-05 -4.05062e-05 -5.7747e-05 -8.22652e-05 -0.000117096 -0.00016652 -0.000236558 - -0.000335656 -0.000475626 -0.000672922 -0.00095036 -2.19694e-16 3.86909e-17 1.09578e-16 -2.05867e-16 2.50608e-17 -6.50794e-17 2.07241e-18 2.59401e-16 - -4.11266e-17 1.75883e-16 1.66222e-16 -1.09627e-16 -2.61128e-16 -1.72521e-17 1.64285e-16 -6.4859e-17 -2.26618e-16 -3.93829e-16 -2.78893e-16 -4.73104e-16 - -3.69193e-16 -1.68198e-16 3.21124e-16 -2.82107e-16 -2.28457e-17 2.55195e-16 2.97241e-16 3.2495e-16 1.54589e-16 7.47151e-17 -6.52662e-17 -1.04436e-16 - 9.42487e-17 -3.31633e-16 -2.67403e-16 -1.65749e-16 -7.96601e-17 1.95027e-17 1.87389e-16 -2.83328e-16 2.25354e-16 -2.22383e-16 3.09415e-17 1.1253e-16 - 1.82988e-16 1.07451e-16 -5.06021e-16 -5.33655e-16 -3.91887e-16 -2.27402e-16 1.21983e-16 8.52888e-17 1.91884e-16 3.98569e-16 5.33555e-16 2.01778e-16 - 2.8992e-16 4.72171e-16 -1.42782e-17 -2.13778e-16 6.44839e-16 -1.39214e-16 -1.45916e-16 9.92374e-17 -1.46056e-16 3.16183e-16 1.87558e-16 -2.83537e-17 - -2.9827e-17 1.27194e-17 -2.85477e-17 1.58682e-17 -4.1214e-17 2.4715e-16 1.69541e-17 1.34752e-16 3.52652e-16 1.4648e-16 1.67966e-16 -2.41997e-17 - -2.10427e-16 1.22674e-17 1.48381e-16 9.95556e-17 2.53359e-16 -3.18081e-16 -1.30471e-16 5.94988e-16 2.4628e-16 6.20319e-17 -1.01921e-16 -1.61089e-16 - -3.88283e-16 -1.12591e-16 -2.40235e-16 2.82216e-16 7.01392e-17 -3.83397e-16 6.71337e-17 3.62957e-16 2.79849e-16 3.53776e-16 7.31312e-16 5.7576e-16 - 3.12338e-16 3.31406e-16 2.74913e-16 -2.66412e-16 1.63918e-16 -2.05548e-16 -3.82497e-16 -2.03756e-16 -6.03083e-16 -1.09161e-15 -7.14643e-16 -3.67226e-16 - -4.82138e-16 -9.77665e-17 -3.30037e-17 1.80267e-17 1.31837e-16 4.50797e-16 7.50872e-17 -2.53594e-17 -3.2439e-16 -3.88714e-16 -3.9151e-16 -4.86972e-16 - -2.055e-16 -6.10113e-16 -7.85354e-16 -7.82038e-16 -1.02402e-15 -8.44764e-16 -8.32912e-16 -8.97064e-16 -7.42603e-16 -1.09048e-15 -9.13554e-16 -8.45676e-16 - -8.87517e-16 -6.40372e-16 -8.98237e-16 -1.21611e-15 -1.12416e-15 -8.29959e-16 -1.05283e-15 -1.15504e-15 -1.31625e-15 -1.22072e-15 -1.04189e-15 -1.21324e-15 - -9.25363e-16 -1.17778e-15 -1.38027e-15 -1.14113e-15 -1.2878e-15 -1.55253e-15 -1.19809e-15 -9.55643e-16 -7.65923e-16 -3.97323e-16 -2.03507e-16 -6.64792e-16 - -4.90466e-16 -7.51288e-16 -6.99339e-16 -6.52694e-16 -6.95253e-16 -7.63571e-16 -5.54359e-16 -3.24806e-16 -5.07934e-16 -2.59589e-16 -1.99932e-16 1.52936e-16 - 3.48032e-17 -1.09753e-16 -2.33193e-16 -4.3029e-16 -3.30376e-16 -2.73637e-16 -4.55501e-16 -2.23809e-16 -3.15503e-16 -4.4991e-16 1.42869e-16 1.78676e-16 - 9.63661e-17 3.61332e-16 7.6166e-16 9.66791e-16 1.02348e-15 1.27368e-15 1.16234e-15 1.31838e-15 1.10448e-15 1.59647e-15 1.3863e-15 1.23954e-15 - 1.39524e-15 1.60265e-15 1.62684e-15 2.17478e-15 2.3239e-15 2.53981e-15 2.45398e-15 2.53796e-15 2.24887e-15 2.21669e-15 1.61455e-15 1.07415e-15 - 9.54537e-16 5.37375e-16 8.66757e-16 4.62673e-16 5.13631e-16 7.01945e-16 6.90065e-16 9.72506e-16 1.0109e-15 8.48123e-16 6.54361e-16 5.90329e-16 - 9.48327e-16 1.03405e-15 1.0658e-15 1.41882e-15 1.35495e-15 1.04677e-15 1.23773e-15 1.33108e-15 1.62189e-15 1.57239e-15 1.40478e-15 1.34799e-15 - 1.1496e-15 1.05542e-15 7.6859e-16 1.37314e-15 1.15017e-15 4.55634e-16 3.2022e-16 5.79103e-16 8.74618e-16 1.28332e-15 1.31547e-15 1.49742e-15 - 1.47655e-15 1.50606e-15 1.54038e-15 1.45013e-15 1.32698e-15 1.32465e-15 1.73171e-15 1.15079e-15 9.8934e-16 1.01575e-15 8.72447e-16 7.86423e-16 - 8.65487e-16 8.96516e-16 1.23869e-15 9.36726e-16 7.39235e-16 3.28067e-16 3.43376e-16 1.79929e-16 7.62814e-16 1.01351e-15 7.18437e-16 4.72567e-16 - 5.60706e-17 5.81716e-16 3.00721e-16 4.43416e-16 6.15843e-17 1.70341e-16 3.72441e-16 1.56607e-16 5.09307e-17 -1.13893e-17 -7.85751e-17 -7.92788e-17 - -5.59556e-16 -4.05831e-16 -5.54596e-16 -7.33976e-16 -7.67805e-16 -1.00618e-15 -1.08462e-15 -1.13165e-15 -1.20145e-15 -1.36061e-15 -9.7158e-16 -1.14396e-15 - -1.15994e-15 -1.03665e-15 -1.10956e-15 -1.00924e-15 -1.02921e-15 -1.08943e-15 -7.23434e-16 -8.56115e-16 -6.41986e-16 -7.32498e-16 -8.94385e-16 -9.97328e-16 - -2.82671e-16 -4.84002e-16 -6.13948e-16 -7.06266e-16 -3.56479e-16 -2.56947e-16 -2.99782e-16 -1.71749e-16 -3.99395e-16 -2.77708e-16 -1.20261e-16 4.17749e-17 - 7.16057e-17 3.1446e-16 4.03019e-16 6.14277e-16 6.94779e-16 7.30146e-16 7.23597e-16 8.2807e-16 5.75944e-16 6.78354e-16 3.3858e-16 4.21255e-16 - 4.89225e-16 8.09961e-16 4.79576e-16 8.40405e-16 9.61994e-16 9.58246e-16 1.89406e-16 3.27253e-16 2.04852e-16 -6.73822e-17 -1.33297e-16 -1.59778e-17 - 2.04091e-16 -2.66752e-16 -2.20621e-16 -4.83282e-16 -7.52526e-16 -6.95154e-16 -9.61431e-16 -8.97495e-16 -9.74038e-16 -9.41462e-16 -1.1333e-15 -1.19868e-15 - -1.22036e-15 -1.35547e-15 -1.74647e-15 -2.00061e-15 -1.56418e-15 -1.34555e-15 -1.38055e-15 -1.24667e-15 -1.21661e-15 -1.25254e-15 -1.14087e-15 -1.00315e-15 - -1.37858e-15 -1.14179e-15 -1.47341e-15 -1.40923e-15 -1.23549e-15 -1.01778e-15 -1.22322e-15 -1.28567e-15 -1.17102e-15 -1.01551e-15 -1.04247e-15 -6.43757e-16 - -7.18422e-16 -8.47634e-16 -5.40404e-16 -6.96456e-16 -7.86699e-16 -1.21669e-15 -1.12805e-15 -1.17632e-15 -1.00272e-15 -1.4382e-15 -1.22238e-15 -1.46116e-15 - -1.63702e-15 -1.51829e-15 -2.02377e-15 -1.71551e-15 -1.74589e-15 -1.71219e-15 -1.78226e-15 -1.73654e-15 -1.72469e-15 -2.05873e-15 -1.66303e-15 -1.37134e-15 - -1.14185e-15 -1.15976e-15 -1.07053e-15 -6.52319e-16 -7.9921e-16 -8.30558e-16 -5.9347e-16 -9.35762e-16 -8.38975e-16 -1.03745e-15 -1.08841e-15 -7.60832e-16 - -1.07476e-15 -7.98674e-16 -3.66739e-16 -8.76446e-16 -1.17476e-15 -1.24479e-15 -1.19475e-15 -1.62584e-15 -1.51902e-15 -1.49766e-15 -1.13752e-15 -1.28088e-15 - -1.20536e-15 -1.09712e-15 -7.75316e-16 -9.94374e-16 -1.18194e-15 -1.42786e-15 -1.22292e-15 -1.42305e-15 -1.3771e-15 -1.33932e-15 -1.61175e-15 -1.79942e-15 - -1.94584e-15 -1.98296e-15 -1.65731e-15 -1.57007e-15 -9.08126e-16 -8.99166e-16 -4.95945e-16 -5.33016e-16 -8.30059e-16 -5.52503e-16 -4.53194e-16 -2.36527e-16 - -5.30202e-16 -4.44022e-16 -5.37977e-16 -2.13846e-17 -6.34985e-17 -4.1142e-16 -1.85389e-16 -3.47663e-16 -5.81331e-16 -1.54546e-16 2.24887e-16 -5.55836e-17 - -2.35454e-16 -1.93941e-16 -4.32116e-16 -6.56922e-17 -1.97136e-16 1.07431e-16 5.45571e-17 -2.03915e-16 3.51442e-16 -3.66596e-16 8.56857e-16 8.11798e-17 - 5.84008e-16 7.50147e-16 9.94328e-16 7.00556e-16 7.42742e-16 3.93483e-16 9.95524e-16 1.20607e-15 1.29887e-15 1.32198e-15 1.17831e-15 8.38885e-16 - 8.21324e-16 6.72759e-16 1.51468e-16 -4.67085e-16 9.87086e-17 1.53763e-16 -3.08071e-16 -4.06528e-16 4.12554e-17 1.31941e-16 1.5322e-16 4.32892e-16 - 3.0913e-16 3.49924e-17 -6.3924e-17 -1.65891e-16 -2.54014e-16 2.86651e-16 4.64545e-16 2.91134e-16 2.1025e-16 1.4506e-16 2.85935e-16 -1.18759e-16 - -1.53135e-16 1.60785e-16 -1.98949e-16 -3.80812e-16 -1.20194e-16 -4.95205e-17 -2.32781e-16 -1.83916e-16 1.66361e-16 -7.57197e-17 -2.47954e-16 4.05352e-16 - 3.46147e-17 1.8961e-16 3.19686e-16 4.61806e-17 -2.47224e-16 1.40979e-16 2.94836e-16 1.78314e-17 1.02376e-16 3.17303e-16 9.1979e-17 6.36401e-16 - -1.48309e-16 -3.23264e-16 -4.23149e-16 -1.90101e-16 -1.52307e-16 -5.38407e-16 -8.47793e-17 -3.5321e-17 1.71904e-16 -8.37472e-17 -7.73778e-16 -1.40647e-15 - -1.26912e-15 -2.02381e-15 -2.38166e-15 -3.77603e-15 -6.05412e-15 -9.19616e-15 -1.38153e-14 -2.15669e-14 -3.23865e-14 -5.01903e-14 -7.69126e-14 -1.17868e-13 - -1.81084e-13 -2.77766e-13 -4.25744e-13 -6.52044e-13 -9.98762e-13 -1.53051e-12 -2.34532e-12 -3.59331e-12 -5.50524e-12 -8.43369e-12 -1.29212e-11 -1.97953e-11 - -3.03258e-11 -4.64572e-11 -7.11695e-11 -1.09025e-10 -1.67014e-10 -2.5584e-10 -3.919e-10 -6.0031e-10 -9.19532e-10 -1.40848e-09 -2.15736e-09 -3.30436e-09 - -5.06107e-09 -7.75154e-09 -1.1872e-08 -1.81823e-08 -2.78461e-08 -4.26451e-08 -6.53075e-08 -1.00011e-07 -1.5315e-07 -2.34519e-07 -3.59108e-07 -5.49871e-07 - -8.41946e-07 -1.28912e-06 -1.97375e-06 -3.02187e-06 -6.59015e-06 -8.18959e-06 -8.80927e-06 -8.99479e-06 -8.99665e-06 -8.92285e-06 -8.81874e-06 -8.70315e-06 - -8.58386e-06 -8.46405e-06 -8.34504e-06 -8.22733e-06 -8.11114e-06 -7.99654e-06 -7.88353e-06 -7.77211e-06 -7.66226e-06 -7.55397e-06 -7.4472e-06 -7.34196e-06 - -7.2382e-06 -7.13591e-06 -7.03507e-06 -6.93565e-06 -6.83765e-06 -6.74103e-06 -6.64578e-06 -6.55188e-06 -6.45931e-06 -6.36805e-06 -6.27808e-06 -6.18938e-06 - -6.10195e-06 -6.01574e-06 -5.93076e-06 -5.84698e-06 -5.76439e-06 -5.68297e-06 -5.6027e-06 -5.52356e-06 -5.44555e-06 -5.36864e-06 -5.29281e-06 -5.21806e-06 - -5.14437e-06 -5.07172e-06 -5.0001e-06 -4.92949e-06 -4.85989e-06 -4.79126e-06 -4.72361e-06 -4.65691e-06 -4.59116e-06 -4.52634e-06 -4.46243e-06 -4.39943e-06 - -4.33732e-06 -4.27609e-06 -4.21572e-06 -4.15621e-06 -4.09754e-06 -4.0397e-06 -3.98268e-06 -3.92646e-06 -3.87104e-06 -3.8164e-06 -3.76253e-06 -3.70943e-06 - -3.65707e-06 -3.60546e-06 -3.55457e-06 -3.5044e-06 -3.45495e-06 -3.40619e-06 -3.35812e-06 -3.31072e-06 -3.264e-06 -3.21794e-06 -3.17253e-06 -3.12776e-06 - -3.08362e-06 -3.04011e-06 -2.99721e-06 -2.95491e-06 -2.91321e-06 -2.8721e-06 -2.83157e-06 -2.79162e-06 -2.75222e-06 -2.71339e-06 -2.6751e-06 -2.63735e-06 - -2.60013e-06 -2.56344e-06 -2.52726e-06 -2.4916e-06 -2.45644e-06 -2.42177e-06 -2.38759e-06 -2.3539e-06 -2.32068e-06 -2.28793e-06 -2.25563e-06 -2.2238e-06 - -2.19241e-06 -2.16147e-06 -2.13096e-06 -2.10088e-06 -2.07123e-06 -2.04199e-06 -2.01316e-06 -1.98474e-06 -1.95672e-06 -1.9291e-06 -1.90186e-06 -1.87501e-06 - -1.84854e-06 -1.82243e-06 -1.7967e-06 -1.77133e-06 -1.74631e-06 -1.72165e-06 -1.69734e-06 -1.67336e-06 -1.64973e-06 -1.62643e-06 -1.60345e-06 -1.5808e-06 - -1.55847e-06 -1.53645e-06 -1.51474e-06 -1.49334e-06 -1.47223e-06 -1.45143e-06 -1.43092e-06 -1.41069e-06 -1.39076e-06 -1.3711e-06 -1.35172e-06 -1.33261e-06 - -1.31377e-06 -1.29519e-06 -1.27688e-06 -1.25883e-06 -1.24103e-06 -1.22348e-06 -1.20617e-06 -1.18912e-06 -1.1723e-06 -1.15572e-06 -1.13937e-06 -1.12325e-06 - -1.10736e-06 -1.09169e-06 -1.07625e-06 -1.06102e-06 -1.04601e-06 -1.0312e-06 -1.01661e-06 -1.00222e-06 -9.88041e-07 -9.74057e-07 -9.60271e-07 -9.46679e-07 - -9.33279e-07 -9.20068e-07 -9.07044e-07 -8.94204e-07 -8.81546e-07 -8.69066e-07 -8.56763e-07 -8.44634e-07 -8.32676e-07 -8.20887e-07 -8.09265e-07 -7.97808e-07 - -7.86513e-07 -7.75377e-07 -7.64399e-07 -7.53577e-07 -7.42908e-07 -7.32391e-07 -7.22022e-07 -7.118e-07 -7.01723e-07 -6.91789e-07 -6.81996e-07 -6.72342e-07 - -6.62825e-07 -6.53443e-07 -6.44194e-07 -6.35076e-07 -6.26088e-07 -6.17227e-07 -6.08493e-07 -5.99882e-07 -5.91393e-07 -5.83026e-07 -5.74777e-07 -5.66645e-07 - -5.58629e-07 -5.50726e-07 -5.42936e-07 -5.35257e-07 -5.27687e-07 -5.20224e-07 -5.12867e-07 -5.05615e-07 -4.98466e-07 -4.91419e-07 -4.84471e-07 -4.77622e-07 - -4.70871e-07 -4.64215e-07 -4.57653e-07 -4.51185e-07 -4.44808e-07 -4.38522e-07 -4.32325e-07 -4.26216e-07 -4.20193e-07 -4.14255e-07 -4.08401e-07 -4.0263e-07 - -3.9694e-07 -3.91331e-07 -3.858e-07 -3.80348e-07 -3.74972e-07 -3.69672e-07 -3.64447e-07 -3.59294e-07 -3.54214e-07 -3.49205e-07 -3.44266e-07 -3.39397e-07 - -3.34595e-07 -3.29859e-07 -3.2519e-07 -3.20586e-07 -3.16045e-07 -3.11567e-07 -3.07151e-07 -3.02796e-07 -2.98501e-07 -2.94265e-07 -2.90087e-07 -2.85966e-07 - -2.81901e-07 -2.77892e-07 -2.73937e-07 -2.70035e-07 -2.66187e-07 -2.6239e-07 -2.58644e-07 -2.54948e-07 -2.51301e-07 -2.47703e-07 -2.44153e-07 -2.4065e-07 - -2.37192e-07 -2.33781e-07 -2.30413e-07 -2.2709e-07 -2.2381e-07 -2.20572e-07 -2.17375e-07 -2.1422e-07 -2.11105e-07 -2.08029e-07 -2.04992e-07 -2.01993e-07 - -1.99032e-07 -1.96108e-07 -1.93219e-07 -1.90367e-07 -1.87549e-07 -1.84765e-07 -1.82015e-07 -1.79298e-07 -1.76614e-07 -1.73961e-07 -1.7134e-07 -1.68749e-07 - -1.66189e-07 -1.63658e-07 -1.61156e-07 -1.58683e-07 -1.56237e-07 -1.53819e-07 -1.51428e-07 -1.49063e-07 -1.46725e-07 -1.44411e-07 -1.42123e-07 -1.39859e-07 - -1.37619e-07 -1.35402e-07 -1.33209e-07 -1.31038e-07 -1.28889e-07 -1.26762e-07 -1.24657e-07 -1.22572e-07 -1.20508e-07 -1.18464e-07 -1.16439e-07 -1.14434e-07 - -1.12448e-07 -1.1048e-07 -1.08531e-07 -1.06599e-07 -1.04685e-07 -1.02788e-07 -1.00908e-07 -9.90438e-08 -9.71961e-08 -9.53642e-08 -9.35478e-08 -9.17466e-08 - -8.99603e-08 -8.81885e-08 -8.6431e-08 -8.46876e-08 -8.29579e-08 -8.12417e-08 -7.95386e-08 -7.78486e-08 -7.61712e-08 -7.45063e-08 -7.28536e-08 -7.12129e-08 - -6.9584e-08 -6.79666e-08 -6.63604e-08 -6.47655e-08 -6.31814e-08 -6.1608e-08 -6.0045e-08 -5.84924e-08 -5.69499e-08 -5.54174e-08 -5.38945e-08 -5.23812e-08 - -5.08772e-08 -4.93823e-08 -4.78963e-08 -4.64188e-08 -4.49497e-08 -4.34883e-08 -4.20343e-08 -4.05868e-08 -3.91448e-08 -3.77069e-08 -3.62711e-08 -3.48343e-08 - -3.33922e-08 -3.19386e-08 -3.04644e-08 -2.89562e-08 -2.73944e-08 -2.57503e-08 -2.39816e-08 -2.20267e-08 -1.97948e-08 -1.71529e-08 -1.39058e-08 -9.76748e-09 - -4.31913e-09 3.05211e-09 1.32412e-08 2.7552e-08 4.78773e-08 7.69503e-08 1.18687e-07 1.78629e-07 2.64476e-07 3.86599e-07 5.58248e-07 7.97726e-07 - 1.13709e-06 1.62594e-06 2.32736e-06 3.33132e-06 4.76671e-06 6.81766e-06 9.74666e-06 1.39274e-05 1.98914e-05 2.83939e-05 4.05062e-05 5.7747e-05 - 8.22652e-05 0.000117096 0.00016652 0.000236558 0.000335656 0.000475626 0.000672922 0.00095036 -5.71103e-17 -2.05382e-16 -1.97396e-16 2.09465e-16 - 2.15115e-16 1.25492e-16 1.53902e-16 -8.21773e-18 -1.51338e-16 5.24829e-17 5.44223e-16 -1.73125e-16 8.31556e-17 -2.07044e-16 -2.61049e-16 -1.59153e-16 - -5.38271e-16 -2.63548e-16 -2.86771e-16 -6.38395e-17 8.89015e-20 -2.71136e-16 -2.62223e-16 -3.88997e-16 -1.71724e-16 -1.7261e-16 -9.7923e-17 1.93926e-16 - -2.0305e-16 7.97897e-17 1.04521e-16 9.46867e-17 5.51728e-17 3.17062e-16 -2.87546e-16 -1.84927e-16 -3.42162e-16 -2.95168e-16 -1.56309e-16 -2.24452e-16 - -1.4369e-16 2.59936e-16 -3.92548e-16 -1.56791e-16 8.94055e-17 -3.10721e-16 -6.51777e-16 -3.73808e-16 -7.9175e-16 -1.38357e-15 -1.14115e-15 -2.78722e-15 - -4.30723e-15 -6.19069e-15 -8.7673e-15 -1.38589e-14 -2.16899e-14 -3.31307e-14 -5.18445e-14 -7.8819e-14 -1.21244e-13 -1.86546e-13 -2.85958e-13 -4.38776e-13 - -6.73538e-13 -1.03469e-12 -1.58789e-12 -2.43772e-12 -3.74268e-12 -5.74559e-12 -8.82219e-12 -1.35457e-11 -2.07982e-11 -3.1936e-11 -4.90401e-11 -7.53066e-11 - -1.15646e-10 -1.77601e-10 -2.72755e-10 -4.18908e-10 -6.43399e-10 -9.88232e-10 -1.51794e-09 -2.33167e-09 -3.58176e-09 -5.50231e-09 -8.453e-09 -1.29866e-08 - -1.99526e-08 -3.06565e-08 -4.71049e-08 -7.23817e-08 -1.11227e-07 -1.70929e-07 -2.62688e-07 -4.03727e-07 -6.2052e-07 -9.53777e-07 -1.46609e-06 -2.2537e-06 - -8.95533e-06 -1.14973e-05 -1.24345e-05 -1.27318e-05 -1.27703e-05 -1.27039e-05 -1.25955e-05 -1.24707e-05 -1.23402e-05 -1.22083e-05 -1.20767e-05 -1.19461e-05 - -1.18169e-05 -1.16892e-05 -1.1563e-05 -1.14382e-05 -1.1315e-05 -1.11931e-05 -1.10728e-05 -1.09539e-05 -1.08363e-05 -1.07202e-05 -1.06055e-05 -1.04921e-05 - -1.038e-05 -1.02693e-05 -1.01598e-05 -1.00517e-05 -9.94484e-06 -9.83923e-06 -9.73487e-06 -9.63172e-06 -9.52979e-06 -9.42905e-06 -9.32949e-06 -9.2311e-06 - -9.13385e-06 -9.03774e-06 -8.94275e-06 -8.84887e-06 -8.75607e-06 -8.66436e-06 -8.57371e-06 -8.48411e-06 -8.39555e-06 -8.30802e-06 -8.2215e-06 -8.13597e-06 - -8.05144e-06 -7.96788e-06 -7.88528e-06 -7.80363e-06 -7.72292e-06 -7.64314e-06 -7.56427e-06 -7.48631e-06 -7.40924e-06 -7.33305e-06 -7.25773e-06 -7.18327e-06 - -7.10966e-06 -7.03688e-06 -6.96494e-06 -6.89381e-06 -6.82349e-06 -6.75397e-06 -6.68523e-06 -6.61727e-06 -6.55008e-06 -6.48365e-06 -6.41797e-06 -6.35303e-06 - -6.28882e-06 -6.22533e-06 -6.16255e-06 -6.10048e-06 -6.0391e-06 -5.97841e-06 -5.9184e-06 -5.85906e-06 -5.80038e-06 -5.74235e-06 -5.68497e-06 -5.62823e-06 - -5.57212e-06 -5.51663e-06 -5.46176e-06 -5.40749e-06 -5.35383e-06 -5.30075e-06 -5.24826e-06 -5.19635e-06 -5.14502e-06 -5.09424e-06 -5.04403e-06 -4.99436e-06 - -4.94524e-06 -4.89666e-06 -4.8486e-06 -4.80108e-06 -4.75407e-06 -4.70757e-06 -4.66158e-06 -4.61609e-06 -4.57109e-06 -4.52658e-06 -4.48256e-06 -4.439e-06 - -4.39593e-06 -4.35331e-06 -4.31116e-06 -4.26946e-06 -4.2282e-06 -4.1874e-06 -4.14703e-06 -4.10709e-06 -4.06758e-06 -4.02849e-06 -3.98982e-06 -3.95157e-06 - -3.91372e-06 -3.87627e-06 -3.83923e-06 -3.80258e-06 -3.76631e-06 -3.73043e-06 -3.69493e-06 -3.65981e-06 -3.62506e-06 -3.59067e-06 -3.55665e-06 -3.52299e-06 - -3.48968e-06 -3.45672e-06 -3.4241e-06 -3.39183e-06 -3.3599e-06 -3.3283e-06 -3.29703e-06 -3.26608e-06 -3.23546e-06 -3.20516e-06 -3.17518e-06 -3.1455e-06 - -3.11614e-06 -3.08708e-06 -3.05832e-06 -3.02985e-06 -3.00168e-06 -2.97381e-06 -2.94622e-06 -2.91891e-06 -2.89189e-06 -2.86514e-06 -2.83867e-06 -2.81247e-06 - -2.78654e-06 -2.76087e-06 -2.73547e-06 -2.71033e-06 -2.68544e-06 -2.66081e-06 -2.63643e-06 -2.61229e-06 -2.58841e-06 -2.56476e-06 -2.54135e-06 -2.51819e-06 - -2.49525e-06 -2.47255e-06 -2.45008e-06 -2.42783e-06 -2.40581e-06 -2.38401e-06 -2.36243e-06 -2.34106e-06 -2.31991e-06 -2.29898e-06 -2.27825e-06 -2.25773e-06 - -2.23742e-06 -2.2173e-06 -2.19739e-06 -2.17768e-06 -2.15816e-06 -2.13884e-06 -2.11971e-06 -2.10077e-06 -2.08202e-06 -2.06345e-06 -2.04507e-06 -2.02686e-06 - -2.00884e-06 -1.991e-06 -1.97333e-06 -1.95583e-06 -1.93851e-06 -1.92136e-06 -1.90437e-06 -1.88755e-06 -1.8709e-06 -1.85441e-06 -1.83808e-06 -1.82191e-06 - -1.80589e-06 -1.79003e-06 -1.77433e-06 -1.75878e-06 -1.74338e-06 -1.72812e-06 -1.71302e-06 -1.69806e-06 -1.68325e-06 -1.66857e-06 -1.65404e-06 -1.63965e-06 - -1.6254e-06 -1.61128e-06 -1.5973e-06 -1.58345e-06 -1.56973e-06 -1.55614e-06 -1.54269e-06 -1.52936e-06 -1.51616e-06 -1.50308e-06 -1.49012e-06 -1.47729e-06 - -1.46458e-06 -1.45199e-06 -1.43952e-06 -1.42716e-06 -1.41492e-06 -1.40279e-06 -1.39078e-06 -1.37888e-06 -1.36709e-06 -1.35541e-06 -1.34383e-06 -1.33237e-06 - -1.32101e-06 -1.30975e-06 -1.2986e-06 -1.28755e-06 -1.2766e-06 -1.26575e-06 -1.255e-06 -1.24435e-06 -1.2338e-06 -1.22334e-06 -1.21298e-06 -1.20271e-06 - -1.19253e-06 -1.18244e-06 -1.17245e-06 -1.16254e-06 -1.15272e-06 -1.14299e-06 -1.13335e-06 -1.12379e-06 -1.11431e-06 -1.10492e-06 -1.09562e-06 -1.08639e-06 - -1.07724e-06 -1.06818e-06 -1.05919e-06 -1.05028e-06 -1.04145e-06 -1.0327e-06 -1.02402e-06 -1.01541e-06 -1.00688e-06 -9.98425e-07 -9.90039e-07 -9.81724e-07 - -9.73479e-07 -9.65305e-07 -9.57199e-07 -9.49161e-07 -9.4119e-07 -9.33285e-07 -9.25447e-07 -9.17673e-07 -9.09964e-07 -9.02318e-07 -8.94734e-07 -8.87213e-07 - -8.79753e-07 -8.72353e-07 -8.65014e-07 -8.57733e-07 -8.50511e-07 -8.43347e-07 -8.3624e-07 -8.2919e-07 -8.22195e-07 -8.15255e-07 -8.0837e-07 -8.01539e-07 - -7.94761e-07 -7.88036e-07 -7.81363e-07 -7.74741e-07 -7.6817e-07 -7.61649e-07 -7.55178e-07 -7.48756e-07 -7.42382e-07 -7.36056e-07 -7.29778e-07 -7.23546e-07 - -7.17361e-07 -7.11221e-07 -7.05126e-07 -6.99076e-07 -6.9307e-07 -6.87108e-07 -6.81189e-07 -6.75312e-07 -6.69477e-07 -6.63684e-07 -6.57932e-07 -6.5222e-07 - -6.46549e-07 -6.40917e-07 -6.35324e-07 -6.2977e-07 -6.24255e-07 -6.18777e-07 -6.13336e-07 -6.07933e-07 -6.02565e-07 -5.97234e-07 -5.91939e-07 -5.86679e-07 - -5.81454e-07 -5.76263e-07 -5.71106e-07 -5.65983e-07 -5.60893e-07 -5.55836e-07 -5.50812e-07 -5.45819e-07 -5.40858e-07 -5.35929e-07 -5.3103e-07 -5.26162e-07 - -5.21324e-07 -5.16515e-07 -5.11734e-07 -5.06982e-07 -5.02256e-07 -4.97555e-07 -4.92877e-07 -4.8822e-07 -4.83579e-07 -4.7895e-07 -4.74324e-07 -4.69689e-07 - -4.65029e-07 -4.6032e-07 -4.55525e-07 -4.50592e-07 -4.45442e-07 -4.39963e-07 -4.33984e-07 -4.27257e-07 -4.19413e-07 -4.099e-07 -3.97897e-07 -3.82162e-07 - -3.60809e-07 -3.30922e-07 -2.87927e-07 -2.24481e-07 -1.28472e-07 2.06911e-08 2.592e-07 6.42549e-07 1.22958e-06 2.08322e-06 3.31172e-06 5.07651e-06 - 7.61214e-06 1.12572e-05 1.65001e-05 2.40445e-05 3.49049e-05 5.05442e-05 7.30717e-05 0.00010553 0.00015231 0.000219745 0.000316978 0.000457204 - 0.000659466 0.000951239 0.00137214 0.00197924 + 5.80458e-16 1.7222e-16 2.80215e-16 2.56364e-16 -1.12245e-16 -1.28863e-16 1.31425e-16 -6.83133e-17 -2.80283e-17 -2.18933e-16 -2.71198e-17 8.22867e-16 + -2.59015e-17 3.33758e-16 1.46693e-16 1.90922e-16 5.13248e-17 -2.22601e-16 -2.34941e-16 -1.37833e-16 -2.37007e-16 -7.93367e-17 1.61874e-16 1.94445e-17 + -2.53293e-16 -6.13405e-17 2.41014e-16 -2.14904e-16 2.90496e-17 7.01206e-17 9.47625e-17 3.77967e-16 3.69567e-16 -1.06725e-16 7.83273e-17 6.70102e-17 + -1.4485e-16 -8.46308e-18 -1.56946e-16 -1.49912e-16 2.40087e-16 -1.15213e-16 -1.94228e-16 -3.95472e-17 -5.49014e-17 1.58489e-16 -5.27483e-16 4.12324e-17 + 4.76834e-17 -1.1365e-16 -1.48485e-16 -3.96753e-16 1.26344e-16 -2.30076e-19 7.2617e-17 3.45154e-17 4.23198e-17 -4.61552e-16 -1.72245e-16 -6.01443e-17 + -8.3625e-17 -2.5921e-16 -3.27431e-16 -1.25968e-16 -1.87507e-16 2.9845e-16 9.01529e-18 -1.78179e-16 1.67201e-16 1.63251e-17 1.7108e-16 1.6388e-16 + -1.21507e-17 -2.81582e-17 1.28702e-16 -2.49113e-16 -1.65993e-16 -5.45872e-17 2.82975e-16 -1.40819e-16 -1.26141e-17 -2.94939e-16 7.69636e-18 -4.2028e-16 + 1.1637e-16 -2.42309e-16 -5.43144e-16 3.26167e-17 2.20555e-16 1.20765e-16 2.52347e-16 -2.40391e-16 -1.6773e-16 -1.13496e-16 -2.499e-17 -4.31647e-17 + 4.85724e-16 3.73653e-16 1.62579e-16 1.55895e-16 4.20124e-16 -2.41547e-16 -1.31514e-16 1.08296e-16 3.06234e-16 -2.97516e-17 -3.51627e-16 -9.15308e-17 + 8.70469e-17 -3.10043e-16 5.01907e-17 8.85434e-17 -1.48753e-16 -1.65489e-16 3.96917e-16 4.59108e-16 -2.33746e-16 -1.17185e-16 8.26605e-17 2.76644e-16 + 3.59297e-16 2.92684e-16 9.00384e-17 -1.0729e-16 -1.11168e-16 5.07699e-16 -7.15005e-17 2.52834e-16 3.0586e-17 -1.52439e-16 2.74614e-16 -1.45827e-16 + -1.6659e-16 -2.37898e-16 -1.03088e-16 -7.0769e-17 1.04278e-16 -1.17107e-16 -7.12436e-17 2.55648e-16 -1.8131e-16 -2.15817e-16 -1.46718e-16 -2.79568e-16 + 3.71535e-16 -9.74571e-17 2.39164e-16 1.51904e-16 -6.41478e-17 1.29402e-16 -7.37194e-17 1.32149e-16 -5.03169e-17 -3.15268e-16 1.85722e-16 3.88388e-16 + 2.26399e-16 -2.66163e-16 -6.95896e-17 3.30373e-17 1.73984e-16 -6.70671e-17 -2.46714e-17 -2.24626e-16 3.6404e-16 1.45556e-16 1.0159e-17 7.06992e-18 + -9.00261e-18 -1.4823e-17 4.28274e-17 1.40316e-16 -7.0339e-17 4.9463e-16 3.60048e-17 2.94186e-16 1.9747e-16 1.70248e-16 1.78917e-16 4.4179e-16 + -8.57581e-17 1.7309e-16 -2.03447e-17 -9.10355e-17 3.25529e-16 -3.9639e-16 -1.67986e-16 1.07545e-16 2.43203e-17 -4.08712e-16 -1.69962e-16 2.4085e-16 + -9.82447e-17 9.63518e-17 8.47394e-17 1.02023e-16 1.41493e-16 1.69008e-17 1.44494e-17 2.53339e-16 -1.79107e-16 -1.27356e-16 3.68815e-16 -1.46087e-17 + 7.07966e-17 -1.46753e-17 2.83244e-16 -3.53544e-16 3.41206e-17 1.85473e-17 2.78643e-16 -5.60483e-16 -6.0937e-16 -2.17145e-16 -1.3186e-16 -3.48879e-16 + -2.25094e-16 1.37971e-16 -2.70228e-16 2.08355e-16 1.48752e-16 4.98301e-16 -2.03702e-17 -1.85667e-16 7.24749e-17 4.72998e-17 4.3377e-17 2.93004e-16 + 1.00249e-16 2.21938e-16 -8.72211e-17 -1.54749e-16 1.42723e-16 5.40234e-16 8.0165e-16 -1.37489e-16 -1.63814e-16 -3.1214e-16 -4.19712e-17 5.41224e-16 + -1.59432e-16 -2.62144e-16 -3.16854e-16 2.12771e-16 1.16291e-16 -2.42705e-16 -2.02156e-16 4.00723e-16 -9.9924e-17 1.19762e-16 -1.02529e-16 2.10596e-16 + 1.88362e-16 -4.0853e-16 -4.82268e-17 -9.4561e-17 -6.34292e-17 -2.48895e-16 2.62246e-17 3.59323e-16 -5.12193e-17 -4.65334e-16 3.85334e-16 2.75773e-16 + -6.88015e-17 1.05513e-16 -6.16018e-17 -9.969e-17 -7.08566e-17 2.00021e-16 2.53825e-16 -1.29596e-16 -3.12583e-17 -1.49912e-17 -1.3454e-16 -1.27056e-16 + 1.02829e-16 -2.6197e-17 -1.93674e-16 -3.53502e-17 2.8655e-16 2.74428e-16 3.42333e-16 -2.41454e-16 -2.16389e-16 -3.14852e-16 -1.33212e-16 -9.30967e-17 + 2.98509e-16 2.6214e-17 -4.68082e-17 -4.99803e-16 -5.87322e-17 -2.40064e-16 -3.37946e-17 -4.97394e-16 -1.99409e-16 -4.061e-16 -5.5371e-16 -2.7545e-17 + 3.61242e-16 3.97345e-16 5.25871e-16 -9.68967e-17 -1.21837e-16 -1.39285e-16 1.61678e-16 -5.83801e-17 2.54475e-16 -6.58762e-17 -1.03881e-16 8.88353e-17 + 2.05863e-16 3.92781e-17 -2.27581e-17 3.94894e-16 3.21417e-16 2.60201e-16 -5.78224e-17 -5.07573e-16 4.68819e-17 2.21191e-16 -8.60301e-17 -2.19286e-16 + 6.83072e-17 -1.09661e-17 1.26077e-16 -8.36518e-18 -1.26067e-16 1.72537e-16 1.70136e-16 5.01968e-16 1.71084e-16 2.26112e-16 -6.42007e-17 3.31058e-17 + 1.18667e-16 1.3691e-16 -1.97733e-17 3.03958e-16 1.97247e-18 8.20592e-17 -7.06986e-17 -2.10139e-16 1.76708e-16 1.86887e-16 -2.62545e-16 5.37767e-17 + -1.65607e-16 -1.88975e-16 2.15004e-16 4.00405e-16 2.68553e-16 2.39011e-16 -1.09249e-16 1.33863e-16 2.4142e-16 -3.69885e-16 -2.03743e-16 8.35602e-17 + 5.36264e-17 -1.84818e-17 1.22211e-16 -2.86562e-16 -5.90525e-17 -2.89907e-16 -3.70952e-16 1.02277e-16 -3.3917e-16 -3.56938e-16 1.0421e-16 -1.71113e-16 + -1.59794e-16 -3.69706e-17 -3.2983e-18 -1.28485e-16 -5.15554e-17 -9.12036e-17 -1.33807e-16 1.94813e-16 5.12435e-16 1.49144e-16 2.78377e-16 -4.63037e-17 + -2.36371e-16 1.78101e-16 8.99763e-17 2.5717e-16 2.53364e-16 2.57973e-16 2.27947e-17 -8.52355e-17 -3.19016e-16 -8.7794e-17 9.45382e-17 -1.08056e-17 + -1.32029e-16 -1.98729e-16 1.90614e-16 -1.05256e-16 -8.74357e-17 -1.48883e-16 3.77266e-16 -9.08448e-17 1.75795e-16 9.18094e-17 -1.33361e-16 -2.35447e-16 + -1.05722e-16 -2.94619e-16 2.29864e-16 4.54849e-16 -3.26877e-17 2.20839e-17 -8.53314e-17 -2.10646e-16 2.79992e-16 1.07264e-16 -1.07471e-16 -2.03015e-16 + -1.93763e-16 -1.47532e-16 5.35161e-16 8.90362e-17 1.08723e-16 3.24978e-16 5.74508e-17 1.36581e-16 4.77939e-17 -1.09303e-16 3.42567e-16 -3.22482e-17 + 6.5323e-17 -2.58665e-17 -1.40067e-16 5.36633e-17 5.44055e-16 6.6084e-17 -1.10196e-16 -2.56811e-17 2.81577e-16 -1.76725e-16 -1.80011e-16 -1.01894e-16 + -2.79022e-16 -1.74521e-16 -5.29892e-17 1.26014e-16 -2.18465e-18 2.26769e-16 -3.07531e-16 -2.93856e-16 -1.67859e-16 2.90697e-16 3.08191e-16 -1.03619e-16 + 2.2779e-16 -3.43456e-16 1.11488e-16 -1.74888e-16 4.91878e-17 3.84827e-17 2.23192e-16 -4.50862e-16 1.8215e-16 -3.70358e-16 -2.87874e-16 2.1121e-16 + -4.31594e-17 -1.02201e-16 -3.01514e-16 -1.0938e-16 -5.68454e-17 -2.31909e-16 -9.45746e-17 -9.23607e-17 3.6115e-16 2.48152e-16 2.86442e-16 -2.23345e-16 + -4.0965e-16 2.03119e-16 -1.17461e-16 -7.01587e-17 1.25562e-16 -2.93661e-16 1.30622e-17 -1.5998e-17 4.97321e-16 4.31393e-16 5.34587e-16 1.97404e-16 + -2.52191e-16 2.01336e-17 5.70117e-17 1.62092e-16 3.76581e-16 2.00885e-16 1.34922e-16 -1.34065e-16 2.27587e-16 3.33381e-16 -3.83699e-17 -4.14182e-17 + -8.80426e-17 3.26485e-17 -1.26178e-16 -1.55218e-16 -2.13138e-16 -9.08402e-17 2.86873e-16 3.34725e-16 4.05951e-16 1.07019e-16 -4.53952e-17 3.71616e-16 + 4.07236e-16 1.50388e-16 1.43878e-16 -1.53618e-16 -2.50166e-16 -5.84402e-16 6.74477e-17 -2.02269e-16 -4.63386e-17 2.04455e-16 -3.0713e-16 -3.40068e-16 + 5.38454e-16 3.88383e-17 -1.23992e-16 -4.45176e-17 1.06473e-16 -4.24868e-16 -4.79228e-16 -2.67004e-16 5.23827e-17 -1.01621e-16 -8.38469e-16 -2.18205e-16 + -1.26812e-18 -2.01791e-16 -1.70672e-16 4.81399e-16 5.18862e-17 -1.99834e-16 1.04171e-17 -3.64096e-17 -7.97425e-17 2.4791e-16 -1.72897e-16 -2.2578e-16 + 3.28753e-16 1.87139e-16 3.01527e-16 1.51273e-16 -1.58576e-16 -4.75702e-16 7.73053e-17 2.67097e-16 2.69699e-17 -5.38406e-16 -1.96107e-16 -5.8169e-17 + -1.57541e-16 5.32966e-16 6.86554e-17 7.08952e-17 -1.45082e-16 5.94443e-16 1.28552e-16 -2.29048e-16 2.17872e-16 4.01103e-16 -2.17167e-16 -1.76969e-16 + -3.35891e-16 -9.64098e-17 -5.00163e-17 -1.00622e-16 1.25208e-17 -3.56549e-16 -3.57942e-16 -2.89127e-16 3.25102e-18 -7.5095e-17 -1.77948e-16 2.61939e-16 + 2.16735e-16 1.46478e-16 -6.01407e-17 1.13598e-16 -2.5091e-16 -4.60891e-16 6.39878e-17 7.84775e-18 -2.21794e-16 8.57657e-18 -2.67185e-16 -3.07065e-16 + 1.27096e-16 1.34225e-16 4.154e-16 1.75263e-16 -9.10744e-17 1.52193e-16 -2.94122e-17 9.26911e-17 -6.13585e-16 -5.41648e-16 -3.03206e-16 1.62674e-16 + 2.05416e-17 -3.35706e-16 2.50361e-16 1.36115e-16 -1.87282e-16 1.90165e-17 6.72211e-17 6.46579e-16 6.79348e-16 1.95889e-16 -6.29814e-16 3.89587e-16 + 3.19909e-16 4.17726e-16 -1.23993e-16 -1.62599e-16 -2.2866e-16 4.9397e-16 -9.34437e-17 2.80955e-17 9.07205e-17 -1.96523e-16 -3.25012e-17 -5.05304e-17 + 2.5754e-16 -2.50002e-16 1.98949e-16 2.80562e-16 -4.18896e-16 1.89934e-16 -2.05484e-17 -1.39873e-16 3.59135e-16 3.88357e-17 1.40968e-16 -2.31068e-16 + -2.27968e-16 3.41589e-16 1.69622e-16 -7.86774e-17 3.21103e-16 2.46068e-16 5.14502e-16 -8.35435e-17 1.75913e-16 6.42331e-18 -3.96345e-17 -2.83705e-17 + 5.59013e-16 4.23374e-16 3.69429e-16 1.4631e-16 -1.49145e-16 -1.91424e-16 -8.24552e-17 2.91615e-16 5.64917e-17 1.77653e-16 -4.00431e-18 -1.21569e-16 + 2.05597e-17 -1.13957e-16 3.42334e-16 -1.96106e-16 9.56304e-17 -2.98289e-16 -9.52855e-17 1.42761e-16 -2.74311e-16 5.59046e-17 -2.06086e-16 2.61367e-16 + -2.87173e-16 -3.82859e-16 1.13479e-16 -3.68127e-16 -6.08188e-16 -2.07622e-16 -1.63155e-16 4.99362e-17 1.04089e-16 -1.32676e-16 3.97338e-16 7.12158e-16 + 4.56727e-16 -2.24073e-16 1.7478e-17 4.82301e-18 3.37243e-16 3.51691e-16 -2.0524e-16 -4.46023e-17 2.32003e-16 1.28104e-17 -1.09227e-16 -7.43727e-17 + 2.80343e-18 -9.27558e-17 -1.30076e-17 1.81855e-17 2.7371e-16 -2.72966e-16 -2.53293e-16 -2.74902e-16 -6.73743e-16 -1.07308e-16 -1.87275e-16 -2.57483e-16 + 6.07427e-17 2.24656e-16 -8.50638e-17 -6.79698e-17 1.92431e-16 2.73733e-16 8.40545e-17 3.75676e-16 9.45823e-17 -7.06364e-17 -3.14025e-17 2.82122e-17 + -5.3735e-17 3.06068e-16 3.93492e-16 2.1259e-17 1.36513e-16 -3.61837e-17 1.76216e-16 -2.25706e-16 1.47312e-16 -7.85031e-17 1.06311e-16 4.00479e-16 + 1.43859e-16 2.14964e-16 5.87998e-17 -3.31221e-17 1.95254e-16 -1.62101e-16 -3.21447e-17 -2.70597e-16 -1.62939e-16 2.60858e-16 -1.87053e-16 -2.75285e-16 + 4.89889e-17 1.88191e-16 2.95629e-16 1.61049e-16 2.656e-16 -3.35186e-17 1.7207e-16 7.21023e-17 -3.39773e-16 1.87337e-17 -3.71322e-16 7.6579e-17 + 3.4168e-16 4.32386e-16 2.90068e-16 5.7417e-17 1.93725e-16 2.03937e-16 -6.03985e-17 1.09933e-16 2.70156e-16 -3.57743e-16 1.10517e-16 6.29994e-16 + 2.87318e-16 2.85829e-16 5.89113e-16 1.40372e-16 2.68438e-17 -2.72656e-16 5.64881e-17 5.11071e-16 4.1541e-16 3.11906e-16 -3.05038e-16 -2.10578e-16 + -4.95237e-16 -5.8802e-16 -4.14146e-17 -4.23066e-17 2.16348e-16 -1.57986e-16 -1.44579e-16 -7.61946e-17 -2.73926e-16 7.80051e-17 1.34117e-16 -5.37428e-18 + 2.59003e-16 -3.52495e-16 -2.94791e-16 -9.59454e-17 6.46822e-17 -1.0715e-16 -4.36125e-16 4.68413e-17 -2.00321e-16 -3.67068e-16 2.15972e-16 2.47184e-16 + 2.20473e-16 7.10133e-17 2.99776e-16 2.50291e-16 1.81985e-16 -2.64414e-16 -2.34205e-16 6.34344e-17 1.23637e-16 -7.35908e-17 -3.42888e-16 -2.30442e-16 + -2.95139e-16 -6.8552e-16 -8.39899e-16 7.10578e-17 3.78253e-16 1.47716e-16 -3.29712e-16 1.38807e-16 -3.34554e-16 -3.86996e-16 -3.23737e-16 1.13133e-16 + -1.59213e-16 -7.43053e-17 -3.6247e-16 -1.30878e-16 -3.28741e-16 1.85752e-16 -1.75968e-17 7.76636e-17 1.36293e-16 -3.37793e-17 2.33604e-16 1.86021e-16 + 2.1774e-16 3.02686e-16 5.61302e-16 1.01007e-16 4.28317e-16 1.18245e-16 -3.19106e-16 -2.34672e-16 -7.1419e-17 -1.77628e-16 -1.00678e-17 -5.34825e-16 + -4.36483e-16 -2.09411e-16 -7.18232e-17 -9.92961e-17 -4.47721e-16 2.11594e-16 5.42924e-17 -3.54819e-17 -6.63433e-17 -1.09721e-16 2.28941e-16 2.57988e-16 + -1.59948e-16 6.98173e-17 3.51259e-16 1.75799e-16 9.40033e-17 1.63376e-16 2.86949e-17 8.30681e-17 -2.31562e-16 5.97543e-16 5.5582e-16 6.69523e-16 + 3.56265e-16 1.93833e-16 5.60163e-16 3.98894e-16 -2.33881e-16 -3.1024e-16 -1.63888e-16 -1.1668e-16 -1.4757e-16 -3.81861e-16 -1.70406e-16 -2.84255e-17 + -4.27865e-16 3.10909e-16 3.52502e-16 -1.93314e-16 -3.18276e-16 8.72048e-18 -3.95678e-17 2.11842e-16 -4.16466e-17 2.03599e-17 -8.72984e-18 -6.20998e-17 + 9.73231e-17 2.51867e-16 -4.05523e-16 1.6141e-16 -1.21593e-16 6.85992e-17 9.49571e-17 1.11682e-16 1.5033e-16 2.17178e-16 4.30786e-16 3.58864e-16 + 9.80528e-18 1.05982e-16 8.92101e-17 3.42782e-16 2.20379e-16 2.25598e-16 8.7396e-17 -1.93854e-16 -4.84909e-17 -6.02075e-17 -1.87744e-16 8.98359e-17 + 1.64602e-16 -2.56281e-16 -2.71102e-16 -4.72443e-16 -5.35308e-16 -5.41088e-16 -8.59619e-17 4.21107e-16 -3.27068e-16 -1.67284e-17 -2.00442e-16 -1.87485e-16 + -7.5627e-17 -7.00657e-17 -2.01382e-16 2.78089e-17 1.31072e-16 2.0876e-16 -1.45918e-16 2.73916e-16 -2.80116e-17 -2.67655e-16 9.29568e-17 -1.4108e-16 + -1.84789e-16 -2.27834e-16 5.56221e-16 -2.02699e-16 -2.1613e-16 -2.16596e-16 -2.71332e-16 -7.74702e-17 -4.03998e-16 3.18993e-16 3.03531e-16 -3.22143e-16 + -3.60661e-16 -1.51553e-16 -2.70831e-16 2.32326e-16 -3.78612e-17 2.361e-16 -6.64663e-17 2.46002e-17 -2.07375e-16 1.30441e-16 6.52501e-17 8.36438e-17 + -4.18251e-16 2.68506e-16 -2.05775e-16 -1.63112e-16 -4.79133e-18 1.31419e-16 1.9198e-17 3.90344e-16 2.25767e-17 -3.20555e-16 -1.69191e-16 2.17808e-16 + 2.63538e-16 2.51853e-16 1.82326e-16 2.56507e-16 7.13457e-16 5.11547e-17 -3.35734e-17 1.68691e-16 2.21183e-16 -2.50798e-16 2.34338e-17 1.21622e-16 + -3.67807e-16 -5.01681e-16 -2.0148e-16 -4.41422e-16 -2.85621e-16 2.0841e-16 2.35753e-16 4.42211e-16 4.60775e-16 2.39378e-16 4.18482e-16 -4.8691e-17 + -3.07704e-16 -6.01511e-16 -3.43405e-16 -6.30469e-17 -3.27766e-16 -1.3722e-16 4.30972e-16 -1.9465e-16 4.34295e-16 3.54764e-16 2.11625e-16 2.83466e-16 + 1.87549e-16 -3.34727e-16 -5.49389e-17 -1.4681e-16 8.55491e-17 -1.3725e-16 4.13214e-17 -3.18375e-16 -2.21214e-16 -3.57281e-16 -1.2839e-16 3.92488e-16 + 3.56937e-16 -3.41159e-16 -3.71024e-16 -3.18605e-16 8.47719e-17 -1.63183e-16 4.32192e-16 -9.64306e-18 -3.08275e-16 -2.15425e-16 -2.16539e-16 1.33203e-18 + 1.59396e-16 3.74158e-16 -1.90822e-16 -3.85056e-16 -3.35671e-17 8.25282e-17 -1.47039e-16 1.25926e-16 2.17953e-16 3.4896e-16 1.04484e-16 -4.62837e-16 + -2.13002e-16 4.965e-17 4.94998e-17 3.22163e-16 2.51867e-16 1.80686e-16 2.3989e-16 -4.72979e-17 -2.24775e-16 -8.26804e-17 -2.58486e-16 1.01199e-16 + -1.52364e-16 -2.22443e-16 -3.54545e-16 -2.76014e-16 -5.16313e-17 1.60325e-16 1.11336e-16 -1.6148e-16 -1.35479e-16 -5.67163e-17 2.16563e-16 -1.6977e-16 + -5.36664e-17 9.99887e-18 1.3556e-16 5.79817e-16 -5.80374e-17 -4.57089e-16 -9.44895e-17 -1.13412e-16 2.93903e-16 1.39159e-16 -1.39925e-16 -6.27247e-17 + -4.40977e-18 1.83758e-16 2.17403e-16 1.24491e-16 7.88892e-17 1.22027e-16 3.26951e-17 2.26396e-16 -6.6145e-18 -1.02689e-16 4.62963e-16 -1.17963e-17 + 1.02497e-16 -4.69467e-17 -3.43809e-16 8.69341e-16 2.01021e-16 -2.89673e-16 -1.80043e-17 1.87832e-16 3.83345e-16 1.36646e-16 -6.15489e-16 -2.02235e-16 + -5.77587e-16 3.80144e-17 2.63004e-17 1.20041e-16 -3.23427e-16 -9.70896e-17 -3.23321e-16 -3.26923e-17 1.86211e-16 -3.34504e-16 1.48786e-17 -8.72094e-17 + -1.80436e-16 5.194e-17 3.02939e-16 -2.083e-16 1.36453e-16 1.59245e-16 -4.18484e-16 1.7767e-16 1.89185e-16 6.30544e-16 2.2947e-16 6.99392e-16 + 3.1712e-16 6.36165e-17 3.37742e-16 -1.71603e-17 -4.57288e-17 4.42736e-16 -1.60293e-16 2.26157e-16 3.71201e-16 1.17211e-16 3.47258e-16 5.19513e-17 + -1.5198e-16 2.08016e-16 3.44626e-16 -1.34211e-17 -2.02298e-16 5.67705e-16 -1.62378e-16 2.50815e-16 -7.78246e-17 -6.52105e-16 -3.10552e-16 4.59455e-16 + -2.73044e-17 -4.20447e-18 -3.65717e-17 -1.88576e-16 5.34514e-17 -3.06444e-16 -3.29146e-16 -4.16606e-16 1.76577e-16 -2.31928e-16 -1.0551e-16 9.67643e-17 + -3.70958e-16 -6.17114e-16 -2.75805e-16 2.76163e-17 -1.32368e-17 4.91471e-16 2.26122e-16 2.23531e-17 3.27971e-16 6.56213e-17 -4.27306e-17 9.09425e-17 + 1.29822e-16 2.14053e-16 1.26633e-16 1.0564e-16 -6.04594e-17 3.19465e-16 -1.96193e-16 4.01e-17 2.93454e-17 2.72391e-16 1.90425e-16 -1.58141e-17 + 2.23268e-16 -1.99794e-16 -2.02676e-16 -4.61393e-16 -2.76018e-16 -8.28384e-17 -1.299e-17 -1.47809e-16 4.59057e-16 -8.04681e-18 -1.3177e-16 -1.3522e-16 + -3.7601e-16 -4.69132e-16 3.59413e-16 8.833e-17 5.73193e-17 4.12081e-16 -2.18806e-16 1.10206e-16 2.86138e-16 7.43135e-16 9.93717e-16 3.01008e-16 + -3.90951e-16 -2.98459e-16 -5.08776e-17 2.08474e-16 -7.06702e-17 -3.16714e-16 7.06656e-17 -3.66813e-17 -4.28694e-17 -4.50663e-17 1.06563e-18 -2.20788e-17 + -3.8878e-16 7.55313e-18 -3.50977e-17 -1.94198e-16 -6.69717e-16 -1.15796e-16 4.87277e-16 -8.63652e-17 -3.15593e-16 2.21208e-16 -1.60516e-17 -1.29188e-16 + -2.98367e-19 -4.75388e-18 -5.56086e-16 -4.31306e-18 2.77059e-16 -2.28998e-16 -2.21625e-16 -3.57727e-16 -2.4845e-16 1.10822e-16 -2.11243e-16 -5.35118e-17 + -5.00548e-16 1.71482e-17 -1.77039e-16 -1.73461e-16 6.13074e-17 2.04581e-16 -3.43405e-16 4.23547e-17 1.72e-16 2.45192e-16 3.9353e-16 3.92735e-16 + -6.5168e-17 7.91424e-17 4.35881e-17 4.54974e-16 4.70935e-16 2.84475e-16 -2.89402e-16 -2.31686e-16 -7.35471e-16 -3.666e-16 -5.34916e-16 -2.51661e-16 + 1.74469e-16 1.45822e-16 1.11414e-16 -4.22156e-16 -3.22537e-16 -1.74159e-16 -5.75206e-17 -2.5324e-16 3.87292e-16 -1.26034e-16 -4.68102e-16 -3.27402e-16 + -4.01012e-16 -2.72572e-17 -6.56779e-16 -4.1581e-16 1.19691e-16 1.19078e-16 4.09345e-16 -8.50226e-17 1.83035e-16 -1.35766e-16 2.52187e-16 -1.33494e-16 + -1.13664e-16 -3.39989e-16 1.72968e-17 -5.21478e-17 8.61743e-17 1.48959e-16 -1.57949e-17 -2.2219e-16 9.99137e-17 1.79164e-16 -1.53578e-16 3.62048e-16 + -1.24984e-16 -7.14723e-17 -4.42118e-16 -2.67922e-16 -1.15764e-16 -3.29373e-16 -4.43285e-16 1.10586e-17 -2.20845e-16 -2.14575e-16 -7.19464e-17 2.35089e-16 + 3.31459e-16 1.98747e-16 -5.38391e-16 3.92108e-16 2.69255e-16 2.74739e-16 2.28892e-16 4.50868e-16 1.2055e-16 5.14487e-16 5.04478e-16 1.88858e-16 + 2.66054e-16 -3.53585e-17 -3.77937e-16 -4.35147e-16 1.21573e-17 -1.83231e-16 2.02121e-16 -3.15605e-16 -1.67675e-16 1.14249e-17 -1.82722e-16 -1.81416e-16 + -2.11314e-16 -8.45114e-17 -1.36894e-16 -1.57912e-16 -7.50578e-17 -3.68973e-16 7.45681e-17 5.76695e-16 -5.52871e-17 3.95201e-17 -5.95492e-17 5.78108e-16 + 1.0703e-16 -4.4009e-16 -4.11813e-16 -4.70224e-16 -3.34178e-16 7.17694e-17 -1.15654e-17 1.48535e-16 2.32337e-16 3.87733e-16 3.90417e-16 6.61733e-17 + -2.07171e-16 3.53694e-16 1.30745e-16 -2.67564e-16 -1.83001e-16 -1.69412e-16 6.90432e-17 -2.34339e-17 2.07384e-16 4.01302e-16 4.86193e-16 5.41852e-16 + 4.28354e-16 2.22189e-16 1.75694e-16 7.25647e-17 3.5991e-16 8.13536e-17 1.42286e-16 -2.32247e-16 -3.05144e-16 -2.70867e-16 -5.77404e-16 -3.95074e-16 + -1.04548e-16 7.45477e-19 6.61205e-17 -3.35941e-16 1.27279e-16 -8.99866e-18 8.58998e-17 1.16636e-16 1.82282e-16 5.55668e-16 6.74774e-16 5.34078e-16 + 4.10633e-16 4.73849e-16 2.98689e-16 1.23765e-16 7.27214e-17 -4.97522e-16 -1.45551e-16 4.32162e-16 1.35985e-16 -3.2559e-16 -1.29152e-16 -2.8155e-16 + -3.26273e-16 1.48437e-16 5.17787e-16 3.66512e-16 2.21589e-16 1.96689e-16 9.15132e-17 4.97243e-16 4.46761e-16 1.23716e-16 -1.1633e-16 5.06131e-17 + -1.79119e-16 -3.44848e-16 -9.74465e-17 4.44043e-17 3.96503e-17 -7.39417e-16 -5.68545e-16 -5.34161e-17 1.16079e-16 -2.38529e-16 -2.9168e-16 -7.65027e-16 + -6.13735e-16 -1.81817e-16 -1.90035e-16 -1.53884e-16 -7.77846e-16 3.78534e-17 -3.55308e-16 1.63679e-16 5.98815e-19 4.76114e-16 6.51191e-16 3.84512e-16 + -9.13077e-18 2.66036e-16 -3.47426e-17 -3.66444e-16 2.9965e-16 5.34175e-16 -5.12603e-17 7.56361e-17 -2.77737e-16 2.1811e-16 2.12232e-16 1.76719e-16 + 7.34901e-17 3.24273e-16 5.1743e-16 3.29386e-16 -2.29718e-16 -2.90778e-16 -1.02202e-16 6.6344e-17 4.02411e-16 -6.43128e-17 9.16687e-17 1.69489e-16 + -3.05321e-17 -9.94566e-17 6.81474e-16 2.44321e-16 7.11147e-17 2.82036e-16 2.46876e-16 2.15928e-16 -2.82603e-16 -1.02613e-16 -2.64609e-16 -1.68125e-16 + 1.32432e-16 -9.57572e-17 -7.27811e-17 2.84425e-17 2.19429e-16 3.4444e-16 -2.92721e-16 1.15038e-16 1.216e-16 -3.16207e-16 -1.12954e-16 -2.66572e-17 + -1.17077e-16 1.67249e-17 1.88258e-16 4.2412e-16 3.86916e-16 2.14947e-16 -3.67694e-16 -5.8132e-16 6.48022e-17 -4.16342e-16 -2.91734e-16 -2.9054e-17 + 5.61874e-16 2.56286e-18 -1.23954e-16 -1.38868e-16 -3.59702e-16 -7.44152e-17 3.03628e-16 3.06102e-16 -1.05438e-16 8.08379e-16 -2.02401e-16 4.76241e-17 + -2.41332e-16 2.88475e-16 4.90989e-17 4.61419e-16 -3.1207e-17 -1.55607e-16 -6.71899e-16 -2.00694e-16 -4.15378e-16 6.50612e-18 -1.66592e-16 -1.8016e-16 + -1.61239e-16 -9.63911e-17 -7.18103e-18 1.02717e-16 4.24112e-16 3.14685e-16 4.42483e-16 -3.60868e-16 2.87705e-16 1.62919e-16 5.58816e-17 8.17061e-17 + 2.33607e-16 -1.72461e-16 3.64336e-17 -2.96209e-16 -1.51204e-16 1.45727e-16 1.52925e-16 2.41574e-16 -3.93335e-17 1.62704e-17 1.31174e-17 -2.8621e-16 + 1.76295e-16 1.80664e-16 -1.12942e-16 1.45535e-16 -3.46178e-16 2.18456e-16 -6.5995e-16 -6.33373e-17 -3.87511e-17 -4.40282e-17 5.0239e-18 2.14288e-16 + -4.60182e-16 1.45594e-16 5.41667e-17 -4.43519e-16 2.48451e-16 4.1904e-17 -7.94521e-17 2.06414e-17 3.67497e-16 3.70603e-16 7.07402e-16 4.17056e-16 + 7.69178e-17 2.68381e-16 -3.47262e-16 1.89761e-16 2.01181e-16 -4.30525e-16 3.88247e-16 -2.94691e-17 -2.18088e-16 -1.86346e-16 1.28416e-16 3.89815e-16 + 5.50515e-16 2.17522e-16 -2.80112e-16 -2.00276e-16 3.07273e-16 1.14264e-16 -5.50197e-17 -4.62629e-16 -2.24025e-16 5.52087e-16 1.54616e-16 -1.7447e-17 + -5.48276e-17 7.25605e-17 2.99898e-17 -3.19691e-16 -4.23048e-16 -5.08481e-17 -2.5344e-16 -6.20566e-17 3.48024e-16 8.18735e-16 3.40618e-16 -1.27301e-16 + -4.5824e-16 -2.46986e-16 -9.59753e-17 1.22012e-16 2.65795e-16 -1.28007e-16 1.78245e-17 5.24498e-16 3.83342e-16 4.61692e-16 3.97092e-16 -8.51477e-17 + 1.873e-16 6.94022e-16 -1.59191e-16 3.03804e-16 3.78489e-16 1.57548e-16 2.7639e-16 -2.03063e-16 3.50901e-16 9.24814e-17 1.14745e-16 1.78813e-16 + 2.81891e-16 2.12786e-16 -1.85191e-16 -2.63389e-16 -2.02664e-16 -2.9791e-16 -5.3809e-16 -4.17194e-16 -7.30057e-16 2.94936e-16 3.64575e-16 2.06801e-16 + 3.52695e-17 -2.34739e-16 -2.52147e-16 -2.56265e-16 -2.43921e-16 1.1308e-16 -2.88947e-16 7.48656e-17 -2.41979e-16 1.4687e-16 1.06011e-16 2.54619e-16 + 1.95643e-16 2.64151e-16 -3.12677e-17 -3.58002e-16 3.71247e-16 2.6642e-16 -1.95982e-16 -8.10529e-17 -1.31067e-16 1.40714e-16 1.72436e-17 -3.8303e-16 + -1.32542e-16 -5.24946e-17 2.4249e-16 1.48639e-16 -3.52794e-17 5.76434e-16 3.23536e-16 3.46353e-16 -1.53439e-16 -5.72135e-16 -2.88331e-16 -6.47008e-16 + -2.03824e-16 -3.39563e-16 7.76338e-17 6.58926e-17 -2.51408e-16 -9.5412e-17 2.70189e-17 4.17047e-16 -1.78695e-17 -5.95732e-16 1.89597e-16 -1.49378e-16 + 3.14725e-16 2.28146e-16 2.29363e-16 2.48414e-16 2.96666e-16 2.10074e-16 4.21167e-16 -2.71453e-16 -2.48767e-16 -4.40316e-16 -3.29739e-16 -2.42995e-16 + -4.43169e-17 2.61231e-17 2.77473e-16 -4.29794e-16 1.02358e-16 1.44165e-16 1.7274e-16 2.15008e-16 3.10763e-17 -1.15042e-16 2.53102e-16 2.11497e-16 + -2.47059e-16 -3.80188e-16 -1.15413e-16 -7.38707e-17 1.92338e-16 4.38314e-16 5.83186e-16 7.57316e-16 3.11359e-16 3.24772e-16 -2.12432e-16 -1.64862e-16 + 1.36583e-16 -2.30075e-16 1.69218e-16 -3.53552e-16 -9.86132e-17 -1.85825e-16 4.77577e-16 9.71063e-17 -4.54856e-16 -3.731e-16 -4.86113e-16 -2.43896e-16 + -2.2995e-16 1.68546e-16 -3.05937e-16 -1.69589e-16 1.25982e-16 1.96585e-16 5.11342e-16 3.95314e-16 -1.82194e-18 -2.77611e-16 2.50408e-16 1.59038e-16 + 4.50457e-16 1.59619e-16 2.00951e-16 -5.75926e-16 -1.00784e-15 -2.90101e-16 -6.94557e-17 -2.32214e-16 -5.37299e-16 -1.02399e-16 1.81252e-16 -1.3159e-16 + -4.06363e-16 -4.61057e-16 -9.20451e-17 -1.7296e-16 4.13821e-16 2.13315e-16 -3.30724e-16 2.6408e-16 -4.32307e-17 1.56727e-16 -7.17274e-17 4.72805e-16 + -7.71382e-17 1.72132e-16 -1.14619e-16 -4.42485e-17 7.68592e-17 -1.27298e-16 3.75262e-16 2.27148e-16 -7.05276e-17 -2.55387e-16 4.75687e-17 1.32347e-16 + 1.41029e-16 3.0069e-16 -2.15879e-16 -1.1298e-16 -5.24695e-16 -2.48786e-16 -1.75101e-16 -2.5789e-16 5.87187e-16 -7.04277e-17 3.14389e-17 2.55829e-16 + -1.0314e-16 -5.25303e-16 -6.50115e-16 -3.79811e-16 -5.70051e-16 -1.54089e-16 -9.1372e-17 -1.2632e-16 3.35129e-16 4.29523e-18 -4.51065e-18 1.29576e-16 + -2.08496e-16 2.30079e-16 1.7614e-16 1.82666e-16 2.95723e-17 -6.14835e-17 1.15028e-16 4.17783e-16 2.26212e-16 1.52849e-16 6.08093e-17 -1.70833e-16 + 1.10685e-16 -7.11818e-17 -2.50086e-16 -4.63169e-16 2.38523e-17 9.62299e-17 -3.18231e-16 -1.82735e-18 -4.10463e-16 1.12365e-16 6.35916e-17 3.54476e-16 + -2.17616e-16 -5.24324e-17 -8.33958e-17 9.03403e-17 -5.16541e-16 4.96346e-16 -7.98901e-19 3.80828e-16 2.66524e-16 1.35852e-16 -3.12294e-16 -1.96326e-16 + -1.11894e-16 8.59148e-17 2.03705e-16 3.4031e-16 -3.11608e-17 6.25281e-17 1.76059e-17 7.14761e-17 -9.99298e-17 1.45592e-16 -6.30121e-17 -1.65885e-16 + -1.33952e-16 2.26978e-17 5.61474e-16 3.825e-16 2.44805e-16 2.23048e-16 4.59726e-16 3.04587e-16 1.07113e-16 1.91196e-16 2.72646e-16 3.00632e-16 + 1.95932e-16 -1.06674e-17 8.08095e-17 -2.51332e-16 2.18193e-16 -3.15902e-17 -2.1425e-16 3.3981e-17 -3.67834e-16 -1.3933e-16 -6.31117e-17 4.2761e-16 + 3.52445e-16 3.85996e-16 1.71558e-16 2.87953e-16 2.68589e-16 2.46428e-16 4.52559e-16 4.32649e-16 1.82719e-16 3.50308e-16 4.26233e-16 1.86448e-16 + 1.79935e-16 3.83226e-16 3.17592e-16 1.7619e-16 -4.48419e-16 -1.19032e-17 3.47792e-16 3.68095e-17 -8.64623e-17 1.7229e-17 -1.55279e-17 5.06066e-16 + 3.18603e-16 3.76783e-17 -4.75118e-17 1.79183e-17 8.23516e-18 -1.95306e-16 -1.77298e-17 1.92776e-16 1.38782e-16 -1.39349e-16 3.07767e-17 4.60389e-17 + 5.6078e-17 -2.20302e-16 -6.59179e-16 2.30208e-16 5.78537e-17 1.09035e-16 -3.16833e-16 -6.0218e-16 -5.65703e-16 1.58482e-16 -5.27533e-17 1.16803e-16 + -6.46085e-16 8.64406e-17 -2.71825e-16 3.1753e-16 1.73778e-16 3.03571e-16 4.58083e-16 9.7519e-17 1.03154e-16 1.17703e-17 1.70439e-16 4.37413e-16 + -9.58291e-17 5.74961e-17 1.13517e-16 -8.46872e-17 -3.22247e-17 -5.32333e-17 -2.30867e-16 -4.59774e-16 -3.39424e-16 7.69778e-17 3.60611e-16 5.61698e-16 + -4.03689e-16 2.94878e-17 -1.49279e-17 2.6907e-16 2.34787e-16 5.76657e-17 -2.96206e-16 8.90449e-17 -6.31343e-17 1.85558e-16 -4.72243e-17 -1.0135e-16 + -1.49547e-16 -1.56075e-16 1.92422e-17 1.06044e-16 -4.34253e-16 -2.70648e-16 4.88418e-17 3.49938e-17 2.63071e-16 1.8551e-17 4.03733e-17 -2.50578e-16 + -1.72016e-17 -3.3202e-17 -2.71709e-17 -8.04865e-17 3.13043e-16 -2.94464e-16 -1.92914e-16 -3.74422e-16 -4.14057e-16 2.03777e-17 2.01416e-16 2.63979e-16 + 5.15175e-16 4.02597e-17 8.38615e-17 -1.00514e-16 1.78475e-16 -3.89558e-16 -9.13001e-17 -2.05135e-16 1.48961e-16 2.36373e-16 1.21385e-16 2.12375e-16 + 1.12982e-16 1.91655e-17 -1.77248e-16 -1.88728e-17 -1.44928e-17 2.25595e-16 -2.24742e-16 -9.04408e-17 4.05559e-17 -1.4684e-16 -3.81823e-16 -3.46675e-16 + -2.13498e-16 -6.79948e-17 3.40028e-17 1.70507e-16 1.26353e-16 5.04284e-16 -2.51862e-16 -5.54082e-17 3.76016e-16 -1.78378e-16 1.16754e-16 2.66977e-16 + -1.27945e-16 1.99835e-16 -3.30406e-17 -3.07313e-16 5.83998e-16 5.39753e-17 -1.94672e-16 -8.2499e-17 -2.72984e-16 -1.95976e-16 2.95113e-16 -2.20519e-16 + 1.47474e-16 -3.76149e-17 -1.91211e-16 -1.58129e-16 -4.31506e-17 -2.8297e-16 -1.79918e-16 -7.55504e-17 3.10588e-16 8.1334e-17 -3.55294e-16 2.10958e-16 + -5.22415e-16 -2.02288e-16 2.66525e-16 -7.79197e-17 -2.36194e-16 -2.84553e-16 -1.4739e-16 3.40534e-17 5.85503e-17 1.18344e-16 1.14829e-16 -1.20751e-16 + -6.28707e-17 -2.89639e-17 3.38862e-16 -2.47396e-16 5.40621e-16 2.87018e-16 1.27116e-16 -5.80594e-17 3.16703e-18 2.75508e-16 -2.28351e-16 1.73393e-16 + 1.40582e-16 -2.5402e-16 4.94659e-18 3.81743e-17 -9.91789e-17 3.41793e-16 8.85636e-17 5.68503e-17 4.50714e-17 1.37521e-16 -1.26799e-16 1.265e-16 + 7.48771e-17 -4.9605e-17 5.56383e-17 2.62636e-16 -2.92406e-17 3.13615e-16 4.36107e-17 -8.9836e-17 -2.01391e-16 -8.96228e-17 -2.78907e-16 6.83254e-17 + -7.1283e-17 2.74547e-16 -4.86063e-17 -3.46257e-16 2.74652e-16 3.6929e-17 3.54283e-16 2.07805e-17 9.97375e-17 2.89945e-17 -5.47317e-17 2.12882e-16 + 6.64924e-17 2.37118e-16 -2.85444e-17 -1.40193e-16 -3.71724e-16 -1.45695e-16 5.55945e-17 1.98117e-16 3.3238e-17 2.51065e-16 1.66367e-16 -1.75578e-16 + -9.33547e-17 3.82787e-16 3.64436e-16 2.02846e-16 2.98836e-16 3.75272e-16 -1.14379e-17 8.36898e-17 -2.70853e-16 1.98469e-17 7.9938e-17 -3.19569e-16 + -3.23262e-16 -3.90144e-16 3.46094e-16 -9.18619e-18 1.70378e-16 3.70432e-16 2.61703e-16 1.32655e-16 -2.72657e-16 -1.18806e-16 8.58973e-17 -2.05851e-16 + -1.27302e-16 3.3294e-16 -8.59661e-17 1.32695e-16 3.93072e-16 5.80151e-16 -9.50818e-17 2.96599e-16 -2.43288e-16 8.90839e-17 -9.30768e-17 3.3292e-16 + 3.88394e-16 1.71662e-16 1.89188e-17 4.17946e-17 1.79001e-16 3.20192e-16 -1.1076e-16 -2.99079e-16 -3.21149e-16 7.68437e-17 -4.35747e-16 6.1473e-17 + -2.18404e-16 2.83058e-16 6.0601e-16 -2.87491e-17 -3.30185e-16 -3.2756e-16 1.78734e-16 -8.59587e-17 -2.37825e-16 -1.3055e-16 -5.14101e-16 -2.06633e-16 + -1.56723e-16 -2.96835e-17 -1.2505e-16 8.76138e-17 2.86914e-18 -5.63556e-17 -1.67448e-16 -2.41282e-16 1.6362e-17 9.96801e-17 -9.352e-18 1.35833e-16 + -6.9101e-17 2.7394e-16 5.77979e-17 -2.89611e-16 2.34587e-17 -1.66313e-16 4.0433e-17 -1.80777e-16 -1.51119e-16 1.00713e-16 1.38768e-16 1.34271e-16 + 2.60038e-16 3.04292e-16 8.10239e-17 3.86537e-17 -2.0483e-16 -8.33311e-17 9.15456e-18 7.25852e-17 -1.98036e-16 -6.33931e-17 2.23274e-16 -3.49971e-16 + -1.42364e-16 -2.7757e-16 2.17253e-16 3.82403e-16 -3.0233e-16 2.49494e-16 2.00825e-16 1.80119e-16 7.1974e-18 -2.80256e-16 -1.71017e-16 -3.69033e-16 + 1.50362e-16 1.51994e-16 8.73746e-17 8.52202e-17 -5.00031e-17 -1.34797e-16 -2.64127e-17 -7.33737e-17 2.52851e-16 -3.70041e-16 -2.90915e-16 2.05118e-16 + 2.10533e-17 -1.7101e-16 -1.67621e-17 4.99314e-16 4.35571e-17 -1.0241e-16 -2.99449e-16 -6.76226e-17 3.89157e-16 -1.60344e-17 2.70766e-17 -4.39166e-16 + -1.70615e-16 1.87173e-16 -1.10016e-16 -3.76414e-17 -5.65532e-17 1.11287e-16 -1.39522e-16 2.09309e-16 2.4893e-16 -4.69741e-17 2.21061e-16 -2.77734e-16 + -1.0012e-16 -1.30489e-16 -1.55546e-16 3.20719e-16 -3.95081e-16 -2.18891e-16 -4.11257e-17 2.7396e-16 -2.05473e-17 7.14753e-17 -7.30499e-17 1.75818e-17 + 3.85438e-16 3.3013e-17 3.24007e-16 2.31423e-16 9.39123e-17 -1.15748e-16 -1.83818e-16 -3.28298e-16 2.31821e-16 2.63624e-17 1.12023e-17 -2.21323e-16 + -9.32403e-17 -1.13897e-17 -4.90234e-17 -1.05657e-16 2.39327e-16 9.48663e-17 -4.1003e-16 1.39184e-16 7.85926e-17 -2.28266e-16 -8.57065e-17 -1.24777e-16 + -1.23097e-16 -1.97304e-16 -1.79486e-16 4.21964e-17 -5.64425e-17 -4.97448e-16 3.75058e-16 5.14946e-17 -6.81333e-17 -1.6419e-16 -2.18272e-17 2.52815e-16 + 3.2702e-17 -1.8188e-16 -1.87506e-16 -2.02046e-17 -9.10543e-17 -4.81321e-16 -4.80231e-16 -5.69878e-16 -2.90525e-16 1.22575e-16 -4.31993e-16 1.89185e-17 + -1.48638e-16 -1.98999e-16 5.76574e-17 1.6643e-16 2.2952e-16 -2.72806e-17 1.71592e-16 6.45778e-17 -3.63262e-16 -5.04034e-16 -2.60956e-17 -6.08713e-18 + -2.19326e-16 4.99501e-16 -1.64391e-17 4.61977e-16 3.89749e-16 1.13404e-16 -2.19259e-16 -1.02079e-16 5.34338e-17 -7.61958e-17 -1.82277e-16 -3.50292e-16 + 3.93249e-16 3.95503e-17 1.63285e-16 2.16004e-16 -2.72643e-16 1.96789e-17 -2.32399e-16 -1.82979e-16 -1.10474e-16 -6.6047e-17 1.58071e-16 -1.13609e-16 + 1.19357e-16 -1.2866e-16 1.35137e-16 -2.03898e-16 1.74119e-17 -1.2044e-16 4.02386e-16 -1.15676e-16 -1.21631e-16 -3.4331e-17 2.51647e-16 1.10679e-16 + -1.85259e-16 -1.94747e-16 1.99413e-16 3.14458e-16 1.49774e-16 3.03173e-16 1.90172e-16 -6.49185e-17 2.83419e-17 -2.01253e-16 -2.54425e-16 -1.94368e-16 + -7.47537e-17 -1.06312e-16 6.41279e-18 -1.90456e-16 -2.82108e-17 -2.4948e-17 -1.10915e-16 3.06383e-16 2.29899e-16 1.19493e-16 3.72077e-16 5.64878e-17 + -1.19399e-16 5.70925e-17 3.36004e-16 -5.08722e-16 2.75206e-16 7.21188e-17 -1.39271e-16 -1.06661e-16 -9.82105e-17 -3.90245e-16 -2.82074e-16 5.57214e-17 + -7.41327e-17 -3.51886e-16 2.02449e-16 -1.71387e-16 -5.17722e-18 2.06724e-16 -2.82083e-16 1.81185e-16 -2.59984e-16 -1.82545e-16 -5.87356e-16 -5.35666e-16 + -1.81556e-16 8.12904e-17 2.21112e-16 -1.41591e-16 -2.29894e-16 -7.39839e-17 3.9426e-16 1.97262e-16 -2.27985e-16 -2.42184e-16 1.48198e-16 3.88718e-16 + -1.66522e-16 -1.30508e-16 2.11237e-18 1.08871e-17 -1.44805e-16 9.28245e-17 -2.64786e-17 -5.89664e-17 -3.4659e-16 -2.98738e-16 5.15854e-16 1.39823e-16 + 2.9531e-18 8.80033e-17 -1.0489e-16 -2.93513e-16 8.73671e-17 2.4979e-16 -1.52052e-16 5.14968e-16 -2.32708e-16 1.44465e-16 5.43725e-17 2.94546e-16 + 6.706e-18 -1.95949e-17 -5.89581e-17 1.20823e-16 9.9995 9.9985 9.9975 9.9965 9.9955 9.9945 9.9935 9.9925 9.9915 9.9905 9.9895 9.9885 -- GitLab From cb8406c976352bdd9ddec1a963ca28a486056943 Mon Sep 17 00:00:00 2001 From: Ned Coltman Date: Wed, 22 Apr 2020 15:23:04 +0000 Subject: [PATCH 14/57] Merge branch 'fix/compiler-error-precond-dune27' into 'master' [linear][seqsolverbacked] Fix compilation error for dune-2.7 related to solveWithParamTree See merge request dumux-repositories/dumux!2025 (cherry picked from commit 9dcf7b6a070cad82b17600a5666f399853bf28be) 78c49f18 [linear][seqsolverbacked] Fix compilation error for dune-2.7 related to solveWithParamTree --- dumux/linear/seqsolverbackend.hh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dumux/linear/seqsolverbackend.hh b/dumux/linear/seqsolverbackend.hh index 00db276e88..c6e83fbc9c 100644 --- a/dumux/linear/seqsolverbackend.hh +++ b/dumux/linear/seqsolverbackend.hh @@ -158,12 +158,15 @@ public: static bool solveWithParamTree(const Matrix& A, Vector& x, const Vector& b, const Dune::ParameterTree& params) { - // make a linear operator from a matrix using MatrixAdapter = Dune::MatrixAdapter; const auto linearOperator = std::make_shared(A); +#if DUNE_VERSION_GT(DUNE_ISTL,2,7) auto precond = std::make_shared(linearOperator, params.sub("preconditioner")); +#else + auto precond = std::make_shared(A, params.sub("preconditioner")); +#endif Solver solver(linearOperator, precond, params); Vector bTmp(b); -- GitLab From cc4dc2b46029f3cd4e9898a8c6ee52c7a3e4e051 Mon Sep 17 00:00:00 2001 From: Ned Coltman Date: Wed, 22 Apr 2020 12:55:30 +0200 Subject: [PATCH 15/57] [parameters][mpfa] capitalize parameter group MPFA and deprecate --- dumux/common/parameters.hh | 3 +- .../cellcentered/mpfa/fvelementgeometry.hh | 34 +++++++++++++++++-- .../cellcentered/mpfa/fvgridgeometry.hh | 17 +++++++++- 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/dumux/common/parameters.hh b/dumux/common/parameters.hh index 9dee178993..e0ecb56027 100644 --- a/dumux/common/parameters.hh +++ b/dumux/common/parameters.hh @@ -331,7 +331,8 @@ private: defaultParams["Vtk.AddProcessRank"] = "true"; // parameters in the mpfa group - defaultParams["Mpfa.Q"] = "0.0"; + defaultParams["Mpfa.Q"] = "0.0"; // DEPRECATED, REMOVE AFTER 3.2 + defaultParams["MPFA.Q"] = "0.0"; // merge the global default tree but do not overwrite if the parameter already exists mergeTree_(params, defaultParams, false); diff --git a/dumux/discretization/cellcentered/mpfa/fvelementgeometry.hh b/dumux/discretization/cellcentered/mpfa/fvelementgeometry.hh index b4e0d84987..498edc6520 100644 --- a/dumux/discretization/cellcentered/mpfa/fvelementgeometry.hh +++ b/dumux/discretization/cellcentered/mpfa/fvelementgeometry.hh @@ -343,7 +343,22 @@ private: const auto& neighborVolVarIndices = gridGeometry().neighborVolVarIndices(eIdx); // the quadrature point parameterizaion to be used on scvfs - static const auto q = getParam("Mpfa.Q"); + static const auto q = []{ // REMOVE deprecated version after release 3.2 + CoordScalar q = 0.0; + bool hasOldParamName = hasParam("Mpfa.Q"); + if (hasOldParamName) { + std::cerr << "Deprecation warning: Parameter Mpfa.Q is deprecated, use MPFA.Q (uppercase MPFA)" << std::endl; + q = getParam("Mpfa.Q"); + } + bool hasNewParamName = hasParam("MPFA.Q"); + if (hasNewParamName) { + q = getParam("MPFA.Q"); + } + if (hasOldParamName | hasNewParamName) + return q; + else + return getParam("MPFA.Q"); + }(); // reserve memory for the scv faces const auto numLocalScvf = scvFaceIndices.size(); @@ -430,7 +445,22 @@ private: const auto& neighborVolVarIndices = gridGeometry().neighborVolVarIndices(eIdxGlobal); // the quadrature point parameterizaion to be used on scvfs - static const auto q = getParam("Mpfa.Q"); + static const auto q = []{ // REMOVE deprecated version after release 3.2 + CoordScalar q = 0.0; + bool hasOldParamName = hasParam("Mpfa.Q"); + if (hasOldParamName) { + std::cerr << "Deprecation warning: Parameter Mpfa.Q is deprecated, use MPFA.Q (uppercase MPFA)" << std::endl; + q = getParam("Mpfa.Q"); + } + bool hasNewParamName = hasParam("MPFA.Q"); + if (hasNewParamName) { + q = getParam("MPFA.Q"); + } + if (hasOldParamName | hasNewParamName) + return q; + else + return getParam("MPFA.Q"); + }(); // for network grids we only want to do one scvf per half facet // this approach assumes conforming grids at branching facets diff --git a/dumux/discretization/cellcentered/mpfa/fvgridgeometry.hh b/dumux/discretization/cellcentered/mpfa/fvgridgeometry.hh index 70131a9314..9f6f851b9f 100644 --- a/dumux/discretization/cellcentered/mpfa/fvgridgeometry.hh +++ b/dumux/discretization/cellcentered/mpfa/fvgridgeometry.hh @@ -278,7 +278,22 @@ public: secondaryInteractionVolumeVertices_[vIdxGlobal] = true; // the quadrature point parameterizarion to be used on scvfs - static const auto q = getParam("Mpfa.Q"); + static const auto q = []{ // REMOVE deprecated version after release 3.2 + CoordScalar q = 0.0; + bool hasOldParamName = hasParam("Mpfa.Q"); + if (hasOldParamName) { + std::cerr << "Deprecation warning: Parameter Mpfa.Q is deprecated, use MPFA.Q (uppercase MPFA)" << std::endl; + q = getParam("Mpfa.Q"); + } + bool hasNewParamName = hasParam("MPFA.Q"); + if (hasNewParamName) { + q = getParam("MPFA.Q"); + } + if (hasOldParamName | hasNewParamName) + return q; + else + return getParam("MPFA.Q"); + }(); // make the scv face (for non-boundary scvfs on network grids, use precalculated outside indices) const auto& outsideScvIndices = [&] () -- GitLab From 82518f1751baac2c85e57df351ac3a38d965c822 Mon Sep 17 00:00:00 2001 From: Ned Coltman Date: Wed, 22 Apr 2020 12:57:05 +0200 Subject: [PATCH 16/57] [parameterlist] cleanup parameterlist.txt for release 3.2 --- bin/doc/compareparameters.sh | 6 ++--- doc/doxygen/extradoc/parameterlist.txt | 34 ++++++++++++++------------ 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/bin/doc/compareparameters.sh b/bin/doc/compareparameters.sh index 920c910db6..3b95867353 100755 --- a/bin/doc/compareparameters.sh +++ b/bin/doc/compareparameters.sh @@ -114,7 +114,7 @@ sort -u old_parameters.csv -o old_parameters.csv # 3. compare lists of old and new parameters # treat additions diff -u old_parameters.csv new_parameters.csv | grep -E "^\+" | grep -v "\++" >added.csv -if [[ -s added.csv ]]; then +if [ -s "added.csv" ]; then echo "" echo "Compared to parameterlist.txt, the following parameters have been _added_:" echo "" @@ -131,7 +131,7 @@ if [[ -s added.csv ]]; then fi # treat deletions diff -u old_parameters.csv new_parameters.csv | grep -E "^\-" | grep -v "\--" >deleted.csv -if [[ -s deleted.csv ]]; then +if [ -s "deleted.csv" ]; then echo "" echo "Compared to parameterlist.txt, the following parameters have been _deleted_:" echo "" @@ -146,7 +146,7 @@ if [[ -s deleted.csv ]]; then echo "their name. If so, delete the corresponding rows in doc/doxygen/extradoc/parameterlist.txt." fi # final remark -if [[ ! -s added.csv && ! -s deleted.csv ]]; then +if [ ! -s "added.csv" && ! -s "deleted.csv" ]; then echo "" echo "Compared to parameterlist.txt, no parameters have been added or deleted." echo "" diff --git a/doc/doxygen/extradoc/parameterlist.txt b/doc/doxygen/extradoc/parameterlist.txt index 48a55c6b2c..57ac8ab96c 100644 --- a/doc/doxygen/extradoc/parameterlist.txt +++ b/doc/doxygen/extradoc/parameterlist.txt @@ -12,10 +12,9 @@ * | :- | :- | :- | :- | :- | * | - | ParameterFile | std::string| executable.input | name of the parameter file | * | \b Adaptive | BCRefinementThreshold | Scalar | 1e-10 | | -Adaptive | MaxLevel | std::size_t | 0 | | +* | | MaxLevel | std::size_t | 0 | | * | \b Assembly | NumericDifference.BaseEpsilon | Scalar | 1e-10 | | * | | NumericDifferenceMethod | int | | | -* | | NumericDifferenceMethod | int | | | * | | NumericDifference.PriVarMagnitude | NumEqVector(-1) | | | * | \b BinaryCoefficients | GasDiffCoeff | Scalar | | | * | | LiquidDiffCoeff | Scalar | | | @@ -47,9 +46,14 @@ Adaptive | MaxLevel | std::size_t | 0 | | * | | ThermoneutralVoltage | Scalar | | | * | | TransferCoefficient | Scalar | | | * | | TransportNumberH20 | Scalar | | | +* | \b FacetCoupling | Xi | Scalar | 1.0 | | * | \b Flux | DifferencingScheme | std::string | Minmod | | * | | TvdApproach | std::string | Uniform | | * | | UpwindWeight | Scalar | | | +* | \b FluxLimiterLET | LowerWaterDepth | Scalar | 1e-5 | | +* | | UpperWaterDepth | Scalar | 1e-3 | | +* | | UpwindFluxLimiting | bool | false | | +* | \b FluxOverSurface | Verbose | bool | false | | * | \b Forchheimer | MaxIterations | std::size_t | 30 | | * | | NewtonTolerance | Scalar | 1e-12 | | * | \b FreeFlow | EnableUnsymmetrizedVelocityGradient | bool | false | | @@ -101,8 +105,6 @@ Adaptive | MaxLevel | std::size_t | 0 | | * | | UpperRight | GlobalPosition | | | * | | Verbosity | bool | false | | * | | WellRadius | Scalar | | | -* | | WriteSubGridToDGF | bool | false) | | -* | | WriteSubGridToVtk | bool | false) | | * | \b Impet | CFLFactor | Scalar | | | * | | DtVariationRestrictionFactorstd::numeric_limits | | | * | | FacePriVarNames | std::vector | | | * | | PriVarNames | std::vector | | | +* | \b MatrixConverter | DeletePatternEntriesBelowAbsThreshold | Scalar | -1.0 | | * | \b MixedDimension | IntegrationOrder | int | 1 | | * | | KernelWidth | Scalar | | | * | | NumCircleSegments | int | | | @@ -165,11 +172,10 @@ Adaptive | MaxLevel | std::size_t | 0 | | * | | TargetSteps | int | | | * | | UseLineSearch | bool | | | * | | Verbosity | int | 2 | | +* | \b PrimaryVariableSwitch | Verbosity | int | 1 | | * | \b Problem | EnableGravity | bool | | | -* | | EnableGravity | bool | | | * | | EnableInertiaTerms | bool | | | * | | Name | std::string | | | -* | | Name | std::string | | | * | | UsePrimaryVariableSwitch | bool | | | * | \b RANS | EddyViscosityModel | std::string | vanDriest | | * | | FlowNormalAxis | int | -1 | | @@ -190,8 +196,6 @@ Adaptive | MaxLevel | std::size_t | 0 | | * | | SubTimestepVerbosity | int | | | * | | TEnd | Scalar | | | * | \b Vtk | AddProcessRank | bool | | | -* | | AddProcessRank | bool | | | -* | | AddVelocity | bool | | | * | | AddVelocity | bool | true | | * | | OutputLevel | int | | | * | | WriteFaceData | bool | false | | -- GitLab From a007db11351b72319a230399d523862517a566d4 Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Wed, 22 Apr 2020 15:53:18 +0000 Subject: [PATCH 17/57] Merge branch 'update/license' into 'master' [License] Update contributors list See merge request dumux-repositories/dumux!2026 (cherry picked from commit 82253d47e0c1f2987e19b824310f9d23feb982b2) 62acebc7 [License] Update contributors list --- LICENSE.md | 54 +++++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/LICENSE.md b/LICENSE.md index 41a80a3287..1bbd947640 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -6,70 +6,70 @@ Copyright holders | Year | Name | |------------|----------------------------| -| 2016-2019 | Sina Ackermann | +| 2016-2020 | Sina Ackermann | | 2010-2014 | Katherina Baber | | 2015-2018 | Martin Beck | -| 2013-2019 | Beatrix Becker | +| 2013-2020 | Beatrix Becker | | 2014 | Markus Blatt | | 2010 | Felix Bode | -| 2018 | Samuel Burbulla | +| 2018-2020 | Samuel Burbulla | | 2007-2011 | Yufei Cao | -| 2018-2019 | Edward 'Ned' Coltman | -| 2011-2019 | Holger Class | +| 2018-2020 | Edward 'Ned' Coltman | +| 2011-2020 | Holger Class | | 2008-2013 | Melanie Darcis | | 2008-2009 | Onur Dogan | +| 2015-2020 | Simon Emmert | | 2009-2011 | Karin Erbertseder | | 2009-2014 | Benjamin Faigle | | 2013-2018 | Thomas Fetzer | -| 2007-2019 | Bernd Flemisch | +| 2007-2020 | Bernd Flemisch | | 2007-2010 | Jochen Fritz | | 2015-2016 | Georg Futter | -| 2015-2019 | Dennis Gläser | -| 2012-2019 | Christoph Grüninger | -| 2016-2019 | Katharina Heck | +| 2015-2020 | Dennis Gläser | +| 2012-2020 | Christoph Grüninger | +| 2016-2020 | Katharina Heck | | 2017 | Rainer Helmig | -| 2015-2019 | Johannes Hommel | +| 2015-2020 | Johannes Hommel | | 2012-2015 | Vishal Jambhekar | | 2013-2014 | Muhammad Adil Javed | | 2012-2017 | Alexander Kissinger | -| 2013-2019 | Timo Koch | +| 2013-2020 | Timo Koch | +| 2020 | Tim Jupe | | 2017 | Kata Kurgyis | -| 2018-2019 | Theresa Kurz | +| 2018-2020 | Theresa Kurz | | 2008-2012 | Andreas Lauser | -| 2018 | Giuliano Lambardo | -| 2018-2019 | Melanie Lipp | -| 2018-2019 | Farid Mohammadi | +| 2018 | Giuliano Lombardo | +| 2018-2020 | Melanie Lipp | +| 2018-2020 | Farid Mohammadi | | 2008-2014 | Klaus Mosthaf | | 2009-2014 | Philipp Nuske | | 2014 | Mirka Papenheim | | 2013-2014 | Dominik Riesterer | | 2008 | Irina Rybak | -| 2019 | Samuel Scherrer | -| 2013-2019 | Martin Schneider | -| 2015-2019 | Simon Scholz | +| 2019-2020 | Samuel Scherrer | +| 2013-2020 | Martin Schneider | | 2009 | Anneli Schöniger | | 2015-2016 | Natalie Schröder | | 2010-2016 | Nicolas Schwenck | -| 2015-2019 | Gabriele Seitz | +| 2015-2020 | Gabriele Seitz | | 2018 | Lincoln Sherpa | | 2011 | Michael Sinsbeck | -| 2010,2019 | Leopold Stadler | +| 2010,2019-2020 | Leopold Stadler | | 2012-2014 | Alexandru Tatomir | -| 2019 | Martin Utz | +| 2013 | Katharina Türk | +| 2018-2020 | Martin Utz | | 2015-2017 | Larissa de Vries | | 2019 | Andrea Vescovini | -| 2013 | Katharina Türk | -| 2018 | Martin Utz | +| 2020 | Maziar Veyskarami | | 2010-2014 | Lena Walter | -| 2018-2019 | Felix Weinhardt | -| 2015-2019 | Kilian Weishaupt | +| 2018-2020 | Felix Weinhardt | +| 2015-2020 | Kilian Weishaupt | | 2010-2011 | David Werner | -| 2019 | Roman Winter | +| 2019-2020 | Roman Winter | | 2015 | Hao Wu | | 2008-2013 | Markus Wolff | | 2013 | Tianyuan Zheng | - License ------- -- GitLab From edc1079fb740321bc943ae1fd1dd96c7c645fbea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dennis=20Gl=C3=A4ser?= Date: Wed, 22 Apr 2020 15:18:36 +0000 Subject: [PATCH 18/57] Merge branch 'feature/examples-add-cover-image' into 'master' [examples] Add images for examples on main example page See merge request dumux-repositories/dumux!2023 (cherry picked from commit 6b8bbe6d4afc59bad09f9a1eae6676ee352dc923) 5f2cee94 [examples] Add images for examples on main example page --- examples/README.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/examples/README.md b/examples/README.md index cff9e3ed7c..1c8d47e7d7 100644 --- a/examples/README.md +++ b/examples/README.md @@ -5,6 +5,8 @@ The description in each folder (best viewed online by following the link) explai ### [:open_file_folder: Example 1: One-phase flow and tracer transport](1ptracer/README.md) + + +
+ In this example, we simulate tracer transport through a confined aquifer with a randomly distributed permeability field. We first solve the pressure field, compute the steady state flow field, and then solve the tracer transport equation. You learn how to @@ -15,8 +17,16 @@ You learn how to * compute the flow field from a pressure solution to pass to a tracer problem * solve an instationary tracer transport problem with a given flow field + +
Tracer result
+
+ ### [:open_file_folder: Example 2: Two-phase flow with infiltration and adaptive grid](2pinfiltration/README.md) + + +
+ In this example we model a soil contamination problem where DNAPL infiltrates a water-saturated porous medium (two-phase flow). The initial distribution of DNAPL is read in from a txt-file. The grid is adapitvely refined where DNAPL enters the domain, around the plume, and around an injection well. @@ -27,17 +37,40 @@ You learn how to * implement a problem with heterogenous material parameters * use adaptive grid refinement around the saturation front + +
2p result
+
+ ### [:open_file_folder: Example 3: Shallow water model](shallowwaterfriction/README.md) + + + +
+ The shallow water flow model is applied to simulate steady subcritical flow in a channel including a bottom friction model. You learn how to * solve a shallow water flow problem including bottom friction * computate and output (VTK) an analytical reference solution + +
swe result
+ ### [:open_file_folder: Example 4: Freeflow channel](freeflowchannel/README.md) + + + + +
+ In this example, we simulate a free flow between two plates in two dimensions. You learn how to * solve a free flow problem * set outflow boundary conditions in the free-flow context + + +
freeflow result
-- GitLab From 3cdb6bfdd02091ad5426649a3fb252f744c188ef Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Wed, 22 Apr 2020 15:48:36 +0000 Subject: [PATCH 19/57] Merge branch 'fix/test_2pncminni' into 'master' Fix/test 2pncminni Closes #870 See merge request dumux-repositories/dumux!2020 (cherry picked from commit 86abdfa9a4f87b69ff9271c9f35b331f96beff25) 9b567384 [test][2pncminni] increase runtime to test precipitation, use fixed time-step... --- .../implicit/nonisothermal/CMakeLists.txt | 4 +- .../2pncmin/implicit/nonisothermal/main.cc | 2 +- .../implicit/nonisothermal/params.input | 2 +- ...t_2pncminni_salinization_box-reference.vtu | 96 +++++++++---------- ..._2pncminni_salinization_tpfa-reference.vtu | 52 +++++----- 5 files changed, 78 insertions(+), 78 deletions(-) diff --git a/test/porousmediumflow/2pncmin/implicit/nonisothermal/CMakeLists.txt b/test/porousmediumflow/2pncmin/implicit/nonisothermal/CMakeLists.txt index 1acb84172c..e470be93f7 100644 --- a/test/porousmediumflow/2pncmin/implicit/nonisothermal/CMakeLists.txt +++ b/test/porousmediumflow/2pncmin/implicit/nonisothermal/CMakeLists.txt @@ -8,7 +8,7 @@ dumux_add_test(NAME test_2pncminni_salinization_box COMMAND ${CMAKE_SOURCE_DIR}/bin/testing/runtest.py CMD_ARGS --script fuzzy --files ${CMAKE_SOURCE_DIR}/test/references/test_2pncminni_salinization_box-reference.vtu - ${CMAKE_CURRENT_BINARY_DIR}/test_2pncminni_salinization_box-00035.vtu + ${CMAKE_CURRENT_BINARY_DIR}/test_2pncminni_salinization_box-00042.vtu --zeroThreshold {"velocity_liq \(m/s\)_0":1e-18,"velocity_gas \(m/s\)_0":1e-14} --command "${CMAKE_CURRENT_BINARY_DIR}/test_2pncminni_salinization_box -ParameterFile params.input -Problem.Name test_2pncminni_salinization_box") @@ -19,6 +19,6 @@ dumux_add_test(NAME test_2pncminni_salinization_tpfa COMMAND ${CMAKE_SOURCE_DIR}/bin/testing/runtest.py CMD_ARGS --script fuzzy --files ${CMAKE_SOURCE_DIR}/test/references/test_2pncminni_salinization_tpfa-reference.vtu - ${CMAKE_CURRENT_BINARY_DIR}/test_2pncminni_salinization_tpfa-00035.vtu + ${CMAKE_CURRENT_BINARY_DIR}/test_2pncminni_salinization_tpfa-00042.vtu --zeroThreshold {"velocity_liq \(m/s\)_0":1e-18,"velocity_gas \(m/s\)_0":1e-14} --command "${CMAKE_CURRENT_BINARY_DIR}/test_2pncminni_salinization_tpfa -ParameterFile params.input -Problem.Name test_2pncminni_salinization_tpfa") diff --git a/test/porousmediumflow/2pncmin/implicit/nonisothermal/main.cc b/test/porousmediumflow/2pncmin/implicit/nonisothermal/main.cc index e8602b480e..2fc5ace5ae 100644 --- a/test/porousmediumflow/2pncmin/implicit/nonisothermal/main.cc +++ b/test/porousmediumflow/2pncmin/implicit/nonisothermal/main.cc @@ -203,7 +203,7 @@ int main(int argc, char** argv) try timeLoop->reportTimeStep(); // set new dt as suggested by the newton solver - timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize())); + timeLoop->setTimeStepSize(2*timeLoop->timeStepSize()); } while (!timeLoop->finished()); diff --git a/test/porousmediumflow/2pncmin/implicit/nonisothermal/params.input b/test/porousmediumflow/2pncmin/implicit/nonisothermal/params.input index 67456e2cae..b8eecf0438 100644 --- a/test/porousmediumflow/2pncmin/implicit/nonisothermal/params.input +++ b/test/porousmediumflow/2pncmin/implicit/nonisothermal/params.input @@ -3,7 +3,7 @@ # Type "./test_2pncmin --help" for more information. [TimeLoop] -TEnd = 80000 # duration of the simulation [s] +TEnd = 150000 # duration of the simulation [s] DtInitial = 1 # initial time step size [s] MaxTimeStepSize = 5000 # maximum time step size diff --git a/test/references/test_2pncminni_salinization_box-reference.vtu b/test/references/test_2pncminni_salinization_box-reference.vtu index 6b0bbdd67f..36c01979bb 100644 --- a/test/references/test_2pncminni_salinization_box-reference.vtu +++ b/test/references/test_2pncminni_salinization_box-reference.vtu @@ -4,76 +4,76 @@ - 0.371978 0.371978 0.354838 0.354838 0.371978 0.354838 0.328172 0.328172 0.328172 0.315209 0.315209 0.315209 - 0.300496 0.300496 0.300496 0.284002 0.284002 0.284002 + 0.299191 0.299191 0.286588 0.286588 0.299191 0.286588 0.260171 0.260171 0.260171 0.177275 0.177275 0.177275 + 0.00321549 0.00321549 0.00321549 0.000284819 0.000284819 0.000284819 - 92441.6 92441.6 92339 92339 92441.6 92339 92142.7 92142.7 92142.7 92022.3 92022.3 92022.3 - 91852.6 91852.6 91852.6 91588.1 91588.1 91588.1 + 91839.3 91839.3 91641.7 91641.7 91839.3 91641.7 90755.8 90755.8 90755.8 82394.9 82394.9 82394.9 + 64731.8 64731.8 64731.8 64432.1 64432.1 64432.1 - 1012.93 1012.93 1012.93 1012.93 1012.93 1012.93 1012.94 1012.94 1012.94 1013.27 1013.27 1013.27 - 1021.12 1021.12 1021.12 1201.64 1201.64 1201.64 + 1012.46 1012.46 1012.46 1012.46 1012.46 1012.46 1012.56 1012.56 1012.56 1028.84 1028.84 1028.84 + 1438 1438 1438 1617.86 1617.86 1617.86 - 6.36547 6.36547 4.25166 4.25166 6.36547 4.25166 1.94604 1.94604 1.94604 1.20035 1.20035 1.20035 - 0.597675 0.597675 0.597675 0.112315 0.112315 0.112315 + 0.609129 0.609129 0.277404 0.277404 0.609129 0.277404 0.00925914 0.00925914 0.00925914 0 0 0 + 0 0 0 0 0 0 - 0.628022 0.628022 0.645162 0.645162 0.628022 0.645162 0.671828 0.671828 0.671828 0.684791 0.684791 0.684791 - 0.699504 0.699504 0.699504 0.715998 0.715998 0.715998 + 0.700809 0.700809 0.713412 0.713412 0.700809 0.713412 0.739829 0.739829 0.739829 0.822725 0.822725 0.822725 + 0.996785 0.996785 0.996785 0.999715 0.999715 0.999715 - 100002 100002 100002 100002 100002 100002 100002 100002 100002 100002 100002 100002 - 100002 100002 100002 100001 100001 100001 + 100006 100006 100006 100006 100006 100006 100006 100006 100006 100005 100005 100005 + 100003 100003 100003 100001 100001 100001 - 1.21011 1.21011 1.21011 1.21011 1.21011 1.21011 1.21009 1.21009 1.21009 1.21009 1.21009 1.21009 - 1.21011 1.21011 1.21011 1.21071 1.21071 1.21071 + 1.19519 1.19519 1.19518 1.19518 1.19519 1.19518 1.19516 1.19516 1.19516 1.19521 1.19521 1.19521 + 1.19708 1.19708 1.19708 1.19822 1.19822 1.19822 - 38092.6 38092.6 40506.3 40506.3 38092.6 40506.3 44380.7 44380.7 44380.7 46405.7 46405.7 46405.7 - 49201.4 49201.4 49201.4 52412.2 52412.2 52412.2 + 49026.4 49026.4 51475.9 51475.9 49026.4 51475.9 55187.2 55187.2 55187.2 55581.9 55581.9 55581.9 + 55581.6 55581.6 55581.6 55581.3 55581.3 55581.3 - 7560.15 7560.15 7662.69 7662.69 7560.15 7662.69 7858.89 7858.89 7858.89 7979.27 7979.27 7979.27 - 8148.98 8148.98 8148.98 8413.08 8413.08 8413.08 + 8166.38 8166.38 8363.88 8363.88 8166.38 8363.88 9249.78 9249.78 9249.78 17610.5 17610.5 17610.5 + 35271.3 35271.3 35271.3 35568.7 35568.7 35568.7 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 - 0.4 0.4 0.4 0.399881 0.399881 0.399881 + 0.39777 0.39777 0.39777 0.380004 0.380004 0.380004 - 0.993731 0.993731 0.993731 0.993731 0.993731 0.993731 0.993726 0.993726 0.993726 0.993572 0.993572 0.993572 - 0.989938 0.989938 0.989938 0.90155 0.90155 0.90155 + 0.993732 0.993732 0.993732 0.993732 0.993732 0.993732 0.993688 0.993688 0.993688 0.986133 0.986133 0.986133 + 0.759211 0.759211 0.759211 0.618053 0.618053 0.618053 - 1.69649e-05 1.69649e-05 1.69646e-05 1.69646e-05 1.69649e-05 1.69646e-05 1.69637e-05 1.69637e-05 1.69637e-05 1.69634e-05 1.69634e-05 1.69634e-05 - 1.6964e-05 1.6964e-05 1.6964e-05 1.69866e-05 1.69866e-05 1.69866e-05 + 1.58379e-05 1.58379e-05 1.58373e-05 1.58373e-05 1.58379e-05 1.58373e-05 1.58356e-05 1.58356e-05 1.58356e-05 1.58372e-05 1.58372e-05 1.58372e-05 + 1.59039e-05 1.59039e-05 1.59039e-05 1.5945e-05 1.5945e-05 1.5945e-05 - 0.00625221 0.00625221 0.00625235 0.00625235 0.00625221 0.00625235 0.00625695 0.00625695 0.00625695 0.00641114 0.00641114 0.00641114 - 0.0100447 0.0100447 0.0100447 0.0984327 0.0984327 0.0984327 + 0.0062518 0.0062518 0.00625191 0.00625191 0.0062518 0.00625191 0.00629582 0.00629582 0.00629582 0.0138512 0.0138512 0.0138512 + 0.240773 0.240773 0.240773 0.381931 0.381931 0.381931 - 55447.9 55447.9 55447.8 55447.8 55447.9 55447.8 55447.8 55447.8 55447.8 55447.1 55447.1 55447.1 - 55430.8 55430.8 55430.8 54633 54633 54633 + 55422.4 55422.4 55422.4 55422.4 55422.4 55422.4 55422.2 55422.2 55422.2 55387.3 55387.3 55387.3 + 51821.1 51821.1 51821.1 48357.9 48357.9 48357.9 - 0.0149482 0.0149482 0.014949 0.014949 0.0149482 0.014949 0.0149513 0.0149513 0.0149513 0.0149498 0.0149498 0.0149498 - 0.014896 0.014896 0.014896 0.0135666 0.0135666 0.0135666 + 0.0183873 0.0183873 0.0183893 0.0183893 0.0183873 0.0183893 0.0183946 0.0183946 0.0183946 0.0182571 0.0182571 0.0182571 + 0.0140581 0.0140581 0.0140581 0.0114462 0.0114462 0.0114462 - 0.985052 0.985052 0.985051 0.985051 0.985052 0.985051 0.985049 0.985049 0.985049 0.98505 0.98505 0.98505 - 0.985104 0.985104 0.985104 0.986433 0.986433 0.986433 + 0.981613 0.981613 0.981611 0.981611 0.981613 0.981611 0.981605 0.981605 0.981605 0.981743 0.981743 0.981743 + 0.985942 0.985942 0.985942 0.988554 0.988554 0.988554 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 - 42.0232 42.0232 42.0231 42.0231 42.0232 42.0231 42.0227 42.0227 42.0227 42.0226 42.0226 42.0226 - 42.0224 42.0224 42.0224 42.0221 42.0221 42.0221 + 41.5595 41.5595 41.5592 41.5592 41.5595 41.5592 41.5584 41.5584 41.5584 41.5581 41.5581 41.5581 + 41.5564 41.5564 41.5564 41.555 41.555 41.555 3 3 3 3 3 3 3 3 3 3 3 3 @@ -81,29 +81,29 @@ 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0.000118571 0.000118571 0.000118571 + 0.00222965 0.00222965 0.00222965 0.0199956 0.0199956 0.0199956 - 286.213 286.213 286.214 286.214 286.213 286.214 286.216 286.216 286.216 286.217 286.217 286.217 - 286.218 286.218 286.218 286.219 286.219 286.219 + 289.42 289.42 289.422 289.422 289.42 289.422 289.427 289.427 289.427 289.429 289.429 289.429 + 289.432 289.432 289.432 289.434 289.434 289.434 - 6.2062e-22 2.38488e-09 0 2.77889e-23 2.38488e-09 0 3.3719e-22 4.64329e-09 0 1.2838e-22 4.64329e-09 0 - -5.65042e-22 2.38488e-09 0 -8.04307e-23 4.64329e-09 0 -1.65664e-22 8.40667e-09 0 1.84071e-23 8.40667e-09 0 - 2.02478e-22 8.40667e-09 0 -4.30149e-23 1.0537e-08 0 7.05231e-23 1.0537e-08 0 1.84061e-22 1.0537e-08 0 - -1.11478e-22 1.10058e-08 0 -2.56098e-23 1.10058e-08 0 6.02583e-23 1.10058e-08 0 -4.8864e-23 1.08492e-08 0 - -2.27388e-23 1.08492e-08 0 3.38638e-24 1.08492e-08 0 + 3.36832e-23 9.99747e-10 0 1.63984e-23 9.99747e-10 0 3.02757e-23 2.00061e-09 0 4.723e-23 2.00061e-09 0 + -8.86399e-25 9.99747e-10 0 6.41844e-23 2.00061e-09 0 2.00221e-23 3.45295e-09 0 2.59977e-23 3.45295e-09 0 + 3.19734e-23 3.45295e-09 0 0 1.95222e-09 0 0 1.95222e-09 0 0 1.95222e-09 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 - 7.76048e-19 -2.41276e-09 0 -1.88469e-18 -2.41276e-09 0 3.35984e-18 -4.70999e-09 0 1.37046e-18 -4.70999e-09 0 - -4.54542e-18 -2.41276e-09 0 -6.18917e-19 -4.70999e-09 0 -4.16556e-18 -7.87067e-09 0 1.58227e-18 -7.87067e-09 0 - 7.3301e-18 -7.87067e-09 0 5.4845e-18 1.09612e-08 0 5.6702e-18 1.09612e-08 0 5.85591e-18 1.09612e-08 0 - 1.21162e-18 6.71232e-07 0 7.64283e-19 6.71232e-07 0 3.16942e-19 6.71232e-07 0 4.76578e-18 1.31181e-06 0 - -5.29865e-19 1.31181e-06 0 -5.82551e-18 1.31181e-06 0 + 4.42326e-18 -1.20144e-09 0 -1.28417e-18 -1.20144e-09 0 -4.1199e-18 -2.37317e-09 0 -2.32213e-18 -2.37317e-09 0 + -6.9916e-18 -1.20144e-09 0 -5.24351e-19 -2.37317e-09 0 4.21617e-18 6.30754e-08 0 2.7907e-18 6.30754e-08 0 + 1.36523e-18 6.30754e-08 0 -5.01388e-18 3.91591e-06 0 3.6163e-19 3.91591e-06 0 5.73714e-18 3.91591e-06 0 + -3.26934e-18 7.96185e-06 0 -9.26596e-19 7.96185e-06 0 1.41614e-18 7.96185e-06 0 -7.74071e-18 8.22157e-06 0 + -8.15862e-19 8.22157e-06 0 6.10899e-18 8.22157e-06 0 - 1e-13 1e-13 1e-13 1e-13 1e-13 1e-13 1e-13 1e-13 1e-13 1e-13 1e-13 1e-13 - 9.99679e-14 9.99679e-14 9.99679e-14 9.99037e-14 9.99037e-14 9.99037e-14 + 1e-13 1e-13 1e-13 1e-13 1e-13 1e-13 1e-13 1e-13 1e-13 9.93978e-14 9.93978e-14 9.93978e-14 + 9.30001e-14 9.30001e-14 9.30001e-14 8.43521e-14 8.43521e-14 8.43521e-14 diff --git a/test/references/test_2pncminni_salinization_tpfa-reference.vtu b/test/references/test_2pncminni_salinization_tpfa-reference.vtu index a6b7cceed9..15bb8f6031 100644 --- a/test/references/test_2pncminni_salinization_tpfa-reference.vtu +++ b/test/references/test_2pncminni_salinization_tpfa-reference.vtu @@ -4,83 +4,83 @@ - 0.362084 0.362084 0.340382 0.340382 0.316467 0.316467 0.301085 0.301085 0.282784 0.282784 + 0.292451 0.292451 0.272084 0.272084 0.23278 0.23278 0.00580009 0.00580009 0.000544176 0.000544176 - 92385.2 92385.2 92240.5 92240.5 92036 92036 91861.4 91861.4 91564.8 91564.8 + 91741.4 91741.4 91299.9 91299.9 88027 88027 64994.5 64994.5 64459.1 64459.1 - 1012.97 1012.97 1012.98 1012.98 1013.13 1013.13 1016.92 1016.92 1116.91 1116.91 + 1012.49 1012.49 1012.5 1012.5 1018.1 1018.1 1480.31 1480.31 1647.07 1647.07 - 5.0377 5.0377 2.83969 2.83969 1.25286 1.25286 0.616885 0.616885 0.148259 0.148259 + 0.410098 0.410098 0.0722886 0.0722886 0 0 0 0 0 0 - 0.637916 0.637916 0.659618 0.659618 0.683533 0.683533 0.698915 0.698915 0.717216 0.717216 + 0.707549 0.707549 0.727916 0.727916 0.76722 0.76722 0.9942 0.9942 0.999456 0.999456 - 100003 100003 100003 100003 100003 100003 100003 100003 100002 100002 + 100006 100006 100006 100006 100006 100006 100004 100004 100001 100001 - 1.21187 1.21187 1.21186 1.21186 1.21186 1.21186 1.21187 1.21187 1.21218 1.21218 + 1.19605 1.19605 1.19599 1.19599 1.19594 1.19594 1.19805 1.19805 1.19912 1.19912 - 39519.2 39519.2 42634 42634 46236.5 46236.5 49135.3 49135.3 52687.6 52687.6 + 50380.3 50380.3 53911.2 53911.2 55607.1 55607.1 55605.7 55605.7 55604.1 55604.1 - 7617.59 7617.59 7762.17 7762.17 7966.6 7966.6 8141.26 8141.26 8437.62 8437.62 + 8264.51 8264.51 8705.88 8705.88 11978.8 11978.8 35009.1 35009.1 35542.4 35542.4 - 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.398636 0.398636 0.388915 0.388915 - 0.993731 0.993731 0.99373 0.99373 0.993658 0.993658 0.991904 0.991904 0.944436 0.944436 + 0.993732 0.993732 0.993727 0.993727 0.991133 0.991133 0.729339 0.729339 0.591445 0.591445 - 1.71059e-05 1.71059e-05 1.71056e-05 1.71056e-05 1.71052e-05 1.71052e-05 1.71055e-05 1.71055e-05 1.71174e-05 1.71174e-05 + 1.58987e-05 1.58987e-05 1.58947e-05 1.58947e-05 1.58903e-05 1.58903e-05 1.59646e-05 1.59646e-05 1.60017e-05 1.60017e-05 - 0.00625227 0.00625227 0.00625305 0.00625305 0.00632463 0.00632463 0.00807839 0.00807839 0.0555471 0.0555471 + 0.00625181 0.00625181 0.00625667 0.00625667 0.00885087 0.00885087 0.270645 0.270645 0.408539 0.408539 - 55450.4 55450.4 55450.4 55450.4 55450 55450 55442.3 55442.3 55126.2 55126.2 + 55424.1 55424.1 55423.9 55423.9 55412.4 55412.4 51121.2 51121.2 47697.5 47697.5 - 0.0145878 0.0145878 0.0145886 0.0145886 0.0145886 0.0145886 0.0145633 0.0145633 0.0138667 0.0138667 + 0.0181726 0.0181726 0.0181866 0.0181866 0.0181571 0.0181571 0.0133691 0.0133691 0.0108492 0.0108492 - 0.985412 0.985412 0.985411 0.985411 0.985411 0.985411 0.985437 0.985437 0.986133 0.986133 + 0.981827 0.981827 0.981813 0.981813 0.981843 0.981843 0.986631 0.986631 0.989151 0.989151 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 - 42.0784 42.0784 42.0783 42.0783 42.0781 42.0781 42.078 42.078 42.0778 42.0778 + 41.586 41.586 41.5842 41.5842 41.5819 41.5819 41.5793 41.5793 41.5767 41.5767 3 3 3 3 3 3 3 3 3 3 - 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0.00136443 0.00136443 0.011085 0.011085 - 285.841 285.841 285.842 285.842 285.843 285.843 285.843 285.843 285.844 285.844 + 289.236 289.236 289.249 289.249 289.264 289.264 289.273 289.273 289.284 289.284 - 3.66541e-22 2.3556e-09 0 3.66541e-22 2.3556e-09 0 0 7.07054e-09 0 0 7.07054e-09 0 - 0 1.01265e-08 0 0 1.01265e-08 0 -4.48843e-23 1.11427e-08 0 -4.48843e-23 1.11427e-08 0 - -1.07872e-23 1.14623e-08 0 -1.07872e-23 1.14623e-08 0 + 2.98386e-23 1.00326e-09 0 2.98386e-23 1.00326e-09 0 0 3.46353e-09 0 0 3.46353e-09 0 + 0 2.46027e-09 0 0 2.46027e-09 0 0 0 0 0 0 0 + 0 -0 0 0 -0 0 - 2.8754e-18 -2.37119e-09 0 2.8754e-18 -2.37119e-09 0 0 -7.00426e-09 0 0 -7.00426e-09 0 - 0 -1.19549e-09 0 0 -1.19549e-09 0 -3.57506e-18 3.11109e-07 0 -3.57506e-18 3.11109e-07 0 - 0 6.15343e-07 0 0 6.15343e-07 0 + 3.66565e-18 -1.74459e-09 0 3.66565e-18 -1.74459e-09 0 3.92256e-18 2.02164e-09 0 3.92256e-18 2.02164e-09 0 + 0 3.28248e-06 0 0 3.28248e-06 0 -7.97287e-18 6.93547e-06 0 -7.97287e-18 6.93547e-06 0 + -3.58493e-18 7.31352e-06 0 -3.58493e-18 7.31352e-06 0 0 0 0 0 0 0 0 0 0 0 - 1e-13 1e-13 1e-13 1e-13 1e-13 1e-13 1e-13 1e-13 1e-13 1e-13 + 1e-13 1e-13 1e-13 1e-13 1e-13 1e-13 9.85315e-14 9.85315e-14 8.86102e-14 8.86102e-14 -- GitLab From afd9d5304ce6196c5ba688a17c458866748591d6 Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Wed, 22 Apr 2020 15:55:31 +0000 Subject: [PATCH 20/57] Merge branch 'cleanup/installscript' into 'master' Cleanup/installscript Closes #848 See merge request dumux-repositories/dumux!1965 (cherry picked from commit 7a6fd6d41d4e81b60f5f56f2842a2bab7088a6db) acaf8100 [install] move and modify installscript b0775e20 [install][handbook] Modify the description of the quick install 14914915 [install][external] Add install course and lecture as options 204468d5 [bin][install] Fix several issues with installdumux.sh script ed7e6247 [install] add check for existing cmake.opts file --- bin/installdumux.sh | 102 +++++++++++++++++++++++++++++ bin/installexternal.sh | 40 +++++++++++ bin/util/test_dumux.sh | 6 ++ doc/handbook/2_quickinstall.tex | 70 ++++++++++++++------ doc/handbook/4_course.tex | 3 +- doc/handbook/4_furtherpractice.tex | 6 +- doc/handbook/installDumux.sh | 44 ------------- 7 files changed, 202 insertions(+), 69 deletions(-) create mode 100755 bin/installdumux.sh create mode 100644 bin/util/test_dumux.sh delete mode 100644 doc/handbook/installDumux.sh diff --git a/bin/installdumux.sh b/bin/installdumux.sh new file mode 100755 index 0000000000..5956e07d3f --- /dev/null +++ b/bin/installdumux.sh @@ -0,0 +1,102 @@ +# One click install script for dumux +echo " " +echo " " +echo "*********************************************************************************************" +echo "(0/3) Checking all prerequistes. (git gcc g++ cmake pkg-config paraview)" +echo "*********************************************************************************************" + +# check some prerequistes +for PRGRM in wget git gcc g++ cmake pkg-config; do + if ! [ -x "$(command -v $PRGRM)" ]; then + echo "ERROR: $PRGRM is not installed." >&2 + exit 1 + fi +done + +if ! [ -x "$(command -v paraview)" ]; then + echo "*********************************************************************************************" + echo "WARNING: paraview seems to be missing. You may not be able to view simulation results!" >&2 + echo "*********************************************************************************************" +fi + +currentver="$(gcc -dumpversion)" +requiredver="7" +if [ "$(printf '%s\n' "$requiredver" "$currentver" | sort -V | head -n1)" != "$requiredver" ]; then + echo "gcc greater than or equal to $requiredver is required for dumux releases >=3.2!" >&2 + exit 1 +fi + +if [ $? -ne 0 ]; then + echo "*********************************************************************************************" + echo "(0/3) An error occured while checking for prerequistes." + echo "*********************************************************************************************" + exit $? +else + echo "*********************************************************************************************" + echo "(1/3) All prerequistes found." + echo "*********************************************************************************************" +fi + + +# make a new folder containing everything +mkdir -p $(pwd)/DUMUX +cd DUMUX + +echo "*********************************************************************************************" +echo "(1/3) Cloning repositories. This may take a while. Make sure to be connected to the internet." +echo "*********************************************************************************************" +DUNE_VERSION=2.7 +DUMUX_VERSION=3.2 +# the core modules +for MOD in common geometry grid localfunctions istl +do + if [ ! -d "dune-$MOD" ]; then + git clone -b releases/$DUNE_VERSION https://gitlab.dune-project.org/core/dune-$MOD.git + else + echo "Skip cloning dune-$MOD because the folder already exists." + fi +done + +# dumux +if [ ! -d "dumux" ]; then + git clone -b releases/$DUMUX_VERSION https://git.iws.uni-stuttgart.de/dumux-repositories/dumux.git +else + echo "Skip cloning dumux because the folder already exists." +fi + +if [ $? -ne 0 ]; then + echo "*********************************************************************************************" + echo "(1/3) Failed to clone the repositories. Look for repository specific errors." + echo "*********************************************************************************************" + exit $? +else + echo "*********************************************************************************************" + echo "(2/3) All repositories have been cloned into a containing folder." + echo "*********************************************************************************************" +fi + +echo " " + +echo "**************************************************************************************************" +echo "(2/3) Configure and build dune modules and dumux using dunecontrol. This may take several minutes." +echo "**************************************************************************************************" + +# run dunecontrol +if [ ! -f "cmake.opts" ]; then + wget https://git.iws.uni-stuttgart.de/dumux-repositories/dumux/-/raw/releases/3.2/cmake.opts +else + echo "A cmake.opts file already exists. The existing file will be used to configure dumux." +fi + +./dune-common/bin/dunecontrol --opts=cmake.opts all + +if [ $? -ne 0 ]; then + echo "*********************************************************************************************" + echo "(2/3) Failed to build the dune libaries." + echo "*********************************************************************************************" + exit $? +else + echo "*****************************************************************************************************" + echo "(3/3) Succesfully configured and built dune and dumux." + echo "*****************************************************************************************************" +fi diff --git a/bin/installexternal.sh b/bin/installexternal.sh index 9ffdbcb6ff..98d5da318d 100755 --- a/bin/installexternal.sh +++ b/bin/installexternal.sh @@ -10,6 +10,8 @@ DOWNLOAD_ONLY="n" TOPDIR=$(pwd) EXTDIR=$(pwd)/external +DUMUX_VERSION=3.2 + checkLocationForDuneModules() { # test for directory dune-common, dune-common-2.4 etc. @@ -53,6 +55,19 @@ installAluGrid() fi } +installCourse() +{ + cd $TOPDIR + if [ ! -d "dumux-course" ]; then + git clone -b releases/$DUMUX_VERSION https://git.iws.uni-stuttgart.de/dumux-repositories/dumux-course.git + else + echo "Skip cloning dumux-course because the folder already exists." + cd dumux-course + git checkout releases/$DUMUX_VERSION + cd .. + fi +} + installFoamGrid() { cd $TOPDIR @@ -135,6 +150,19 @@ installGStat() fi } +installLecture() +{ + cd $TOPDIR + if [ ! -d "dumux-lecture" ]; then + git clone -b releases/$DUMUX_VERSION https://git.iws.uni-stuttgart.de/dumux-repositories/dumux-lecture.git + else + echo "Skip cloning dumux-lecture because the folder already exists." + cd dumux-lecture + git checkout releases/$DUMUX_VERSION + cd .. + fi +} + installMETIS() { cd $EXTDIR @@ -404,9 +432,11 @@ usage() echo "Where PACKAGES is one or more of the following" echo " all Install everything and the kitchen sink." echo " alugrid Download dune-alugrid." + echo " course Download the dumux-course." echo " foamgrid Download dune-foamgrid." echo " glpk Download and install glpk." echo " gstat Download and install gstat." + echo " lecture Download the dumux-lecture." echo " metis Install the METIS graph partitioner." echo " multidomain Download dune-multidomain." echo " multidomaingrid Download and patch dune-multidomaingrid." @@ -471,9 +501,11 @@ for TMP in "$@"; do SOMETHING_DONE="y" createExternalDirectory installAluGrid + installCourse installFoamGrid installGLPK installGStat + installLecture installMETIS installMultidomain installMultidomainGrid @@ -487,6 +519,10 @@ for TMP in "$@"; do SOMETHING_DONE="y" installAluGrid ;; + course) + SOMETHING_DONE="y" + installCourse + ;; foamgrid|dune-foamgrid) SOMETHING_DONE="y" installFoamGrid @@ -501,6 +537,10 @@ for TMP in "$@"; do createExternalDirectory installGStat ;; + lecture) + SOMETHING_DONE="y" + installLecture + ;; metis) SOMETHING_DONE="y" createExternalDirectory diff --git a/bin/util/test_dumux.sh b/bin/util/test_dumux.sh new file mode 100644 index 0000000000..6a55344cb0 --- /dev/null +++ b/bin/util/test_dumux.sh @@ -0,0 +1,6 @@ +# Test to see if the download and configuration worked properly + +cd DUMUX/dumux/build-cmake/test/porousmediumflow/1p/implicit/isothermal +make test_1p_tpfa +./test_1p_tpfa params.input +paraview *pvd diff --git a/doc/handbook/2_quickinstall.tex b/doc/handbook/2_quickinstall.tex index 88656a8686..8f9e256f11 100644 --- a/doc/handbook/2_quickinstall.tex +++ b/doc/handbook/2_quickinstall.tex @@ -3,38 +3,68 @@ For this quick start guide the following software packages are required: \begin{itemize} \item GitLab client \item A standard-compliant C++17 compiler supporting the C++11/C++14/C++17 features of GCC 7 -(\Dumux $> 3.1$\footnote{\Dumux $\leq 3.1$ only requires the C++11/C++14 feature set of GCC 4.9, e.g. GCC 4.9 or newer and Clang 3.8 or newer}), -e.g. GCC 7 or newer and Clang 5 or newer. +(\Dumux $> 3.1$\footnote{\Dumux $\leq 3.1$ only requires the C++11/C++14 feature set of GCC 4.9, +e.g. GCC 4.9 or newer and Clang 3.8 or newer}), e.g. GCC 7 or newer and Clang 5 or newer. \item CMake 2.8.12 or newer \item pkg-config \item ParaView (to visualize the results) \end{itemize} \section{Obtaining code and configuring all modules with a script} -We provide you with a shell-script \texttt{installDumux.sh} that facilitates setting up a {\Dune}/{\Dumux} directory tree -and configures all modules with CMake. -Copy the following lines into a text file named \texttt{installDumux.sh}: -\lstinputlisting[style=DumuxCode, numbersep=5pt, firstline=1, firstnumber=1]{installDumux.sh} +To easily install Dumux, we've provided a shell-script \texttt{installdumux.sh} that facilitates +setting up a {\Dune}/{\Dumux} directory tree and configures all modules with CMake. +First, you will have to download this script. To do this, first navigate to the directory where you +want to install \Dumux and \Dune (a single root folder \texttt{DUMUX} will be produced, so you do +not need to provide one). Then use \texttt{wget} to download the script with the following command: +\begin{lstlisting}[style=Bash] +$ wget https://git.iws.uni-stuttgart.de/dumux-repositories/dumux/-/raw/releases/3.2/bin/installdumux.sh +\end{lstlisting} -Place the \texttt{installDumux.sh} script in the directory where you want to install \Dumux and \Dune (a single -root folder \texttt{DUMUX} will be produced, so you do not need to provide one). Make \texttt{installDumux.sh} executable and run the script by typing into the terminal: \texttt{./installDumux.sh} +After the download is complete, execute the script. This can be done with +\begin{lstlisting}[style=Bash] +$ sh installdumux.sh +\end{lstlisting} -Configuring \Dune and \Dumux is done by the command-line script \texttt{dunecontrol} -using optimized configure options, see the line entitled \texttt{\# run build} in the \texttt{installDumux.sh} script. +This script will download each of the \Dune-modules that \Dumux depends on at their 2.7 release, +as well as \Dumux's 3.2 release. After these individual modules are downloaded, \Dune and \Dumux +are automatically configured using the command-line script \texttt{dunecontrol}, located in +\texttt{dune-common/bin/dunecontrol}, optimized using configure options defined in the \texttt{cmake.opts} +file located in \texttt{dumux/cmake.opts}. The commands beneath the \texttt{\# run dunecontrol} in +the \texttt{installdumux.sh} script execute this configuration script, so no further steps are required. More details about the build-system can be found in section \ref{buildIt}. \subsection{A first test run of \Dumux} -When the \texttt{installDumux.sh} script from the subsection above has run successfully, you can execute a second script that -will compile and run a simple one-phase ground water flow example and will visualize the result using ParaView. -The test script can be obtained by copying the following lines into a text file named \texttt{test\_dumux.sh} -that has to be located in the same directory as the installation script. -\begin{lstlisting}[style=DumuxCode] +When the \texttt{installdumux.sh} script from the subsection above has run successfully, +you run a simple test to ensure that the installation ran correctly. To do this, you can +begin by compiling an example problem and running the simulation. You can then visualize +the results using ParaView. We recommend looking at a basic single phase groundwater flow problem. +\begin{enumerate} +\item Navigate to this test in the build directory using: +\begin{lstlisting}[style=Bash] cd DUMUX/dumux/build-cmake/test/porousmediumflow/1p/implicit/isothermal -make -B test_1p_tpfa +\end{lstlisting} +\item Build the executable with the following command: +\begin{lstlisting}[style=Bash] +make test_1p_tpfa +\end{lstlisting} +\item Run the simulation with the parameters listed in \texttt{params.input} like this: +\begin{lstlisting}[style=Bash] ./test_1p_tpfa params.input +\end{lstlisting} +\item Visualize the results in paraview with: +\begin{lstlisting}[style=Bash] paraview *pvd \end{lstlisting} -After making \texttt{test\_dumux.sh} executable, it can be executed by typing into the terminal: \texttt{./test\_dumux.sh}. -If everything works fine, a ParaView window with the result should open automatically, showing the initial -conditions. Advance ParaView to the next frame (green arrow button) and rescale to data range (green double arrow on top right) to admire -the colorful pressure distribution. +\item Advance ParaView to the next frame (green arrow button) and rescale to data range +(green double arrow on top right) to admire the colorful pressure distribution. +\end{enumerate} + +These commands are compiled into \texttt{test\_dumux.sh}, which you can download and run +from the same directory from which you ran \texttt{installDumux.sh}. + +\begin{lstlisting}[style=Bash] +$ wget https://git.iws.uni-stuttgart.de/dumux-repositories/dumux/-/raw/releases/3.2/bin/util/test_dumux.sh +$ wget sh test_dumux.sh +\end{lstlisting} + +For further information on how to get started with dumux, see Section \ref{chp:tutorial}. diff --git a/doc/handbook/4_course.tex b/doc/handbook/4_course.tex index 17016c5bbc..bb083fd8a9 100644 --- a/doc/handbook/4_course.tex +++ b/doc/handbook/4_course.tex @@ -25,7 +25,8 @@ $ wget https://git.iws.uni-stuttgart.de/dumux-repositories/dumux-course/raw/rele \end{lstlisting} This script will install \texttt{dumux}, it's Dune dependencies, and the \texttt{dumux-course} repository. Within the directory \texttt{dumux-course} there are a series of exercises -and slides describing the previously described examples. \par +and slides describing the previously described examples. The course can also be added to your existing +dumux installation using the \texttt{installExternal.sh} script and the argument \texttt{course}.\par % The \Dumux course will be updated with each \Dumux release. The above script will download the correct version (\textbf{releases/3.2}) of both diff --git a/doc/handbook/4_furtherpractice.tex b/doc/handbook/4_furtherpractice.tex index 76c6c31209..194781c9b6 100644 --- a/doc/handbook/4_furtherpractice.tex +++ b/doc/handbook/4_furtherpractice.tex @@ -9,10 +9,8 @@ cases can be found in the class documentation \url{http://www.dumux.org/document Another possibility to gain more experience with \Dumux is the \texttt{dumux-lecture} module that contains different application examples that are used in the lectures at the Department of Hydromechanics and Modelling of Hydrosystems in Stuttgart. -The \texttt{dumux-lecture} module can be obtained as follows: -\begin{lstlisting}[style=Bash] -$ git clone https://git.iws.uni-stuttgart.de/dumux-repositories/dumux-lecture.git -\end{lstlisting} +The \texttt{dumux-lecture} module can be obtained with the \texttt{installExternal.sh} +script and the argument \texttt{lecture}. The module is structured based on the different lectures: \begin{itemize} diff --git a/doc/handbook/installDumux.sh b/doc/handbook/installDumux.sh deleted file mode 100644 index fe06600aa2..0000000000 --- a/doc/handbook/installDumux.sh +++ /dev/null @@ -1,44 +0,0 @@ -# One click install script for dumux - -# make a new folder containing everything -mkdir $(pwd)/DUMUX -cd DUMUX - -echo "*************************************************" -echo "(1/2) Cloning repositories. This may take a while. -Make sure to be connected to the internet." -echo "*************************************************" -# the core modules -for MOD in common geometry grid localfunctions istl; do - git clone -b releases/2.6 https://gitlab.dune-project.org/core/dune-$MOD.git -done - -# dumux -git clone -b releases/3.1 https://git.iws.uni-stuttgart.de/dumux-repositories/dumux.git - -if [ $? -ne 0 ]; then - echo "*************************************************" - echo "Failed to clone the repositories." - echo "*************************************************" - exit $? -fi - -echo "*************************************************" -echo "(2/2) Configure dune modules and dumux. Build the -dune libaries. This may take several minutes." -echo "*************************************************" -# run build -./dune-common/bin/dunecontrol --opts=dumux/cmake.opts all -# -if [ $? -ne 0 ]; then - echo "*************************************************" - echo "Failed to build the dune libaries." - echo "*************************************************" - exit $? -fi - -# echo result -echo "*************************************************" -echo "Successfully configured and built dune and dumux." -echo "Please run the test_dumux.sh script to confirm everything works." -echo "*************************************************" -- GitLab From 644a86a2655db590aff471e1d953a9f7599fb38e Mon Sep 17 00:00:00 2001 From: Bernd Flemisch Date: Wed, 22 Apr 2020 18:29:22 +0200 Subject: [PATCH 21/57] [doc] fix CMakeLists.txt for the handbook --- doc/handbook/CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/handbook/CMakeLists.txt b/doc/handbook/CMakeLists.txt index 59083907c5..8c26c7e840 100644 --- a/doc/handbook/CMakeLists.txt +++ b/doc/handbook/CMakeLists.txt @@ -29,8 +29,7 @@ set(TEX_INPUTS 6_propertysystem.tex 6_spatialdiscretizations.tex 6_stepsofasimulation.tex - 6_temporaldiscretizations.tex - installDumux.sh) + 6_temporaldiscretizations.tex) set(TEX_IMAGES png/box_disc.png -- GitLab From bbbab3ad94a2e1f608e6144d7c50949c6be52f8c Mon Sep 17 00:00:00 2001 From: Bernd Flemisch Date: Wed, 22 Apr 2020 18:43:14 +0200 Subject: [PATCH 22/57] [doc] fix the handbook version to 3.2 --- doc/handbook/0_dumux-handbook.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/handbook/0_dumux-handbook.tex b/doc/handbook/0_dumux-handbook.tex index ecc2362996..4fe825e08a 100644 --- a/doc/handbook/0_dumux-handbook.tex +++ b/doc/handbook/0_dumux-handbook.tex @@ -42,7 +42,7 @@ % Dune and Dumux logo \newcommand{\Dune}{{DUNE}\xspace} \newcommand{\Dumux}{\texorpdfstring{Du\-Mu$^\text{x}$\xspace}{DuMuX\xspace}} -\newcommand{\DumuxVersion}{3.2-git} +\newcommand{\DumuxVersion}{3.2} \definecolor{dumuxYellow}{HTML}{E19417} \definecolor{dumuxBlue}{HTML}{0C73CF} -- GitLab From 73375dd586cd0701e018acfa92ebd8144b39b74c Mon Sep 17 00:00:00 2001 From: Ned Coltman Date: Thu, 23 Apr 2020 08:31:17 +0200 Subject: [PATCH 23/57] [test][boundary][convergence] Remove gridview deprecation warning --- .../stokesdarcy/1p_1p/convergencetest/problem_darcy.hh | 6 +++--- .../stokesdarcy/1p_1p/convergencetest/problem_stokes.hh | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/multidomain/boundary/stokesdarcy/1p_1p/convergencetest/problem_darcy.hh b/test/multidomain/boundary/stokesdarcy/1p_1p/convergencetest/problem_darcy.hh index 8312e44e9b..b47c9518a2 100644 --- a/test/multidomain/boundary/stokesdarcy/1p_1p/convergencetest/problem_darcy.hh +++ b/test/multidomain/boundary/stokesdarcy/1p_1p/convergencetest/problem_darcy.hh @@ -81,16 +81,16 @@ template class DarcySubProblem : public PorousMediumFlowProblem { using ParentType = PorousMediumFlowProblem; - using GridView = GetPropType; + using GridGeometry = GetPropType; + using GridView = typename GridGeometry::GridView; using Scalar = GetPropType; using PrimaryVariables = GetPropType; using NumEqVector = GetPropType; using BoundaryTypes = GetPropType; using VolumeVariables = GetPropType; - using FVElementGeometry = typename GetPropType::LocalView; + using FVElementGeometry = typename GridGeometry::LocalView; using SubControlVolume = typename FVElementGeometry::SubControlVolume; using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace; - using GridGeometry = GetPropType; using Element = typename GridView::template Codim<0>::Entity; using GlobalPosition = typename Element::Geometry::GlobalCoordinate; diff --git a/test/multidomain/boundary/stokesdarcy/1p_1p/convergencetest/problem_stokes.hh b/test/multidomain/boundary/stokesdarcy/1p_1p/convergencetest/problem_stokes.hh index 25cd89a662..e0b8f81e71 100644 --- a/test/multidomain/boundary/stokesdarcy/1p_1p/convergencetest/problem_stokes.hh +++ b/test/multidomain/boundary/stokesdarcy/1p_1p/convergencetest/problem_stokes.hh @@ -77,10 +77,10 @@ template class StokesSubProblem : public NavierStokesProblem { using ParentType = NavierStokesProblem; - using GridView = GetPropType; + using GridGeometry = GetPropType; + using GridView = typename GridGeometry::GridView; using Scalar = GetPropType; using BoundaryTypes = GetPropType; - using GridGeometry = GetPropType; using FVElementGeometry = typename GridGeometry::LocalView; using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace; using Element = typename GridView::template Codim<0>::Entity; -- GitLab From 48752199effe5e5bbdef20e00c99b0981ec7a8cf Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Thu, 23 Apr 2020 10:19:33 +0000 Subject: [PATCH 24/57] Merge branch 'feature/rot-symmetry-example' into 'master' Feature/rot symmetry example See merge request dumux-repositories/dumux!2039 (cherry picked from commit 84c6fb826a9241b88ffca1e4d5e69d8048864516) 219e7879 [examples] implement rotation-symmetric example 297e729b [examples][rotationsymmetry] add images and more docu 34bbeecc [examples][rotsym] add structural elements and compile docu --- examples/1protationsymmetry/.doc_config | 35 + examples/1protationsymmetry/CMakeLists.txt | 10 + examples/1protationsymmetry/README.md | 113 ++ examples/1protationsymmetry/doc/_intro.md | 94 ++ examples/1protationsymmetry/doc/main.md | 253 ++++ examples/1protationsymmetry/doc/main_intro.md | 9 + examples/1protationsymmetry/doc/paraview.md | 24 + .../1protationsymmetry/doc/paraview_doc.md | 14 + examples/1protationsymmetry/doc/problem.md | 376 +++++ .../1protationsymmetry/doc/problem_intro.md | 5 + examples/1protationsymmetry/img/result.png | Bin 0 -> 319365 bytes examples/1protationsymmetry/img/setup.svg | 1042 ++++++++++++++ examples/1protationsymmetry/main.cc | 225 +++ examples/1protationsymmetry/params.input | 18 + examples/1protationsymmetry/problem.hh | 123 ++ examples/1protationsymmetry/properties.hh | 146 ++ examples/1protationsymmetry/spatialparams.hh | 82 ++ examples/CMakeLists.txt | 1 + examples/README.md | 17 + .../example_rotationsymmetry-reference.vtp | 1231 +++++++++++++++++ 20 files changed, 3818 insertions(+) create mode 100644 examples/1protationsymmetry/.doc_config create mode 100644 examples/1protationsymmetry/CMakeLists.txt create mode 100644 examples/1protationsymmetry/README.md create mode 100644 examples/1protationsymmetry/doc/_intro.md create mode 100644 examples/1protationsymmetry/doc/main.md create mode 100644 examples/1protationsymmetry/doc/main_intro.md create mode 100644 examples/1protationsymmetry/doc/paraview.md create mode 100644 examples/1protationsymmetry/doc/paraview_doc.md create mode 100644 examples/1protationsymmetry/doc/problem.md create mode 100644 examples/1protationsymmetry/doc/problem_intro.md create mode 100644 examples/1protationsymmetry/img/result.png create mode 100644 examples/1protationsymmetry/img/setup.svg create mode 100644 examples/1protationsymmetry/main.cc create mode 100644 examples/1protationsymmetry/params.input create mode 100644 examples/1protationsymmetry/problem.hh create mode 100644 examples/1protationsymmetry/properties.hh create mode 100644 examples/1protationsymmetry/spatialparams.hh create mode 100644 test/references/example_rotationsymmetry-reference.vtp diff --git a/examples/1protationsymmetry/.doc_config b/examples/1protationsymmetry/.doc_config new file mode 100644 index 0000000000..f85531dc67 --- /dev/null +++ b/examples/1protationsymmetry/.doc_config @@ -0,0 +1,35 @@ +{ + "README.md" : [ + "doc/_intro.md" + ], + + "doc/problem.md" : [ + "doc/problem_intro.md", + "properties.hh", + "problem.hh", + "spatialparams.hh" + ], + + "doc/main.md" : [ + "doc/main_intro.md", + "main.cc" + ], + + "doc/paraview.md" : [ + "doc/paraview_doc.md" + ], + + "navigation" : { + "mainpage" : "README.md", + "subpages" : [ + "doc/problem.md", + "doc/main.md", + "doc/paraview.md" + ], + "subtitles" : [ + "Rotation-symmetric one-phase flow simulation setup", + "Main program flow", + "Post-processing with ParaView" + ] + } +} diff --git a/examples/1protationsymmetry/CMakeLists.txt b/examples/1protationsymmetry/CMakeLists.txt new file mode 100644 index 0000000000..cb926b1fd8 --- /dev/null +++ b/examples/1protationsymmetry/CMakeLists.txt @@ -0,0 +1,10 @@ +dune_symlink_to_source_files(FILES "params.input") + +dune_add_test(NAME example_1p_rotationsymmetry + LABELS porousmediumflow 1p + SOURCES main.cc + COMMAND ${CMAKE_SOURCE_DIR}/bin/testing/runtest.py + CMD_ARGS --script fuzzy + --files ${CMAKE_SOURCE_DIR}/test/references/example_rotationsymmetry-reference.vtp + ${CMAKE_CURRENT_BINARY_DIR}/example_rotationsymmetry-00000.vtp + --command "${CMAKE_CURRENT_BINARY_DIR}/example_1p_rotationsymmetry params.input -Problem.Name example_rotationsymmetry") diff --git a/examples/1protationsymmetry/README.md b/examples/1protationsymmetry/README.md new file mode 100644 index 0000000000..11cb39cdf2 --- /dev/null +++ b/examples/1protationsymmetry/README.md @@ -0,0 +1,113 @@ + + +# Rotation-symmetric pressure distribution + +__In this example, you will learn how to__ + +* solve a rotation-symmetric problem one-dimensionally +* perform a convergence test against an analytical solution +* apply the `Rotational Extrusion` filters in [ParaView](https://www.paraview.org/) for a two-dimensional visualization of the one-dimensional results + + +__Result__. With the `Rotational Extrusion` and the `Warp By Scalar` filters in [ParaView](https://www.paraview.org/), +the pressure distribution of this example looks as shown in the following picture: + +
+
+ Rotation-symmetric pressure distribution +
Fig.1 - Rotation-symmetric pressure distribution on a disc (warped to 3D).
+
+
+ + +__Table of contents__. This description is structured as follows: + +[[_TOC_]] + + +## Problem setup + +We consider a single-phase problem that leads to a rotation-symmetric pressure distribution. +The following figure illustrates the setup: + +
+
+ Rotation-symmetric setup +
Fig.2 - Setup for the rotation-symmetric problem. The pressure boundary conditions are shown by the colored lines and the simulation domain is depicted in grey.
+
+
+ +This could, for example, represent a cross section of an injection/extraction well in a homogeneous +and isotropic porous medium, where the well with radius $`r_1`$ is cut out and the +injection/extraction pressure $`p_1`$ is prescribed as a Dirichlet boundary condition. At the outer +radius $`r_2`$, we set the pressure $`p_2`$. In the polar coordinates $`r`$ and $`\varphi`$, the +solution to this problem is independent of the angular coordinate $`\varphi`$ and can be reduced to +a one-dimensional problem in the radial coordinate $`r`$. Therefore, in this example, we want to +solve the problem on a one-dimensional computational domain as illustrated by the orange line in +the above figure. + +## Mathematical model + +In this example we are using the single-phase model of DuMux, which considers Darcy's law to relate +the Darcy velocity $`\textbf u`$ to gradients of the pressure $`p`$. In the case of rotational +symmetry, the mass balance equation for the fluid phase can be transformed using polar coordinates: + +```math +-\frac{1}{r} \frac{\partial}{\partial r} \left( r \frac{\varrho k}{\mu} \frac{\partial p}{\partial r} \right) = 0, +``` + +where we identify the Darcy velocity in radial direction $`u_r = -\frac{k}{\mu} \frac{\partial p}{\partial r}`$, +and where $`k`$ is the permeability of the porous medium, $`\mu`$ is the dynamic viscosity of the +fluid, and $`\varrho`$ is the fluid density. + +## Discretization + +We employ a finite-volume scheme to spatially discretize the mass balance equation shown above. +Let us consider a discretization of the one-dimensional domain into control volumes +$`K_i = \left[ r_i, r_{i+1} \right]`$. The discrete equation describing mass conservation inside a control volume +$`K_i`$ is obtained by integration and reads: + +```math + - 2 \pi r_{i+1} \left( \varrho u_r \right)_{r_{i+1}} + + 2 \pi r_i \left( \varrho u_r \right)_{r_i} + = 0. +``` + +For this type of equation, the implementation of the finite-volume schemes in DuMux is based on +the general form: + +```math +\sum_{\sigma \in \mathcal{S}_K} | \sigma | \left( \varrho \textbf u \cdot \textbf n \right)_\sigma = 0, +``` + +where $`\sigma`$ are the faces of the control volume and where the notation +$`( \cdot )_\sigma`$ was used to denote quantities evaluated for a face $`\sigma`$. +The area of a face is denoted with $`| \sigma |`$. Thus, comparing the two equations +we identify $`| \sigma | = 2 \pi r_\sigma`$ for the case of rotational symmetry +on a disc. Here, $`r_\sigma`$ refers to the radius at which the face is situated +in the one-dimensional discretization. + +In DuMux, this is realized in the classes `RotationSymmetricSubControlVolume` and +`RotationSymmetricSubControlVolumeFace`, which implement one-dimensional control +volumes and faces, that take into account the extrusion about the rotation axes +of symmetry in the computations of volumes and areas. This will be discussed in part 1 +of the documentation. + +# Implementation & Post processing + +## Part 1: Rotation-symmetric one-phase flow simulation setup + +| [:arrow_right: Click to continue with part 1 of the documentation](doc/problem.md) | +|---:| + + +## Part 2: Main program flow + +| [:arrow_right: Click to continue with part 2 of the documentation](doc/main.md) | +|---:| + + +## Part 3: Post-processing with ParaView + +| [:arrow_right: Click to continue with part 3 of the documentation](doc/paraview.md) | +|---:| \ No newline at end of file diff --git a/examples/1protationsymmetry/doc/_intro.md b/examples/1protationsymmetry/doc/_intro.md new file mode 100644 index 0000000000..8c60975f59 --- /dev/null +++ b/examples/1protationsymmetry/doc/_intro.md @@ -0,0 +1,94 @@ +# Rotation-symmetric pressure distribution + +__In this example, you will learn how to__ + +* solve a rotation-symmetric problem one-dimensionally +* perform a convergence test against an analytical solution +* apply the `Rotational Extrusion` filters in [ParaView](https://www.paraview.org/) for a two-dimensional visualization of the one-dimensional results + + +__Result__. With the `Rotational Extrusion` and the `Warp By Scalar` filters in [ParaView](https://www.paraview.org/), +the pressure distribution of this example looks as shown in the following picture: + +
+
+ Rotation-symmetric pressure distribution +
Fig.1 - Rotation-symmetric pressure distribution on a disc (warped to 3D).
+
+
+ + +__Table of contents__. This description is structured as follows: + +[[_TOC_]] + + +## Problem setup + +We consider a single-phase problem that leads to a rotation-symmetric pressure distribution. +The following figure illustrates the setup: + +
+
+ Rotation-symmetric setup +
Fig.2 - Setup for the rotation-symmetric problem. The pressure boundary conditions are shown by the colored lines and the simulation domain is depicted in grey.
+
+
+ +This could, for example, represent a cross section of an injection/extraction well in a homogeneous +and isotropic porous medium, where the well with radius $`r_1`$ is cut out and the +injection/extraction pressure $`p_1`$ is prescribed as a Dirichlet boundary condition. At the outer +radius $`r_2`$, we set the pressure $`p_2`$. In the polar coordinates $`r`$ and $`\varphi`$, the +solution to this problem is independent of the angular coordinate $`\varphi`$ and can be reduced to +a one-dimensional problem in the radial coordinate $`r`$. Therefore, in this example, we want to +solve the problem on a one-dimensional computational domain as illustrated by the orange line in +the above figure. + +## Mathematical model + +In this example we are using the single-phase model of DuMux, which considers Darcy's law to relate +the Darcy velocity $`\textbf u`$ to gradients of the pressure $`p`$. In the case of rotational +symmetry, the mass balance equation for the fluid phase can be transformed using polar coordinates: + +```math +-\frac{1}{r} \frac{\partial}{\partial r} \left( r \frac{\varrho k}{\mu} \frac{\partial p}{\partial r} \right) = 0, +``` + +where we identify the Darcy velocity in radial direction $`u_r = -\frac{k}{\mu} \frac{\partial p}{\partial r}`$, +and where $`k`$ is the permeability of the porous medium, $`\mu`$ is the dynamic viscosity of the +fluid, and $`\varrho`$ is the fluid density. + +## Discretization + +We employ a finite-volume scheme to spatially discretize the mass balance equation shown above. +Let us consider a discretization of the one-dimensional domain into control volumes +$`K_i = \left[ r_i, r_{i+1} \right]`$. The discrete equation describing mass conservation inside a control volume +$`K_i`$ is obtained by integration and reads: + +```math + - 2 \pi r_{i+1} \left( \varrho u_r \right)_{r_{i+1}} + + 2 \pi r_i \left( \varrho u_r \right)_{r_i} + = 0. +``` + +For this type of equation, the implementation of the finite-volume schemes in DuMux is based on +the general form: + +```math +\sum_{\sigma \in \mathcal{S}_K} | \sigma | \left( \varrho \textbf u \cdot \textbf n \right)_\sigma = 0, +``` + +where $`\sigma`$ are the faces of the control volume and where the notation +$`( \cdot )_\sigma`$ was used to denote quantities evaluated for a face $`\sigma`$. +The area of a face is denoted with $`| \sigma |`$. Thus, comparing the two equations +we identify $`| \sigma | = 2 \pi r_\sigma`$ for the case of rotational symmetry +on a disc. Here, $`r_\sigma`$ refers to the radius at which the face is situated +in the one-dimensional discretization. + +In DuMux, this is realized in the classes `RotationSymmetricSubControlVolume` and +`RotationSymmetricSubControlVolumeFace`, which implement one-dimensional control +volumes and faces, that take into account the extrusion about the rotation axes +of symmetry in the computations of volumes and areas. This will be discussed in part 1 +of the documentation. + +# Implementation & Post processing diff --git a/examples/1protationsymmetry/doc/main.md b/examples/1protationsymmetry/doc/main.md new file mode 100644 index 0000000000..ebb097d694 --- /dev/null +++ b/examples/1protationsymmetry/doc/main.md @@ -0,0 +1,253 @@ + + + +| [:arrow_left: Back to the main documentation](../README.md) | [:arrow_left: Go back to part 1](problem.md) | [:arrow_right: Continue with part 3](paraview.md) | +|---|---|---:| + +# Part 2: Main program flow + +We want to solve a rotational symmetric Laplace problem on a disc and +conduct a grid convergence study against an analytical solution. +The main program flow is implemented in file `main.cc` described below. + +The code documentation is structured as follows: + +[[_TOC_]] + + +## The main program (`main.cc`) +This file contains the main program flow. In this example, we solve a stationary +and rotationally symmetric single-phase problem for a sequence of refined grids +and compute the convergence rates. + +
+Click to hide/show the file documentation (or inspect the [source code](../main.cc)) + +### Includes +
Click to show includes + +```cpp +#include + +#include +#include + +#include // for GetPropType +#include // for getParam +#include // for integrateL2Error + +#include // for UMFPackBackend +#include // for LinearPDESolver +#include +#include + +#include +#include + +#include "properties.hh" +``` + +
+ +### Beginning of the main function + +```cpp +int main(int argc, char** argv) try +{ + using namespace Dumux; + + // We initialize MPI. Finalization is done automatically on exit. + Dune::MPIHelper::instance(argc, argv); + + // We parse the command line arguments. + Parameters::init(argc, argv); + + // Convenience alias for the type tag of the problem. + using TypeTag = Properties::TTag::OnePRotSym; +``` + +### Create the grid and the grid geometry + +```cpp + // The grid manager can be used to create a grid from the input file + using Grid = GetPropType; + GridManager gridManager; + gridManager.init(); + + // We compute on the leaf grid view. + const auto& leafGridView = gridManager.grid().leafGridView(); + + // instantiate the grid geometry + using GridGeometry = GetPropType; + auto gridGeometry = std::make_shared(leafGridView); + gridGeometry->update(); +``` + +### Initialize the problem and grid variables + +```cpp + using Problem = GetPropType; + auto problem = std::make_shared(gridGeometry); + + // We define a function to update the discrete analytical solution vector + // using the exactSolution() function in the problem + const auto updateAnalyticalSolution = [&](auto& pExact) + { + pExact.resize(gridGeometry->numDofs()); + for (const auto& element : elements(gridGeometry->gridView())) + { + auto fvGeometry = localView(*gridGeometry); + fvGeometry.bindElement(element); + for (auto&& scv : scvs(fvGeometry)) + pExact[scv.dofIndex()] = problem->exactSolution(scv.dofPosition()); + } + }; + + // instantiate and initialize the discrete and exact solution vectors + using SolutionVector = GetPropType; + SolutionVector p(gridGeometry->numDofs()); + SolutionVector pExact; updateAnalyticalSolution(pExact); + + // instantiate and initialize the grid variables + using GridVariables = GetPropType; + auto gridVariables = std::make_shared(problem, gridGeometry); + gridVariables->init(p); +``` + +### Initialize VTK output + +```cpp + VtkOutputModule vtkWriter(*gridVariables, p, problem->name()); + GetPropType::initOutputModule(vtkWriter); + vtkWriter.addField(pExact, "pExact"); // add the exact solution to the output fields +``` + +### Instantiate the solver +We use the `LinearPDESolver` class, which is instantiated on the basis +of an assembler and a linear solver. When the `solve` function of the +`LinearPDESolver` is called, it uses the assembler and linear +solver classes to assemble and solve the linear system around the provided +solution and stores the result therein. + +```cpp + using Assembler = FVAssembler; + auto assembler = std::make_shared(problem, gridGeometry, gridVariables); + + using LinearSolver = UMFPackBackend; + auto linearSolver = std::make_shared(); + LinearPDESolver solver(assembler, linearSolver); + solver.setVerbose(false); // suppress output during solve() +``` + +### Solution of the problem and error computation +The problem is solved by calling `solve` on the instance of `LinearPDESolver` +that we have created above. In the following piece of code, we solve the +problem on the initial refinement and compute the corresponding L2 error. +For a convenient way of computing the L2 error, the function `integrateL2Error` +can be used. + +```cpp + solver.solve(p); + + // container to store the L2 errors for the different refinements + const int numRefinements = getParam("Grid.RefinementSteps"); + std::vector l2Errors(numRefinements); + + // use third order error integration + constexpr int orderQuadratureRule = 3; + + // compute initial L2 error + l2Errors[0] = integrateL2Error(*gridGeometry, p, pExact, orderQuadratureRule); +``` + +This procedure is now repeated for the number of refinements as specified +in the input file. + +```cpp + for (int stepIdx = 1; stepIdx < numRefinements; stepIdx++) + { + // Globally refine the grid once + gridManager.grid().globalRefine(1); + + // update the grid geometry, the grid variables and + // the solution vectors now that the grid has been refined + gridGeometry->update(); + gridVariables->updateAfterGridAdaption(p); + + p.resize(gridGeometry->numDofs()); + updateAnalyticalSolution(pExact); + + // this recreates the linear system, i.e. the sizes of + // the right hand side vector and the Jacobian matrix, + // and its sparsity pattern. + assembler->setLinearSystem(); + + // solve problem on refined grid + solver.solve(p); +``` + +#### Post-processing and output +At the end of each refinement step, the convergence +rate is printed to the terminal. + +```cpp + // Calculate the L2 error using the numerical solution + l2Errors[stepIdx] = integrateL2Error(*gridGeometry, p, pExact, orderQuadratureRule); + + // Print the error and convergence rate + const auto rate = std::log(l2Errors[stepIdx]/l2Errors[stepIdx-1])/std::log(0.5); + const auto numDofs = gridGeometry->numDofs(); + std::cout << std::setprecision(8) << std::scientific + << "-- L2 error for " << std::setw(5) << numDofs << " dofs: " << l2Errors[stepIdx] + << ", rate: " << rate + << std::endl; + } +``` + +After the last refinement, we write the solution to VTK file format on the +finest grid and exit the main function. + +```cpp + vtkWriter.write(0.0); + + // program end, return with 0 exit code (success) + return 0; +} +``` + +### Exception handling +In this part of the main file we catch and print possible exceptions that could +occur during the simulation. +
Click to show error handler + +```cpp + +catch (const Dumux::ParameterException &e) +{ + std::cerr << std::endl << e << " ---> Abort!" << std::endl; + return 1; +} +catch (const Dune::DGFException & e) +{ + std::cerr << "DGF exception thrown (" << e << + "). Most likely, the DGF file name is wrong " + "or the DGF file is corrupted, " + "e.g. missing hash at end of file or wrong number (dimensions) of entries." + << " ---> Abort!" << std::endl; + return 2; +} +catch (const Dune::Exception &e) +{ + std::cerr << "Dune reported error: " << e << " ---> Abort!" << std::endl; + return 3; +} +``` + +
+ +
+ + +| [:arrow_left: Back to the main documentation](../README.md) | [:arrow_left: Go back to part 1](problem.md) | [:arrow_right: Continue with part 3](paraview.md) | +|---|---|---:| + diff --git a/examples/1protationsymmetry/doc/main_intro.md b/examples/1protationsymmetry/doc/main_intro.md new file mode 100644 index 0000000000..9909b61a5b --- /dev/null +++ b/examples/1protationsymmetry/doc/main_intro.md @@ -0,0 +1,9 @@ +# Part 2: Main program flow + +We want to solve a rotational symmetric Laplace problem on a disc and +conduct a grid convergence study against an analytical solution. +The main program flow is implemented in file `main.cc` described below. + +The code documentation is structured as follows: + +[[_TOC_]] diff --git a/examples/1protationsymmetry/doc/paraview.md b/examples/1protationsymmetry/doc/paraview.md new file mode 100644 index 0000000000..3cae53afc6 --- /dev/null +++ b/examples/1protationsymmetry/doc/paraview.md @@ -0,0 +1,24 @@ + + + +| [:arrow_left: Back to the main documentation](../README.md) | [:arrow_left: Go back to part 2](main.md) | +|---|---:| + +# Part 3: Post-processing with ParaView + +The result file `example_rotationsymmetry.pvd` can be opened with the software [ParaView](https://www.paraview.org/). +To obtain a visualisation as shown in the introduction of this documented example, after loading +the result file, choose `Filters`>`Alphabetical`>`Rotational Extrusion`. +You might have to reset your view and switch to `3D`. Then apply `Filters`>`Alphabetical`>`Warp By Scalar`. +The result should look like this: + +
+
+ Rotation-symmetric pressure distribution +
Fig.1 - Rotation-symmetric pressure distribution on a disc (warped to 3D)
+
+
+ +| [:arrow_left: Back to the main documentation](../README.md) | [:arrow_left: Go back to part 2](main.md) | +|---|---:| + diff --git a/examples/1protationsymmetry/doc/paraview_doc.md b/examples/1protationsymmetry/doc/paraview_doc.md new file mode 100644 index 0000000000..a5c127ee10 --- /dev/null +++ b/examples/1protationsymmetry/doc/paraview_doc.md @@ -0,0 +1,14 @@ +# Part 3: Post-processing with ParaView + +The result file `example_rotationsymmetry.pvd` can be opened with the software [ParaView](https://www.paraview.org/). +To obtain a visualisation as shown in the introduction of this documented example, after loading +the result file, choose `Filters`>`Alphabetical`>`Rotational Extrusion`. +You might have to reset your view and switch to `3D`. Then apply `Filters`>`Alphabetical`>`Warp By Scalar`. +The result should look like this: + +
+
+ Rotation-symmetric pressure distribution +
Fig.1 - Rotation-symmetric pressure distribution on a disc (warped to 3D)
+
+
diff --git a/examples/1protationsymmetry/doc/problem.md b/examples/1protationsymmetry/doc/problem.md new file mode 100644 index 0000000000..983554ea60 --- /dev/null +++ b/examples/1protationsymmetry/doc/problem.md @@ -0,0 +1,376 @@ + + + +| [:arrow_left: Back to the main documentation](../README.md) | [:arrow_right: Continue with part 2](main.md) | +|---|---:| + +# Part 1: Simulation setup + +The code documentation is structured as follows: + +[[_TOC_]] + + +## Compile-time settings (`properties.hh`) +This file defines the `TypeTag` used for the simulation in this example, for +which we specialize a number of compile-time `properties`. + +
+Click to hide/show the file documentation (or inspect the [source code](../properties.hh)) + +### Includes +
Click to show includes + +```cpp + +#include // for `Dune::YaspGrid` +#include // for `TTag::BoxModel` +``` + +The `OneP` type tag specializes most of the `properties` required for single- +phase flow simulations in DuMux. We will use this in the following to inherit the +respective properties, and subsequently specialize those properties for our +type tag, which we want to modify or for which no meaningful default can be set. + +```cpp +#include // for `TTag::OneP` +``` + +The local residual for incompressible flow is included. +The one-phase flow model (included above) uses a default implementation of the +local residual for single-phase flow. However, in this example we are using an +incompressible fluid phase. Therefore, we are including the specialized local +residual which contains functionality to analytically compute the entries of +the Jacobian matrix. We will use this in the main file. + +```cpp +#include +``` + +We will use a single liquid phase consisting of a component with constant fluid properties. + +```cpp +#include +#include +``` + +As mentioned at the beginning of the documentation of this example, DuMux +provides specialized implementations of control volumes and faces for +rotation-symmetric problems. These take care of adjusting volume and area +computations to account for the extrusion about the symmetry axes. +These implementations are exported by the `RotationSymmetricGridGeometryTraits`. + +```cpp +#include +``` + +The classes that define the problem and parameters used in this simulation + +```cpp +#include "problem.hh" +#include "spatialparams.hh" +``` + +
+ +### `TypeTag` definition +A `TypeTag` for our simulation is defined, which inherits properties from the +single-phase flow model and the box scheme. + +```cpp +namespace Dumux::Properties { +namespace TTag { +struct OnePRotSym { using InheritsFrom = std::tuple; }; +} +``` + +### Property specializations + +In the following piece of code, mandatory `properties` for which no meaningful +default can be set, are specialized for our type tag `OnePRotSym`. + +```cpp +// We use a structured 1D grid with an offset. This allows us to define the +// computational domain to be between the radii $`r_1`$ and $`r_2`$ as illustrated +// in the beginning of the documentation of this example +template +struct Grid +{ using type = Dune::YaspGrid<1, Dune::EquidistantOffsetCoordinates>; }; + +// The problem class specifying initial and boundary conditions: +template +struct Problem +{ using type = RotSymExampleProblem; }; + +// Our spatial parameters class defining the permeability and porosity of the porous medium: +template +struct SpatialParams +{ +private: + using GridGeometry = GetPropType; + using Scalar = GetPropType; +public: + using type = RotSymExampleSpatialParams; +}; + +// We use a single liquid phase consisting of a component with constant fluid properties. +template +struct FluidSystem +{ +private: + using Scalar = GetPropType; +public: + using type = FluidSystems::OnePLiquid >; +}; +``` + +As mentioned before, DuMux provides specialized implementations of sub-control +volumes and faces for rotation-symmetric problems, which are exported by the +`RotationSymmetricGridGeometryTraits`. +Here, we pass these traits to the grid geometry of the box scheme (the scheme +that we use here) and specialize the `GridGeometry` property accordingly. + +```cpp +template +struct GridGeometry +{ +private: + static constexpr bool enableCache = getPropValue(); + using Scalar = GetPropType; + using GridView = typename GetPropType::LeafGridView; + + // The default traits for box grid geometries + using DefaultTraits = BoxDefaultGridGeometryTraits; + + // On the basis of the default traits, define the traits for rotational symmetry. + // These will export the corresponding rotation-symmetric sub-control volumes and faces. + using GGTraits = RotationSymmetricGridGeometryTraits; + +public: + // Pass the above traits to the box grid geometry such that it uses the + // rotation-symmetric sub-control volumes and faces. + using type = BoxFVGridGeometry; +}; +``` + +Moreover, here we use a local residual specialized for incompressible flow +that contains functionality related to analytic differentiation. + +```cpp +template +struct LocalResidual +{ using type = OnePIncompressibleLocalResidual; }; + +} // end namespace Dumux::Properties +``` + + +
+ + + +## The problem class (`problem.hh`) +This file contains the __problem class__ which defines the initial and boundary +conditions for the single-phase flow simulation. + +
+Click to hide/show the file documentation (or inspect the [source code](../problem.hh)) + +### Includes + +```cpp +#include // for `std::log` +#include // for `GetPropType` +#include // for `getParam` +#include // for `PorousMediumFlowProblem` +``` + +### The problem class +We enter the problem class where all necessary boundary conditions and initial conditions are set for our simulation. +As this is a porous medium flow problem, we inherit from the base class `PorousMediumFlowProblem`. + +```cpp +namespace Dumux { + +template +class RotSymExampleProblem : public PorousMediumFlowProblem +{ + using ParentType = PorousMediumFlowProblem; + using GridGeometry = GetPropType; + using Scalar = GetPropType; + using PrimaryVariables = GetPropType; + using BoundaryTypes = GetPropType; + using Element = typename GridGeometry::GridView::template Codim<0>::Entity; + using GlobalPosition = typename Element::Geometry::GlobalCoordinate; + +public: +``` + +In the constructor, we obtain a number of parameters, related to fluid +properties and boundary conditions, from the input file. + +```cpp + RotSymExampleProblem(std::shared_ptr gridGeometry) + : ParentType(gridGeometry) + { + // fluid properties + k_ = getParam("SpatialParams.Permeability"); + nu_ = getParam("Component.LiquidKinematicViscosity"); + + // The inner radius r1 can be determined from the grid + r1_ = gridGeometry->bBoxMin()[0]; + + // boundary conditions + q1_ = getParam("Problem.Q1"); // mass flux into the domain at r1 in kg/s/m + p1_ = getParam("Problem.P1"); // pressure at the inner boundary at r1 + + } +``` + +We need to specify a constant temperature for our isothermal problem. +Fluid properties that depend on temperature will be calculated with this value. + +```cpp + Scalar temperature() const + { return 283.15; } +``` + +#### Specify the types of boundary conditions +This function is used to define the type of boundary conditions used depending on the location. +Two types of boundary conditions can be specified: Dirichlet or Neumann boundary condition. +On a Dirichlet boundary, the values of the primary variables need to be fixed. On a Neumann +boundary condition, values for derivatives need to be fixed. Here, we use Dirichlet boundary +conditions on all boundaries. + +```cpp + BoundaryTypes boundaryTypesAtPos(const GlobalPosition& globalPos) const + { + BoundaryTypes values; + values.setAllDirichlet(); + return values; + } +``` + +#### Specify Dirichlet boundary condition values +This function is used to specify the values of the primary variables at Dirichlet boundaries. +Here, we evaluate the analytical solution (see below) to define the pressures at the boundaries. + +```cpp + PrimaryVariables dirichletAtPos(const GlobalPosition& globalPos) const + { return exactSolution(globalPos); } +``` + +#### Analytical solution +The analytical solution to the problem of this example reads: + +```math +p = p (r) = p_1 - \frac{q_1 \nu}{2 \pi k} \text{ln} (\frac{r}{r_1}), +``` + +where $`q_1`$ is the mass flux into the domain at the inner radius $`r_1`$ +(in kg/s/m) and $`\nu = \mu/\varrho`$ is the kinematic viscosity. +The following function evaluates this solution depending on the +position in the domain. We use this function here both to specify Dirichlet +boundaries and to evaluate the error of the numerical solutions obtained for +different levels of grid refinement. + +```cpp + PrimaryVariables exactSolution(const GlobalPosition& globalPos) const + { + const auto r = globalPos[0]; + const auto p = p1_ - 1.0/(2*M_PI)*nu_/k_*q1_*std::log(r/r1_); + return p; + } + +private: + // private data members required for the analytical solution + Scalar q1_, k_, nu_, r1_, p1_; +}; + +} // end namespace Dumux +``` + + +
+ + + +## Parameter distributions (`spatialparams.hh`) + +This file contains the __spatial parameters class__ which defines the +distributions for the porous medium parameters permeability and porosity +over the computational grid. + +
+Click to hide/show the file documentation (or inspect the [source code](../spatialparams.hh)) + +We include the spatial parameters class for single-phase models discretized +by finite volume schemes, from which the spatial parameters defined for this +example inherit. + +```cpp +#include +``` + +### The spatial parameters class + +In the `RotSymExampleSpatialParams` class, we define the functions needed to describe +the porous medium, that is, porosity and permeability. +We inherit from the `FVSpatialParamsOneP` class here, which is the base class +for spatial parameters in the context of single-phase porous medium flow +applications using finite volume discretization schemes. + +```cpp +namespace Dumux { + +template +class RotSymExampleSpatialParams +: public FVSpatialParamsOneP> +{ + using ThisType = RotSymExampleSpatialParams; + using ParentType = FVSpatialParamsOneP; + using Element = typename GridGeometry::GridView::template Codim<0>::Entity; + using GlobalPosition = typename Element::Geometry::GlobalCoordinate; +public: + // Spatial parameter classes for porous medium flow applications need to + // export the type used for intrinsic permeabilities. + using PermeabilityType = Scalar; + + // In the constructor we obtain the permeability value from the input file. + RotSymExampleSpatialParams(std::shared_ptr gridGeometry) + : ParentType(gridGeometry) + { permeability_ = getParam("SpatialParams.Permeability"); } +``` + +#### Porosity distribution +This function is used to define the porosity distribution in the +computational domain. Here, we use a constant porosity of 1.0. + +```cpp + Scalar porosityAtPos(const GlobalPosition& globalPos) const + { return 1.0; } +``` + +#### Permeability distribution +This function is used to define the permeability distribution in the +computational domain. Here, we use a constant permeability that is +defined in the input file. + +```cpp + PermeabilityType permeabilityAtPos(const GlobalPosition& globalPos) const + { return permeability_; } + +private: + Scalar permeability_; +}; + +} // end namespace Dumux +``` + + +
+ + +| [:arrow_left: Back to the main documentation](../README.md) | [:arrow_right: Continue with part 2](main.md) | +|---|---:| + diff --git a/examples/1protationsymmetry/doc/problem_intro.md b/examples/1protationsymmetry/doc/problem_intro.md new file mode 100644 index 0000000000..106967a62f --- /dev/null +++ b/examples/1protationsymmetry/doc/problem_intro.md @@ -0,0 +1,5 @@ +# Part 1: Simulation setup + +The code documentation is structured as follows: + +[[_TOC_]] diff --git a/examples/1protationsymmetry/img/result.png b/examples/1protationsymmetry/img/result.png new file mode 100644 index 0000000000000000000000000000000000000000..7311f787fab3e0e082ae9b39b8808813a6191c0f GIT binary patch literal 319365 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

bw*z9Wb*DX^*-ZzUSqJ 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 MuH_f4^OHj_tEO` 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綌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