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