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 "KokkosHeader.h"
13 : #include "KokkosThread.h"
14 :
15 : #include <typeindex>
16 : #include <type_traits>
17 :
18 : namespace Moose::Kokkos
19 : {
20 :
21 : using Policy = ::Kokkos::RangePolicy<ExecSpace, ::Kokkos::IndexType<ThreadID>>;
22 :
23 : /**
24 : * Base class for Kokkos functor dispatcher.
25 : * Used for type erasure so that the base class of functors can hold the dispatcher without knowing
26 : * the actual type of functors.
27 : */
28 : class DispatcherBase
29 : {
30 : public:
31 514659 : virtual ~DispatcherBase() {}
32 : /**
33 : * Dispatch this functor with Kokkos parallel_for() given a Kokkos execution policy
34 : * @param policy The Kokkos execution policy
35 : */
36 0 : virtual void parallelFor(const Policy & /* policy */)
37 : {
38 0 : mooseError("parallelFor() called for an instance that is not a dispatcher.");
39 : }
40 : /**
41 : * Dispatch this functor with Kokkos parallel_reduce() given a Kokkos execution policy and result
42 : * buffer
43 : * @param policy The Kokkos execution policy
44 : * @param result The result buffer
45 : */
46 0 : virtual void parallelReduce(const Policy & /* policy */,
47 : ::Kokkos::View<Real *, ::Kokkos::HostSpace> & /* result */)
48 : {
49 0 : mooseError("parallelReduce() called for an instance that is not a reducer.");
50 : }
51 : };
52 :
53 : /**
54 : * Class that dispatches a parallel loop operation of a Kokkos functor.
55 : * Calls operator() of the functor with a specified function tag.
56 : * @tparam Operation The function tag of operator() to be dispatched
57 : * @tparam Object The functor class type
58 : */
59 : template <typename Operation, typename Object>
60 : class Dispatcher : public DispatcherBase
61 : {
62 : public:
63 : /**
64 : * Constructor
65 : * @param object The pointer to the functor. This dispatcher is constructed by the base class of
66 : * functors, and the actual type of functors is unknown by the base class. Therefore, it is passed
67 : * as a void pointer and cast to the actual type here.
68 : */
69 24497 : Dispatcher(const void * object)
70 13417 : : _functor_host(*static_cast<const Object *>(object)), _functor_device(_functor_host)
71 : {
72 24497 : }
73 : /**
74 : * Copy constructor for parallel dispatch
75 : */
76 482428 : Dispatcher(const Dispatcher & functor)
77 274548 : : _functor_host(functor._functor_host), _functor_device(functor._functor_host)
78 : {
79 482428 : }
80 :
81 482427 : void parallelFor(const Policy & policy) override final
82 : {
83 482427 : ::Kokkos::parallel_for(policy, *this);
84 482427 : ::Kokkos::fence();
85 482427 : }
86 :
87 : /**
88 : * The parallel computation entry function called by Kokkos::parallel_for
89 : */
90 11793765 : KOKKOS_FUNCTION void operator()(const ThreadID tid) const
91 : {
92 11793765 : _functor_device(Operation{}, tid, _functor_device);
93 11793765 : }
94 :
95 : private:
96 : /**
97 : * Reference of the functor on host
98 : */
99 : const Object & _functor_host;
100 : /**
101 : * Copy of the functor on device
102 : */
103 : const Object _functor_device;
104 : };
105 :
106 : /**
107 : * Class that dispatches a parallel reduction operation of a Kokkos functor.
108 : * Calls operator() of the functor with a specified function tag.
109 : * @tparam Operation The function tag of operator() to be dispatched
110 : * @tparam Object The functor class type
111 : */
112 : template <typename Operation, typename Object>
113 : class Reducer : public DispatcherBase
114 : {
115 : public:
116 : /**
117 : * Constructor
118 : * @param object The pointer to the functor. This reducer is constructed by the base class of
119 : * functors, and the actual type of functors is unknown by the base class. Therefore, it is passed
120 : * as a void pointer and cast to the actual type here.
121 : */
122 979 : Reducer(const void * object)
123 545 : : _functor_host(*static_cast<const Object *>(object)), _functor_device(_functor_host)
124 : {
125 979 : }
126 : /**
127 : * Copy constructor for parallel dispatch
128 : */
129 6793 : Reducer(const Reducer & functor)
130 4113 : : value_count(functor.value_count),
131 4113 : _functor_host(functor._functor_host),
132 4113 : _functor_device(functor._functor_host)
133 : {
134 6793 : }
135 :
136 2264 : void parallelReduce(const Policy & policy,
137 : ::Kokkos::View<Real *, ::Kokkos::HostSpace> & result) override final
138 : {
139 2264 : value_count = result.size();
140 :
141 2264 : ::Kokkos::parallel_reduce(policy, *this, result);
142 2264 : ::Kokkos::fence();
143 2264 : }
144 :
145 : using value_type = Real[];
146 : using size_type = ::Kokkos::View<Real *>::size_type;
147 :
148 : size_type value_count;
149 :
150 : /**
151 : * The parallel computation entry function called by Kokkos::parallel_reduce
152 : */
153 382822 : KOKKOS_FUNCTION void operator()(const ThreadID tid, value_type result) const
154 : {
155 382822 : _functor_device(Operation{}, tid, _functor_device, result);
156 382822 : }
157 :
158 : /**
159 : * Functions required by the reducer concept of Kokkos
160 : */
161 : ///@{
162 169 : KOKKOS_FUNCTION void join(value_type result, const value_type source) const
163 : {
164 169 : _functor_device.template join<Object>(result, source);
165 169 : }
166 1540 : KOKKOS_FUNCTION void init(value_type result) const
167 : {
168 1540 : _functor_device.template init<Object>(result);
169 1540 : }
170 : ///@}
171 :
172 : private:
173 : /**
174 : * Reference of the functor on host
175 : */
176 : const Object & _functor_host;
177 : /**
178 : * Copy of the functor on device
179 : */
180 : const Object _functor_device;
181 : };
182 :
183 : /**
184 : * Base class for dispatcher registry entry.
185 : * Used for type erasure so that the registry can hold dispatchers for different functor types in a
186 : * single container.
187 : */
188 : class DispatcherRegistryEntryBase
189 : {
190 : public:
191 4 : virtual ~DispatcherRegistryEntryBase() {}
192 :
193 : /**
194 : * Build a dispatcher for this operation and functor
195 : * @param object The pointer to the functor
196 : */
197 : virtual std::unique_ptr<DispatcherBase> build(const void * object) const = 0;
198 :
199 : /**
200 : * Set whether the user has overriden the hook method associated with this operation
201 : * @param flag Whether the user has overriden the hook method
202 : */
203 7150753 : void hasUserMethod(bool flag) { _has_user_method = flag; }
204 : /**
205 : * Get whether the user has overriden the hook method associated with this operation
206 : * @returns Whether the user has overriden the hook method
207 : */
208 92494 : bool hasUserMethod() const { return _has_user_method; }
209 :
210 : private:
211 : /**
212 : * Flag whether the user has overriden the hook method associated with this operation
213 : */
214 : bool _has_user_method = false;
215 : };
216 :
217 : /**
218 : * Class that stores the information of a dispatcher and builds it.
219 : * This shell class is the entry of the dispatcher registry instead of the dispatcher itself.
220 : * The reason this class does not dispatch the functor directly is to let the dispatcher hold
221 : * the reference of the functor so that the functor does not need to be copied twice at each
222 : * dispatch. Namely, dispatchers are to be built and held by the functors, not the registry.
223 : * @tparam Operation The function tag of operator() to be dispatched
224 : * @tparam Object The functor class type
225 : */
226 : ///@{
227 : template <typename Operation, typename Object>
228 : class DispatcherRegistryEntry : public DispatcherRegistryEntryBase
229 : {
230 : public:
231 24497 : std::unique_ptr<DispatcherBase> build(const void * object) const override final
232 : {
233 24497 : return std::make_unique<Dispatcher<Operation, Object>>(object);
234 : }
235 : };
236 :
237 : template <typename Operation, typename Object>
238 : class ReducerRegistryEntry : public DispatcherRegistryEntryBase
239 : {
240 : public:
241 979 : std::unique_ptr<DispatcherBase> build(const void * object) const override final
242 : {
243 979 : return std::make_unique<Reducer<Operation, Object>>(object);
244 : }
245 : };
246 : ///@}
247 :
248 : /**
249 : * Class that registers dispatchers of all Kokkos functors
250 : */
251 : class DispatcherRegistry
252 : {
253 : public:
254 41104 : DispatcherRegistry() = default;
255 :
256 : DispatcherRegistry(DispatcherRegistry const &) = delete;
257 : DispatcherRegistry & operator=(DispatcherRegistry const &) = delete;
258 :
259 : DispatcherRegistry(DispatcherRegistry &&) = delete;
260 : DispatcherRegistry & operator=(DispatcherRegistry &&) = delete;
261 :
262 : /**
263 : * Register a dispatcher of an operation of a functor
264 : * @tparam Operation The function tag of operator() to be dispatched
265 : * @tparam Object The functor class type
266 : * @param name The registered object type name
267 : */
268 : template <typename Operation, typename Object>
269 11260120 : static void addDispatcher(const std::string & name)
270 : {
271 11260120 : auto operation = std::type_index(typeid(Operation));
272 :
273 11260120 : getRegistry()._dispatchers[std::make_pair(operation, name)] =
274 : std::make_unique<DispatcherRegistryEntry<Operation, Object>>();
275 11260120 : }
276 :
277 : /**
278 : * Register a reducer of an operation of a functor
279 : * @tparam Operation The function tag of operator() to be dispatched
280 : * @tparam Object The functor class type
281 : * @param name The registered object type name
282 : */
283 : template <typename Operation, typename Object>
284 863137 : static void addReducer(const std::string & name)
285 : {
286 863137 : auto operation = std::type_index(typeid(Operation));
287 :
288 863137 : getRegistry()._dispatchers[std::make_pair(operation, name)] =
289 : std::make_unique<ReducerRegistryEntry<Operation, Object>>();
290 863137 : }
291 :
292 : /**
293 : * Set whether the user has overriden the hook method associated with an operation of a functor
294 : * @tparam Operation The function tag of operator()
295 : * @param name The registered object type name
296 : * @param flag Whether the user has overriden the hook method
297 : */
298 : template <typename Operation>
299 7150753 : static void hasUserMethod(const std::string & name, const bool flag)
300 : {
301 7150753 : getDispatcher<Operation>(name)->hasUserMethod(flag);
302 7150753 : }
303 :
304 : /**
305 : * Get whether the user has overriden the hook method associated with an operation of a functor
306 : * @tparam Operation The function tag of operator()
307 : * @param name The registered object type name
308 : * @returns Whether the user has overriden the hook method
309 : */
310 : template <typename Operation>
311 92494 : static bool hasUserMethod(const std::string & name)
312 : {
313 92494 : return getDispatcher<Operation>(name)->hasUserMethod();
314 : }
315 :
316 : /**
317 : * Build and get a dispatcher of an operation of a functor
318 : * @tparam Operation The function tag of operator()
319 : * @param object The pointer to the functor
320 : * @param name The registered object type name
321 : * @returns The dispatcher
322 : */
323 : template <typename Operation>
324 25476 : static std::unique_ptr<DispatcherBase> build(const void * object, const std::string & name)
325 : {
326 25476 : return getDispatcher<Operation>(name)->build(object);
327 : }
328 :
329 : private:
330 : /**
331 : * Get the registry singleton
332 : * @returns The registry singleton
333 : */
334 : static DispatcherRegistry & getRegistry();
335 :
336 : /**
337 : * Get the dispatcher shell of an operation of a functor
338 : * @tparam Operation The function tag of operator()
339 : * @param name The registered object type name
340 : * @returns The dispatcher shell
341 : */
342 : template <typename Operation>
343 7268723 : static auto & getDispatcher(const std::string & name)
344 : {
345 7268723 : auto operation = std::type_index(typeid(Operation));
346 :
347 7268723 : auto it = getRegistry()._dispatchers.find(std::make_pair(operation, name));
348 7268723 : if (it == getRegistry()._dispatchers.end())
349 0 : mooseError("Kokkos functor dispatcher not registered for object type '",
350 : name,
351 : "'. Double check that you used Kokkos-specific registration macro.");
352 :
353 14537446 : return it->second;
354 : }
355 :
356 : /**
357 : * Map containing the dispatcher shells with the key being the pair of function tag type index and
358 : * registered object type name
359 : */
360 : std::map<std::pair<std::type_index, std::string>, std::unique_ptr<DispatcherRegistryEntryBase>>
361 : _dispatchers;
362 : };
363 :
364 : template <typename T, typename = void>
365 : struct has_split_linear_fv_flux_dispatchers : std::false_type
366 : {
367 : };
368 :
369 : template <typename T>
370 : struct has_split_linear_fv_flux_dispatchers<T,
371 : std::void_t<typename T::InternalRightHandSideLoop,
372 : typename T::BoundaryRightHandSideLoop,
373 : typename T::InternalMatrixLoop,
374 : typename T::BoundaryMatrixLoop>>
375 : : std::true_type
376 : {
377 : };
378 :
379 : template <typename Object>
380 : bool
381 41104 : hasLinearFVMatrixContribution()
382 : {
383 41104 : return &Object::template computeMatrixContribution<Object> !=
384 118107 : Object::template defaultMatrixContribution<Object>() ||
385 39369 : &Object::template computeNeighborMatrixContribution<Object> !=
386 78738 : Object::template defaultNeighborMatrixContribution<Object>();
387 : }
388 :
389 : template <typename Object>
390 : bool
391 82208 : hasInternalLinearFVFluxMatrixContribution()
392 : {
393 82208 : return &Object::template computeInternalMatrixContribution<Object> !=
394 157476 : Object::template defaultInternalMatrixContribution<Object>() ||
395 0 : &Object::template computeInternalNeighborMatrixContribution<Object> !=
396 78738 : Object::template defaultInternalNeighborMatrixContribution<Object>();
397 : }
398 :
399 : template <typename Object>
400 : bool
401 82208 : hasBoundaryLinearFVFluxMatrixContribution()
402 : {
403 82208 : return &Object::template computeBoundaryMatrixContribution<Object> !=
404 157476 : Object::template defaultBoundaryMatrixContribution<Object>();
405 : }
406 :
407 : template <typename Object>
408 : void
409 123312 : registerLinearFVKernelDispatchers(const std::string & objectname)
410 : {
411 : if constexpr (has_split_linear_fv_flux_dispatchers<Object>::value)
412 : {
413 82208 : DispatcherRegistry::addDispatcher<typename Object::InternalRightHandSideLoop, Object>(
414 : objectname);
415 82208 : DispatcherRegistry::addDispatcher<typename Object::BoundaryRightHandSideLoop, Object>(
416 : objectname);
417 82208 : DispatcherRegistry::addDispatcher<typename Object::InternalMatrixLoop, Object>(objectname);
418 82208 : DispatcherRegistry::addDispatcher<typename Object::BoundaryMatrixLoop, Object>(objectname);
419 :
420 82208 : DispatcherRegistry::hasUserMethod<typename Object::InternalMatrixLoop>(
421 78738 : objectname, hasInternalLinearFVFluxMatrixContribution<Object>());
422 82208 : DispatcherRegistry::hasUserMethod<typename Object::BoundaryMatrixLoop>(
423 78738 : objectname, hasBoundaryLinearFVFluxMatrixContribution<Object>());
424 : }
425 : else
426 : {
427 41104 : DispatcherRegistry::addDispatcher<typename Object::RightHandSideLoop, Object>(objectname);
428 41104 : DispatcherRegistry::addDispatcher<typename Object::MatrixLoop, Object>(objectname);
429 41104 : DispatcherRegistry::hasUserMethod<typename Object::MatrixLoop>(
430 39369 : objectname, hasLinearFVMatrixContribution<Object>());
431 : }
432 123312 : }
433 :
434 : } // namespace Moose::Kokkos
435 :
436 : // Kernel, NodalKernel, BC
437 :
438 : #define callRegisterKokkosResidualObjectFunction(classname, objectname) \
439 : static char registerKokkosResidualObject##classname() \
440 : { \
441 : using namespace Moose::Kokkos; \
442 : \
443 : DispatcherRegistry::addDispatcher<classname::ResidualLoop, classname>(objectname); \
444 : DispatcherRegistry::addDispatcher<classname::JacobianLoop, classname>(objectname); \
445 : DispatcherRegistry::addDispatcher<classname::OffDiagJacobianLoop, classname>(objectname); \
446 : DispatcherRegistry::hasUserMethod<classname::JacobianLoop>( \
447 : objectname, \
448 : &classname::computeQpJacobian<classname> != classname::defaultJacobian<classname>()); \
449 : DispatcherRegistry::hasUserMethod<classname::OffDiagJacobianLoop>( \
450 : objectname, \
451 : &classname::computeQpOffDiagJacobian<classname> != \
452 : classname::defaultOffDiagJacobian<classname>()); \
453 : \
454 : return 0; \
455 : } \
456 : \
457 : [[maybe_unused]] static char combineNames(kokkos_dispatcher_residual_object_##classname, \
458 : __COUNTER__) = \
459 : registerKokkosResidualObject##classname()
460 :
461 : #define registerKokkosResidualObject(app, classname) \
462 : registerMooseObject(app, classname); \
463 : callRegisterKokkosResidualObjectFunction(classname, #classname)
464 :
465 : #define registerKokkosResidualObjectAliased(app, classname, alias) \
466 : registerMooseObjectAliased(app, classname, alias); \
467 : callRegisterKokkosResidualObjectFunction(classname, alias)
468 :
469 : // AD Kernel, NodalKernel, BC
470 :
471 : #define callRegisterKokkosADResidualObjectFunction(classname, objectname) \
472 : static char registerKokkosADResidualObject##classname() \
473 : { \
474 : using namespace Moose::Kokkos; \
475 : \
476 : DispatcherRegistry::addDispatcher<classname::ResidualLoop, classname>(objectname); \
477 : \
478 : return 0; \
479 : } \
480 : \
481 : [[maybe_unused]] static char combineNames(kokkos_dispatcher_ad_residual_object_##classname, \
482 : __COUNTER__) = \
483 : registerKokkosADResidualObject##classname()
484 :
485 : #define registerKokkosADResidualObject(app, classname) \
486 : registerMooseObject(app, classname); \
487 : callRegisterKokkosADResidualObjectFunction(classname, #classname)
488 :
489 : #define registerKokkosADResidualObjectAliased(app, classname, alias) \
490 : registerMooseObjectAliased(app, classname, alias); \
491 : callRegisterKokkosADResidualObjectFunction(classname, alias)
492 :
493 : #define callRegisterKokkosLinearFVKernelFunction(classname, objectname) \
494 : static char registerKokkosLinearFVKernel##classname() \
495 : { \
496 : using namespace Moose::Kokkos; \
497 : \
498 : registerLinearFVKernelDispatchers<classname>(objectname); \
499 : \
500 : return 0; \
501 : } \
502 : \
503 : static char combineNames(kokkos_dispatcher_linear_fv_kernel_##classname, __COUNTER__) = \
504 : registerKokkosLinearFVKernel##classname()
505 :
506 : #define registerKokkosLinearFVKernel(app, classname) \
507 : registerMooseObject(app, classname); \
508 : callRegisterKokkosLinearFVKernelFunction(classname, #classname)
509 :
510 : #define registerKokkosLinearFVKernelAliased(app, classname, alias) \
511 : registerMooseObjectAliased(app, classname, alias); \
512 : callRegisterKokkosLinearFVKernelFunction(classname, alias)
513 :
514 : #define callRegisterKokkosLinearFVBoundaryConditionFunction(classname, objectname) \
515 : static char registerKokkosLinearFVBoundaryCondition##classname() \
516 : { \
517 : using namespace Moose::Kokkos; \
518 : \
519 : DispatcherRegistry::addDispatcher<classname::BoundaryValueLoop, classname>(objectname); \
520 : DispatcherRegistry::addDispatcher<classname::BoundaryNormalGradientLoop, classname>( \
521 : objectname); \
522 : DispatcherRegistry::hasUserMethod<classname::BoundaryValueLoop>( \
523 : objectname, \
524 : &classname::computeBoundaryValue<classname> != \
525 : classname::defaultBoundaryValue<classname>()); \
526 : DispatcherRegistry::hasUserMethod<classname::BoundaryNormalGradientLoop>( \
527 : objectname, \
528 : &classname::computeBoundaryNormalGradient<classname> != \
529 : classname::defaultBoundaryNormalGradient<classname>()); \
530 : \
531 : return 0; \
532 : } \
533 : \
534 : static char combineNames(kokkos_dispatcher_linear_fv_boundary_condition_##classname, \
535 : __COUNTER__) = registerKokkosLinearFVBoundaryCondition##classname()
536 :
537 : #define registerKokkosLinearFVBoundaryCondition(app, classname) \
538 : registerMooseObject(app, classname); \
539 : callRegisterKokkosLinearFVBoundaryConditionFunction(classname, #classname)
540 :
541 : #define registerKokkosLinearFVBoundaryConditionAliased(app, classname, alias) \
542 : registerMooseObjectAliased(app, classname, alias); \
543 : callRegisterKokkosLinearFVBoundaryConditionFunction(classname, alias)
544 :
545 : // Material
546 :
547 : #define callRegisterKokkosMaterialFunction(classname, objectname) \
548 : static char registerKokkosMaterial##classname() \
549 : { \
550 : using namespace Moose::Kokkos; \
551 : \
552 : DispatcherRegistry::addDispatcher<classname::ElementInit, classname>(objectname); \
553 : DispatcherRegistry::addDispatcher<classname::SideInit, classname>(objectname); \
554 : DispatcherRegistry::addDispatcher<classname::NeighborInit, classname>(objectname); \
555 : DispatcherRegistry::addDispatcher<classname::ElementCompute, classname>(objectname); \
556 : DispatcherRegistry::addDispatcher<classname::SideCompute, classname>(objectname); \
557 : DispatcherRegistry::addDispatcher<classname::NeighborCompute, classname>(objectname); \
558 : DispatcherRegistry::hasUserMethod<classname::ElementInit>( \
559 : objectname, \
560 : &classname::initQpStatefulProperties<classname> != \
561 : classname::defaultInitStateful<classname>()); \
562 : DispatcherRegistry::hasUserMethod<classname::SideInit>( \
563 : objectname, \
564 : &classname::initQpStatefulProperties<classname> != \
565 : classname::defaultInitStateful<classname>()); \
566 : DispatcherRegistry::hasUserMethod<classname::NeighborInit>( \
567 : objectname, \
568 : &classname::initQpStatefulProperties<classname> != \
569 : classname::defaultInitStateful<classname>()); \
570 : \
571 : return 0; \
572 : } \
573 : \
574 : [[maybe_unused]] static char combineNames(kokkos_dispatcher_material_##classname, __COUNTER__) = \
575 : registerKokkosMaterial##classname()
576 :
577 : #define registerKokkosMaterial(app, classname) \
578 : registerMooseObject(app, classname); \
579 : callRegisterKokkosMaterialFunction(classname, #classname)
580 :
581 : #define registerKokkosMaterialAliased(app, classname, alias) \
582 : registerMooseObjectAliased(app, classname, alias); \
583 : callRegisterKokkosMaterialFunction(classname, alias)
584 :
585 : // AuxKernel
586 :
587 : #define callRegisterKokkosAuxKernelFunction(classname, objectname) \
588 : static char registerKokkosAuxKernel##classname() \
589 : { \
590 : using namespace Moose::Kokkos; \
591 : \
592 : DispatcherRegistry::addDispatcher<classname::ElementLoop, classname>(objectname); \
593 : DispatcherRegistry::addDispatcher<classname::NodeLoop, classname>(objectname); \
594 : \
595 : return 0; \
596 : } \
597 : \
598 : [[maybe_unused]] static char combineNames(kokkos_dispatcher_auxkernel_##classname, \
599 : __COUNTER__) = registerKokkosAuxKernel##classname()
600 :
601 : #define registerKokkosAuxKernel(app, classname) \
602 : registerMooseObject(app, classname); \
603 : callRegisterKokkosAuxKernelFunction(classname, #classname)
604 :
605 : #define registerKokkosAuxKernelAliased(app, classname, alias) \
606 : registerMooseObjectAliased(app, classname, alias); \
607 : callRegisterKokkosAuxKernelFunction(classname, alias)
608 :
609 : // UserObject
610 :
611 : #define callRegisterKokkosUserObjectFunction(classname, objectname) \
612 : static char registerKokkosUserObject##classname() \
613 : { \
614 : using namespace Moose::Kokkos; \
615 : \
616 : DispatcherRegistry::addDispatcher<classname::DefaultLoop, classname>(objectname); \
617 : DispatcherRegistry::addReducer<classname::ReducerLoop, classname>(objectname); \
618 : DispatcherRegistry::hasUserMethod<classname::DefaultLoop>( \
619 : objectname, &classname::execute<classname> != classname::defaultExecute<classname>()); \
620 : DispatcherRegistry::hasUserMethod<classname::ReducerLoop>( \
621 : objectname, &classname::reduce<classname> != classname::defaultReduce<classname>()); \
622 : \
623 : return 0; \
624 : } \
625 : \
626 : [[maybe_unused]] static char combineNames(kokkos_dispatcher_userobject_##classname, \
627 : __COUNTER__) = registerKokkosUserObject##classname()
628 :
629 : #define registerKokkosUserObject(app, classname) \
630 : registerMooseObject(app, classname); \
631 : callRegisterKokkosUserObjectFunction(classname, #classname)
632 :
633 : #define registerKokkosUserObjectAliased(app, classname, alias) \
634 : registerMooseObjectAliased(app, classname, alias); \
635 : callRegisterKokkosUserObjectFunction(classname, alias)
636 :
637 : // User-defined parallel operation registry
638 :
639 : #define registerKokkosAdditionalOperation(classname, operation) \
640 : static char registerKokkos##classname##operation() \
641 : { \
642 : using namespace Moose::Kokkos; \
643 : \
644 : DispatcherRegistry::addDispatcher<classname::operation, classname>(#classname); \
645 : \
646 : return 0; \
647 : } \
648 : \
649 : [[maybe_unused]] static char combineNames(kokkos_##classname##_##operation, __COUNTER__) = \
650 : registerKokkos##classname##operation()
|