diff --git a/dumux/linear/amgbackend.hh b/dumux/linear/amgbackend.hh index bc79e5d4738fe32bfaa8ce0225257ef340bd4b02..b6d0ee62d488351e41d5da166d2ef95db51161ed 100644 --- a/dumux/linear/amgbackend.hh +++ b/dumux/linear/amgbackend.hh @@ -24,132 +24,18 @@ #ifndef DUMUX_AMGBACKEND_HH #define DUMUX_AMGBACKEND_HH -#if HAVE_DUNE_PDELAB - -#include <dune/pdelab/gridoperator/gridoperator.hh> -#include <dune/pdelab/backend/novlpistlsolverbackend.hh> -#include <dune/pdelab/backend/ovlpistlsolverbackend.hh> -#include <dune/pdelab/backend/seqistlsolverbackend.hh> -#include <dune/pdelab/backend/istlvectorbackend.hh> - -#include <dune/pdelab/finiteelementmap/q1fem.hh> +#include <dune/common/parallel/indexset.hh> +#include <dune/common/parallel/mpicollectivecommunication.hh> +#include <dune/istl/paamg/amg.hh> +#include <dune/istl/paamg/pinfo.hh> +#include <dune/istl/solvers.hh> + +#include <dumux/linear/amgproperties.hh> +#include <dumux/linear/amgparallelhelpers.hh> #include <dumux/linear/p0fem.hh> -#include <dumux/implicit/box/boxproperties.hh> -#include <dumux/implicit/cellcentered/ccproperties.hh> -#include <dumux/decoupled/common/pressureproperties.hh> -#include "linearsolverproperties.hh" - namespace Dumux { -// forward declaration for the property definitions -template <class TypeTag> class AMGBackend; - -namespace Properties -{ -//! the PDELab finite element map used for the gridfunctionspace -NEW_PROP_TAG(AMGLocalFemMap); - -//! box: use the (multi-)linear local FEM space associated with cubes by default -SET_PROP(BoxModel, AMGLocalFemMap) -{ - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - enum{dim = GridView::dimension}; -public: - typedef Dune::PDELab::Q1LocalFiniteElementMap<Scalar,Scalar,dim> type; -}; - -//! cell-centered: use the element-wise constant local FEM space by default -SET_PROP(CCModel, AMGLocalFemMap) -{ - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - enum{dim = GridView::dimension}; -public: - typedef Dumux::P0LocalFiniteElementMap<Scalar,Scalar,dim> type; -}; - -//! decoupled models: use the element-wise constant local FEM space by default -SET_PROP(DecoupledModel, AMGLocalFemMap) -{ - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - enum{dim = GridView::dimension}; -public: - typedef Dumux::P0LocalFiniteElementMap<Scalar,Scalar,dim> type; -}; - -//! the type of the employed PDELab backend -NEW_PROP_TAG(AMGPDELabBackend); - -//! box: use the non-overlapping PDELab AMG backend -SET_PROP(BoxModel, AMGPDELabBackend) -{ - typedef typename Dumux::AMGBackend<TypeTag>::GridOperator GridOperator; -public: - typedef Dune::PDELab::ISTLBackend_NOVLP_BCGS_AMG_SSOR<GridOperator> type; -}; - -//! cell-centered: use the overlapping PDELab AMG backend -SET_PROP(CCModel, AMGPDELabBackend) -{ - typedef typename Dumux::AMGBackend<TypeTag>::GridOperator GridOperator; -public: - typedef Dune::PDELab::ISTLBackend_BCGS_AMG_SSOR<GridOperator> type; -}; - -//! decoupled model: use the overlapping PDELab AMG backend -SET_PROP(DecoupledModel, AMGPDELabBackend) -{ - typedef typename Dumux::AMGBackend<TypeTag>::GridOperator GridOperator; -public: - typedef Dune::PDELab::ISTLBackend_BCGS_AMG_SSOR<GridOperator> type; -}; - -//! box: reset the type of solution vector to be PDELab conforming -SET_PROP(BoxModel, SolutionVector) -{ - typedef typename Dumux::AMGBackend<TypeTag>::GridOperator GridOperator; -public: - typedef typename GridOperator::Traits::Domain type; -}; - -//! cell-centered: reset the type of solution vector to be PDELab conforming -SET_PROP(CCModel, SolutionVector) -{ - typedef typename Dumux::AMGBackend<TypeTag>::GridOperator GridOperator; -public: - typedef typename GridOperator::Traits::Domain type; -}; - - -//! decoupled model: reset the type of solution vector to be PDELab conforming -SET_PROP(DecoupledModel, PressureSolutionVector) -{ - typedef typename Dumux::AMGBackend<TypeTag>::GridOperator GridOperator; -public: - typedef typename GridOperator::Traits::Domain type; -}; - -//! decoupled model: reset the type of solution vector to be PDELab conforming -SET_PROP(DecoupledModel, PressureRHSVector) -{ - typedef typename Dumux::AMGBackend<TypeTag>::GridOperator GridOperator; -public: - typedef typename GridOperator::Traits::Domain type; -}; - -//! set a property JacobianMatrix also for the decoupled models -SET_PROP(DecoupledModel, JacobianMatrix) -{ -public: - typedef typename GET_PROP_TYPE(TypeTag, PressureCoefficientMatrix) type; -}; - - -} - /*! * \brief Scale the linear system by the inverse of * its (block-)diagonal entries. @@ -188,36 +74,20 @@ class AMGBackend { typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, AMGLocalFemMap) LocalFemMap; typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - enum { dim = GridView::dimension }; - typedef typename Dune::PDELab::NoConstraints Constraints; typedef typename GET_PROP_TYPE(TypeTag, JacobianMatrix) JacobianMatrix; enum { numEq = JacobianMatrix::block_type::rows}; - typedef Dune::PDELab::GridFunctionSpace<GridView, - LocalFemMap, - Constraints, - Dune::PDELab::ISTLVectorBackend<numEq> - > ScalarGridFunctionSpace; - typedef Dune::PDELab::PowerGridFunctionSpace<ScalarGridFunctionSpace, - numEq, - Dune::PDELab::GridFunctionSpaceBlockwiseMapper - > GridFunctionSpace; - typedef typename GridFunctionSpace::template ConstraintsContainer<Scalar>::Type ConstraintsTrafo; - typedef int LocalOperator; -public: - typedef typename Dune::PDELab::GridOperator<GridFunctionSpace, - GridFunctionSpace, - LocalOperator, - Dune::PDELab::ISTLBCRSMatrixBackend<numEq, numEq>, - Scalar, Scalar, Scalar, - ConstraintsTrafo, - ConstraintsTrafo, - true - > GridOperator; - typedef typename GET_PROP_TYPE(TypeTag, AMGPDELabBackend) PDELabBackend; + typedef typename GET_PROP(TypeTag, AMGPDELabBackend) PDELabBackend; + typedef typename PDELabBackend::LinearOperator LinearOperator; + typedef typename PDELabBackend::VType VType; + typedef typename PDELabBackend::Comm Comm; + typedef typename PDELabBackend::Smoother Smoother; + typedef Dune::Amg::AMG<typename PDELabBackend::LinearOperator, VType, + Smoother,Comm> AMGType; + typedef typename PDELabBackend::LinearOperator::matrix_type BCRSMat; +public: /*! * \brief Construct the backend. * @@ -226,13 +96,6 @@ public: AMGBackend(const Problem& problem) : problem_(problem) { - fem_ = Dune::make_shared<LocalFemMap>(); - constraints_ = Dune::make_shared<Constraints>(); - scalarGridFunctionSpace_ = Dune::make_shared<ScalarGridFunctionSpace>(problem.gridView(), *fem_, *constraints_); - gridFunctionSpace_ = Dune::make_shared<GridFunctionSpace>(*scalarGridFunctionSpace_); - int maxIt = GET_PARAM_FROM_GROUP(TypeTag, double, LinearSolver, MaxIterations); - int verbosity = GET_PARAM_FROM_GROUP(TypeTag, int, LinearSolver, Verbosity); - imp_ = Dune::make_shared<PDELabBackend>(*gridFunctionSpace_, maxIt, verbosity); } /*! @@ -245,17 +108,49 @@ public: template<class Matrix, class Vector> bool solve(Matrix& A, Vector& x, Vector& b) { + int maxIt = GET_PARAM_FROM_GROUP(TypeTag, double, LinearSolver, MaxIterations); + int verbosity = GET_PARAM_FROM_GROUP(TypeTag, int, LinearSolver, Verbosity); static const double residReduction = GET_PARAM_FROM_GROUP(TypeTag, double, LinearSolver, ResidualReduction); - imp_->apply(A, x, b, residReduction); - - result_.converged = imp_->result().converged; - result_.iterations = imp_->result().iterations; - result_.elapsed = imp_->result().elapsed; - result_.reduction = imp_->result().reduction; - result_.conv_rate = imp_->result().conv_rate; + +#if HAVE_MPI + typename PDELabBackend::Comm comm(problem_.model().gridView().comm(), + PDELabBackend::isNonOverlapping? + Dune::SolverCategory::nonoverlapping: + Dune::SolverCategory::overlapping); + + if(PDELabBackend::isNonOverlapping) + { + // extend the matrix pattern such that it is usable for AMG + + } + typename PDELabBackend::LinearOperator fop(A, comm); + typename PDELabBackend::ScalarProduct sp(comm); + int rank = comm_.communicator().rank(); +#else + typename PDELabBackend::Comm comm; + typename PDELabBackend::LinearOperator fop(A); + typename PDELabBackend::ScalarProduct sp; + int rank=0; +#endif + + typedef typename Dune::Amg::SmootherTraits<Smoother>::Arguments + SmootherArgs; + typedef Dune::Amg::CoarsenCriterion<Dune::Amg::SymmetricCriterion<BCRSMat, + Dune::Amg::FirstDiagonal> > + Criterion; + Criterion criterion(15, 2000); + criterion.setDefaultValuesIsotropic(2); + SmootherArgs smootherArgs; + smootherArgs.iterations = 1; + smootherArgs.relaxationFactor = 1; + + AMGType amg(fop, criterion, smootherArgs, 1, 1, 1, false, comm); + Dune::BiCGSTABSolver<typename PDELabBackend::VType> solver(fop, sp, amg, residReduction, maxIt, + rank==0?verbosity: 0); + solver.apply(x, b, result_); return result_.converged; - } + } /*! * \brief The result containing the convergence history. @@ -267,11 +162,6 @@ public: private: const Problem& problem_; - Dune::shared_ptr<LocalFemMap> fem_; - Dune::shared_ptr<Constraints> constraints_; - Dune::shared_ptr<ScalarGridFunctionSpace> scalarGridFunctionSpace_; - Dune::shared_ptr<GridFunctionSpace> gridFunctionSpace_; - Dune::shared_ptr<PDELabBackend> imp_; Dune::InverseOperatorResult result_; }; @@ -282,8 +172,15 @@ template <class TypeTag> class SeqAMGBackend { typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename AMGBackend<TypeTag>::GridOperator GridOperator; - typedef Dune::PDELab::ISTLBackend_SEQ_BCGS_AMG_SSOR<GridOperator> PDELabBackend; + typedef typename GET_PROP_TYPE(TypeTag, JacobianMatrix) JacobianMatrix; + enum { numEq = JacobianMatrix::block_type::rows}; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef Dune::BCRSMatrix<Dune::FieldMatrix<Scalar,numEq,numEq> > MType; + typedef Dune::BlockVector<Dune::FieldVector<Scalar,numEq> > VType; + typedef Dune::Amg::SequentialInformation Comm; + typedef Dune::AssembledLinearOperator<MType,VType, VType> LinearOperator; + typedef Dune::SeqSSOR<MType,VType, VType> Smoother; + typedef Dune::Amg::AMG<LinearOperator,VType,Smoother> AMGType; public: /*! @@ -307,19 +204,22 @@ public: { int maxIt = GET_PARAM_FROM_GROUP(TypeTag, double, LinearSolver, MaxIterations); int verbosity = GET_PARAM_FROM_GROUP(TypeTag, int, LinearSolver, Verbosity); - imp_ = Dune::make_shared<PDELabBackend>(maxIt, verbosity); - static const double residReduction = GET_PARAM_FROM_GROUP(TypeTag, double, LinearSolver, ResidualReduction); - imp_->apply(A, x, b, residReduction); - - result_.converged = imp_->result().converged; - result_.iterations = imp_->result().iterations; - result_.elapsed = imp_->result().elapsed; - result_.reduction = imp_->result().reduction; - result_.conv_rate = imp_->result().conv_rate; - - imp_.template reset<PDELabBackend>(0); - + LinearOperator fop(A); + typedef Dune::Amg::CoarsenCriterion<Dune::Amg::SymmetricCriterion<typename LinearOperator::matrix_type, + Dune::Amg::FirstDiagonal> > + Criterion; + Criterion criterion(15,2000); + criterion.setDefaultValuesIsotropic(2); + typedef typename Dune::Amg::SmootherTraits<Smoother>::Arguments SmootherArgs; + SmootherArgs smootherArgs; + smootherArgs.iterations = 1; + smootherArgs.relaxationFactor = 1; + + AMGType amg(fop, criterion, smootherArgs, 1, 1, 1); + Dune::BiCGSTABSolver<VType> solver(fop, amg, residReduction, maxIt, + verbosity); + solver.apply(x, b, result_); return result_.converged; } @@ -333,7 +233,6 @@ public: private: const Problem& problem_; - Dune::shared_ptr<PDELabBackend> imp_; Dune::InverseOperatorResult result_; }; @@ -347,8 +246,15 @@ template <class TypeTag> class ScaledSeqAMGBackend { typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename AMGBackend<TypeTag>::GridOperator GridOperator; - typedef Dune::PDELab::ISTLBackend_SEQ_BCGS_AMG_SSOR<GridOperator> PDELabBackend; + typedef typename GET_PROP_TYPE(TypeTag, JacobianMatrix) JacobianMatrix; + enum { numEq = JacobianMatrix::block_type::rows}; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef Dune::BCRSMatrix<Dune::FieldMatrix<Scalar,numEq,numEq> > MType; + typedef Dune::BlockVector<Dune::FieldVector<Scalar,numEq> > VType; + typedef Dune::Amg::SequentialInformation Comm; + typedef Dune::MatrixAdapter<MType,VType, VType> LinearOperator; + typedef Dune::SeqSSOR<MType,VType, VType> Smoother; + typedef Dune::Amg::AMG<LinearOperator,VType,Smoother> AMGType; public: /*! @@ -374,18 +280,20 @@ public: int maxIt = GET_PARAM_FROM_GROUP(TypeTag, double, LinearSolver, MaxIterations); int verbosity = GET_PARAM_FROM_GROUP(TypeTag, int, LinearSolver, Verbosity); - imp_ = Dune::make_shared<PDELabBackend>(maxIt, verbosity); - static const double residReduction = GET_PARAM_FROM_GROUP(TypeTag, double, LinearSolver, ResidualReduction); - imp_->apply(A, x, b, residReduction); - - result_.converged = imp_->result().converged; - result_.iterations = imp_->result().iterations; - result_.elapsed = imp_->result().elapsed; - result_.reduction = imp_->result().reduction; - result_.conv_rate = imp_->result().conv_rate; - - imp_.template reset<PDELabBackend>(0); + LinearOperator fop(A); + typedef Dune::Amg::CoarsenCriterion<Dune::Amg::SymmetricCriterion<MType, + Dune::Amg::FirstDiagonal> > + Criterion; + Criterion criterion(15,2000); + criterion.setDefaultValuesIsotropic(2); + typedef typename Dune::Amg::SmootherTraits<Smoother>::Arguments SmootherArgs; + SmootherArgs smootherArgs; + smootherArgs.iterations = 1; + smootherArgs.relaxationFactor = 1; + AMGType amg(fop, criterion, smootherArgs, 1, 1, 1); + Dune::BiCGSTABSolver<VType> solver(fop, amg, residReduction, maxIt, + verbosity); return result_.converged; } @@ -400,11 +308,9 @@ public: private: const Problem& problem_; - Dune::shared_ptr<PDELabBackend> imp_; Dune::InverseOperatorResult result_; }; } // namespace Dumux -#endif // HAVE_DUNE_PDELAB #endif // DUMUX_AMGBACKEND_HH diff --git a/dumux/linear/amgparallelhelpers.hh b/dumux/linear/amgparallelhelpers.hh new file mode 100644 index 0000000000000000000000000000000000000000..fa9b1b20a7198d4bfce8c51d2c61c13e40d1e50b --- /dev/null +++ b/dumux/linear/amgparallelhelpers.hh @@ -0,0 +1,819 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +#ifndef DUMUX_AMGPARALLELHELPERS_HH +#define DUMUX_AMGPARALLELHELPERS_HH + +#include <dumux/implicit/box/boxproperties.hh> +#include <dumux/implicit/cellcentered/ccproperties.hh> +#include <dumux/decoupled/common/pressureproperties.hh> + + +namespace Dumux +{ + +//======================================================== +// A parallel helper class providing a nonoverlapping +// decomposition of all degrees of freedom +//======================================================== + +// operator that resets result to zero at constrained DOFS +template<class TypeTag> +class ParallelISTLHelper +{ + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GET_PROP_TYPE(TypeTag, AMGLocalFemMap) LocalFemMap; + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + + enum { isBox = GET_PROP_VALUE(TypeTag, ImplicitIsBox) }; + enum { dofCodim = isBox ? GridView::dimension : 0 }; + + class BaseGatherScatter + { + public: + BaseGatherScatter(const Problem& problem) + : problem_(problem) + {} + + bool contains(int dim, int codim) + { + return dofCodim==codim; + } + + bool fixedSize(int dim, int codim) + { + return true; + + } + template<class EntityType> + int map(const EntityType& e) + { + return problem_.model().dofMapper().map(e); + } + + private: + Problem& problem_; + }; + + + /** + * @brief Writes 1<<24 to each data item (of the container) that is gathered or scattered + * and is neither interior nor border. + * + * Can be used to mark ghost cells. + */ + class GhostGatherScatter + : public BaseGatherScatter, Dune::CommDataHandleIF<GhostGatherScatter,std::size_t> + { + public: + typedef std::size_t DataType; + + GhostGatherScatter(std::vector<std::size_t>& ranks, + const Problem& problem) + : BaseGatherScatter(problem), ranks_(ranks) + {} + + template<class MessageBuffer, class EntityType> + void gather (MessageBuffer& buff, const EntityType& e) + { + std::size_t& data= ranks_[this->map(e)]; + if (e.partitionType()!=Dune::InteriorEntity && e.partitionType()!=Dune::BorderEntity) + data = (1<<24); + buff.write(data); + } + + template<class MessageBuffer, class EntityType> + void scatter (MessageBuffer& buff, const EntityType& e) + { + std::size_t x; + std::size_t& data = ranks_[this->map(e)]; + buff.read(x); + if (e.partitionType()!=Dune::InteriorEntity && e.partitionType()!=Dune::BorderEntity) + data= (1<<24); + else + data = x; + } + private: + std::vector<std::size_t>& ranks_; + }; + + /** + * @brief GatherScatter handle that sets 1<<24 for data items neither associated to + * the interior or border and take the minimum when scattering. + * + * Used to compute an owner rank for each unknown. + */ + class InteriorBorderGatherScatter + : public BaseGatherScatter, Dune::CommDataHandleIF<InteriorBorderGatherScatter,std::size_t> + { + public: + typedef std::size_t DataType; + + InteriorBorderGatherScatter(std::vector<std::size_t>& ranks, + const Problem& problem) + : BaseGatherScatter(problem), ranks_(ranks) + {} + + template<class MessageBuffer, class EntityType> + void gather (MessageBuffer& buff, const EntityType& e) + { + + std::size_t& data = ranks_[this->map(e)]; + if (e.partitionType()!=Dune::InteriorEntity && e.partitionType()!=Dune::BorderEntity) + data = (1<<24); + buff.write(data); + } + + template<class MessageBuffer, class EntityType> + void scatter (MessageBuffer& buff, const EntityType& e) + { + std::size_t x; + std::size_t& data = ranks_[this->map(e)]; + buff.read(x); + if (e.partitionType()!=Dune::InteriorEntity && e.partitionType()!=Dune::BorderEntity) + data = x; + else + data = std::min(data,x); + } + private: + std::vector<std::size_t>& ranks_; + }; + + /** + * @brief GatherScatter handle for finding out about neighbouring processor ranks. + * + */ + struct NeighbourGatherScatter + : public BaseGatherScatter, Dune::CommDataHandleIF<NeighbourGatherScatter,int> + { + typedef int DataType; + + NeighbourGatherScatter(int rank_, std::set<int>& neighbours_) + : myrank(rank_), neighbours(neighbours_) + {} + + template<class MessageBuffer, class EntityType> + void gather (MessageBuffer& buff, const EntityType &e) + { + buff.write(myrank); + } + + template<class MessageBuffer, class EntityType> + void scatter (MessageBuffer& buff, const EntityType &e) + { + int x; + buff.read(x); + neighbours.insert(x); + } + int myrank; + std::set<int>& neighbours; + }; + + + /** + * @brief GatherScatter handle for finding out about neighbouring processor ranks. + * + */ + struct SharedGatherScatter + : public BaseGatherScatter, Dune::CommDataHandleIF<SharedGatherScatter,int> + { + typedef int DataType; + + SharedGatherScatter(std::vector<int>& shared, + const Problem& problem) + : BaseGatherScatter(problem), shared_(shared) + {} + + template<class MessageBuffer, class EntityType> + void gather (MessageBuffer& buff, EntityType& e) + { + bool data=true; + buff.write(data); + } + + template<class MessageBuffer, class EntityType> + void scatter (MessageBuffer& buff, const EntityType &e) + { + bool x; + buff.read(x); + bool& data= shared_[this->map(e)]; + data = data || x; + } + private: + std::vector<int>& shared_; + + }; + + /** + * @brief GatherScatter handle for finding out about neighbouring processor ranks. + * + */ + template<typename GI> + struct GlobalIndexGatherScatter + : public BaseGatherScatter, Dune::CommDataHandleIF<GlobalIndexGatherScatter<GI>, GI> + { + typedef GI DataType; + GlobalIndexGatherScatter(std::vector<GI>& gindices, + const Problem& problem) + : BaseGatherScatter(problem), gindices_(gindices_) + {} + + template<class MessageBuffer, class EntityType> + void gather (MessageBuffer& buff, const EntityType& e) + { + buff.write(gindices_[this->map(e)]); + } + + template<class MessageBuffer, class EntityType> + void scatter (MessageBuffer& buff, const EntityType& e) + { + DataType x; + buff.read(x); + gindices_[this->map(e)] = std::min(gindices_[this->map(e)], x); + } + private: + std::vector<GI>& gindices_; + }; + +public: + + ParallelISTLHelper (const Problem& problem, int verbose=1) + : problem_(problem), owner_(problem.dofMapper().size(), + problem.gridView().comm().rank()), + isGhost_(problem.dofMapper().size(),0.0), verbose_(verbose) + { + // find out about ghosts + GhostGatherScatter ggs(owner_,problem); + + if (problem.gridView().comm().size()>1) + problem.gridView().communicate(ggs,Dune::InteriorBorder_All_Interface,Dune::ForwardCommunication); + + isGhost_ = owner_; + + // partition interior/border + InteriorBorderGatherScatter dh(owner_, problem_); + + if (problem.gridView().comm().size()>1) + problem.gridView().communicate(dh,Dune::InteriorBorder_InteriorBorder_Interface,Dune::ForwardCommunication); + + // convert vector into mask vector + for(auto v=owner_.begin(), vend=owner_.end(); v!=vend;++v) + if(*v=problem.gridView().comm().rank()) + *v=1.0; + else + *v=0.0; + } + + // keep only DOFs assigned to this processor + template<typename W> + void mask (W& w) const + { + auto v1=w.begin(); + + for(auto v2=owner_.begin(), vend=owner_.end(); v2!=vend;++v1,++v2) + v1*=v2; + } + + // access to mask vector + double mask (std::size_t i) const + { + return owner_[i]; + } + + // access to ghost vector + double ghost (std::size_t i) const + { + return isGhost_[i]; + } + +#if HAVE_MPI + + /** + * @brief Creates a matrix suitable for parallel AMG and the parallel information + * + * It is silently assumed that the unknows are associated with vertices. + * + * @tparam MatrixType The type of the ISTL matrix used. + * @tparam Comm The type of the OwnerOverlapCopyCommunication + * @param m The local matrix. + * @param c The parallel information object providing index set, interfaces and + * communicators. + */ + template<typename MatrixType, typename Comm> + void createIndexSetAndProjectForAMG(MatrixType& m, Comm& c); +#endif +private: + const Problem& problem_; + std::vector<std::size_t> owner_; // vector to identify unique decomposition + std::vector<std::size_t> isGhost_; //vector to identify ghost dofs + int verbose_; //verbosity +}; + +/** + * @brief Helper class for adding up matrix entries on border. + * @tparam GridOperator The grid operator to work on. + * @tparam MatrixType The MatrixType. + */ +template<class TypeTag> +class EntityExchanger +{ + typedef typename GET_PROP_TYPE(TypeTag, JacobianMatrix) JacobianMatrix; + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, AMGLocalFemMap) LocalFemMap; + enum { numEq = JacobianMatrix::block_type::rows}; + typedef Dune::BCRSMatrix<Dune::FieldMatrix<Scalar,numEq,numEq> > Matrix; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + enum {dim = GridView::dimension}; + typedef typename GridView::Traits::Grid Grid; + typedef typename Matrix::block_type BlockType; + typedef typename GridView::template Codim<LocalFemMap::dof_codim>::Iterator EntityIterator; + typedef typename Grid::Traits::GlobalIdSet IDS; + typedef typename IDS::IdType IdType; + typedef typename Matrix::RowIterator RowIterator; + typedef typename Matrix::ColIterator ColIterator; + + enum { isBox = GET_PROP_VALUE(TypeTag, ImplicitIsBox) }; + enum { dofCodim = isBox ? dim : 0 }; + +public: + /*! \brief Constructor. Sets up the local to global relations. + + \param[in] gridView The grid view to operate on. + */ + EntityExchanger(const Problem& problem) + : problem_(problem) + { + gid2Index_.clear(); + index2GID_.clear(); + + const GridView& gridView = problem.model().gridView(); + + EntityIterator entityEndIt = gridView.template end<dim>(); + for (EntityIterator entityIt = gridView.template begin<dim>(); entityIt != entityEndIt; ++entityIt) + { + if (entityIt->partitionType() == Dune::BorderEntity) + { + int localIdx = problem_.model().dofMapper().map(*entityIt); + IdType globalIdx = gridView.grid().globalIdSet().id(*entityIt); + + std::pair<IdType,int> g2iPair(globalIdx, localIdx); + gid2Index_.insert(g2iPair); + + std::pair<int,IdType> i2gPair(localIdx, globalIdx); + index2GID_.insert(i2gPair); + + } + } + } + + /** + * @brief A DataHandle class to exchange matrix sparsity patterns. + * + * We look at a 2D example with a nonoverlapping grid, + * two processes and no ghosts with Q1 discretization. + * Process 0 has the left part of the domain + * with three cells and eight vertices (1-8), + * Process 1 the right part with three cells + * and eight vertices (2,4,7-12). + * <pre> + * 1 _ 2 2 _ 9 _ 10 + * | | | | | + * 3 _ 4 _ 7 4 _ 7 _ 11 + * | | | | | + * 5 _ 6 _ 8 8 _ 12 + * </pre> + * If we look at vertex 7 and the corresponding entries in the matrix for P0, + * there will be entries for (7,4) and (7,8), but not for (7,2). + * The MatPatternExchange class will find these entries and returns a vector "sparsity", + * that contains all missing connections. + */ + class MatPatternExchange + : public Dune::CommDataHandleIF<MatPatternExchange,IdType> { + typedef typename Matrix::RowIterator RowIterator; + typedef typename Matrix::ColIterator ColIterator; + public: + //! Export type of data for message buffer + typedef IdType DataType; + + /** @brief Returns true if data for given valid codim should be communicated + */ + bool contains (int dim, int codim) const + { + return (codim==dofCodim); + } + + /** @brief Returns true if size of data per entity of given dim and codim is a constant + */ + bool fixedsize (int dim, int codim) const + { + return false; + } + + /** @brief How many objects of type DataType have to be sent for a given entity + */ + template<class EntityType> + size_t size (EntityType& e) const + { + int i = problem_.model().dofMapper().map(e); + int n = 0; + for (ColIterator j = A_[i].begin(); j != A_[i].end(); ++j) + { + typename std::map<int,IdType>::const_iterator it = index2GID_.find(j.index()); + if (it != index2GID_.end()) + n++; + } + + return n; + } + + /** @brief Pack data from user to message buffer + */ + template<class MessageBuffer, class EntityType> + void gather (MessageBuffer& buff, const EntityType& e) const + { + int i = problem_.model().dofMapper().map(e); + for (ColIterator j = A_[i].begin(); j != A_[i].end(); ++j) + { + typename std::map<int,IdType>::const_iterator it=index2GID_.find(j.index()); + if (it != index2GID_.end()) + buff.write(it->second); + } + + } + + /** @brief Unpack data from message buffer to user + */ + template<class MessageBuffer, class EntityType> + void scatter (MessageBuffer& buff, const EntityType& e, size_t n) + { + int i = problem_.model().dofMapper().map(e); + for (size_t k = 0; k < n; k++) + { + IdType id; + buff.read(id); + // only add entries corresponding to border entities + typename std::map<IdType,int>::const_iterator it = gid2Index_.find(id); + if (it != gid2Index_.end() + && sparsity_[i].find(it->second) == sparsity_[i].end() + && helper_.ghost(it->second) != 1<<24) + sparsity_[i].insert(it->second); + } + } + + /** + * @brief Get the communicated sparsity pattern + * @return the vector with the sparsity pattern + */ + std::vector<std::set<int> >& sparsity () + { + return sparsity_; + } + + /** @brief Constructor + @param[in] gridView Grid view. + @param[in] g2i Global to local index map. + @param[in] i2g Local to global index map. + @param[in] A Matrix to operate on. + @param[in] helper parallel istl helper. + */ + MatPatternExchange (const Problem& problem, + const std::map<IdType,int>& g2i, + const std::map<int,IdType>& i2g, Matrix& A, + const ParallelISTLHelper<TypeTag>& helper) + : problem_(problem), gid2Index_(g2i), index2GID_(i2g), + sparsity_(A.N()), A_(A), helper_(helper) + {} + + private: + const Problem& problem_; + const std::map<IdType,int>& gid2Index_; + const std::map<int,IdType>& index2GID_; + std::vector<std::set<int> > sparsity_; + Matrix& A_; + const ParallelISTLHelper<TypeTag>& helper_; + }; + + //! Local matrix blocks associated with the global id set + struct MatEntry + { + IdType first; + BlockType second; + MatEntry (const IdType& f, const BlockType& s) : first(f),second(s) {} + MatEntry () {} + }; + + //! A DataHandle class to exchange matrix entries + class MatEntryExchange + : public Dune::CommDataHandleIF<MatEntryExchange,MatEntry> { + typedef typename Matrix::RowIterator RowIterator; + typedef typename Matrix::ColIterator ColIterator; + public: + //! Export type of data for message buffer + typedef MatEntry DataType; + + /** @brief Returns true if data for given valid codim should be communicated + */ + bool contains (int dim, int codim) const + { + return (codim==dofCodim); + } + + /** @brief Returns true if size of data per entity of given dim and codim is a constant + */ + bool fixedsize (int dim, int codim) const + { + return false; + } + + /** @brief How many objects of type DataType have to be sent for a given entity + */ + template<class EntityType> + size_t size (EntityType& e) const + { + int i = problem_.model().dofMapper().map(e); + int n = 0; + for (ColIterator j = A_[i].begin(); j != A_[i].end(); ++j) + { + typename std::map<int,IdType>::const_iterator it = index2GID_.find(j.index()); + if (it != index2GID_.end()) + n++; + } + + return n; + } + + /** @brief Pack data from user to message buffer + */ + template<class MessageBuffer, class EntityType> + void gather (MessageBuffer& buff, const EntityType& e) const + { + int i = problem_.model().dofMapper().map(e); + for (ColIterator j = A_[i].begin(); j != A_[i].end(); ++j) + { + typename std::map<int,IdType>::const_iterator it=index2GID_.find(j.index()); + if (it != index2GID_.end()) + buff.write(MatEntry(it->second,*j)); + } + + } + + /** @brief Unpack data from message buffer to user + */ + template<class MessageBuffer, class EntityType> + void scatter (MessageBuffer& buff, const EntityType& e, size_t n) + { + int i = problem_.model().dofMapper().map(e); + for (size_t k = 0; k < n; k++) + { + MatEntry m; + buff.read(m); + // only add entries corresponding to border entities + typename std::map<IdType,int>::const_iterator it = gid2Index_.find(m.first); + if (it != gid2Index_.end()) + if (A_[i].find(it->second) != A_[i].end()) + A_[i][it->second] += m.second; + } + } + + /** @brief Constructor + @param[in] gridView Grid view. + @param[in] g2i Global to local index map. + @param[in] i2g Local to global index map. + @param[in] A Matrix to operate on. + */ + MatEntryExchange (const Problem& problem, const std::map<IdType,int>& g2i, + const std::map<int,IdType>& i2g, + Matrix& A) + : problem_(problem), gid2Index_(g2i), index2GID_(i2g), A_(A) + {} + + private: + const Problem& problem_; + const std::map<IdType,int>& gid2Index_; + const std::map<int,IdType>& index2GID_; + Matrix& A_; + }; + + /** @brief communicates values for the sparsity pattern of the new matrix. + @param A Matrix to operate on. + @param helper ParallelelISTLHelper. + */ + void getextendedmatrix (Matrix& A,const ParallelISTLHelper<TypeTag>& helper) + { + if (problem_.model().gridView().comm().size() > 1) { + Matrix tmp(A); + std::size_t nnz=0; + // get entries from other processes + MatPatternExchange datahandle(problem_, gid2Index_, index2GID_, A, helper); + problem_.model().gridView().communicate(datahandle, + Dune::InteriorBorder_InteriorBorder_Interface, + Dune::ForwardCommunication); + std::vector<std::set<int> >& sparsity = datahandle.sparsity(); + // add own entries, count number of nonzeros + for (RowIterator i = A.begin(); i != A.end(); ++i){ + for (ColIterator j = A[i.index()].begin(); j != A[i.index()].end(); ++j){ + if (sparsity[i.index()].find(j.index()) == sparsity[i.index()].end()) + sparsity[i.index()].insert(j.index()); + } + nnz += sparsity[i.index()].size(); + } + A.setSize(tmp.N(), tmp.N(), nnz); + A.setBuildMode(Matrix::row_wise); + typename Matrix::CreateIterator citer = A.createbegin(); + typedef typename std::vector<std::set<int> >::const_iterator Iter; + for (Iter i = sparsity.begin(), end = sparsity.end(); i!=end; ++i, ++citer){ + typedef typename std::set<int>::const_iterator SIter; + for (SIter si = i->begin(), send = i->end(); si!=send; ++si) + citer.insert(*si); + } + // set matrix old values + A = 0; + for (RowIterator i = tmp.begin(); i != tmp.end(); ++i) + for (ColIterator j = tmp[i.index()].begin(); j != tmp[i.index()].end(); ++j){ + A[i.index()][j.index()] = tmp[i.index()][j.index()]; + } + } + } + + /** @brief Sums up the entries corresponding to border vertices. + @param A Matrix to operate on. + */ + void sumEntries (Matrix& A) + { + if (problem_.model().gridView().comm().size() > 1) + { + MatEntryExchange datahandle(problem_.model().gridView(), gid2Index_, index2GID_, A); + problem_.model().gridView().communicate(datahandle, + Dune::InteriorBorder_InteriorBorder_Interface, + Dune::ForwardCommunication); + } + } + +private: + const Problem& problem_; + std::map<IdType,int> gid2Index_; + std::map<int,IdType> index2GID_; +}; + +#if HAVE_MPI + +void getextendedmatrix (M& A) const +{ + const GridView& gridView = problem_.model().gridView(); + if (gridView.comm().size() > 1) { + Matrix tmp(A); + std::size_t nnz=0; + // get entries from other processes + MatPatternExchange datahandle(problem_, gid2Index_, index2GID_, A, *this); + gridView.communicate(datahandle, + Dune::InteriorBorder_InteriorBorder_Interface, + Dune::ForwardCommunication); + std::vector<std::set<int> >& sparsity = datahandle.sparsity(); + // add own entries, count number of nonzeros + for (RowIterator i = A.begin(); i != A.end(); ++i){ + for (ColIterator j = A[i.index()].begin(); j != A[i.index()].end(); ++j){ + if (sparsity[i.index()].find(j.index()) == sparsity[i.index()].end()) + sparsity[i.index()].insert(j.index()); + } + nnz += sparsity[i.index()].size(); + } + A.setSize(tmp.N(), tmp.N(), nnz); + A.setBuildMode(Matrix::row_wise); + typename Matrix::CreateIterator citer = A.createbegin(); + typedef typename std::vector<std::set<int> >::const_iterator Iter; + for (Iter i = sparsity.begin(), end = sparsity.end(); i!=end; ++i, ++citer){ + typedef typename std::set<int>::const_iterator SIter; + for (SIter si = i->begin(), send = i->end(); si!=send; ++si) + citer.insert(*si); + } + // set matrix old values + A = 0; + for (RowIterator i = tmp.begin(); i != tmp.end(); ++i) + for (ColIterator j = tmp[i.index()].begin(); j != tmp[i.index()].end(); ++j){ + A[i.index()][j.index()] = tmp[i.index()][j.index()]; + } + } +} + +template<typename M, typename C> +void ParallelISTLHelper<GFS,skipBlocksizeCheck>::createIndexSetAndProjectForAMG(M& m, C& c) +{ + const GridView& gridview = problem_.model().gridView(); + + // First find out which dofs we share with other processors + std::vector<int> sharedDofs(problem_.model().dofMapper().size(), false); + + SharedGatherScatter sgs(sharedDofs, problem_); + + if (gridview.comm().size()>1) + gridview.communicate(sgs,Dune::All_All_Interface, + Dune::ForwardCommunication); + + // Count shared dofs that we own + typedef typename C::ParallelIndexSet::GlobalIndex GlobalIndex; + GlobalIndex count=0; + + for(auto v=sharedDofs.begin(), vend=sharedDofs.end(); v != vend; ++v) + if(*v) + ++count; + + dverb<<gridview.comm().rank()<<": shared count is "<< count.touint() + <<std::endl; + + dverb<<gridview.comm().rank()<<": shared block count is " + << count.touint()<<std::endl; + + + std::vector<GlobalIndex> counts(gridview.comm().size()); + gridview.comm().allgather(&count, 1, &(counts[0])); + + // Compute start index start_p = \sum_{i=0}^{i<p} counts_i + GlobalIndex start=0; + for(int i=0; i<gridview.comm().rank(); ++i) + start=start+counts[i]; + //std::cout<<gv.comm().rank()<<": start index = "<<start.touint()<<std::endl; + + + typedef std::vector<GlobalIndex> GIVector; + GIVector scalarIndices(problem_.model().dofMapper().size(), + std::numeric_limits<GlobalIndex>::max()); + + auto shared=sharedDofs.begin(); + auto index=scalarIndices.begin(); + + for(auto i=vi.begin(), ien=vi.end(); i!=vi; ++i, ++shared) + if(*i==1.0 && *shared){ + *index=start; + } + + // publish global indices for the shared DOFS to other processors. + typedef GlobalIndexGatherScatter<GlobalIndex> GIGS; + GIGS gigs(scalarIndices, problem_); + if (gridview.comm().size()>1) + gridview.communicate(gigs,Dune::All_All_Interface, + Dune::ForwardCommunication); + + + // Setup the index set + c.indexSet().beginResize(); + index=scalarIndices.begin(); + auto ghost=isGhost.begin(); + + for(auto i=v.begin(), iend=vend(); i!=iend; ++i) + { + Dune::OwnerOverlapCopyAttributeSet::AttributeSet attr; + if(*index!=std::numeric_limits<GlobalIndex>::max()){ + // global index exist in index set + if(*i>0){ + // This dof is managed by us. + attr = Dune::OwnerOverlapCopyAttributeSet::owner; + } + else if ( *g==(1<<24) && ( c.getSolverCategory() == + static_cast<int>(SolverCategory::nonoverlapping)) ){ + //use attribute overlap for ghosts in novlp grids + attr = Dune::OwnerOverlapCopyAttributeSet::overlap; + } + else { + attr = Dune::OwnerOverlapCopyAttributeSet::copy; + } + c.indexSet().add(index, typename C::ParallelIndexSet::LocalIndex(i, attr))); + } + c.indexSet().endResize(); + //std::cout<<gv.comm().rank()<<": index set size = "<<c.indexSet().size()<<std::endl; + //std::cout<<gv.comm().rank()<<": "<<c.indexSet()<<std::endl; + + // Compute neighbours using communication + typedef NeighbourGatherScatter NeighbourGS; + std::set<int> neighbours; + NeighbourGatherScatter ngs(gridview.comm().rank(), + neighbours); + + if (gridview.comm().size()>1) + gridview.communicate(ngs,Dune::All_All_Interface, + Dune::ForwardCommunication); + c.remoteIndices().setNeighbours(neighbours); + //std::cout<<gv.comm().rank()<<": no neighbours="<<neighbours.size()<<std::endl; + + c.remoteIndices().template rebuild<false>(); + //std::cout<<c.remoteIndices()<<std::endl; + +} +#endif +} +#endif diff --git a/dumux/linear/amgproperties.hh b/dumux/linear/amgproperties.hh new file mode 100644 index 0000000000000000000000000000000000000000..cfc3c32aba96edbc99bafa90708a7f8af2aef926 --- /dev/null +++ b/dumux/linear/amgproperties.hh @@ -0,0 +1,212 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +#ifndef DUMUXAMGPROPERTIES_HH +#define DUMUXAMGPROPERTIES_HH + + +#include <dune/istl/schwarz.hh> +#include <dune/istl/novlpschwarz.hh> +#include <dune/istl/owneroverlapcopy.hh> +#include <dune/istl/paamg/pinfo.hh> +#include <dune/istl/preconditioners.hh> + +#include <dumux/implicit/box/boxproperties.hh> +#include <dumux/implicit/cellcentered/ccproperties.hh> +#include <dumux/decoupled/common/decoupledproperties.hh> +#include <dumux/decoupled/common/pressureproperties.hh> +#include "linearsolverproperties.hh" + +namespace Dumux +{ + +// forward declaration for the property definitions +template <class TypeTag> class AMGBackend; + +namespace Properties +{ +//! the PDELab finite element map used for the gridfunctionspace +NEW_PROP_TAG(AMGLocalFemMap); + +//! box: use the (multi-)linear local FEM space associated with cubes by default +SET_PROP(BoxModel, AMGLocalFemMap) +{ + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + enum{dim = GridView::dimension}; + public: + enum{ + //! \brief The codimension that the degrees of freedom are attached to. + dof_codimension = GridView::dimension + }; +}; + +//! cell-centered: use the element-wise constant local FEM space by default +SET_PROP(CCModel, AMGLocalFemMap) +{ + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + enum{dim = GridView::dimension}; + public: + enum{ + //! \brief The codimension that the degrees of freedom are attached to. + dof_codimension = 0 + }; +}; + +//! decoupled models: use the element-wise constant local FEM space by default +SET_PROP(DecoupledModel, AMGLocalFemMap) +{ + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + enum{dim = GridView::dimension}; + public: + enum{ + //! \brief The codimension that the degrees of freedom are attached to. + dof_codimension = 0 + }; +}; +/* +//! set a property JacobianMatrix also for the decoupled models +SET_PROP(DecoupledModel, JacobianMatrix) +{ +public: +typedef typename GET_PROP_TYPE(TypeTag, PressureCoefficientMatrix) type; +}; +*/ + //! the type of the employed PDELab backend +NEW_PROP_TAG(AMGPDELabBackend); + +//! box: use the non-overlapping AMG backend +SET_PROP(BoxModel, AMGPDELabBackend) +{ + public: + //typedef Dune::PDELab::ISTLBackend_NOVLP_BCGS_AMG_SSOR<GridOperator> type; + typedef typename GET_PROP_TYPE(TypeTag, JacobianMatrix) JacobianMatrix; + enum { + numEq = JacobianMatrix::block_type::rows, + isNonOverlapping = true + }; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef Dune::BCRSMatrix<Dune::FieldMatrix<Scalar,numEq,numEq> > MType; + typedef Dune::BlockVector<Dune::FieldVector<Scalar,numEq> > VType; +#if HAVE_MPI + typedef Dune::OwnerOverlapCopyCommunication<bigunsignedint<96>,int> Comm; + typedef Dune::NonoverlappingSchwarzOperator<MType,VType, VType> LinearOperator; + typedef Dune::NonoverlappingSchwarzScalarProduct<VType,Comm> ScalarProduct; + typedef Dune::NonoverlappingBlockPreconditioner<Comm,Dune::SeqSSOR<MType,VType, VType> > Smoother; +#else + typedef Dune::Amg::SequentialInformation Comm; + typedef Dune::MatrixAdapter<MType,VType,VType> LinearOperator; + typedef Dune::SeqScalarProduct<VType> ScalarProduct; + typedef Dune::SeqSSOR<MType,VType, VType> Smoother; +#endif +}; + +//! cell-centered: use the overlapping PDELab AMG backend +SET_PROP(CCModel, AMGPDELabBackend) +{ + public: + typedef typename GET_PROP_TYPE(TypeTag, JacobianMatrix) JacobianMatrix; + enum { + numEq = JacobianMatrix::block_type::rows, + isNonOverlapping = true + }; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef Dune::BCRSMatrix<Dune::FieldMatrix<Scalar,numEq,numEq> > MType; + typedef Dune::BlockVector<Dune::FieldVector<Scalar,numEq> > VType; +#if HAVE_MPI + typedef Dune::OwnerOverlapCopyCommunication<bigunsignedint<96>,int> Comm; + typedef Dune::OverlappingSchwarzOperator<MType,VType, VType> LinearOperator; + typedef Dune::OverlappingSchwarzScalarProduct<VType,Comm> ScalarProduct; + typedef Dune::BlockPreconditioner<Comm,Dune::SeqSSOR<MType,VType, VType> > Smoother; +#else + typedef Dune::Amg::SequentialInformation Comm; + typedef Dune::MatrixAdapter<MType,VType,VType> LinearOperator; + typedef Dune::SeqScalarProduct<VType> ScalarProduct; + typedef Dune::SeqSSOR<MType,VType, VType> Smoother; +#endif +}; + +//! decoupled model: use the overlapping PDELab AMG backend +SET_PROP(DecoupledModel, AMGPDELabBackend) +{ + typedef typename Dumux::AMGBackend<TypeTag>::GridOperator GridOperator; + public: + typedef typename GET_PROP_TYPE(TypeTag, JacobianMatrix) JacobianMatrix; + enum { + numEq = JacobianMatrix::block_type::rows, + isNonOverlapping = false + }; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef Dune::BCRSMatrix<Dune::FieldMatrix<Scalar,numEq,numEq> > MType; + typedef Dune::BlockVector<Dune::FieldVector<Scalar,numEq> > VType; +#if HAVE_MPI + typedef Dune::OwnerOverlapCopyCommunication<bigunsignedint<96>,int> Comm; + typedef Dune::OverlappingSchwarzOperator<MType,VType, VType> LinearOperator; + typedef Dune::OverlappingSchwarzScalarProduct<VType,Comm> ScalarProduct; + typedef Dune::BlockPreconditioner<Comm,Dune::SeqSSOR<MType,VType, VType> > Smoother; +#else + typedef Dune::Amg::SequentialInformation Comm; + typedef Dune::MatrixAdapter<MType,VType,VType> LinearOperator; + typedef Dune::SeqScalarProduct<VType> ScalarProduct; + typedef Dune::SeqSSOR<MType,VType, VType> Smoother; +#endif +}; + +//! box: reset the type of solution vector to be PDELab conforming +SET_PROP(BoxModel, SolutionVector) +{ + typedef typename GET_PROP_TYPE(TypeTag, JacobianMatrix) JacobianMatrix; + enum { numEq = JacobianMatrix::block_type::rows}; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + public: + typedef Dune::BlockVector<Dune::FieldVector<Scalar,numEq> > type; +}; + +//! cell-centered: reset the type of solution vector to be PDELab conforming +SET_PROP(CCModel, SolutionVector) +{ + typedef typename GET_PROP_TYPE(TypeTag, JacobianMatrix) JacobianMatrix; + enum { numEq = JacobianMatrix::block_type::rows}; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + public: + typedef Dune::BlockVector<Dune::FieldVector<Scalar,numEq> > type; +}; + + +//! decoupled model: reset the type of solution vector to be PDELab conforming +SET_PROP(DecoupledModel, PressureSolutionVector) +{ + typedef typename GET_PROP_TYPE(TypeTag, JacobianMatrix) JacobianMatrix; + enum { numEq = JacobianMatrix::block_type::rows}; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + public: + typedef Dune::BlockVector<Dune::FieldVector<Scalar,numEq> > type; +}; + +//! decoupled model: reset the type of solution vector to be PDELab conforming +SET_PROP(DecoupledModel, PressureRHSVector) +{ + typedef typename GET_PROP_TYPE(TypeTag, JacobianMatrix) JacobianMatrix; + enum { numEq = JacobianMatrix::block_type::rows}; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + public: + typedef Dune::BlockVector<Dune::FieldVector<Scalar,numEq> > type; +}; + +} // namespace Properties +} // namespace Dumux +#endif diff --git a/test/decoupled/2p/test_impesproblem.hh b/test/decoupled/2p/test_impesproblem.hh index 5cc6eda7116209ee749a8ba5551ef2aa905a3ac3..672cbd279c2ae68c731f8f9b5c600575eac0f24e 100644 --- a/test/decoupled/2p/test_impesproblem.hh +++ b/test/decoupled/2p/test_impesproblem.hh @@ -49,14 +49,7 @@ #include<dumux/decoupled/2p/transport/fv/evalcflfluxcoats.hh> -#if HAVE_DUNE_PDELAB - -// Check if DUNE-PDELab has been patched for our needs. -#ifdef DUNE_PDELAB_IS_PATCHED_FOR_DUMUX #include <dumux/linear/amgbackend.hh> -#endif // DUNE_PDELAB_IS_PATCHED_FOR_DUMUX - -#endif // HAVE_DUNE_PDELAB namespace Dumux { @@ -134,7 +127,6 @@ SET_TYPE_PROP(IMPESTestProblem, EvalCflFluxFunction, Dumux::EvalCflFluxCoats<Typ SET_SCALAR_PROP(IMPESTestProblem, ImpetCFLFactor, 0.95); -#ifdef DUNE_PDELAB_IS_PATCHED_FOR_DUMUX // set up an additional problem where the AMG backend is used NEW_TYPE_TAG(IMPESTestProblemWithAMG, INHERITS_FROM(IMPESTestProblem)); // use the AMG backend for the corresponding test @@ -143,7 +135,6 @@ SET_TYPE_PROP(IMPESTestProblemWithAMG, LinearSolver, Dumux::AMGBackend<TypeTag>) SET_TYPE_PROP(IMPESTestProblemWithAMG, Grid, Dune::YaspGrid<2>); // set the GridCreator property SET_TYPE_PROP(IMPESTestProblemWithAMG, GridCreator, Dumux::DgfGridCreator<TypeTag>); -#endif } /*! diff --git a/test/geomechanics/el1p2c/el1p2cproblem.hh b/test/geomechanics/el1p2c/el1p2cproblem.hh index 502b7c52cf2e1c441664e01c55f5dac81a03aaa8..6cbb57fc44518655edcf50f75ccd6a0a2bdd2b2e 100644 --- a/test/geomechanics/el1p2c/el1p2cproblem.hh +++ b/test/geomechanics/el1p2c/el1p2cproblem.hh @@ -86,14 +86,8 @@ namespace Dumux SET_BOOL_PROP(El1P2CProblem, ImplicitWithStabilization, true); // Check if DUNE-PDELab is available and has been patched for our needs. -#if HAVE_DUNE_PDELAB && DUNE_PDELAB_IS_PATCHED_FOR_DUMUX SET_TYPE_PROP(El1P2CProblem, LinearSolver, Dumux::AMGBackend<TypeTag> ); // #endif // DUNE_PDELAB_IS_PATCHED_FOR_DUMUX -#elif HAVE_SUPERLU - SET_TYPE_PROP(El1P2CProblem, LinearSolver, Dumux::SuperLUBackend<TypeTag> ); -#else -#warning Neither DUNE_PDELAB nor SuperLU detected, you are not able to run this test! -#endif // HAVE_DUNE_PDELAB } diff --git a/test/implicit/1p/1ptestproblem.hh b/test/implicit/1p/1ptestproblem.hh index 186c8da7ec76fd743653ac80fc30319521d8f610..8a1488f5a0c4e90f19c8a5bb19dcd91660fdfa81 100644 --- a/test/implicit/1p/1ptestproblem.hh +++ b/test/implicit/1p/1ptestproblem.hh @@ -40,14 +40,7 @@ #include <dumux/material/components/simpleh2o.hh> #include <dumux/material/fluidsystems/liquidphase.hh> -#if HAVE_DUNE_PDELAB - -// Check if DUNE-PDELab has been patched for our needs. -#ifdef DUNE_PDELAB_IS_PATCHED_FOR_DUMUX #include <dumux/linear/amgbackend.hh> -#endif // DUNE_PDELAB_IS_PATCHED_FOR_DUMUX - -#endif // HAVE_DUNE_PDELAB #include "1ptestspatialparams.hh" @@ -93,13 +86,11 @@ SET_INT_PROP(OnePTestProblem, LinearSolverVerbosity, 0); SET_INT_PROP(OnePTestProblem, LinearSolverPreconditionerIterations, 1); SET_SCALAR_PROP(OnePTestProblem, LinearSolverPreconditionerRelaxation, 1.0); -#ifdef DUNE_PDELAB_IS_PATCHED_FOR_DUMUX NEW_TYPE_TAG(OnePTestBoxProblemWithAMG, INHERITS_FROM(OnePTestBoxProblem)); NEW_TYPE_TAG(OnePTestCCProblemWithAMG, INHERITS_FROM(OnePTestCCProblem)); // Solver settings for the tests using AMG SET_TYPE_PROP(OnePTestBoxProblemWithAMG, LinearSolver, Dumux::AMGBackend<TypeTag> ); SET_TYPE_PROP(OnePTestCCProblemWithAMG, LinearSolver, Dumux::AMGBackend<TypeTag> ); -#endif // Enable gravity SET_BOOL_PROP(OnePTestProblem, ProblemEnableGravity, true); diff --git a/test/implicit/1p/test_box1pwithamg.cc b/test/implicit/1p/test_box1pwithamg.cc index f05fa5fb06f2957732729086fc26a28935375e49..8ee1b7a01137908b55ddc6a10594ddf0ca4c0a68 100644 --- a/test/implicit/1p/test_box1pwithamg.cc +++ b/test/implicit/1p/test_box1pwithamg.cc @@ -23,10 +23,8 @@ */ #include "config.h" -#if HAVE_DUNE_PDELAB // Check if DUNE-PDELab has been patched for our needs. -#ifdef DUNE_PDELAB_IS_PATCHED_FOR_DUMUX #include "1ptestproblem.hh" #include <dumux/common/start.hh> @@ -68,30 +66,3 @@ int main(int argc, char** argv) typedef TTAG(OnePTestBoxProblemWithAMG) ProblemTypeTag; return Dumux::start<ProblemTypeTag>(argc, argv, usage); } -#else // DUNE_PDELAB_IS_PATCHED_FOR_DUMUX - -#warning You need to have a patched dune-pdelab to run this test, see ../../../patches/README for details. - -#include <iostream> - -int main() -{ - std::cerr << "You need to have a patched dune-pdelab to run this test, " - "see ../../../patches/README for details." << std::endl; - return 77; -} - -#endif // DUNE_PDELAB_IS_PATCHED_FOR_DUMUX - -#else // HAVE_DUNE_PDELAB - -#warning You need to have dune-pdelab installed and patched to run this test. - -#include <iostream> - -int main() -{ - std::cerr << "You need to have dune-pdelab installed and patched to run this test.\n"; - return 77; -} -#endif // HAVE_DUNE_PDELAB diff --git a/test/implicit/1p/test_cc1pwithamg.cc b/test/implicit/1p/test_cc1pwithamg.cc index e3c30bc09198a3e9b934e3a8c38b4242d7af3ba3..30494c06b3cffe83e1579391eb2e179c0265ece2 100644 --- a/test/implicit/1p/test_cc1pwithamg.cc +++ b/test/implicit/1p/test_cc1pwithamg.cc @@ -23,10 +23,6 @@ */ #include "config.h" -#if HAVE_DUNE_PDELAB - -// Check if DUNE-PDELab has been patched for our needs. -#ifdef DUNE_PDELAB_IS_PATCHED_FOR_DUMUX #include "1ptestproblem.hh" #include <dumux/common/start.hh> @@ -68,30 +64,4 @@ int main(int argc, char** argv) typedef TTAG(OnePTestCCProblemWithAMG) ProblemTypeTag; return Dumux::start<ProblemTypeTag>(argc, argv, usage); } -#else // DUNE_PDELAB_IS_PATCHED_FOR_DUMUX - -#warning You need to have a patched dune-pdelab to run this test, see ../../../patches/README for details. - -#include <iostream> - -int main() -{ - std::cerr << "You need to have a patched dune-pdelab to run this test, " - "see ../../../patches/README for details." << std::endl; - return 77; -} -#endif // DUNE_PDELAB_IS_PATCHED_FOR_DUMUX - -#else // HAVE_DUNE_PDELAB - -#warning You need to have dune-pdelab installed and patched to run this test. - -#include <iostream> - -int main() -{ - std::cerr << "You need to have dune-pdelab installed and patched to run this test.\n"; - return 77; -} -#endif // HAVE_DUNE_PDELAB