// Copyright (c) 2010-2023, Lawrence Livermore National Security, LLC. Produced // at the Lawrence Livermore National Laboratory. All Rights reserved. See files // LICENSE and NOTICE for details. LLNL-CODE-806117. // // This file is part of the MFEM library. For more information and source code // availability visit https://mfem.org. // // MFEM is free software; you can redistribute it and/or modify it under the // terms of the BSD-3 license. We welcome feedback and contributions, see file // CONTRIBUTING.md for details. #ifndef MFEM_MULTIGRID #define MFEM_MULTIGRID #include "fespacehierarchy.hpp" #include "bilinearform.hpp" #include "../linalg/operator.hpp" #include "../linalg/handle.hpp" namespace mfem { /// Abstract base class for Multigrid solvers class MultigridBase : public Solver { public: enum class CycleType { VCYCLE, WCYCLE }; protected: Array operators; Array smoothers; Array ownedOperators; Array ownedSmoothers; CycleType cycleType; int preSmoothingSteps; int postSmoothingSteps; mutable Array2D X, Y, R, Z; mutable int nrhs; public: /// Constructs an empty multigrid hierarchy MultigridBase(); /// Constructs a multigrid hierarchy from the given inputs /** Inputs include operators and smoothers on all levels, and ownership of the given operators and smoothers */ MultigridBase(const Array& operators_, const Array& smoothers_, const Array& ownedOperators_, const Array& ownedSmoothers_); /// Destructor virtual ~MultigridBase(); /// Adds a level to the multigrid operator hierarchy /** The ownership of the operators and solvers/smoothers may be transferred to the Multigrid by setting the according boolean variables */ void AddLevel(Operator* op, Solver* smoother, bool ownOperator, bool ownSmoother); /// Returns the number of levels int NumLevels() const { return operators.Size(); } /// Returns the index of the finest level int GetFinestLevelIndex() const { return NumLevels() - 1; } /// Returns operator at given level const Operator* GetOperatorAtLevel(int level) const { return operators[level]; } Operator* GetOperatorAtLevel(int level) { return operators[level]; } /// Returns operator at finest level const Operator* GetOperatorAtFinestLevel() const { return GetOperatorAtLevel(GetFinestLevelIndex()); } Operator* GetOperatorAtFinestLevel() { return GetOperatorAtLevel(GetFinestLevelIndex()); } /// Returns smoother at given level const Solver* GetSmootherAtLevel(int level) const { return smoothers[level]; } Solver* GetSmootherAtLevel(int level) { return smoothers[level]; } /// Set cycle type and number of pre- and post-smoothing steps used by Mult void SetCycleType(CycleType cycleType_, int preSmoothingSteps_, int postSmoothingSteps_); /// Application of the multigrid as a preconditioner virtual void Mult(const Vector& x, Vector& y) const override; virtual void ArrayMult(const Array& X_, Array& Y_) const override; /// Not supported for multigrid virtual void SetOperator(const Operator& op) override { MFEM_ABORT("SetOperator is not supported in Multigrid!"); } private: /// Application of a multigrid cycle at particular level void Cycle(int level) const; /// Application of a pre-/post-smoothing step at particular level void SmoothingStep(int level, bool zero, bool transpose) const; /// Allocate or destroy temporary storage void InitVectors() const; void EraseVectors() const; /// Returns prolongation operator at given level virtual const Operator* GetProlongationAtLevel(int level) const = 0; }; /// Multigrid solver class class Multigrid : public MultigridBase { protected: Array prolongations; Array ownedProlongations; public: /// Constructs an empty multigrid hierarchy Multigrid(); /// Constructs a multigrid hierarchy from the given inputs /** Inputs include operators and smoothers on all levels, prolongation operators that go from coarser to finer levels, and ownership of the given operators, smoothers, and prolongations */ Multigrid(const Array& operators_, const Array& smoothers_, const Array& prolongations_, const Array& ownedOperators_, const Array& ownedSmoothers_, const Array& ownedProlongations_); /// Destructor virtual ~Multigrid(); private: /// Returns prolongation operator at given level virtual const Operator* GetProlongationAtLevel(int level) const override { return prolongations[level]; } }; /// Geometric multigrid associated with a hierarchy of finite element spaces class GeometricMultigrid : public MultigridBase { protected: const FiniteElementSpaceHierarchy& fespaces; Array*> essentialTrueDofs; Array bfs; public: /** Construct an empty multigrid object for the given finite element space hierarchy @a fespaces_ */ GeometricMultigrid(const FiniteElementSpaceHierarchy& fespaces_); /// Destructor virtual ~GeometricMultigrid(); /** Form the linear system A X = B, corresponding to the operator on the finest level of the geometric multigrid hierarchy */ void FormFineLinearSystem(Vector& x, Vector& b, OperatorHandle& A, Vector& X, Vector& B); /// Recover the solution of a linear system formed with FormFineLinearSystem() void RecoverFineFEMSolution(const Vector& X, const Vector& b, Vector& x); private: /// Returns prolongation operator at given level virtual const Operator* GetProlongationAtLevel(int level) const override { return fespaces.GetProlongationAtLevel(level); } }; } // namespace mfem #endif