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 : #pragma once
11 :
12 : #include <tuple>
13 :
14 : #include "MooseFunctorForward.h"
15 : #include "MooseFunctorArguments.h"
16 : #include "FaceArgInterface.h"
17 : #include "MooseMesh.h"
18 : #include "MooseTypes.h"
19 : #include "MooseError.h"
20 : #include "MooseUtils.h"
21 :
22 : #include "libmesh/remote_elem.h"
23 : #include "libmesh/tensor_tools.h"
24 :
25 : #include "metaphysicl/ct_types.h"
26 :
27 : #include <unordered_map>
28 : #include <functional>
29 :
30 : namespace Moose
31 : {
32 : /**
33 : * An enumeration of possible functor evaluation kinds. The available options are value, gradient,
34 : * time derivative (dot), and gradient of time derivative (gradDot)
35 : */
36 : enum class FunctorEvaluationKind
37 : {
38 : Value,
39 : Gradient,
40 : Dot,
41 : GradDot
42 : };
43 :
44 : /**
45 : * A structure that defines the return type of a functor based on the type of the functor and the
46 : * requested evaluation kind, e.g. value, gradient, time derivative, or gradient of time derivative
47 : */
48 : template <typename, FunctorEvaluationKind>
49 : struct FunctorReturnType;
50 :
51 : /**
52 : * The return type for a value evaluation is just the type of the functor
53 : */
54 : template <typename T>
55 : struct FunctorReturnType<T, FunctorEvaluationKind::Value>
56 : {
57 : typedef T type;
58 : };
59 :
60 : /**
61 : * The return type of a gradient evaluation is the rank increment of a value return type. So if the
62 : * value type is Real, then a gradient will be a VectorValue<Real>. This also allows for containers
63 : * of mathematical types. So if a value type is std::vector<Real>, then the gradient type will be
64 : * std::vector<VectorValue<Real>>
65 : */
66 : template <typename T>
67 : struct FunctorReturnType<T, FunctorEvaluationKind::Gradient>
68 : {
69 : typedef typename MetaPhysicL::ReplaceAlgebraicType<
70 : T,
71 : typename libMesh::TensorTools::IncrementRank<
72 : typename MetaPhysicL::ValueType<T>::type>::type>::type type;
73 : };
74 :
75 : /**
76 : * The return type of a time derivative evaluation is the same as the value type
77 : */
78 : template <typename T>
79 : struct FunctorReturnType<T, FunctorEvaluationKind::Dot>
80 : {
81 : typedef T type;
82 : };
83 :
84 : /**
85 : * The return type of a gradient of time derivative evaluation is the same as the gradient type
86 : */
87 : template <typename T>
88 : struct FunctorReturnType<T, FunctorEvaluationKind::GradDot>
89 : {
90 : typedef typename FunctorReturnType<T, FunctorEvaluationKind::Gradient>::type type;
91 : };
92 :
93 : /**
94 : * This structure takes an evaluation kind as a template argument and defines a constant expression
95 : * indicating the associated gradient kind
96 : */
97 : template <FunctorEvaluationKind>
98 : struct FunctorGradientEvaluationKind;
99 :
100 : /**
101 : * The gradient kind associated with a value is simply the gradient
102 : */
103 : template <>
104 : struct FunctorGradientEvaluationKind<FunctorEvaluationKind::Value>
105 : {
106 : static constexpr FunctorEvaluationKind value = FunctorEvaluationKind::Gradient;
107 : };
108 :
109 : /**
110 : * The gradient kind associated with a time derivative is the gradient of the time derivative
111 : */
112 : template <>
113 : struct FunctorGradientEvaluationKind<FunctorEvaluationKind::Dot>
114 : {
115 : static constexpr FunctorEvaluationKind value = FunctorEvaluationKind::GradDot;
116 : };
117 :
118 : /**
119 : * Abstract base class that can be used to hold collections of functors
120 : */
121 : class FunctorAbstract : public FaceArgInterface
122 : {
123 : public:
124 : virtual void residualSetup() = 0;
125 : virtual void jacobianSetup() = 0;
126 : virtual void timestepSetup() = 0;
127 : virtual void customSetup(const ExecFlagType & exec_type) = 0;
128 : };
129 :
130 : /**
131 : * Base class template for functor objects. This class template defines various \p operator()
132 : * overloads that allow a user to evaluate the functor at arbitrary geometric locations. This
133 : * template is meant to enable highly flexible on-the-fly variable and material property
134 : * evaluations
135 : */
136 : template <typename T>
137 : class FunctorBase : public FunctorAbstract
138 : {
139 : public:
140 : using FunctorType = FunctorBase<T>;
141 : using ValueType = T;
142 : /// This rigmarole makes it so that a user can create functors that return containers (std::vector,
143 : /// std::array). This logic will make it such that if a user requests a functor type T that is a
144 : /// container of algebraic types, for example Reals, then the GradientType will be a container of
145 : /// the gradients of those algebraic types, in this example VectorValue<Reals>. So if T is
146 : /// std::vector<Real>, then GradientType will be std::vector<VectorValue<Real>>. As another
147 : /// example: T = std::array<VectorValue<Real>, 1> -> GradientType = std::array<TensorValue<Real>,
148 : /// 1>
149 : using GradientType = typename FunctorReturnType<T, FunctorEvaluationKind::Gradient>::type;
150 : using DotType = ValueType;
151 :
152 1123946 : virtual ~FunctorBase() = default;
153 1196822 : FunctorBase(const MooseFunctorName & name,
154 : const std::set<ExecFlagType> & clearance_schedule = {EXEC_ALWAYS})
155 1196822 : : _always_evaluate(true), _functor_name(name)
156 :
157 : {
158 1196822 : setCacheClearanceSchedule(clearance_schedule);
159 1196822 : }
160 :
161 : /**
162 : * Perform a generic evaluation based on the supplied template argument \p FET and supplied
163 : * spatial and temporal arguments
164 : */
165 : template <FunctorEvaluationKind FET, typename Space, typename State>
166 : typename FunctorReturnType<T, FET>::type genericEvaluate(const Space & r,
167 : const State & state) const;
168 :
169 : /// Return the functor name
170 893729 : const MooseFunctorName & functorName() const { return _functor_name; }
171 :
172 : ///@{
173 : /**
174 : * Same as their \p evaluate overloads with the same arguments but allows for caching
175 : * implementation. These are the methods a user will call in their code
176 : */
177 : ValueType operator()(const ElemArg & elem, const StateArg & state) const;
178 : ValueType operator()(const FaceArg & face, const StateArg & state) const;
179 : ValueType operator()(const ElemQpArg & qp, const StateArg & state) const;
180 : ValueType operator()(const ElemSideQpArg & qp, const StateArg & state) const;
181 : ValueType operator()(const ElemPointArg & elem_point, const StateArg & state) const;
182 : ValueType operator()(const NodeArg & node, const StateArg & state) const;
183 : ///@}
184 :
185 : ///@{
186 : /**
187 : * Same as their \p evaluateGradient overloads with the same arguments but allows for caching
188 : * implementation. These are the methods a user will call in their code
189 : */
190 : GradientType gradient(const ElemArg & elem, const StateArg & state) const;
191 : GradientType gradient(const FaceArg & face, const StateArg & state) const;
192 : GradientType gradient(const ElemQpArg & qp, const StateArg & state) const;
193 : GradientType gradient(const ElemSideQpArg & qp, const StateArg & state) const;
194 : GradientType gradient(const ElemPointArg & elem_point, const StateArg & state) const;
195 : GradientType gradient(const NodeArg & node, const StateArg & state) const;
196 : ///@}
197 :
198 : ///@{
199 : /**
200 : * Same as their \p evaluateDot overloads with the same arguments but allows for caching
201 : * implementation. These are the methods a user will call in their code
202 : */
203 : DotType dot(const ElemArg & elem, const StateArg & state) const;
204 : DotType dot(const FaceArg & face, const StateArg & state) const;
205 : DotType dot(const ElemQpArg & qp, const StateArg & state) const;
206 : DotType dot(const ElemSideQpArg & qp, const StateArg & state) const;
207 : DotType dot(const ElemPointArg & elem_point, const StateArg & state) const;
208 : DotType dot(const NodeArg & node, const StateArg & state) const;
209 : ///@}
210 :
211 : ///@{
212 : /**
213 : * Same as their \p evaluateGradDot overloads with the same arguments but allows for caching
214 : * implementation. These are the methods a user will call in their code
215 : */
216 : GradientType gradDot(const ElemArg & elem, const StateArg & state) const;
217 : GradientType gradDot(const FaceArg & face, const StateArg & state) const;
218 : GradientType gradDot(const ElemQpArg & qp, const StateArg & state) const;
219 : GradientType gradDot(const ElemSideQpArg & qp, const StateArg & state) const;
220 : GradientType gradDot(const ElemPointArg & elem_point, const StateArg & state) const;
221 : GradientType gradDot(const NodeArg & node, const StateArg & state) const;
222 : ///@}
223 :
224 : virtual void residualSetup() override;
225 : virtual void jacobianSetup() override;
226 : virtual void timestepSetup() override;
227 : virtual void customSetup(const ExecFlagType & exec_type) override;
228 :
229 : /**
230 : * Set how often to clear the functor evaluation cache
231 : */
232 : void setCacheClearanceSchedule(const std::set<ExecFlagType> & clearance_schedule);
233 :
234 : /**
235 : * Returns whether the functor is defined on this block
236 : */
237 0 : virtual bool hasBlocks(SubdomainID /* id */) const
238 : {
239 0 : mooseError("Block restriction has not been implemented for functor " + functorName());
240 : return false;
241 : }
242 :
243 : /**
244 : * Returns whether this (sided) face is an extrapolated boundary face for
245 : * this functor
246 : */
247 0 : virtual bool isExtrapolatedBoundaryFace(const FaceInfo &, const Elem *, const StateArg &) const
248 : {
249 0 : mooseError("not implemented");
250 : }
251 :
252 : /**
253 : * Returns true if the face is an internal face
254 : */
255 : bool isInternalFace(const FaceInfo &) const;
256 :
257 : /**
258 : * Returns true if this functor is a constant
259 : */
260 0 : virtual bool isConstant() const { return false; }
261 :
262 : virtual bool hasFaceSide(const FaceInfo & fi, const bool fi_elem_side) const override;
263 :
264 : /**
265 : * Examines the incoming face argument. If the face argument producer (residual object,
266 : * postprocessor, etc.) did not indicate a sidedness to the face, e.g. if the \p face_side member
267 : * of the \p FaceArg is \p nullptr, then we may "modify" the sidedness of the argument if we are
268 : * only defined on one side of the face. If the face argument producer \emph has indicated a
269 : * sidedness and we are not defined on that side, then we will error
270 : * @param face The face argument created by the face argument producer, likely a residual object
271 : * @return A face with possibly changed sidedness depending on whether we aren't defined on both
272 : * sides of the face
273 : */
274 : void checkFace(const Moose::FaceArg & face) const;
275 :
276 : /**
277 : * Whether this functor supports evaluation with FaceArg
278 : */
279 : virtual bool supportsFaceArg() const = 0;
280 :
281 : /**
282 : * Whether this functor supports evaluation with ElemSideQpArg
283 : */
284 : virtual bool supportsElemSideQpArg() const = 0;
285 :
286 : protected:
287 : /** @name Functor evaluation routines
288 : * These methods are all for evaluating functors with different kinds of spatial arguments. Each
289 : * of these methods also takes a state argument. For a description of the state argument, please
290 : * see the \p StateArg doxygen
291 : */
292 : ///@{
293 : /**
294 : * Evaluate the functor with a given element. Some example implementations of this method
295 : * could compute an element-average or evaluate at the element centroid
296 : */
297 : virtual ValueType evaluate(const ElemArg & elem, const StateArg & state) const = 0;
298 :
299 : /**
300 : * @param face See the \p FaceArg doxygen
301 : * @param state See the \p StateArg doxygen
302 : * @return The functor evaluated at the requested state and space
303 : */
304 : virtual ValueType evaluate(const FaceArg & face, const StateArg & state) const = 0;
305 :
306 : /**
307 : * @param qp See the \p ElemQpArg doxygen
308 : * @param state See the \p StateArg doxygen
309 : * @return The functor evaluated at the requested state and space
310 : */
311 : virtual ValueType evaluate(const ElemQpArg & qp, const StateArg & state) const = 0;
312 :
313 : /**
314 : * @param side_qp See the \p ElemSideQpArg doxygen
315 : * @param state See the \p StateArg doxygen
316 : * @return The functor evaluated at the requested state and space
317 : */
318 : virtual ValueType evaluate(const ElemSideQpArg & side_qp, const StateArg & state) const = 0;
319 :
320 : /**
321 : * Evaluate the functor with a given element and point. Some example implementations of this
322 : * method could perform a two-term Taylor expansion using cell-centered value and gradient
323 : */
324 : virtual ValueType evaluate(const ElemPointArg & elem_point, const StateArg & state) const = 0;
325 :
326 : virtual ValueType evaluate(const NodeArg & node, const StateArg & state) const = 0;
327 :
328 : /**
329 : * Evaluate the functor gradient with a given element. Some example implementations of this
330 : * method could compute an element-average or evaluate at the element centroid
331 : */
332 1 : virtual GradientType evaluateGradient(const ElemArg &, const StateArg &) const
333 : {
334 1 : mooseError("Element gradient not implemented for functor " + functorName());
335 : }
336 :
337 : /**
338 : * @param face See the \p FaceArg doxygen
339 : * @param state See the \p StateArg doxygen
340 : * @return The functor gradient evaluated at the requested state and space
341 : */
342 1 : virtual GradientType evaluateGradient(const FaceArg &, const StateArg &) const
343 : {
344 1 : mooseError("Face gradient not implemented for functor " + functorName());
345 : }
346 :
347 : /**
348 : * @param qp See the \p ElemQpArg doxygen
349 : * @param state See the \p StateArg doxygen
350 : * @return The functor gradient evaluated at the requested state and space
351 : */
352 1 : virtual GradientType evaluateGradient(const ElemQpArg &, const StateArg &) const
353 : {
354 1 : mooseError("Element quadrature point gradient not implemented for functor " + functorName());
355 : }
356 :
357 : /**
358 : * @param side_qp See the \p ElemSideQpArg doxygen
359 : * @param state See the \p StateArg doxygen
360 : * @return The functor gradient evaluated at the requested state and space
361 : */
362 1 : virtual GradientType evaluateGradient(const ElemSideQpArg &, const StateArg &) const
363 : {
364 1 : mooseError("Element side quadrature point gradient not implemented for functor " +
365 1 : functorName());
366 : }
367 :
368 : /**
369 : * Evaluate the functor gradient with a given element and point
370 : */
371 1 : virtual GradientType evaluateGradient(const ElemPointArg &, const StateArg &) const
372 : {
373 1 : mooseError("Element-point gradient not implemented for functor " + functorName());
374 : }
375 :
376 1 : virtual GradientType evaluateGradient(const NodeArg &, const StateArg &) const
377 : {
378 1 : mooseError("Gradient at node not implemented for functor " + functorName());
379 : }
380 :
381 : /**
382 : * Evaluate the functor time derivative with a given element. Some example implementations of
383 : * this method could compute an element-average or evaluate at the element centroid
384 : */
385 1 : virtual DotType evaluateDot(const ElemArg &, const StateArg &) const
386 : {
387 1 : mooseError("Element time derivative not implemented for functor " + functorName());
388 : }
389 :
390 : /**
391 : * @param face See the \p FaceArg doxygen
392 : * @param state See the \p StateArg doxygen
393 : * @return The functor time derivative evaluated at the requested state and space
394 : */
395 1 : virtual DotType evaluateDot(const FaceArg &, const StateArg &) const
396 : {
397 1 : mooseError("Face time derivative not implemented for functor " + functorName());
398 : }
399 :
400 : /**
401 : * @param qp See the \p ElemQpArg doxygen
402 : * @param state See the \p StateArg doxygen
403 : * @return The functor time derivative evaluated at the requested state and space
404 : */
405 4 : virtual DotType evaluateDot(const ElemQpArg &, const StateArg &) const
406 : {
407 4 : mooseError("Element quadrature point time derivative not implemented for functor " +
408 4 : functorName());
409 : }
410 :
411 : /**
412 : * @param side_qp See the \p ElemSideQpArg doxygen
413 : * @param state See the \p StateArg doxygen
414 : * @return The functor time derivative evaluated at the requested state and space
415 : */
416 1 : virtual DotType evaluateDot(const ElemSideQpArg &, const StateArg &) const
417 : {
418 1 : mooseError("Element side quadrature point time derivative not implemented for functor " +
419 1 : functorName());
420 : }
421 :
422 : /**
423 : * Evaluate the functor time derivative with a given element and point
424 : */
425 1 : virtual DotType evaluateDot(const ElemPointArg &, const StateArg &) const
426 : {
427 1 : mooseError("Element-point time derivative not implemented for functor " + functorName());
428 : }
429 :
430 1 : virtual DotType evaluateDot(const NodeArg &, const StateArg &) const
431 : {
432 1 : mooseError("Time derivative at node not implemented for functor " + functorName());
433 : }
434 :
435 : /**
436 : * Evaluate the functor gradient-dot with a given element. Some example implementations of this
437 : * method could compute an element-average or evaluate at the element centroid
438 : */
439 0 : virtual GradientType evaluateGradDot(const ElemArg &, const StateArg &) const
440 : {
441 0 : mooseError("Element gradient-dot not implemented for functor " + functorName());
442 : }
443 :
444 : /**
445 : * @param face See the \p FaceArg doxygen
446 : * @param state See the \p StateArg doxygen
447 : * @return The functor gradient-dot evaluated at the requested state and space
448 : */
449 0 : virtual GradientType evaluateGradDot(const FaceArg &, const StateArg &) const
450 : {
451 0 : mooseError("Face gradient-dot not implemented for functor " + functorName());
452 : }
453 :
454 : /**
455 : * @param qp See the \p ElemQpArg doxygen
456 : * @param state See the \p StateArg doxygen
457 : * @return The functor gradient-dot evaluated at the requested state and space
458 : */
459 0 : virtual GradientType evaluateGradDot(const ElemQpArg &, const StateArg &) const
460 : {
461 0 : mooseError("Element quadrature point gradient-dot not implemented for functor " +
462 0 : functorName());
463 : }
464 :
465 : /**
466 : * @param side_qp See the \p ElemSideQpArg doxygen
467 : * @param state See the \p StateArg doxygen
468 : * @return The functor gradient-dot evaluated at the requested state and space
469 : */
470 0 : virtual GradientType evaluateGradDot(const ElemSideQpArg &, const StateArg &) const
471 : {
472 0 : mooseError("Element side quadrature point gradient-dot not implemented for functor " +
473 0 : functorName());
474 : }
475 :
476 : /**
477 : * Evaluate the functor gradient-dot with a given element and point
478 : */
479 0 : virtual GradientType evaluateGradDot(const ElemPointArg &, const StateArg &) const
480 : {
481 0 : mooseError("Element-point gradient-dot not implemented for functor " + functorName());
482 : }
483 :
484 0 : virtual GradientType evaluateGradDot(const NodeArg &, const StateArg &) const
485 : {
486 0 : mooseError("Gradient-dot at node not implemented for functor " + functorName());
487 : }
488 : ///@}
489 :
490 : private:
491 : /**
492 : * clear cache data
493 : */
494 : void clearCacheData();
495 :
496 : /**
497 : * check a qp cache and if invalid then evaluate
498 : */
499 : template <typename SpaceArg, typename StateArg>
500 : ValueType queryQpCache(unsigned int qp,
501 : const libMesh::QBase & qrule,
502 : std::vector<std::pair<bool, T>> & qp_cache_data,
503 : const SpaceArg & space,
504 : const StateArg & state) const;
505 :
506 : /**
507 : * check a finite volume spatial argument cache and if invalid then evaluate
508 : */
509 : template <typename SpaceArg>
510 : ValueType queryFVArgCache(std::map<SpaceArg, ValueType> & cache_data,
511 : const SpaceArg & space) const;
512 :
513 : /// How often to clear the material property cache
514 : std::set<ExecFlagType> _clearance_schedule;
515 :
516 : /// Boolean to check if we always need evaluation
517 : bool _always_evaluate;
518 :
519 : // Data for traditional element-quadrature point property evaluations which are useful for
520 : // caching implementation
521 :
522 : /// Current key for qp map cache
523 : mutable dof_id_type _current_qp_map_key = libMesh::DofObject::invalid_id;
524 :
525 : /// Current value for qp map cache
526 : mutable std::vector<std::pair<bool, ValueType>> * _current_qp_map_value = nullptr;
527 :
528 : /// Cached element quadrature point functor property evaluations. The map key is the element
529 : /// id. The map values should have size corresponding to the number of quadrature points on the
530 : /// element. The vector elements are pairs. The first member of the pair indicates whether a
531 : /// cached value has been computed. The second member of the pair is the (cached) value. If the
532 : /// boolean is false, then the value cannot be trusted
533 : mutable std::unordered_map<dof_id_type, std::vector<std::pair<bool, ValueType>>> _qp_to_value;
534 :
535 : // Data for traditional element-side-quadrature point property evaluations which are useful for
536 : // caching implementation
537 :
538 : /// Current key for side-qp map cache
539 : mutable dof_id_type _current_side_qp_map_key = libMesh::DofObject::invalid_id;
540 :
541 : /// Current value for side-qp map cache
542 : mutable std::vector<std::vector<std::pair<bool, ValueType>>> * _current_side_qp_map_value =
543 : nullptr;
544 :
545 : /// Cached element quadrature point functor property evaluations. The map key is the element
546 : /// id. The map values are a multi-dimensional vector (or vector of vectors) with the first index
547 : /// corresponding to the side and the second index corresponding to the quadrature point
548 : /// index. The elements returned after double indexing are pairs. The first member of the pair
549 : /// indicates whether a cached value has been computed. The second member of the pair is the
550 : /// (cached) value. If the boolean is false, then the value cannot be trusted
551 : mutable std::unordered_map<dof_id_type, std::vector<std::vector<std::pair<bool, ValueType>>>>
552 : _side_qp_to_value;
553 :
554 : /// Map from element arguments to their cached evaluations
555 : mutable std::map<ElemArg, ValueType> _elem_arg_to_value;
556 :
557 : /// Map from face arguments to their cached evaluations
558 : mutable std::map<FaceArg, ValueType> _face_arg_to_value;
559 :
560 : /// Map from nodal arguments to their cached evaluations
561 : mutable std::map<NodeArg, ValueType> _node_arg_to_value;
562 :
563 : /// name of the functor
564 : MooseFunctorName _functor_name;
565 : };
566 :
567 : template <typename T>
568 : bool
569 204495827 : FunctorBase<T>::isInternalFace(const FaceInfo & fi) const
570 : {
571 204495827 : if (!fi.neighborPtr())
572 4109443 : return false;
573 :
574 200386384 : return hasBlocks(fi.elem().subdomain_id()) && hasBlocks(fi.neighborPtr()->subdomain_id());
575 : }
576 :
577 : template <typename T>
578 : template <typename SpaceArg>
579 : typename FunctorBase<T>::ValueType
580 0 : FunctorBase<T>::queryFVArgCache(std::map<SpaceArg, ValueType> & cache_data,
581 : const SpaceArg & space) const
582 : {
583 : // We don't want to evaluate if the key already exists, so instead we value initialize
584 0 : auto [it, inserted] = cache_data.try_emplace(space, ValueType());
585 0 : auto & value = it->second;
586 :
587 0 : if (inserted)
588 : // value not ready to go
589 : // this function is only called from functions that assert we are in the current time state
590 0 : value = evaluate(space, currentState());
591 :
592 0 : return value;
593 : }
594 :
595 : template <typename T>
596 : typename FunctorBase<T>::ValueType
597 273544167 : FunctorBase<T>::operator()(const ElemArg & elem, const StateArg & state) const
598 : {
599 273544167 : if (_always_evaluate)
600 273544167 : return evaluate(elem, state);
601 :
602 : mooseAssert(state.state == 0,
603 : "Cached evaluations are only currently supported for the current state.");
604 :
605 0 : return queryFVArgCache(_elem_arg_to_value, elem);
606 : }
607 :
608 : template <typename T>
609 : typename FunctorBase<T>::ValueType
610 92015400 : FunctorBase<T>::operator()(const FaceArg & face_in, const StateArg & state) const
611 : {
612 92015400 : checkFace(face_in);
613 :
614 92015400 : if (_always_evaluate)
615 92015400 : return evaluate(face_in, state);
616 :
617 : mooseAssert(state.state == 0,
618 : "Cached evaluations are only currently supported for the current state.");
619 :
620 0 : return queryFVArgCache(_face_arg_to_value, face_in);
621 : }
622 :
623 : template <typename T>
624 : template <typename SpaceArg, typename StateArg>
625 : typename FunctorBase<T>::ValueType
626 0 : FunctorBase<T>::queryQpCache(const unsigned int qp,
627 : const libMesh::QBase & qrule,
628 : std::vector<std::pair<bool, ValueType>> & qp_cache_data,
629 : const SpaceArg & space,
630 : const StateArg & state) const
631 : {
632 : // Check and see whether we even have sized for this quadrature point. If we haven't then we
633 : // must evaluate
634 0 : if (qp >= qp_cache_data.size())
635 : {
636 0 : qp_cache_data.resize(qrule.n_points(), std::make_pair(false, ValueType()));
637 0 : auto & pr = qp_cache_data[qp];
638 0 : pr.second = evaluate(space, state);
639 0 : pr.first = true;
640 0 : return pr.second;
641 : }
642 :
643 : // We've already sized for this qp, so let's see whether we have a valid cache value
644 0 : auto & pr = qp_cache_data[qp];
645 0 : if (pr.first)
646 0 : return pr.second;
647 :
648 : // No valid cache value so evaluate
649 0 : pr.second = evaluate(space, state);
650 0 : pr.first = true;
651 0 : return pr.second;
652 : }
653 :
654 : template <typename T>
655 : typename FunctorBase<T>::ValueType
656 32739469 : FunctorBase<T>::operator()(const ElemQpArg & elem_qp, const StateArg & state) const
657 : {
658 32739469 : if (_always_evaluate)
659 32739469 : return evaluate(elem_qp, state);
660 :
661 0 : const auto elem_id = elem_qp.elem->id();
662 0 : if (elem_id != _current_qp_map_key)
663 : {
664 0 : _current_qp_map_key = elem_id;
665 0 : _current_qp_map_value = &_qp_to_value[elem_id];
666 : }
667 0 : auto & qp_data = *_current_qp_map_value;
668 0 : const auto qp = elem_qp.qp;
669 0 : const auto * const qrule = elem_qp.qrule;
670 : mooseAssert(qrule, "qrule must be non-null");
671 :
672 0 : return queryQpCache(qp, *qrule, qp_data, elem_qp, state);
673 : }
674 :
675 : template <typename T>
676 : typename FunctorBase<T>::ValueType
677 1890590 : FunctorBase<T>::operator()(const ElemSideQpArg & elem_side_qp, const StateArg & state) const
678 : {
679 1890590 : if (_always_evaluate)
680 1890590 : return evaluate(elem_side_qp, state);
681 :
682 0 : const Elem * const elem = elem_side_qp.elem;
683 : mooseAssert(elem, "elem must be non-null");
684 0 : const auto elem_id = elem->id();
685 0 : if (elem_id != _current_side_qp_map_key)
686 : {
687 0 : _current_side_qp_map_key = elem_id;
688 0 : _current_side_qp_map_value = &_side_qp_to_value[elem_id];
689 : }
690 0 : auto & side_qp_data = *_current_side_qp_map_value;
691 0 : const auto side = elem_side_qp.side;
692 0 : const auto qp = elem_side_qp.qp;
693 0 : const auto * const qrule = elem_side_qp.qrule;
694 : mooseAssert(qrule, "qrule must be non-null");
695 :
696 : // Check and see whether we even have sized for this side
697 0 : if (side >= side_qp_data.size())
698 0 : side_qp_data.resize(elem->n_sides());
699 :
700 : // Ok we were sized enough for our side
701 0 : auto & qp_data = side_qp_data[side];
702 0 : return queryQpCache(qp, *qrule, qp_data, elem_side_qp, state);
703 : }
704 :
705 : template <typename T>
706 : typename FunctorBase<T>::ValueType
707 36605 : FunctorBase<T>::operator()(const ElemPointArg & elem_point, const StateArg & state) const
708 : {
709 36605 : return evaluate(elem_point, state);
710 : }
711 :
712 : template <typename T>
713 : void
714 1196822 : FunctorBase<T>::setCacheClearanceSchedule(const std::set<ExecFlagType> & clearance_schedule)
715 : {
716 1196822 : if (clearance_schedule.count(EXEC_ALWAYS))
717 1196337 : _always_evaluate = true;
718 :
719 1196822 : _clearance_schedule = clearance_schedule;
720 1196822 : }
721 :
722 : template <typename T>
723 : typename FunctorBase<T>::ValueType
724 777249 : FunctorBase<T>::operator()(const NodeArg & node, const StateArg & state) const
725 : {
726 : mooseAssert(node.subdomain_ids, "Subdomain IDs must be supplied to the node argument");
727 777249 : return evaluate(node, state);
728 : }
729 :
730 : template <typename T>
731 : void
732 96790595 : FunctorBase<T>::checkFace(const Moose::FaceArg &
733 : #if DEBUG
734 : face
735 : #endif
736 : ) const
737 : {
738 : #if DEBUG
739 : const Elem * const elem = face.face_side;
740 : const FaceInfo * const fi = face.fi;
741 : mooseAssert(fi, "face info should be non-null");
742 : bool check_elem_def = false;
743 : bool check_neighbor_def = false;
744 : // We check if the functor is defined on both sides of the face
745 : if (!elem)
746 : {
747 : if (!hasFaceSide(*fi, true))
748 : check_neighbor_def = true;
749 : else if (!hasFaceSide(*fi, false))
750 : check_elem_def = true;
751 : }
752 : else if (elem == fi->elemPtr())
753 : check_elem_def = true;
754 : else
755 : {
756 : mooseAssert(elem == fi->neighborPtr(), "This has to match something");
757 : check_neighbor_def = true;
758 : }
759 :
760 : if (check_elem_def && !hasFaceSide(*fi, true))
761 : {
762 : std::string additional_message = "It is not defined on the neighbor side either.";
763 : if (hasFaceSide(*fi, false))
764 : additional_message = "It is however defined on the neighbor side.";
765 : additional_message += " Face centroid: " + Moose::stringify(fi->faceCentroid());
766 : mooseError(_functor_name,
767 : " is not defined on the element side of the face information, but a face argument "
768 : "producer "
769 : "(e.g. residual object, postprocessor, etc.) has requested evaluation there.\n",
770 : additional_message);
771 : }
772 : if (check_neighbor_def && !hasFaceSide(*fi, false))
773 : {
774 : std::string additional_message = "It is not defined on the element side either.";
775 : if (hasFaceSide(*fi, true))
776 : additional_message = "It is however defined on the element side.";
777 : additional_message += " Face centroid: " + Moose::stringify(fi->faceCentroid());
778 : mooseError(
779 : _functor_name,
780 : " is not defined on the neighbor side of the face information, but a face argument "
781 : "producer (e.g. residual object, postprocessor, etc.) has requested evaluation there.\n",
782 : additional_message);
783 : }
784 : #endif
785 96790595 : }
786 :
787 : template <typename T>
788 : void
789 31945 : FunctorBase<T>::clearCacheData()
790 : {
791 31945 : for (auto & map_pr : _qp_to_value)
792 0 : for (auto & pr : map_pr.second)
793 0 : pr.first = false;
794 :
795 31945 : for (auto & map_pr : _side_qp_to_value)
796 : {
797 0 : auto & side_vector = map_pr.second;
798 0 : for (auto & qp_vector : side_vector)
799 0 : for (auto & pr : qp_vector)
800 0 : pr.first = false;
801 : }
802 :
803 31945 : _current_qp_map_key = libMesh::DofObject::invalid_id;
804 31945 : _current_qp_map_value = nullptr;
805 31945 : _current_side_qp_map_key = libMesh::DofObject::invalid_id;
806 31945 : _current_side_qp_map_value = nullptr;
807 :
808 31945 : _elem_arg_to_value.clear();
809 31945 : _face_arg_to_value.clear();
810 31945 : _node_arg_to_value.clear();
811 31945 : }
812 :
813 : template <typename T>
814 : void
815 1373420 : FunctorBase<T>::timestepSetup()
816 : {
817 1373420 : if (_clearance_schedule.count(EXEC_TIMESTEP_BEGIN))
818 24 : clearCacheData();
819 1373420 : }
820 :
821 : template <typename T>
822 : void
823 10128184 : FunctorBase<T>::residualSetup()
824 : {
825 10128184 : if (_clearance_schedule.count(EXEC_LINEAR))
826 30713 : clearCacheData();
827 10128184 : }
828 :
829 : template <typename T>
830 : void
831 1632742 : FunctorBase<T>::jacobianSetup()
832 : {
833 1632742 : if (_clearance_schedule.count(EXEC_NONLINEAR))
834 1208 : clearCacheData();
835 1632742 : }
836 :
837 : template <typename T>
838 : void
839 1481169 : FunctorBase<T>::customSetup(const ExecFlagType & exec_type)
840 : {
841 1481169 : if (_clearance_schedule.count(exec_type))
842 0 : clearCacheData();
843 1481169 : }
844 :
845 : template <typename T>
846 : typename FunctorBase<T>::GradientType
847 5032908 : FunctorBase<T>::gradient(const ElemArg & elem, const StateArg & state) const
848 : {
849 5032908 : return evaluateGradient(elem, state);
850 : }
851 :
852 : template <typename T>
853 : typename FunctorBase<T>::GradientType
854 4775174 : FunctorBase<T>::gradient(const FaceArg & face, const StateArg & state) const
855 : {
856 4775174 : checkFace(face);
857 4775174 : return evaluateGradient(face, state);
858 : }
859 :
860 : template <typename T>
861 : typename FunctorBase<T>::GradientType
862 11138481 : FunctorBase<T>::gradient(const ElemQpArg & elem_qp, const StateArg & state) const
863 : {
864 11138481 : return evaluateGradient(elem_qp, state);
865 : }
866 :
867 : template <typename T>
868 : typename FunctorBase<T>::GradientType
869 11 : FunctorBase<T>::gradient(const ElemSideQpArg & elem_side_qp, const StateArg & state) const
870 : {
871 11 : return evaluateGradient(elem_side_qp, state);
872 : }
873 :
874 : template <typename T>
875 : typename FunctorBase<T>::GradientType
876 11 : FunctorBase<T>::gradient(const ElemPointArg & elem_point, const StateArg & state) const
877 : {
878 11 : return evaluateGradient(elem_point, state);
879 : }
880 :
881 : template <typename T>
882 : typename FunctorBase<T>::GradientType
883 41 : FunctorBase<T>::gradient(const NodeArg & node, const StateArg & state) const
884 : {
885 41 : return evaluateGradient(node, state);
886 : }
887 :
888 : template <typename T>
889 : typename FunctorBase<T>::DotType
890 74403 : FunctorBase<T>::dot(const ElemArg & elem, const StateArg & state) const
891 : {
892 74403 : return evaluateDot(elem, state);
893 : }
894 :
895 : template <typename T>
896 : typename FunctorBase<T>::DotType
897 11 : FunctorBase<T>::dot(const FaceArg & face, const StateArg & state) const
898 : {
899 11 : checkFace(face);
900 11 : return evaluateDot(face, state);
901 : }
902 :
903 : template <typename T>
904 : typename FunctorBase<T>::DotType
905 837847 : FunctorBase<T>::dot(const ElemQpArg & elem_qp, const StateArg & state) const
906 : {
907 837847 : return evaluateDot(elem_qp, state);
908 : }
909 :
910 : template <typename T>
911 : typename FunctorBase<T>::DotType
912 11 : FunctorBase<T>::dot(const ElemSideQpArg & elem_side_qp, const StateArg & state) const
913 : {
914 11 : return evaluateDot(elem_side_qp, state);
915 : }
916 :
917 : template <typename T>
918 : typename FunctorBase<T>::DotType
919 11 : FunctorBase<T>::dot(const ElemPointArg & elem_point, const StateArg & state) const
920 : {
921 11 : return evaluateDot(elem_point, state);
922 : }
923 :
924 : template <typename T>
925 : typename FunctorBase<T>::DotType
926 9 : FunctorBase<T>::dot(const NodeArg & node, const StateArg & state) const
927 : {
928 9 : return evaluateDot(node, state);
929 : }
930 :
931 : template <typename T>
932 : typename FunctorBase<T>::GradientType
933 1932 : FunctorBase<T>::gradDot(const ElemArg & elem, const StateArg & state) const
934 : {
935 1932 : return evaluateGradDot(elem, state);
936 : }
937 :
938 : template <typename T>
939 : typename FunctorBase<T>::GradientType
940 10 : FunctorBase<T>::gradDot(const FaceArg & face, const StateArg & state) const
941 : {
942 10 : checkFace(face);
943 10 : return evaluateGradDot(face, state);
944 : }
945 :
946 : template <typename T>
947 : typename FunctorBase<T>::GradientType
948 8 : FunctorBase<T>::gradDot(const ElemQpArg & elem_qp, const StateArg & state) const
949 : {
950 8 : return evaluateGradDot(elem_qp, state);
951 : }
952 :
953 : template <typename T>
954 : typename FunctorBase<T>::GradientType
955 8 : FunctorBase<T>::gradDot(const ElemSideQpArg & elem_side_qp, const StateArg & state) const
956 : {
957 8 : return evaluateGradDot(elem_side_qp, state);
958 : }
959 :
960 : template <typename T>
961 : typename FunctorBase<T>::GradientType
962 8 : FunctorBase<T>::gradDot(const ElemPointArg & elem_point, const StateArg & state) const
963 : {
964 8 : return evaluateGradDot(elem_point, state);
965 : }
966 :
967 : template <typename T>
968 : typename FunctorBase<T>::GradientType
969 8 : FunctorBase<T>::gradDot(const NodeArg & node, const StateArg & state) const
970 : {
971 8 : return evaluateGradDot(node, state);
972 : }
973 :
974 : template <typename T>
975 : bool
976 5966 : FunctorBase<T>::hasFaceSide(const FaceInfo & fi, const bool fi_elem_side) const
977 : {
978 5966 : if (fi_elem_side)
979 2983 : return hasBlocks(fi.elem().subdomain_id());
980 : else
981 2983 : return fi.neighborPtr() && hasBlocks(fi.neighbor().subdomain_id());
982 : }
983 :
984 : template <typename T>
985 : template <FunctorEvaluationKind FET, typename Space, typename State>
986 : typename FunctorReturnType<T, FET>::type
987 193711752 : FunctorBase<T>::genericEvaluate(const Space & r, const State & state) const
988 : {
989 : if constexpr (FET == FunctorEvaluationKind::Value)
990 184162534 : return (*this)(r, state);
991 : else if constexpr (FET == FunctorEvaluationKind::Gradient)
992 9549218 : return gradient(r, state);
993 : else if constexpr (FET == FunctorEvaluationKind::Dot)
994 0 : return dot(r, state);
995 : else
996 0 : return gradDot(r, state);
997 : }
998 :
999 : /**
1000 : * A non-templated base class for functors that allow an owner object to hold
1001 : * different class template instantiations of \p Functor in a single container
1002 : */
1003 : class FunctorEnvelopeBase
1004 : {
1005 : public:
1006 599140 : FunctorEnvelopeBase() = default;
1007 562571 : virtual ~FunctorEnvelopeBase() = default;
1008 :
1009 : /**
1010 : * @return Whether this envelope wraps a null functor
1011 : */
1012 : virtual bool wrapsNull() const = 0;
1013 :
1014 : /**
1015 : * @return The return type, as a string, of the functor this envelope wraps
1016 : */
1017 : virtual std::string returnType() const = 0;
1018 :
1019 : /**
1020 : * @return Whether this envelope wraps a constant functor
1021 : */
1022 : virtual bool isConstant() const = 0;
1023 :
1024 : /**
1025 : * @return Whether this envelope owns its wrapped functor. This envelope may briefly own null
1026 : * functors during simulation setup or it may own non-AD or AD wrappers of "true" functors, but we
1027 : * should never own any "true" functors, e.g. we expect memory of "true" functors to be managed by
1028 : * warehouses (e.g. variable, function, etc.), or by the \p SubProblem itself. With this
1029 : * expectation, we don't have to worry about performing setup calls
1030 : */
1031 : virtual bool ownsWrappedFunctor() const = 0;
1032 : };
1033 :
1034 : /**
1035 : * This is a wrapper that forwards calls to the implementation,
1036 : * which can be switched out at any time without disturbing references to
1037 : * FunctorBase. Implementation motivated by https://stackoverflow.com/a/65455485/4493669
1038 : */
1039 : template <typename T>
1040 : class FunctorEnvelope final : public FunctorBase<T>, public FunctorEnvelopeBase
1041 : {
1042 : public:
1043 : using typename Moose::FunctorBase<T>::ValueType;
1044 : using typename Moose::FunctorBase<T>::GradientType;
1045 : using typename Moose::FunctorBase<T>::DotType;
1046 :
1047 : /**
1048 : * @param wrapped The functor to wrap. We will *not* not own the wrapped object
1049 : */
1050 294187 : FunctorEnvelope(const FunctorBase<T> & wrapped)
1051 588374 : : FunctorBase<T>("wraps_" + wrapped.functorName()), FunctorEnvelopeBase(), _wrapped(&wrapped)
1052 : {
1053 588374 : }
1054 :
1055 : /**
1056 : * @param wrapped A unique pointer around the functor to wrap. We *will* own the wrapped object,
1057 : * e.g. if we are ever destructed or we are reassigned to wrap another functor, then this functor
1058 : * will be destructed
1059 : */
1060 304953 : FunctorEnvelope(std::unique_ptr<FunctorBase<T>> && wrapped)
1061 304953 : : FunctorBase<T>("wraps_" + wrapped->functorName()),
1062 : FunctorEnvelopeBase(),
1063 304953 : _owned(std::move(wrapped)),
1064 1219812 : _wrapped(_owned.get())
1065 : {
1066 609906 : }
1067 :
1068 : /**
1069 : * Prevent wrapping of a temporary object. If we are to own a functor, the unique_ptr constructor
1070 : * overload should be used
1071 : */
1072 : FunctorEnvelope(FunctorBase<T> &&) = delete;
1073 :
1074 : /**
1075 : * @param wrapped The functor to wrap. We will *not* not own the wrapped object. If we previously
1076 : * owned a functor, it will be destructed
1077 : */
1078 138 : void assign(const FunctorBase<T> & wrapped)
1079 : {
1080 138 : _owned.reset();
1081 138 : _wrapped = &wrapped;
1082 138 : }
1083 :
1084 : /**
1085 : * @param wrapped A unique pointer around the functor to wrap. We *will* own the wrapped object.
1086 : * If we previously owned a functor, it will be destructed
1087 : */
1088 138 : void assign(std::unique_ptr<FunctorBase<T>> && wrapped)
1089 : {
1090 138 : _owned = std::move(wrapped);
1091 138 : _wrapped = _owned.get();
1092 138 : }
1093 :
1094 : /**
1095 : * Prevent wrapping of a temporary object. If we are to own a functor, the unique_ptr assign
1096 : * overload should be used
1097 : */
1098 : void assign(FunctorBase<T> &&) = delete;
1099 :
1100 : FunctorEnvelope(const FunctorEnvelope &) = delete;
1101 : FunctorEnvelope(FunctorEnvelope &&) = delete;
1102 : FunctorEnvelope & operator=(const FunctorEnvelope &) = delete;
1103 : FunctorEnvelope & operator=(FunctorEnvelope &&) = delete;
1104 :
1105 1125141 : virtual ~FunctorEnvelope() = default;
1106 :
1107 : /**
1108 : * @return whether this object wraps a null functor
1109 : */
1110 285610 : virtual bool wrapsNull() const override { return wrapsType<NullFunctor<T>>(); }
1111 :
1112 : /**
1113 : * @return a string representation of the return type of this functor
1114 : */
1115 0 : virtual std::string returnType() const override { return libMesh::demangle(typeid(T).name()); }
1116 :
1117 285610 : virtual bool ownsWrappedFunctor() const override { return _owned.get(); }
1118 :
1119 : /**
1120 : * @return whether the wrapped object is of the requested type
1121 : */
1122 : template <typename T2>
1123 312797 : bool wrapsType() const
1124 : {
1125 312797 : return dynamic_cast<const T2 *>(_wrapped);
1126 : }
1127 :
1128 0 : virtual bool isExtrapolatedBoundaryFace(const FaceInfo & fi,
1129 : const Elem * const elem,
1130 : const StateArg & state) const override
1131 : {
1132 0 : return _wrapped->isExtrapolatedBoundaryFace(fi, elem, state);
1133 : }
1134 0 : virtual bool isConstant() const override { return _wrapped->isConstant(); }
1135 95024 : virtual bool hasBlocks(const SubdomainID id) const override { return _wrapped->hasBlocks(id); }
1136 686 : virtual bool hasFaceSide(const FaceInfo & fi, const bool fi_elem_side) const override
1137 : {
1138 686 : return _wrapped->hasFaceSide(fi, fi_elem_side);
1139 : }
1140 :
1141 1382 : bool supportsFaceArg() const override final { return true; }
1142 532 : bool supportsElemSideQpArg() const override final { return true; }
1143 :
1144 : protected:
1145 : ///@{
1146 : /**
1147 : * Forward calls to wrapped object
1148 : */
1149 31474171 : virtual ValueType evaluate(const ElemArg & elem, const StateArg & state) const override
1150 : {
1151 31474171 : return _wrapped->operator()(elem, state);
1152 : }
1153 2931047 : virtual ValueType evaluate(const FaceArg & face, const StateArg & state) const override
1154 : {
1155 2931047 : return _wrapped->operator()(face, state);
1156 : }
1157 16307263 : virtual ValueType evaluate(const ElemQpArg & qp, const StateArg & state) const override
1158 : {
1159 16307263 : return _wrapped->operator()(qp, state);
1160 : }
1161 942621 : virtual ValueType evaluate(const ElemSideQpArg & qp, const StateArg & state) const override
1162 : {
1163 942621 : return _wrapped->operator()(qp, state);
1164 : }
1165 1421 : virtual ValueType evaluate(const ElemPointArg & elem_point, const StateArg & state) const override
1166 : {
1167 1421 : return _wrapped->operator()(elem_point, state);
1168 : }
1169 274437 : virtual ValueType evaluate(const NodeArg & node, const StateArg & state) const override
1170 : {
1171 274437 : return _wrapped->operator()(node, state);
1172 : }
1173 :
1174 32257 : virtual GradientType evaluateGradient(const ElemArg & elem, const StateArg & state) const override
1175 : {
1176 32257 : return _wrapped->gradient(elem, state);
1177 : }
1178 1 : virtual GradientType evaluateGradient(const FaceArg & face, const StateArg & state) const override
1179 : {
1180 1 : return _wrapped->gradient(face, state);
1181 : }
1182 74801 : virtual GradientType evaluateGradient(const ElemQpArg & qp, const StateArg & state) const override
1183 : {
1184 74801 : return _wrapped->gradient(qp, state);
1185 : }
1186 1 : virtual GradientType evaluateGradient(const ElemSideQpArg & qp,
1187 : const StateArg & state) const override
1188 : {
1189 1 : return _wrapped->gradient(qp, state);
1190 : }
1191 1 : virtual GradientType evaluateGradient(const ElemPointArg & elem_point,
1192 : const StateArg & state) const override
1193 : {
1194 1 : return _wrapped->gradient(elem_point, state);
1195 : }
1196 16 : virtual GradientType evaluateGradient(const NodeArg & node, const StateArg & state) const override
1197 : {
1198 16 : return _wrapped->gradient(node, state);
1199 : }
1200 :
1201 9289 : virtual DotType evaluateDot(const ElemArg & elem, const StateArg & state) const override
1202 : {
1203 9289 : return _wrapped->dot(elem, state);
1204 : }
1205 1 : virtual DotType evaluateDot(const FaceArg & face, const StateArg & state) const override
1206 : {
1207 1 : return _wrapped->dot(face, state);
1208 : }
1209 2727 : virtual DotType evaluateDot(const ElemQpArg & qp, const StateArg & state) const override
1210 : {
1211 2727 : return _wrapped->dot(qp, state);
1212 : }
1213 1 : virtual DotType evaluateDot(const ElemSideQpArg & qp, const StateArg & state) const override
1214 : {
1215 1 : return _wrapped->dot(qp, state);
1216 : }
1217 1 : virtual DotType evaluateDot(const ElemPointArg & elem_point,
1218 : const StateArg & state) const override
1219 : {
1220 1 : return _wrapped->dot(elem_point, state);
1221 : }
1222 0 : virtual DotType evaluateDot(const NodeArg & node, const StateArg & state) const override
1223 : {
1224 0 : return _wrapped->dot(node, state);
1225 : }
1226 :
1227 960 : virtual GradientType evaluateGradDot(const ElemArg & elem, const StateArg & state) const override
1228 : {
1229 960 : return _wrapped->gradDot(elem, state);
1230 : }
1231 0 : virtual GradientType evaluateGradDot(const FaceArg & face, const StateArg & state) const override
1232 : {
1233 0 : return _wrapped->gradDot(face, state);
1234 : }
1235 0 : virtual GradientType evaluateGradDot(const ElemQpArg & qp, const StateArg & state) const override
1236 : {
1237 0 : return _wrapped->gradDot(qp, state);
1238 : }
1239 0 : virtual GradientType evaluateGradDot(const ElemSideQpArg & qp,
1240 : const StateArg & state) const override
1241 : {
1242 0 : return _wrapped->gradDot(qp, state);
1243 : }
1244 0 : virtual GradientType evaluateGradDot(const ElemPointArg & elem_point,
1245 : const StateArg & state) const override
1246 : {
1247 0 : return _wrapped->gradDot(elem_point, state);
1248 : }
1249 0 : virtual GradientType evaluateGradDot(const NodeArg & node, const StateArg & state) const override
1250 : {
1251 0 : return _wrapped->gradDot(node, state);
1252 : }
1253 : ///@}
1254 :
1255 : private:
1256 : /// Our wrapped object
1257 : std::unique_ptr<FunctorBase<T>> _owned;
1258 : const FunctorBase<T> * _wrapped;
1259 :
1260 : friend class ::SubProblem;
1261 : };
1262 :
1263 : /**
1264 : * Class template for creating constant functors
1265 : */
1266 : template <typename T>
1267 : class ConstantFunctor final : public FunctorBase<T>
1268 : {
1269 : public:
1270 : using typename FunctorBase<T>::FunctorType;
1271 : using typename FunctorBase<T>::ValueType;
1272 : using typename FunctorBase<T>::GradientType;
1273 : using typename FunctorBase<T>::DotType;
1274 :
1275 4170 : ConstantFunctor(const ValueType & value)
1276 8340 : : FunctorBase<T>("constant_" + std::to_string(value)), _value(value)
1277 : {
1278 8340 : }
1279 6322 : ConstantFunctor(ValueType && value)
1280 12644 : : FunctorBase<T>("constant_" + std::to_string(MetaPhysicL::raw_value(value))), _value(value)
1281 : {
1282 12644 : }
1283 :
1284 0 : virtual bool isConstant() const override { return true; }
1285 :
1286 24264 : bool hasBlocks(SubdomainID /* id */) const override { return true; }
1287 :
1288 0 : bool supportsFaceArg() const override final { return true; }
1289 0 : bool supportsElemSideQpArg() const override final { return true; }
1290 :
1291 : private:
1292 22119933 : ValueType evaluate(const ElemArg &, const StateArg &) const override { return _value; }
1293 521622 : ValueType evaluate(const FaceArg &, const StateArg &) const override { return _value; }
1294 3822367 : ValueType evaluate(const ElemQpArg &, const StateArg &) const override { return _value; }
1295 230929 : ValueType evaluate(const ElemSideQpArg &, const StateArg &) const override { return _value; }
1296 191 : ValueType evaluate(const ElemPointArg &, const StateArg &) const override { return _value; }
1297 45729 : ValueType evaluate(const NodeArg &, const StateArg &) const override { return _value; }
1298 :
1299 5 : GradientType evaluateGradient(const ElemArg &, const StateArg &) const override { return 0; }
1300 5 : GradientType evaluateGradient(const FaceArg &, const StateArg &) const override { return 0; }
1301 5 : GradientType evaluateGradient(const ElemQpArg &, const StateArg &) const override { return 0; }
1302 5 : GradientType evaluateGradient(const ElemSideQpArg &, const StateArg &) const override
1303 : {
1304 5 : return 0;
1305 : }
1306 5 : GradientType evaluateGradient(const ElemPointArg &, const StateArg &) const override { return 0; }
1307 5 : GradientType evaluateGradient(const NodeArg &, const StateArg &) const override { return 0; }
1308 :
1309 5 : DotType evaluateDot(const ElemArg &, const StateArg &) const override { return 0; }
1310 5 : DotType evaluateDot(const FaceArg &, const StateArg &) const override { return 0; }
1311 5 : DotType evaluateDot(const ElemQpArg &, const StateArg &) const override { return 0; }
1312 5 : DotType evaluateDot(const ElemSideQpArg &, const StateArg &) const override { return 0; }
1313 5 : DotType evaluateDot(const ElemPointArg &, const StateArg &) const override { return 0; }
1314 5 : DotType evaluateDot(const NodeArg &, const StateArg &) const override { return 0; }
1315 :
1316 5 : GradientType evaluateGradDot(const ElemArg &, const StateArg &) const override { return 0; }
1317 5 : GradientType evaluateGradDot(const FaceArg &, const StateArg &) const override { return 0; }
1318 5 : GradientType evaluateGradDot(const ElemQpArg &, const StateArg &) const override { return 0; }
1319 5 : GradientType evaluateGradDot(const ElemSideQpArg &, const StateArg &) const override { return 0; }
1320 5 : GradientType evaluateGradDot(const ElemPointArg &, const StateArg &) const override { return 0; }
1321 5 : GradientType evaluateGradDot(const NodeArg &, const StateArg &) const override { return 0; }
1322 :
1323 : private:
1324 : ValueType _value;
1325 : };
1326 :
1327 : /**
1328 : * A functor that serves as a placeholder during the simulation setup phase if a functor consumer
1329 : * requests a functor that has not yet been constructed.
1330 : */
1331 : template <typename T>
1332 : class NullFunctor final : public FunctorBase<T>
1333 : {
1334 : public:
1335 : using typename FunctorBase<T>::FunctorType;
1336 : using typename FunctorBase<T>::ValueType;
1337 : using typename FunctorBase<T>::GradientType;
1338 : using typename FunctorBase<T>::DotType;
1339 :
1340 554 : NullFunctor() : FunctorBase<T>("null") {}
1341 :
1342 : // For backwards compatiblity of unit testing
1343 : bool hasFaceSide(const FaceInfo & fi, bool) const override;
1344 :
1345 0 : bool supportsFaceArg() const override final { return false; }
1346 0 : bool supportsElemSideQpArg() const override final { return false; }
1347 :
1348 : private:
1349 1 : ValueType evaluate(const ElemArg &, const StateArg &) const override
1350 : {
1351 1 : mooseError("We should never get here. If you have, contact a MOOSE developer and tell them "
1352 : "they've written broken code");
1353 : }
1354 1 : ValueType evaluate(const FaceArg &, const StateArg &) const override
1355 : {
1356 1 : mooseError("We should never get here. If you have, contact a MOOSE developer and tell them "
1357 : "they've written broken code");
1358 : }
1359 1 : ValueType evaluate(const ElemQpArg &, const StateArg &) const override
1360 : {
1361 1 : mooseError("We should never get here. If you have, contact a MOOSE developer and tell them "
1362 : "they've written broken code");
1363 : }
1364 1 : ValueType evaluate(const ElemSideQpArg &, const StateArg &) const override
1365 : {
1366 1 : mooseError("We should never get here. If you have, contact a MOOSE developer and tell them "
1367 : "they've written broken code");
1368 : }
1369 1 : ValueType evaluate(const ElemPointArg &, const StateArg &) const override
1370 : {
1371 1 : mooseError("We should never get here. If you have, contact a MOOSE developer and tell them "
1372 : "they've written broken code");
1373 : }
1374 1 : ValueType evaluate(const NodeArg &, const StateArg &) const override
1375 : {
1376 1 : mooseError("We should never get here. If you have, contact a MOOSE developer and tell them "
1377 : "they've written broken code");
1378 : }
1379 : };
1380 :
1381 : template <typename T>
1382 : bool
1383 0 : NullFunctor<T>::hasFaceSide(const FaceInfo &, const bool) const
1384 : {
1385 : // For backwards compatiblity of unit testing
1386 0 : return true;
1387 : }
1388 : }
|