MFEM v4.9.0
Finite element discretization library
Loading...
Searching...
No Matches
div_free_solver.hpp
Go to the documentation of this file.
1// Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11
12#ifndef MFEM_DIVFREE_SOLVER_HPP
13#define MFEM_DIVFREE_SOLVER_HPP
14
15#include "darcy_solver.hpp"
16#include <memory>
17
18namespace mfem::blocksolvers
19{
20
21/// Parameters for the divergence free solver
23{
24 /** There are three components in the solver: a particular solution
25 satisfying the divergence constraint, the remaining div-free component of
26 the flux, and the pressure. When coupled_solve == false, the three
27 components will be solved one by one in the aforementioned order.
28 Otherwise, they will be solved at the same time. */
29 bool coupled_solve = false;
30 bool verbose = false;
33};
34
35/// Data for the divergence free solver
36struct DFSData
37{
38 using UniqueOperatorPtr = std::unique_ptr<OperatorPtr>;
39 using UniqueHypreParMatrix = std::unique_ptr<HypreParMatrix>;
40
41 std::vector<OperatorPtr> agg_hdivdof; // agglomerates to H(div) dofs table
42 std::vector<OperatorPtr> agg_l2dof; // agglomerates to L2 dofs table
43 std::vector<UniqueOperatorPtr> P_hdiv; // Interpolation matrix for H(div) space
44 std::vector<UniqueOperatorPtr> P_l2; // Interpolation matrix for L2 space
45 std::vector<UniqueOperatorPtr> P_hcurl; // Interpolation for kernel space of div
46 std::vector<OperatorPtr> Q_l2; // Q_l2[l] = (W_{l+1})^{-1} P_l2[l]^T W_l
47 Array<int> coarsest_ess_hdivdofs; // coarsest level essential H(div) dofs
48 std::vector<OperatorPtr> C; // discrete curl: ND -> RT, map to Null(B)
49 std::vector<UniqueHypreParMatrix> Ae;
51};
52
53/// Finite element spaces concerning divergence free solvers
54/// The main usage of this class is to collect data needed for the solver.
56{
57 RT_FECollection hdiv_fec_;
58 L2_FECollection l2_fec_;
59 std::unique_ptr<FiniteElementCollection> hcurl_fec_;
60 L2_FECollection l2_0_fec_;
61
62 std::unique_ptr<ParFiniteElementSpace> coarse_hdiv_fes_;
63 std::unique_ptr<ParFiniteElementSpace> coarse_l2_fes_;
64 std::unique_ptr<ParFiniteElementSpace> coarse_hcurl_fes_;
65 std::unique_ptr<ParFiniteElementSpace> l2_0_fes_;
66
67 std::unique_ptr<ParFiniteElementSpace> hdiv_fes_;
68 std::unique_ptr<ParFiniteElementSpace> l2_fes_;
69 std::unique_ptr<ParFiniteElementSpace> hcurl_fes_;
70
71 std::vector<SparseMatrix> el_l2dof_;
72 const Array<int>& ess_bdr_attr_;
73 Array<int> all_bdr_attr_;
74
75 int level_;
76 DFSData data_;
77
78 void MakeDofRelationTables(int level);
79 void DataFinalize();
80public:
81 DFSSpaces(int order, int num_refine, ParMesh *mesh,
82 const Array<int>& ess_attr, const DFSParameters& param);
83
84 /** This should be called each time when the mesh (where the FE spaces are
85 defined) is refined. The spaces will be updated, and the prolongation for
86 the spaces and other data needed for the div-free solver are stored. */
87 void CollectDFSData();
88
89 const DFSData& GetDFSData() const { return data_; }
90 ParFiniteElementSpace* GetHdivFES() const { return hdiv_fes_.get(); }
91 ParFiniteElementSpace* GetL2FES() const { return l2_fes_.get(); }
92};
93
94/// Solvers for DFS
95/// Solver for B * B^T
96/// Compute the product B * B^T and solve it with CG preconditioned by BoomerAMG
97class BBTSolver : public Solver
98{
99 OperatorPtr BBT_, BBT_prec_;
100 CGSolver BBT_solver_;
101public:
103 void Mult(const Vector &x, Vector &y) const override { BBT_solver_.Mult(x, y); }
104 void SetOperator(const Operator &op) override { }
105};
106
107/// Block diagonal solver for symmetric A, each block is inverted by direct solver
109{
110public:
112 : DirectSubBlockSolver(A, block_dof) { }
113 void MultTranspose(const Vector &x, Vector &y) const override { Mult(x, y); }
114};
115
116/// non-overlapping additive Schwarz smoother for saddle point systems
117/// [ M B^T ]
118/// [ B 0 ]
120{
121 const SparseMatrix &agg_hdivdof_, &agg_l2dof_;
122 OperatorPtr coarse_l2_projector_;
123
124 Array<int> offsets_;
125 mutable Array<int> offsets_loc_, hdivdofs_loc_, l2dofs_loc_;
126 std::vector<OperatorPtr> solvers_loc_;
127public:
128 /** SaddleSchwarzSmoother solves local saddle point problems defined on a
129 list of non-overlapping aggregates (of elements).
130 @param M the [1,1] block of the saddle point system
131 @param B the [2,1] block of the saddle point system
132 @param agg_hdivdof aggregate to H(div) dofs relation table (boolean matrix)
133 @param agg_l2dof aggregate to L2 dofs relation table (boolean matrix)
134 @param P_l2 prolongation matrix of the discrete L2 space
135 @param Q_l2 projection matrix of the discrete L2 space:
136 Q_l2 := (P_l2 W P_l2)^{-1} * P_l2 * W,
137 where W is the mass matrix of the discrete L2 space. */
139 const HypreParMatrix& B,
140 const SparseMatrix& agg_hdivdof,
141 const SparseMatrix& agg_l2dof,
142 const HypreParMatrix& P_l2,
143 const ProductOperator& Q_l2);
144 void Mult(const Vector &x, Vector &y) const override;
145 void MultTranspose(const Vector &x, Vector &y) const override { Mult(x, y); }
146 void SetOperator(const Operator &op) override { }
147};
148
149/// Solver for local problems in SaddleSchwarzSmoother
150class LocalSolver : public Solver
151{
152 DenseMatrix local_system_;
153 DenseMatrixInverse local_solver_;
154 const int offset_;
155public:
156 LocalSolver(const DenseMatrix &M, const DenseMatrix &B);
157 void Mult(const Vector &x, Vector &y) const override;
158 void SetOperator(const Operator &op) override { }
159};
160
161/// Divergence free solver.
162/** Divergence free solver.
163 The basic idea of the solver is to exploit a multilevel decomposition of
164 Raviart-Thomas space to find a particular solution satisfying the divergence
165 constraint, and then solve the remaining (divergence-free) component in the
166 kernel space of the discrete divergence operator.
167
168 For more details see
169 1. Vassilevski, Multilevel Block Factorization Preconditioners (Appendix F.3),
170 Springer, 2008.
171 2. Voronin, Lee, Neumuller, Sepulveda, Vassilevski, Space-time discretizations
172 using constrained first-order system least squares (CFOSLS).
173 J. Comput. Phys. 373: 863-876, 2018. */
175{
176 const DFSData& data_;
177 DFSParameters param_;
178 OperatorPtr BT_;
179 BBTSolver BBT_solver_;
180 std::vector<Array<int>> ops_offsets_;
181 std::vector<std::unique_ptr<BlockOperator>> ops_;
182 std::vector<std::unique_ptr<BlockOperator>> blk_Ps_;
183 std::vector<std::unique_ptr<Solver>> smoothers_;
184 OperatorPtr prec_, solver_;
185
186 void SolveParticular(const Vector& rhs, Vector& sol) const;
187 void SolveDivFree(const Vector& rhs, Vector& sol) const;
188 void SolvePotential(const Vector &rhs, Vector& sol) const;
189public:
191 const DFSData& data);
192 void Mult(const Vector &x, Vector &y) const override;
193 void SetOperator(const Operator &op) override { }
194 int GetNumIterations() const override;
195};
196
197} // namespace mfem::blocksolvers
198
199#endif // MFEM_DIVFREE_SOLVER_HPP
Conjugate gradient method.
Definition solvers.hpp:627
void Mult(const Vector &b, Vector &x) const override
Iterative solution of the linear system using the Conjugate Gradient method.
Definition solvers.cpp:869
Data type dense matrix using column-major storage.
Definition densemat.hpp:24
Block diagonal solver for A, each block is inverted by direct solver.
Definition solvers.hpp:1288
void Mult(const Vector &x, Vector &y) const override
Direct solution of the block diagonal linear system.
Definition solvers.cpp:3641
Wrapper for hypre's ParCSR matrix class.
Definition hypre.hpp:419
Arbitrary order "L2-conforming" discontinuous finite elements.
Definition fe_coll.hpp:350
Pointer to an Operator of a specified type.
Definition handle.hpp:34
Abstract operator.
Definition operator.hpp:25
Abstract parallel finite element space.
Definition pfespace.hpp:31
Class for parallel meshes.
Definition pmesh.hpp:34
General product operator: x -> (A*B)(x) = A(B(x)).
Definition operator.hpp:906
Arbitrary order H(div)-conforming Raviart-Thomas finite elements.
Definition fe_coll.hpp:407
Base class for solvers.
Definition operator.hpp:792
Data type sparse matrix.
Definition sparsemat.hpp:51
Vector data type.
Definition vector.hpp:82
void Mult(const Vector &x, Vector &y) const override
Operator application: y=A(x).
BBTSolver(const HypreParMatrix &B, IterSolveParameters param)
void SetOperator(const Operator &op) override
Set/update the solver for the given operator.
DFSSpaces(int order, int num_refine, ParMesh *mesh, const Array< int > &ess_attr, const DFSParameters &param)
const DFSData & GetDFSData() const
ParFiniteElementSpace * GetHdivFES() const
ParFiniteElementSpace * GetL2FES() const
Abstract solver class for Darcy's flow.
void SetOperator(const Operator &op) override
Set/update the solver for the given operator.
DivFreeSolver(const HypreParMatrix &M, const HypreParMatrix &B, const DFSData &data)
void Mult(const Vector &x, Vector &y) const override
Operator application: y=A(x).
Solver for local problems in SaddleSchwarzSmoother.
void Mult(const Vector &x, Vector &y) const override
Operator application: y=A(x).
void SetOperator(const Operator &op) override
Set/update the solver for the given operator.
LocalSolver(const DenseMatrix &M, const DenseMatrix &B)
void Mult(const Vector &x, Vector &y) const override
Operator application: y=A(x).
void SetOperator(const Operator &op) override
Set/update the solver for the given operator.
void MultTranspose(const Vector &x, Vector &y) const override
Action of the transpose operator: y=A^t(x). The default behavior in class Operator is to generate an ...
SaddleSchwarzSmoother(const HypreParMatrix &M, const HypreParMatrix &B, const SparseMatrix &agg_hdivdof, const SparseMatrix &agg_l2dof, const HypreParMatrix &P_l2, const ProductOperator &Q_l2)
Block diagonal solver for symmetric A, each block is inverted by direct solver.
void MultTranspose(const Vector &x, Vector &y) const override
Action of the transpose operator: y=A^t(x). The default behavior in class Operator is to generate an ...
SymDirectSubBlockSolver(const SparseMatrix &A, const SparseMatrix &block_dof)
Data for the divergence free solver.
std::vector< OperatorPtr > agg_l2dof
std::vector< UniqueOperatorPtr > P_l2
std::unique_ptr< OperatorPtr > UniqueOperatorPtr
std::vector< OperatorPtr > Q_l2
std::vector< UniqueHypreParMatrix > Ae
std::vector< UniqueOperatorPtr > P_hdiv
std::vector< UniqueOperatorPtr > P_hcurl
std::vector< OperatorPtr > agg_hdivdof
std::vector< OperatorPtr > C
std::unique_ptr< HypreParMatrix > UniqueHypreParMatrix
Parameters for the divergence free solver.