Line data Source code
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 : #pragma once
13 :
14 : #include "Attributes.h"
15 : #include "ExternalProblem.h"
16 : #include "MFEMProblemData.h"
17 : #include "MFEMMesh.h"
18 : #include "MFEMRefinementMarker.h"
19 : #include "MFEMComplexVariable.h"
20 :
21 : #include <map>
22 :
23 : class MFEMProblem : public ExternalProblem
24 : {
25 : public:
26 : /**
27 : * Return the input parameters used to construct an MFEM problem.
28 : */
29 : static InputParameters validParams();
30 :
31 : /**
32 : * Construct an MFEM problem from the supplied parameters.
33 : */
34 : MFEMProblem(const InputParameters & params);
35 :
36 : /**
37 : * Destroy the MFEM problem.
38 : */
39 1959 : virtual ~MFEMProblem() {}
40 :
41 : virtual void initialSetup() override;
42 : virtual void execute(const ExecFlagType & exec_type) override;
43 0 : virtual void externalSolve() override {}
44 78 : virtual void syncSolutions(Direction) override {}
45 :
46 : /**
47 : * Overwritten mesh() method from base MooseMesh to retrieve the correct mesh type, in this case
48 : * MFEMMesh.
49 : */
50 : virtual MFEMMesh & mesh() override;
51 : virtual const MFEMMesh & mesh() const override;
52 : using ExternalProblem::mesh;
53 :
54 : /**
55 : * Returns all the variable names from the auxiliary system base. This is helpful in the
56 : * syncSolutions() method when transferring variable data.
57 : */
58 : virtual std::vector<VariableName> getAuxVariableNames();
59 :
60 : void addBoundaryCondition(const std::string & bc_name,
61 : const std::string & name,
62 : InputParameters & parameters) override;
63 :
64 : void addMaterial(const std::string & material_name,
65 : const std::string & name,
66 : InputParameters & parameters) override;
67 :
68 : void addFunctorMaterial(const std::string & material_name,
69 : const std::string & name,
70 : InputParameters & parameters) override;
71 :
72 : /**
73 : * Add an MFEM FESpace to the problem.
74 : */
75 : void addFESpace(const std::string & type, const std::string & name, InputParameters & parameters);
76 :
77 : /**
78 : * Add an MFEM FESpaceHierarchy to the problem.
79 : */
80 : void addFESpaceHierarchy(const std::string & type,
81 : const std::string & name,
82 : InputParameters & parameters);
83 :
84 : /**
85 : * Set the mesh used by MFEM.
86 : */
87 : void setMesh();
88 :
89 : /**
90 : * Add an MFEM SubMesh to the problem.
91 : */
92 : void addSubMesh(const std::string & type, const std::string & name, InputParameters & parameters);
93 :
94 : /**
95 : * Add an MFEM QuadratureFunction-backed coefficient to the problem.
96 : */
97 : void addQuadratureFunction(const std::string & type,
98 : const std::string & name,
99 : InputParameters & parameters);
100 :
101 : /**
102 : * Add transfers between MultiApps and/or MFEM SubMeshes.
103 : */
104 : void addTransfer(const std::string & transfer_name,
105 : const std::string & name,
106 : InputParameters & parameters) override;
107 : /**
108 : * Override of ExternalProblem::addVariable. Sets a
109 : * MFEM grid function (and time derivative, for transient problems) to be used in the MFEM solve.
110 : */
111 : virtual void addVariable(const std::string & var_type,
112 : const std::string & var_name,
113 : InputParameters & parameters) override;
114 :
115 : /**
116 : * Adds one MFEM GridFunction to be used in the MFEM solve.
117 : */
118 : void addGridFunction(const std::string & var_type,
119 : const std::string & var_name,
120 : InputParameters & parameters);
121 :
122 : using ExternalProblem::addAuxVariable;
123 : /**
124 : * Override of ExternalProblem::addAuxVariable. Sets a
125 : * MFEM grid function to be used in the MFEM solve.
126 : */
127 : void addAuxVariable(const std::string & var_type,
128 : const std::string & var_name,
129 : InputParameters & parameters) override;
130 :
131 : /**
132 : * Override of FEProblemBase::addElementalFieldVariable to be a no-op because we do not use the
133 : * Marker/Indicator objects designed to work with libMesh infrastructure
134 : */
135 : void
136 52 : addElementalFieldVariable(const std::string &, const std::string &, InputParameters &) override
137 : {
138 52 : }
139 :
140 : /**
141 : * Override of ExternalProblem::addKernel. Creates the MOOSE-side MFEM kernel wrapper and the
142 : * corresponding MFEM kernel to be used in the MFEM solve.
143 : */
144 : void addKernel(const std::string & kernel_name,
145 : const std::string & name,
146 : InputParameters & parameters) override;
147 :
148 : /**
149 : * Adds a real component kernel to the parent MFEMComplexKernel.
150 : */
151 : void addRealComponentToKernel(const std::string & kernel_name,
152 : const std::string & name,
153 : InputParameters & parameters);
154 :
155 : /**
156 : * Adds an imaginary component kernel to the parent MFEMComplexKernel.
157 : */
158 : void addImagComponentToKernel(const std::string & kernel_name,
159 : const std::string & name,
160 : InputParameters & parameters);
161 :
162 : /**
163 : * Adds a real component BC to the parent MFEMComplexIntegratedBC.
164 : */
165 : void addRealComponentToBC(const std::string & kernel_name,
166 : const std::string & name,
167 : InputParameters & parameters);
168 :
169 : /**
170 : * Adds an imaginary component BC to the parent MFEMComplexIntegratedBC.
171 : */
172 : void addImagComponentToBC(const std::string & kernel_name,
173 : const std::string & name,
174 : InputParameters & parameters);
175 :
176 : /**
177 : * Override of ExternalProblem::addAuxKernel. Creates the MOOSE-side MFEM auxkernel wrapper.
178 : */
179 : void addAuxKernel(const std::string & kernel_name,
180 : const std::string & name,
181 : InputParameters & parameters) override;
182 :
183 : /**
184 : * Override of ExternalProblem::addFunction. Creates a corresponding MFEM Coefficient or
185 : * VectorCoefficient object for the added MOOSE function.
186 : */
187 : void addFunction(const std::string & type,
188 : const std::string & name,
189 : InputParameters & parameters) override;
190 :
191 : /**
192 : * Add an MFEM initial condition to the problem.
193 : */
194 : void addInitialCondition(const std::string & ic_name,
195 : const std::string & name,
196 : InputParameters & parameters) override;
197 :
198 : /**
199 : * Override of ExternalProblem::addPostprocessor. In addition to
200 : * creating the postprocessor object, it will create a coefficient
201 : * that will hold its value.
202 : */
203 : void addPostprocessor(const std::string & type,
204 : const std::string & name,
205 : InputParameters & parameters) override;
206 :
207 : /**
208 : * Add a vector postprocessor and register its vectors with the MFEM execution system.
209 : */
210 : void addVectorPostprocessor(const std::string & type,
211 : const std::string & name,
212 : InputParameters & parameters) override;
213 :
214 : /**
215 : * Override of FEProblemBase::addIndicator. Creates the MFEMIndicator used when setting up
216 : * adaptive mesh refinement later.
217 : */
218 : void addIndicator(const std::string & type,
219 : const std::string & name,
220 : InputParameters & parameters) override;
221 :
222 : /**
223 : * Override of FEProblemBase::addMarker. Creates the MFEMRefinementMarker used for adaptive mesh
224 : * refinement.
225 : */
226 : void addMarker(const std::string & type,
227 : const std::string & name,
228 : InputParameters & parameters) override;
229 :
230 : /**
231 : * Method called in AddMFEMSolverAction which records a solver for later dependency-ordered
232 : * construction.
233 : */
234 : virtual void addMFEMSolver(const std::string & user_object_name,
235 : const std::string & name,
236 : InputParameters & parameters);
237 :
238 : /**
239 : * Construct recorded MFEM solvers in dependency order and select the problem driver solver(s).
240 : */
241 : virtual void resolveMFEMSolvers();
242 :
243 : /**
244 : * Execute MFEM executed objects scheduled on the supplied execute flag.
245 : */
246 : void executeMFEMObjects(const ExecFlagType & exec_type);
247 :
248 : /**
249 : * Method used to get an mfem FEC depending on the variable family specified in the input file.
250 : * This method is used in addAuxVariable to help create the MFEM grid function that corresponds to
251 : * a given MOOSE aux-variable.
252 : */
253 : InputParameters addMFEMFESpaceFromMOOSEVariable(InputParameters & moosevar_params);
254 :
255 : /**
256 : * Method to get the PropertyManager object for storing material
257 : * properties and converting them to MFEM coefficients. This is used
258 : * by Material and Kernel classes (among others).
259 : */
260 25036 : Moose::MFEM::CoefficientManager & getCoefficients() { return _problem_data.coefficients; }
261 :
262 : /**
263 : * Method to get the current MFEMProblemData object storing the
264 : * current data specifying the FE problem.
265 : */
266 42426 : MFEMProblemData & getProblemData() { return _problem_data; }
267 :
268 : /**
269 : * Return the current MFEM problem data in a const context.
270 : */
271 : const MFEMProblemData & getProblemData() const { return _problem_data; }
272 :
273 : /**
274 : * Return the MPI communicator associated with this FE problem's mesh.
275 : */
276 2237 : MPI_Comm getComm() { return getProblemData().comm; }
277 :
278 : /**
279 : * Return the ParMesh associated with a particular variable.
280 : */
281 4131 : const mfem::ParMesh & getMFEMVariableMesh(std::string var_name)
282 : {
283 4131 : if (_problem_data.gridfunctions.Has(var_name))
284 3845 : return *_problem_data.gridfunctions.Get(var_name)->ParFESpace()->GetParMesh();
285 286 : else if (_problem_data.cmplx_gridfunctions.Has(var_name))
286 286 : return *_problem_data.cmplx_gridfunctions.Get(var_name)->ParFESpace()->GetParMesh();
287 : else
288 0 : mooseError("Variable " + var_name +
289 : " not found in MFEMProblem real or complex gridfunctions.");
290 : }
291 :
292 : /**
293 : * Displace the mesh, if mesh displacement is enabled.
294 : */
295 : void displaceMesh();
296 :
297 : /**
298 : * Rebalance the (necessarily nonconforming) mesh.
299 : */
300 : void rebalanceMesh(mfem::ParMesh & pmesh);
301 :
302 : /**
303 : * Returns optional reference to the displacement GridFunction to apply to nodes.
304 : */
305 : std::optional<std::reference_wrapper<mfem::ParGridFunction const>>
306 : getMeshDisplacementGridFunction();
307 :
308 12544 : Moose::FEBackend feBackend() const override { return Moose::FEBackend::MFEM; }
309 :
310 : std::string solverTypeString(unsigned int solver_sys_num) override;
311 :
312 : /**
313 : * Calls Update() on all FE spaces
314 : */
315 : void updateFESpaces();
316 :
317 : /**
318 : * Calls Update() on all gridfunctions
319 : */
320 : void updateGridFunctions();
321 :
322 : /**
323 : * If AMR is enabled, request (and perform if needed) h-refinement
324 : */
325 2522 : bool hRefine() { return _problem_data.refiner && _problem_data.refiner->hRefine(); }
326 :
327 : /**
328 : * If AMR is enabled, request (and perform if needed) p-refinement
329 : */
330 2535 : bool pRefine() { return _problem_data.refiner && _problem_data.refiner->pRefine(); }
331 :
332 : /**
333 : * @returns a shared pointer to an MFEM parallel grid function
334 : */
335 5778 : std::shared_ptr<mfem::ParGridFunction> getGridFunction(const std::string & name)
336 : {
337 5778 : return _problem_data.gridfunctions.GetShared(name);
338 : }
339 :
340 : /**
341 : * @returns a shared pointer to an MFEM parallel complex grid function
342 : */
343 106 : std::shared_ptr<mfem::ParComplexGridFunction> getComplexGridFunction(const std::string & name)
344 : {
345 106 : return _problem_data.cmplx_gridfunctions.GetShared(name);
346 : }
347 :
348 : /**
349 : * Enumerates the supported numeric representations for MFEM variables and operators.
350 : */
351 : enum class NumericType
352 : {
353 : REAL,
354 : COMPLEX
355 : };
356 :
357 : /**
358 : * Retrieve the numeric type of the problem.
359 : */
360 1318 : NumericType getNumericType() const { return _num_type; }
361 :
362 : /**
363 : * Retrieve an MFEM object from the warehouse by system and name.
364 : */
365 : template <typename T>
366 : T & getMFEMObject(const std::string & system,
367 : const std::string & name,
368 : const THREAD_ID tid = 0) const;
369 :
370 : /**
371 : * Determine whether an MFEM object with the supplied system and name exists.
372 : */
373 : bool hasMFEMObject(const std::string & system, const std::string & name) const;
374 :
375 : protected:
376 : struct MFEMSolverDefinition
377 : {
378 : std::string type;
379 : InputParameters * parameters;
380 : bool referenced = false;
381 : };
382 :
383 : /**
384 : * Aggregated MFEM-side state for meshes, spaces, variables, coefficients, and solvers.
385 : */
386 : MFEMProblemData _problem_data;
387 :
388 : /**
389 : * The numeric representation currently active for this problem.
390 : */
391 : NumericType _num_type;
392 :
393 : /**
394 : * Solver definitions recorded by AddMFEMSolverAction before the dependency resolver constructs
395 : * them. Each key is the user-provided solver object name, which corresponds to a child block
396 : * name under [Solvers]. Solver parameters of type MFEMSolverName refer to these same keys when
397 : * declaring dependencies between solver objects.
398 : */
399 : std::map<std::string, MFEMSolverDefinition> _mfem_solver_definitions;
400 : };
401 :
402 : template <typename T>
403 : T &
404 9272 : MFEMProblem::getMFEMObject(const std::string & system,
405 : const std::string & name,
406 : const THREAD_ID tid) const
407 : {
408 9272 : std::vector<T *> objs;
409 9272 : theWarehouse()
410 : .query()
411 18544 : .condition<AttribSystem>(system)
412 9272 : .condition<AttribThread>(tid)
413 9272 : .condition<AttribName>(name)
414 9272 : .queryInto(objs);
415 9272 : if (objs.empty())
416 0 : mooseError("Unable to find MFEM object with system '" + system + "' and name '" + name + "'");
417 : mooseAssert(objs.size() == 1, "Shouldn't find more than one object with given system and name");
418 18544 : return *(objs[0]);
419 9272 : }
420 :
421 : #endif
|