https://mooseframework.inl.gov
MFEMProblem.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 
12 #include "MFEMProblem.h"
13 #include "MFEMVariable.h"
14 #include "MFEMIndicator.h"
15 #include "MFEMSubMesh.h"
16 #include "MFEMFunctorMaterial.h"
17 #include "MFEMExecutedObject.h"
18 #include "MFEMVectorUtils.h"
19 #include "libmesh/string_to_enum.h"
20 
21 #include <vector>
22 #include <algorithm>
23 #include <map>
24 #include <set>
25 #include <deque>
26 #include <sstream>
27 
28 registerMooseObject("MooseApp", MFEMProblem);
29 
32 {
34  params.addClassDescription("Problem type for building and solving the finite element problem "
35  "using the MFEM finite element library.");
36  MooseEnum numeric_types("real complex", "real");
37  params.addParam<MooseEnum>("numeric_type", numeric_types, "Number type used for the problem");
38 
39  return params;
40 }
41 
43  : ExternalProblem(params), _num_type{static_cast<int>(getParam<MooseEnum>("numeric_type"))}
44 {
45  // Initialise Hypre for all MFEM problems.
46  mfem::Hypre::Init();
47  // Disable multithreading for all MFEM problems (including any libMesh or MFEM subapps).
49 #ifdef LIBMESH_HAVE_OPENMP
50  omp_set_num_threads(1);
51 #endif
52  setMesh();
53 }
54 
55 void
57 {
59 
60  // MFEM indicators create their estimators during addIndicator(); markers still need an explicit
61  // setup pass because they are no longer initialized through the libMesh/MOOSE user-object path.
62  std::vector<MFEMRefinementMarker *> markers;
63  theWarehouse().query().condition<AttribSystem>("Marker").queryInto(markers);
64  for (auto marker : markers)
65  marker->initialSetup();
66 }
67 
68 void
70 {
71  setCurrentExecuteOnFlag(exec_type);
72  executeMFEMObjects(exec_type);
73 
74  ExternalProblem::execute(exec_type);
75 }
76 
77 void
79 {
80  auto pmesh = mesh().getMFEMParMeshPtr();
81  getProblemData().pmesh = pmesh;
82  getProblemData().comm = pmesh->GetComm();
83  getProblemData().num_procs = pmesh->GetNRanks();
84  getProblemData().myid = pmesh->GetMyRank();
85 }
86 
87 void
88 MFEMProblem::addMFEMPreconditioner(const std::string & user_object_name,
89  const std::string & name,
90  InputParameters & parameters)
91 {
92  addObject<Moose::MFEM::SolverBase>(user_object_name, name, parameters);
93 }
94 
95 void
96 MFEMProblem::addIndicator(const std::string & user_object_name,
97  const std::string & name,
98  InputParameters & parameters)
99 {
100  auto estimator = addObject<MFEMIndicator>(user_object_name, name, parameters).front();
101 
102  // construct the estimator itself
103  estimator->createEstimator();
104 }
105 
106 void
107 MFEMProblem::addMarker(const std::string & user_object_name,
108  const std::string & name,
109  InputParameters & parameters)
110 {
112  addObject<MFEMRefinementMarker>(user_object_name, name, parameters).front();
113 }
114 
115 void
116 MFEMProblem::addMFEMSolver(const std::string & user_object_name,
117  const std::string & name,
118  InputParameters & parameters)
119 {
120  auto object = addObject<Moose::MFEM::SolverBase>(user_object_name, name, parameters).front();
121  auto & problem_data = getProblemData();
122 
123  if (auto lin_solver = std::dynamic_pointer_cast<Moose::MFEM::LinearSolverBase>(object))
124  {
125  if (problem_data.jacobian_solver)
126  mooseError("Multiple linear solvers provided. '",
127  problem_data.jacobian_solver->name(),
128  "' and '",
129  lin_solver->name(),
130  "'");
131  problem_data.jacobian_solver = lin_solver;
132  }
133  else if (auto nonlinear_solver =
134  std::dynamic_pointer_cast<Moose::MFEM::NonlinearSolverBase>(object);
135  nonlinear_solver)
136  {
137  if (problem_data.nonlinear_solver)
138  mooseError("Multiple nonlinear solvers provided. '",
139  problem_data.nonlinear_solver->name(),
140  "' and '",
141  nonlinear_solver->name(),
142  "'");
143  problem_data.nonlinear_solver = nonlinear_solver;
144  }
145  else
146  mooseError(
147  "Unsupported MFEM solver object type '", user_object_name, "' for solver '", name, "'.");
148 }
149 
150 void
151 MFEMProblem::addBoundaryCondition(const std::string & bc_name,
152  const std::string & name,
153  InputParameters & parameters)
154 {
155  auto bc = addObject<MFEMBoundaryCondition>(bc_name, name, parameters).front();
156  const auto & mfem_bc = *bc;
157 
158  if (dynamic_cast<const MFEMIntegratedBC *>(&mfem_bc))
159  {
160  auto integrated_bc = std::dynamic_pointer_cast<MFEMIntegratedBC>(bc);
161  auto eqsys =
163  if (eqsys)
164  eqsys->AddIntegratedBC(std::move(integrated_bc));
165  else
166  mooseError("Cannot add integrated BC with name '" + name +
167  "' because there is no corresponding equation system.");
168  }
169  else if (dynamic_cast<const MFEMComplexIntegratedBC *>(&mfem_bc))
170  {
171  auto integrated_bc = std::dynamic_pointer_cast<MFEMComplexIntegratedBC>(bc);
172  auto eqsys =
174  if (eqsys)
175  eqsys->AddComplexIntegratedBC(std::move(integrated_bc));
176  else
177  mooseError("Cannot add complex integrated BC with name '" + name +
178  "' because there is no corresponding equation system.");
179  }
180  else if (dynamic_cast<const MFEMComplexEssentialBC *>(&mfem_bc))
181  {
182  auto essential_bc = std::dynamic_pointer_cast<MFEMComplexEssentialBC>(bc);
183  auto eqsys =
185  if (eqsys)
186  eqsys->AddComplexEssentialBCs(std::move(essential_bc));
187  else
188  mooseError("Cannot add boundary condition with name '" + name +
189  "' because there is no corresponding equation system.");
190  }
191  else if (dynamic_cast<const MFEMEssentialBC *>(&mfem_bc))
192  {
193  auto essential_bc = std::dynamic_pointer_cast<MFEMEssentialBC>(bc);
194  auto eqsys =
196  if (eqsys)
197  eqsys->AddEssentialBC(std::move(essential_bc));
198  else
199  mooseError("Cannot add boundary condition with name '" + name +
200  "' because there is no corresponding equation system.");
201  }
202  else
203  {
204  mooseError("Unsupported bc of type '", bc_name, "' and name '", name, "' detected.");
205  }
206 }
207 
208 void
209 MFEMProblem::addMaterial(const std::string &, const std::string &, InputParameters &)
210 {
211  mooseError(
212  "MFEM materials must be added through the 'FunctorMaterials' block and not 'Materials'");
213 }
214 
215 void
216 MFEMProblem::addFunctorMaterial(const std::string & material_name,
217  const std::string & name,
218  InputParameters & parameters)
219 {
220  addObject<MFEMFunctorMaterial>(material_name, name, parameters);
221 }
222 
223 void
224 MFEMProblem::addFESpace(const std::string & type,
225  const std::string & name,
226  InputParameters & parameters)
227 {
228  auto & mfem_fespace = *addObject<MFEMFESpace>(type, name, parameters).front();
229 
230  // Register fespace and associated fe collection.
231  getProblemData().fecs.Register(name, mfem_fespace.getFEC());
232  getProblemData().fespaces.Register(name, mfem_fespace.getFESpace());
233 }
234 
235 void
236 MFEMProblem::addVariable(const std::string & var_type,
237  const std::string & var_name,
238  InputParameters & parameters)
239 {
240  addGridFunction(var_type, var_name, parameters);
241  // MOOSE variables store DoFs for the trial variable and its time derivatives up to second order;
242  // MFEM GridFunctions store data for only one set of DoFs each, so we must add additional
243  // GridFunctions for time derivatives.
244  if (isTransient())
245  {
246  const auto time_derivative_var_name =
247  getMFEMObject<MFEMVariable>("MooseVariableBase", var_name).getTimeDerivativeName();
249  time_derivative_var_name);
250  addGridFunction(var_type, time_derivative_var_name, parameters);
251  }
252 }
253 
254 void
255 MFEMProblem::addGridFunction(const std::string & var_type,
256  const std::string & var_name,
257  InputParameters & parameters)
258 {
259 
260  if (var_type == "MFEMVariable" || var_type == "MFEMComplexVariable")
261  {
262  // Add MFEM variable directly.
263  if (var_type == "MFEMComplexVariable")
264  addObject<MFEMComplexVariable>(var_type, var_name, parameters);
265  else
266  addObject<MFEMVariable>(var_type, var_name, parameters);
267  }
268  else
269  {
270  // Add MOOSE variable.
271  ExternalProblem::addVariable(var_type, var_name, parameters);
272 
273  // Add MFEM variable indirectly ("gridfunction").
275  addObject<MFEMVariable>("MFEMVariable", var_name, mfem_variable_params);
276  }
277 
278  // Register gridfunction.
279  if (var_type == "MFEMComplexVariable")
280  {
281  MFEMComplexVariable & mfem_variable =
282  getMFEMObject<MFEMComplexVariable>("MooseVariableBase", var_name);
284  mfem_variable.declareCoefficients();
285  }
286  else // must be real, but may have been set up indirectly from a MOOSE variable
287  {
288  MFEMVariable & mfem_variable = getMFEMObject<MFEMVariable>("MooseVariableBase", var_name);
289  getProblemData().gridfunctions.Register(var_name, mfem_variable.getGridFunction());
290  mfem_variable.declareCoefficients();
291  }
292 }
293 
294 void
295 MFEMProblem::addAuxVariable(const std::string & var_type,
296  const std::string & var_name,
297  InputParameters & parameters)
298 {
299  // We handle MFEM AuxVariables just like MFEM Variables, except
300  // we do not add additional GridFunctions for time derivatives.
301  addGridFunction(var_type, var_name, parameters);
302 }
303 
304 void
305 MFEMProblem::addAuxKernel(const std::string & kernel_name,
306  const std::string & name,
307  InputParameters & parameters)
308 {
309  addObject<MFEMExecutedObject>(kernel_name, name, parameters);
310 }
311 
312 void
313 MFEMProblem::addKernel(const std::string & kernel_name,
314  const std::string & name,
315  InputParameters & parameters)
316 {
317  auto kernel = addObject<MFEMKernel>(kernel_name, name, parameters).front();
318  const auto & kernel_object = *kernel;
319 
320  if (dynamic_cast<const MFEMComplexKernel *>(&kernel_object))
321  {
322  auto complex_kernel = std::dynamic_pointer_cast<MFEMComplexKernel>(kernel);
323  auto eqsys =
325  if (eqsys)
326  eqsys->AddComplexKernel(std::move(complex_kernel));
327  else
328  mooseError("Cannot add complex kernel with name '" + name +
329  "' because there is no corresponding equation system.");
330  }
331  else
332  {
333  auto eqsys =
335  if (eqsys)
336  eqsys->AddKernel(std::move(kernel));
337  else
338  mooseError("Cannot add kernel with name '" + name +
339  "' because there is no corresponding equation system.");
340  }
341 }
342 
343 void
344 MFEMProblem::addRealComponentToKernel(const std::string & kernel_name,
345  const std::string & name,
346  InputParameters & parameters)
347 {
348  auto parent_ptr = std::dynamic_pointer_cast<MFEMComplexKernel>(
349  getMFEMObject<MFEMComplexKernel>("Kernel", name).getSharedPtr());
350  parameters.set<VariableName>("variable") = parent_ptr->getParam<VariableName>("variable");
351  auto kernel_ptr = addObject<MFEMKernel>(kernel_name, name + "_real", parameters).front();
352  parent_ptr->setRealKernel(kernel_ptr);
353 }
354 
355 void
356 MFEMProblem::addImagComponentToKernel(const std::string & kernel_name,
357  const std::string & name,
358  InputParameters & parameters)
359 {
360  auto parent_ptr = std::dynamic_pointer_cast<MFEMComplexKernel>(
361  getMFEMObject<MFEMComplexKernel>("Kernel", name).getSharedPtr());
362  parameters.set<VariableName>("variable") = parent_ptr->getParam<VariableName>("variable");
363  auto kernel_ptr = addObject<MFEMKernel>(kernel_name, name + "_imag", parameters).front();
364  parent_ptr->setImagKernel(kernel_ptr);
365 }
366 
367 void
368 MFEMProblem::addRealComponentToBC(const std::string & kernel_name,
369  const std::string & name,
370  InputParameters & parameters)
371 {
373  getMFEMObject<MFEMComplexIntegratedBC>("BoundaryCondition", name).getSharedPtr());
374  parameters.set<VariableName>("variable") = parent_ptr->getParam<VariableName>("variable");
375  parameters.set<std::vector<BoundaryName>>("boundary") =
376  parent_ptr->getParam<std::vector<BoundaryName>>("boundary");
378  addObject<MFEMBoundaryCondition>(kernel_name, name + "_real", parameters).front());
379  parent_ptr->setRealBC(bc_ptr);
380 }
381 
382 void
383 MFEMProblem::addImagComponentToBC(const std::string & kernel_name,
384  const std::string & name,
385  InputParameters & parameters)
386 {
388  getMFEMObject<MFEMComplexIntegratedBC>("BoundaryCondition", name).getSharedPtr());
389  parameters.set<VariableName>("variable") = parent_ptr->getParam<VariableName>("variable");
390  parameters.set<std::vector<BoundaryName>>("boundary") =
391  parent_ptr->getParam<std::vector<BoundaryName>>("boundary");
393  addObject<MFEMBoundaryCondition>(kernel_name, name + "_imag", parameters).front());
394  parent_ptr->setImagBC(bc_ptr);
395 }
396 
397 int
398 vectorFunctionDim(const std::string & type, const InputParameters & parameters)
399 {
400  if (parameters.isParamSetByUser("expression_z"))
401  return 3;
402  if (parameters.isParamSetByUser("expression_y") || type == "LevelSetOlssonVortex")
403  return 2;
404  if (parameters.isParamSetByUser("expression_x"))
405  return 1;
406 
407  return 3;
408 }
409 
410 const std::vector<std::string> SCALAR_FUNCS = {"Axisymmetric2D3DSolutionFunction",
411  "BicubicSplineFunction",
412  "CoarsenedPiecewiseLinear",
413  "CompositeFunction",
414  "ConstantFunction",
415  "ImageFunction",
416  "ParsedFunction",
417  "ParsedGradFunction",
418  "PeriodicFunction",
419  "PiecewiseBilinear",
420  "PiecewiseConstant",
421  "PiecewiseConstantFromCSV",
422  "PiecewiseLinear",
423  "PiecewiseLinearFromVectorPostprocessor",
424  "PiecewiseMultiInterpolation",
425  "PiecewiseMulticonstant",
426  "SolutionFunction",
427  "SplineFunction",
428  "FunctionSeries",
429  "LevelSetOlssonBubble",
430  "LevelSetOlssonPlane",
431  "NearestReporterCoordinatesFunction",
432  "ParameterMeshFunction",
433  "ParsedOptimizationFunction",
434  "FourierNoise",
435  "MovingPlanarFront",
436  "MultiControlDrumFunction",
437  "Grad2ParsedFunction",
438  "GradParsedFunction",
439  "ScaledAbsDifferenceDRLRewardFunction",
440  "CircularAreaHydraulicDiameterFunction",
441  "CosineHumpFunction",
442  "CosineTransitionFunction",
443  "CubicTransitionFunction",
444  "GeneralizedCircumference",
445  "PiecewiseFunction",
446  "TimeRampFunction"},
447  VECTOR_FUNCS = {"ParsedVectorFunction", "LevelSetOlssonVortex"};
448 
449 void
450 MFEMProblem::addFunction(const std::string & type,
451  const std::string & name,
452  InputParameters & parameters)
453 {
455  auto & func = getFunction(name);
456  // FIXME: Do we want to have optimised versions for when functions
457  // are only of space or only of time.
458  if (std::find(SCALAR_FUNCS.begin(), SCALAR_FUNCS.end(), type) != SCALAR_FUNCS.end())
459  {
460  getCoefficients().declareScalar<mfem::FunctionCoefficient>(
461  name,
462  [&func](const mfem::Vector & p, mfem::real_t t) -> mfem::real_t
463  { return func.value(t, Moose::MFEM::libMeshPointFromMFEMVector(p)); });
464  }
465  else if (std::find(VECTOR_FUNCS.begin(), VECTOR_FUNCS.end(), type) != VECTOR_FUNCS.end())
466  {
468  getCoefficients().declareVector<mfem::VectorFunctionCoefficient>(
469  name,
470  dim,
471  [&func, dim](const mfem::Vector & p, mfem::real_t t, mfem::Vector & u)
472  {
473  libMesh::RealVectorValue vector_value =
474  func.vectorValue(t, Moose::MFEM::libMeshPointFromMFEMVector(p));
475  for (int i = 0; i < dim; i++)
476  {
477  u[i] = vector_value(i);
478  }
479  });
480  }
481  else if ("MFEMParsedFunction" != type)
482  {
483  mooseWarning("Could not identify whether function ",
484  type,
485  " is scalar or vector; no MFEM coefficient object created.");
486  }
487 }
488 
489 void
490 MFEMProblem::addPostprocessor(const std::string & type,
491  const std::string & name,
492  InputParameters & parameters)
493 {
494  if (parameters.getSystemAttributeName() == "MFEMExecutedObject")
495  {
496  checkUserObjectNameCollision(name, "Postprocessor");
497  addObject<MFEMExecutedObject>(type, name, parameters);
499  getCoefficients().declareScalar<mfem::FunctionCoefficient>(
500  name, [&val](const mfem::Vector &) -> mfem::real_t { return val; });
501  }
502  else
504 }
505 
506 void
507 MFEMProblem::addVectorPostprocessor(const std::string & type,
508  const std::string & name,
509  InputParameters & parameters)
510 {
511  if (parameters.getSystemAttributeName() == "MFEMExecutedObject")
512  {
513  checkUserObjectNameCollision(name, "VectorPostprocessor");
514  addObject<MFEMExecutedObject>(type, name, parameters);
515  }
516  else
518 }
519 
522 {
523 
524  InputParameters fespace_params = _factory.getValidParams("MFEMGenericFESpace");
525  InputParameters variable_params = _factory.getValidParams("MFEMVariable");
526 
527  const auto family = Utility::string_to_enum<FEFamily>(parameters.get<MooseEnum>("family"));
528  auto order = static_cast<int>(parameters.get<MooseEnum>("order"));
529  const auto dim = mesh().dimension();
530 
531  std::string space;
532  int vdim = 1;
533 
534  switch (family)
535  {
536  case FEFamily::LAGRANGE:
537  space = "H1";
538  break;
539  case FEFamily::NEDELEC_ONE:
540  space = "ND";
541  break;
542  case FEFamily::RAVIART_THOMAS:
543  space = "RT";
544  --order;
545  break;
546  case FEFamily::MONOMIAL:
547  case FEFamily::L2_LAGRANGE:
548  space = "L2";
549  break;
550  case FEFamily::LAGRANGE_VEC:
551  space = "H1";
552  vdim = dim;
553  break;
554  case FEFamily::MONOMIAL_VEC:
555  case FEFamily::L2_LAGRANGE_VEC:
556  space = "L2";
557  vdim = dim;
558  break;
559  default:
560  mooseError("Unable to set MFEM FESpace for MOOSE variable");
561  break;
562  }
563 
564  // Create fespace name. If this already exists, we will reuse this for
565  // the mfem variable ("gridfunction"). If using AMR, this implies all
566  // variables sharing the fespace are affected.
567  const auto fec_name = space + "_" + std::to_string(dim) + "D_P" + std::to_string(order);
568  const auto fes_name = fec_name + "_X" + std::to_string(vdim);
569 
570  // Set all fespace parameters.
571  fespace_params.set<std::string>("fec_name") = fec_name;
572  fespace_params.set<int>("vdim") = vdim;
573 
574  if (!hasMFEMObject("MFEMFESpace", fes_name))
575  addFESpace("MFEMGenericFESpace", fes_name, fespace_params);
576 
577  variable_params.set<MFEMFESpaceName>("fespace") = fes_name;
578 
579  return variable_params;
580 }
581 
582 void
584 {
585  // Displace mesh
586  if (mesh().shouldDisplace())
587  {
588  mesh().displace(static_cast<mfem::GridFunction const &>(*getMeshDisplacementGridFunction()));
589  // TODO: update FESpaces GridFunctions etc for transient solves
590  }
591 }
592 
593 std::optional<std::reference_wrapper<mfem::ParGridFunction const>>
595 {
596  // If C++23 transform were available this would be easier
597  auto const displacement_variable = mesh().getMeshDisplacementVariable();
598  if (displacement_variable)
599  {
600  return *_problem_data.gridfunctions.Get(displacement_variable.value());
601  }
602  else
603  {
604  return std::nullopt;
605  }
606 }
607 
608 void
609 MFEMProblem::rebalanceMesh(mfem::ParMesh & pmesh)
610 {
611  if (pmesh.Nonconforming())
612  {
613  pmesh.Rebalance();
614  updateFESpaces();
616  }
617 }
618 
619 void
621 {
622  for (const auto & fe_space_pair : _problem_data.fespaces)
623  fe_space_pair.second->Update();
624 }
625 
626 void
628 {
629  for (const auto & gridfunction_pair : _problem_data.gridfunctions)
630  gridfunction_pair.second->Update();
631 }
632 
633 std::vector<VariableName>
635 {
637 }
638 
639 MFEMMesh &
641 {
642  mooseAssert(ExternalProblem::mesh().type() == "MFEMMesh",
643  "Please choose the MFEMMesh mesh type for an MFEMProblem\n");
644  return static_cast<MFEMMesh &>(_mesh);
645 }
646 
647 const MFEMMesh &
649 {
650  return const_cast<MFEMProblem *>(this)->mesh();
651 }
652 
653 void
654 MFEMProblem::addSubMesh(const std::string & var_type,
655  const std::string & var_name,
656  InputParameters & parameters)
657 {
658  auto & mfem_submesh = *addObject<MFEMSubMesh>(var_type, var_name, parameters).front();
659  // Register submesh.
660  getProblemData().submeshes.Register(var_name, mfem_submesh.getSubMesh());
661 }
662 
663 void
664 MFEMProblem::addTransfer(const std::string & transfer_name,
665  const std::string & name,
666  InputParameters & parameters)
667 {
668  if (parameters.getBase() == "MFEMSubMeshTransfer")
669  addObject<MFEMExecutedObject>(transfer_name, name, parameters);
670  else
672 }
673 
674 void
675 MFEMProblem::addInitialCondition(const std::string & ic_name,
676  const std::string & name,
677  InputParameters & parameters)
678 {
679  addObject<MFEMExecutedObject>(ic_name, name, parameters);
680 }
681 
682 void
684 {
685  std::vector<MFEMExecutedObject *> objects;
686  theWarehouse()
687  .query()
688  .condition<AttribSystem>("MFEMExecutedObject")
689  .condition<AttribExecOns>(exec_type)
690  .condition<AttribThread>(0)
691  .queryInto(objects);
692 
693  std::map<std::string, const MFEMExecutedObject *> suppliers;
694  for (auto * const object : objects)
695  for (const auto & item : object->getSuppliedItems())
696  {
697  const auto [it, inserted] = suppliers.emplace(item, object);
698  if (!inserted && it->second != object)
699  mooseError("MFEM executed-object dependency ambiguity on ",
700  exec_type,
701  ": both '",
702  it->second->name(),
703  "' and '",
704  object->name(),
705  "' supply '",
706  item,
707  "'.");
708  }
709 
710  for (auto * const object : objects)
711  {
712  object->initialize();
713  object->execute();
714  object->finalize();
715 
716  if (auto * const pp = dynamic_cast<const Postprocessor *>(object))
717  {
718  _reporter_data.finalize(pp->PPName());
719  setPostprocessorValueByName(pp->PPName(), pp->getValue());
720  }
721 
722  if (auto * const vpp = dynamic_cast<VectorPostprocessor *>(object))
723  _reporter_data.finalize(vpp->PPName());
724  }
725 }
726 
727 std::string
728 MFEMProblem::solverTypeString(const unsigned int libmesh_dbg_var(solver_sys_num))
729 {
730  mooseAssert(solver_sys_num == 0, "No support for multi-system with MFEM right now");
731 
732  std::vector<std::string> solvers;
733 
734  if (getProblemData().nonlinear_solver)
735  solvers.push_back(MooseUtils::prettyCppType(getProblemData().nonlinear_solver.get()));
736 
738  {
739  solvers.push_back(MooseUtils::prettyCppType(getProblemData().jacobian_solver.get()));
740  if (const auto * prec = getProblemData().jacobian_solver->GetPreconditioner())
741  solvers.push_back(MooseUtils::prettyCppType(prec));
742  }
743 
744  return solvers.empty() ? "None" : MooseUtils::stringJoin(solvers);
745 }
746 
747 bool
748 MFEMProblem::hasMFEMObject(const std::string & system, const std::string & name) const
749 {
750  std::vector<MooseObject *> objs;
751  theWarehouse()
752  .query()
753  .condition<AttribSystem>(system)
754  .condition<AttribThread>(0)
755  .condition<AttribName>(name)
756  .queryInto(objs);
757  return !objs.empty();
758 }
759 
760 #endif
std::shared_ptr< mfem::ParMesh > pmesh
void addGridFunction(const std::string &var_type, const std::string &var_name, InputParameters &parameters)
Adds one MFEM GridFunction to be used in the MFEM solve.
Definition: MFEMProblem.C:255
Constructs and stores an mfem::ParComplexGridFunction object.
std::shared_ptr< mfem::ParComplexGridFunction > getComplexGridFunction() const
Returns a shared pointer to the constructed gridfunction.
void addMarker(const std::string &type, const std::string &name, InputParameters &parameters) override
Override of FEProblemBase::addMarker.
Definition: MFEMProblem.C:107
void addMFEMPreconditioner(const std::string &user_object_name, const std::string &name, InputParameters &parameters)
Method called in AddMFEMPreconditionerAction which will create the solver.
Definition: MFEMProblem.C:88
virtual void addTransfer(const std::string &transfer_name, const std::string &name, InputParameters &parameters)
Add a Transfer to the problem.
KOKKOS_INLINE_FUNCTION const T * find(const T &target, const T *const begin, const T *const end)
Find a value in an array.
Definition: KokkosUtils.h:40
unsigned int dimension() const override
Returns MeshBase::mesh_dimension(), (not MeshBase::spatial_dimension()!) of the underlying libMesh me...
Definition: MFEMMesh.h:72
Factory & _factory
The Factory for building objects.
Definition: SubProblem.h:1054
libMesh::Point libMeshPointFromMFEMVector(const mfem::Vector &vec)
Convert an MFEM position vector to a libMesh::Point.
virtual void AddKernel(std::shared_ptr< MFEMKernel > kernel)
Add kernels.
void addRealComponentToBC(const std::string &kernel_name, const std::string &name, InputParameters &parameters)
Adds a real component BC to the parent MFEMComplexIntegratedBC.
Definition: MFEMProblem.C:368
Moose::MFEM::ComplexGridFunctions cmplx_gridfunctions
MFEMProblemData & getProblemData()
Method to get the current MFEMProblemData object storing the current data specifying the FE problem...
Definition: MFEMProblem.h:254
const std::string & name() const
Definition: MooseEnumItem.h:35
const std::vector< std::string > SCALAR_FUNCS
Definition: MFEMProblem.C:410
void addImagComponentToBC(const std::string &kernel_name, const std::string &name, InputParameters &parameters)
Adds an imaginary component BC to the parent MFEMComplexIntegratedBC.
Definition: MFEMProblem.C:383
void setPostprocessorValueByName(const PostprocessorName &name, const PostprocessorValue &value, std::size_t t_index=0)
Set the value of a PostprocessorValue.
void addPostprocessor(const std::string &type, const std::string &name, InputParameters &parameters) override
Override of ExternalProblem::addPostprocessor.
Definition: MFEMProblem.C:490
std::vector< std::pair< R1, R2 > > get(const std::string &param1, const std::string &param2) const
Combine two vector parameters into a single vector of pairs.
std::optional< std::reference_wrapper< std::string const > > getMeshDisplacementVariable() const
Returns an optional reference to displacement variable name.
Definition: MFEMMesh.h:60
void addFunction(const std::string &type, const std::string &name, InputParameters &parameters) override
Override of ExternalProblem::addFunction.
Definition: MFEMProblem.C:450
InputParameters addMFEMFESpaceFromMOOSEVariable(InputParameters &moosevar_params)
Method used to get an mfem FEC depending on the variable family specified in the input file...
Definition: MFEMProblem.C:521
static InputParameters validParams()
Return the input parameters used to construct an MFEM problem.
Definition: MFEMProblem.C:31
virtual MFEMMesh & mesh() override
Overwritten mesh() method from base MooseMesh to retrieve the correct mesh type, in this case MFEMMes...
Definition: MFEMProblem.C:640
const InputParameters & parameters() const
Get the parameters of the object.
Definition: MooseBase.h:131
registerMooseObject("MooseApp", MFEMProblem)
virtual void addVariable(const std::string &var_type, const std::string &var_name, InputParameters &parameters) override
Override of ExternalProblem::addVariable.
Definition: MFEMProblem.C:236
T & set(const std::string &name, bool quiet_mode=false)
Returns a writable reference to the named parameters.
InputParameters getValidParams(const std::string &name) const
Get valid parameters for the object.
Definition: Factory.C:68
static InputParameters validParams()
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
std::shared_ptr< Moose::MFEM::LinearSolverBase > jacobian_solver
Class to store weak form components (bilinear and linear forms, and optionally mixed and nonlinear fo...
void executeMFEMObjects(const ExecFlagType &exec_type)
Execute MFEM executed objects scheduled on the supplied execute flag.
Definition: MFEMProblem.C:683
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
Definition: Moose.h:163
std::string solverTypeString(unsigned int solver_sys_num) override
Return solver type as a human readable string.
Definition: MFEMProblem.C:728
virtual void AddEssentialBC(std::shared_ptr< MFEMEssentialBC > bc)
Add BC associated with essentially constrained DoFs on boundaries.
std::unique_ptr< T_DEST, T_DELETER > dynamic_pointer_cast(std::unique_ptr< T_SRC, T_DELETER > &src)
These are reworked from https://stackoverflow.com/a/11003103.
std::shared_ptr< MooseObject > getSharedPtr()
Get another shared pointer to this object that has the same ownership group.
Definition: MooseObject.C:70
int vectorFunctionDim(const std::string &type, const InputParameters &parameters)
Definition: MFEMProblem.C:398
void setCurrentExecuteOnFlag(const ExecFlagType &)
void displaceMesh()
Displace the mesh, if mesh displacement is enabled.
Definition: MFEMProblem.C:583
MFEMProblemData _problem_data
Aggregated MFEM-side state for meshes, spaces, variables, coefficients, and solvers.
Definition: MFEMProblem.h:367
const std::string & getBase() const
Moose::MFEM::FESpaces fespaces
Moose::MFEM::SubMeshes submeshes
Constructs and stores an mfem::ParGridFunction object.
Definition: MFEMVariable.h:20
Moose::MFEM::FECollections fecs
bool hasMFEMObject(const std::string &system, const std::string &name) const
Determine whether an MFEM object with the supplied system and name exists.
Definition: MFEMProblem.C:748
void AddComplexEssentialBCs(std::shared_ptr< MFEMComplexEssentialBC > bc)
Add complex essential BCs.
void checkUserObjectNameCollision(const std::string &name, const std::string &type) const
Check for name collision between different user objects.
virtual Function & getFunction(const std::string &name, const THREAD_ID tid=0)
virtual void addPostprocessor(const std::string &pp_name, const std::string &name, InputParameters &parameters)
void mooseWarning(Args &&... args) const
virtual void execute(const ExecFlagType &exec_type)
Convenience function for performing execution of MOOSE systems.
void rebalanceMesh(mfem::ParMesh &pmesh)
Rebalance the (necessarily nonconforming) mesh.
Definition: MFEMProblem.C:609
ReporterData _reporter_data
const std::string & name() const
Get the name of the class.
Definition: MooseBase.h:103
mfem::Coefficient & declareScalar(const std::string &name, const std::string &existing_or_literal)
Declare an alias to an existing scalar coefficient or, if it does not exist, try interpreting the nam...
void addTimeDerivativeAssociation(const std::string &var_name, const std::string &time_derivative_var_name)
TheWarehouse & theWarehouse() const
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...
mfem::VectorCoefficient & declareVector(const std::string &name, const std::string &existing_or_literal)
Declare an alias to an existing vector coefficientor or, if it does not exist, try interpreting the n...
virtual void addFunction(const std::string &type, const std::string &name, InputParameters &parameters)
Real PostprocessorValue
various MOOSE typedefs
Definition: MooseTypes.h:230
virtual void addVectorPostprocessor(const std::string &pp_name, const std::string &name, InputParameters &parameters)
Moose::MFEM::CoefficientManager & getCoefficients()
Method to get the PropertyManager object for storing material properties and converting them to MFEM ...
Definition: MFEMProblem.h:248
MooseMesh & _mesh
void addMaterial(const std::string &material_name, const std::string &name, InputParameters &parameters) override
Definition: MFEMProblem.C:209
virtual void initialSetup() override
Definition: MFEMProblem.C:56
const std::string & type() const
Get the type of this class.
Definition: MooseBase.h:93
void initialSetup() override
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:54
void setMesh()
Set the mesh used by MFEM.
Definition: MFEMProblem.C:78
virtual const SystemBase & systemBaseAuxiliary() const override
Return the auxiliary system object as a base class reference.
virtual void addMFEMSolver(const std::string &user_object_name, const std::string &name, InputParameters &parameters)
Method called in AddMFEMSolverAction which will create the solver.
Definition: MFEMProblem.C:116
void finalize(const std::string &object_name)
Helper function for performing post calculation actions via the ReporterContext objects.
Definition: ReporterData.C:48
void addAuxKernel(const std::string &kernel_name, const std::string &name, InputParameters &parameters) override
Override of ExternalProblem::addAuxKernel.
Definition: MFEMProblem.C:305
std::shared_ptr< mfem::ParMesh > getMFEMParMeshPtr()
Copy a shared_ptr to the mfem::ParMesh object.
Definition: MFEMMesh.h:40
std::shared_ptr< mfem::ParGridFunction > getGridFunction() const
Returns a shared pointer to the constructed gridfunction.
Definition: MFEMVariable.h:28
const PostprocessorValue & getPostprocessorValueByName(const PostprocessorName &name, std::size_t t_index=0) const
Get a read-only reference to the value associated with a Postprocessor that exists.
std::shared_ptr< Moose::MFEM::EquationSystem > eqn_system
void AddComplexIntegratedBC(std::shared_ptr< MFEMComplexIntegratedBC > bc)
Add complex integrated BCs.
virtual void addVariable(const std::string &var_type, const std::string &var_name, InputParameters &params)
Canonical method for adding a non-linear variable.
std::shared_ptr< MFEMRefinementMarker > refiner
bool isParamSetByUser(const std::string &name) const
Method returns true if the parameter was set by the user.
void Register(const std::string &field_name, FieldArgs &&... args)
Construct new field with name field_name and register.
MFEMProblem(const InputParameters &params)
Construct an MFEM problem from the supplied parameters.
Definition: MFEMProblem.C:42
void displace(mfem::GridFunction const &displacement)
Displace the nodes of the mesh by the given displacement.
Definition: MFEMMesh.C:99
void addFunctorMaterial(const std::string &material_name, const std::string &name, InputParameters &parameters) override
Definition: MFEMProblem.C:216
Class for containing MooseEnum item information.
Definition: MooseEnumItem.h:18
void addFESpace(const std::string &type, const std::string &name, InputParameters &parameters)
Add an MFEM FESpace to the problem.
Definition: MFEMProblem.C:224
void updateGridFunctions()
Calls Update() on all gridfunctions.
Definition: MFEMProblem.C:627
void addIndicator(const std::string &type, const std::string &name, InputParameters &parameters) override
Override of FEProblemBase::addIndicator.
Definition: MFEMProblem.C:96
MFEMMesh inherits a MOOSE mesh class which allows us to work with other MOOSE objects.
Definition: MFEMMesh.h:20
virtual std::vector< VariableName > getAuxVariableNames()
Returns all the variable names from the auxiliary system base.
Definition: MFEMProblem.C:634
Query query()
query creates and returns an initialized a query object for querying objects from the warehouse...
Definition: TheWarehouse.h:467
void addBoundaryCondition(const std::string &bc_name, const std::string &name, InputParameters &parameters) override
Definition: MFEMProblem.C:151
const std::vector< std::string > VECTOR_FUNCS
Definition: MFEMProblem.C:447
virtual MooseMesh & mesh() override
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type and optionally a file path to the top-level block p...
Definition: MooseBase.h:281
const std::vector< VariableName > & getVariableNames() const
Definition: SystemBase.h:863
void updateFESpaces()
Calls Update() on all FE spaces.
Definition: MFEMProblem.C:620
void addImagComponentToKernel(const std::string &kernel_name, const std::string &name, InputParameters &parameters)
Adds an imaginary component kernel to the parent MFEMComplexKernel.
Definition: MFEMProblem.C:356
void addClassDescription(const std::string &doc_string)
This method adds a description of the class that will be displayed in the input file syntax dump...
const std::string & getSystemAttributeName() const
Get the system attribute name if it was registered.
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an optional parameter and a documentation string to the InputParameters object...
QueryCache & condition(Args &&... args)
Adds a new condition to the query.
Definition: TheWarehouse.h:285
void addVectorPostprocessor(const std::string &type, const std::string &name, InputParameters &parameters) override
Add a vector postprocessor and register its vectors with the MFEM execution system.
Definition: MFEMProblem.C:507
void addKernel(const std::string &kernel_name, const std::string &name, InputParameters &parameters) override
Override of ExternalProblem::addKernel.
Definition: MFEMProblem.C:313
void declareCoefficients()
Declare default coefficients associated with this gridfunction.
Definition: MFEMVariable.C:60
virtual bool isTransient() const override
std::optional< std::reference_wrapper< mfem::ParGridFunction const > > getMeshDisplacementGridFunction()
Returns optional reference to the displacement GridFunction to apply to nodes.
Definition: MFEMProblem.C:594
Moose::MFEM::GridFunctions gridfunctions
void addAuxVariable(const std::string &var_type, const std::string &var_name, InputParameters &parameters) override
Override of ExternalProblem::addAuxVariable.
Definition: MFEMProblem.C:295
std::string stringJoin(const std::vector< std::string > &values, const std::string &separator=" ")
Concatenates value into a single string separated by separator.
void addRealComponentToKernel(const std::string &kernel_name, const std::string &name, InputParameters &parameters)
Adds a real component kernel to the parent MFEMComplexKernel.
Definition: MFEMProblem.C:344
virtual void AddIntegratedBC(std::shared_ptr< MFEMIntegratedBC > kernel)
void addSubMesh(const std::string &type, const std::string &name, InputParameters &parameters)
Add an MFEM SubMesh to the problem.
Definition: MFEMProblem.C:654
Moose::MFEM::TimeDerivativeMap time_derivative_map
virtual void execute(const ExecFlagType &exec_type) override
Convenience function for performing execution of MOOSE systems.
Definition: MFEMProblem.C:69
std::string prettyCppType(const std::string &cpp_type)
Definition: MooseUtils.C:1140
void addTransfer(const std::string &transfer_name, const std::string &name, InputParameters &parameters) override
Add transfers between MultiApps and/or MFEM SubMeshes.
Definition: MFEMProblem.C:664
void addInitialCondition(const std::string &ic_name, const std::string &name, InputParameters &parameters) override
Add an MFEM initial condition to the problem.
Definition: MFEMProblem.C:675
void AddComplexKernel(std::shared_ptr< MFEMComplexKernel > kernel)
Add complex kernels.