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 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 
26 /*
27 Class to store weak form components (bilinear and linear forms, and optionally
28 mixed and nonlinear forms) and build methods
29 */
30 class EquationSystem : public mfem::Operator
31 {
32 
33 public:
36 
37  EquationSystem() = default;
38  ~EquationSystem() override;
39 
40  // add test variable to EquationSystem;
41  virtual void AddTestVariableNameIfMissing(const std::string & test_var_name);
42  virtual void AddTrialVariableNameIfMissing(const std::string & trial_var_name);
43 
44  // Add kernels.
45  virtual void AddKernel(std::shared_ptr<MFEMKernel> kernel);
46  virtual void AddIntegratedBC(std::shared_ptr<MFEMIntegratedBC> kernel);
47  virtual void AddEssentialBC(std::shared_ptr<MFEMEssentialBC> bc);
48  virtual void ApplyEssentialBCs();
49 
50  // Build forms
51  virtual void Init(Moose::MFEM::GridFunctions & gridfunctions,
52  const Moose::MFEM::FESpaces & fespaces,
53  mfem::AssemblyLevel assembly_level);
54  virtual void BuildLinearForms();
55  virtual void BuildBilinearForms();
56  virtual void BuildMixedBilinearForms();
57  virtual void BuildEquationSystem();
58 
59  // Form linear system, with essential boundary conditions accounted for
60  virtual void FormLinearSystem(mfem::OperatorHandle & op,
61  mfem::BlockVector & trueX,
62  mfem::BlockVector & trueRHS);
63 
64  virtual void
65  FormSystem(mfem::OperatorHandle & op, mfem::BlockVector & trueX, mfem::BlockVector & trueRHS);
66  virtual void FormLegacySystem(mfem::OperatorHandle & op,
67  mfem::BlockVector & trueX,
68  mfem::BlockVector & trueRHS);
69 
70  // Build linear system, with essential boundary conditions accounted for
71  virtual void BuildJacobian(mfem::BlockVector & trueX, mfem::BlockVector & trueRHS);
72 
74  void Mult(const mfem::Vector & u, mfem::Vector & residual) const override;
75 
77  mfem::Operator & GetGradient(const mfem::Vector & u) const override;
78 
79  // Update variable from solution vector after solve
80  using mfem::Operator::RecoverFEMSolution;
81  virtual void RecoverFEMSolution(mfem::BlockVector & trueX,
82  Moose::MFEM::GridFunctions & gridfunctions);
83 
84  std::vector<mfem::Array<int>> _ess_tdof_lists;
85 
86  const std::vector<std::string> & TrialVarNames() const { return _trial_var_names; }
87  const std::vector<std::string> & TestVarNames() const { return _test_var_names; }
88 
89 protected:
90  // Deletes the HypreParMatrix associated with any pointer stored in _h_blocks,
91  // and then proceeds to delete all dynamically allocated memory for _h_blocks
92  // itself, resetting all dimensions to zero.
93  void DeleteAllBlocks();
94 
95  bool VectorContainsName(const std::vector<std::string> & the_vector,
96  const std::string & name) const;
97 
98  // Test variables are associated with LinearForms,
99  // whereas trial variables are associated with gridfunctions.
100 
101  // Names of all variables corresponding to gridfunctions. This may differ
102  // from test_var_names when time derivatives are present.
103  std::vector<std::string> _trial_var_names;
104  // Pointers to trial variables.
106  // Names of all test variables corresponding to linear forms in this equation
107  // system
108  std::vector<std::string> _test_var_names;
109  std::vector<mfem::ParFiniteElementSpace *> _test_pfespaces;
110 
111  // Components of weak form. // Named according to test variable
116  _mblfs; // named according to trial variable
117 
122  template <class FormType>
124  const std::string & trial_var_name,
125  const std::string & test_var_name,
126  std::shared_ptr<FormType> form,
128  Moose::MFEM::NamedFieldsMap<std::vector<std::shared_ptr<MFEMKernel>>>> & kernels_map);
129 
131  const std::string & test_var_name,
132  std::shared_ptr<mfem::ParLinearForm> form,
134  Moose::MFEM::NamedFieldsMap<std::vector<std::shared_ptr<MFEMKernel>>>> & kernels_map);
135 
136  template <class FormType>
138  const std::string & trial_var_name,
139  const std::string & test_var_name,
140  std::shared_ptr<FormType> form,
142  Moose::MFEM::NamedFieldsMap<std::vector<std::shared_ptr<MFEMIntegratedBC>>>> &
143  integrated_bc_map);
144 
146  const std::string & test_var_name,
147  std::shared_ptr<mfem::ParLinearForm> form,
149  Moose::MFEM::NamedFieldsMap<std::vector<std::shared_ptr<MFEMIntegratedBC>>>> &
150  integrated_bc_map);
151 
152  // gridfunctions for setting Dirichlet BCs
153  std::vector<std::unique_ptr<mfem::ParGridFunction>> _xs;
154  std::vector<std::unique_ptr<mfem::ParGridFunction>> _dxdts;
155 
156  mfem::Array2D<const mfem::HypreParMatrix *> _h_blocks;
157 
158  // Arrays to store kernels to act on each component of weak form. Named
159  // according to test variable
166 
167  mutable mfem::OperatorHandle _jacobian;
168 
169  mfem::AssemblyLevel _assembly_level;
170 };
171 
172 template <class FormType>
173 void
175  const std::string & trial_var_name,
176  const std::string & test_var_name,
177  std::shared_ptr<FormType> form,
179  Moose::MFEM::NamedFieldsMap<std::vector<std::shared_ptr<MFEMKernel>>>> & kernels_map)
180 {
181  if (kernels_map.Has(test_var_name) && kernels_map.Get(test_var_name)->Has(trial_var_name))
182  {
183  auto kernels = kernels_map.GetRef(test_var_name).GetRef(trial_var_name);
184  for (auto & kernel : kernels)
185  {
186  mfem::BilinearFormIntegrator * integ = kernel->createBFIntegrator();
187  if (integ != nullptr)
188  {
189  kernel->isSubdomainRestricted()
190  ? form->AddDomainIntegrator(std::move(integ), kernel->getSubdomainMarkers())
191  : form->AddDomainIntegrator(std::move(integ));
192  }
193  }
194  }
195 }
196 
197 inline void
199  const std::string & test_var_name,
200  std::shared_ptr<mfem::ParLinearForm> form,
202  Moose::MFEM::NamedFieldsMap<std::vector<std::shared_ptr<MFEMKernel>>>> & kernels_map)
203 {
204  if (kernels_map.Has(test_var_name))
205  {
206  auto kernels = kernels_map.GetRef(test_var_name).GetRef(test_var_name);
207  for (auto & kernel : kernels)
208  {
209  mfem::LinearFormIntegrator * integ = kernel->createLFIntegrator();
210  if (integ != nullptr)
211  {
212  kernel->isSubdomainRestricted()
213  ? form->AddDomainIntegrator(std::move(integ), kernel->getSubdomainMarkers())
214  : form->AddDomainIntegrator(std::move(integ));
215  }
216  }
217  }
218 }
219 
220 template <class FormType>
221 void
223  const std::string & trial_var_name,
224  const std::string & test_var_name,
225  std::shared_ptr<FormType> form,
227  Moose::MFEM::NamedFieldsMap<std::vector<std::shared_ptr<MFEMIntegratedBC>>>> &
228  integrated_bc_map)
229 {
230  if (integrated_bc_map.Has(test_var_name) &&
231  integrated_bc_map.Get(test_var_name)->Has(trial_var_name))
232  {
233  auto bcs = integrated_bc_map.GetRef(test_var_name).GetRef(trial_var_name);
234  for (auto & bc : bcs)
235  {
236  mfem::BilinearFormIntegrator * integ = bc->createBFIntegrator();
237  if (integ != nullptr)
238  {
239  bc->isBoundaryRestricted()
240  ? form->AddBoundaryIntegrator(std::move(integ), bc->getBoundaryMarkers())
241  : form->AddBoundaryIntegrator(std::move(integ));
242  }
243  }
244  }
245 }
246 
247 inline void
249  const std::string & test_var_name,
250  std::shared_ptr<mfem::ParLinearForm> form,
252  Moose::MFEM::NamedFieldsMap<std::vector<std::shared_ptr<MFEMIntegratedBC>>>> &
253  integrated_bc_map)
254 {
255  if (integrated_bc_map.Has(test_var_name))
256  {
257  auto bcs = integrated_bc_map.GetRef(test_var_name).GetRef(test_var_name);
258  for (auto & bc : bcs)
259  {
260  mfem::LinearFormIntegrator * integ = bc->createLFIntegrator();
261  if (integ != nullptr)
262  {
263  bc->isBoundaryRestricted()
264  ? form->AddBoundaryIntegrator(std::move(integ), bc->getBoundaryMarkers())
265  : form->AddBoundaryIntegrator(std::move(integ));
266  }
267  }
268  }
269 }
270 
271 /*
272 Class to store weak form components for time dependent PDEs
273 */
275 {
276 public:
278 
279  void AddTrialVariableNameIfMissing(const std::string & trial_var_name) override;
280 
281  virtual void SetTimeStep(double dt);
282  virtual void UpdateEquationSystem();
283 
284  virtual void AddKernel(std::shared_ptr<MFEMKernel> kernel) override;
285  virtual void BuildBilinearForms() override;
286  virtual void FormLegacySystem(mfem::OperatorHandle & op,
287  mfem::BlockVector & truedXdt,
288  mfem::BlockVector & trueRHS) override;
289  virtual void FormSystem(mfem::OperatorHandle & op,
290  mfem::BlockVector & truedXdt,
291  mfem::BlockVector & trueRHS) override;
292 
293  const std::vector<std::string> & TrialVarTimeDerivativeNames() const;
294 
295 protected:
296  mfem::ConstantCoefficient _dt_coef; // Coefficient for timestep scaling
297  std::vector<std::string> _trial_var_time_derivative_names;
298 
301  // Container to store contributions to weak form of the form (F du/dt, v)
303 };
304 
305 inline const std::vector<std::string> &
307 {
309 }
310 
311 } // namespace Moose::MFEM
312 
313 #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...
virtual void AddKernel(std::shared_ptr< MFEMKernel > kernel) override
virtual void AddTestVariableNameIfMissing(const std::string &test_var_name)
virtual void AddKernel(std::shared_ptr< MFEMKernel > kernel)
virtual void RecoverFEMSolution(mfem::BlockVector &trueX, Moose::MFEM::GridFunctions &gridfunctions)
virtual void BuildBilinearForms()
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::unique_ptr< mfem::ParGridFunction > > _xs
Moose::MFEM::NamedFieldsMap< Moose::MFEM::NamedFieldsMap< mfem::ParMixedBilinearForm > > _mblfs
std::vector< std::unique_ptr< mfem::ParGridFunction > > _dxdts
virtual void AddEssentialBC(std::shared_ptr< MFEMEssentialBC > bc)
Problem operator for time-dependent problems with an equation system.
std::vector< mfem::Array< int > > _ess_tdof_lists
mfem::AssemblyLevel _assembly_level
void AddTrialVariableNameIfMissing(const std::string &trial_var_name) override
Moose::MFEM::NamedFieldsMap< std::vector< std::shared_ptr< MFEMEssentialBC > > > _essential_bc_map
std::vector< mfem::ParFiniteElementSpace * > _test_pfespaces
const std::vector< std::string > & TrialVarTimeDerivativeNames() const
void Mult(const mfem::Vector &u, mfem::Vector &residual) const override
Compute residual y = Mu.
std::vector< std::string > _trial_var_names
virtual void FormLegacySystem(mfem::OperatorHandle &op, mfem::BlockVector &trueX, mfem::BlockVector &trueRHS)
mfem::OperatorHandle _jacobian
virtual void AddTrialVariableNameIfMissing(const std::string &trial_var_name)
std::vector< std::string > _test_var_names
Steady-state problem operator with an equation system.
virtual void BuildEquationSystem()
virtual void Init(Moose::MFEM::GridFunctions &gridfunctions, const Moose::MFEM::FESpaces &fespaces, mfem::AssemblyLevel assembly_level)
virtual void FormLegacySystem(mfem::OperatorHandle &op, mfem::BlockVector &truedXdt, mfem::BlockVector &trueRHS) override
virtual void BuildMixedBilinearForms()
mfem::Array2D< const mfem::HypreParMatrix * > _h_blocks
virtual void FormLinearSystem(mfem::OperatorHandle &op, mfem::BlockVector &trueX, mfem::BlockVector &trueRHS)
std::vector< std::string > _trial_var_time_derivative_names
Moose::MFEM::NamedFieldsMap< Moose::MFEM::NamedFieldsMap< std::vector< std::shared_ptr< MFEMIntegratedBC > > > > _integrated_bc_map
Moose::MFEM::NamedFieldsMap< mfem::ParBilinearForm > _td_blfs
Moose::MFEM::GridFunctions _trial_variables
virtual void BuildJacobian(mfem::BlockVector &trueX, mfem::BlockVector &trueRHS)
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()
Moose::MFEM::NamedFieldsMap< mfem::ParLinearForm > _lfs
virtual void BuildBilinearForms() override
Moose::MFEM::NamedFieldsMap< Moose::MFEM::NamedFieldsMap< std::vector< std::shared_ptr< MFEMKernel > > > > _kernels_map
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)