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 #include "libmesh/ignore_warnings.h"
14 #include "mfem/miniapps/common/pfem_extras.hpp"
15 #include "libmesh/restore_warnings.h"
16 #include "MFEMIntegratedBC.h"
17 #include "MFEMEssentialBC.h"
18 #include "MFEMContainers.h"
19 #include "MFEMKernel.h"
21 #include "ScaleIntegrator.h"
22 
23 namespace Moose::MFEM
24 {
25 
30 class EquationSystem : public mfem::Operator
31 {
32 
33 public:
36 
37  EquationSystem() = default;
38  ~EquationSystem() override;
39 
41  virtual void AddTestVariableNameIfMissing(const std::string & test_var_name);
43  virtual void AddCoupledVariableNameIfMissing(const std::string & coupled_var_name);
44 
46  virtual void AddKernel(std::shared_ptr<MFEMKernel> kernel);
47  virtual void AddIntegratedBC(std::shared_ptr<MFEMIntegratedBC> kernel);
48 
50  virtual void AddEssentialBC(std::shared_ptr<MFEMEssentialBC> bc);
51 
53  virtual void Init(Moose::MFEM::GridFunctions & gridfunctions, mfem::AssemblyLevel assembly_level);
54 
56  virtual void BuildLinearForms();
57 
60  virtual void ApplyEssentialBC(const std::string & test_var_name,
61  mfem::ParGridFunction & trial_gf,
62  mfem::Array<int> & global_ess_markers);
64  virtual void ApplyEssentialBCs();
65 
67  virtual void EliminateCoupledVariables();
68 
70  virtual void BuildBilinearForms();
72  virtual void BuildMixedBilinearForms();
74  virtual void BuildEquationSystem();
75 
78  void AssembleJacobian(
81  jac_mblfs,
83  std::vector<mfem::Array<int>> & ess_tdof_lists,
84  std::vector<std::unique_ptr<mfem::ParGridFunction>> & var_ess_constraints,
85  mfem::OperatorHandle & op,
86  mfem::BlockVector & trueX,
87  mfem::BlockVector & trueRHS);
88 
90  virtual void FormLinearSystem(mfem::OperatorHandle & op,
91  mfem::BlockVector & trueX,
92  mfem::BlockVector & trueRHS);
93 
94  virtual void
95  FormSystem(mfem::OperatorHandle & op, mfem::BlockVector & trueX, mfem::BlockVector & trueRHS);
96  virtual void FormLegacySystem(mfem::OperatorHandle & op,
97  mfem::BlockVector & trueX,
98  mfem::BlockVector & trueRHS);
99 
101  virtual void BuildJacobian(mfem::BlockVector & trueX, mfem::BlockVector & trueRHS);
102 
104  void Mult(const mfem::Vector & u, mfem::Vector & residual) const override;
105 
107  mfem::Operator & GetGradient(const mfem::Vector & u) const override;
108 
110  virtual void RecoverFEMSolution(mfem::BlockVector & trueX,
111  Moose::MFEM::GridFunctions & gridfunctions);
112 
113  std::vector<mfem::Array<int>> _ess_tdof_lists;
114 
115  const std::vector<std::string> & TrialVarNames() const { return _trial_var_names; }
116  const std::vector<std::string> & TestVarNames() const { return _test_var_names; }
117 
118 private:
120  using mfem::Operator::RecoverFEMSolution;
121 
123  virtual void SetTrialVariableNames();
124 
125 protected:
129  void DeleteAllBlocks();
130 
131  bool VectorContainsName(const std::vector<std::string> & the_vector,
132  const std::string & name) const;
133 
134  // Test variables are associated with LinearForms,
135  // whereas trial variables are associated with gridfunctions.
136 
139  std::vector<std::string> _coupled_var_names;
143  std::vector<std::string> _trial_var_names;
145  std::vector<std::string> _eliminated_var_names;
149  std::vector<std::string> _test_var_names;
151  std::vector<mfem::ParFiniteElementSpace *> _test_pfespaces;
153  std::vector<mfem::ParFiniteElementSpace *> _coupled_pfespaces;
154 
155  // Components of weak form. // Named according to test variable
160  _mblfs; // named according to trial variable
161 
166  template <class FormType>
168  const std::string & trial_var_name,
169  const std::string & test_var_name,
170  std::shared_ptr<FormType> form,
172  Moose::MFEM::NamedFieldsMap<std::vector<std::shared_ptr<MFEMKernel>>>> & kernels_map);
173 
175  const std::string & test_var_name,
176  std::shared_ptr<mfem::ParLinearForm> form,
178  Moose::MFEM::NamedFieldsMap<std::vector<std::shared_ptr<MFEMKernel>>>> & kernels_map);
179 
180  template <class FormType>
182  const std::string & trial_var_name,
183  const std::string & test_var_name,
184  std::shared_ptr<FormType> form,
186  Moose::MFEM::NamedFieldsMap<std::vector<std::shared_ptr<MFEMIntegratedBC>>>> &
187  integrated_bc_map);
188 
190  const std::string & test_var_name,
191  std::shared_ptr<mfem::ParLinearForm> form,
193  Moose::MFEM::NamedFieldsMap<std::vector<std::shared_ptr<MFEMIntegratedBC>>>> &
194  integrated_bc_map);
195 
197  std::vector<std::unique_ptr<mfem::ParGridFunction>> _var_ess_constraints;
198 
199  mfem::Array2D<const mfem::HypreParMatrix *> _h_blocks;
200 
213 
214  mutable mfem::OperatorHandle _jacobian;
215 
216  mfem::AssemblyLevel _assembly_level;
217 };
218 
219 template <class FormType>
220 void
222  const std::string & trial_var_name,
223  const std::string & test_var_name,
224  std::shared_ptr<FormType> form,
226  Moose::MFEM::NamedFieldsMap<std::vector<std::shared_ptr<MFEMKernel>>>> & kernels_map)
227 {
228  if (kernels_map.Has(test_var_name) && kernels_map.Get(test_var_name)->Has(trial_var_name))
229  {
230  auto kernels = kernels_map.GetRef(test_var_name).GetRef(trial_var_name);
231  for (auto & kernel : kernels)
232  {
233  mfem::BilinearFormIntegrator * integ = kernel->createBFIntegrator();
234  if (integ != nullptr)
235  {
236  kernel->isSubdomainRestricted()
237  ? form->AddDomainIntegrator(std::move(integ), kernel->getSubdomainMarkers())
238  : form->AddDomainIntegrator(std::move(integ));
239  }
240  }
241  }
242 }
243 
244 inline void
246  const std::string & test_var_name,
247  std::shared_ptr<mfem::ParLinearForm> form,
249  Moose::MFEM::NamedFieldsMap<std::vector<std::shared_ptr<MFEMKernel>>>> & kernels_map)
250 {
251  if (kernels_map.Has(test_var_name) && kernels_map.Get(test_var_name)->Has(test_var_name))
252  {
253  auto kernels = kernels_map.GetRef(test_var_name).GetRef(test_var_name);
254  for (auto & kernel : kernels)
255  {
256  mfem::LinearFormIntegrator * integ = kernel->createLFIntegrator();
257  if (integ != nullptr)
258  {
259  kernel->isSubdomainRestricted()
260  ? form->AddDomainIntegrator(std::move(integ), kernel->getSubdomainMarkers())
261  : form->AddDomainIntegrator(std::move(integ));
262  }
263  }
264  }
265 }
266 
267 template <class FormType>
268 void
270  const std::string & trial_var_name,
271  const std::string & test_var_name,
272  std::shared_ptr<FormType> form,
274  Moose::MFEM::NamedFieldsMap<std::vector<std::shared_ptr<MFEMIntegratedBC>>>> &
275  integrated_bc_map)
276 {
277  if (integrated_bc_map.Has(test_var_name) &&
278  integrated_bc_map.Get(test_var_name)->Has(trial_var_name))
279  {
280  auto bcs = integrated_bc_map.GetRef(test_var_name).GetRef(trial_var_name);
281  for (auto & bc : bcs)
282  {
283  mfem::BilinearFormIntegrator * integ = bc->createBFIntegrator();
284  if (integ != nullptr)
285  {
286  bc->isBoundaryRestricted()
287  ? form->AddBoundaryIntegrator(std::move(integ), bc->getBoundaryMarkers())
288  : form->AddBoundaryIntegrator(std::move(integ));
289  }
290  }
291  }
292 }
293 
294 inline void
296  const std::string & test_var_name,
297  std::shared_ptr<mfem::ParLinearForm> form,
299  Moose::MFEM::NamedFieldsMap<std::vector<std::shared_ptr<MFEMIntegratedBC>>>> &
300  integrated_bc_map)
301 {
302  if (integrated_bc_map.Has(test_var_name) &&
303  integrated_bc_map.Get(test_var_name)->Has(test_var_name))
304  {
305  auto bcs = integrated_bc_map.GetRef(test_var_name).GetRef(test_var_name);
306  for (auto & bc : bcs)
307  {
308  mfem::LinearFormIntegrator * integ = bc->createLFIntegrator();
309  if (integ != nullptr)
310  {
311  bc->isBoundaryRestricted()
312  ? form->AddBoundaryIntegrator(std::move(integ), bc->getBoundaryMarkers())
313  : form->AddBoundaryIntegrator(std::move(integ));
314  }
315  }
316  }
317 }
318 
323 {
324 public:
325  TimeDependentEquationSystem(const Moose::MFEM::TimeDerivativeMap & time_derivative_map);
326 
328  virtual void Init(Moose::MFEM::GridFunctions & gridfunctions,
329  mfem::AssemblyLevel assembly_level) override;
330 
331  virtual void SetTimeStep(mfem::real_t dt);
332  virtual void UpdateEquationSystem();
333 
334  virtual void AddKernel(std::shared_ptr<MFEMKernel> kernel) override;
335  virtual void BuildBilinearForms() override;
336  virtual void BuildMixedBilinearForms() override;
337  virtual void ApplyEssentialBCs() override;
338  virtual void EliminateCoupledVariables() override;
339  virtual void FormLegacySystem(mfem::OperatorHandle & op,
340  mfem::BlockVector & truedXdt,
341  mfem::BlockVector & trueRHS) override;
342  virtual void FormSystem(mfem::OperatorHandle & op,
343  mfem::BlockVector & truedXdt,
344  mfem::BlockVector & trueRHS) override;
345 
348  template <class FormType>
349  void ScaleAndAddBLFIntegrators(std::shared_ptr<FormType> source_blf,
350  std::shared_ptr<FormType> target_blf,
351  mfem::real_t scale_factor)
352  {
353  // Add and scale all domain integrators existing on source_blf to target_blf
354  auto domain_integrators = source_blf->GetDBFI();
355  auto domain_markers = source_blf->GetDBFI_Marker();
356  for (int i = 0; i < domain_integrators->Size(); ++i)
357  target_blf->AddDomainIntegrator(
358  new ScaleIntegrator(*domain_integrators[i], scale_factor, false), *(*domain_markers[i]));
359  // Add and scale all boundary integrators existing on source_blf to target_blf
360  auto boundary_integrators = source_blf->GetBBFI();
361  auto boundary_markers = source_blf->GetBBFI_Marker();
362  for (int i = 0; i < boundary_integrators->Size(); ++i)
363  target_blf->AddBoundaryIntegrator(
364  new ScaleIntegrator(*boundary_integrators[i], scale_factor, false),
365  *(*boundary_markers[i]));
366  }
367 
368 protected:
370  mfem::ConstantCoefficient _dt_coef;
371 
377  _td_mblfs; // named according to trial variable
378 
380  std::vector<std::unique_ptr<mfem::ParGridFunction>> _td_var_ess_constraints;
381 
384 
385 private:
387  virtual void SetTrialVariableNames() override;
388 };
389 
390 } // namespace Moose::MFEM
391 
392 #endif
void ApplyDomainBLFIntegrators(const std::string &trial_var_name, const std::string &test_var_name, std::shared_ptr< FormType > form, Moose::MFEM::NamedFieldsMap< Moose::MFEM::NamedFieldsMap< std::vector< std::shared_ptr< MFEMKernel >>>> &kernels_map)
Template method for applying BilinearFormIntegrators on domains from kernels to a BilinearForm...
mfem::ConstantCoefficient _dt_coef
Coefficient for timestep scaling.
virtual void EliminateCoupledVariables()
Perform trivial eliminations of coupled variables lacking corresponding test variables.
virtual void AddKernel(std::shared_ptr< MFEMKernel > kernel) override
Add kernels.
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 RecoverFEMSolution(mfem::BlockVector &trueX, Moose::MFEM::GridFunctions &gridfunctions)
Update variable from solution vector after solve.
virtual void BuildBilinearForms()
Build bilinear forms (diagonal Jacobian contributions)
void AssembleJacobian(Moose::MFEM::NamedFieldsMap< mfem::ParBilinearForm > &jac_blfs, Moose::MFEM::NamedFieldsMap< Moose::MFEM::NamedFieldsMap< mfem::ParMixedBilinearForm >> &jac_mblfs, Moose::MFEM::NamedFieldsMap< mfem::ParLinearForm > &rhs_lfs, std::vector< mfem::Array< int >> &ess_tdof_lists, std::vector< std::unique_ptr< mfem::ParGridFunction >> &var_ess_constraints, mfem::OperatorHandle &op, mfem::BlockVector &trueX, mfem::BlockVector &trueRHS)
Form Jacobian operator based on on- and off-diagonal bilinear form contributions, populate solution a...
std::vector< mfem::ParFiniteElementSpace * > _coupled_pfespaces
Pointers to finite element spaces associated with coupled variables.
Moose::MFEM::NamedFieldsMap< Moose::MFEM::NamedFieldsMap< std::vector< std::shared_ptr< MFEMKernel > > > > _td_kernels_map
const std::vector< std::string > & TestVarNames() const
Moose::MFEM::NamedFieldsMap< mfem::ParNonlinearForm > _nlfs
virtual void FormSystem(mfem::OperatorHandle &op, mfem::BlockVector &truedXdt, mfem::BlockVector &trueRHS) override
const std::vector< std::string > & TrialVarNames() const
void ApplyBoundaryLFIntegrators(const std::string &test_var_name, std::shared_ptr< mfem::ParLinearForm > form, Moose::MFEM::NamedFieldsMap< Moose::MFEM::NamedFieldsMap< std::vector< std::shared_ptr< MFEMIntegratedBC >>>> &integrated_bc_map)
bool VectorContainsName(const std::vector< std::string > &the_vector, const std::string &name) const
std::vector< std::string > _eliminated_var_names
Names of all coupled variables without a corresponding test variable.
Moose::MFEM::NamedFieldsMap< Moose::MFEM::NamedFieldsMap< mfem::ParMixedBilinearForm > > _mblfs
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.
Lightweight adaptor over a std::map relating names of GridFunctions with the name of their time deriv...
Problem operator for time-dependent problems with an equation system.
std::vector< mfem::Array< int > > _ess_tdof_lists
Moose::MFEM::NamedFieldsMap< Moose::MFEM::NamedFieldsMap< mfem::ParMixedBilinearForm > > _td_mblfs
mfem::AssemblyLevel _assembly_level
Moose::MFEM::NamedFieldsMap< std::vector< std::shared_ptr< MFEMEssentialBC > > > _essential_bc_map
Arrays to store essential BCs to act on each component of weak form.
std::vector< mfem::ParFiniteElementSpace * > _test_pfespaces
Pointers to finite element spaces associated with test variables.
Class to store weak form components for time dependent PDEs.
virtual void Init(Moose::MFEM::GridFunctions &gridfunctions, mfem::AssemblyLevel assembly_level) override
Initialise.
virtual void SetTimeStep(mfem::real_t dt)
void Mult(const mfem::Vector &u, mfem::Vector &residual) const override
Compute residual y = Mu.
std::vector< std::string > _trial_var_names
Subset of _coupled_var_names of all variables corresponding to gridfunctions with degrees of freedom ...
std::vector< std::unique_ptr< mfem::ParGridFunction > > _td_var_ess_constraints
Gridfunctions holding essential constraints from Dirichlet BCs.
virtual void BuildMixedBilinearForms() override
Build mixed bilinear forms (off-diagonal Jacobian contributions)
virtual void EliminateCoupledVariables() override
Perform trivial eliminations of coupled variables lacking corresponding test variables.
virtual void FormLegacySystem(mfem::OperatorHandle &op, mfem::BlockVector &trueX, mfem::BlockVector &trueRHS)
virtual void SetTrialVariableNames() override
Set trial variable names from subset of coupled variables that have an associated test variable...
mfem::OperatorHandle _jacobian
virtual void Init(Moose::MFEM::GridFunctions &gridfunctions, mfem::AssemblyLevel assembly_level)
Initialise.
void ScaleAndAddBLFIntegrators(std::shared_ptr< FormType > source_blf, std::shared_ptr< FormType > target_blf, mfem::real_t scale_factor)
Fetch all integrators on a source bilinear form, scale them by a real factor, and add to a second tar...
TimeDependentEquationSystem(const Moose::MFEM::TimeDerivativeMap &time_derivative_map)
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.
virtual void FormLegacySystem(mfem::OperatorHandle &op, mfem::BlockVector &truedXdt, mfem::BlockVector &trueRHS) override
virtual void BuildMixedBilinearForms()
Build mixed bilinear forms (off-diagonal Jacobian contributions)
Integrator which scales its results by a constant value.
mfem::Array2D< const mfem::HypreParMatrix * > _h_blocks
virtual void ApplyEssentialBCs() override
Update all essentially constrained true DoF markers and values on boundaries.
virtual void SetTrialVariableNames()
Set trial variable names from subset of coupled variables that have an associated test variable...
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 system, with essential boundary conditions accounted for.
std::vector< std::string > _coupled_var_names
Names of all trial variables of kernels and boundary conditions added to this EquationSystem.
Moose::MFEM::NamedFieldsMap< Moose::MFEM::NamedFieldsMap< std::vector< std::shared_ptr< MFEMIntegratedBC > > > > _integrated_bc_map
Arrays to store integrated BCs to act on each component of weak form.
void DeleteAllBlocks()
Deletes the HypreParMatrix associated with any pointer stored in _h_blocks, and then proceeds to dele...
Moose::MFEM::NamedFieldsMap< mfem::ParBilinearForm > _td_blfs
Containers to store contributions to weak form of the form (F du/dt, v)
virtual void BuildLinearForms()
Build linear forms and eliminate constrained DoFs.
const Moose::MFEM::TimeDerivativeMap & _time_derivative_map
Map between variable names and their time derivatives.
virtual void BuildJacobian(mfem::BlockVector &trueX, mfem::BlockVector &trueRHS)
Build linear system, with essential boundary conditions accounted for.
void ApplyDomainLFIntegrators(const std::string &test_var_name, std::shared_ptr< mfem::ParLinearForm > form, Moose::MFEM::NamedFieldsMap< Moose::MFEM::NamedFieldsMap< std::vector< std::shared_ptr< MFEMKernel >>>> &kernels_map)
virtual void ApplyEssentialBCs()
Update all essentially constrained true DoF markers and values on boundaries.
virtual void ApplyEssentialBC(const std::string &test_var_name, mfem::ParGridFunction &trial_gf, mfem::Array< int > &global_ess_markers)
Apply essential BC(s) associated with test_var_name to set true DoFs of trial_gf and update markers o...
Moose::MFEM::NamedFieldsMap< mfem::ParLinearForm > _lfs
virtual void BuildBilinearForms() override
Build bilinear forms (diagonal Jacobian contributions)
Moose::MFEM::NamedFieldsMap< Moose::MFEM::NamedFieldsMap< std::vector< std::shared_ptr< MFEMKernel > > > > _kernels_map
Arrays to store kernels to act on each component of weak form.
mfem::Operator & GetGradient(const mfem::Vector &u) const override
Compute J = M + grad_H(u)
virtual void FormSystem(mfem::OperatorHandle &op, mfem::BlockVector &trueX, mfem::BlockVector &trueRHS)
Moose::MFEM::NamedFieldsMap< mfem::ParBilinearForm > _blfs
void ApplyBoundaryBLFIntegrators(const std::string &trial_var_name, const std::string &test_var_name, std::shared_ptr< FormType > form, Moose::MFEM::NamedFieldsMap< Moose::MFEM::NamedFieldsMap< std::vector< std::shared_ptr< MFEMIntegratedBC >>>> &integrated_bc_map)
virtual void AddIntegratedBC(std::shared_ptr< MFEMIntegratedBC > kernel)