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