https://mooseframework.inl.gov
TimeDependentEquationSystem.C
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 
13 
14 namespace Moose::MFEM
15 {
17  const Moose::MFEM::TimeDerivativeMap & time_derivative_map)
18  : _dt(1.0), _time_derivative_map(time_derivative_map)
19 {
20 }
21 
22 void
23 TimeDependentEquationSystem::AddKernel(std::shared_ptr<MFEMKernel> kernel)
24 {
25  if (!_time_derivative_map.isTimeDerivative(kernel->getTrialVariableName()))
26  {
28  return;
29  }
30 
31  const auto & trial_var_name =
32  _time_derivative_map.getTimeIntegralName(kernel->getTrialVariableName());
33  const auto & test_var_name = kernel->getTestVariableName();
34  AddEliminatedVariableNameIfMissing(trial_var_name);
35  AddTestVariableNameIfMissing(test_var_name);
36  // Register new td kernels map if not present for the test variable
37  if (!_td_kernels_map.Has(test_var_name))
38  {
39  auto kernel_field_map =
40  std::make_shared<Moose::MFEM::NamedFieldsMap<std::vector<std::shared_ptr<MFEMKernel>>>>();
41  _td_kernels_map.Register(test_var_name, std::move(kernel_field_map));
42  }
43  // Register new td kernels map if not present for the test/trial variable pair
44  if (!_td_kernels_map.Get(test_var_name)->Has(trial_var_name))
45  {
46  auto kernels = std::make_shared<std::vector<std::shared_ptr<MFEMKernel>>>();
47  _td_kernels_map.Get(test_var_name)->Register(trial_var_name, std::move(kernels));
48  }
49  _td_kernels_map.GetRef(test_var_name).Get(trial_var_name)->push_back(std::move(kernel));
50 }
51 
52 void
54 {
55  // Register bilinear forms
56  for (const auto i : index_range(_test_var_names))
57  {
58  const auto & test_var_name = _test_var_names.at(i);
59 
60  // Apply kernels to blf
61  _blfs.Register(test_var_name, std::make_shared<mfem::ParBilinearForm>(_test_pfespaces.at(i)));
62  auto blf = _blfs.GetShared(test_var_name);
63  blf->SetAssemblyLevel(_assembly_level);
64  ApplyBoundaryBLFIntegrators<mfem::ParBilinearForm>(
65  test_var_name, test_var_name, blf, _integrated_bc_map, _dt);
66  ApplyDomainBLFIntegrators<mfem::ParBilinearForm>(
67  test_var_name, test_var_name, blf, _kernels_map, _dt);
68  // Apply dt*du/dt contributions from the operator on the trial variable
69  ApplyDomainBLFIntegrators<mfem::ParBilinearForm>(
70  test_var_name, test_var_name, blf, _td_kernels_map);
71  // Assemble
72  blf->Assemble();
73 
74  // Apply kernels to td_blf
75  _td_blfs.Register(test_var_name,
76  std::make_shared<mfem::ParBilinearForm>(_test_pfespaces.at(i)));
77  auto td_blf = _td_blfs.GetShared(test_var_name);
78  td_blf->SetAssemblyLevel(_assembly_level);
79  ApplyDomainBLFIntegrators<mfem::ParBilinearForm>(
80  test_var_name, test_var_name, td_blf, _td_kernels_map);
81  // Assemble
82  td_blf->Assemble();
83  }
84 }
85 
86 void
88 {
89  // Register mixed bilinear forms. Note that not all combinations may
90  // have a kernel.
91 
92  // Create mblf for each test/coupled variable pair with an added kernel.
93  // Mixed bilinear forms with coupled variables that are not trial variables are
94  // associated with contributions from eliminated variables.
95  for (const auto i : index_range(_test_var_names))
96  {
97  const auto & test_var_name = _test_var_names.at(i);
98  auto test_mblfs = std::make_shared<Moose::MFEM::NamedFieldsMap<mfem::ParMixedBilinearForm>>();
99  for (const auto j : index_range(_coupled_var_names))
100  {
101  const auto & coupled_var_name = _coupled_var_names.at(j);
102  auto mblf = std::make_shared<mfem::ParMixedBilinearForm>(_coupled_pfespaces.at(j),
103  _test_pfespaces.at(i));
104  // Register MixedBilinearForm if kernels exist for it, and assemble kernels
105  if (test_var_name != coupled_var_name)
106  {
107  // Apply all mixed kernels with this test/trial pair
108  ApplyBoundaryBLFIntegrators<mfem::ParMixedBilinearForm>(
109  coupled_var_name, test_var_name, mblf, _integrated_bc_map, _dt);
110  ApplyDomainBLFIntegrators<mfem::ParMixedBilinearForm>(
111  coupled_var_name, test_var_name, mblf, _kernels_map, _dt);
112  // Apply dt*du/dt contributions from the operator on the trial variable
113  ApplyDomainBLFIntegrators<mfem::ParMixedBilinearForm>(
114  coupled_var_name, test_var_name, mblf, _td_kernels_map);
115  if (mblf->GetDBFI()->Size() || mblf->GetBBFI()->Size())
116  {
117  // Assemble mixed bilinear forms
118  mblf->SetAssemblyLevel(_assembly_level);
119  mblf->Assemble();
120  // Register mixed bilinear forms associated with a single trial variable
121  // for the current test variable
122  test_mblfs->Register(coupled_var_name, mblf);
123  }
124  }
125  }
126  // Register all mixed bilinear form sets associated with a single test variable
127  _mblfs.Register(test_var_name, test_mblfs);
128  }
129 
130  // Register mixed bilinear forms. Note that not all combinations may
131  // have a kernel.
132 
133  // Create mblf for each test/trial variable pair with an added kernel
134  for (const auto i : index_range(_test_var_names))
135  {
136  const auto & test_var_name = _test_var_names.at(i);
137  auto test_td_mblfs =
138  std::make_shared<Moose::MFEM::NamedFieldsMap<mfem::ParMixedBilinearForm>>();
139  for (const auto j : index_range(_trial_var_names))
140  {
141  const auto & trial_var_name = _trial_var_names.at(j);
142  auto td_mblf = std::make_shared<mfem::ParMixedBilinearForm>(_test_pfespaces.at(j),
143  _test_pfespaces.at(i));
144  // Register MixedBilinearForm if kernels exist for it, and assemble kernels
145  if (test_var_name != trial_var_name)
146  {
147  // Apply all mixed kernels with this test/trial pair
148  ApplyDomainBLFIntegrators<mfem::ParMixedBilinearForm>(
149  trial_var_name, test_var_name, td_mblf, _td_kernels_map);
150  // Assemble mixed bilinear form
151  if (td_mblf->GetDBFI()->Size() || td_mblf->GetBBFI()->Size())
152  {
153  td_mblf->SetAssemblyLevel(_assembly_level);
154  td_mblf->Assemble();
155  // Register mixed bilinear forms associated with a single trial variable
156  // for the current test variable
157  test_td_mblfs->Register(trial_var_name, td_mblf);
158  }
159  }
160  }
161  // Register all mixed bilinear forms associated with a single test variable
162  _td_mblfs.Register(test_var_name, test_td_mblfs);
163  }
164 }
165 
166 void
168 {
169  // Register non-linear Action forms
170  for (const auto i : index_range(_test_var_names))
171  {
172  auto test_var_name = _test_var_names.at(i);
173  _nlfs.Register(test_var_name, std::make_shared<mfem::ParNonlinearForm>(_test_pfespaces.at(i)));
174  // Apply kernels
175  auto nlf = _nlfs.GetShared(test_var_name);
176  nlf->SetEssentialTrueDofs(_ess_tdof_lists.at(i));
177  ApplyDomainNLFIntegrators(test_var_name, nlf, _kernels_map, _dt);
178  ApplyBoundaryNLFIntegrators(test_var_name, nlf, _integrated_bc_map, _dt);
179  }
180 }
181 
182 void
184 {
185  for (const auto & test_var_name : _test_var_names)
186  {
187  auto & lf = *_lfs.Get(test_var_name) *= _dt;
188  for (const auto & eliminated_var_name : _eliminated_var_names)
189  if (eliminated_var_name == test_var_name)
190  {
191  // if implicit, add contribution to linear form from terms involving state
192  // The AddMult method in mfem::BilinearForm is not defined for non-legacy assembly
193  mfem::Vector lf_prev(lf.Size());
194  auto & td_blf = *_td_blfs.Get(test_var_name);
195  td_blf.Mult(*_eliminated_variables.Get(test_var_name), lf_prev);
196  lf += lf_prev;
197  }
198  else if (_td_mblfs.Has(test_var_name) &&
199  _td_mblfs.Get(test_var_name)->Has(eliminated_var_name))
200  {
201  auto & td_mblf = *_td_mblfs.Get(test_var_name)->Get(eliminated_var_name);
202  td_mblf.AddMult(*_eliminated_variables.Get(eliminated_var_name), lf);
203  }
204  }
205  // Eliminate contributions from other coupled variables.
207 }
208 
209 } // namespace Moose::MFEM
210 
211 #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.
virtual void AddKernel(std::shared_ptr< MFEMKernel > kernel) override
Add kernels.
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.
bool Has(const std::string &field_name) const
Predicate to check if a field is registered with name field_name.
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
bool isTimeDerivative(const std::string &time_derivative_var_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.
NamedFieldsMap< mfem::ParNonlinearForm > _nlfs
Moose::MFEM::GridFunctions _eliminated_variables
Pointers to coupled variables not part of the reduced EquationSystem.
Lightweight adaptor over a std::map relating names of GridFunctions with the name of their time deriv...
const std::string & getTimeIntegralName(const std::string &time_derivative_var_name) const
std::vector< mfem::Array< int > > _ess_tdof_lists
Moose::MFEM::NamedFieldsMap< Moose::MFEM::NamedFieldsMap< mfem::ParMixedBilinearForm > > _td_mblfs
mfem::AssemblyLevel _assembly_level
std::vector< mfem::ParFiniteElementSpace * > _test_pfespaces
Pointers to finite element spaces associated with test variables.
std::vector< std::string > _trial_var_names
Subset of _coupled_var_names of all variables corresponding to gridfunctions with degrees of freedom ...
virtual void BuildMixedBilinearForms() override
Build mixed bilinear forms (off-diagonal Jacobian contributions)
T * Get(const std::string &field_name) const
Returns a non-owning pointer to the field. This is guaranteed to return a non-null pointer...
virtual void EliminateCoupledVariables() override
Perform trivial eliminations of coupled variables lacking corresponding test variables.
std::shared_ptr< T > GetShared(const std::string &field_name) const
Returns a shared pointer to the field. This is guaranteed to return a non-null shared pointer...
NamedFieldsMap< NamedFieldsMap< std::vector< std::shared_ptr< MFEMKernel > > > > _kernels_map
Arrays to store kernels to act on each component of weak form.
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.
std::vector< std::string > _coupled_var_names
Names of all trial variables of kernels and boundary conditions added to this EquationSystem.
void Register(const std::string &field_name, FieldArgs &&... args)
Construct new field with name field_name and register.
Moose::MFEM::NamedFieldsMap< mfem::ParBilinearForm > _td_blfs
Containers to store contributions to weak form of the form (F du/dt, v)
NamedFieldsMap< mfem::ParLinearForm > _lfs
const Moose::MFEM::TimeDerivativeMap & _time_derivative_map
Map between variable names and their time derivatives.
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...
Utilities for converting between vector(s) of libMesh Points and MFEM Vector(s).
virtual void BuildBilinearForms() override
Build bilinear forms (diagonal Jacobian contributions)
virtual void AddEliminatedVariableNameIfMissing(const std::string &eliminated_var_name)
Add eliminated variable to EquationSystem.
virtual void BuildNonlinearForms() override
Build non-linear action forms.
T & GetRef(const std::string &field_name) const
Returns a reference to a field.
auto index_range(const T &sizable)