https://mooseframework.inl.gov
MFEMFESpaceHierarchy.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 "MFEMFESpaceHierarchy.h"
13 #include "MFEMFESpace.h"
14 #include "MFEMProblem.h"
15 
17 
20 {
22  params.registerBase("MFEMFESpaceHierarchy");
23  params.registerSystemAttributeName("MFEMFESpaceHierarchy");
24  params.addClassDescription(
25  "Builds a mfem::ParFiniteElementSpaceHierarchy from a base FESpace by applying a "
26  "sequence of h-refinements ('h') and/or p-refinements (integer order strings).");
27  params.addRequiredParam<MFEMFESpaceName>("fespace",
28  "Name of the base (coarsest-level) FESpace object.");
29  params.addRequiredParam<std::vector<std::string>>(
30  "refinements",
31  "Ordered sequence of refinements. Each entry is 'h' for uniform h-refinement or "
32  "an integer string for p-refinement to that polynomial order (must be strictly "
33  "increasing across p-entries).");
34  return params;
35 }
36 
38  : MFEMObject(parameters)
39 {
41 }
42 
43 void
45 {
46  const auto & fespace_name = getParam<MFEMFESpaceName>("fespace");
47  const auto & refinements = getParam<std::vector<std::string>>("refinements");
48 
49  if (refinements.empty())
50  paramError("refinements", "must not be empty.");
51 
52  const auto & base_fespace_object =
53  getMFEMProblem().getMFEMObject<MFEMFESpace>("MFEMFESpace", fespace_name);
54  _is_scalar = base_fespace_object.isScalar();
55 
56  // Retrieve the base (coarsest) ParFiniteElementSpace from ProblemData.
57  auto base_fespace = base_fespace_object.getFESpace();
58  mfem::ParMesh * base_mesh = base_fespace->GetParMesh();
59  const int vdim = base_fespace->GetVDim();
60  const int ordering = base_fespace->GetOrdering();
61 
62  // Construct the hierarchy with the coarse level.
63  // MOOSE owns the mesh and fespace, so pass ownM=false, ownFES=false.
64  _hierarchy = std::make_shared<mfem::ParFiniteElementSpaceHierarchy>(
65  base_mesh, base_fespace.get(), /*ownM=*/false, /*ownFES=*/false);
66 
67  for (const auto & entry : refinements)
68  {
69  if (entry == "h")
70  _hierarchy->AddUniformlyRefinedLevel(vdim, ordering);
71  else
72  {
73  // p-refinement: parse the target polynomial order.
74  int new_order = 0;
75  try
76  {
77  new_order = std::stoi(entry);
78  }
79  catch (const std::exception &)
80  {
81  paramError("refinements",
82  "entry '",
83  entry,
84  "' is neither 'h' nor a valid integer polynomial order.");
85  }
86 
87  if (new_order < 1)
88  paramError("refinements", "p-refinement order must be >= 1, got ", new_order, ".");
89 
90  // Derive the new FEC name from the current finest level's FEC.
91  const std::string current_fec_name = _hierarchy->GetFinestFESpace().FEColl()->Name();
92  const auto pos = current_fec_name.rfind("_P");
93  if (pos == std::string::npos)
94  paramError("refinements",
95  "cannot infer polynomial order from FEC name '",
96  current_fec_name,
97  "' - expected a '_P<N>' suffix.");
98 
99  const int current_order = std::stoi(current_fec_name.substr(pos + 2));
100  if (new_order <= current_order)
101  paramError("refinements",
102  "p-refinement orders must be strictly increasing; requested order ",
103  new_order,
104  " is not greater than the current finest level's order ",
105  current_order,
106  ".");
107 
108  const std::string new_fec_name =
109  current_fec_name.substr(0, pos + 2) + std::to_string(new_order);
110 
111  auto new_fec = std::unique_ptr<mfem::FiniteElementCollection>(
112  mfem::FiniteElementCollection::New(new_fec_name.c_str()));
113  _hierarchy->AddOrderRefinedLevel(new_fec.get(), vdim, ordering);
114  _level_fecs.push_back(std::move(new_fec));
115  }
116  }
117 }
118 #endif
Thin base for MFEM objects backed directly by MooseObject instead of UserObject.
Definition: MFEMObject.h:25
MFEMProblem & getMFEMProblem()
Return the owning MFEM problem.
Definition: MFEMObject.h:45
void paramError(const std::string &param, Args... args) const
Emits an error prefixed with the file and line number of the given param (from the input file) along ...
Definition: MooseBase.h:457
std::vector< std::unique_ptr< mfem::FiniteElementCollection > > _level_fecs
FECs for p-refined levels.
T & getMFEMObject(const std::string &system, const std::string &name, const THREAD_ID tid=0) const
Retrieve an MFEM object from the warehouse by system and name.
Definition: MFEMProblem.h:418
void registerSystemAttributeName(const std::string &value)
This method is used to define the MOOSE system name that is used by the TheWarehouse object for stori...
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
void addRequiredParam(const std::string &name, const std::string &doc_string)
This method adds a parameter and documentation string to the InputParameters object that will be extr...
static InputParameters validParams()
void registerBase(const std::string &value)
This method must be called from every base "Moose System" to create linkage with the Action System...
MFEMFESpaceHierarchy(const InputParameters &parameters)
std::shared_ptr< mfem::ParFiniteElementSpaceHierarchy > _hierarchy
The hierarchy - shared_ptr so that MFEMGeometricMultigridSolver and ProblemData can co-own...
Builds and owns a mfem::ParFiniteElementSpaceHierarchy from a base FESpace by applying a sequence of ...
registerMooseObject("MooseApp", MFEMFESpaceHierarchy)
Constructs and stores an mfem::ParFiniteElementSpace object.
Definition: MFEMFESpace.h:20
static InputParameters validParams()
Declare the common parameters required by MFEM MooseObject-backed classes.
Definition: MFEMObject.C:17
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...