From baa0ff6af7381b6ebf2e4c704b73e7fae2755d72 Mon Sep 17 00:00:00 2001 From: Markus Blatt Date: Sun, 26 Jan 2020 09:48:04 +0100 Subject: [PATCH 01/27] Added a generic linear backend using the solver factories from istl. This requires a version newer than 2.7.0. The backend translates the configuration parameters from Dumux CamelCase to the dune-istl names. If a Dumux parameter is not found we fall back to using the dune-istl parameter name. We fall back to the parallel AMG backend if the DUNE version is not sufficient. --- dumux/common/loggingparametertree.hh | 51 ++++++ dumux/common/parameters.hh | 7 + dumux/linear/CMakeLists.txt | 1 + dumux/linear/genericistlbackend.hh | 261 +++++++++++++++++++++++++++ 4 files changed, 320 insertions(+) create mode 100644 dumux/linear/genericistlbackend.hh diff --git a/dumux/common/loggingparametertree.hh b/dumux/common/loggingparametertree.hh index 8117172a29..0dc766d7ef 100644 --- a/dumux/common/loggingparametertree.hh +++ b/dumux/common/loggingparametertree.hh @@ -66,6 +66,16 @@ public: bool hasKey(const std::string& key) const { return params_.hasKey(key); } + /** \brief test for key (even in default parameters + * + * Tests whether given key exists. + * + * \param key key name + * \return true if key exists in structure, otherwise false + */ + bool hasKeyOrDefaultKey(const std::string& key) const + { return params_.hasKey(key) || defaultParams_.hasKey(key); } + /** \brief test for key in group * * Tests whether given key exists in a group. @@ -101,6 +111,47 @@ public: return false; } + /** \brief test for subgroup in group + * + * Tests whether given sub group exists in a group. + * Given a group this function starts to look from the back + * for dots. In G1.G2.G3 the function first looks if the key + * "G3.Key" exists, then "G2.Key", ... + * + * \param key key name + * \param groupPrefix the group prefix name + * \return a vector of fully qualified groups ordered by decresing relevance + */ + std::vector getSubGroups(const std::string& groupName, + std::string groupPrefix) const + { + std::vector groupNames; + /* + if (groupPrefix == "" && + (params_.hasSub(groupName) || defaultParams_.hasSub(groupName)) + { + groupNames.push_back(groupName); + return groupNames; + } + */ + auto compoundGroup = groupPrefix.empty()? groupName : groupPrefix + "." + groupName; + auto dot = groupPrefix.rfind("."); + + while (dot != std::string::npos) + { + groupPrefix = groupPrefix.substr(0, dot); + compoundGroup = groupPrefix + "." + groupName; + if (params_.hasSub(compoundGroup) || defaultParams_.hasSub(compoundGroup)) + groupNames.push_back(compoundGroup); + dot = groupPrefix.rfind("."); + } + + if (params_.hasSub(groupName) || defaultParams_.hasSub(groupName)) + groupNames.push_back(groupName); + + return groupNames; + } + /** \brief print the hierarchical parameter tree to stream * * \param stream the output stream to print to diff --git a/dumux/common/parameters.hh b/dumux/common/parameters.hh index b01b9aa1ad..4ae00d23f8 100644 --- a/dumux/common/parameters.hh +++ b/dumux/common/parameters.hh @@ -454,6 +454,13 @@ inline bool hasParam(const std::string& param) inline bool hasParamInGroup(const std::string& paramGroup, const std::string& param) { return Parameters::getTree().hasKeyInGroup(param, paramGroup); } +/*! + * \ingroup Common + * \brief Get a list of sub groups from the parameter tree sorted by relevance + * \return A vector of fully qualified subGroup names sorted by descending relevance. + */ +inline std::vector getSubGroups(const std::string& paramGroup, const std::string& subGroupName) +{ return Parameters::getTree().getSubGroups(subGroupName, paramGroup); } } // namespace Dumux #endif diff --git a/dumux/linear/CMakeLists.txt b/dumux/linear/CMakeLists.txt index 6cdfe68ee2..14e0505b49 100644 --- a/dumux/linear/CMakeLists.txt +++ b/dumux/linear/CMakeLists.txt @@ -2,6 +2,7 @@ install(FILES amgbackend.hh amgparallelhelpers.hh amgtraits.hh +genericistlbackend.hh linearsolvertraits.hh linearsolveracceptsmultitypematrix.hh matrixconverter.hh diff --git a/dumux/linear/genericistlbackend.hh b/dumux/linear/genericistlbackend.hh new file mode 100644 index 0000000000..75f10fc35b --- /dev/null +++ b/dumux/linear/genericistlbackend.hh @@ -0,0 +1,261 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *****************************************************************************/ +/*! + * \file + * \ingroup Linear + * \brief Provides a generic linear solver based on the ISTL that chooses the + * solver and preconditioner at runtime. Needs dune version 2.7.1 or + * higher + */ + +#ifndef DUMUX_GENERIC_ISTLBACKEND_HH +#define DUMUX_GENERIC_ISTLBACKEND_HH + +#include +#include +#include + +#include +#include +#include + +// preconditioners +#include +#include + +// solvers +#include + +#if DUNE_VERSION_NEWER_REV(DUNE_ISTL,2,7,1) + +namespace Dumux +{ +/*! + * \ingroup Linear + * \brief A linear solver using the ISTL solver factory + * allowing choosing the solver and preconditioner + * at runtime. + */ +template +class GenericIstlBackend : public LinearSolver +{ + using GridView = typename GridGeometry::GridView; + using AMGTraits = AmgTraits; + using Grid = typename GridView::Grid; + using LinearOperator = typename AMGTraits::LinearOperator; + using ScalarProduct = typename AMGTraits::ScalarProduct; + using VType = typename AMGTraits::VType; + using Comm = typename AMGTraits::Comm; + using BCRSMat = typename AMGTraits::LinearOperator::matrix_type; + using DofMapper = typename AMGTraits::DofMapper; + +public: + /*! + * \brief Construct the backend for the sequential case only + * + * \param paramGroup the parameter group for parameter lookup + */ + GenericIstlBackend(const std::string& paramGroup = "") + : firstCall_(true) + { + if (Dune::MPIHelper::getCollectiveCommunication().size() > 1) + DUNE_THROW(Dune::InvalidStateException, "Using sequential constructor for parallel run. Use signature with gridView and dofMapper!"); + convertParameterTree(paramGroup); + } + /*! + * \brief Construct the backend for parallel or sequential runs + * + * \param gridView the grid view on which we are performing the multi-grid + * \param dofMapper an index mapper for dof entities + * \param paramGroup the parameter group for parameter lookup + */ + GenericIstlBackend(const GridView& gridView, + const DofMapper& dofMapper, + const std::string& paramGroup = "") + : phelper_(std::make_shared>(gridView, dofMapper)) + , firstCall_(true) + { + convertParameterTree(paramGroup); + } + /*! + * \brief Solve a linear system. + * + * \param A the matrix + * \param x the seeked solution vector, containing the initial solution upon entry + * \param b the right hand side vector + */ + bool solve(Matrix& A, Vector& x, Vector& b) + { + int rank = 0; + std::shared_ptr comm; + std::shared_ptr fop; + std::shared_ptr sp; // not used. + +#if HAVE_MPI + if constexpr (AMGTraits::isParallel) + prepareLinearAlgebraParallel(A, b, comm, fop, sp, *phelper_, firstCall_); + else + prepareLinearAlgebraSequential(A, comm, fop, sp); +#else + prepareLinearAlgebraSequential(A, comm, fop, sp); +#endif + + if (firstCall_) + { + Dune::initSolverFactories(); + } + try{ + std::shared_ptr> solver = getSolverFromFactory(fop, params_); + Dune::InverseOperatorResult res; + solver->apply(x,b,result_); + }catch(Dune::Exception& e){ + std::cerr << "Could not create solver" << std::endl; + std::cerr << e.what() << std::endl; + throw e; + } + firstCall_ = false; + return result_.converged; + } +private: + + void convertParameterTree(const std::string& paramGroup="") + { + const auto& loggingTree = Parameters::getTree(); + auto matchingGroups = loggingTree.getSubGroups("LinearSolver", + paramGroup); + + bool doThrow{}; + + for (const auto& transPair : istl2DumuxSolverParams) + { + for (const auto fullGroup : matchingGroups) + { + auto istlName = fullGroup+"."+transPair[0]; + auto dumuxName = fullGroup+"."+transPair[1]; + if(loggingTree.hasKeyOrDefaultKey(dumuxName)) + { + if(loggingTree.hasKeyOrDefaultKey(istlName)) + { + std::cerr << "Found equivalent keys " << istlName + << " " << dumuxName << std::endl + << "Please use only one (e.g. " << dumuxName + << ")." << std::endl; + doThrow = true; + } + params_[transPair[0]] = loggingTree.get(dumuxName); + break; + } + else if (loggingTree.hasKey(istlName)) + { + params_[transPair[0]] = loggingTree.get(istlName); + break; + } + } + } + + for (const auto& transPair : istl2DumuxPreconditionerParams) + { + for (const auto fullGroup : matchingGroups) + { + auto istlName = fullGroup+".preconditioner."+transPair[0]; + auto dumuxName = fullGroup+"."+transPair[1]; + if(loggingTree.hasKey(dumuxName)) + { + if(loggingTree.hasKeyOrDefaultKey(istlName)) + { + std::cerr << "Found equivalent keys " << istlName + << " " << dumuxName << std::endl + << "Please use only one (e.g. " << dumuxName + << ")." << std::endl; + doThrow = true; + } + params_["preconditioner."+transPair[0]] = loggingTree.get(dumuxName); + break; + } + else if (loggingTree.hasKeyOrDefaultKey(istlName)) + { + params_["preconditioner."+transPair[0]] = loggingTree.get(istlName); + break; + } + } + } + params_.report(); + if (!params_.hasKey("type")) + // prevent throw in solve + DUNE_THROW(Dune::InvalidStateException, "Solverfactory needs a specified \"type\" key to select the solver"); + + if (doThrow) + DUNE_THROW(Dune::InvalidStateException, "Ambiguous parameters used for linear solver"); + } + + static std::vector > istl2DumuxSolverParams; + static std::vector > istl2DumuxPreconditionerParams; + std::shared_ptr> phelper_; + bool firstCall_; + Dune::InverseOperatorResult result_; + Dune::ParameterTree params_; +}; + +template +std::vector > GenericIstlBackend::istl2DumuxSolverParams = + { + {"verbose", "Verbosity"}, {"maxit", "MaxIterations"}, + {"reduction", "ResidualReduction"}, {"type", "Type"}, + {"restart", "Restart"}, // cycles before restarting + // maximum number of vectors to store for orthogonalization + {"mmax", "MaxOrthogonalizationVectors"} + }; + +template +std::vector > GenericIstlBackend::istl2DumuxPreconditionerParams = + { + {"verbosity", "PreconditionerVerbosity"}, {"type", "PreconditionerType"}, + {"iterations", "PreconditionerIterations"}, {"relaxation", "PreconditionerRelaxation"}, + {"n", "ILUOrder"}, {"resort", "ILUResort"}, + {"smootherRelaxation", "AmgSmootherRelaxation"}, + {"smootherIterations", "AmgSmootherIterations"}, + {"maxLevel", "AmgMaxLevel"}, {"coarsenTarget", "AmgCoarsenTarget"}, + {"minCoarseningRate", "MinCoarseningRate"}, + {"prolongationDampingFactor", "AmgProlongationDampingFactor"}, + {"alpha", "AmgAlpha"}, {"beta", "AmgBeta"}, + {"additive", "AmgAdditive"}, {"gamma", "AmgGamma"}, + {"preSteps", "AmgPreSmoothingSteps"}, {"postSteps", "AmgPostSmoothingSteps"}, + {"criterionSymmetric", "AmgCriterionSymmetric"}, {"strengthMeasure", "AmgStrengthMeasure"}, + {"diagonalRowIndex", "AmgDiagonalRowIndex"}, + {"defaultAggregationSizeMode", "DefaultAggregationSizeMode"}, + {"defaultAggregationDimension", "defaultAggregationDimension"}, + {"maxAggregateDistance", "MaxAggregateDistance"}, + {"minAggregateSize", "MinAggregateSize"}, + {"maxAggregateSize", "MaxAggregateSize"} + }; + +template +using IstlSolverBackend = GenericIstlBackend< + GetPropType, + GetPropType, + GetPropType>; +} // end namespace Dumux +#else +#warn "Generic ISTL backend needs dune-istl > 2.7.0!" +#warn "Ignoring configuration parameters and falling back to AMG backend." +#include "amgbackend.hh" +template +using IstlSolverBackend = AMGBackend; +#endif // DUNE version check +#endif // DUMUX_GENERIC_ISTLBACKEND_HH -- GitLab From aabf6701a96474588e56e38849caaef3bbf0b047 Mon Sep 17 00:00:00 2001 From: Markus Blatt Date: Sun, 26 Jan 2020 10:02:54 +0100 Subject: [PATCH 02/27] [test] Use generic istl backend for shallow water dam break problem. --- test/freeflow/shallowwater/dambreak/main.cc | 7 ++++--- test/freeflow/shallowwater/dambreak/params.input | 10 ++++++++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/test/freeflow/shallowwater/dambreak/main.cc b/test/freeflow/shallowwater/dambreak/main.cc index 55cdcdc79a..79816452c7 100644 --- a/test/freeflow/shallowwater/dambreak/main.cc +++ b/test/freeflow/shallowwater/dambreak/main.cc @@ -39,8 +39,9 @@ #include #include -#include -#include +//#include +#include + #include #include @@ -123,7 +124,7 @@ int main(int argc, char** argv) try auto assembler = std::make_shared(problem, gridGeometry, gridVariables, timeLoop, xOld); // the linear solver - using LinearSolver = AMGBiCGSTABBackend>; + using LinearSolver = Dumux::IstlSolverBackend; auto linearSolver = std::make_shared(leafGridView, gridGeometry->dofMapper()); // the non-linear solver diff --git a/test/freeflow/shallowwater/dambreak/params.input b/test/freeflow/shallowwater/dambreak/params.input index 67c55fab56..e6ccb7fe55 100644 --- a/test/freeflow/shallowwater/dambreak/params.input +++ b/test/freeflow/shallowwater/dambreak/params.input @@ -15,3 +15,13 @@ Cells1 = 25 [Newton] EnablePartialReassembly = true EnableDynamicOutput = false + +[LinearSolver] +Type = cgsolver +MaxIterations = 80 +PreconditionerType = amg +PreconditionerVerbosity = 0 +AmgMaxLevel = 2 +AmgPreSmoothingSteps = 1 +AmgPostSmoothingSteps = 1 +CriterionSymmetric = true -- GitLab From 5d3ce16b55eacf5aa463c76e19ae0993d635919c Mon Sep 17 00:00:00 2001 From: Markus Blatt Date: Mon, 27 Jan 2020 20:46:20 +0100 Subject: [PATCH 03/27] [cleanup][solver] Removed commented code --- dumux/common/loggingparametertree.hh | 8 -------- test/freeflow/shallowwater/dambreak/main.cc | 1 - 2 files changed, 9 deletions(-) diff --git a/dumux/common/loggingparametertree.hh b/dumux/common/loggingparametertree.hh index 0dc766d7ef..47ea8f898b 100644 --- a/dumux/common/loggingparametertree.hh +++ b/dumux/common/loggingparametertree.hh @@ -126,14 +126,6 @@ public: std::string groupPrefix) const { std::vector groupNames; - /* - if (groupPrefix == "" && - (params_.hasSub(groupName) || defaultParams_.hasSub(groupName)) - { - groupNames.push_back(groupName); - return groupNames; - } - */ auto compoundGroup = groupPrefix.empty()? groupName : groupPrefix + "." + groupName; auto dot = groupPrefix.rfind("."); diff --git a/test/freeflow/shallowwater/dambreak/main.cc b/test/freeflow/shallowwater/dambreak/main.cc index 79816452c7..6c0fbb1219 100644 --- a/test/freeflow/shallowwater/dambreak/main.cc +++ b/test/freeflow/shallowwater/dambreak/main.cc @@ -39,7 +39,6 @@ #include #include -//#include #include #include -- GitLab From ceae02f6a5a6a69fb8d97bcf4ddd3f97ea9baabd Mon Sep 17 00:00:00 2001 From: Markus Blatt Date: Mon, 27 Jan 2020 20:47:10 +0100 Subject: [PATCH 04/27] [cleanup][solver] Fixed typo in documentation --- dumux/common/loggingparametertree.hh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dumux/common/loggingparametertree.hh b/dumux/common/loggingparametertree.hh index 47ea8f898b..4018a99d1e 100644 --- a/dumux/common/loggingparametertree.hh +++ b/dumux/common/loggingparametertree.hh @@ -66,7 +66,7 @@ public: bool hasKey(const std::string& key) const { return params_.hasKey(key); } - /** \brief test for key (even in default parameters + /** \brief test for key (even in default parameters) * * Tests whether given key exists. * @@ -120,7 +120,7 @@ public: * * \param key key name * \param groupPrefix the group prefix name - * \return a vector of fully qualified groups ordered by decresing relevance + * \return a vector of fully qualified groups ordered by decreasing relevance */ std::vector getSubGroups(const std::string& groupName, std::string groupPrefix) const -- GitLab From cf36a587c71d20eaaa0f0fda82918a6d07bdee97 Mon Sep 17 00:00:00 2001 From: Markus Blatt Date: Mon, 27 Jan 2020 20:47:38 +0100 Subject: [PATCH 05/27] Commit throw exceptions in the setup or solve. --- dumux/linear/genericistlbackend.hh | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/dumux/linear/genericistlbackend.hh b/dumux/linear/genericistlbackend.hh index 75f10fc35b..f06f0e7d53 100644 --- a/dumux/linear/genericistlbackend.hh +++ b/dumux/linear/genericistlbackend.hh @@ -120,12 +120,20 @@ public: { Dune::initSolverFactories(); } + std::shared_ptr> solver; try{ - std::shared_ptr> solver = getSolverFromFactory(fop, params_); - Dune::InverseOperatorResult res; + solver = getSolverFromFactory(fop, params_); + } + catch(Dune::Exception& e){ + std::cerr << "Could not create solver with factory" << std::endl; + std::cerr << e.what() << std::endl; + throw e; + } + try + { solver->apply(x,b,result_); }catch(Dune::Exception& e){ - std::cerr << "Could not create solver" << std::endl; + std::cerr << "Exception thrown during linear solve." << std::endl; std::cerr << e.what() << std::endl; throw e; } -- GitLab From aa066372f1ccf265672bf99dcea6d4757303a789 Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Fri, 24 Jan 2020 18:49:17 +0100 Subject: [PATCH 06/27] [test][richards][parallel][lens] Use istl solver factory backend --- test/porousmediumflow/richards/implicit/lens/main.cc | 5 ++--- test/porousmediumflow/richards/implicit/lens/params.input | 8 +++++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/test/porousmediumflow/richards/implicit/lens/main.cc b/test/porousmediumflow/richards/implicit/lens/main.cc index 06ab3fc8c8..1a095ab1d6 100644 --- a/test/porousmediumflow/richards/implicit/lens/main.cc +++ b/test/porousmediumflow/richards/implicit/lens/main.cc @@ -38,8 +38,7 @@ #include #include -#include -#include +#include #include #include @@ -144,7 +143,7 @@ int main(int argc, char** argv) try auto assembler = std::make_shared(problem, gridGeometry, gridVariables, timeLoop, xOld); // the linear solver - using LinearSolver = AMGBiCGSTABBackend>; + using LinearSolver = Dumux::GenericIstlBackend; auto linearSolver = std::make_shared(leafGridView, gridGeometry->dofMapper()); // the non-linear solver diff --git a/test/porousmediumflow/richards/implicit/lens/params.input b/test/porousmediumflow/richards/implicit/lens/params.input index 89b7a2d41f..f247d2d9cf 100644 --- a/test/porousmediumflow/richards/implicit/lens/params.input +++ b/test/porousmediumflow/richards/implicit/lens/params.input @@ -8,8 +8,14 @@ Cells = 24 16 [Problem] Name = richardslens -EnableGravity = 1 # enable gravity +EnableGravity = true # enable gravity [Newton] TargetSteps = 18 # set the "desirable" number of Newton iterations of a time step EnableChop = true # chop for better convergence + +[LinearSolver] +Type = bicgstabsolver +PreconditionerType = amg +AmgMaxLevel = 2 +AmgAccumulationMode = atOnce -- GitLab From d6284598cfb828b67a88e29c8e4070f5ca9fc578 Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Wed, 29 Jan 2020 14:13:19 +0100 Subject: [PATCH 07/27] [solver][istl] Rename GenericIstlBackend to IstlSolverFactoryBackend. Remove TypeTag alias. --- dumux/linear/CMakeLists.txt | 2 +- ...backend.hh => istlsolverfactorybackend.hh} | 61 +++++++++---------- test/freeflow/shallowwater/dambreak/main.cc | 18 +++++- .../richards/implicit/lens/main.cc | 19 +++++- 4 files changed, 61 insertions(+), 39 deletions(-) rename dumux/linear/{genericistlbackend.hh => istlsolverfactorybackend.hh} (87%) diff --git a/dumux/linear/CMakeLists.txt b/dumux/linear/CMakeLists.txt index 14e0505b49..f9ffe34368 100644 --- a/dumux/linear/CMakeLists.txt +++ b/dumux/linear/CMakeLists.txt @@ -2,7 +2,7 @@ install(FILES amgbackend.hh amgparallelhelpers.hh amgtraits.hh -genericistlbackend.hh +istlsolverfactorybackend.hh linearsolvertraits.hh linearsolveracceptsmultitypematrix.hh matrixconverter.hh diff --git a/dumux/linear/genericistlbackend.hh b/dumux/linear/istlsolverfactorybackend.hh similarity index 87% rename from dumux/linear/genericistlbackend.hh rename to dumux/linear/istlsolverfactorybackend.hh index f06f0e7d53..30862a982b 100644 --- a/dumux/linear/genericistlbackend.hh +++ b/dumux/linear/istlsolverfactorybackend.hh @@ -20,20 +20,15 @@ * \file * \ingroup Linear * \brief Provides a generic linear solver based on the ISTL that chooses the - * solver and preconditioner at runtime. Needs dune version 2.7.1 or - * higher + * solver and preconditioner at runtime */ -#ifndef DUMUX_GENERIC_ISTLBACKEND_HH -#define DUMUX_GENERIC_ISTLBACKEND_HH - -#include -#include -#include +#ifndef DUMUX_LINEAR_ISTL_SOLVERFACTORYBACKEND_HH +#define DUMUX_LINEAR_ISTL_SOLVERFACTORYBACKEND_HH +#include #include #include -#include // preconditioners #include @@ -42,18 +37,24 @@ // solvers #include +#include +#include +#include + #if DUNE_VERSION_NEWER_REV(DUNE_ISTL,2,7,1) -namespace Dumux -{ +namespace Dumux { + /*! * \ingroup Linear - * \brief A linear solver using the ISTL solver factory + * \brief A linear solver using the dune-istl solver factory * allowing choosing the solver and preconditioner * at runtime. + * \note the solvers are configured via the input file + * \note Requires Dune version 2.7.1 or newer */ template -class GenericIstlBackend : public LinearSolver +class IstlSolverFactoryBackend : public LinearSolver { using GridView = typename GridGeometry::GridView; using AMGTraits = AmgTraits; @@ -71,13 +72,14 @@ public: * * \param paramGroup the parameter group for parameter lookup */ - GenericIstlBackend(const std::string& paramGroup = "") - : firstCall_(true) + IstlSolverFactoryBackend(const std::string& paramGroup = "") + : firstCall_(true) { if (Dune::MPIHelper::getCollectiveCommunication().size() > 1) DUNE_THROW(Dune::InvalidStateException, "Using sequential constructor for parallel run. Use signature with gridView and dofMapper!"); convertParameterTree(paramGroup); } + /*! * \brief Construct the backend for parallel or sequential runs * @@ -85,14 +87,15 @@ public: * \param dofMapper an index mapper for dof entities * \param paramGroup the parameter group for parameter lookup */ - GenericIstlBackend(const GridView& gridView, - const DofMapper& dofMapper, - const std::string& paramGroup = "") - : phelper_(std::make_shared>(gridView, dofMapper)) - , firstCall_(true) + IstlSolverFactoryBackend(const GridView& gridView, + const DofMapper& dofMapper, + const std::string& paramGroup = "") + : phelper_(std::make_shared>(gridView, dofMapper)) + , firstCall_(true) { convertParameterTree(paramGroup); } + /*! * \brief Solve a linear system. * @@ -221,7 +224,7 @@ private: }; template -std::vector > GenericIstlBackend::istl2DumuxSolverParams = +std::vector > IstlSolverFactoryBackend::istl2DumuxSolverParams = { {"verbose", "Verbosity"}, {"maxit", "MaxIterations"}, {"reduction", "ResidualReduction"}, {"type", "Type"}, @@ -231,7 +234,7 @@ std::vector > GenericIstlBackend -std::vector > GenericIstlBackend::istl2DumuxPreconditionerParams = +std::vector > IstlSolverFactoryBackend::istl2DumuxPreconditionerParams = { {"verbosity", "PreconditionerVerbosity"}, {"type", "PreconditionerType"}, {"iterations", "PreconditionerIterations"}, {"relaxation", "PreconditionerRelaxation"}, @@ -253,17 +256,9 @@ std::vector > GenericIstlBackend -using IstlSolverBackend = GenericIstlBackend< - GetPropType, - GetPropType, - GetPropType>; } // end namespace Dumux + #else -#warn "Generic ISTL backend needs dune-istl > 2.7.0!" -#warn "Ignoring configuration parameters and falling back to AMG backend." -#include "amgbackend.hh" -template -using IstlSolverBackend = AMGBackend; +#warning "Generic dune-istl solver factory backend needs dune-istl >= 2.7.1!" #endif // DUNE version check -#endif // DUMUX_GENERIC_ISTLBACKEND_HH +#endif // header guard diff --git a/test/freeflow/shallowwater/dambreak/main.cc b/test/freeflow/shallowwater/dambreak/main.cc index 6c0fbb1219..7b3d94b4f5 100644 --- a/test/freeflow/shallowwater/dambreak/main.cc +++ b/test/freeflow/shallowwater/dambreak/main.cc @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -39,7 +40,14 @@ #include #include -#include + +#include + +#if DUNE_VERSION_NEWER_REV(DUNE_ISTL,2,7,1) +#include +#else +#include +#endif #include @@ -123,7 +131,13 @@ int main(int argc, char** argv) try auto assembler = std::make_shared(problem, gridGeometry, gridVariables, timeLoop, xOld); // the linear solver - using LinearSolver = Dumux::IstlSolverBackend; +#if DUNE_VERSION_NEWER_REV(DUNE_ISTL,2,7,1) + using Matrix = GetPropType; + using Vector = Dune::BlockVector>; + using LinearSolver = IstlSolverFactoryBackend; +#else + using LinearSolver = AMGBiCGSTABBackend>; +#endif auto linearSolver = std::make_shared(leafGridView, gridGeometry->dofMapper()); // the non-linear solver diff --git a/test/porousmediumflow/richards/implicit/lens/main.cc b/test/porousmediumflow/richards/implicit/lens/main.cc index 1a095ab1d6..bb5251ec2a 100644 --- a/test/porousmediumflow/richards/implicit/lens/main.cc +++ b/test/porousmediumflow/richards/implicit/lens/main.cc @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -37,10 +38,15 @@ #include #include #include +#include -#include -#include +#if DUNE_VERSION_NEWER_REV(DUNE_ISTL,2,7,1) +#include +#else +#include +#endif +#include #include #include @@ -143,7 +149,14 @@ int main(int argc, char** argv) try auto assembler = std::make_shared(problem, gridGeometry, gridVariables, timeLoop, xOld); // the linear solver - using LinearSolver = Dumux::GenericIstlBackend; +#if DUNE_VERSION_NEWER_REV(DUNE_ISTL,2,7,1) + using Matrix = GetPropType; + using Vector = Dune::BlockVector>; + using LinearSolver = IstlSolverFactoryBackend; +#else + using LinearSolver = AMGBiCGSTABBackend>; +#endif + auto linearSolver = std::make_shared(leafGridView, gridGeometry->dofMapper()); // the non-linear solver -- GitLab From 05ca2c5cbe5103c2969fb70849d6698640a16c44 Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Wed, 29 Jan 2020 15:54:22 +0100 Subject: [PATCH 08/27] [solver] Use structured bindings --- dumux/linear/istlsolverfactorybackend.hh | 25 ++++++++++++------------ 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/dumux/linear/istlsolverfactorybackend.hh b/dumux/linear/istlsolverfactorybackend.hh index 30862a982b..f622635aed 100644 --- a/dumux/linear/istlsolverfactorybackend.hh +++ b/dumux/linear/istlsolverfactorybackend.hh @@ -148,17 +148,16 @@ private: void convertParameterTree(const std::string& paramGroup="") { const auto& loggingTree = Parameters::getTree(); - auto matchingGroups = loggingTree.getSubGroups("LinearSolver", - paramGroup); + auto matchingGroups = loggingTree.getSubGroups("LinearSolver", paramGroup); - bool doThrow{}; + bool doThrow = false; - for (const auto& transPair : istl2DumuxSolverParams) + for (const auto& [istlKey, dumuxKey] : istl2DumuxSolverParams) { for (const auto fullGroup : matchingGroups) { - auto istlName = fullGroup+"."+transPair[0]; - auto dumuxName = fullGroup+"."+transPair[1]; + auto istlName = fullGroup + "." + istlKey; + auto dumuxName = fullGroup + "." + dumuxKey; if(loggingTree.hasKeyOrDefaultKey(dumuxName)) { if(loggingTree.hasKeyOrDefaultKey(istlName)) @@ -169,23 +168,23 @@ private: << ")." << std::endl; doThrow = true; } - params_[transPair[0]] = loggingTree.get(dumuxName); + params_[istlKey] = loggingTree.get(dumuxName); break; } else if (loggingTree.hasKey(istlName)) { - params_[transPair[0]] = loggingTree.get(istlName); + params_[istlKey] = loggingTree.get(istlName); break; } } } - for (const auto& transPair : istl2DumuxPreconditionerParams) + for (const auto& [istlKey, dumuxKey] : istl2DumuxPreconditionerParams) { for (const auto fullGroup : matchingGroups) { - auto istlName = fullGroup+".preconditioner."+transPair[0]; - auto dumuxName = fullGroup+"."+transPair[1]; + auto istlName = fullGroup + ".preconditioner." + istlKey; + auto dumuxName = fullGroup + "." + dumuxKey; if(loggingTree.hasKey(dumuxName)) { if(loggingTree.hasKeyOrDefaultKey(istlName)) @@ -196,12 +195,12 @@ private: << ")." << std::endl; doThrow = true; } - params_["preconditioner."+transPair[0]] = loggingTree.get(dumuxName); + params_["preconditioner." + istlKey] = loggingTree.get(dumuxName); break; } else if (loggingTree.hasKeyOrDefaultKey(istlName)) { - params_["preconditioner."+transPair[0]] = loggingTree.get(istlName); + params_["preconditioner." + istlKey] = loggingTree.get(istlName); break; } } -- GitLab From d8d8390c52062975ce99041299473a088508a711 Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Wed, 29 Jan 2020 16:04:27 +0100 Subject: [PATCH 09/27] [solver] Simplify translate using a bit more memory --- dumux/linear/istlsolverfactorybackend.hh | 113 +++++++++-------------- 1 file changed, 45 insertions(+), 68 deletions(-) diff --git a/dumux/linear/istlsolverfactorybackend.hh b/dumux/linear/istlsolverfactorybackend.hh index f622635aed..ec261f841a 100644 --- a/dumux/linear/istlsolverfactorybackend.hh +++ b/dumux/linear/istlsolverfactorybackend.hh @@ -67,6 +67,9 @@ class IstlSolverFactoryBackend : public LinearSolver using DofMapper = typename AMGTraits::DofMapper; public: + //! translation table for solver parameters + static std::vector > istlToDumuxSolverParams; + /*! * \brief Construct the backend for the sequential case only * @@ -150,9 +153,7 @@ private: const auto& loggingTree = Parameters::getTree(); auto matchingGroups = loggingTree.getSubGroups("LinearSolver", paramGroup); - bool doThrow = false; - - for (const auto& [istlKey, dumuxKey] : istl2DumuxSolverParams) + for (const auto& [istlKey, dumuxKey] : istlToDumuxSolverParams) { for (const auto fullGroup : matchingGroups) { @@ -166,7 +167,7 @@ private: << " " << dumuxName << std::endl << "Please use only one (e.g. " << dumuxName << ")." << std::endl; - doThrow = true; + DUNE_THROW(Dune::InvalidStateException, "Ambiguous parameters used for linear solver"); } params_[istlKey] = loggingTree.get(dumuxName); break; @@ -179,43 +180,11 @@ private: } } - for (const auto& [istlKey, dumuxKey] : istl2DumuxPreconditionerParams) - { - for (const auto fullGroup : matchingGroups) - { - auto istlName = fullGroup + ".preconditioner." + istlKey; - auto dumuxName = fullGroup + "." + dumuxKey; - if(loggingTree.hasKey(dumuxName)) - { - if(loggingTree.hasKeyOrDefaultKey(istlName)) - { - std::cerr << "Found equivalent keys " << istlName - << " " << dumuxName << std::endl - << "Please use only one (e.g. " << dumuxName - << ")." << std::endl; - doThrow = true; - } - params_["preconditioner." + istlKey] = loggingTree.get(dumuxName); - break; - } - else if (loggingTree.hasKeyOrDefaultKey(istlName)) - { - params_["preconditioner." + istlKey] = loggingTree.get(istlName); - break; - } - } - } - params_.report(); + // prevent throw in solve if (!params_.hasKey("type")) - // prevent throw in solve DUNE_THROW(Dune::InvalidStateException, "Solverfactory needs a specified \"type\" key to select the solver"); - - if (doThrow) - DUNE_THROW(Dune::InvalidStateException, "Ambiguous parameters used for linear solver"); } - static std::vector > istl2DumuxSolverParams; - static std::vector > istl2DumuxPreconditionerParams; std::shared_ptr> phelper_; bool firstCall_; Dune::InverseOperatorResult result_; @@ -223,37 +192,45 @@ private: }; template -std::vector > IstlSolverFactoryBackend::istl2DumuxSolverParams = - { - {"verbose", "Verbosity"}, {"maxit", "MaxIterations"}, - {"reduction", "ResidualReduction"}, {"type", "Type"}, - {"restart", "Restart"}, // cycles before restarting - // maximum number of vectors to store for orthogonalization - {"mmax", "MaxOrthogonalizationVectors"} - }; - -template -std::vector > IstlSolverFactoryBackend::istl2DumuxPreconditionerParams = - { - {"verbosity", "PreconditionerVerbosity"}, {"type", "PreconditionerType"}, - {"iterations", "PreconditionerIterations"}, {"relaxation", "PreconditionerRelaxation"}, - {"n", "ILUOrder"}, {"resort", "ILUResort"}, - {"smootherRelaxation", "AmgSmootherRelaxation"}, - {"smootherIterations", "AmgSmootherIterations"}, - {"maxLevel", "AmgMaxLevel"}, {"coarsenTarget", "AmgCoarsenTarget"}, - {"minCoarseningRate", "MinCoarseningRate"}, - {"prolongationDampingFactor", "AmgProlongationDampingFactor"}, - {"alpha", "AmgAlpha"}, {"beta", "AmgBeta"}, - {"additive", "AmgAdditive"}, {"gamma", "AmgGamma"}, - {"preSteps", "AmgPreSmoothingSteps"}, {"postSteps", "AmgPostSmoothingSteps"}, - {"criterionSymmetric", "AmgCriterionSymmetric"}, {"strengthMeasure", "AmgStrengthMeasure"}, - {"diagonalRowIndex", "AmgDiagonalRowIndex"}, - {"defaultAggregationSizeMode", "DefaultAggregationSizeMode"}, - {"defaultAggregationDimension", "defaultAggregationDimension"}, - {"maxAggregateDistance", "MaxAggregateDistance"}, - {"minAggregateSize", "MinAggregateSize"}, - {"maxAggregateSize", "MaxAggregateSize"} - }; +std::vector> +IstlSolverFactoryBackend::istlToDumuxSolverParams = +{ + // solver params + {"verbose", "Verbosity"}, + {"maxit", "MaxIterations"}, + {"reduction", "ResidualReduction"}, + {"type", "Type"}, + {"restart", "Restart"}, // cycles before restarting + {"mmax", "MaxOrthogonalizationVectors"}, + + // preconditioner params + {"preconditioner.verbosity", "PreconditionerVerbosity"}, + {"preconditioner.type", "PreconditionerType"}, + {"preconditioner.iterations", "PreconditionerIterations"}, + {"preconditioner.relaxation", "PreconditionerRelaxation"}, + {"preconditioner.n", "ILUOrder"}, + {"preconditioner.resort", "ILUResort"}, + {"preconditioner.smootherRelaxation", "AmgSmootherRelaxation"}, + {"preconditioner.smootherIterations", "AmgSmootherIterations"}, + {"preconditioner.maxLevel", "AmgMaxLevel"}, + {"preconditioner.coarsenTarget", "AmgCoarsenTarget"}, + {"preconditioner.minCoarseningRate", "MinCoarseningRate"}, + {"preconditioner.prolongationDampingFactor", "AmgProlongationDampingFactor"}, + {"preconditioner.alpha", "AmgAlpha"}, + {"preconditioner.beta", "AmgBeta"}, + {"preconditioner.additive", "AmgAdditive"}, + {"preconditioner.gamma", "AmgGamma"}, + {"preconditioner.preSteps", "AmgPreSmoothingSteps"}, + {"preconditioner.postSteps", "AmgPostSmoothingSteps"}, + {"preconditioner.criterionSymmetric", "AmgCriterionSymmetric"}, + {"preconditioner.strengthMeasure", "AmgStrengthMeasure"}, + {"preconditioner.diagonalRowIndex", "AmgDiagonalRowIndex"}, + {"preconditioner.defaultAggregationSizeMode", "DefaultAggregationSizeMode"}, + {"preconditioner.defaultAggregationDimension", "defaultAggregationDimension"}, + {"preconditioner.maxAggregateDistance", "MaxAggregateDistance"}, + {"preconditioner.minAggregateSize", "MinAggregateSize"}, + {"preconditioner.maxAggregateSize", "MaxAggregateSize"} +}; } // end namespace Dumux -- GitLab From 7656351860db1965f22c2f2cb62be36da771e4ea Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Wed, 29 Jan 2020 17:04:07 +0100 Subject: [PATCH 10/27] [params] Move global defaults for linear solver to local defaults in the solver class --- CHANGELOG.md | 2 ++ dumux/linear/istlsolverfactorybackend.hh | 21 ++++++++++++++++++--- dumux/linear/solver.hh | 10 +++++----- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a36b953e7..fc0be3f2c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,8 @@ Differences Between DuMuX 3.2 and DuMuX 3.1 - __Van Genuchten__: Corrected VanGenuchten-Mualem exponent in the non-wetting saturation formula (`1/3` instead of `1/2` (or `l`, see above)) - __Van Genuchten__: Corrected VanGenuchten-Mualem implementation of `dkrn/dSw` - __AMGBackend__: The internal structure of the AMGBackend and the ParallelISTLHelper has been overhauled, as only used by the AMG, we did not make the changes backwards-compatible +- The global default parameters for linear solvers have been removed and moved to the class `LinearSolver`. +This only affects users that directly obtain this parameter via `getParam` somewhere in the code. - __Change matrix block arrangement for staggered models__: The matrix block structure has been adapted such that it complies with the literature standard, i.e., having the velocity block (C) on `M[0][0]` rather than on `M[1][1]`. This also requires re-arranging the submodels and properties in dumux-multidomain such that the face-related classes and vector entries now appear before the cell-centered ones. diff --git a/dumux/linear/istlsolverfactorybackend.hh b/dumux/linear/istlsolverfactorybackend.hh index ec261f841a..3c5d9706d3 100644 --- a/dumux/linear/istlsolverfactorybackend.hh +++ b/dumux/linear/istlsolverfactorybackend.hh @@ -80,7 +80,9 @@ public: { if (Dune::MPIHelper::getCollectiveCommunication().size() > 1) DUNE_THROW(Dune::InvalidStateException, "Using sequential constructor for parallel run. Use signature with gridView and dofMapper!"); - convertParameterTree(paramGroup); + + resetDefaultParameters(); + convertParameterTree_(paramGroup); } /*! @@ -96,7 +98,8 @@ public: : phelper_(std::make_shared>(gridView, dofMapper)) , firstCall_(true) { - convertParameterTree(paramGroup); + resetDefaultParameters(); + convertParameterTree_(paramGroup); } /*! @@ -146,9 +149,21 @@ public: firstCall_ = false; return result_.converged; } + + //! reset some defaults for the solver parameters + void resetDefaultParameters() + { + params_["restart"] = "10"; + params_["maxit"] = "250"; + params_["reduction"] = "1e-13"; + params_["verbose"] = "0"; + params_["preconditioner.iterations"] = "1"; + params_["preconditioner.relaxation"] = "1.0"; + } + private: - void convertParameterTree(const std::string& paramGroup="") + void convertParameterTree_(const std::string& paramGroup="") { const auto& loggingTree = Parameters::getTree(); auto matchingGroups = loggingTree.getSubGroups("LinearSolver", paramGroup); diff --git a/dumux/linear/solver.hh b/dumux/linear/solver.hh index 328e9604e2..822dee897c 100644 --- a/dumux/linear/solver.hh +++ b/dumux/linear/solver.hh @@ -52,11 +52,11 @@ public: LinearSolver(const std::string& paramGroup = "") : paramGroup_(paramGroup) { - verbosity_ = getParamFromGroup(paramGroup, "LinearSolver.Verbosity"); - maxIter_ = getParamFromGroup(paramGroup, "LinearSolver.MaxIterations"); - residReduction_ = getParamFromGroup(paramGroup, "LinearSolver.ResidualReduction"); - relaxation_ = getParamFromGroup(paramGroup, "LinearSolver.PreconditionerRelaxation"); - precondIter_ = getParamFromGroup(paramGroup, "LinearSolver.PreconditionerIterations"); + verbosity_ = getParamFromGroup(paramGroup, "LinearSolver.Verbosity", 0); + maxIter_ = getParamFromGroup(paramGroup, "LinearSolver.MaxIterations", 250); + residReduction_ = getParamFromGroup(paramGroup, "LinearSolver.ResidualReduction", 1e-13); + relaxation_ = getParamFromGroup(paramGroup, "LinearSolver.PreconditionerRelaxation", 1); + precondIter_ = getParamFromGroup(paramGroup, "LinearSolver.PreconditionerIterations", 1); } /*! -- GitLab From e4177239ce4786b1db67c0b7b131fdd6beb79ac4 Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Wed, 29 Jan 2020 17:05:49 +0100 Subject: [PATCH 11/27] [params] Rename getSubGroups to getParamSubGroups --- dumux/common/parameters.hh | 7 ++++--- dumux/linear/istlsolverfactorybackend.hh | 10 +++++----- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/dumux/common/parameters.hh b/dumux/common/parameters.hh index 4ae00d23f8..1e6733594e 100644 --- a/dumux/common/parameters.hh +++ b/dumux/common/parameters.hh @@ -459,8 +459,9 @@ inline bool hasParamInGroup(const std::string& paramGroup, const std::string& pa * \brief Get a list of sub groups from the parameter tree sorted by relevance * \return A vector of fully qualified subGroup names sorted by descending relevance. */ -inline std::vector getSubGroups(const std::string& paramGroup, const std::string& subGroupName) -{ return Parameters::getTree().getSubGroups(subGroupName, paramGroup); } -} // namespace Dumux +inline std::vector getParamSubGroups(const std::string& subGroupName, const std::string& paramGroup) +{ return Parameters::getTree().getSubGroups(subGroupName, paramGroup); } + +} // end namespace Dumux #endif diff --git a/dumux/linear/istlsolverfactorybackend.hh b/dumux/linear/istlsolverfactorybackend.hh index 3c5d9706d3..c01afb3a6b 100644 --- a/dumux/linear/istlsolverfactorybackend.hh +++ b/dumux/linear/istlsolverfactorybackend.hh @@ -166,15 +166,15 @@ private: void convertParameterTree_(const std::string& paramGroup="") { const auto& loggingTree = Parameters::getTree(); - auto matchingGroups = loggingTree.getSubGroups("LinearSolver", paramGroup); + auto linearSolverGroups = getParamSubGroups("LinearSolver", paramGroup); for (const auto& [istlKey, dumuxKey] : istlToDumuxSolverParams) { - for (const auto fullGroup : matchingGroups) + for (const auto& group : linearSolverGroups) { - auto istlName = fullGroup + "." + istlKey; - auto dumuxName = fullGroup + "." + dumuxKey; - if(loggingTree.hasKeyOrDefaultKey(dumuxName)) + auto istlName = group + "." + istlKey; + auto dumuxName = group + "." + dumuxKey; + if (loggingTree.hasKeyOrDefaultKey(dumuxName)) { if(loggingTree.hasKeyOrDefaultKey(istlName)) { -- GitLab From 9810532d19d0f613d069ad1b461ce97b3e105617 Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Wed, 29 Jan 2020 17:21:35 +0100 Subject: [PATCH 12/27] [istl][solver] Do not use logging tree directly --- dumux/linear/istlsolverfactorybackend.hh | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/dumux/linear/istlsolverfactorybackend.hh b/dumux/linear/istlsolverfactorybackend.hh index c01afb3a6b..4e17853ebd 100644 --- a/dumux/linear/istlsolverfactorybackend.hh +++ b/dumux/linear/istlsolverfactorybackend.hh @@ -165,18 +165,16 @@ private: void convertParameterTree_(const std::string& paramGroup="") { - const auto& loggingTree = Parameters::getTree(); auto linearSolverGroups = getParamSubGroups("LinearSolver", paramGroup); - for (const auto& [istlKey, dumuxKey] : istlToDumuxSolverParams) { for (const auto& group : linearSolverGroups) { auto istlName = group + "." + istlKey; auto dumuxName = group + "." + dumuxKey; - if (loggingTree.hasKeyOrDefaultKey(dumuxName)) + if (hasParam(dumuxName)) { - if(loggingTree.hasKeyOrDefaultKey(istlName)) + if(hasParam(istlName)) { std::cerr << "Found equivalent keys " << istlName << " " << dumuxName << std::endl @@ -184,12 +182,12 @@ private: << ")." << std::endl; DUNE_THROW(Dune::InvalidStateException, "Ambiguous parameters used for linear solver"); } - params_[istlKey] = loggingTree.get(dumuxName); + params_[istlKey] = getParam(dumuxName); break; } - else if (loggingTree.hasKey(istlName)) + else if (hasParam(istlName)) { - params_[istlKey] = loggingTree.get(istlName); + params_[istlKey] = getParam(istlName); break; } } -- GitLab From 179ccbc1fc313cdb50de8a354b712e58b1864d92 Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Wed, 29 Jan 2020 17:23:48 +0100 Subject: [PATCH 13/27] [loggingparamtree] Remove unused function --- dumux/common/loggingparametertree.hh | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/dumux/common/loggingparametertree.hh b/dumux/common/loggingparametertree.hh index 4018a99d1e..fa05227a14 100644 --- a/dumux/common/loggingparametertree.hh +++ b/dumux/common/loggingparametertree.hh @@ -66,16 +66,6 @@ public: bool hasKey(const std::string& key) const { return params_.hasKey(key); } - /** \brief test for key (even in default parameters) - * - * Tests whether given key exists. - * - * \param key key name - * \return true if key exists in structure, otherwise false - */ - bool hasKeyOrDefaultKey(const std::string& key) const - { return params_.hasKey(key) || defaultParams_.hasKey(key); } - /** \brief test for key in group * * Tests whether given key exists in a group. -- GitLab From a53177ac56de2542c297d039c934e168d08ccc3a Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Wed, 29 Jan 2020 18:26:25 +0100 Subject: [PATCH 14/27] [istl][solver] Fix include, use qualified call, initialize in constructor --- dumux/linear/istlsolverfactorybackend.hh | 42 +++++++++++++----------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/dumux/linear/istlsolverfactorybackend.hh b/dumux/linear/istlsolverfactorybackend.hh index 4e17853ebd..ea8b8fa6fc 100644 --- a/dumux/linear/istlsolverfactorybackend.hh +++ b/dumux/linear/istlsolverfactorybackend.hh @@ -36,6 +36,7 @@ // solvers #include +#include #include #include @@ -76,13 +77,13 @@ public: * \param paramGroup the parameter group for parameter lookup */ IstlSolverFactoryBackend(const std::string& paramGroup = "") - : firstCall_(true) + : paramGroup_(paramGroup) + , firstCall_(true) { if (Dune::MPIHelper::getCollectiveCommunication().size() > 1) DUNE_THROW(Dune::InvalidStateException, "Using sequential constructor for parallel run. Use signature with gridView and dofMapper!"); - resetDefaultParameters(); - convertParameterTree_(paramGroup); + reset(); } /*! @@ -95,11 +96,11 @@ public: IstlSolverFactoryBackend(const GridView& gridView, const DofMapper& dofMapper, const std::string& paramGroup = "") - : phelper_(std::make_shared>(gridView, dofMapper)) + : paramGroup_(paramGroup) + , parallelHelper_(std::make_unique>(gridView, dofMapper)) , firstCall_(true) { - resetDefaultParameters(); - convertParameterTree_(paramGroup); + reset(); } /*! @@ -125,31 +126,31 @@ public: prepareLinearAlgebraSequential(A, comm, fop, sp); #endif - if (firstCall_) - { - Dune::initSolverFactories(); - } std::shared_ptr> solver; try{ - solver = getSolverFromFactory(fop, params_); + solver = Dune::getSolverFromFactory(fop, params_); } catch(Dune::Exception& e){ std::cerr << "Could not create solver with factory" << std::endl; std::cerr << e.what() << std::endl; throw e; } - try - { - solver->apply(x,b,result_); - }catch(Dune::Exception& e){ - std::cerr << "Exception thrown during linear solve." << std::endl; - std::cerr << e.what() << std::endl; - throw e; - } + + // solve + solver->apply(x, b, result_); + firstCall_ = false; return result_.converged; } + //! reset the linear solver factory + void reset() + { + resetDefaultParameters(); + convertParameterTree_(paramGroup_); + Dune::initSolverFactories(); + } + //! reset some defaults for the solver parameters void resetDefaultParameters() { @@ -198,7 +199,8 @@ private: DUNE_THROW(Dune::InvalidStateException, "Solverfactory needs a specified \"type\" key to select the solver"); } - std::shared_ptr> phelper_; + const std::string paramGroup_; + std::unique_ptr> parallelHelper_; bool firstCall_; Dune::InverseOperatorResult result_; Dune::ParameterTree params_; -- GitLab From b0a5b0bc5864364c2c4c423284d639c0b0df9b9d Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Wed, 29 Jan 2020 18:27:16 +0100 Subject: [PATCH 15/27] [istl][solver] Fix error message --- dumux/linear/istlsolverfactorybackend.hh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dumux/linear/istlsolverfactorybackend.hh b/dumux/linear/istlsolverfactorybackend.hh index ea8b8fa6fc..31bc333790 100644 --- a/dumux/linear/istlsolverfactorybackend.hh +++ b/dumux/linear/istlsolverfactorybackend.hh @@ -194,9 +194,9 @@ private: } } - // prevent throw in solve + // The type param is mandatory if (!params_.hasKey("type")) - DUNE_THROW(Dune::InvalidStateException, "Solverfactory needs a specified \"type\" key to select the solver"); + DUNE_THROW(Dune::InvalidStateException, "Solver factory needs a specified \"Type\" key to select the solver"); } const std::string paramGroup_; -- GitLab From 63956403a3f4df1ed2394e99920015d63e53f8a8 Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Wed, 29 Jan 2020 18:27:51 +0100 Subject: [PATCH 16/27] [istl][solver] Switch dumux and istl keys translation --- dumux/linear/istlsolverfactorybackend.hh | 70 ++++++++++++------------ 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/dumux/linear/istlsolverfactorybackend.hh b/dumux/linear/istlsolverfactorybackend.hh index 31bc333790..19d65c5f91 100644 --- a/dumux/linear/istlsolverfactorybackend.hh +++ b/dumux/linear/istlsolverfactorybackend.hh @@ -69,7 +69,7 @@ class IstlSolverFactoryBackend : public LinearSolver public: //! translation table for solver parameters - static std::vector > istlToDumuxSolverParams; + static std::vector > dumuxToIstlSolverParams; /*! * \brief Construct the backend for the sequential case only @@ -167,7 +167,7 @@ private: void convertParameterTree_(const std::string& paramGroup="") { auto linearSolverGroups = getParamSubGroups("LinearSolver", paramGroup); - for (const auto& [istlKey, dumuxKey] : istlToDumuxSolverParams) + for (const auto& [dumuxKey, istlKey] : dumuxToIstlSolverParams) { for (const auto& group : linearSolverGroups) { @@ -208,43 +208,43 @@ private: template std::vector> -IstlSolverFactoryBackend::istlToDumuxSolverParams = +IstlSolverFactoryBackend::dumuxToIstlSolverParams = { // solver params - {"verbose", "Verbosity"}, - {"maxit", "MaxIterations"}, - {"reduction", "ResidualReduction"}, - {"type", "Type"}, - {"restart", "Restart"}, // cycles before restarting - {"mmax", "MaxOrthogonalizationVectors"}, + {"Verbosity", "verbose"}, + {"MaxIterations", "maxit"}, + {"ResidualReduction", "reduction"}, + {"Type", "type"}, + {"Restart", "restart"}, // cycles before restarting + {"MaxOrthogonalizationVectors", "mmax"}, // preconditioner params - {"preconditioner.verbosity", "PreconditionerVerbosity"}, - {"preconditioner.type", "PreconditionerType"}, - {"preconditioner.iterations", "PreconditionerIterations"}, - {"preconditioner.relaxation", "PreconditionerRelaxation"}, - {"preconditioner.n", "ILUOrder"}, - {"preconditioner.resort", "ILUResort"}, - {"preconditioner.smootherRelaxation", "AmgSmootherRelaxation"}, - {"preconditioner.smootherIterations", "AmgSmootherIterations"}, - {"preconditioner.maxLevel", "AmgMaxLevel"}, - {"preconditioner.coarsenTarget", "AmgCoarsenTarget"}, - {"preconditioner.minCoarseningRate", "MinCoarseningRate"}, - {"preconditioner.prolongationDampingFactor", "AmgProlongationDampingFactor"}, - {"preconditioner.alpha", "AmgAlpha"}, - {"preconditioner.beta", "AmgBeta"}, - {"preconditioner.additive", "AmgAdditive"}, - {"preconditioner.gamma", "AmgGamma"}, - {"preconditioner.preSteps", "AmgPreSmoothingSteps"}, - {"preconditioner.postSteps", "AmgPostSmoothingSteps"}, - {"preconditioner.criterionSymmetric", "AmgCriterionSymmetric"}, - {"preconditioner.strengthMeasure", "AmgStrengthMeasure"}, - {"preconditioner.diagonalRowIndex", "AmgDiagonalRowIndex"}, - {"preconditioner.defaultAggregationSizeMode", "DefaultAggregationSizeMode"}, - {"preconditioner.defaultAggregationDimension", "defaultAggregationDimension"}, - {"preconditioner.maxAggregateDistance", "MaxAggregateDistance"}, - {"preconditioner.minAggregateSize", "MinAggregateSize"}, - {"preconditioner.maxAggregateSize", "MaxAggregateSize"} + {"PreconditionerVerbosity", "preconditioner.verbosity"}, + {"PreconditionerType", "preconditioner.type"}, + {"PreconditionerIterations", "preconditioner.iterations"}, + {"PreconditionerRelaxation", "preconditioner.relaxation"}, + {"ILUOrder", "preconditioner.n"}, + {"ILUResort", "preconditioner.resort"}, + {"AmgSmootherRelaxation", "preconditioner.smootherRelaxation"}, + {"AmgSmootherIterations", "preconditioner.smootherIterations"}, + {"AmgMaxLevel", "preconditioner.maxLevel"}, + {"AmgCoarsenTarget", "preconditioner.coarsenTarget"}, + {"MinCoarseningRate", "preconditioner.minCoarseningRate"}, + {"AmgProlongationDampingFactor", "preconditioner.prolongationDampingFactor"}, + {"AmgAlpha", "preconditioner.alpha"}, + {"AmgBeta", "preconditioner.beta"}, + {"AmgAdditive", "preconditioner.additive"}, + {"AmgGamma", "preconditioner.gamma"}, + {"AmgPreSmoothingSteps", "preconditioner.preSteps"}, + {"AmgPostSmoothingSteps", "preconditioner.postSteps"}, + {"AmgCriterionSymmetric", "preconditioner.criterionSymmetric"}, + {"AmgStrengthMeasure", "preconditioner.strengthMeasure"}, + {"AmgDiagonalRowIndex", "preconditioner.diagonalRowIndex"}, + {"DefaultAggregationSizeMode", "preconditioner.defaultAggregationSizeMode"}, + {"defaultAggregationDimension", "preconditioner.defaultAggregationDimension"}, + {"MaxAggregateDistance", "preconditioner.maxAggregateDistance"}, + {"MinAggregateSize", "preconditioner.minAggregateSize"}, + {"MaxAggregateSize", "preconditioner.maxAggregateSize"} }; } // end namespace Dumux -- GitLab From fff202cd5d256d7bae87ac859610c45eb8c64574 Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Wed, 29 Jan 2020 18:43:47 +0100 Subject: [PATCH 17/27] [istl][solver] Only allow Dumux parameter names --- dumux/linear/istlsolverfactorybackend.hh | 26 ++++++++---------------- 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/dumux/linear/istlsolverfactorybackend.hh b/dumux/linear/istlsolverfactorybackend.hh index 19d65c5f91..dae993adb1 100644 --- a/dumux/linear/istlsolverfactorybackend.hh +++ b/dumux/linear/istlsolverfactorybackend.hh @@ -167,29 +167,19 @@ private: void convertParameterTree_(const std::string& paramGroup="") { auto linearSolverGroups = getParamSubGroups("LinearSolver", paramGroup); + if (linearSolverGroups.empty()) // no linear solver parameters were specified + return; + for (const auto& [dumuxKey, istlKey] : dumuxToIstlSolverParams) { for (const auto& group : linearSolverGroups) { - auto istlName = group + "." + istlKey; - auto dumuxName = group + "." + dumuxKey; - if (hasParam(dumuxName)) - { - if(hasParam(istlName)) - { - std::cerr << "Found equivalent keys " << istlName - << " " << dumuxName << std::endl - << "Please use only one (e.g. " << dumuxName - << ")." << std::endl; - DUNE_THROW(Dune::InvalidStateException, "Ambiguous parameters used for linear solver"); - } - params_[istlKey] = getParam(dumuxName); - break; - } - else if (hasParam(istlName)) + const auto fullDumuxKey = group + "." + dumuxKey; + const auto value = getParam(fullDumuxKey, ""); + if (!value.empty()) { - params_[istlKey] = getParam(istlName); - break; + params_[istlKey] = value; + break; // skip groups with smaller depth in the tree } } } -- GitLab From 62a3fcadc2c2f908d0e15c1f0ef53aec98cf2dd1 Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Wed, 29 Jan 2020 18:44:28 +0100 Subject: [PATCH 18/27] [istl][solver] Use subgroup Preconditioner Backwards-compatible implementation. Legacy parameter names e.g. PreconditionerIterations will still work but subgroup params overwrite them, e.g. Preconditioner.Iterations. --- dumux/linear/istlsolverfactorybackend.hh | 52 +++++++++++-------- .../shallowwater/dambreak/params.input | 8 +-- .../richards/implicit/lens/params.input | 4 +- 3 files changed, 38 insertions(+), 26 deletions(-) diff --git a/dumux/linear/istlsolverfactorybackend.hh b/dumux/linear/istlsolverfactorybackend.hh index dae993adb1..65cca90660 100644 --- a/dumux/linear/istlsolverfactorybackend.hh +++ b/dumux/linear/istlsolverfactorybackend.hh @@ -209,32 +209,40 @@ IstlSolverFactoryBackend::dumuxToIstlSolverParams = {"MaxOrthogonalizationVectors", "mmax"}, // preconditioner params + // we expect parameters in the subgroup "Preconditioner" + // there are some legacy param names that are still supported + // subgroup parameters overwrite legacy parameters {"PreconditionerVerbosity", "preconditioner.verbosity"}, + {"Preconditioner.Verbosity", "preconditioner.verbosity"}, {"PreconditionerType", "preconditioner.type"}, + {"Preconditioner.Type", "preconditioner.type"}, {"PreconditionerIterations", "preconditioner.iterations"}, + {"Preconditioner.Iterations", "preconditioner.iterations"}, {"PreconditionerRelaxation", "preconditioner.relaxation"}, - {"ILUOrder", "preconditioner.n"}, - {"ILUResort", "preconditioner.resort"}, - {"AmgSmootherRelaxation", "preconditioner.smootherRelaxation"}, - {"AmgSmootherIterations", "preconditioner.smootherIterations"}, - {"AmgMaxLevel", "preconditioner.maxLevel"}, - {"AmgCoarsenTarget", "preconditioner.coarsenTarget"}, - {"MinCoarseningRate", "preconditioner.minCoarseningRate"}, - {"AmgProlongationDampingFactor", "preconditioner.prolongationDampingFactor"}, - {"AmgAlpha", "preconditioner.alpha"}, - {"AmgBeta", "preconditioner.beta"}, - {"AmgAdditive", "preconditioner.additive"}, - {"AmgGamma", "preconditioner.gamma"}, - {"AmgPreSmoothingSteps", "preconditioner.preSteps"}, - {"AmgPostSmoothingSteps", "preconditioner.postSteps"}, - {"AmgCriterionSymmetric", "preconditioner.criterionSymmetric"}, - {"AmgStrengthMeasure", "preconditioner.strengthMeasure"}, - {"AmgDiagonalRowIndex", "preconditioner.diagonalRowIndex"}, - {"DefaultAggregationSizeMode", "preconditioner.defaultAggregationSizeMode"}, - {"defaultAggregationDimension", "preconditioner.defaultAggregationDimension"}, - {"MaxAggregateDistance", "preconditioner.maxAggregateDistance"}, - {"MinAggregateSize", "preconditioner.minAggregateSize"}, - {"MaxAggregateSize", "preconditioner.maxAggregateSize"} + {"Preconditioner.Relaxation", "preconditioner.relaxation"}, + {"Preconditioner.ILUOrder", "preconditioner.n"}, + {"Preconditioner.ILUResort", "preconditioner.resort"}, + {"Preconditioner.AmgSmootherRelaxation", "preconditioner.smootherRelaxation"}, + {"Preconditioner.AmgSmootherIterations", "preconditioner.smootherIterations"}, + {"Preconditioner.AmgMaxLevel", "preconditioner.maxLevel"}, + {"Preconditioner.AmgCoarsenTarget", "preconditioner.coarsenTarget"}, + {"Preconditioner.AmgMinCoarseningRate", "preconditioner.minCoarseningRate"}, + {"Preconditioner.AmgAccumulationMode", "preconditioner.accumulationMode"}, + {"Preconditioner.AmgProlongationDampingFactor", "preconditioner.prolongationDampingFactor"}, + {"Preconditioner.AmgAlpha", "preconditioner.alpha"}, + {"Preconditioner.AmgBeta", "preconditioner.beta"}, + {"Preconditioner.AmgAdditive", "preconditioner.additive"}, + {"Preconditioner.AmgGamma", "preconditioner.gamma"}, + {"Preconditioner.AmgPreSmoothingSteps", "preconditioner.preSteps"}, + {"Preconditioner.AmgPostSmoothingSteps", "preconditioner.postSteps"}, + {"Preconditioner.AmgCriterionSymmetric", "preconditioner.criterionSymmetric"}, + {"Preconditioner.AmgStrengthMeasure", "preconditioner.strengthMeasure"}, + {"Preconditioner.AmgDiagonalRowIndex", "preconditioner.diagonalRowIndex"}, + {"Preconditioner.AmgDefaultAggregationSizeMode", "preconditioner.defaultAggregationSizeMode"}, + {"Preconditioner.AmgDefaultAggregationDimension", "preconditioner.defaultAggregationDimension"}, + {"Preconditioner.AmgMaxAggregateDistance", "preconditioner.maxAggregateDistance"}, + {"Preconditioner.AmgMinAggregateSize", "preconditioner.minAggregateSize"}, + {"Preconditioner.AmgMaxAggregateSize", "preconditioner.maxAggregateSize"} }; } // end namespace Dumux diff --git a/test/freeflow/shallowwater/dambreak/params.input b/test/freeflow/shallowwater/dambreak/params.input index e6ccb7fe55..03b5a00414 100644 --- a/test/freeflow/shallowwater/dambreak/params.input +++ b/test/freeflow/shallowwater/dambreak/params.input @@ -19,9 +19,11 @@ EnableDynamicOutput = false [LinearSolver] Type = cgsolver MaxIterations = 80 -PreconditionerType = amg -PreconditionerVerbosity = 0 + +[LinearSolver.Preconditioner] +Type = amg +Verbosity = 0 AmgMaxLevel = 2 AmgPreSmoothingSteps = 1 AmgPostSmoothingSteps = 1 -CriterionSymmetric = true +AmgCriterionSymmetric = true diff --git a/test/porousmediumflow/richards/implicit/lens/params.input b/test/porousmediumflow/richards/implicit/lens/params.input index f247d2d9cf..72e9e5fedd 100644 --- a/test/porousmediumflow/richards/implicit/lens/params.input +++ b/test/porousmediumflow/richards/implicit/lens/params.input @@ -16,6 +16,8 @@ EnableChop = true # chop for better convergence [LinearSolver] Type = bicgstabsolver -PreconditionerType = amg + +[LinearSolver.Preconditioner] +Type = amg AmgMaxLevel = 2 AmgAccumulationMode = atOnce -- GitLab From aadd9a90422ef8eb952e6bd6c8c6d5f9aeb7c271 Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Wed, 29 Jan 2020 19:40:27 +0100 Subject: [PATCH 19/27] [istl][solver] Cleanup internal structure and interface --- dumux/linear/istlsolverfactorybackend.hh | 88 +++++++++++++++--------- 1 file changed, 56 insertions(+), 32 deletions(-) diff --git a/dumux/linear/istlsolverfactorybackend.hh b/dumux/linear/istlsolverfactorybackend.hh index 65cca90660..78e4dd4f1e 100644 --- a/dumux/linear/istlsolverfactorybackend.hh +++ b/dumux/linear/istlsolverfactorybackend.hh @@ -39,8 +39,8 @@ #include #include -#include -#include +#include +#include #if DUNE_VERSION_NEWER_REV(DUNE_ISTL,2,7,1) @@ -52,20 +52,20 @@ namespace Dumux { * allowing choosing the solver and preconditioner * at runtime. * \note the solvers are configured via the input file - * \note Requires Dune version 2.7.1 or newer + * \note requires Dune version 2.7.1 or newer */ template class IstlSolverFactoryBackend : public LinearSolver { using GridView = typename GridGeometry::GridView; - using AMGTraits = AmgTraits; + using LinearSolverTraits = Dumux::LinearSolverTraits; using Grid = typename GridView::Grid; - using LinearOperator = typename AMGTraits::LinearOperator; - using ScalarProduct = typename AMGTraits::ScalarProduct; - using VType = typename AMGTraits::VType; - using Comm = typename AMGTraits::Comm; - using BCRSMat = typename AMGTraits::LinearOperator::matrix_type; - using DofMapper = typename AMGTraits::DofMapper; + using LinearOperator = typename LinearSolverTraits::LinearOperator; + using ScalarProduct = typename LinearSolverTraits::ScalarProduct; + using VType = typename LinearSolverTraits::VType; + using Comm = typename LinearSolverTraits::Comm; + using BCRSMat = typename LinearSolverTraits::LinearOperator::matrix_type; + using DofMapper = typename LinearSolverTraits::DofMapper; public: //! translation table for solver parameters @@ -97,7 +97,7 @@ public: const DofMapper& dofMapper, const std::string& paramGroup = "") : paramGroup_(paramGroup) - , parallelHelper_(std::make_unique>(gridView, dofMapper)) + , parallelHelper_(std::make_unique>(gridView, dofMapper)) , firstCall_(true) { reset(); @@ -112,31 +112,23 @@ public: */ bool solve(Matrix& A, Vector& x, Vector& b) { - int rank = 0; std::shared_ptr comm; - std::shared_ptr fop; - std::shared_ptr sp; // not used. + std::shared_ptr linearOperator; + std::shared_ptr scalarProduct; // not used. #if HAVE_MPI - if constexpr (AMGTraits::isParallel) - prepareLinearAlgebraParallel(A, b, comm, fop, sp, *phelper_, firstCall_); + if constexpr (LinearSolverTraits::isParallel) + prepareLinearAlgebraParallel(A, b, comm, linearOperator, scalarProduct, *parallelHelper_, firstCall_); else - prepareLinearAlgebraSequential(A, comm, fop, sp); + prepareLinearAlgebraSequential(A, comm, linearOperator, scalarProduct); #else - prepareLinearAlgebraSequential(A, comm, fop, sp); + prepareLinearAlgebraSequential(A, comm, linearOperator, scalarProduct); #endif - std::shared_ptr> solver; - try{ - solver = Dune::getSolverFromFactory(fop, params_); - } - catch(Dune::Exception& e){ - std::cerr << "Could not create solver with factory" << std::endl; - std::cerr << e.what() << std::endl; - throw e; - } + // construct solver + auto solver = getSolverFromFactory_(linearOperator); - // solve + // solve linear system solver->apply(x, b, result_); firstCall_ = false; @@ -148,7 +140,11 @@ public: { resetDefaultParameters(); convertParameterTree_(paramGroup_); - Dune::initSolverFactories(); + checkMandatoryParameters_(); + Dune::initSolverFactories(); + name_ = params_.get("preconditioner.type") + "-preconditioned " + params_.get("type"); + if (params_.get("verbose", 0) > 0) + std::cout << "Initialized linear solver of type: " << name_ << std::endl; } //! reset some defaults for the solver parameters @@ -162,6 +158,16 @@ public: params_["preconditioner.relaxation"] = "1.0"; } + const Dune::InverseOperatorResult& result() const + { + return result_; + } + + const std::string& name() const + { + return name_; + } + private: void convertParameterTree_(const std::string& paramGroup="") @@ -183,19 +189,37 @@ private: } } } + } - // The type param is mandatory + void checkMandatoryParameters_() + { if (!params_.hasKey("type")) - DUNE_THROW(Dune::InvalidStateException, "Solver factory needs a specified \"Type\" key to select the solver"); + DUNE_THROW(Dune::InvalidStateException, "Solver factory needs \"LinearSolver.Type\" parameter to select the solver"); + + if (!params_.hasKey("preconditioner.type")) + DUNE_THROW(Dune::InvalidStateException, "Solver factory needs \"LinearSolver.Preconditioner.Type\" parameter to select the preconditioner"); + } + + auto getSolverFromFactory_(std::shared_ptr& fop) + { + try { return Dune::getSolverFromFactory(fop, params_); } + catch(Dune::Exception& e) + { + std::cerr << "Could not create solver with factory" << std::endl; + std::cerr << e.what() << std::endl; + throw e; + } } const std::string paramGroup_; - std::unique_ptr> parallelHelper_; + std::unique_ptr> parallelHelper_; bool firstCall_; Dune::InverseOperatorResult result_; Dune::ParameterTree params_; + std::string name_; }; +//! translation table for solver parameters template std::vector> IstlSolverFactoryBackend::dumuxToIstlSolverParams = -- GitLab From 4241e9e31a176826590c0ebb63e4d33ed882bb02 Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Fri, 31 Jan 2020 09:24:32 +0100 Subject: [PATCH 20/27] [params] Fix getSubGroup, improve doc, add unit test --- dumux/common/loggingparametertree.hh | 45 ++++++++++++------- .../parameters/test_loggingparametertree.cc | 8 ++++ 2 files changed, 36 insertions(+), 17 deletions(-) diff --git a/dumux/common/loggingparametertree.hh b/dumux/common/loggingparametertree.hh index fa05227a14..a1ab8c1157 100644 --- a/dumux/common/loggingparametertree.hh +++ b/dumux/common/loggingparametertree.hh @@ -101,35 +101,46 @@ public: return false; } - /** \brief test for subgroup in group + /** \brief obtain a vector of all full group names for a specified subgroup name * - * Tests whether given sub group exists in a group. - * Given a group this function starts to look from the back - * for dots. In G1.G2.G3 the function first looks if the key - * "G3.Key" exists, then "G2.Key", ... + * Example: + * ------------ + * For the parameter tree * - * \param key key name - * \param groupPrefix the group prefix name - * \return a vector of fully qualified groups ordered by decreasing relevance + * [G1] + * MyParam1 = 1 + * [G2.G1] + * MyParam2 = 2 + * [G3.G2.G1] + * MyParam3 = 3 + * + * and groupPrefix="G3.G2" and subGroupName="G1" + * this returns a vector with the entries {"G3.G2.G1", "G2.G1", "G1"}. + * If groupPrefix = "G2", it returns {"G2.G1", "G1"}. + * If groupPrefix = "" the returned vector has size 1 (containing subGroupName), + * or size 0 if the subgroup does not exist in the parameter tree. + * + * \param subGroupName the sub group to look for + * \param groupPrefix the group prefix name (potentially prefixing the subgroup) + * \return a vector of fully qualified groups ordered by decreasing tree depth */ - std::vector getSubGroups(const std::string& groupName, + std::vector getSubGroups(const std::string& subGroupName, std::string groupPrefix) const { std::vector groupNames; - auto compoundGroup = groupPrefix.empty()? groupName : groupPrefix + "." + groupName; - auto dot = groupPrefix.rfind("."); + auto compoundGroup = groupPrefix.empty() ? subGroupName : groupPrefix + "." + subGroupName; - while (dot != std::string::npos) + for (std::string::size_type dotPos = 0; dotPos != std::string::npos; dotPos = groupPrefix.rfind(".")) { - groupPrefix = groupPrefix.substr(0, dot); - compoundGroup = groupPrefix + "." + groupName; if (params_.hasSub(compoundGroup) || defaultParams_.hasSub(compoundGroup)) groupNames.push_back(compoundGroup); - dot = groupPrefix.rfind("."); + + groupPrefix = groupPrefix.substr(0, dotPos); + compoundGroup = groupPrefix + "." + subGroupName; } - if (params_.hasSub(groupName) || defaultParams_.hasSub(groupName)) - groupNames.push_back(groupName); + if (params_.hasSub(subGroupName) || defaultParams_.hasSub(subGroupName)) + groupNames.push_back(subGroupName); return groupNames; } diff --git a/test/common/parameters/test_loggingparametertree.cc b/test/common/parameters/test_loggingparametertree.cc index 044b747610..1bdfce986f 100644 --- a/test/common/parameters/test_loggingparametertree.cc +++ b/test/common/parameters/test_loggingparametertree.cc @@ -45,6 +45,14 @@ int main (int argc, char *argv[]) try tEnd = getParamFromGroup("Hulk", "TimeLoop.TEnd"); if (tEnd != 1e6) DUNE_THROW(Dune::InvalidStateException, "TEnd should be 1e6!"); + auto groups = getParamSubGroups("TimeLoop", "Bulk"); + std::cout << "Found the following TimeLoop groups: "; + for (const auto& g : groups) std::cout << g << " "; + std::cout << std::endl; + if (groups.size() != 2) DUNE_THROW(Dune::InvalidStateException, "Wrong number of groups with ending name TimeLoop! (" << groups.size() << ", should be 2)"); + if (groups[0] != "Bulk.TimeLoop") DUNE_THROW(Dune::InvalidStateException, "Wrong order or name of subgroups with ending name TimeLoop!"); + if (groups[1] != "TimeLoop") DUNE_THROW(Dune::InvalidStateException, "Wrong order or name of subgroups with ending name TimeLoop!"); + Parameters::print(); // check the unused keys -- GitLab From b69b4b37436251ccbf19eac733a84fb3ac5d5b2d Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Fri, 31 Jan 2020 09:29:07 +0100 Subject: [PATCH 21/27] [istlsolver] Improve doc --- dumux/linear/istlsolverfactorybackend.hh | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dumux/linear/istlsolverfactorybackend.hh b/dumux/linear/istlsolverfactorybackend.hh index 78e4dd4f1e..88940345c1 100644 --- a/dumux/linear/istlsolverfactorybackend.hh +++ b/dumux/linear/istlsolverfactorybackend.hh @@ -49,8 +49,7 @@ namespace Dumux { /*! * \ingroup Linear * \brief A linear solver using the dune-istl solver factory - * allowing choosing the solver and preconditioner - * at runtime. + * to choose the solver and preconditioner at runtime. * \note the solvers are configured via the input file * \note requires Dune version 2.7.1 or newer */ @@ -89,7 +88,7 @@ public: /*! * \brief Construct the backend for parallel or sequential runs * - * \param gridView the grid view on which we are performing the multi-grid + * \param gridView the grid view for parallel communication via the grid * \param dofMapper an index mapper for dof entities * \param paramGroup the parameter group for parameter lookup */ -- GitLab From b02928d6233490e011b114970b9763ad01423ba1 Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Fri, 31 Jan 2020 09:36:06 +0100 Subject: [PATCH 22/27] [istlsolver] Add support for GMResRestart parameter --- dumux/linear/istlsolverfactorybackend.hh | 1 + 1 file changed, 1 insertion(+) diff --git a/dumux/linear/istlsolverfactorybackend.hh b/dumux/linear/istlsolverfactorybackend.hh index 88940345c1..ca6ed3de9f 100644 --- a/dumux/linear/istlsolverfactorybackend.hh +++ b/dumux/linear/istlsolverfactorybackend.hh @@ -228,6 +228,7 @@ IstlSolverFactoryBackend::dumuxToIstlSolverParams = {"MaxIterations", "maxit"}, {"ResidualReduction", "reduction"}, {"Type", "type"}, + {"GMResRestart", "restart"}, // cycles before restarting {"Restart", "restart"}, // cycles before restarting {"MaxOrthogonalizationVectors", "mmax"}, -- GitLab From 12d0c7d376638c9949af678fb8dc7aac1ee157c5 Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Thu, 27 Feb 2020 09:16:14 +0100 Subject: [PATCH 23/27] [istlfactory] Adjust to new structure after rebase --- dumux/linear/istlsolverfactorybackend.hh | 130 ++++++++++++------ test/freeflow/shallowwater/dambreak/main.cc | 4 +- .../richards/implicit/lens/main.cc | 5 +- 3 files changed, 93 insertions(+), 46 deletions(-) diff --git a/dumux/linear/istlsolverfactorybackend.hh b/dumux/linear/istlsolverfactorybackend.hh index ca6ed3de9f..db03353bed 100644 --- a/dumux/linear/istlsolverfactorybackend.hh +++ b/dumux/linear/istlsolverfactorybackend.hh @@ -39,7 +39,6 @@ #include #include -#include #include #if DUNE_VERSION_NEWER_REV(DUNE_ISTL,2,7,1) @@ -53,22 +52,12 @@ namespace Dumux { * \note the solvers are configured via the input file * \note requires Dune version 2.7.1 or newer */ -template +template class IstlSolverFactoryBackend : public LinearSolver { - using GridView = typename GridGeometry::GridView; - using LinearSolverTraits = Dumux::LinearSolverTraits; - using Grid = typename GridView::Grid; - using LinearOperator = typename LinearSolverTraits::LinearOperator; - using ScalarProduct = typename LinearSolverTraits::ScalarProduct; - using VType = typename LinearSolverTraits::VType; - using Comm = typename LinearSolverTraits::Comm; - using BCRSMat = typename LinearSolverTraits::LinearOperator::matrix_type; - using DofMapper = typename LinearSolverTraits::DofMapper; - public: //! translation table for solver parameters - static std::vector > dumuxToIstlSolverParams; + static std::vector> dumuxToIstlSolverParams; /*! * \brief Construct the backend for the sequential case only @@ -77,9 +66,9 @@ public: */ IstlSolverFactoryBackend(const std::string& paramGroup = "") : paramGroup_(paramGroup) - , firstCall_(true) + , isParallel_(Dune::MPIHelper::getCollectiveCommunication().size() > 1) { - if (Dune::MPIHelper::getCollectiveCommunication().size() > 1) + if (isParallel_) DUNE_THROW(Dune::InvalidStateException, "Using sequential constructor for parallel run. Use signature with gridView and dofMapper!"); reset(); @@ -92,12 +81,12 @@ public: * \param dofMapper an index mapper for dof entities * \param paramGroup the parameter group for parameter lookup */ - IstlSolverFactoryBackend(const GridView& gridView, - const DofMapper& dofMapper, + IstlSolverFactoryBackend(const typename LinearSolverTraits::GridView& gridView, + const typename LinearSolverTraits::DofMapper& dofMapper, const std::string& paramGroup = "") : paramGroup_(paramGroup) - , parallelHelper_(std::make_unique>(gridView, dofMapper)) - , firstCall_(true) + , parallelHelper_(std::make_unique>(gridView, dofMapper)) + , isParallel_(Dune::MPIHelper::getCollectiveCommunication().size() > 1) { reset(); } @@ -109,27 +98,14 @@ public: * \param x the seeked solution vector, containing the initial solution upon entry * \param b the right hand side vector */ + template bool solve(Matrix& A, Vector& x, Vector& b) { - std::shared_ptr comm; - std::shared_ptr linearOperator; - std::shared_ptr scalarProduct; // not used. - #if HAVE_MPI - if constexpr (LinearSolverTraits::isParallel) - prepareLinearAlgebraParallel(A, b, comm, linearOperator, scalarProduct, *parallelHelper_, firstCall_); - else - prepareLinearAlgebraSequential(A, comm, linearOperator, scalarProduct); + solveSequentialOrParallel_(A, x, b); #else - prepareLinearAlgebraSequential(A, comm, linearOperator, scalarProduct); + solveSequential_(A, x, b); #endif - - // construct solver - auto solver = getSolverFromFactory_(linearOperator); - - // solve linear system - solver->apply(x, b, result_); - firstCall_ = false; return result_.converged; } @@ -137,10 +113,10 @@ public: //! reset the linear solver factory void reset() { + firstCall_ = true; resetDefaultParameters(); convertParameterTree_(paramGroup_); checkMandatoryParameters_(); - Dune::initSolverFactories(); name_ = params_.get("preconditioner.type") + "-preconditioned " + params_.get("type"); if (params_.get("verbose", 0) > 0) std::cout << "Initialized linear solver of type: " << name_ << std::endl; @@ -168,7 +144,6 @@ public: } private: - void convertParameterTree_(const std::string& paramGroup="") { auto linearSolverGroups = getParamSubGroups("LinearSolver", paramGroup); @@ -199,6 +174,79 @@ private: DUNE_THROW(Dune::InvalidStateException, "Solver factory needs \"LinearSolver.Preconditioner.Type\" parameter to select the preconditioner"); } +#if HAVE_MPI + template + void solveSequentialOrParallel_(Matrix& A, Vector& x, Vector& b) + { + if constexpr (LinearSolverTraits::canCommunicate) + { + if (isParallel_) + { + if (LinearSolverTraits::isNonOverlapping(parallelHelper_->gridView())) + { + using PTraits = typename LinearSolverTraits::template ParallelNonoverlapping; + solveParallel_(A, x, b); + } + else + { + using PTraits = typename LinearSolverTraits::template ParallelOverlapping; + solveParallel_(A, x, b); + } + } + else + solveSequential_(A, x, b); + } + else + { + solveSequential_(A, x, b); + } + } + + template + void solveParallel_(Matrix& A, Vector& x, Vector& b) + { + using Comm = typename ParallelTraits::Comm; + using LinearOperator = typename ParallelTraits::LinearOperator; + using ScalarProduct = typename ParallelTraits::ScalarProduct; + + if (firstCall_) + { + Dune::initSolverFactories(); + parallelHelper_->initGhostsAndOwners(); + } + + std::shared_ptr comm; + std::shared_ptr linearOperator; + std::shared_ptr scalarProduct; + prepareLinearAlgebraParallel(A, b, comm, linearOperator, scalarProduct, *parallelHelper_); + + // construct solver + auto solver = getSolverFromFactory_(linearOperator); + + // solve linear system + solver->apply(x, b, result_); + } +#endif // HAVE_MPI + + template + void solveSequential_(Matrix& A, Vector& x, Vector& b) + { + // construct linear operator + using Traits = typename LinearSolverTraits::template Sequential; + using LinearOperator = typename Traits::LinearOperator; + auto linearOperator = std::make_shared(A); + + if (firstCall_) + Dune::initSolverFactories(); + + // construct solver + auto solver = getSolverFromFactory_(linearOperator); + + // solve linear system + solver->apply(x, b, result_); + } + + template auto getSolverFromFactory_(std::shared_ptr& fop) { try { return Dune::getSolverFromFactory(fop, params_); } @@ -211,17 +259,19 @@ private: } const std::string paramGroup_; - std::unique_ptr> parallelHelper_; + std::unique_ptr> parallelHelper_; + bool isParallel_; bool firstCall_; + Dune::InverseOperatorResult result_; Dune::ParameterTree params_; std::string name_; }; //! translation table for solver parameters -template +template std::vector> -IstlSolverFactoryBackend::dumuxToIstlSolverParams = +IstlSolverFactoryBackend::dumuxToIstlSolverParams = { // solver params {"Verbosity", "verbose"}, diff --git a/test/freeflow/shallowwater/dambreak/main.cc b/test/freeflow/shallowwater/dambreak/main.cc index 7b3d94b4f5..18080ada72 100644 --- a/test/freeflow/shallowwater/dambreak/main.cc +++ b/test/freeflow/shallowwater/dambreak/main.cc @@ -132,9 +132,7 @@ int main(int argc, char** argv) try // the linear solver #if DUNE_VERSION_NEWER_REV(DUNE_ISTL,2,7,1) - using Matrix = GetPropType; - using Vector = Dune::BlockVector>; - using LinearSolver = IstlSolverFactoryBackend; + using LinearSolver = IstlSolverFactoryBackend>; #else using LinearSolver = AMGBiCGSTABBackend>; #endif diff --git a/test/porousmediumflow/richards/implicit/lens/main.cc b/test/porousmediumflow/richards/implicit/lens/main.cc index bb5251ec2a..40e3cbbb1d 100644 --- a/test/porousmediumflow/richards/implicit/lens/main.cc +++ b/test/porousmediumflow/richards/implicit/lens/main.cc @@ -42,6 +42,7 @@ #if DUNE_VERSION_NEWER_REV(DUNE_ISTL,2,7,1) #include +#include #else #include #endif @@ -150,9 +151,7 @@ int main(int argc, char** argv) try // the linear solver #if DUNE_VERSION_NEWER_REV(DUNE_ISTL,2,7,1) - using Matrix = GetPropType; - using Vector = Dune::BlockVector>; - using LinearSolver = IstlSolverFactoryBackend; + using LinearSolver = IstlSolverFactoryBackend>; #else using LinearSolver = AMGBiCGSTABBackend>; #endif -- GitLab From 9d849fa41a9c8de49f883e0dc7b265aa0c38e1b5 Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Thu, 27 Feb 2020 09:45:26 +0100 Subject: [PATCH 24/27] [loggingtree] Fix getSubGroups for empty key --- dumux/common/loggingparametertree.hh | 15 +++++++++------ .../parameters/test_loggingparametertree.cc | 9 ++++++++- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/dumux/common/loggingparametertree.hh b/dumux/common/loggingparametertree.hh index a1ab8c1157..3716ac7b19 100644 --- a/dumux/common/loggingparametertree.hh +++ b/dumux/common/loggingparametertree.hh @@ -128,15 +128,18 @@ public: std::string groupPrefix) const { std::vector groupNames; - auto compoundGroup = groupPrefix.empty() ? subGroupName : groupPrefix + "." + subGroupName; - for (std::string::size_type dotPos = 0; dotPos != std::string::npos; dotPos = groupPrefix.rfind(".")) + if (!groupPrefix.empty()) { - if (params_.hasSub(compoundGroup) || defaultParams_.hasSub(compoundGroup)) - groupNames.push_back(compoundGroup); + auto compoundGroup = groupPrefix + "." + subGroupName; + for (std::string::size_type dotPos = 0; dotPos != std::string::npos; dotPos = groupPrefix.rfind(".")) + { + if (params_.hasSub(compoundGroup) || defaultParams_.hasSub(compoundGroup)) + groupNames.push_back(compoundGroup); - groupPrefix = groupPrefix.substr(0, dotPos); - compoundGroup = groupPrefix + "." + subGroupName; + groupPrefix = groupPrefix.substr(0, dotPos); + compoundGroup = groupPrefix + "." + subGroupName; + } } if (params_.hasSub(subGroupName) || defaultParams_.hasSub(subGroupName)) diff --git a/test/common/parameters/test_loggingparametertree.cc b/test/common/parameters/test_loggingparametertree.cc index 1bdfce986f..65618da66a 100644 --- a/test/common/parameters/test_loggingparametertree.cc +++ b/test/common/parameters/test_loggingparametertree.cc @@ -46,13 +46,20 @@ int main (int argc, char *argv[]) try if (tEnd != 1e6) DUNE_THROW(Dune::InvalidStateException, "TEnd should be 1e6!"); auto groups = getParamSubGroups("TimeLoop", "Bulk"); - std::cout << "Found the following TimeLoop groups: "; + std::cout << "Found the following TimeLoop groups (group: Bulk): "; for (const auto& g : groups) std::cout << g << " "; std::cout << std::endl; if (groups.size() != 2) DUNE_THROW(Dune::InvalidStateException, "Wrong number of groups with ending name TimeLoop! (" << groups.size() << ", should be 2)"); if (groups[0] != "Bulk.TimeLoop") DUNE_THROW(Dune::InvalidStateException, "Wrong order or name of subgroups with ending name TimeLoop!"); if (groups[1] != "TimeLoop") DUNE_THROW(Dune::InvalidStateException, "Wrong order or name of subgroups with ending name TimeLoop!"); + groups = getParamSubGroups("TimeLoop", ""); + std::cout << "Found the following TimeLoop groups (group: empty): "; + for (const auto& g : groups) std::cout << g << " "; + std::cout << std::endl; + if (groups.size() != 1) DUNE_THROW(Dune::InvalidStateException, "Wrong number of groups with ending name TimeLoop! (" << groups.size() << ", should be 1)"); + if (groups[0] != "TimeLoop") DUNE_THROW(Dune::InvalidStateException, "Wrong order or name of subgroups with ending name TimeLoop!"); + Parameters::print(); // check the unused keys -- GitLab From 59bc45cf24db595761be08f7438d044ef96e8b21 Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Thu, 27 Feb 2020 09:49:01 +0100 Subject: [PATCH 25/27] [istlsolverbackend] set default preconditioner verbosity to 0 --- dumux/linear/istlsolverfactorybackend.hh | 1 + dumux/linear/solver.hh | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/dumux/linear/istlsolverfactorybackend.hh b/dumux/linear/istlsolverfactorybackend.hh index db03353bed..d6e7e11b89 100644 --- a/dumux/linear/istlsolverfactorybackend.hh +++ b/dumux/linear/istlsolverfactorybackend.hh @@ -131,6 +131,7 @@ public: params_["verbose"] = "0"; params_["preconditioner.iterations"] = "1"; params_["preconditioner.relaxation"] = "1.0"; + params_["preconditioner.verbosity"] = "0"; } const Dune::InverseOperatorResult& result() const diff --git a/dumux/linear/solver.hh b/dumux/linear/solver.hh index 822dee897c..93d102b495 100644 --- a/dumux/linear/solver.hh +++ b/dumux/linear/solver.hh @@ -48,6 +48,7 @@ public: * - LinearSolver.ResidualReduction the residual reduction threshold, i.e. stopping criterion * - LinearSolver.PreconditionerRelaxation precondition relaxation * - LinearSolver.PreconditionerIterations the number of preconditioner iterations + * - LinearSolver.PreconditionerVerbosity the preconditioner verbosity level */ LinearSolver(const std::string& paramGroup = "") : paramGroup_(paramGroup) @@ -57,6 +58,7 @@ public: residReduction_ = getParamFromGroup(paramGroup, "LinearSolver.ResidualReduction", 1e-13); relaxation_ = getParamFromGroup(paramGroup, "LinearSolver.PreconditionerRelaxation", 1); precondIter_ = getParamFromGroup(paramGroup, "LinearSolver.PreconditionerIterations", 1); + precondVerbosity_ = getParamFromGroup(paramGroup, "LinearSolver.PreconditionerVerbosity", 0); } /*! @@ -117,12 +119,21 @@ public: void setPrecondIter(int i) { precondIter_ = i; } + //! the preconditioner verbosity + int precondVerbosity() const + { return precondVerbosity_; } + + //! set the preconditioner verbosity + void setPrecondVerbosity(int verbosityLevel) + { precondVerbosity_ = verbosityLevel; } + private: int verbosity_; int maxIter_; double residReduction_; double relaxation_; int precondIter_; + int precondVerbosity_; const std::string paramGroup_; }; -- GitLab From 2e67dc60672eb4e05ae1104175bd6b630707518c Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Thu, 27 Feb 2020 10:16:21 +0100 Subject: [PATCH 26/27] [test] Add linear solver unit test for istlsolverfactory --- test/linear/params.input | 13 +++++-- test/linear/test_linearsolver.cc | 60 ++++++++++++++++++++++++-------- 2 files changed, 56 insertions(+), 17 deletions(-) diff --git a/test/linear/params.input b/test/linear/params.input index 2be5e3aec4..1cdde54446 100644 --- a/test/linear/params.input +++ b/test/linear/params.input @@ -1,6 +1,15 @@ -TestSolver = CG ProblemSize = 2 -[CG.LinearSolver] +[LinearSolver] +Verbosity = 1 + +[AMGCG.LinearSolver] Type = cgsolver Preconditioner.Type = amg + +[SSORCG.LinearSolver] +Type = cgsolver +Preconditioner.Type = ssor + +[AMGBiCGSTAB.LinearSolver] +Verbosity = 1 diff --git a/test/linear/test_linearsolver.cc b/test/linear/test_linearsolver.cc index d379a47e53..3bdccd032f 100644 --- a/test/linear/test_linearsolver.cc +++ b/test/linear/test_linearsolver.cc @@ -4,13 +4,8 @@ #include #include -#include -#include -#include -//#include -#include - #include +#include #include #include @@ -23,6 +18,15 @@ #include #include +#include +#include +#include + +#if DUNE_VERSION_NEWER_REV(DUNE_ISTL,2,7,1) +#include +#endif +#include + namespace Dumux::Test { struct MockGridGeometry @@ -33,6 +37,22 @@ struct MockGridGeometry static constexpr auto discMethod = DiscretizationMethod::box; }; +#if DUNE_VERSION_NEWER_REV(DUNE_ISTL,2,7,1) +template +void solveWithFactory(M& A, X& x, V& b, const std::string& paramGroup) +{ + std::cout << std::endl; + + using LinearSolver = IstlSolverFactoryBackend>; + LinearSolver solver(paramGroup); + + std::cout << "Solving Laplace problem with " << solver.name() << "\n"; + solver.solve(A, x, b); + if (!solver.result().converged) + DUNE_THROW(Dune::Exception, solver.name() << " did not converge!"); +} +#endif + } // end namespace Dumux::Test int main(int argc, char* argv[]) try @@ -53,15 +73,25 @@ int main(int argc, char* argv[]) try Vector x(A.N()); Vector b(A.M()); x = 0; b = 1; - using LinearSolverTraits = Dumux::LinearSolverTraits; - using LinearSolver = AMGBiCGSTABBackend; - - const auto testSolverName = getParam("TestSolver"); - LinearSolver solver(testSolverName); - - solver.solve(A, x, b); - if (!solver.result().converged) - DUNE_THROW(Dune::Exception, testSolverName << " did not converge!"); + // AMGBiCGSTABBackend + { + std::cout << std::endl; + + const auto testSolverName = "AMGBiCGSTAB"; + using LinearSolver = AMGBiCGSTABBackend>; + LinearSolver solver(testSolverName); + + std::cout << "Solving Laplace problem with " << solver.name() << "\n"; + solver.solve(A, x, b); + if (!solver.result().converged) + DUNE_THROW(Dune::Exception, testSolverName << " did not converge!"); + } + +#if DUNE_VERSION_NEWER_REV(DUNE_ISTL,2,7,1) + // IstlSolverFactoryBackend + Test::solveWithFactory(A, x, b, "AMGCG"); + Test::solveWithFactory(A, x, b, "SSORCG"); +#endif return 0; } -- GitLab From 71a30d10517af648971aec7d1fc8985a85e94411 Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Wed, 11 Mar 2020 17:38:32 +0100 Subject: [PATCH 27/27] [test] Run dambreak test in parallel --- .../shallowwater/dambreak/CMakeLists.txt | 26 +++++++++++++++---- .../shallowwater/dambreak/params.input | 10 +++---- .../shallowwater/roughchannel/CMakeLists.txt | 7 ++--- 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/test/freeflow/shallowwater/dambreak/CMakeLists.txt b/test/freeflow/shallowwater/dambreak/CMakeLists.txt index 88e0ced92a..ee23f9b411 100644 --- a/test/freeflow/shallowwater/dambreak/CMakeLists.txt +++ b/test/freeflow/shallowwater/dambreak/CMakeLists.txt @@ -1,12 +1,28 @@ dune_symlink_to_source_files(FILES "params.input") -dumux_add_test(NAME test_shallowwater_dambreak - SOURCES main.cc - TIMEOUT 1500 - COMMAND ${CMAKE_SOURCE_DIR}/bin/testing/runtest.py - CMD_ARGS --script fuzzy +add_executable(test_shallowwater_dambreak EXCLUDE_FROM_ALL main.cc) + +dumux_add_test(NAME test_shallowwater_dambreak_sequential + TARGET test_shallowwater_dambreak + LABELS shallowwater + TIMEOUT 1500 + COMMAND ${CMAKE_SOURCE_DIR}/bin/testing/runtest.py + CMD_ARGS --script fuzzy --files ${CMAKE_SOURCE_DIR}/test/references/test_ff_shallowwater_dambreak-reference.vtu ${CMAKE_CURRENT_BINARY_DIR}/dambreak-00001.vtu --zeroThreshold {"velocityY":1e-14} --command "${CMAKE_CURRENT_BINARY_DIR}/test_shallowwater_dambreak params.input -Problem.Name dambreak") + +dumux_add_test(NAME test_shallowwater_dambreak_parallel + TARGET test_shallowwater_dambreak + LABELS shallowwater parallel + TIMEOUT 1500 + CMAKE_GUARD MPI_FOUND + COMMAND ${CMAKE_SOURCE_DIR}/bin/testing/runtest.py + CMD_ARGS --script fuzzy + --files ${CMAKE_SOURCE_DIR}/test/references/test_ff_shallowwater_dambreak-reference.vtu + ${CMAKE_CURRENT_BINARY_DIR}/s0002-dambreak_parallel-00001.pvtu + --zeroThreshold {"velocityY":1e-14,"process rank":100} + --command "${MPIEXEC} -np 2 ${CMAKE_CURRENT_BINARY_DIR}/test_shallowwater_dambreak params.input + -Problem.Name dambreak_parallel") diff --git a/test/freeflow/shallowwater/dambreak/params.input b/test/freeflow/shallowwater/dambreak/params.input index 03b5a00414..7254db45d5 100644 --- a/test/freeflow/shallowwater/dambreak/params.input +++ b/test/freeflow/shallowwater/dambreak/params.input @@ -17,13 +17,11 @@ EnablePartialReassembly = true EnableDynamicOutput = false [LinearSolver] -Type = cgsolver +Type = bicgstabsolver MaxIterations = 80 [LinearSolver.Preconditioner] -Type = amg +Type = ilu Verbosity = 0 -AmgMaxLevel = 2 -AmgPreSmoothingSteps = 1 -AmgPostSmoothingSteps = 1 -AmgCriterionSymmetric = true +ILUOrder = 0 +ILUResort = true diff --git a/test/freeflow/shallowwater/roughchannel/CMakeLists.txt b/test/freeflow/shallowwater/roughchannel/CMakeLists.txt index 3ae5d9a161..b6d509befe 100644 --- a/test/freeflow/shallowwater/roughchannel/CMakeLists.txt +++ b/test/freeflow/shallowwater/roughchannel/CMakeLists.txt @@ -1,9 +1,10 @@ dune_symlink_to_source_files(FILES "params.input") dumux_add_test(NAME test_shallowwater_roughchannel - SOURCES main.cc - COMMAND ${CMAKE_SOURCE_DIR}/bin/testing/runtest.py - CMD_ARGS --script fuzzy + SOURCES main.cc + LABELS shallowwater + COMMAND ${CMAKE_SOURCE_DIR}/bin/testing/runtest.py + CMD_ARGS --script fuzzy --files ${CMAKE_SOURCE_DIR}/test/references/test_ff_shallowwater_roughchannel-reference.vtu ${CMAKE_CURRENT_BINARY_DIR}/roughchannel-00001.vtu --zeroThreshold {"velocityY":1e-14} -- GitLab