diff --git a/src/amdis/BiLinearForm.hpp b/src/amdis/BiLinearForm.hpp index f7d3b8e2a99d13432d8d331d153cf1a9e1fec0f4..8971f493b4c3fe4dde3d215be3e4dbfae0c58541 100644 --- a/src/amdis/BiLinearForm.hpp +++ b/src/amdis/BiLinearForm.hpp @@ -43,20 +43,41 @@ namespace AMDiS using ElementMatrix = FlatMatrix<CoefficientType>; public: - /// Constructor. Wraps the reference into a non-destroying shared_ptr or moves the basis into - /// a new shared_ptr. + /// Constructor. Stores the row and column basis in a local `shared_ptr` to const BiLinearForm(std::shared_ptr<RB> const& rowBasis, std::shared_ptr<CB> const& colBasis) : Super(*rowBasis, *colBasis) , rowBasis_(rowBasis) , colBasis_(colBasis) { - operators_.init(*rowBasis, *colBasis); + operators_.init(*rowBasis_, *colBasis_); - auto const rowSize = rowBasis->localView().maxSize(); - auto const colSize = colBasis->localView().maxSize(); + auto const rowSize = rowBasis_->localView().maxSize(); + auto const colSize = colBasis_->localView().maxSize(); elementMatrix_.resize(rowSize, colSize); } + /// Wraps the passed global bases into (non-destroying) shared_ptr + template <class RB_, class CB_, + REQUIRES(Concepts::Similar<RB_,RB>), + REQUIRES(Concepts::Similar<CB_,CB>)> + BiLinearForm(RB_&& rowBasis, CB_&& colBasis) + : BiLinearForm(Dune::wrap_or_move(FWD(rowBasis)), Dune::wrap_or_move(FWD(colBasis))) + {} + + /// Constructor for rowBasis == colBasis + template <class RB_ = RB, class CB_ = CB, + REQUIRES(std::is_same<RB_,CB_>::value)> + explicit BiLinearForm(std::shared_ptr<RB> const& rowBasis) + : BiLinearForm(rowBasis, rowBasis) + {} + + /// Wraps the passed row-basis into a (non-destroying) shared_ptr + template <class RB_, + REQUIRES(Concepts::Similar<RB_,RB>)> + explicit BiLinearForm(RB_&& rowBasis) + : BiLinearForm(Dune::wrap_or_move(FWD(rowBasis))) + {} + std::shared_ptr<RowBasis const> const& rowBasis() const { return rowBasis_; } std::shared_ptr<ColBasis const> const& colBasis() const { return colBasis_; } @@ -108,7 +129,6 @@ namespace AMDiS void assemble(SymmetryStructure symmetry = SymmetryStructure::unknown); protected: - /// Dense matrix to store coefficients during \ref assemble() ElementMatrix elementMatrix_; @@ -124,15 +144,26 @@ namespace AMDiS template <class RB, class CB> BiLinearForm(RB&&, CB&&) -> BiLinearForm<Underlying_t<RB>, Underlying_t<CB>>; + + template <class RB> + BiLinearForm(RB&&) + -> BiLinearForm<Underlying_t<RB>, Underlying_t<RB>>; #endif - template <class RB, class CB, class... Args> + template <class T = double, class RB, class CB> auto makeBiLinearForm(RB&& rowBasis, CB&& colBasis) { - using BLF = BiLinearForm<Underlying_t<RB>, Underlying_t<CB>>; + using BLF = BiLinearForm<Underlying_t<RB>, Underlying_t<CB>, T>; return BLF{FWD(rowBasis), FWD(colBasis)}; } + template <class T = double, class RB> + auto makeBiLinearForm(RB&& rowBasis) + { + using BLF = BiLinearForm<Underlying_t<RB>, Underlying_t<RB>, T>; + return BLF{FWD(rowBasis)}; + } + } // end namespace AMDiS #include <amdis/BiLinearForm.inc.hpp> diff --git a/src/amdis/LinearForm.hpp b/src/amdis/LinearForm.hpp index 78d047184bd40a4d19915b11b441cf5c4db578ae..430c50152ee73c4fcdbd5f69b8f145746bdb65a9 100644 --- a/src/amdis/LinearForm.hpp +++ b/src/amdis/LinearForm.hpp @@ -49,6 +49,13 @@ namespace AMDiS elementVector_.resize(localSize); } + /// Wraps the passed global basis into a (non-destroying) shared_ptr + template <class GB_, + REQUIRES(Concepts::Similar<GB_,GB>)> + explicit LinearForm(GB_&& basis) + : LinearForm(Dune::wrap_or_move(FWD(basis))) + {} + std::shared_ptr<GlobalBasis const> const& basis() const { return basis_; } /// \brief Associate a local operator with this LinearForm diff --git a/src/amdis/ProblemStatTraits.hpp b/src/amdis/ProblemStatTraits.hpp index b5a297f9d3741f10a7b1fad091bfe21edad9e911..2094d18c18010f51b7c0678e45c9bda20bd49401 100644 --- a/src/amdis/ProblemStatTraits.hpp +++ b/src/amdis/ProblemStatTraits.hpp @@ -6,6 +6,7 @@ #include <dune/functions/functionspacebases/powerbasis.hh> #include <dune/grid/yaspgrid.hh> +#include <amdis/AdaptiveGrid.hpp> #include <amdis/common/Logical.hpp> #include <amdis/common/TypeTraits.hpp> #include <amdis/functions/ParallelGlobalBasis.hpp> @@ -70,7 +71,7 @@ namespace AMDiS template <class HostGrid, class PreBasisCreator, class T = double> struct DefaultBasisCreator { - using Grid = AdaptiveGrid<HostGrid>; + using Grid = AdaptiveGrid_t<HostGrid>; using GridView = typename Grid::LeafGridView; static auto create(std::string const& name, GridView const& gridView) diff --git a/src/amdis/common/Algorithm.hpp b/src/amdis/common/Algorithm.hpp index dabbe0331cc384a9584e1e306d06faae8147871b..7805a66f42f5ba1c8b02c11566069496e59f46d2 100644 --- a/src/amdis/common/Algorithm.hpp +++ b/src/amdis/common/Algorithm.hpp @@ -1,36 +1,67 @@ #pragma once #include <algorithm> +#include <functional> +#include <utility> namespace AMDiS { - template <class InputIter, class T, class Func> - void split(InputIter first, InputIter end, T const& t, Func f) + /// \brief Split a sequence `[first,last)` by the separators `sep` and pass the tokens as + /// begin-end iterator pair to the provided functor `f = void(InputIterator, InputIterator)` + template <class InputIter, class Tp, class BinaryFunc> + void split(InputIter first, InputIter last, Tp sep, BinaryFunc f) { - if (first == end) + if (first == last) return; while (true) { - InputIter found = std::find(first, end, t); + InputIter found = std::find(first, last, sep); f(first, found); - if (found == end) + if (found == last) break; first = ++found; } } - template <class InputIter, class SeparaterIter, class Func> - void split(InputIter first, InputIter end, SeparaterIter s_first, SeparaterIter s_end, Func f) + /// \brief Split a sequence `[first,last)` by any of the separators `[s_first, s_last)` and pass the tokens as + /// begin-end iterator pair to the provided functor `f = void(InputIterator, InputIterator)` + template <class InputIter, class SeparaterIter, class BinaryFunc> + void split(InputIter first, InputIter last, SeparaterIter s_first, SeparaterIter s_last, BinaryFunc f) { - if (first == end) + if (first == last) return; while (true) { - InputIter found = std::find_first_of(first, end, s_first, s_end); + InputIter found = std::find_first_of(first, last, s_first, s_last); f(first, found); - if (found == end) + if (found == last) break; first = ++found; } } + + /// \brief Output the cumulative sum of one range to a second range + // NOTE: backport of std::exclusive_scan from c++17 + template <class InputIter, class OutputIter, class Tp, class BinaryOperation> + OutputIter exclusive_scan(InputIter first, InputIter last, + OutputIter result, Tp init, BinaryOperation binary_op) + { + while (first != last) { + auto v = init; + init = binary_op(init, *first); + ++first; + *result++ = std::move(v); + } + return result; + } + + /// \brief Output the cumulative sum of one range to a second range + // NOTE: backport of std::exclusive_scan from c++17 + template <class InputIter, class OutputIter, class Tp> + inline OutputIter exclusive_scan(InputIter first, InputIter last, + OutputIter result, Tp init) + { + return AMDiS::exclusive_scan(first, last, result, std::move(init), std::plus<>()); + } + } \ No newline at end of file diff --git a/src/amdis/linearalgebra/LinearSolver.hpp b/src/amdis/linearalgebra/LinearSolver.hpp index 3facaa4a2fa6220fbed0c886c4dc14ea213b33e1..1eb051b8b5dee1e65e42dfa775bb73cfbbe60acb 100644 --- a/src/amdis/linearalgebra/LinearSolver.hpp +++ b/src/amdis/linearalgebra/LinearSolver.hpp @@ -44,13 +44,17 @@ namespace AMDiS public: /// Constructor - explicit LinearSolver(std::string prefix) - : runner_(prefix) + template <class... Args> + explicit LinearSolver(std::string prefix, Args&&... args) + : runner_(prefix, FWD(args)...) {} + Runner& runner() { return runner_; } + Runner const& runner() const { return runner_; } + private: /// Implements \ref LinearSolverInterface::solveSystemImpl() - void solveImpl(Mat const& A, Vec& x, Vec const& b, Comm& comm, SolverInfo& solverInfo) override + void solveImpl(Mat const& A, Vec& x, Vec const& b, Comm const& comm, SolverInfo& solverInfo) override { Dune::Timer t; if (solverInfo.doCreateMatrixData()) { diff --git a/src/amdis/linearalgebra/LinearSolverInterface.hpp b/src/amdis/linearalgebra/LinearSolverInterface.hpp index bbaee462ae6ecfefc0f8772c69d6f2bfafda56b6..14e255206beea3ec20b9852909ac5222eb8a1e59 100644 --- a/src/amdis/linearalgebra/LinearSolverInterface.hpp +++ b/src/amdis/linearalgebra/LinearSolverInterface.hpp @@ -38,14 +38,14 @@ namespace AMDiS * \p x A [block-]vector for the unknown components. * \p b A [block-]vector for the right-hand side of the linear system. **/ - void solve(Mat const& A, Vec& x, Vec const& b, Comm& comm, SolverInfo& solverInfo) + void solve(Mat const& A, Vec& x, Vec const& b, Comm const& comm, SolverInfo& solverInfo) { solveImpl(A, x, b, comm, solverInfo); } private: /// main methods that all solvers must implement - virtual void solveImpl(Mat const& A, Vec& x, Vec const& b, Comm& comm, SolverInfo& solverInfo) = 0; + virtual void solveImpl(Mat const& A, Vec& x, Vec const& b, Comm const& comm, SolverInfo& solverInfo) = 0; }; } // end namespace AMDiS diff --git a/src/amdis/linearalgebra/RunnerInterface.hpp b/src/amdis/linearalgebra/RunnerInterface.hpp index 4f46d3e456c0d23b32b4dc451ba72cca81b7e5a9..7fcf48d7dea87f105edb018006ea0d31af880201 100644 --- a/src/amdis/linearalgebra/RunnerInterface.hpp +++ b/src/amdis/linearalgebra/RunnerInterface.hpp @@ -20,7 +20,7 @@ namespace AMDiS virtual ~RunnerInterface() = default; /// Is called at the beginning of a solution procedure - virtual void init(Mat const& A, Comm& comm) = 0; + virtual void init(Mat const& A, Comm const& comm) = 0; /// Is called at the end of a solution procedure virtual void exit() = 0; diff --git a/src/amdis/linearalgebra/eigen/DirectRunner.hpp b/src/amdis/linearalgebra/eigen/DirectRunner.hpp index 61f74dade1152b2389677f15ab38146b208771f7..47649fc6c2faad44b9207d44cf35fbccc1042de3 100644 --- a/src/amdis/linearalgebra/eigen/DirectRunner.hpp +++ b/src/amdis/linearalgebra/eigen/DirectRunner.hpp @@ -35,7 +35,7 @@ namespace AMDiS } /// Implements \ref RunnerInterface::init() - void init(Mat const& A, Comm& comm) override + void init(Mat const& A, Comm const& comm) override { DUNE_UNUSED_PARAMETER(comm); @@ -49,9 +49,11 @@ namespace AMDiS "Error in solver.compute(matrix)"); } - /// Implements \ref RunnerInterface::exit() - void exit() override {} + void exit() override + { + initialized_ = false; + } /// Implements \ref RunnerInterface::solve() int solve(Mat const& A, Vec& x, Vec const& b, SolverInfo& solverInfo) override diff --git a/src/amdis/linearalgebra/eigen/IterativeRunner.hpp b/src/amdis/linearalgebra/eigen/IterativeRunner.hpp index 45541907b9d7a8a89d0ac13c0ce0b0e6075c5ae6..ad66327324adca85af122dd5360cd533fb68c7a8 100644 --- a/src/amdis/linearalgebra/eigen/IterativeRunner.hpp +++ b/src/amdis/linearalgebra/eigen/IterativeRunner.hpp @@ -30,7 +30,7 @@ namespace AMDiS /// Implements \ref RunnerInterface::init() - void init(Mat const& A, Comm& comm) override + void init(Mat const& A, Comm const& comm) override { DUNE_UNUSED_PARAMETER(comm); @@ -45,7 +45,10 @@ namespace AMDiS } /// Implements \ref RunnerInterface::exit() - void exit() override {} + void exit() override + { + initialized_ = false; + } /// Implements \ref RunnerInterface::solve() int solve(Mat const& A, Vec& x, Vec const& b, SolverInfo& solverInfo) override diff --git a/src/amdis/linearalgebra/istl/ISTLRunner.hpp b/src/amdis/linearalgebra/istl/ISTLRunner.hpp index 7eaf846a41f4feba63bedf24548ad6e2e37975b5..5c688535a5c43de46ef901272407d99a5da23dcb 100644 --- a/src/amdis/linearalgebra/istl/ISTLRunner.hpp +++ b/src/amdis/linearalgebra/istl/ISTLRunner.hpp @@ -32,7 +32,7 @@ namespace AMDiS } /// Implements \ref RunnerInterface::init() - void init(Mat const& mat, typename Traits::Comm& comm) override + void init(Mat const& mat, typename Traits::Comm const& comm) override { solver_ = solverCreator_->create(mat, comm); } diff --git a/src/amdis/linearalgebra/mtl/KrylovRunner.hpp b/src/amdis/linearalgebra/mtl/KrylovRunner.hpp index 3087971bc11c93c533a3999d3ede8554a624424d..3ec3ee6aae7572ca4336c2351a9e7e5d185d8aa3 100644 --- a/src/amdis/linearalgebra/mtl/KrylovRunner.hpp +++ b/src/amdis/linearalgebra/mtl/KrylovRunner.hpp @@ -41,13 +41,14 @@ namespace AMDiS Parameters::get(prefix_ + "->relative tolerance", rTol_); Parameters::get(prefix_ + "->max iteration", maxIter_); Parameters::get(prefix_ + "->print cycle", printCycle_); + + initPrecon(prefix_); } /// Implementation of \ref RunnerInterface::init() - void init(Matrix const& A, Comm& comm) override + void init(Matrix const& A, Comm const& comm) override { DUNE_UNUSED_PARAMETER(comm); - initPrecon(prefix_); P_->init(A); } diff --git a/src/amdis/linearalgebra/mtl/UmfpackRunner.hpp b/src/amdis/linearalgebra/mtl/UmfpackRunner.hpp index 4703b6ca4670888e87d5998c1705635657955d20..4c9065f34df1191ce98fa78c694b4226a7b4fa95 100644 --- a/src/amdis/linearalgebra/mtl/UmfpackRunner.hpp +++ b/src/amdis/linearalgebra/mtl/UmfpackRunner.hpp @@ -45,7 +45,7 @@ namespace AMDiS } /// Implementation of \ref RunnerInterface::init() - void init(Matrix const& matrix, Comm&) override + void init(Matrix const& matrix, Comm const&) override { try { if (bool(solver_) && storeSymbolic_) diff --git a/src/amdis/linearalgebra/petsc/MatrixBackend.hpp b/src/amdis/linearalgebra/petsc/MatrixBackend.hpp index e72a33fbe9b5d0927cd76bc56f4e58e49fd748eb..e00b5874ee5f98bef06baff5995503b3de9a3f8b 100644 --- a/src/amdis/linearalgebra/petsc/MatrixBackend.hpp +++ b/src/amdis/linearalgebra/petsc/MatrixBackend.hpp @@ -13,11 +13,13 @@ namespace AMDiS { + template <class> class Constraints; + /// \brief The basic container that stores a base matrix template <class DofMap> class PetscMatrix { - friend struct Constraints<PetscMatrix<DofMap>>; + template <class> friend class Constraints; public: /// The matrix type of the underlying base matrix diff --git a/src/amdis/linearalgebra/petsc/PetscRunner.hpp b/src/amdis/linearalgebra/petsc/PetscRunner.hpp index 55f6ea893a92810f501bd26409b47dc2139733ce..7a233c5cd698365b9aa9d6a291f25299d6e5c1ad 100644 --- a/src/amdis/linearalgebra/petsc/PetscRunner.hpp +++ b/src/amdis/linearalgebra/petsc/PetscRunner.hpp @@ -68,7 +68,7 @@ namespace AMDiS } /// Implements \ref RunnerInterface::init() - void init(typename Traits::Mat const& mat, typename Traits::Comm& comm) override + void init(typename Traits::Mat const& mat, typename Traits::Comm const& comm) override { exit(); #if HAVE_MPI @@ -110,23 +110,26 @@ namespace AMDiS protected: // initialize the KSP solver from the initfile - void initKSP(KSP ksp, std::string prefix) const + virtual void initKSP(KSP ksp, std::string prefix) const { // see https://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/KSP/KSPType.html - auto kspTypeStr = Parameters::get<std::string>(prefix); - if (kspTypeStr) { - if (kspTypeStr.value() == "direct") - initDirectSolver(ksp, prefix); - else if (kspTypeStr.value() != "default") { - KSPSetType(ksp, kspTypeStr.value().c_str()); - - // initialize some KSP specific parameters - initKSPParameters(ksp, kspTypeStr.value().c_str(), prefix); - - // set initial guess to nonzero only for non-preonly ksp type - if (kspTypeStr.value() != "preonly") - KSPSetInitialGuessNonzero(ksp, PETSC_TRUE); - } + auto kspType = Parameters::get<std::string>(prefix + "->ksp"); + std::string kspTypeStr = kspType.value_or("default"); + + if (!kspType) + Parameters::get(prefix, kspTypeStr); + + if (kspTypeStr == "direct") + initDirectSolver(ksp, prefix); + else if (kspTypeStr != "default") { + KSPSetType(ksp, kspTypeStr.c_str()); + + // initialize some KSP specific parameters + initKSPParameters(ksp, kspTypeStr.c_str(), prefix); + + // set initial guess to nonzero only for non-preonly ksp type + if (kspTypeStr != "preonly") + KSPSetInitialGuessNonzero(ksp, PETSC_TRUE); } // set a KSPMonitor if info > 0 @@ -167,7 +170,7 @@ namespace AMDiS // initialize a direct solver from the initfile - void initDirectSolver(KSP ksp, std::string prefix) const + virtual void initDirectSolver(KSP ksp, std::string prefix) const { KSPSetInitialGuessNonzero(ksp, PETSC_TRUE); KSPSetType(ksp, KSPRICHARDSON); @@ -192,7 +195,7 @@ namespace AMDiS // initialize the preconditioner pc from the initfile - void initPC(PC pc, std::string prefix) const + virtual void initPC(PC pc, std::string prefix) const { // see https://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/PC/PCType.html auto pcType = Parameters::get<std::string>(prefix); @@ -234,7 +237,7 @@ namespace AMDiS // provide initfile parameters for some PETSc KSP parameters - void initKSPParameters(KSP ksp, char const* ksptype, std::string prefix) const + virtual void initKSPParameters(KSP ksp, char const* ksptype, std::string prefix) const { // parameters for the Richardson solver if (std::strcmp(ksptype, KSPRICHARDSON) == 0) @@ -288,7 +291,7 @@ namespace AMDiS } } - private: + protected: std::string prefix_; int info_ = 0;