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 "KokkosLinearFVKernel.h"
13 : #include "KokkosLinearFVBoundaryCondition.h"
14 : #include "KokkosDatum.h"
15 :
16 : namespace Moose::Kokkos
17 : {
18 :
19 : /**
20 : * Base class for Kokkos linear finite volume kernels that contribute on faces (flux terms). On
21 : * boundary faces the contribution comes from the boundary face data populated by the boundary
22 : * conditions acting on this kernel's variable.
23 : */
24 : class LinearFVFluxKernel : public LinearFVKernel
25 : {
26 : public:
27 : static InputParameters validParams();
28 :
29 : LinearFVFluxKernel(const InputParameters & parameters);
30 : LinearFVFluxKernel(const LinearFVFluxKernel & object);
31 :
32 : virtual void computeRightHandSide() override;
33 : virtual void computeMatrix() override;
34 : virtual void initialSetup() override;
35 :
36 : /// Whether this kernel needs boundary value data from its boundary conditions
37 312 : virtual bool needsBoundaryValueData() const { return false; }
38 : /// Whether this kernel needs boundary normal gradient data from its boundary conditions
39 28 : virtual bool needsBoundaryNormalGradientData() const { return false; }
40 : /// Whether this kernel has nonzero internal-face RHS contributions
41 0 : virtual bool hasInternalRightHandSideContribution() const { return true; }
42 :
43 : /// Tag dispatch type for internal-face right-hand side computation
44 : struct InternalRightHandSideLoop
45 : {
46 : };
47 : /// Tag dispatch type for boundary-face right-hand side computation
48 : struct BoundaryRightHandSideLoop
49 : {
50 : };
51 : /// Tag dispatch type for internal-face matrix computation
52 : struct InternalMatrixLoop
53 : {
54 : };
55 : /// Tag dispatch type for boundary-face matrix computation
56 : struct BoundaryMatrixLoop
57 : {
58 : };
59 :
60 : template <typename Derived>
61 : KOKKOS_FUNCTION void
62 : operator()(InternalRightHandSideLoop, const ThreadID tid, const Derived & kernel) const;
63 :
64 : template <typename Derived>
65 : KOKKOS_FUNCTION void
66 : operator()(BoundaryRightHandSideLoop, const ThreadID tid, const Derived & kernel) const;
67 :
68 : template <typename Derived>
69 : KOKKOS_FUNCTION void
70 : operator()(InternalMatrixLoop, const ThreadID tid, const Derived & kernel) const;
71 :
72 : template <typename Derived>
73 : KOKKOS_FUNCTION void
74 : operator()(BoundaryMatrixLoop, const ThreadID tid, const Derived & kernel) const;
75 :
76 : /**
77 : * Default methods to prevent compile errors when matrix/RHS contributions are not defined in the
78 : * derived class.
79 : */
80 : ///@{
81 : template <typename Derived>
82 : KOKKOS_FUNCTION Real computeInternalMatrixContribution(const FVDatum & datum) const;
83 : template <typename Derived>
84 : KOKKOS_FUNCTION Real computeInternalNeighborMatrixContribution(const FVDatum & datum) const;
85 : template <typename Derived>
86 : KOKKOS_FUNCTION Real computeBoundaryMatrixContribution(
87 : const FVDatum & datum, const int bc_index, const MOOSE_KOKKOS_INDEX_TYPE bc_face_index) const;
88 : template <typename Derived>
89 : KOKKOS_FUNCTION Real computeInternalRightHandSideContribution(const FVDatum & datum) const;
90 : template <typename Derived>
91 : KOKKOS_FUNCTION Real computeBoundaryRightHandSideContribution(
92 : const FVDatum & datum, const int bc_index, const MOOSE_KOKKOS_INDEX_TYPE bc_face_index) const;
93 : ///@}
94 :
95 : /**
96 : * Functions used to check if users have overriden the matrix hook methods, whose calculations can
97 : * be skipped when not overriden.
98 : * @returns The function pointer of the default hook method
99 : */
100 : ///@{
101 : template <typename Derived>
102 82208 : static auto defaultInternalMatrixContribution()
103 : {
104 82208 : return &LinearFVFluxKernel::computeInternalMatrixContribution<Derived>;
105 : }
106 :
107 : template <typename Derived>
108 0 : static auto defaultInternalNeighborMatrixContribution()
109 : {
110 0 : return &LinearFVFluxKernel::computeInternalNeighborMatrixContribution<Derived>;
111 : }
112 :
113 : template <typename Derived>
114 82208 : static auto defaultBoundaryMatrixContribution()
115 : {
116 82208 : return &LinearFVFluxKernel::computeBoundaryMatrixContribution<Derived>;
117 : }
118 : ///@}
119 :
120 : protected:
121 : /// Directed element side operated on by this flux kernel
122 : using FaceID = Pair<ContiguousElementID, unsigned int>;
123 : /// Directed boundary side and its compact boundary condition and BC-local face indices
124 : struct BoundaryFaceID
125 : {
126 : ContiguousElementID elem;
127 : unsigned int side;
128 : int bc_index;
129 : MOOSE_KOKKOS_INDEX_TYPE bc_face_index;
130 :
131 15913 : bool operator<(const BoundaryFaceID & other) const
132 : {
133 15913 : if (bc_index != other.bc_index)
134 3606 : return bc_index < other.bc_index;
135 12307 : if (elem != other.elem)
136 12191 : return elem < other.elem;
137 116 : return side < other.side;
138 : }
139 : };
140 :
141 : #ifndef NDEBUG
142 : /**
143 : * Whether this face has a mesh neighbor on a subdomain where this kernel's variable is active.
144 : * A mesh-internal face is treated as a boundary for a block-restricted variable when the adjacent
145 : * element is outside the variable's block restriction.
146 : */
147 : KOKKOS_FUNCTION bool hasFaceNeighbor(const FVDatum & datum) const;
148 :
149 : /// Whether this boundary face has a boundary condition data provider
150 : KOKKOS_FUNCTION bool hasBoundaryData(const FVDatum & datum, const int bc_index) const;
151 : #endif
152 :
153 : /// Boundary value coefficient for this boundary face
154 : KOKKOS_FUNCTION Real boundaryValueCoefficient(const int bc_index,
155 : const MOOSE_KOKKOS_INDEX_TYPE bc_face_index) const;
156 : /// Boundary value source for this boundary face
157 : KOKKOS_FUNCTION Real boundaryValueSource(const int bc_index,
158 : const MOOSE_KOKKOS_INDEX_TYPE bc_face_index) const;
159 : /// Boundary normal gradient coefficient for this boundary face
160 : KOKKOS_FUNCTION Real boundaryNormalGradientCoefficient(
161 : const int bc_index, const MOOSE_KOKKOS_INDEX_TYPE bc_face_index) const;
162 : /// Boundary normal gradient source for this boundary face
163 : KOKKOS_FUNCTION Real boundaryNormalGradientSource(
164 : const int bc_index, const MOOSE_KOKKOS_INDEX_TYPE bc_face_index) const;
165 :
166 : /// Boundary condition data handles indexed by compact boundary condition index
167 : Array<LinearFVBoundaryCondition::BoundaryData> _bc_data;
168 : /// Setup/debug map from (side, element) to compact boundary condition index
169 : Array2D<int> _bc_index;
170 : /// Directed internal element sides with an active variable on the neighbor element
171 : Array<FaceID> _internal_face_ids;
172 : /// Directed boundary element sides with active Kokkos boundary data
173 : Array<BoundaryFaceID> _boundary_face_ids;
174 :
175 : std::unique_ptr<DispatcherBase> _internal_rhs_dispatcher;
176 : std::unique_ptr<DispatcherBase> _boundary_rhs_dispatcher;
177 : std::unique_ptr<DispatcherBase> _internal_matrix_dispatcher;
178 : std::unique_ptr<DispatcherBase> _boundary_matrix_dispatcher;
179 : };
180 :
181 : #ifndef NDEBUG
182 : KOKKOS_FUNCTION inline bool
183 : LinearFVFluxKernel::hasFaceNeighbor(const FVDatum & datum) const
184 : {
185 : if (!datum.hasNeighbor())
186 : return false;
187 :
188 : const auto & sys = kokkosSystem(_var.sys());
189 : return sys.isVariableActive(_var.var(), datum.neighborSubdomain());
190 : }
191 :
192 : KOKKOS_FUNCTION inline bool
193 : LinearFVFluxKernel::hasBoundaryData(const FVDatum & datum, const int bc_index) const
194 : {
195 : return bc_index >= 0 && _bc_index.isAlloc() &&
196 : _bc_index(datum.side(), datum.elemID()) == bc_index;
197 : }
198 : #endif
199 :
200 : KOKKOS_FUNCTION inline Real
201 28 : LinearFVFluxKernel::boundaryValueCoefficient(const int bc_index,
202 : const MOOSE_KOKKOS_INDEX_TYPE bc_face_index) const
203 : {
204 : KOKKOS_ASSERT(bc_index >= 0);
205 28 : return _bc_data[bc_index].value.coefficient[bc_face_index];
206 : }
207 :
208 : KOKKOS_FUNCTION inline Real
209 28 : LinearFVFluxKernel::boundaryValueSource(const int bc_index,
210 : const MOOSE_KOKKOS_INDEX_TYPE bc_face_index) const
211 : {
212 : KOKKOS_ASSERT(bc_index >= 0);
213 28 : return _bc_data[bc_index].value.source[bc_face_index];
214 : }
215 :
216 : KOKKOS_FUNCTION inline Real
217 1570 : LinearFVFluxKernel::boundaryNormalGradientCoefficient(
218 : const int bc_index, const MOOSE_KOKKOS_INDEX_TYPE bc_face_index) const
219 : {
220 : KOKKOS_ASSERT(bc_index >= 0);
221 1570 : return _bc_data[bc_index].normal_gradient.coefficient[bc_face_index];
222 : }
223 :
224 : KOKKOS_FUNCTION inline Real
225 1570 : LinearFVFluxKernel::boundaryNormalGradientSource(const int bc_index,
226 : const MOOSE_KOKKOS_INDEX_TYPE bc_face_index) const
227 : {
228 : KOKKOS_ASSERT(bc_index >= 0);
229 1570 : return _bc_data[bc_index].normal_gradient.source[bc_face_index];
230 : }
231 :
232 : template <typename Derived>
233 : KOKKOS_FUNCTION Real
234 0 : LinearFVFluxKernel::computeInternalMatrixContribution(const FVDatum &) const
235 : {
236 0 : ::Kokkos::abort("Default computeInternalMatrixContribution() should never be called. Make sure "
237 : "you properly redefined this method in your class without typos.");
238 :
239 : return 0;
240 : }
241 :
242 : template <typename Derived>
243 : KOKKOS_FUNCTION Real
244 0 : LinearFVFluxKernel::computeInternalNeighborMatrixContribution(const FVDatum &) const
245 : {
246 0 : ::Kokkos::abort("Default computeInternalNeighborMatrixContribution() should never be called. "
247 : "Make sure you properly redefined this method in your class without typos.");
248 :
249 : return 0;
250 : }
251 :
252 : template <typename Derived>
253 : KOKKOS_FUNCTION Real
254 0 : LinearFVFluxKernel::computeBoundaryMatrixContribution(const FVDatum &,
255 : const int,
256 : const MOOSE_KOKKOS_INDEX_TYPE) const
257 : {
258 0 : ::Kokkos::abort("Default computeBoundaryMatrixContribution() should never be called. Make sure "
259 : "you properly redefined this method in your class without typos.");
260 :
261 : return 0;
262 : }
263 :
264 : template <typename Derived>
265 : KOKKOS_FUNCTION Real
266 0 : LinearFVFluxKernel::computeInternalRightHandSideContribution(const FVDatum &) const
267 : {
268 0 : ::Kokkos::abort("Default computeInternalRightHandSideContribution() should never be called. Make "
269 : "sure you properly redefined this method in your class without typos.");
270 :
271 : return 0;
272 : }
273 :
274 : template <typename Derived>
275 : KOKKOS_FUNCTION Real
276 : LinearFVFluxKernel::computeBoundaryRightHandSideContribution(const FVDatum &,
277 : const int,
278 : const MOOSE_KOKKOS_INDEX_TYPE) const
279 : {
280 : ::Kokkos::abort("Default computeBoundaryRightHandSideContribution() should never be called. Make "
281 : "sure you properly redefined this method in your class without typos.");
282 :
283 : return 0;
284 : }
285 :
286 : template <typename Derived>
287 : KOKKOS_FUNCTION void
288 0 : LinearFVFluxKernel::operator()(InternalRightHandSideLoop,
289 : const ThreadID tid,
290 : const Derived & kernel) const
291 : {
292 0 : const auto [elem, side] = _internal_face_ids[tid];
293 0 : FVDatum datum(elem, side, kokkosMesh());
294 : KOKKOS_ASSERT(hasFaceNeighbor(datum));
295 :
296 : KOKKOS_ASSERT(_var.components() == 1);
297 0 : const auto & sys = kokkosSystem(_var.sys());
298 0 : kernel.accumulateTaggedVector(
299 : kernel.template computeInternalRightHandSideContribution<Derived>(datum),
300 : sys.getElemLocalDofIndex(elem, 0, _var.var()));
301 0 : }
302 :
303 : template <typename Derived>
304 : KOKKOS_FUNCTION void
305 1598 : LinearFVFluxKernel::operator()(BoundaryRightHandSideLoop,
306 : const ThreadID tid,
307 : const Derived & kernel) const
308 : {
309 1598 : const auto [elem, side, bc_index, bc_face_index] = _boundary_face_ids[tid];
310 1598 : FVDatum datum(elem, side, kokkosMesh());
311 : KOKKOS_ASSERT(hasBoundaryData(datum, bc_index));
312 :
313 : KOKKOS_ASSERT(_var.components() == 1);
314 1598 : const auto & sys = kokkosSystem(_var.sys());
315 1598 : kernel.accumulateTaggedVector(kernel.template computeBoundaryRightHandSideContribution<Derived>(
316 : datum, bc_index, bc_face_index),
317 : sys.getElemLocalDofIndex(elem, 0, _var.var()));
318 1598 : }
319 :
320 : template <typename Derived>
321 : KOKKOS_FUNCTION void
322 39858 : LinearFVFluxKernel::operator()(InternalMatrixLoop, const ThreadID tid, const Derived & kernel) const
323 : {
324 39858 : const auto [elem, side] = _internal_face_ids[tid];
325 39858 : FVDatum datum(elem, side, kokkosMesh());
326 : KOKKOS_ASSERT(hasFaceNeighbor(datum));
327 :
328 : KOKKOS_ASSERT(_var.components() == 1);
329 39858 : const auto var_num = _var.var();
330 39858 : const auto & sys = kokkosSystem(_var.sys());
331 39858 : const auto row = sys.getElemLocalDofIndex(elem, 0, var_num);
332 39858 : kernel.accumulateTaggedMatrix(kernel.template computeInternalMatrixContribution<Derived>(datum),
333 : row,
334 : sys.getElemGlobalDofIndex(elem, 0, var_num));
335 39858 : kernel.accumulateTaggedMatrix(
336 : kernel.template computeInternalNeighborMatrixContribution<Derived>(datum),
337 : row,
338 : sys.getElemGlobalDofIndex(datum.neighborID(), 0, var_num));
339 39858 : }
340 :
341 : template <typename Derived>
342 : KOKKOS_FUNCTION void
343 1598 : LinearFVFluxKernel::operator()(BoundaryMatrixLoop, const ThreadID tid, const Derived & kernel) const
344 : {
345 1598 : const auto [elem, side, bc_index, bc_face_index] = _boundary_face_ids[tid];
346 1598 : FVDatum datum(elem, side, kokkosMesh());
347 : KOKKOS_ASSERT(hasBoundaryData(datum, bc_index));
348 :
349 : KOKKOS_ASSERT(_var.components() == 1);
350 1598 : const auto var_num = _var.var();
351 1598 : const auto & sys = kokkosSystem(_var.sys());
352 1598 : const auto row = sys.getElemLocalDofIndex(elem, 0, var_num);
353 1598 : kernel.accumulateTaggedMatrix(
354 : kernel.template computeBoundaryMatrixContribution<Derived>(datum, bc_index, bc_face_index),
355 : row,
356 : sys.getElemGlobalDofIndex(elem, 0, var_num));
357 1598 : }
358 :
359 : } // namespace Moose::Kokkos
|