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