https://mooseframework.inl.gov
EquationSystem.h
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://mooseframework.inl.gov
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
10 #ifdef MOOSE_MFEM_ENABLED
11 
12 #pragma once
13 
14 #include "libmesh/ignore_warnings.h"
15 #include "mfem/miniapps/common/pfem_extras.hpp"
16 #include "libmesh/restore_warnings.h"
17 #include "MFEMIntegratedBC.h"
18 #include "MFEMEssentialBC.h"
19 #include "MFEMContainers.h"
20 #include "MFEMKernel.h"
22 #include "ScaleIntegrator.h"
23 #include "NLScaleIntegrator.h"
24 
25 namespace Moose::MFEM
26 {
27 class LinearSolverBase;
28 
33 class EquationSystem : public mfem::Operator
34 {
35 
36 public:
37  EquationSystem() = default;
38  ~EquationSystem() override;
39 
41  virtual void AddKernel(std::shared_ptr<MFEMKernel> kernel);
42  virtual void AddIntegratedBC(std::shared_ptr<MFEMIntegratedBC> kernel);
44  virtual void AddEssentialBC(std::shared_ptr<MFEMEssentialBC> bc);
45 
47  virtual void Init(GridFunctions & gridfunctions,
48  ComplexGridFunctions & cmplx_gridfunctions,
49  mfem::AssemblyLevel assembly_level);
54  void FormSystem(mfem::BlockVector & trueX, mfem::BlockVector & trueRHS);
56  void Mult(const mfem::Vector & u, mfem::Vector & residual) const override;
58  virtual void ComputeNonlinearResidual(const mfem::Vector & u, mfem::Vector & residual) const;
60  mfem::Operator & GetGradient(const mfem::Vector & u) const override;
61 
63  virtual void SetTrialVariablesFromTrueVectors(const mfem::BlockVector & trueX) const;
64 
66  void SetSolverRequiresGradient(bool requires_gradient)
67  {
68  _solver_requires_gradient = requires_gradient;
69  }
70 
71  // Test variables are associated with linear forms,
72  // whereas trial variables are associated with gridfunctions.
73  const std::vector<std::string> & GetTrialVarNames() const { return _trial_var_names; }
74  const std::vector<std::string> & GetTestVarNames() const { return _test_var_names; }
75 
79  bool Nonlinear() const { return _non_linear; }
80 
87 
88 protected:
90  virtual void AddCoupledVariableNameIfMissing(const std::string & coupled_var_name);
92  virtual void AddEliminatedVariableNameIfMissing(const std::string & eliminated_var_name);
94  virtual void AddTestVariableNameIfMissing(const std::string & test_var_name);
96  virtual void SetTrialVariableNames();
97 
101  void DeleteHBlocks();
102 
106  void DeleteJacobianBlocks();
107 
108  bool VectorContainsName(const std::vector<std::string> & the_vector,
109  const std::string & name) const;
110 
113  virtual void ApplyEssentialBC(const std::string & var_name,
114  mfem::ParGridFunction & trial_gf,
115  mfem::Array<int> & global_ess_markers);
117  virtual void ApplyEssentialBCs();
119  virtual void EliminateCoupledVariables();
121  virtual void BuildLinearForms();
123  virtual void BuildNonlinearForms();
125  virtual void BuildBilinearForms();
127  virtual void BuildMixedBilinearForms();
129  virtual void BuildEquationSystem();
130 
133  virtual void FormLinearSystem(mfem::OperatorHandle & op,
134  mfem::BlockVector & trueX,
135  mfem::BlockVector & trueRHS);
136  using mfem::Operator::FormSystemOperator;
139  virtual void FormSystemOperator(mfem::OperatorHandle & op,
140  mfem::BlockVector & trueX,
141  mfem::BlockVector & trueRHS);
144  virtual void FormSystemMatrix(mfem::OperatorHandle & op,
145  mfem::BlockVector & trueX,
146  mfem::BlockVector & trueRHS);
148  void FormJacobianMatrix(const mfem::Vector & u);
149 
154  template <class FormType>
156  const std::string & trial_var_name,
157  const std::string & test_var_name,
158  std::shared_ptr<FormType> form,
159  NamedFieldsMap<NamedFieldsMap<std::vector<std::shared_ptr<MFEMKernel>>>> & kernels_map,
160  std::optional<mfem::real_t> scale_factor = std::nullopt);
161 
167  const std::string & test_var_name,
168  std::shared_ptr<mfem::ParLinearForm> form,
169  NamedFieldsMap<NamedFieldsMap<std::vector<std::shared_ptr<MFEMKernel>>>> & kernels_map);
170 
176  const std::string & test_var_name,
177  std::shared_ptr<mfem::ParNonlinearForm> form,
178  NamedFieldsMap<NamedFieldsMap<std::vector<std::shared_ptr<MFEMKernel>>>> & kernels_map,
179  std::optional<mfem::real_t> scale_factor = std::nullopt);
180 
185  template <class FormType>
187  const std::string & trial_var_name,
188  const std::string & test_var_name,
189  std::shared_ptr<FormType> form,
190  NamedFieldsMap<NamedFieldsMap<std::vector<std::shared_ptr<MFEMIntegratedBC>>>> &
191  integrated_bc_map,
192  std::optional<mfem::real_t> scale_factor = std::nullopt);
193 
199  const std::string & test_var_name,
200  std::shared_ptr<mfem::ParLinearForm> form,
201  NamedFieldsMap<NamedFieldsMap<std::vector<std::shared_ptr<MFEMIntegratedBC>>>> &
202  integrated_bc_map);
203 
209  const std::string & test_var_name,
210  std::shared_ptr<mfem::ParNonlinearForm> form,
211  NamedFieldsMap<NamedFieldsMap<std::vector<std::shared_ptr<MFEMIntegratedBC>>>> &
212  integrated_bc_map,
213  std::optional<mfem::real_t> scale_factor = std::nullopt);
214 
218  virtual bool Complex() const { return false; }
219 
222  std::vector<std::string> _coupled_var_names;
226  std::vector<std::string> _trial_var_names;
228  std::vector<std::string> _eliminated_var_names;
232  std::vector<std::string> _test_var_names;
234  std::vector<mfem::ParFiniteElementSpace *> _test_pfespaces;
236  std::vector<mfem::ParFiniteElementSpace *> _coupled_pfespaces;
237 
238  // Components of weak form, named according to test variable
243 
245  std::vector<std::unique_ptr<mfem::ParGridFunction>> _var_ess_constraints;
246  std::vector<mfem::Array<int>> _ess_tdof_lists;
247 
248  mfem::Array2D<const mfem::HypreParMatrix *> _h_blocks, _jacobian_blocks;
258 
259  // Operator handle for the jacobian
260  mutable mfem::OperatorHandle _jacobian;
261  // Operator handle for the linear components of the system operator
262  mutable mfem::OperatorHandle _linear_operator;
263  mfem::AssemblyLevel _assembly_level;
264 
265  // Pointer to GridFunctions to enable updates during nonlinear iterations
267  // Array storing block offsets of solution and residual vector
268  mfem::Array<int> _block_true_offsets;
269  // Boolean indicating if EquationSystem contains nonlinear integrators
270  bool _non_linear = false;
271  // Whether a nonlinear solver exists and whether it requires Jacobian/gradient information.
273 
274 private:
276  friend class ::MFEMProblemSolve;
278  using mfem::Operator::RecoverFEMSolution;
279 };
280 
281 template <class FormType>
282 void
284  const std::string & trial_var_name,
285  const std::string & test_var_name,
286  std::shared_ptr<FormType> form,
287  NamedFieldsMap<NamedFieldsMap<std::vector<std::shared_ptr<MFEMKernel>>>> & kernels_map,
288  std::optional<mfem::real_t> scale_factor)
289 {
290  if (kernels_map.Has(test_var_name) && kernels_map.Get(test_var_name)->Has(trial_var_name))
291  {
292  auto kernels = kernels_map.GetRef(test_var_name).GetRef(trial_var_name);
293  for (auto & kernel : kernels)
294  {
295  mfem::BilinearFormIntegrator * integ = kernel->createBFIntegrator();
296 
297  if (integ)
298  {
299  if (scale_factor.has_value())
300  integ = new ScaleIntegrator(integ, scale_factor.value(), true);
301  kernel->isSubdomainRestricted()
302  ? form->AddDomainIntegrator(std::move(integ), kernel->getSubdomainMarkers())
303  : form->AddDomainIntegrator(std::move(integ));
304  }
305  }
306  }
307 }
308 
309 template <class FormType>
310 void
312  const std::string & trial_var_name,
313  const std::string & test_var_name,
314  std::shared_ptr<FormType> form,
315  NamedFieldsMap<NamedFieldsMap<std::vector<std::shared_ptr<MFEMIntegratedBC>>>> &
316  integrated_bc_map,
317  std::optional<mfem::real_t> scale_factor)
318 {
319  if (integrated_bc_map.Has(test_var_name) &&
320  integrated_bc_map.Get(test_var_name)->Has(trial_var_name))
321  {
322  auto bcs = integrated_bc_map.GetRef(test_var_name).GetRef(trial_var_name);
323  for (auto & bc : bcs)
324  {
325  mfem::BilinearFormIntegrator * integ = bc->createBFIntegrator();
326 
327  if (integ)
328  {
329  if (scale_factor.has_value())
330  integ = new ScaleIntegrator(integ, scale_factor.value(), true);
331  bc->isBoundaryRestricted()
332  ? form->AddBoundaryIntegrator(std::move(integ), bc->getBoundaryMarkers())
333  : form->AddBoundaryIntegrator(std::move(integ));
334  }
335  }
336  }
337 }
338 
339 } // namespace Moose::MFEM
340 
341 #endif
void ApplyDomainNLFIntegrators(const std::string &test_var_name, std::shared_ptr< mfem::ParNonlinearForm > form, NamedFieldsMap< NamedFieldsMap< std::vector< std::shared_ptr< MFEMKernel >>>> &kernels_map, std::optional< mfem::real_t > scale_factor=std::nullopt)
Apply domain NonlinearFormIntegrators from kernels to the nonlinear form associated with the supplied...
NamedFieldsMap< mfem::ParBilinearForm > _blfs
virtual void EliminateCoupledVariables()
Perform trivial eliminations of coupled variables lacking corresponding test variables.
NamedFieldsMap< NamedFieldsMap< mfem::ParMixedBilinearForm > > _mblfs
virtual void AddTestVariableNameIfMissing(const std::string &test_var_name)
Add test variable to EquationSystem.
virtual void AddKernel(std::shared_ptr< MFEMKernel > kernel)
Add kernels.
virtual void BuildBilinearForms()
Build bilinear forms (diagonal Jacobian contributions)
std::vector< mfem::ParFiniteElementSpace * > _coupled_pfespaces
Pointers to finite element spaces associated with coupled variables.
void PrepareLinearSolver(LinearSolverBase &solver)
Prepare the provided linear solver.
void SetSolverRequiresGradient(bool requires_gradient)
Set whether the nonlinear solver driving this equation system requires Jacobian information.
virtual void SetTrialVariablesFromTrueVectors(const mfem::BlockVector &trueX) const
Update variable from solution vector after solve.
void DeleteJacobianBlocks()
Deletes the HypreParMatrix associated with any pointer stored in _jacobian_blocks, and then proceeds to delete all dynamically allocated memory for _jacobian_blocks itself, resetting all dimensions to zero.
bool VectorContainsName(const std::vector< std::string > &the_vector, const std::string &name) const
NamedFieldsMap< NamedFieldsMap< std::vector< std::shared_ptr< MFEMIntegratedBC > > > > _integrated_bc_map
Arrays to store integrated BCs to act on each component of weak form.
std::vector< std::string > _eliminated_var_names
Names of all coupled variables without a corresponding test variable.
void FormJacobianMatrix(const mfem::Vector &u)
Compute Jacobian matrix at the provided vector of true DoFs of trial variables.
NamedFieldsMap< mfem::ParNonlinearForm > _nlfs
Class to store weak form components (bilinear and linear forms, and optionally mixed and nonlinear fo...
Moose::MFEM::GridFunctions _eliminated_variables
Pointers to coupled variables not part of the reduced EquationSystem.
virtual void AddEssentialBC(std::shared_ptr< MFEMEssentialBC > bc)
Add BC associated with essentially constrained DoFs on boundaries.
std::vector< mfem::Array< int > > _ess_tdof_lists
mfem::AssemblyLevel _assembly_level
void ApplyBoundaryBLFIntegrators(const std::string &trial_var_name, const std::string &test_var_name, std::shared_ptr< FormType > form, NamedFieldsMap< NamedFieldsMap< std::vector< std::shared_ptr< MFEMIntegratedBC >>>> &integrated_bc_map, std::optional< mfem::real_t > scale_factor=std::nullopt)
Template method for applying BilinearFormIntegrators on boundaries from integrated boundary condition...
std::vector< mfem::ParFiniteElementSpace * > _test_pfespaces
Pointers to finite element spaces associated with test variables.
void FormSystem(mfem::BlockVector &trueX, mfem::BlockVector &trueRHS)
Assemble the linear part of the operator, assemble the right-hand side, apply essential and eliminate...
void Mult(const mfem::Vector &u, mfem::Vector &residual) const override
Compute residual y = Mu.
mfem::Array< int > _block_true_offsets
std::vector< std::string > _trial_var_names
Subset of _coupled_var_names of all variables corresponding to gridfunctions with degrees of freedom ...
Base class for linear MFEM solvers and preconditioners.
NamedFieldsMap< std::vector< std::shared_ptr< MFEMEssentialBC > > > _essential_bc_map
Arrays to store essential BCs to act on each component of weak form.
void ApplyDomainBLFIntegrators(const std::string &trial_var_name, const std::string &test_var_name, std::shared_ptr< FormType > form, NamedFieldsMap< NamedFieldsMap< std::vector< std::shared_ptr< MFEMKernel >>>> &kernels_map, std::optional< mfem::real_t > scale_factor=std::nullopt)
Template method for applying BilinearFormIntegrators on domains from kernels to a BilinearForm...
mfem::OperatorHandle _jacobian
NamedFieldsMap< NamedFieldsMap< std::vector< std::shared_ptr< MFEMKernel > > > > _kernels_map
Arrays to store kernels to act on each component of weak form.
std::vector< std::string > _test_var_names
Names of all test variables corresponding to linear forms in this equation system.
Steady-state problem operator with an equation system.
virtual void BuildEquationSystem()
Build all forms comprising this EquationSystem.
std::vector< std::unique_ptr< mfem::ParGridFunction > > _var_ess_constraints
Gridfunctions holding essential constraints from Dirichlet BCs.
void ApplyBoundaryLFIntegrators(const std::string &test_var_name, std::shared_ptr< mfem::ParLinearForm > form, NamedFieldsMap< NamedFieldsMap< std::vector< std::shared_ptr< MFEMIntegratedBC >>>> &integrated_bc_map)
Apply boundary LinearFormIntegrators from integrated boundary conditions to the linear form associate...
virtual void BuildMixedBilinearForms()
Build mixed bilinear forms (off-diagonal Jacobian contributions)
virtual void FormSystemOperator(mfem::OperatorHandle &op, mfem::BlockVector &trueX, mfem::BlockVector &trueRHS)
Form matrix-free representation of linear components of system operator.
Integrator which scales its results by a constant value.
mfem::Array2D< const mfem::HypreParMatrix * > _h_blocks
virtual void SetTrialVariableNames()
Set trial variable names from subset of coupled variables that have an associated test variable...
virtual void FormSystemMatrix(mfem::OperatorHandle &op, mfem::BlockVector &trueX, mfem::BlockVector &trueRHS)
Form matrix representation of linear components of system operator as a HypreParMatrix.
virtual void AddCoupledVariableNameIfMissing(const std::string &coupled_var_name)
Add coupled variable to EquationSystem.
virtual void FormLinearSystem(mfem::OperatorHandle &op, mfem::BlockVector &trueX, mfem::BlockVector &trueRHS)
Form linear components of system based on on- and off-diagonal bilinear form contributions, populate solution and RHS vectors of true DoFs, and apply constraints.
void DeleteHBlocks()
Deletes the HypreParMatrix associated with any pointer stored in _h_blocks, and then proceeds to dele...
std::vector< std::string > _coupled_var_names
Names of all trial variables of kernels and boundary conditions added to this EquationSystem.
virtual void BuildNonlinearForms()
Build non-linear action forms.
NamedFieldsMap< mfem::ParLinearForm > _lfs
virtual void BuildLinearForms()
Build linear forms and eliminate constrained DoFs.
const std::vector< std::string > & GetTrialVarNames() const
const std::vector< std::string > & GetTestVarNames() const
void ApplyBoundaryNLFIntegrators(const std::string &test_var_name, std::shared_ptr< mfem::ParNonlinearForm > form, NamedFieldsMap< NamedFieldsMap< std::vector< std::shared_ptr< MFEMIntegratedBC >>>> &integrated_bc_map, std::optional< mfem::real_t > scale_factor=std::nullopt)
Apply boundary NonlinearFormIntegrators from integrated boundary conditions to the nonlinear form ass...
virtual void ApplyEssentialBCs()
Update all essentially constrained true DoF markers and values on boundaries.
void ApplyDomainLFIntegrators(const std::string &test_var_name, std::shared_ptr< mfem::ParLinearForm > form, NamedFieldsMap< NamedFieldsMap< std::vector< std::shared_ptr< MFEMKernel >>>> &kernels_map)
Apply domain LinearFormIntegrators from kernels to the linear form associated with the supplied test ...
Utilities for converting between vector(s) of libMesh Points and MFEM Vector(s).
mfem::OperatorHandle _linear_operator
virtual void AddEliminatedVariableNameIfMissing(const std::string &eliminated_var_name)
Add eliminated variable to EquationSystem.
virtual void Init(GridFunctions &gridfunctions, ComplexGridFunctions &cmplx_gridfunctions, mfem::AssemblyLevel assembly_level)
Initialise.
mfem::Operator & GetGradient(const mfem::Vector &u) const override
Get Jacobian at the provided vector of true DoFs of trial variables.
virtual void ComputeNonlinearResidual(const mfem::Vector &u, mfem::Vector &residual) const
Compute the contribution to the residual from nonlinear forms only.
virtual void ApplyEssentialBC(const std::string &var_name, mfem::ParGridFunction &trial_gf, mfem::Array< int > &global_ess_markers)
Apply essential BC(s) associated with var_name to set true DoFs of trial_gf and update markers of all...
virtual void AddIntegratedBC(std::shared_ptr< MFEMIntegratedBC > kernel)
virtual bool Complex() const
Whether this a complex equation system.
mfem::Array2D< const mfem::HypreParMatrix * > _jacobian_blocks
Moose::MFEM::GridFunctions * _gfuncs