diff --git a/src/amdis/BiLinearForm.hpp b/src/amdis/BiLinearForm.hpp index af41ef1e41741ac2d4ab52f224e636cb0269661a..ff1fda26299f625bd62f962bc52c530a2b0058ce 100644 --- a/src/amdis/BiLinearForm.hpp +++ b/src/amdis/BiLinearForm.hpp @@ -45,10 +45,12 @@ 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. - template <class RB_, class CB_, class Comm_> - BiLinearForm(RB_&& rowBasis, CB_&& colBasis, Comm_&& comm) - : Super(FWD(rowBasis), FWD(colBasis), FWD(comm)) + /// Constructor. Wraps the reference into a non-destroying shared_ptr or moves + /// the basis into a new shared_ptr. The additional arguments can be the communication + /// object. If not provided, a new communication is created. + template <class RB_, class CB_, class... Args> + BiLinearForm(RB_&& rowBasis, CB_&& colBasis, Args&&... args) + : Super(FWD(rowBasis), FWD(colBasis), FWD(args)...) { operators_.init(*Super::rowBasis(), *Super::colBasis()); } @@ -63,7 +65,7 @@ namespace AMDiS elementMatrix_.resize(rowSize, colSize); } - /// \brief Associate a local operator with this DOFMatrix + /// \brief Associate a local operator with this BiLinearForm /** * Stores an operator in a list that gets assembled during a call to \ref assemble(). * The operator may be assigned to a specific context, i.e. either an element @@ -72,20 +74,36 @@ namespace AMDiS * functions the operator is applied to. * * \tparam ContextTag One of \ref tag::element_operator, \ref tag::intersection_operator - * or \ref tag::boundary_operator indicating where to assemble this operator. + * or \ref tag::boundary_operator indicating where to assemble + * this operator. * \tparam Expr An pre-operator that can be bound to a gridView, or a valid - * GridOperator. - * \tparam row A tree-path for the RowBasis - * \tparam col A tree-path for the ColBasis + * GridOperator. + * \tparam row A tree-path for the RowBasis + * \tparam col A tree-path for the ColBasis * * [[expects: row is valid tree-path in RowBasis]] * [[expects: col is valid tree-path in ColBasis]] + * @{ **/ - // TODO: add method without contextTag. - template <class ContextTag, class Expr, - class RowTreePath = RootTreePath, class ColTreePath = RootTreePath> - void addOperator(ContextTag contextTag, Expr const& expr, - RowTreePath row = {}, ColTreePath col = {}); + template <class ContextTag, class Expr, class Row, class Col> + void addOperator(ContextTag contextTag, Expr const& expr, Row row, Col col); + + // Add an operator to be assembled on the elements of the grid + template <class Expr, class Row = RootTreePath, class Col = RootTreePath> + void addOperator(Expr const& expr, Row row = {}, Col col = {}) + { + using E = typename RowLocalView::Element; + addOperator(tag::element_operator<E>{}, expr, row, col); + } + + // Add an operator to be assembled on the intersections of the grid + template <class Expr, class Row = RootTreePath, class Col = RootTreePath> + void addIntersectionOperator(Expr const& expr, Row row = {}, Col col = {}) + { + using I = typename RowLocalView::GridView::Intersection; + addOperator(tag::intersection_operator<I>{}, expr, row, col); + } + /// @} /// Assemble the matrix operators on the bound element. void assemble(RowLocalView const& rowLocalView, @@ -103,6 +121,20 @@ namespace AMDiS MatrixOperators<RowBasis,ColBasis,ElementMatrix> operators_; }; + +#if DUNE_HAVE_CXX_CLASS_TEMPLATE_ARGUMENT_DEDUCTION + template <class RB, class CB, class... Args> + BiLinearForm(RB&&, CB&&, Args&&...) + -> BiLinearForm<Underlying_t<RB>, Underlying_t<CB>>; +#endif + + template <class RB, class CB, class... Args> + auto makeBiLinearForm(RB&& rowBasis, CB&& colBasis, Args&&... args) + { + using BLF = BiLinearForm<Underlying_t<RB>, Underlying_t<CB>>; + return BLF{FWD(rowBasis), FWD(colBasis), FWD(args)...}; + } + } // end namespace AMDiS #include <amdis/BiLinearForm.inc.hpp> diff --git a/src/amdis/BiLinearForm.inc.hpp b/src/amdis/BiLinearForm.inc.hpp index 940297e68d64aaaab1fd1c3894de778e62cde771..3e66984c131e9f50243c583a44a1c1165a09107d 100644 --- a/src/amdis/BiLinearForm.inc.hpp +++ b/src/amdis/BiLinearForm.inc.hpp @@ -75,7 +75,7 @@ assemble(SymmetryStructure symmetry) this->assemble(rowLocalView, colLocalView); colLocalView.unbind(); } - rowLocalView.unbind(element); + rowLocalView.unbind(); } this->finish(); } diff --git a/src/amdis/LinearForm.hpp b/src/amdis/LinearForm.hpp index 2ecfb4c3817dd20959699c3cd0b3cf56f68fa638..a57ec0f1b0790cbee3bbd57f2382b80dea20bbbe 100644 --- a/src/amdis/LinearForm.hpp +++ b/src/amdis/LinearForm.hpp @@ -21,6 +21,7 @@ namespace AMDiS : public VectorBase<GB, VectorBackend<BackendTraits<GB,T>>> { using Super = VectorBase<GB, VectorBackend<BackendTraits<GB,T>>>; + using Self = LinearForm; public: using Backend = VectorBackend<BackendTraits<GB,T>>; @@ -28,6 +29,7 @@ namespace AMDiS /// The type of the functionspace basis associated to this linearform using GlobalBasis = GB; + using LocalView = typename GlobalBasis::LocalView; /// A traits class collecting several parameters of the linear algebra backend using Traits = typename Backend::Traits; @@ -40,9 +42,12 @@ namespace AMDiS public: /// Constructor. Stores the shared_ptr of the basis and creates a new DataTransfer. - template <class GB_, class Comm_> - LinearForm(GB_&& basis, Comm_&& comm) - : Super(FWD(basis), FWD(comm)) + /// The additional arguments can be the communication object. If not provided, + /// a new communication is created. + template <class GB_, class... Args, + Dune::disableCopyMove<Self, GB_, Args...> = 0> + explicit LinearForm(GB_&& basis, Args&&... args) + : Super(FWD(basis), FWD(args)...) { operators_.init(*Super::basis()); } @@ -57,12 +62,47 @@ namespace AMDiS elementVector_.resize(localSize); } - /// Associate a local operator with this LinearForm - template <class ContextTag, class Expr, class TreePath = RootTreePath> - void addOperator(ContextTag contextTag, Expr const& expr, TreePath path = {}); + /// \brief Associate a local operator with this LinearForm + /** + * Stores an operator in a list that gets assembled during a call to \ref assemble(). + * The operator may be assigned to a specific context, i.e. either an element + * operator, an intersection operator, or a boundary operator. + * The \p path tree paths specify the sub-basis for test functions the operator + * is applied to. + * + * \tparam ContextTag One of \ref tag::element_operator, \ref tag::intersection_operator + * or \ref tag::boundary_operator indicating where to assemble + * this operator. + * \tparam Expr An pre-operator that can be bound to a gridView, or a valid + * GridOperator. + * \tparam path A tree-path for the Basis + * + * [[expects: path is valid tree-path in Basis]] + * @{ + **/ + template <class ContextTag, class Expr, class TreePath> + void addOperator(ContextTag contextTag, Expr const& expr, TreePath path); + + // Add an operator to be assembled on the elements of the grid + template <class Expr, class TreePath = RootTreePath> + void addOperator(Expr const& expr, TreePath path = {}) + { + using E = typename LocalView::Element; + addOperator(tag::element_operator<E>{}, expr, path); + } + + // Add an operator to be assembled on the intersections of the grid + template <class Expr, class TreePath = RootTreePath> + void addIntersectionOperator(Expr const& expr, TreePath path = {}) + { + using I = typename LocalView::GridView::Intersection; + addOperator(tag::intersection_operator<I>{}, expr, path); + } + /// @} + /// Assemble the vector operators on the bound element. - void assemble(typename GB::LocalView const& localView); + void assemble(LocalView const& localView); /// Assemble all vector operators added by \ref addOperator(). void assemble(); @@ -75,12 +115,20 @@ namespace AMDiS VectorOperators<GlobalBasis,ElementVector> operators_; }; + #if DUNE_HAVE_CXX_CLASS_TEMPLATE_ARGUMENT_DEDUCTION - template <class GB, class C> - LinearForm(GB&& basis, C const& comm) - -> LinearForm<Underlying_t<GB>, VectorBackend<BackendTraits<Underlying_t<GB>>> >; + template <class GB, class... Args> + LinearForm(GB&& basis, Args&&... args) + -> LinearForm<Underlying_t<GB>, double>; #endif + template <class T = double, class GB, class... Args> + auto makeLinearForm(GB&& basis, Args&&... args) + { + using LF = LinearForm<Underlying_t<GB>, T>; + return LF{FWD(basis), FWD(args)...}; + } + } // end namespace AMDiS #include <amdis/LinearForm.inc.hpp> diff --git a/src/amdis/linearalgebra/MatrixBase.hpp b/src/amdis/linearalgebra/MatrixBase.hpp index 9348984b6862b6799a8dc9ea5beb9fcafdcc3ce6..601330327a3f88fd5b8854ad1013bbbcb7308999 100644 --- a/src/amdis/linearalgebra/MatrixBase.hpp +++ b/src/amdis/linearalgebra/MatrixBase.hpp @@ -36,25 +36,41 @@ namespace AMDiS using ColBasis = CB; using ColLocalView = typename ColBasis::LocalView; - /// The Linear-Aglebra backend used to store the assembled coefficients + /// The Linear-Algebra backend used to store the assembled coefficients using Backend = B; - - private: using Comm = typename B::Traits::Comm; public: - /// Constructor. Stores the shared_ptr to the bases. - MatrixBase(std::shared_ptr<RowBasis> rowBasis, std::shared_ptr<ColBasis> colBasis, std::shared_ptr<Comm> comm) + /// (1) Constructor. Stores the shared_ptr to the bases and the communication object. + MatrixBase(std::shared_ptr<RB> rowBasis, std::shared_ptr<CB> colBasis, + std::shared_ptr<Comm> comm) : rowBasis_(std::move(rowBasis)) , colBasis_(std::move(colBasis)) , backend_(std::move(comm)) {} - /// Constructor. Wraps the reference into a non-destroying shared_ptr or moves the basis into a new shared_ptr. + /// (2) Constructor. Forwards to (1) by wraping reference into non-destroying + /// shared_ptr, see \ref Dune::wrap_or_move. template <class RB_, class CB_, class Comm_, - REQUIRES(Concepts::Similar<RB_,RB> && Concepts::Similar<CB_,CB> && Concepts::Similar<Comm_,Comm>)> + REQUIRES(Concepts::Similar<Types<RB_,CB_,Comm_>, Types<RB,CB,Comm>>)> MatrixBase(RB_&& rowBasis, CB_&& colBasis, Comm_&& comm) - : MatrixBase(Dune::wrap_or_move(FWD(rowBasis)), Dune::wrap_or_move(FWD(colBasis)), Dune::wrap_or_move(FWD(comm))) + : MatrixBase(Dune::wrap_or_move(FWD(rowBasis)), + Dune::wrap_or_move(FWD(colBasis)), + Dune::wrap_or_move(FWD(comm))) + {} + + /// (3) Constructor. Forwards to (1) by creating a new communicator + MatrixBase(std::shared_ptr<RB> const& rowBasis, std::shared_ptr<CB> const& colBasis) + : MatrixBase(rowBasis, colBasis, + std::shared_ptr<Comm>(CommunicationCreator<Comm>::create(*rowBasis))) + {} + + /// (4) Constructor. Forwards to (3) by wrapping references into non-destroying + /// shared_ptr, see \ref Dune::wrap_or_move. + template <class RB_, class CB_, + REQUIRES(Concepts::Similar<Types<RB_,CB_>, Types<RB,CB>>)> + MatrixBase(RB_&& rowBasis, CB_&& colBasis) + : MatrixBase(Dune::wrap_or_move(FWD(rowBasis)), Dune::wrap_or_move(FWD(colBasis))) {} /// Return the row-basis \ref rowBasis of the matrix @@ -69,20 +85,15 @@ namespace AMDiS return colBasis_; } - Backend& backend() - { - return backend_; - } - - Backend const& backend() const - { - return backend_; - } + /// Return the underlying linear algebra backend + Backend const& backend() const { return backend_; } + Backend& backend() { return backend_; } /// \brief Initialize the matrix for insertion, i.e. allocate the non-zero pattern /** * With the optional parameter \p symmetry some additional information about the - * structure of the values or the sparsity pattern can be provided. See \ref SymmetryStructure. + * structure of the values or the sparsity pattern can be provided. + * See \ref SymmetryStructure. **/ void init(SymmetryStructure symmetry = SymmetryStructure::unknown) { @@ -111,7 +122,9 @@ namespace AMDiS assert(r.size() == localMatrix.rows()); assert(c.size() == localMatrix.cols()); - const bool optimized = std::is_same<RowLocalView,ColLocalView>::value && r.tree().treeIndex() == c.tree().treeIndex(); + const bool optimized = std::is_same<RowLocalView,ColLocalView>::value + && r.tree().treeIndex() == c.tree().treeIndex(); + if (optimized) backend_.scatter(nodeIndices(r), localMatrix); else diff --git a/src/amdis/linearalgebra/VectorBase.hpp b/src/amdis/linearalgebra/VectorBase.hpp index 4f69608047c186d8fbebe5ed7b1e72b1f2560870..36a55ad16480943166b6f967d0f69b7512a5938b 100644 --- a/src/amdis/linearalgebra/VectorBase.hpp +++ b/src/amdis/linearalgebra/VectorBase.hpp @@ -26,8 +26,8 @@ namespace AMDiS { /// \brief The basic container that stores a base vector and a corresponding basis /** - * A vector storing all the assembled Operators indexed with DOF indices. The vector - * data is associated to a global basis. + * A vector storing all the assembled Operators indexed with DOF indices. The + * vector data is associated to a global basis. * * \tparam GB Basis of the vector * \tparam B A linear algebra backend implementing the storage and operations. @@ -42,16 +42,15 @@ namespace AMDiS using GlobalBasis = GB; using LocalView = typename GlobalBasis::LocalView; - /// The Linear-Aglebra backend used to store the assembled coefficients + /// The Linear-Algebra backend used to store the assembled coefficients using Backend = B; + using Comm = typename B::Traits::Comm; private: - // proxy class redirecting the mutable element access to the inserValue method + // proxy class redirecting the mutable element access to the insertValue method template <class Index> struct AccessProxy; - using Comm = typename B::Traits::Comm; - enum class VectorState { unknown = 0, @@ -66,7 +65,7 @@ namespace AMDiS std::integral_constant<VectorState, VectorState::insert_values>>; public: - /// Constructor. Stores the shared_ptr of the basis and creates a new DataTransfer. + /// (1) Constructor. Stores the shared_ptr of the basis and communication object. VectorBase(std::shared_ptr<GB> basis, std::shared_ptr<Comm> comm) : basis_(std::move(basis)) , comm_(std::move(comm)) @@ -75,15 +74,27 @@ namespace AMDiS resizeZero(); } - /// Constructor. Wraps the reference into a non-destroying shared_ptr or moves - /// the basis into a new shared_ptr. + /// (2) Constructor. Forwards to (1) by wraping reference into non-destroying + /// shared_ptr. template <class GB_, class Comm_, - REQUIRES(Concepts::Similar<GB_,GB>), - REQUIRES(Concepts::Similar<Comm_,Comm>)> + REQUIRES(Concepts::Similar<Types<GB_,Comm_>, Types<GB,Comm>>)> VectorBase(GB_&& basis, Comm_&& comm) : VectorBase(Dune::wrap_or_move(FWD(basis)), Dune::wrap_or_move(FWD(comm))) {} + /// (3) Constructor. Forwards to (1) by creating a new communicator + explicit VectorBase(std::shared_ptr<GB> const& basis) + : VectorBase(basis, std::shared_ptr<Comm>(CommunicationCreator<Comm>::create(*basis))) + {} + + /// (4) Constructor. Forwards to (3) by wrapping references into non-destroying + /// shared_ptr, see \ref Dune::wrap_or_move. + template <class GB_, + REQUIRES(Concepts::Similar<GB_,GB>)> + explicit VectorBase(GB_&& basis) + : VectorBase(Dune::wrap_or_move(FWD(basis))) + {} + /// Return the basis \ref basis_ associated to the vector std::shared_ptr<GlobalBasis> const& basis() const { return basis_; } std::shared_ptr<GlobalBasis> const& basis() { return basis_; } @@ -157,7 +168,8 @@ namespace AMDiS return at(idx); } - /// Access the entry \p i of the \ref vector with write-access. Uses a proxy class the redirects to \ref insertValue. + /// Access the entry \p i of the \ref vector with write-access. Uses a proxy + /// class the redirects to \ref insertValue. template <class Index> AccessProxy<Index> DUNE_DEPRECATED_MSG("Do not use element-wise vector access") operator[](Index const& idx) @@ -176,10 +188,10 @@ namespace AMDiS /// \brief Insert a single value into the matrix (add or overwrite to existing value) /** - * Inserts or adds a value into a certain location \p dof (given as dof multi-index) of a vector. - * The insertion mode is determined by the \p assign functor. Use \ref Assigner::plus_assign for - * adding values (default) or \ref Assigner::assign for overwriting (setting) values. Different - * insertion modes can not be mixed! + * Inserts or adds a value into a certain location \p dof (given as dof multi-index) + * of a vector. The insertion mode is determined by the \p assign functor. Use + * \ref Assigner::plus_assign for adding values (default) or \ref Assigner::assign + * for overwriting (setting) values. Different insertion modes can not be mixed! * * Insertion must be closed with a call to \ref finish(). * @@ -214,13 +226,15 @@ namespace AMDiS } - /// \brief Extract values from the vector referring to the given local indices and store it into a buffer + /// \brief Extract values from the vector referring to the given local indices + /// and store it into a buffer /** - * Collect value of indices and store them into a buffer. The buffer must be a vector-like container - * with `buffer.resize()` and `buffer.begin()`. The indices must be stored in an iterable container. + * Collect value of indices and store them into a buffer. The buffer must be + * a vector-like container with `buffer.resize()` and `buffer.begin()`. The + * indices must be stored in an iterable container. * - * If the vector is not in synchronized state, collects all necessary values possibly from - * neighbouring processors. + * If the vector is not in synchronized state, collects all necessary values + * possibly from neighbouring processors. * * [[expects: localView is bound to an element]] * [[expects: node is in localView.tree()]] @@ -249,18 +263,19 @@ namespace AMDiS /// Insert a block of values into the vector (add or overwrite to existing values) /** - * Inserts or adds values into certain locations of a vector. Insertion indices are extracted from - * the given \p localView. The insertion mode is determined by the \p assign functor. Use - * \ref Assigner::plus_assign for adding values (default) or \ref Assigner::assign for overwriting - * (setting) values. Different insertion modes can not be mixed! The \p localVector is assumed - * to be a continuous memory container with a `data()` method to get a pointer to the beginning. + * Inserts or adds values into certain locations of a vector. Insertion indices + * are extracted from the given \p localView. The insertion mode is determined + * by the \p assign functor. Use \ref Assigner::plus_assign for adding values + * (default) or \ref Assigner::assign for overwriting (setting) values. Different + * insertion modes can not be mixed! The \p localVector is assumed to be a continuous + * memory container with a `data()` method to get a pointer to the beginning. * - * The \p mask models a boolean range with at least a `begin()` method. Must be forward iterable - * for at least `localVector.size()` elements. Does not need an `end()` method. See, e.g. - * \ref FakeContainer. + * The \p mask models a boolean range with at least a `begin()` method. Must + * be forward iterable for at least `localVector.size()` elements. Does not + * need an `end()` method. See, e.g. \ref FakeContainer. * - * Insertion must be closed with a call to \ref finish(). It is not allowed to switch insertion - * mode before calling `finish()`. + * Insertion must be closed with a call to \ref finish(). It is not allowed + * to switch insertion mode before calling `finish()`. * * [[expects: localView is bound to an element]] * [[expects: node is in localView.tree()]] @@ -338,8 +353,8 @@ namespace AMDiS /// Apply \p func to each value at given indices \p localInd /** - * First, synchronizes the values of the vector, then applies the functor to each local value - * associated to the local indices \p localInd. + * First, synchronizes the values of the vector, then applies the functor to + * each local value associated to the local indices \p localInd. * * [[mutable]] **/ @@ -361,8 +376,8 @@ namespace AMDiS /// Apply \p func to each value at given indices \p localInd /** - * First, synchronizes the values of the vector, then applies the functor to each local value - * associated to the local indices \p localInd. + * First, synchronizes the values of the vector, then applies the functor to + * each local value associated to the local indices \p localInd. * * [[const]] **/ @@ -414,7 +429,8 @@ namespace AMDiS /// Data backend Backend backend_; - /// The current state of the vector, one of {synchronized, insert_values, add_values, unknown} + /// The current state of the vector, one of {synchronized, insert_values, + /// add_values, unknown} VectorState state_ = VectorState::unknown; };