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