Line data Source code
1 : //* This file is part of the MOOSE framework
2 : //* https://www.mooseframework.org
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 : #pragma once
11 :
12 : #include "KokkosSystem.h"
13 : #include "KokkosAssembly.h"
14 :
15 : class MooseMesh;
16 : class SystemBase;
17 :
18 : namespace Moose::Kokkos
19 : {
20 :
21 : class NodalBCBase;
22 :
23 : /**
24 : * The Kokkos FE system class. Each system in MOOSE with FE variables has a corresponding Kokkos FE
25 : * system.
26 : */
27 : class FESystem : public System, public AssemblyHolder
28 : {
29 : public:
30 : /**
31 : * Constructor for standalone use (pure FE simulations)
32 : * @param system The associated MOOSE system
33 : */
34 : FESystem(SystemBase & system);
35 :
36 : /**
37 : * Constructor for mixed FE+FV simulations, sharing device memory with an existing System
38 : * @param base The existing Kokkos System whose device memory to share
39 : * @param system The associated MOOSE system
40 : */
41 : FESystem(System & base, SystemBase & system);
42 :
43 : #ifdef MOOSE_KOKKOS_SCOPE
44 : ///@}
45 : /**
46 : * Allocate the quadrature point vectors for active variable and tags and cache
47 : * quadrature point values
48 : */
49 : void reinit();
50 :
51 : /**
52 : * Get the list of off-diagonal coupled variable numbers of a variable
53 : * @param var The variable number
54 : * @returns The list of off-diagonal coupled variable numbers
55 : */
56 311773 : KOKKOS_FUNCTION const auto & getCoupling(unsigned int var) const { return _coupling[var]; }
57 :
58 : /**
59 : * Check whether a local DOF index is associated with a nodal BC for an extra matrix tag
60 : * @param dof The local DOF index
61 : * @param tag The extra matrix tag
62 : * @returns Whether the local DOF index is covered by a nodal BC
63 : */
64 15301638 : KOKKOS_FUNCTION bool hasNodalBCMatrixTag(dof_id_type dof, TagID tag) const
65 : {
66 15301638 : return _nbc_matrix_tag_dof[tag].isAlloc() && _nbc_matrix_tag_dof[tag][dof];
67 : }
68 :
69 : /**
70 : * Get the FE type ID of a variable
71 : * @param var The variable number
72 : * @returns The FE type ID
73 : */
74 18747900 : KOKKOS_FUNCTION unsigned int getFETypeID(unsigned int var) const { return _var_fe_types[var]; }
75 :
76 : /**
77 : * Get the local DOF index of a variable for a node
78 : * @param node The contiguous node ID
79 : * @param i The node-local DOF index
80 : * @param var The variable number
81 : * @returns The local DOF index
82 : */
83 7423436 : KOKKOS_FUNCTION dof_id_type getNodeLocalDofIndex(ContiguousNodeID node,
84 : unsigned int i,
85 : unsigned int var) const
86 : {
87 7423436 : return _local_node_dof_index[var][node] + i;
88 : }
89 :
90 : /**
91 : * Get the global DOF index of a variable for a node
92 : * @param node The contiguous node ID
93 : * @param i The node-local DOF index
94 : * @param var The variable number
95 : * @returns The global DOF index
96 : */
97 354996 : KOKKOS_FUNCTION dof_id_type getNodeGlobalDofIndex(ContiguousNodeID node,
98 : unsigned int i,
99 : unsigned int var) const
100 : {
101 354996 : return _local_to_global_dof_index[getNodeLocalDofIndex(node, i, var)];
102 : }
103 :
104 : /**
105 : * Get whether a variable is defined on a node
106 : * @param node The contiguous node ID
107 : * @param var The variable number
108 : * @returns Whether the variable is defined on the node
109 : */
110 4992074 : KOKKOS_FUNCTION bool isNodalDefined(ContiguousNodeID node, unsigned int var) const
111 : {
112 4992074 : return _local_node_dof_index[var][node] != libMesh::DofObject::invalid_id;
113 : }
114 :
115 : /**
116 : * Get the DOF value of a tagged vector for automatic differentiation (AD)
117 : * @param dof The local DOF index
118 : * @param tag The vector tag
119 : * @param seed The derivative seed
120 : * @returns The DOF AD value with optional seed derivative
121 : */
122 : KOKKOS_FUNCTION ADReal getVectorDofADValue(const dof_id_type dof,
123 : const TagID tag,
124 : const Real seed) const;
125 : /**
126 : * Get the quadrature point value of a variable from a tagged vector
127 : * @param info The element information object
128 : * @param qp The subdomain-local flattened quadrature point index
129 : * @param var The variable number
130 : * @param tag The vector tag
131 : * @returns The quadrature value
132 : */
133 79909158 : KOKKOS_FUNCTION Real & getVectorQpValue(const ElementInfo info,
134 : const dof_id_type qp,
135 : const unsigned int var,
136 : const TagID tag) const
137 : {
138 79909158 : return _qp_solutions[tag](info.subdomain, var)[qp];
139 : }
140 : /**
141 : * Get the quadrature point value of a variable from a tagged vector for automatic differentiation
142 : * (AD)
143 : * @param info The element information object
144 : * @param offset The element's offset into the subdomain-local flattened quadrature point index
145 : * @param qp The local quadrature point index
146 : * @param var The variable number
147 : * @param tag The vector tag
148 : * @param seed The derivative seed
149 : * @returns The quadrature AD value
150 : */
151 : KOKKOS_FUNCTION ADReal getVectorQpADValue(const ElementInfo info,
152 : const dof_id_type offset,
153 : const dof_id_type qp,
154 : const unsigned int var,
155 : const TagID tag,
156 : const Real seed) const;
157 : /**
158 : * Get the quadrature point gradient of a variable from a tagged vector
159 : * @param info The element information object
160 : * @param qp The subdomain-local flattened quadrature point index
161 : * @param var The variable number
162 : * @param tag The vector tag
163 : * @returns The quadrature gradient
164 : */
165 109293042 : KOKKOS_FUNCTION Real3 & getVectorQpGrad(const ElementInfo info,
166 : const dof_id_type qp,
167 : const unsigned int var,
168 : const TagID tag) const
169 : {
170 109293042 : return _qp_solutions_grad[tag](info.subdomain, var)[qp];
171 : }
172 : /**
173 : * Get the quadrature point value of a vector variable from a tagged vector
174 : * @param info The element information object
175 : * @param qp The subdomain-local flattened quadrature point index
176 : * @param var The variable number
177 : * @param tag The vector tag
178 : * @returns The quadrature vector value
179 : */
180 4168469 : KOKKOS_FUNCTION Real3 & getVectorQpVectorValue(const ElementInfo info,
181 : const dof_id_type qp,
182 : const unsigned int var,
183 : const TagID tag) const
184 : {
185 4168469 : return _qp_vector_solutions[tag](info.subdomain, var)[qp];
186 : }
187 : /**
188 : * Get the quadrature point gradient of a vector variable from a tagged vector
189 : * @param info The element information object
190 : * @param qp The subdomain-local flattened quadrature point index
191 : * @param var The variable number
192 : * @param tag The vector tag
193 : * @returns The quadrature vector gradient
194 : */
195 4183822 : KOKKOS_FUNCTION Real33 & getVectorQpVectorGrad(const ElementInfo info,
196 : const dof_id_type qp,
197 : const unsigned int var,
198 : const TagID tag) const
199 : {
200 4183822 : return _qp_vector_solutions_grad[tag](info.subdomain, var)[qp];
201 : }
202 : /**
203 : * Get the quadrature point curl of a vector variable from a tagged vector
204 : * @param info The element information object
205 : * @param qp The subdomain-local flattened quadrature point index
206 : * @param var The variable number
207 : * @param tag The vector tag
208 : * @returns The quadrature vector curl
209 : */
210 3056613 : KOKKOS_FUNCTION Real3 & getVectorQpVectorCurl(const ElementInfo info,
211 : const dof_id_type qp,
212 : const unsigned int var,
213 : const TagID tag) const
214 : {
215 3056613 : return _qp_vector_solutions_curl[tag](info.subdomain, var)[qp];
216 : }
217 : /**
218 : * Get the quadrature point gradient of a variable from a tagged vector for automatic
219 : * differentiation (AD)
220 : * @param info The element information object
221 : * @param jacobian The inverse Jacobian matrix
222 : * @param offset The element's offset into the subdomain-local flattened quadrature point index
223 : * @param qp The local quadrature point index
224 : * @param var The variable number
225 : * @param tag The vector tag
226 : * @param seed The derivative seed
227 : * @returns The quadrature AD gradient
228 : */
229 : KOKKOS_FUNCTION ADReal3 getVectorQpADGrad(const ElementInfo info,
230 : const Real33 jacobian,
231 : const dof_id_type offset,
232 : const dof_id_type qp,
233 : const unsigned int var,
234 : const TagID tag,
235 : const Real seed) const;
236 : /**
237 : * Get the face quadrature point value of a variable from a tagged vector
238 : * @param info The element information object
239 : * @param side The side index
240 : * @param qp The local quadrature point index
241 : * @param var The variable number
242 : * @param tag The vector tag
243 : * @returns The face quadrature value
244 : */
245 : KOKKOS_FUNCTION Real getVectorQpValueFace(const ElementInfo info,
246 : const unsigned int side,
247 : const unsigned int qp,
248 : const unsigned int var,
249 : const TagID tag) const;
250 : /**
251 : * Get the face quadrature point value of a vector variable from a tagged vector
252 : * @param info The element information object
253 : * @param side The side index
254 : * @param qp The local quadrature point index
255 : * @param var The variable number
256 : * @param tag The vector tag
257 : * @returns The face quadrature vector value
258 : */
259 : KOKKOS_FUNCTION Real3 getVectorQpVectorValueFace(const ElementInfo info,
260 : const unsigned int side,
261 : const unsigned int qp,
262 : const unsigned int var,
263 : const TagID tag) const;
264 : /**
265 : * Get the face quadrature point value of a variable from a tagged vector for automatic
266 : * differentiation (AD)
267 : * @param info The element information object
268 : * @param side The side index
269 : * @param qp The local quadrature point index
270 : * @param var The variable number
271 : * @param tag The vector tag
272 : * @param seed The derivative seed
273 : * @returns The face quadrature AD value
274 : */
275 : KOKKOS_FUNCTION ADReal getVectorQpADValueFace(const ElementInfo info,
276 : const unsigned int side,
277 : const unsigned int qp,
278 : const unsigned int var,
279 : const TagID tag,
280 : const Real seed) const;
281 : /**
282 : * Get the face quadrature point gradient of a variable from a tagged vector
283 : * @param info The element information object
284 : * @param side The side index
285 : * @param jacobian The inverse Jacobian matrix
286 : * @param qp The local quadrature point index
287 : * @param var The variable number
288 : * @param tag The vector tag
289 : * @returns The face quadrature gradient
290 : */
291 : KOKKOS_FUNCTION Real3 getVectorQpGradFace(const ElementInfo info,
292 : const unsigned int side,
293 : const Real33 jacobian,
294 : const unsigned int qp,
295 : const unsigned int var,
296 : const TagID tag) const;
297 : /**
298 : * Get the face quadrature point gradient of a vector variable from a tagged vector
299 : * @param info The element information object
300 : * @param side The side index
301 : * @param jacobian The inverse Jacobian matrix
302 : * @param qp The local quadrature point index
303 : * @param var The variable number
304 : * @param tag The vector tag
305 : * @returns The face quadrature vector gradient
306 : */
307 : KOKKOS_FUNCTION Real33 getVectorQpVectorGradFace(const ElementInfo info,
308 : const unsigned int side,
309 : const Real33 jacobian,
310 : const unsigned int qp,
311 : const unsigned int var,
312 : const TagID tag) const;
313 :
314 : /**
315 : * Get the face quadrature point gradient of a variable from a tagged vector for automatic
316 : * differentiation (AD)
317 : * @param info The element information object
318 : * @param side The side index
319 : * @param jacobian The inverse Jacobian matrix
320 : * @param qp The local quadrature point index
321 : * @param var The variable number
322 : * @param tag The vector tag
323 : * @param seed The derivative seed
324 : * @returns The face quadrature AD gradient
325 : */
326 : KOKKOS_FUNCTION ADReal3 getVectorQpADGradFace(const ElementInfo info,
327 : const unsigned int side,
328 : const Real33 jacobian,
329 : const unsigned int qp,
330 : const unsigned int var,
331 : const TagID tag,
332 : const Real seed) const;
333 :
334 : /**
335 : * Kokkos function for caching variable values on element quadrature points
336 : */
337 : KOKKOS_FUNCTION void operator()(const ThreadID tid) const;
338 : #endif
339 :
340 : private:
341 : /**
342 : * Setup variable data
343 : */
344 : void setupVariables();
345 :
346 : /**
347 : * Setup DOF data
348 : */
349 : void setupDofs();
350 :
351 : /**
352 : * Setup coupling data between variables
353 : */
354 : void setupCoupling();
355 :
356 : /**
357 : * Mark the DOFs covered by nodal BCs
358 : */
359 : void setupNodalBCDofs();
360 :
361 : /**
362 : * Get the list of DOFs covered by a nodal BC
363 : * @param nbc The Kokkos nodal BC object
364 : * @param dofs Local-plus-ghost DOF mask; entries are set true for DOFs covered by the nodal BC
365 : */
366 : void getNodalBCDofs(const NodalBCBase * nbc, Array<bool> & dofs);
367 :
368 : /**
369 : * Kokkos thread object
370 : */
371 : Thread<> _thread;
372 :
373 : /**
374 : * Cached elemental quadrature values and gradients
375 : */
376 : ///@{
377 : Array<Array2D<Array<Real>>> _qp_solutions;
378 : Array<Array2D<Array<Real3>>> _qp_solutions_grad;
379 : Array<Array2D<Array<Real3>>> _qp_vector_solutions;
380 : Array<Array2D<Array<Real33>>> _qp_vector_solutions_grad;
381 : Array<Array2D<Array<Real3>>> _qp_vector_solutions_curl;
382 : ///@}
383 :
384 : /**
385 : * Local nodal DOF indices of each variable
386 : */
387 : Array<Array<dof_id_type>> _local_node_dof_index;
388 :
389 : /**
390 : * FE type ID of each variable
391 : */
392 : Array<unsigned int> _var_fe_types;
393 :
394 : /**
395 : * Whether each variable is vector-valued
396 : */
397 : Array<bool> _var_is_vector;
398 :
399 : /**
400 : * Off-diagonal coupled variable numbers of each variable
401 : */
402 : Array<Array<unsigned int>> _coupling;
403 :
404 : /**
405 : * Per-matrix-tag local-plus-ghost DOF masks for nodal BC coverage
406 : */
407 : Array<Array<bool>> _nbc_matrix_tag_dof;
408 : };
409 :
410 : #ifdef MOOSE_KOKKOS_SCOPE
411 :
412 : KOKKOS_FUNCTION inline ADReal
413 17390912 : FESystem::getVectorDofADValue(const dof_id_type dof, TagID tag, const Real seed) const
414 : {
415 17390912 : ADReal value = _vectors[tag][dof];
416 :
417 17390912 : if (seed != 0)
418 17298214 : value.derivatives().insert(_local_to_global_dof_index[dof]) = seed;
419 :
420 17390912 : return value;
421 0 : }
422 :
423 : KOKKOS_FUNCTION inline ADReal
424 2270400 : FESystem::getVectorQpADValue(const ElementInfo info,
425 : const dof_id_type offset,
426 : const dof_id_type qp,
427 : const unsigned int var,
428 : const TagID tag,
429 : const Real seed) const
430 : {
431 2270400 : ADReal value = 0;
432 :
433 2270400 : if (seed == 0)
434 16800 : value = getVectorQpValue(info, offset + qp, var, tag);
435 : else
436 : {
437 2253600 : auto fe = _var_fe_types[var];
438 2253600 : auto n_dofs = kokkosAssembly().getNumDofs(info.type, fe);
439 2253600 : auto & phi = kokkosAssembly().getPhi(info.subdomain, info.type, fe);
440 :
441 11268000 : for (unsigned int i = 0; i < n_dofs; ++i)
442 9014400 : value += getVectorDofADValue(getElemLocalDofIndex(info.id, i, var), tag, seed) * phi(i, qp);
443 : }
444 :
445 2270400 : return value;
446 0 : }
447 :
448 : KOKKOS_FUNCTION inline ADReal3
449 2368704 : FESystem::getVectorQpADGrad(const ElementInfo info,
450 : const Real33 jacobian,
451 : const dof_id_type offset,
452 : const dof_id_type qp,
453 : const unsigned int var,
454 : const TagID tag,
455 : const Real seed) const
456 : {
457 2368704 : ADReal3 grad;
458 :
459 2368704 : if (seed == 0)
460 275920 : grad = getVectorQpGrad(info, offset + qp, var, tag);
461 : else
462 : {
463 2092784 : auto fe = _var_fe_types[var];
464 2092784 : auto n_dofs = kokkosAssembly().getNumDofs(info.type, fe);
465 2092784 : auto & grad_phi = kokkosAssembly().getGradPhi(info.subdomain, info.type, fe);
466 :
467 10341680 : for (unsigned int i = 0; i < n_dofs; ++i)
468 8248896 : grad +=
469 16497792 : getVectorDofADValue(getElemLocalDofIndex(info.id, i, var), tag, seed) * grad_phi(i, qp);
470 :
471 2092784 : grad = jacobian * grad;
472 : }
473 :
474 2368704 : return grad;
475 0 : }
476 :
477 : KOKKOS_FUNCTION inline Real
478 221890 : FESystem::getVectorQpValueFace(const ElementInfo info,
479 : const unsigned int side,
480 : const unsigned int qp,
481 : const unsigned int var,
482 : const TagID tag) const
483 : {
484 221890 : auto fe = _var_fe_types[var];
485 221890 : auto n_dofs = kokkosAssembly().getNumDofs(info.type, fe);
486 221890 : auto & phi = kokkosAssembly().getPhiFace(info.subdomain, info.type, fe)(side);
487 :
488 221890 : Real value = 0;
489 :
490 1120782 : for (unsigned int i = 0; i < n_dofs; ++i)
491 898892 : value += getVectorDofValue(getElemLocalDofIndex(info.id, i, var), tag) * phi(i, qp);
492 :
493 221890 : return value;
494 : }
495 :
496 : KOKKOS_FUNCTION inline Real3
497 53760 : FESystem::getVectorQpVectorValueFace(const ElementInfo info,
498 : const unsigned int side,
499 : const unsigned int qp,
500 : const unsigned int var,
501 : const TagID tag) const
502 : {
503 53760 : auto fe = _var_fe_types[var];
504 53760 : auto n_dofs = kokkosAssembly().getNumDofs(info.type, fe);
505 53760 : auto & phi = kokkosAssembly().getVectorPhiFace(info.subdomain, info.type, fe)(side);
506 :
507 53760 : Real3 value = 0;
508 :
509 483840 : for (unsigned int i = 0; i < n_dofs; ++i)
510 430080 : value += getVectorDofValue(getElemLocalDofIndex(info.id, i, var), tag) * phi(i, qp);
511 :
512 53760 : return value;
513 : }
514 :
515 : KOKKOS_FUNCTION inline ADReal
516 15148 : FESystem::getVectorQpADValueFace(const ElementInfo info,
517 : const unsigned int side,
518 : const unsigned int qp,
519 : const unsigned int var,
520 : const TagID tag,
521 : const Real seed) const
522 : {
523 15148 : auto fe = _var_fe_types[var];
524 15148 : auto n_dofs = kokkosAssembly().getNumDofs(info.type, fe);
525 15148 : auto & phi = kokkosAssembly().getPhiFace(info.subdomain, info.type, fe)(side);
526 :
527 15148 : ADReal value = 0;
528 :
529 73924 : for (unsigned int i = 0; i < n_dofs; ++i)
530 58776 : value += getVectorDofADValue(getElemLocalDofIndex(info.id, i, var), tag, seed) * phi(i, qp);
531 :
532 15148 : return value;
533 0 : }
534 :
535 : KOKKOS_FUNCTION inline Real3
536 0 : FESystem::getVectorQpGradFace(const ElementInfo info,
537 : const unsigned int side,
538 : const Real33 jacobian,
539 : const unsigned int qp,
540 : const unsigned int var,
541 : const TagID tag) const
542 : {
543 0 : auto fe = _var_fe_types[var];
544 0 : auto n_dofs = kokkosAssembly().getNumDofs(info.type, fe);
545 0 : auto & grad_phi = kokkosAssembly().getGradPhiFace(info.subdomain, info.type, fe)(side);
546 :
547 0 : Real3 grad = 0;
548 :
549 0 : for (unsigned int i = 0; i < n_dofs; ++i)
550 0 : grad += getVectorDofValue(getElemLocalDofIndex(info.id, i, var), tag) * grad_phi(i, qp);
551 :
552 0 : grad = jacobian * grad;
553 :
554 0 : return grad;
555 : }
556 :
557 : KOKKOS_FUNCTION inline Real33
558 0 : FESystem::getVectorQpVectorGradFace(const ElementInfo info,
559 : const unsigned int side,
560 : const Real33 jacobian,
561 : const unsigned int qp,
562 : const unsigned int var,
563 : const TagID tag) const
564 : {
565 0 : auto fe = _var_fe_types[var];
566 0 : auto n_dofs = kokkosAssembly().getNumDofs(info.type, fe);
567 0 : auto & grad_phi = kokkosAssembly().getVectorGradPhiFace(info.subdomain, info.type, fe)(side);
568 :
569 0 : Real33 grad = 0;
570 :
571 0 : for (unsigned int i = 0; i < n_dofs; ++i)
572 0 : grad += getVectorDofValue(getElemLocalDofIndex(info.id, i, var), tag) * grad_phi(i, qp);
573 :
574 0 : grad = grad * jacobian.transpose();
575 :
576 0 : return grad;
577 : }
578 :
579 : KOKKOS_FUNCTION inline ADReal3
580 0 : FESystem::getVectorQpADGradFace(const ElementInfo info,
581 : const unsigned int side,
582 : const Real33 jacobian,
583 : const unsigned int qp,
584 : const unsigned int var,
585 : const TagID tag,
586 : const Real seed) const
587 : {
588 0 : auto fe = _var_fe_types[var];
589 0 : auto n_dofs = kokkosAssembly().getNumDofs(info.type, fe);
590 0 : auto & grad_phi = kokkosAssembly().getGradPhiFace(info.subdomain, info.type, fe)(side);
591 :
592 0 : ADReal3 grad = ADReal(0);
593 :
594 0 : for (unsigned int i = 0; i < n_dofs; ++i)
595 0 : grad += getVectorDofADValue(getElemLocalDofIndex(info.id, i, var), tag, seed) * grad_phi(i, qp);
596 :
597 0 : grad = jacobian * grad;
598 :
599 0 : return grad;
600 0 : }
601 : #endif
602 :
603 55872031 : MakeSystemHolder(FESystem);
604 : } // namespace Moose::Kokkos
|