https://mooseframework.inl.gov
MFEMMesh.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 "MFEMMesh.h"
13 #include "MooseApp.h"
14 #include "libmesh/mesh_generation.h"
15 
16 #include <fstream>
17 
18 registerMooseObject("MooseApp", MFEMMesh);
19 
22 {
24  params.addParam<unsigned int>(
25  "serial_refine",
26  0,
27  "Number of serial refinements to perform on the mesh. Equivalent to uniform_refine.");
28  params.addParam<unsigned int>(
29  "uniform_refine",
30  0,
31  "Number of serial refinements to perform on the mesh. Equivalent to serial_refine");
32  params.addParam<unsigned int>(
33  "parallel_refine", 0, "Number of parallel refinements to perform on the mesh.");
34  params.addParam<std::string>("displacement", "Optional variable to use for mesh displacement.");
35  params.addParam<bool>("nonconforming",
36  false,
37  "Ensures the mesh is non-conforming: necessary for refining quad/hex "
38  "meshes and load (re)balancing.");
39  params.addParam<bool>("reorder_mesh",
40  false,
41  "Determines whether we reorder the mesh to improve dynamic partitioning. "
42  "Only Hilbert sorting is supported at present.");
43 
44  params.addClassDescription("Class to read in and store an mfem::ParMesh from file.");
45 
46  return params;
47 }
48 
49 MFEMMesh::MFEMMesh(const InputParameters & parameters) : FileMesh(parameters) {}
50 
52 
53 void
55 {
56  // MooseMesh::init() handles the libMesh dummy mesh:
57  // - recovery: reads the libMesh mesh back from its checkpoint file
58  // - normal run: calls buildMesh(), which for MFEMMesh builds both the
59  // dummy libMesh mesh and the MFEM ParMesh
61 
63  {
64  // MooseMesh::init() already restored the libMesh dummy mesh from its checkpoint.
65  // Now restore the MFEM parallel mesh from its own checkpoint file.
66  const auto checkpoint_file = _app.getRestartRecoverFileBase() + _app.checkpointSuffix() +
67  ".mfem.mesh." + std::to_string(this->processor_id());
68  std::ifstream input(checkpoint_file);
69  if (!input)
70  mooseError("Unable to open MFEM recovery mesh file '", checkpoint_file, "'.");
71 
72  _mfem_par_mesh = std::make_shared<mfem::ParMesh>(this->comm().get(), input);
73 
74  if (isParamSetByUser("displacement"))
75  _mesh_displacement_variable.emplace(getParam<std::string>("displacement"));
76  }
77 }
78 
79 void
81 {
82  TIME_SECTION("buildMesh", 2, "Reading Mesh");
83 
84  // Build the MFEM ParMesh from a serial MFEM mesh
85  mfem::Mesh mfem_ser_mesh(getFileName());
86 
87  if (isParamSetByUser("serial_refine") && isParamSetByUser("uniform_refine"))
88  paramError(
89  "Cannot define serial_refine and uniform_refine to be nonzero at the same time (they "
90  "are the same variable). Please choose one.\n");
91 
92  uniformRefinement(mfem_ser_mesh,
93  isParamSetByUser("serial_refine") ? getParam<unsigned int>("serial_refine")
94  : getParam<unsigned int>("uniform_refine"));
95 
96  // MFEM supports load balancing of parallel non-conforming meshes
97  // with a space-filling curve partitioning, and we can improve it
98  // by re-ordering the mesh. For now, we only support the Hilbert
99  // ordering, although there is one other option.
100  if (getParam<bool>("reorder_mesh"))
101  {
102  mfem::Array<int> ordering;
103  mfem_ser_mesh.GetHilbertElementOrdering(ordering);
104  mfem_ser_mesh.ReorderElements(ordering);
105  }
106 
107  // Make sure mesh is in non-conforming mode to enable local refinement of
108  // quadrilaterals/hexahedra (c.f. MFEM example 6p). The argument (true/false)
109  // determines whether a simplex mesh is considered to be non-conforming.
110  if (getParam<bool>("nonconforming"))
111  mfem_ser_mesh.EnsureNCMesh(true);
112 
113  // multi app should take the mpi comm from moose so is split correctly??
114  auto comm = this->comm().get();
115  _mfem_par_mesh = std::make_shared<mfem::ParMesh>(comm, mfem_ser_mesh);
116 
117  // Perform parallel refinements
118  uniformRefinement(*_mfem_par_mesh, getParam<unsigned int>("parallel_refine"));
119 
120  if (isParamSetByUser("displacement"))
121  _mesh_displacement_variable.emplace(getParam<std::string>("displacement"));
122 
123  // Build a dummy MOOSE mesh to enable this class to work with other MOOSE classes.
125 }
126 
127 std::vector<std::filesystem::path>
128 MFEMMesh::writeRecoveryFiles(const std::filesystem::path & file_base)
129 {
131 
132  mooseAssert(_mfem_par_mesh, "MFEM parallel mesh is not initialized");
133 
134  const auto checkpoint_file =
135  file_base.string() + ".mfem.mesh." + std::to_string(this->processor_id());
136  std::ofstream output(checkpoint_file);
137  if (!output)
138  mooseError("Unable to open MFEM recovery mesh file '", checkpoint_file, "' for writing.");
139 
140  _mfem_par_mesh->ParPrint(output);
141  return {checkpoint_file};
142 }
143 
144 void
145 MFEMMesh::displace(mfem::GridFunction const & displacement)
146 {
147  _mfem_par_mesh->EnsureNodes();
148  mfem::GridFunction * nodes = _mfem_par_mesh->GetNodes();
149 
150  *nodes += displacement;
151 }
152 
153 void
155 {
156  auto & dummy = static_cast<UnstructuredMesh &>(getMesh());
157  MeshTools::Generation::build_point(dummy);
158  if (dimension() >= 2)
159  MeshTools::Generation::build_square(dummy, 1, 1, 0., 1., 0., 1., ElemType::QUAD9);
160 }
161 
162 void
163 MFEMMesh::uniformRefinement(mfem::Mesh & mesh, const unsigned int nref) const
164 {
165  for (unsigned int i = 0; i < nref; ++i)
166  mesh.UniformRefinement();
167 }
168 
169 std::unique_ptr<MooseMesh>
171 {
172  return _app.getFactory().copyConstruct(*this);
173 }
174 
175 #endif
static const std::string & checkpointSuffix()
The file suffix for the checkpoint mesh.
Definition: MooseApp.C:3039
std::vector< std::filesystem::path > writeRecoveryFiles(const std::filesystem::path &file_base) override
Write the mesh files needed for recovery/checkpointing.
Definition: MFEMMesh.C:128
unsigned int dimension() const override
Returns MeshBase::mesh_dimension(), (not MeshBase::spatial_dimension()!) of the underlying libMesh me...
Definition: MFEMMesh.h:75
bool isUltimateMaster() const
Whether or not this app is the ultimate master app.
Definition: MooseApp.h:866
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
void uniformRefinement(mfem::Mesh &mesh, const unsigned int nref) const
Performs a uniform refinement on the chosen mesh nref times.
Definition: MFEMMesh.C:163
virtual ~MFEMMesh()
Definition: MFEMMesh.C:51
std::optional< std::string > _mesh_displacement_variable
Holds name of variable used for mesh displacement, if set.
Definition: MFEMMesh.h:95
MeshBase & mesh
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
const Parallel::Communicator & comm() const
virtual void init()
Initialize the Mesh object.
Definition: MooseMesh.C:2928
virtual std::vector< std::filesystem::path > writeRecoveryFiles(const std::filesystem::path &file_base)
Write the mesh files needed for recovery/checkpointing.
Definition: MooseMesh.C:2977
std::unique_ptr< T > copyConstruct(const T &object)
Copy constructs the object object.
Definition: Factory.h:358
Factory & getFactory()
Retrieve a writable reference to the Factory associated with this App.
Definition: MooseApp.h:407
void init() override
Build MFEM ParMesh and a placeholder MOOSE mesh.
Definition: MFEMMesh.C:54
static InputParameters validParams()
Definition: MFEMMesh.C:21
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
Definition: MooseMesh.C:3548
void buildDummyMooseMesh()
Builds a placeholder mesh when no MOOSE mesh is required.
Definition: MFEMMesh.C:154
void buildMesh() override
Must be overridden by child classes.
Definition: MFEMMesh.C:80
std::unique_ptr< MooseMesh > safeClone() const override
Clones the mesh.
Definition: MFEMMesh.C:170
MooseApp & _app
The MOOSE application this is associated with.
Definition: MooseBase.h:375
bool allowRecovery() const
Returns whether this mesh is allowed to read a recovery file.
Definition: MooseMesh.h:1575
registerMooseObject("MooseApp", MFEMMesh)
MFEMMesh(const InputParameters &parameters)
Definition: MFEMMesh.C:49
std::shared_ptr< mfem::ParMesh > _mfem_par_mesh
Smart pointers to mfem::ParMesh object.
Definition: MFEMMesh.h:101
void displace(mfem::GridFunction const &displacement)
Displace the nodes of the mesh by the given displacement.
Definition: MFEMMesh.C:145
MFEMMesh inherits a MOOSE mesh class which allows us to work with other MOOSE objects.
Definition: MFEMMesh.h:20
static InputParameters validParams()
Definition: FileMesh.C:28
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:271
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...
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...
virtual std::string getFileName() const override
Returns the name of the mesh file read to produce this mesh if any or an empty string otherwise...
Definition: FileMesh.h:31
processor_id_type processor_id() const
bool isRecovering() const
Whether or not this is a "recover" calculation.
Definition: MooseApp.C:1669
std::string getRestartRecoverFileBase() const
The file_base for the recovery file.
Definition: MooseApp.h:500
bool isParamSetByUser(const std::string &name) const
Test if the supplied parameter is set by a user, as opposed to not set or set to default.
Definition: MooseBase.h:205