MFEM  v4.3.0
Finite element discretization library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
lor.hpp
Go to the documentation of this file.
1 // Copyright (c) 2010-2021, 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_LOR
13 #define MFEM_LOR
14 
15 #include "bilinearform.hpp"
16 
17 namespace mfem
18 {
19 
20 /// @brief Abstract base class for LORDiscretization and ParLORDiscretization
21 /// classes, which construct low-order refined versions of bilinear forms.
22 class LORBase
23 {
24 private:
25  using GetIntegratorsFn = Array<BilinearFormIntegrator*> *(BilinearForm::*)();
26  using GetMarkersFn = Array<Array<int>*> *(BilinearForm::*)();
27  using AddIntegratorFn = void (BilinearForm::*)(BilinearFormIntegrator*);
28  using AddIntegratorMarkersFn =
30 
31  IntegrationRules irs;
32  const IntegrationRule *ir_el, *ir_face;
33  std::map<BilinearFormIntegrator*, const IntegrationRule*> ir_map;
34 
35  /// Adds all the integrators from the BilinearForm @a a_from to @a a_to. If
36  /// the mesh consists of tensor product elements, temporarily changes the
37  /// integration rules of the integrators to use collocated quadrature for
38  /// better conditioning of the %LOR system.
39  void AddIntegrators(BilinearForm &a_from,
40  BilinearForm &a_to,
41  GetIntegratorsFn get_integrators,
42  AddIntegratorFn add_integrator,
43  const IntegrationRule *ir);
44 
45  /// Adds all the integrators from the BilinearForm @a a_from to @a a_to,
46  /// using the same marker lists (e.g. for integrators only applied to
47  /// certain boundary attributes). @sa LORBase::AddIntegrators
48  void AddIntegratorsAndMarkers(BilinearForm &a_from,
49  BilinearForm &a_to,
50  GetIntegratorsFn get_integrators,
51  GetMarkersFn get_markers,
52  AddIntegratorMarkersFn add_integrator,
53  const IntegrationRule *ir);
54 
55  /// Resets the integration rules of the integrators of @a a to their original
56  /// values (after temporarily changing them for %LOR assembly).
57  void ResetIntegrationRules(GetIntegratorsFn get_integrators);
58 
59  static inline int absdof(int i) { return i < 0 ? -1-i : i; }
60 
61 protected:
62  enum FESpaceType { H1, ND, RT, L2, INVALID };
63 
70  mutable Array<int> perm;
71  bool nonconforming = false;
72 
73  /// Constructs the local DOF (ldof) permutation. In parallel this is used as
74  /// an intermediate step in computing the DOF permutation (see
75  /// ConstructDofPermutation and GetDofPermutation).
76  void ConstructLocalDofPermutation(Array<int> &perm_) const;
77 
78  /// Construct the permutation that maps %LOR DOFs to high-order DOFs. See
79  /// GetDofPermutation.
80  void ConstructDofPermutation() const;
81 
82  /// Sets up the prolongation and restriction operators required for
83  /// nonconforming spaces.
84  void SetupNonconforming();
85 
86  /// Returns the type of finite element space: H1, ND, RT or L2.
88 
89  /// Returns the order of the %LOR space. 1 for H1 or ND, 0 for L2 or RT.
90  int GetLOROrder() const;
91 
92  LORBase(FiniteElementSpace &fes_ho_);
93 
94 public:
95  /// Returns the assembled %LOR system.
96  const OperatorHandle &GetAssembledSystem() const;
97 
98  /// Assembles the %LOR system.
99  void AssembleSystem(BilinearForm &a_ho, const Array<int> &ess_dofs);
100 
101  /// @brief Returns the permutation that maps %LOR DOFs to high-order DOFs.
102  ///
103  /// This permutation is constructed the first time it is requested, and then
104  /// is cached. For H1 and L2 finite element spaces (or for nonconforming
105  /// spaces) this is the identity. In these cases, RequiresDofPermutation will
106  /// return false. However, if the DOF permutation is requested, an identity
107  /// permutation will be built and returned.
108  ///
109  /// For vector finite element spaces (ND and RT), the DOF permutation is
110  /// nontrivial. Returns an array @a perm such that, given an index @a i of a
111  /// %LOR dof, @a perm[i] is the index of the corresponding HO dof.
112  const Array<int> &GetDofPermutation() const;
113 
114  /// Returns true if the %LOR spaces requires a DOF permutation (if the
115  /// corresponding %LOR and HO DOFs are numbered differently), false
116  /// otherwise. Note: permutations are not required in the case of
117  /// nonconforming spaces, since the DOF numbering is incorporated into the
118  /// prolongation operators.
119  bool RequiresDofPermutation() const;
120 
121  /// Returns the low-order refined finite element space.
122  FiniteElementSpace &GetFESpace() const { return *fes; }
123 
124  ~LORBase();
125 };
126 
127 /// Create and assemble a low-order refined version of a BilinearForm.
129 {
130 public:
131  /// @brief Construct the low-order refined version of @a a_ho using the given
132  /// list of essential DOFs.
133  ///
134  /// The mesh is refined using the refinement type specified by @a ref_type
135  /// (see Mesh::MakeRefined).
136  LORDiscretization(BilinearForm &a_ho, const Array<int> &ess_tdof_list,
137  int ref_type=BasisType::GaussLobatto);
138 
139  /// @brief Construct a low-order refined version of the FiniteElementSpace @a
140  /// fes_ho.
141  ///
142  /// The mesh is refined using the refinement type specified by @a ref_type
143  /// (see Mesh::MakeRefined).
145  int ref_type=BasisType::GaussLobatto);
146 
147  /// Return the assembled %LOR operator as a SparseMatrix.
149 };
150 
151 #ifdef MFEM_USE_MPI
152 
153 /// Create and assemble a low-order refined version of a ParBilinearForm.
155 {
156 public:
157  /// @brief Construct the low-order refined version of @a a_ho using the given
158  /// list of essential DOFs.
159  ///
160  /// The mesh is refined using the refinement type specified by @a ref_type
161  /// (see ParMesh::MakeRefined).
162  ParLORDiscretization(ParBilinearForm &a_ho, const Array<int> &ess_tdof_list,
163  int ref_type=BasisType::GaussLobatto);
164 
165  /// @brief Construct a low-order refined version of the ParFiniteElementSpace
166  /// @a pfes_ho.
167  ///
168  /// The mesh is refined using the refinement type specified by @a ref_type
169  /// (see ParMesh::MakeRefined).
171  int ref_type=BasisType::GaussLobatto);
172 
173  /// Return the assembled %LOR operator as a HypreParMatrix.
175 
176  /// Return the %LOR ParFiniteElementSpace.
178 };
179 
180 #endif
181 
182 /// @brief Represents a solver of type @a SolverType created using the low-order
183 /// refined version of the given BilinearForm or ParBilinearForm.
184 ///
185 /// @note To achieve good solver performance, the high-order finite element
186 /// space should use BasisType::GaussLobatto for H1 discretizations, and basis
187 /// pair (BasisType::GaussLobatto, BasisType::IntegratedGLL) for Nedelec and
188 /// Raviart-Thomas elements.
189 template <typename SolverType>
190 class LORSolver : public Solver
191 {
192 protected:
194  bool own_lor = true;
195  bool use_permutation = true;
196  SolverType solver;
197  mutable Vector px, py;
198 public:
199  /// @brief Create a solver of type @a SolverType, formed using the assembled
200  /// SparseMatrix of the %LOR version of @a a_ho. @see LORDiscretization
201  LORSolver(BilinearForm &a_ho, const Array<int> &ess_tdof_list,
202  int ref_type=BasisType::GaussLobatto)
203  {
204  lor = new LORDiscretization(a_ho, ess_tdof_list, ref_type);
206  }
207 
208 #ifdef MFEM_USE_MPI
209  /// @brief Create a solver of type @a SolverType, formed using the assembled
210  /// HypreParMatrix of the %LOR version of @a a_ho. @see ParLORDiscretization
211  LORSolver(ParBilinearForm &a_ho, const Array<int> &ess_tdof_list,
212  int ref_type=BasisType::GaussLobatto)
213  {
214  lor = new ParLORDiscretization(a_ho, ess_tdof_list, ref_type);
216  }
217 #endif
218 
219  /// @brief Create a solver of type @a SolverType using Operator @a op and
220  /// arguments @a args.
221  ///
222  /// The object @a lor_ will be used for DOF permutations.
223  template <typename... Args>
224  LORSolver(const Operator &op, LORBase &lor_, Args&&... args) : solver(args...)
225  {
226  lor = &lor_;
227  own_lor = false;
228  SetOperator(op);
229  }
230 
231  /// @brief Create a solver of type @a SolverType using the assembled %LOR
232  /// operator represented by @a lor_.
233  ///
234  /// The given @a args will be used as arguments to the solver constructor.
235  template <typename... Args>
236  LORSolver(LORBase &lor_, Args&&... args)
237  : LORSolver(*lor_.GetAssembledSystem(), lor_, args...) { }
238 
239  void SetOperator(const Operator &op)
240  {
241  solver.SetOperator(op);
242  width = solver.Width();
243  height = solver.Height();
244  }
245 
246  void Mult(const Vector &x, Vector &y) const
247  {
249  {
250  const Array<int> &p = lor->GetDofPermutation();
251  px.SetSize(x.Size());
252  py.SetSize(y.Size());
253  for (int i=0; i<x.Size(); ++i)
254  { px[i] = p[i] < 0 ? -x[-1-p[i]] : x[p[i]]; }
255 
256  solver.Mult(px, py);
257 
258  for (int i=0; i<y.Size(); ++i)
259  {
260  int pi = p[i];
261  int s = pi < 0 ? -1 : 1;
262  y[pi < 0 ? -1-pi : pi] = s*py[i];
263  }
264  }
265  else
266  {
267  solver.Mult(x, y);
268  }
269  }
270 
271  /// @brief Enable or disable the DOF permutation (enabled by default).
272  ///
273  /// The corresponding %LOR and high-order DOFs may not have the same
274  /// numbering (for example, when using ND or RT spaces), and so a permutation
275  /// is required when applying the %LOR solver as a preconditioner for the
276  /// high-order problem. This permutation can be disabled (for example, in
277  /// order to precondition the low-order problem directly).
278  void UsePermutation(bool use_permutation_)
279  {
280  use_permutation = use_permutation_;
281  }
282 
283  /// Access the underlying solver.
284  SolverType &GetSolver() { return solver; }
285 
286  /// Access the underlying solver.
287  const SolverType &GetSolver() const { return solver; }
288 
289  ~LORSolver() { if (own_lor) { delete lor; } }
290 };
291 
292 } // namespace mfem
293 
294 #endif
Abstract base class for LORDiscretization and ParLORDiscretization classes, which construct low-order...
Definition: lor.hpp:22
LORDiscretization(BilinearForm &a_ho, const Array< int > &ess_tdof_list, int ref_type=BasisType::GaussLobatto)
Construct the low-order refined version of a_ho using the given list of essential DOFs...
Definition: lor.cpp:371
const OperatorHandle & GetAssembledSystem() const
Returns the assembled LOR system.
Definition: lor.cpp:235
Create and assemble a low-order refined version of a ParBilinearForm.
Definition: lor.hpp:154
Class for an integration rule - an Array of IntegrationPoint.
Definition: intrules.hpp:90
FESpaceType GetFESpaceType() const
Returns the type of finite element space: H1, ND, RT or L2.
Definition: lor.cpp:60
LORBase * lor
Definition: lor.hpp:193
int GetLOROrder() const
Returns the order of the LOR space. 1 for H1 or ND, 0 for L2 or RT.
Definition: lor.cpp:71
void SetSize(int s)
Resize the vector to size s.
Definition: vector.hpp:513
Pointer to an Operator of a specified type.
Definition: handle.hpp:33
FiniteElementSpace & fes_ho
Definition: lor.hpp:64
Container class for integration rules.
Definition: intrules.hpp:311
int Size() const
Returns the size of the vector.
Definition: vector.hpp:190
const Array< int > & GetDofPermutation() const
Returns the permutation that maps LOR DOFs to high-order DOFs.
Definition: lor.cpp:223
Vector px
Definition: lor.hpp:197
Abstract parallel finite element space.
Definition: pfespace.hpp:28
HypreParMatrix & GetAssembledMatrix() const
Return the assembled LOR operator as a HypreParMatrix.
Definition: lor.cpp:442
void UsePermutation(bool use_permutation_)
Enable or disable the DOF permutation (enabled by default).
Definition: lor.hpp:278
Create and assemble a low-order refined version of a BilinearForm.
Definition: lor.hpp:128
LORSolver(ParBilinearForm &a_ho, const Array< int > &ess_tdof_list, int ref_type=BasisType::GaussLobatto)
Create a solver of type SolverType, formed using the assembled HypreParMatrix of the LOR version of a...
Definition: lor.hpp:211
FiniteElementSpace * fes
Definition: lor.hpp:67
Data type sparse matrix.
Definition: sparsemat.hpp:41
Mesh * mesh
Definition: lor.hpp:65
FiniteElementSpace & GetFESpace() const
Returns the low-order refined finite element space.
Definition: lor.hpp:122
SolverType solver
Definition: lor.hpp:196
Array< int > perm
Definition: lor.hpp:70
void SetupNonconforming()
Definition: lor.cpp:281
void SetOperator(const Operator &op)
Set/update the solver for the given operator.
Definition: lor.hpp:239
LORSolver(LORBase &lor_, Args &&...args)
Create a solver of type SolverType using the assembled LOR operator represented by lor_...
Definition: lor.hpp:236
BilinearForm * a
Definition: lor.hpp:68
bool use_permutation
Definition: lor.hpp:195
SolverType & GetSolver()
Access the underlying solver.
Definition: lor.hpp:284
Abstract base class BilinearFormIntegrator.
Definition: bilininteg.hpp:34
bool own_lor
Definition: lor.hpp:194
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition: fespace.hpp:87
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
Definition: fe_coll.hpp:26
LORSolver(const Operator &op, LORBase &lor_, Args &&...args)
Create a solver of type SolverType using Operator op and arguments args.
Definition: lor.hpp:224
const SolverType & GetSolver() const
Access the underlying solver.
Definition: lor.hpp:287
void Mult(const Vector &x, Vector &y) const
Operator application: y=A(x).
Definition: lor.hpp:246
void ConstructDofPermutation() const
Definition: lor.cpp:181
int height
Dimension of the output / number of rows in the matrix.
Definition: operator.hpp:27
A &quot;square matrix&quot; operator for the associated FE space and BLFIntegrators The sum of all the BLFInteg...
ParFiniteElementSpace & GetParFESpace() const
Return the LOR ParFiniteElementSpace.
Definition: lor.cpp:448
FiniteElementCollection * fec
Definition: lor.hpp:66
ParLORDiscretization(ParBilinearForm &a_ho, const Array< int > &ess_tdof_list, int ref_type=BasisType::GaussLobatto)
Construct the low-order refined version of a_ho using the given list of essential DOFs...
Definition: lor.cpp:410
void AssembleSystem(BilinearForm &a_ho, const Array< int > &ess_dofs)
Assembles the LOR system.
Definition: lor.cpp:241
void ConstructLocalDofPermutation(Array< int > &perm_) const
Definition: lor.cpp:77
LORSolver(BilinearForm &a_ho, const Array< int > &ess_tdof_list, int ref_type=BasisType::GaussLobatto)
Create a solver of type SolverType, formed using the assembled SparseMatrix of the LOR version of a_h...
Definition: lor.hpp:201
Class for parallel bilinear form.
LORBase(FiniteElementSpace &fes_ho_)
Definition: lor.cpp:343
bool RequiresDofPermutation() const
Definition: lor.cpp:229
SparseMatrix & GetAssembledMatrix() const
Return the assembled LOR operator as a SparseMatrix.
Definition: lor.cpp:402
Vector data type.
Definition: vector.hpp:60
Vector py
Definition: lor.hpp:197
RefCoord s[3]
Base class for solvers.
Definition: operator.hpp:648
Abstract operator.
Definition: operator.hpp:24
Wrapper for hypre&#39;s ParCSR matrix class.
Definition: hypre.hpp:277
OperatorHandle A
Definition: lor.hpp:69
int width
Dimension of the input / number of columns in the matrix.
Definition: operator.hpp:28
Represents a solver of type SolverType created using the low-order refined version of the given Bilin...
Definition: lor.hpp:190
bool nonconforming
Definition: lor.hpp:71