https://mooseframework.inl.gov
EquationSystem.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 MFEM_ENABLED
11 
12 #include "EquationSystem.h"
13 #include "libmesh/int_range.h"
14 
15 namespace Moose::MFEM
16 {
17 
19 
20 void
22 {
23  for (const auto i : make_range(_h_blocks.NumRows()))
24  for (const auto j : make_range(_h_blocks.NumCols()))
25  delete _h_blocks(i, j);
26  _h_blocks.DeleteAll();
27 }
28 
29 bool
30 EquationSystem::VectorContainsName(const std::vector<std::string> & the_vector,
31  const std::string & name) const
32 {
33 
34  auto iter = std::find(the_vector.begin(), the_vector.end(), name);
35 
36  return (iter != the_vector.end());
37 }
38 
39 void
40 EquationSystem::AddTrialVariableNameIfMissing(const std::string & trial_var_name)
41 {
42  if (!VectorContainsName(_trial_var_names, trial_var_name))
43  {
44  _trial_var_names.push_back(trial_var_name);
45  }
46 }
47 
48 void
49 EquationSystem::AddTestVariableNameIfMissing(const std::string & test_var_name)
50 {
51  if (!VectorContainsName(_test_var_names, test_var_name))
52  {
53  _test_var_names.push_back(test_var_name);
54  }
55 }
56 
57 void
58 EquationSystem::AddKernel(std::shared_ptr<MFEMKernel> kernel)
59 {
60  AddTestVariableNameIfMissing(kernel->getTestVariableName());
61  AddTrialVariableNameIfMissing(kernel->getTrialVariableName());
62  auto trial_var_name = kernel->getTrialVariableName();
63  auto test_var_name = kernel->getTestVariableName();
64  if (!_kernels_map.Has(test_var_name))
65  {
66  auto kernel_field_map =
67  std::make_shared<Moose::MFEM::NamedFieldsMap<std::vector<std::shared_ptr<MFEMKernel>>>>();
68  _kernels_map.Register(test_var_name, std::move(kernel_field_map));
69  }
70  // Register new kernels map if not present for the test/trial variable
71  // pair
72  if (!_kernels_map.Get(test_var_name)->Has(trial_var_name))
73  {
74  auto kernels = std::make_shared<std::vector<std::shared_ptr<MFEMKernel>>>();
75  _kernels_map.Get(test_var_name)->Register(trial_var_name, std::move(kernels));
76  }
77  _kernels_map.GetRef(test_var_name).Get(trial_var_name)->push_back(std::move(kernel));
78 }
79 
80 void
81 EquationSystem::AddIntegratedBC(std::shared_ptr<MFEMIntegratedBC> bc)
82 {
83  AddTestVariableNameIfMissing(bc->getTestVariableName());
84  AddTrialVariableNameIfMissing(bc->getTrialVariableName());
85  auto trial_var_name = bc->getTrialVariableName();
86  auto test_var_name = bc->getTestVariableName();
87  if (!_integrated_bc_map.Has(test_var_name))
88  {
89  auto integrated_bc_field_map = std::make_shared<
91  _integrated_bc_map.Register(test_var_name, std::move(integrated_bc_field_map));
92  }
93  // Register new integrated bc map if not present for the test/trial variable
94  // pair
95  if (!_integrated_bc_map.Get(test_var_name)->Has(trial_var_name))
96  {
97  auto bcs = std::make_shared<std::vector<std::shared_ptr<MFEMIntegratedBC>>>();
98  _integrated_bc_map.Get(test_var_name)->Register(trial_var_name, std::move(bcs));
99  }
100  _integrated_bc_map.GetRef(test_var_name).Get(trial_var_name)->push_back(std::move(bc));
101 }
102 
103 void
104 EquationSystem::AddEssentialBC(std::shared_ptr<MFEMEssentialBC> bc)
105 {
106  AddTestVariableNameIfMissing(bc->getTestVariableName());
107  auto test_var_name = bc->getTestVariableName();
108  if (!_essential_bc_map.Has(test_var_name))
109  {
110  auto bcs = std::make_shared<std::vector<std::shared_ptr<MFEMEssentialBC>>>();
111  _essential_bc_map.Register(test_var_name, std::move(bcs));
112  }
113  _essential_bc_map.GetRef(test_var_name).push_back(std::move(bc));
114 }
115 
116 void
118 {
119  _ess_tdof_lists.resize(_test_var_names.size());
120  for (const auto i : index_range(_test_var_names))
121  {
122  auto test_var_name = _test_var_names.at(i);
123  if (!_essential_bc_map.Has(test_var_name))
124  continue;
125 
126  // Set default value of gridfunction used in essential BC. Values
127  // overwritten in applyEssentialBCs
128  mfem::ParGridFunction & trial_gf(*(_xs.at(i)));
129  auto * const pmesh = _test_pfespaces.at(i)->GetParMesh();
130  mooseAssert(pmesh, "parallel mesh is null");
131 
132  auto bcs = _essential_bc_map.GetRef(test_var_name);
133  mfem::Array<int> global_ess_markers(pmesh->bdr_attributes.Max());
134  global_ess_markers = 0;
135  for (auto & bc : bcs)
136  {
137  bc->ApplyBC(trial_gf);
138 
139  mfem::Array<int> ess_bdrs(bc->getBoundaryMarkers());
140  for (auto it = 0; it != pmesh->bdr_attributes.Max(); ++it)
141  {
142  global_ess_markers[it] = std::max(global_ess_markers[it], ess_bdrs[it]);
143  }
144  }
145  trial_gf.FESpace()->GetEssentialTrueDofs(global_ess_markers, _ess_tdof_lists.at(i));
146  }
147 }
148 
149 void
150 EquationSystem::FormLinearSystem(mfem::OperatorHandle & op,
151  mfem::BlockVector & trueX,
152  mfem::BlockVector & trueRHS)
153 {
154 
155  switch (_assembly_level)
156  {
157  case mfem::AssemblyLevel::LEGACY:
158  FormLegacySystem(op, trueX, trueRHS);
159  break;
160  default:
161  mooseAssert(_test_var_names.size() == 1,
162  "Non-legacy assembly is only supported for single-variable systems");
163  mooseAssert(
164  _test_var_names.size() == _trial_var_names.size(),
165  "Non-legacy assembly is only supported for single test and trial variable systems");
166  FormSystem(op, trueX, trueRHS);
167  }
168 }
169 
170 void
171 EquationSystem::FormSystem(mfem::OperatorHandle & op,
172  mfem::BlockVector & trueX,
173  mfem::BlockVector & trueRHS)
174 {
175  auto & test_var_name = _test_var_names.at(0);
176  auto blf = _blfs.Get(test_var_name);
177  auto lf = _lfs.Get(test_var_name);
178  mfem::BlockVector aux_x, aux_rhs;
179  mfem::OperatorPtr aux_a;
180 
181  blf->FormLinearSystem(_ess_tdof_lists.at(0), *(_xs.at(0)), *lf, aux_a, aux_x, aux_rhs);
182 
183  trueX.GetBlock(0) = aux_x;
184  trueRHS.GetBlock(0) = aux_rhs;
185  trueX.SyncFromBlocks();
186  trueRHS.SyncFromBlocks();
187 
188  op.Reset(aux_a.Ptr());
189  aux_a.SetOperatorOwner(false);
190 }
191 
192 void
193 EquationSystem::FormLegacySystem(mfem::OperatorHandle & op,
194  mfem::BlockVector & trueX,
195  mfem::BlockVector & trueRHS)
196 {
197 
198  // Allocate block operator
199  DeleteAllBlocks();
200  _h_blocks.SetSize(_test_var_names.size(), _test_var_names.size());
201  // Form diagonal blocks.
202  for (const auto i : index_range(_test_var_names))
203  {
204  auto & test_var_name = _test_var_names.at(i);
205  auto blf = _blfs.Get(test_var_name);
206  auto lf = _lfs.Get(test_var_name);
207  mfem::Vector aux_x, aux_rhs;
208  mfem::HypreParMatrix * aux_a = new mfem::HypreParMatrix;
209  blf->FormLinearSystem(_ess_tdof_lists.at(i), *(_xs.at(i)), *lf, *aux_a, aux_x, aux_rhs);
210  _h_blocks(i, i) = aux_a;
211  trueX.GetBlock(i) = aux_x;
212  trueRHS.GetBlock(i) = aux_rhs;
213  }
214 
215  // Form off-diagonal blocks
216  for (const auto i : index_range(_test_var_names))
217  {
218  auto test_var_name = _test_var_names.at(i);
219  for (const auto j : index_range(_test_var_names))
220  {
221  auto trial_var_name = _trial_var_names.at(j);
222 
223  mfem::Vector aux_x, aux_rhs;
224  mfem::ParLinearForm aux_lf(_test_pfespaces.at(i));
225  aux_lf = 0.0;
226  if (_mblfs.Has(test_var_name) && _mblfs.Get(test_var_name)->Has(trial_var_name))
227  {
228  auto mblf = _mblfs.Get(test_var_name)->Get(trial_var_name);
229  mfem::HypreParMatrix * aux_a = new mfem::HypreParMatrix;
230  mblf->FormRectangularLinearSystem(_ess_tdof_lists.at(j),
231  _ess_tdof_lists.at(i),
232  *(_xs.at(j)),
233  aux_lf,
234  *aux_a,
235  aux_x,
236  aux_rhs);
237  _h_blocks(i, j) = aux_a;
238  trueRHS.GetBlock(i) += aux_rhs;
239  }
240  }
241  }
242  // Sync memory
243  for (const auto i : index_range(_test_var_names))
244  {
245  trueX.GetBlock(i).SyncAliasMemory(trueX);
246  trueRHS.GetBlock(i).SyncAliasMemory(trueRHS);
247  }
248 
249  // Create monolithic matrix
250  op.Reset(mfem::HypreParMatrixFromBlocks(_h_blocks));
251 }
252 
253 void
254 EquationSystem::BuildJacobian(mfem::BlockVector & trueX, mfem::BlockVector & trueRHS)
255 {
256  height = trueX.Size();
257  width = trueRHS.Size();
258  FormLinearSystem(_jacobian, trueX, trueRHS);
259 }
260 
261 void
262 EquationSystem::Mult(const mfem::Vector & x, mfem::Vector & residual) const
263 {
264  _jacobian->Mult(x, residual);
265  x.HostRead();
266  residual.HostRead();
267 }
268 
269 mfem::Operator &
270 EquationSystem::GetGradient(const mfem::Vector &) const
271 {
272  return *_jacobian;
273 }
274 
275 void
276 EquationSystem::RecoverFEMSolution(mfem::BlockVector & trueX,
277  Moose::MFEM::GridFunctions & gridfunctions)
278 {
279  for (const auto i : index_range(_trial_var_names))
280  {
281  auto & trial_var_name = _trial_var_names.at(i);
282  trueX.GetBlock(i).SyncAliasMemory(trueX);
283  gridfunctions.Get(trial_var_name)->Distribute(&(trueX.GetBlock(i)));
284  }
285 }
286 
287 void
289  const Moose::MFEM::FESpaces & /*fespaces*/,
290  mfem::AssemblyLevel assembly_level)
291 {
292  _assembly_level = assembly_level;
293 
294  for (auto & test_var_name : _test_var_names)
295  {
296  if (!gridfunctions.Has(test_var_name))
297  {
298  MFEM_ABORT("Test variable " << test_var_name
299  << " requested by equation system during initialisation was "
300  "not found in gridfunctions");
301  }
302  // Store pointers to variable FESpaces
303  _test_pfespaces.push_back(gridfunctions.Get(test_var_name)->ParFESpace());
304  // Create auxiliary gridfunctions for applying Dirichlet conditions
305  _xs.emplace_back(
306  std::make_unique<mfem::ParGridFunction>(gridfunctions.Get(test_var_name)->ParFESpace()));
307  _dxdts.emplace_back(
308  std::make_unique<mfem::ParGridFunction>(gridfunctions.Get(test_var_name)->ParFESpace()));
309  _trial_variables.Register(test_var_name, gridfunctions.GetShared(test_var_name));
310  }
311 }
312 
313 void
315 {
316  // Register linear forms
317  for (const auto i : index_range(_test_var_names))
318  {
319  auto test_var_name = _test_var_names.at(i);
320  _lfs.Register(test_var_name, std::make_shared<mfem::ParLinearForm>(_test_pfespaces.at(i)));
321  _lfs.GetRef(test_var_name) = 0.0;
322  }
323  // Apply boundary conditions
325 
326  for (auto & test_var_name : _test_var_names)
327  {
328  // Apply kernels
329  auto lf = _lfs.GetShared(test_var_name);
330  ApplyDomainLFIntegrators(test_var_name, lf, _kernels_map);
332  lf->Assemble();
333  }
334 }
335 
336 void
338 {
339  // Register bilinear forms
340  for (const auto i : index_range(_test_var_names))
341  {
342  auto test_var_name = _test_var_names.at(i);
343  _blfs.Register(test_var_name, std::make_shared<mfem::ParBilinearForm>(_test_pfespaces.at(i)));
344 
345  // Apply kernels
346  auto blf = _blfs.GetShared(test_var_name);
347  blf->SetAssemblyLevel(_assembly_level);
348  ApplyBoundaryBLFIntegrators<mfem::ParBilinearForm>(
349  test_var_name, test_var_name, blf, _integrated_bc_map);
350  ApplyDomainBLFIntegrators<mfem::ParBilinearForm>(
351  test_var_name, test_var_name, blf, _kernels_map);
352  // Assemble
353  blf->Assemble();
354  }
355 }
356 
357 void
359 {
360  // Register mixed bilinear forms. Note that not all combinations may
361  // have a kernel
362 
363  // Create mblf for each test/trial pair
364  for (const auto i : index_range(_test_var_names))
365  {
366  auto test_var_name = _test_var_names.at(i);
367  auto test_mblfs = std::make_shared<Moose::MFEM::NamedFieldsMap<mfem::ParMixedBilinearForm>>();
368  for (const auto j : index_range(_test_var_names))
369  {
370  auto trial_var_name = _trial_var_names.at(j);
371  auto mblf = std::make_shared<mfem::ParMixedBilinearForm>(_test_pfespaces.at(j),
372  _test_pfespaces.at(i));
373  // Register MixedBilinearForm if kernels exist for it, and assemble
374  // kernels
375  if (_kernels_map.Has(test_var_name) && _kernels_map.Get(test_var_name)->Has(trial_var_name) &&
376  test_var_name != trial_var_name)
377  {
378  mblf->SetAssemblyLevel(_assembly_level);
379  // Apply all mixed kernels with this test/trial pair
380  ApplyDomainBLFIntegrators<mfem::ParMixedBilinearForm>(
381  trial_var_name, test_var_name, mblf, _kernels_map);
382  // Assemble mixed bilinear forms
383  mblf->Assemble();
384  // Register mixed bilinear forms associated with a single trial variable
385  // for the current test variable
386  test_mblfs->Register(trial_var_name, mblf);
387  }
388  }
389  // Register all mixed bilinear form sets associated with a single test
390  // variable
391  _mblfs.Register(test_var_name, test_mblfs);
392  }
393 }
394 
395 void
397 {
401 }
402 
404 
405 void
407 {
408  // The TimeDependentEquationSystem operator expects to act on a vector of variable time
409  // derivatives
410  std::string var_time_derivative_name = GetTimeDerivativeName(var_name);
411 
412  if (!VectorContainsName(_trial_var_names, var_time_derivative_name))
413  {
414  _trial_var_names.push_back(var_time_derivative_name);
415  _trial_var_time_derivative_names.push_back(var_time_derivative_name);
416  }
417 }
418 
419 void
421 {
422  if (fabs(dt - _dt_coef.constant) > 1.0e-12 * dt)
423  {
424  _dt_coef.constant = dt;
425  for (auto test_var_name : _test_var_names)
426  {
427  auto blf = _blfs.Get(test_var_name);
428  blf->Update();
429  blf->Assemble();
430  }
431  }
432 }
433 
434 void
435 TimeDependentEquationSystem::AddKernel(std::shared_ptr<MFEMKernel> kernel)
436 {
437  if (kernel->getTrialVariableName() == GetTimeDerivativeName(kernel->getTestVariableName()))
438  {
439  auto trial_var_name = kernel->getTrialVariableName();
440  auto test_var_name = kernel->getTestVariableName();
441  AddTestVariableNameIfMissing(test_var_name);
442  AddTrialVariableNameIfMissing(test_var_name);
443  if (!_td_kernels_map.Has(test_var_name))
444  {
445  auto kernel_field_map =
446  std::make_shared<Moose::MFEM::NamedFieldsMap<std::vector<std::shared_ptr<MFEMKernel>>>>();
447  _td_kernels_map.Register(test_var_name, std::move(kernel_field_map));
448  }
449  // Register new kernels map if not present for the test variable
450  if (!_td_kernels_map.Get(test_var_name)->Has(test_var_name))
451  {
452  auto kernels = std::make_shared<std::vector<std::shared_ptr<MFEMKernel>>>();
453  _td_kernels_map.Get(test_var_name)->Register(test_var_name, std::move(kernels));
454  }
455  _td_kernels_map.GetRef(test_var_name).Get(test_var_name)->push_back(std::move(kernel));
456  }
457  else
458  {
460  }
461 }
462 
463 void
465 {
467 
468  // Build and assemble bilinear forms acting on time derivatives
469  for (const auto i : index_range(_test_var_names))
470  {
471  auto test_var_name = _test_var_names.at(i);
472 
473  _td_blfs.Register(test_var_name,
474  std::make_shared<mfem::ParBilinearForm>(_test_pfespaces.at(i)));
475 
476  // Apply kernels to td_blf
477  auto td_blf = _td_blfs.GetShared(test_var_name);
478  td_blf->SetAssemblyLevel(_assembly_level);
479  ApplyBoundaryBLFIntegrators<mfem::ParBilinearForm>(
480  test_var_name, test_var_name, td_blf, _integrated_bc_map);
481  ApplyDomainBLFIntegrators<mfem::ParBilinearForm>(
482  test_var_name, test_var_name, td_blf, _td_kernels_map);
483 
484  // Recover and scale integrators from blf. This is to apply the dt*du/dt contributions from the
485  // operator on the trial variable in the implicit integration scheme
486  auto blf = _blfs.Get(test_var_name);
487  auto integs = blf->GetDBFI();
488  auto b_integs = blf->GetBBFI();
489  auto markers = blf->GetBBFI_Marker();
490 
491  mfem::SumIntegrator * sum = new mfem::SumIntegrator(false);
492  ScaleIntegrator * scaled_sum = new ScaleIntegrator(sum, _dt_coef.constant, true);
493 
494  for (int i = 0; i < integs->Size(); ++i)
495  {
496  sum->AddIntegrator(*integs[i]);
497  }
498 
499  for (int i = 0; i < b_integs->Size(); ++i)
500  {
501  td_blf->AddBoundaryIntegrator(new ScaleIntegrator(*b_integs[i], _dt_coef.constant, false),
502  *(*markers[i]));
503  }
504 
505  // scaled_sum is owned by td_blf
506  td_blf->AddDomainIntegrator(scaled_sum);
507 
508  // Assemble form
509  td_blf->Assemble();
510  }
511 }
512 
513 void
515  mfem::BlockVector & truedXdt,
516  mfem::BlockVector & trueRHS)
517 {
518 
519  // Allocate block operator
520  DeleteAllBlocks();
521  _h_blocks.SetSize(_test_var_names.size(), _test_var_names.size());
522  // Form diagonal blocks.
523  for (const auto i : index_range(_test_var_names))
524  {
525  auto & test_var_name = _test_var_names.at(i);
526  auto td_blf = _td_blfs.Get(test_var_name);
527  auto blf = _blfs.Get(test_var_name);
528  auto lf = _lfs.Get(test_var_name);
529  // if implicit, add contribution to linear form from terms involving state
530  // variable at previous timestep: {
531  blf->AddMult(*_trial_variables.Get(test_var_name), *lf, -1.0);
532  // }
533  mfem::Vector aux_x, aux_rhs;
534  // Update solution values on Dirichlet values to be in terms of du/dt instead of u
535  mfem::Vector bc_x = *(_xs.at(i).get());
536  bc_x -= *_trial_variables.Get(test_var_name);
537  bc_x /= _dt_coef.constant;
538 
539  // Form linear system for operator acting on vector of du/dt
540  mfem::HypreParMatrix * aux_a = new mfem::HypreParMatrix;
541  td_blf->FormLinearSystem(_ess_tdof_lists.at(i), bc_x, *lf, *aux_a, aux_x, aux_rhs);
542  _h_blocks(i, i) = aux_a;
543  truedXdt.GetBlock(i) = aux_x;
544  trueRHS.GetBlock(i) = aux_rhs;
545  }
546 
547  truedXdt.SyncFromBlocks();
548  trueRHS.SyncFromBlocks();
549 
550  // Create monolithic matrix
551  op.Reset(mfem::HypreParMatrixFromBlocks(_h_blocks));
552 }
553 
554 void
555 TimeDependentEquationSystem::FormSystem(mfem::OperatorHandle & op,
556  mfem::BlockVector & truedXdt,
557  mfem::BlockVector & trueRHS)
558 {
559  auto & test_var_name = _test_var_names.at(0);
560  auto td_blf = _td_blfs.Get(test_var_name);
561  auto blf = _blfs.Get(test_var_name);
562  auto lf = _lfs.Get(test_var_name);
563  // if implicit, add contribution to linear form from terms involving state
564  // variable at previous timestep: {
565 
566  // The AddMult method in mfem::BilinearForm is not defined for non-legacy assembly
567  mfem::Vector lf_prev(lf->Size());
568  blf->Mult(*_trial_variables.Get(test_var_name), lf_prev);
569  *lf -= lf_prev;
570  // }
571  mfem::Vector aux_x, aux_rhs;
572  // Update solution values on Dirichlet values to be in terms of du/dt instead of u
573  mfem::Vector bc_x = *(_xs.at(0).get());
574  bc_x -= *_trial_variables.Get(test_var_name);
575  bc_x /= _dt_coef.constant;
576 
577  // Form linear system for operator acting on vector of du/dt
578  mfem::OperatorPtr aux_a;
579  td_blf->FormLinearSystem(_ess_tdof_lists.at(0), bc_x, *lf, aux_a, aux_x, aux_rhs);
580 
581  truedXdt.GetBlock(0) = aux_x;
582  trueRHS.GetBlock(0) = aux_rhs;
583  truedXdt.SyncFromBlocks();
584  trueRHS.SyncFromBlocks();
585 
586  // Create monolithic matrix
587  op.Reset(aux_a.Ptr());
588  aux_a.SetOperatorOwner(false);
589 }
590 
591 void
593 {
597 }
598 
599 } // namespace Moose::MFEM
600 
601 #endif
std::string name(const ElemQuality q)
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()
bool Has(const std::string &field_name) const
Predicate to check if a field is registered with name field_name.
Moose::MFEM::NamedFieldsMap< Moose::MFEM::NamedFieldsMap< std::vector< std::shared_ptr< MFEMKernel > > > > _td_kernels_map
virtual void FormSystem(mfem::OperatorHandle &op, mfem::BlockVector &truedXdt, mfem::BlockVector &trueRHS) override
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)
std::vector< mfem::Array< int > > _ess_tdof_lists
Lightweight adaptor over an std::map from strings to pointer to T.
mfem::AssemblyLevel _assembly_level
void AddTrialVariableNameIfMissing(const std::string &trial_var_name) override
std::string GetTimeDerivativeName(std::string name)
auto max(const L &left, const R &right)
Moose::MFEM::NamedFieldsMap< std::vector< std::shared_ptr< MFEMEssentialBC > > > _essential_bc_map
std::vector< mfem::ParFiniteElementSpace * > _test_pfespaces
void Mult(const mfem::Vector &u, mfem::Vector &residual) const override
Compute residual y = Mu.
std::vector< std::string > _trial_var_names
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 FormLegacySystem(mfem::OperatorHandle &op, mfem::BlockVector &trueX, mfem::BlockVector &trueRHS)
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...
mfem::OperatorHandle _jacobian
virtual void AddTrialVariableNameIfMissing(const std::string &trial_var_name)
std::vector< std::string > _test_var_names
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()
Integrator which scales its results by a constant value.
mfem::Array2D< const mfem::HypreParMatrix * > _h_blocks
virtual void FormLinearSystem(mfem::OperatorHandle &op, mfem::BlockVector &trueX, mfem::BlockVector &trueRHS)
void Register(const std::string &field_name, FieldArgs &&... args)
Construct new field with name field_name and register.
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
IntRange< T > make_range(T beg, T end)
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
T & GetRef(const std::string &field_name) const
Returns a reference to a field.
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
virtual void AddIntegratedBC(std::shared_ptr< MFEMIntegratedBC > kernel)
auto index_range(const T &sizable)