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<MFEMSolverBase>(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 {
121  addObject<MFEMSolverBase>(user_object_name, name, parameters).front();
122 }
123 
124 void
125 MFEMProblem::addMFEMNonlinearSolver(unsigned int nl_max_its,
126  mfem::real_t nl_abs_tol,
127  mfem::real_t nl_rel_tol,
128  unsigned int print_level)
129 {
130  // TODO: allow users to specify other mfem::IterativeSolvers
131  auto nl_solver = std::make_shared<mfem::NewtonSolver>(getComm());
132 
133  // Defaults to one iteration, without further nonlinear iterations
134  nl_solver->SetRelTol(nl_rel_tol);
135  nl_solver->SetAbsTol(nl_abs_tol);
136  nl_solver->SetMaxIter(nl_max_its);
137  nl_solver->SetPrintLevel(print_level);
138  getProblemData().nonlinear_solver = nl_solver;
139 }
140 
141 void
142 MFEMProblem::addBoundaryCondition(const std::string & bc_name,
143  const std::string & name,
144  InputParameters & parameters)
145 {
146  auto bc = addObject<MFEMBoundaryCondition>(bc_name, name, parameters).front();
147  const auto & mfem_bc = *bc;
148 
149  if (dynamic_cast<const MFEMIntegratedBC *>(&mfem_bc))
150  {
151  auto integrated_bc = std::dynamic_pointer_cast<MFEMIntegratedBC>(bc);
152  auto eqsys =
154  if (eqsys)
155  eqsys->AddIntegratedBC(std::move(integrated_bc));
156  else
157  mooseError("Cannot add integrated BC with name '" + name +
158  "' because there is no corresponding equation system.");
159  }
160  else if (dynamic_cast<const MFEMComplexIntegratedBC *>(&mfem_bc))
161  {
162  auto integrated_bc = std::dynamic_pointer_cast<MFEMComplexIntegratedBC>(bc);
163  auto eqsys =
165  if (eqsys)
166  eqsys->AddComplexIntegratedBC(std::move(integrated_bc));
167  else
168  mooseError("Cannot add complex integrated BC with name '" + name +
169  "' because there is no corresponding equation system.");
170  }
171  else if (dynamic_cast<const MFEMComplexEssentialBC *>(&mfem_bc))
172  {
173  auto essential_bc = std::dynamic_pointer_cast<MFEMComplexEssentialBC>(bc);
174  auto eqsys =
176  if (eqsys)
177  eqsys->AddComplexEssentialBCs(std::move(essential_bc));
178  else
179  mooseError("Cannot add boundary condition with name '" + name +
180  "' because there is no corresponding equation system.");
181  }
182  else if (dynamic_cast<const MFEMEssentialBC *>(&mfem_bc))
183  {
184  auto essential_bc = std::dynamic_pointer_cast<MFEMEssentialBC>(bc);
185  auto eqsys =
187  if (eqsys)
188  eqsys->AddEssentialBC(std::move(essential_bc));
189  else
190  mooseError("Cannot add boundary condition with name '" + name +
191  "' because there is no corresponding equation system.");
192  }
193  else
194  {
195  mooseError("Unsupported bc of type '", bc_name, "' and name '", name, "' detected.");
196  }
197 }
198 
199 void
200 MFEMProblem::addMaterial(const std::string &, const std::string &, InputParameters &)
201 {
202  mooseError(
203  "MFEM materials must be added through the 'FunctorMaterials' block and not 'Materials'");
204 }
205 
206 void
207 MFEMProblem::addFunctorMaterial(const std::string & material_name,
208  const std::string & name,
209  InputParameters & parameters)
210 {
211  addObject<MFEMFunctorMaterial>(material_name, name, parameters);
212 }
213 
214 void
215 MFEMProblem::addFESpace(const std::string & type,
216  const std::string & name,
217  InputParameters & parameters)
218 {
219  auto & mfem_fespace = *addObject<MFEMFESpace>(type, name, parameters).front();
220 
221  // Register fespace and associated fe collection.
222  getProblemData().fecs.Register(name, mfem_fespace.getFEC());
223  getProblemData().fespaces.Register(name, mfem_fespace.getFESpace());
224 }
225 
226 void
227 MFEMProblem::addVariable(const std::string & var_type,
228  const std::string & var_name,
229  InputParameters & parameters)
230 {
231  addGridFunction(var_type, var_name, parameters);
232  // MOOSE variables store DoFs for the trial variable and its time derivatives up to second order;
233  // MFEM GridFunctions store data for only one set of DoFs each, so we must add additional
234  // GridFunctions for time derivatives.
235  if (isTransient())
236  {
237  const auto time_derivative_var_name =
238  getMFEMObject<MFEMVariable>("MooseVariableBase", var_name).getTimeDerivativeName();
240  time_derivative_var_name);
241  addGridFunction(var_type, time_derivative_var_name, parameters);
242  }
243 }
244 
245 void
246 MFEMProblem::addGridFunction(const std::string & var_type,
247  const std::string & var_name,
248  InputParameters & parameters)
249 {
250 
251  if (var_type == "MFEMVariable" || var_type == "MFEMComplexVariable")
252  {
253  // Add MFEM variable directly.
254  if (var_type == "MFEMComplexVariable")
255  addObject<MFEMComplexVariable>(var_type, var_name, parameters);
256  else
257  addObject<MFEMVariable>(var_type, var_name, parameters);
258  }
259  else
260  {
261  // Add MOOSE variable.
262  ExternalProblem::addVariable(var_type, var_name, parameters);
263 
264  // Add MFEM variable indirectly ("gridfunction").
266  addObject<MFEMVariable>("MFEMVariable", var_name, mfem_variable_params);
267  }
268 
269  // Register gridfunction.
270  if (var_type == "MFEMComplexVariable")
271  {
272  MFEMComplexVariable & mfem_variable =
273  getMFEMObject<MFEMComplexVariable>("MooseVariableBase", var_name);
275  mfem_variable.declareCoefficients();
276  }
277  else // must be real, but may have been set up indirectly from a MOOSE variable
278  {
279  MFEMVariable & mfem_variable = getMFEMObject<MFEMVariable>("MooseVariableBase", var_name);
280  getProblemData().gridfunctions.Register(var_name, mfem_variable.getGridFunction());
281  mfem_variable.declareCoefficients();
282  }
283 }
284 
285 void
286 MFEMProblem::addAuxVariable(const std::string & var_type,
287  const std::string & var_name,
288  InputParameters & parameters)
289 {
290  // We handle MFEM AuxVariables just like MFEM Variables, except
291  // we do not add additional GridFunctions for time derivatives.
292  addGridFunction(var_type, var_name, parameters);
293 }
294 
295 void
296 MFEMProblem::addAuxKernel(const std::string & kernel_name,
297  const std::string & name,
298  InputParameters & parameters)
299 {
300  addObject<MFEMExecutedObject>(kernel_name, name, parameters);
301 }
302 
303 void
304 MFEMProblem::addKernel(const std::string & kernel_name,
305  const std::string & name,
306  InputParameters & parameters)
307 {
308  auto kernel = addObject<MFEMKernel>(kernel_name, name, parameters).front();
309  const auto & kernel_object = *kernel;
310 
311  if (dynamic_cast<const MFEMComplexKernel *>(&kernel_object))
312  {
313  auto complex_kernel = std::dynamic_pointer_cast<MFEMComplexKernel>(kernel);
314  auto eqsys =
316  if (eqsys)
317  eqsys->AddComplexKernel(std::move(complex_kernel));
318  else
319  mooseError("Cannot add complex kernel with name '" + name +
320  "' because there is no corresponding equation system.");
321  }
322  else
323  {
324  auto eqsys =
326  if (eqsys)
327  eqsys->AddKernel(std::move(kernel));
328  else
329  mooseError("Cannot add kernel with name '" + name +
330  "' because there is no corresponding equation system.");
331  }
332 }
333 
334 void
335 MFEMProblem::addRealComponentToKernel(const std::string & kernel_name,
336  const std::string & name,
337  InputParameters & parameters)
338 {
339  auto parent_ptr = std::dynamic_pointer_cast<MFEMComplexKernel>(
340  getMFEMObject<MFEMComplexKernel>("Kernel", name).getSharedPtr());
341  parameters.set<VariableName>("variable") = parent_ptr->getParam<VariableName>("variable");
342  auto kernel_ptr = addObject<MFEMKernel>(kernel_name, name + "_real", parameters).front();
343  parent_ptr->setRealKernel(kernel_ptr);
344 }
345 
346 void
347 MFEMProblem::addImagComponentToKernel(const std::string & kernel_name,
348  const std::string & name,
349  InputParameters & parameters)
350 {
351  auto parent_ptr = std::dynamic_pointer_cast<MFEMComplexKernel>(
352  getMFEMObject<MFEMComplexKernel>("Kernel", name).getSharedPtr());
353  parameters.set<VariableName>("variable") = parent_ptr->getParam<VariableName>("variable");
354  auto kernel_ptr = addObject<MFEMKernel>(kernel_name, name + "_imag", parameters).front();
355  parent_ptr->setImagKernel(kernel_ptr);
356 }
357 
358 void
359 MFEMProblem::addRealComponentToBC(const std::string & kernel_name,
360  const std::string & name,
361  InputParameters & parameters)
362 {
364  getMFEMObject<MFEMComplexIntegratedBC>("BoundaryCondition", name).getSharedPtr());
365  parameters.set<VariableName>("variable") = parent_ptr->getParam<VariableName>("variable");
366  parameters.set<std::vector<BoundaryName>>("boundary") =
367  parent_ptr->getParam<std::vector<BoundaryName>>("boundary");
369  addObject<MFEMBoundaryCondition>(kernel_name, name + "_real", parameters).front());
370  parent_ptr->setRealBC(bc_ptr);
371 }
372 
373 void
374 MFEMProblem::addImagComponentToBC(const std::string & kernel_name,
375  const std::string & name,
376  InputParameters & parameters)
377 {
379  getMFEMObject<MFEMComplexIntegratedBC>("BoundaryCondition", name).getSharedPtr());
380  parameters.set<VariableName>("variable") = parent_ptr->getParam<VariableName>("variable");
381  parameters.set<std::vector<BoundaryName>>("boundary") =
382  parent_ptr->getParam<std::vector<BoundaryName>>("boundary");
384  addObject<MFEMBoundaryCondition>(kernel_name, name + "_imag", parameters).front());
385  parent_ptr->setImagBC(bc_ptr);
386 }
387 
388 int
389 vectorFunctionDim(const std::string & type, const InputParameters & parameters)
390 {
391  if (parameters.isParamSetByUser("expression_z"))
392  return 3;
393  if (parameters.isParamSetByUser("expression_y") || type == "LevelSetOlssonVortex")
394  return 2;
395  if (parameters.isParamSetByUser("expression_x"))
396  return 1;
397 
398  return 3;
399 }
400 
401 const std::vector<std::string> SCALAR_FUNCS = {"Axisymmetric2D3DSolutionFunction",
402  "BicubicSplineFunction",
403  "CoarsenedPiecewiseLinear",
404  "CompositeFunction",
405  "ConstantFunction",
406  "ImageFunction",
407  "ParsedFunction",
408  "ParsedGradFunction",
409  "PeriodicFunction",
410  "PiecewiseBilinear",
411  "PiecewiseConstant",
412  "PiecewiseConstantFromCSV",
413  "PiecewiseLinear",
414  "PiecewiseLinearFromVectorPostprocessor",
415  "PiecewiseMultiInterpolation",
416  "PiecewiseMulticonstant",
417  "SolutionFunction",
418  "SplineFunction",
419  "FunctionSeries",
420  "LevelSetOlssonBubble",
421  "LevelSetOlssonPlane",
422  "NearestReporterCoordinatesFunction",
423  "ParameterMeshFunction",
424  "ParsedOptimizationFunction",
425  "FourierNoise",
426  "MovingPlanarFront",
427  "MultiControlDrumFunction",
428  "Grad2ParsedFunction",
429  "GradParsedFunction",
430  "ScaledAbsDifferenceDRLRewardFunction",
431  "CircularAreaHydraulicDiameterFunction",
432  "CosineHumpFunction",
433  "CosineTransitionFunction",
434  "CubicTransitionFunction",
435  "GeneralizedCircumference",
436  "PiecewiseFunction",
437  "TimeRampFunction"},
438  VECTOR_FUNCS = {"ParsedVectorFunction", "LevelSetOlssonVortex"};
439 
440 void
441 MFEMProblem::addFunction(const std::string & type,
442  const std::string & name,
443  InputParameters & parameters)
444 {
446  auto & func = getFunction(name);
447  // FIXME: Do we want to have optimised versions for when functions
448  // are only of space or only of time.
449  if (std::find(SCALAR_FUNCS.begin(), SCALAR_FUNCS.end(), type) != SCALAR_FUNCS.end())
450  {
451  getCoefficients().declareScalar<mfem::FunctionCoefficient>(
452  name,
453  [&func](const mfem::Vector & p, mfem::real_t t) -> mfem::real_t
454  { return func.value(t, Moose::MFEM::libMeshPointFromMFEMVector(p)); });
455  }
456  else if (std::find(VECTOR_FUNCS.begin(), VECTOR_FUNCS.end(), type) != VECTOR_FUNCS.end())
457  {
459  getCoefficients().declareVector<mfem::VectorFunctionCoefficient>(
460  name,
461  dim,
462  [&func, dim](const mfem::Vector & p, mfem::real_t t, mfem::Vector & u)
463  {
464  libMesh::RealVectorValue vector_value =
465  func.vectorValue(t, Moose::MFEM::libMeshPointFromMFEMVector(p));
466  for (int i = 0; i < dim; i++)
467  {
468  u[i] = vector_value(i);
469  }
470  });
471  }
472  else if ("MFEMParsedFunction" != type)
473  {
474  mooseWarning("Could not identify whether function ",
475  type,
476  " is scalar or vector; no MFEM coefficient object created.");
477  }
478 }
479 
480 void
481 MFEMProblem::addPostprocessor(const std::string & type,
482  const std::string & name,
483  InputParameters & parameters)
484 {
485  if (parameters.getSystemAttributeName() == "MFEMExecutedObject")
486  {
487  checkUserObjectNameCollision(name, "Postprocessor");
488  addObject<MFEMExecutedObject>(type, name, parameters);
490  getCoefficients().declareScalar<mfem::FunctionCoefficient>(
491  name, [&val](const mfem::Vector &) -> mfem::real_t { return val; });
492  }
493  else
495 }
496 
497 void
498 MFEMProblem::addVectorPostprocessor(const std::string & type,
499  const std::string & name,
500  InputParameters & parameters)
501 {
502  if (parameters.getSystemAttributeName() == "MFEMExecutedObject")
503  {
504  checkUserObjectNameCollision(name, "VectorPostprocessor");
505  addObject<MFEMExecutedObject>(type, name, parameters);
506  }
507  else
509 }
510 
513 {
514 
515  InputParameters fespace_params = _factory.getValidParams("MFEMGenericFESpace");
516  InputParameters variable_params = _factory.getValidParams("MFEMVariable");
517 
518  const auto family = Utility::string_to_enum<FEFamily>(parameters.get<MooseEnum>("family"));
519  auto order = static_cast<int>(parameters.get<MooseEnum>("order"));
520  const auto dim = mesh().dimension();
521 
522  std::string space;
523  int vdim = 1;
524 
525  switch (family)
526  {
527  case FEFamily::LAGRANGE:
528  space = "H1";
529  break;
530  case FEFamily::NEDELEC_ONE:
531  space = "ND";
532  break;
533  case FEFamily::RAVIART_THOMAS:
534  space = "RT";
535  --order;
536  break;
537  case FEFamily::MONOMIAL:
538  case FEFamily::L2_LAGRANGE:
539  space = "L2";
540  break;
541  case FEFamily::LAGRANGE_VEC:
542  space = "H1";
543  vdim = dim;
544  break;
545  case FEFamily::MONOMIAL_VEC:
546  case FEFamily::L2_LAGRANGE_VEC:
547  space = "L2";
548  vdim = dim;
549  break;
550  default:
551  mooseError("Unable to set MFEM FESpace for MOOSE variable");
552  break;
553  }
554 
555  // Create fespace name. If this already exists, we will reuse this for
556  // the mfem variable ("gridfunction"). If using AMR, this implies all
557  // variables sharing the fespace are affected.
558  const auto fec_name = space + "_" + std::to_string(dim) + "D_P" + std::to_string(order);
559  const auto fes_name = fec_name + "_X" + std::to_string(vdim);
560 
561  // Set all fespace parameters.
562  fespace_params.set<std::string>("fec_name") = fec_name;
563  fespace_params.set<int>("vdim") = vdim;
564 
565  if (!hasMFEMObject("MFEMFESpace", fes_name))
566  addFESpace("MFEMGenericFESpace", fes_name, fespace_params);
567 
568  variable_params.set<MFEMFESpaceName>("fespace") = fes_name;
569 
570  return variable_params;
571 }
572 
573 void
575 {
576  // Displace mesh
577  if (mesh().shouldDisplace())
578  {
579  mesh().displace(static_cast<mfem::GridFunction const &>(*getMeshDisplacementGridFunction()));
580  // TODO: update FESpaces GridFunctions etc for transient solves
581  }
582 }
583 
584 std::optional<std::reference_wrapper<mfem::ParGridFunction const>>
586 {
587  // If C++23 transform were available this would be easier
588  auto const displacement_variable = mesh().getMeshDisplacementVariable();
589  if (displacement_variable)
590  {
591  return *_problem_data.gridfunctions.Get(displacement_variable.value());
592  }
593  else
594  {
595  return std::nullopt;
596  }
597 }
598 
599 void
600 MFEMProblem::rebalanceMesh(mfem::ParMesh & pmesh)
601 {
602  if (pmesh.Nonconforming())
603  {
604  pmesh.Rebalance();
605  updateFESpaces();
607  }
608 }
609 
610 void
612 {
613  for (const auto & fe_space_pair : _problem_data.fespaces)
614  fe_space_pair.second->Update();
615 }
616 
617 void
619 {
620  for (const auto & gridfunction_pair : _problem_data.gridfunctions)
621  gridfunction_pair.second->Update();
622 }
623 
624 std::vector<VariableName>
626 {
628 }
629 
630 MFEMMesh &
632 {
633  mooseAssert(ExternalProblem::mesh().type() == "MFEMMesh",
634  "Please choose the MFEMMesh mesh type for an MFEMProblem\n");
635  return static_cast<MFEMMesh &>(_mesh);
636 }
637 
638 const MFEMMesh &
640 {
641  return const_cast<MFEMProblem *>(this)->mesh();
642 }
643 
644 void
645 MFEMProblem::addSubMesh(const std::string & var_type,
646  const std::string & var_name,
647  InputParameters & parameters)
648 {
649  auto & mfem_submesh = *addObject<MFEMSubMesh>(var_type, var_name, parameters).front();
650  // Register submesh.
651  getProblemData().submeshes.Register(var_name, mfem_submesh.getSubMesh());
652 }
653 
654 void
655 MFEMProblem::addTransfer(const std::string & transfer_name,
656  const std::string & name,
657  InputParameters & parameters)
658 {
659  if (parameters.getBase() == "MFEMSubMeshTransfer")
660  addObject<MFEMExecutedObject>(transfer_name, name, parameters);
661  else
663 }
664 
665 void
666 MFEMProblem::addInitialCondition(const std::string & ic_name,
667  const std::string & name,
668  InputParameters & parameters)
669 {
670  addObject<MFEMExecutedObject>(ic_name, name, parameters);
671 }
672 
673 void
675 {
676  std::vector<MFEMExecutedObject *> objects;
677  theWarehouse()
678  .query()
679  .condition<AttribSystem>("MFEMExecutedObject")
680  .condition<AttribExecOns>(exec_type)
681  .condition<AttribThread>(0)
682  .queryInto(objects);
683 
684  std::map<std::string, const MFEMExecutedObject *> suppliers;
685  for (auto * const object : objects)
686  for (const auto & item : object->getSuppliedItems())
687  {
688  const auto [it, inserted] = suppliers.emplace(item, object);
689  if (!inserted && it->second != object)
690  mooseError("MFEM executed-object dependency ambiguity on ",
691  exec_type,
692  ": both '",
693  it->second->name(),
694  "' and '",
695  object->name(),
696  "' supply '",
697  item,
698  "'.");
699  }
700 
701  for (auto * const object : objects)
702  {
703  object->initialize();
704  object->execute();
705  object->finalize();
706 
707  if (auto * const pp = dynamic_cast<const Postprocessor *>(object))
708  {
709  _reporter_data.finalize(pp->PPName());
710  setPostprocessorValueByName(pp->PPName(), pp->getValue());
711  }
712 
713  if (auto * const vpp = dynamic_cast<VectorPostprocessor *>(object))
714  _reporter_data.finalize(vpp->PPName());
715  }
716 }
717 
718 std::string
719 MFEMProblem::solverTypeString(const unsigned int libmesh_dbg_var(solver_sys_num))
720 {
721  mooseAssert(solver_sys_num == 0, "No support for multi-system with MFEM right now");
722 
723  std::vector<std::string> solvers;
724 
725  if (getProblemData().nonlinear_solver)
726  solvers.push_back(MooseUtils::prettyCppType(getProblemData().nonlinear_solver.get()));
727 
729  {
730  solvers.push_back(MooseUtils::prettyCppType(getProblemData().jacobian_solver.get()));
731  if (const auto * prec = getProblemData().jacobian_solver->getPreconditioner())
732  solvers.push_back(MooseUtils::prettyCppType(prec));
733  }
734 
735  return solvers.empty() ? "None" : MooseUtils::stringJoin(solvers);
736 }
737 
738 bool
739 MFEMProblem::hasMFEMObject(const std::string & system, const std::string & name) const
740 {
741  std::vector<MooseObject *> objs;
742  theWarehouse()
743  .query()
744  .condition<AttribSystem>(system)
745  .condition<AttribThread>(0)
746  .condition<AttribName>(name)
747  .queryInto(objs);
748  return !objs.empty();
749 }
750 
751 #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:246
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:359
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:263
const std::string & name() const
Definition: MooseEnumItem.h:35
const std::vector< std::string > SCALAR_FUNCS
Definition: MFEMProblem.C:401
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:374
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:481
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
std::shared_ptr< mfem::IterativeSolver > nonlinear_solver
void addFunction(const std::string &type, const std::string &name, InputParameters &parameters) override
Override of ExternalProblem::addFunction.
Definition: MFEMProblem.C:441
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:512
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:631
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:227
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...
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:674
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:719
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:389
void setCurrentExecuteOnFlag(const ExecFlagType &)
void displaceMesh()
Displace the mesh, if mesh displacement is enabled.
Definition: MFEMProblem.C:574
MFEMProblemData _problem_data
Aggregated MFEM-side state for meshes, spaces, variables, coefficients, and solvers.
Definition: MFEMProblem.h:376
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:739
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:600
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:257
MooseMesh & _mesh
void addMaterial(const std::string &material_name, const std::string &name, InputParameters &parameters) override
Definition: MFEMProblem.C:200
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:296
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
MPI_Comm getComm()
Return the MPI communicator associated with this FE problem&#39;s mesh.
Definition: MFEMProblem.h:273
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:207
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:215
void updateGridFunctions()
Calls Update() on all gridfunctions.
Definition: MFEMProblem.C:618
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:625
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:142
const std::vector< std::string > VECTOR_FUNCS
Definition: MFEMProblem.C:438
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:611
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:347
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:498
void addKernel(const std::string &kernel_name, const std::string &name, InputParameters &parameters) override
Override of ExternalProblem::addKernel.
Definition: MFEMProblem.C:304
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:585
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:286
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:335
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:645
Moose::MFEM::TimeDerivativeMap time_derivative_map
std::shared_ptr< MFEMSolverBase > jacobian_solver
virtual void execute(const ExecFlagType &exec_type) override
Convenience function for performing execution of MOOSE systems.
Definition: MFEMProblem.C:69
void addMFEMNonlinearSolver(unsigned int nl_max_its, mfem::real_t nl_abs_tol, mfem::real_t nl_rel_tol, unsigned int print_level)
Add the nonlinear solver to the system.
Definition: MFEMProblem.C:125
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:655
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:666
void AddComplexKernel(std::shared_ptr< MFEMComplexKernel > kernel)
Add complex kernels.