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 "KokkosKernel.h" 13 : 14 : namespace Moose 15 : { 16 : namespace Kokkos 17 : { 18 : 19 : /** 20 : * The base class for a user to derive their own Kokkos kernels where the residual is of the form 21 : * 22 : * $(\dots, \psi_i)$ 23 : * 24 : * i.e. the test function $(\psi_i)$ can be factored out for optimization. 25 : * 26 : * The user should still define computeQpResidual() and computeQpJacobian(), but their signatures 27 : * are different from the base class. The signature of computeQpResidual() expected to be defined in 28 : * the derived class is as follows: 29 : * 30 : * @param qp The local quadrature point index 31 : * @param datum The AssemblyDatum object of the current thread 32 : * @returns The component of the residual contribution that will be multiplied by the test function 33 : * 34 : * KOKKOS_FUNCTION Real computeQpResidual(const unsigned int qp, 35 : * AssemblyDatum & datum) const; 36 : * 37 : * The signature of computeQpJacobian() can be found in the code below. The definition of 38 : * computeQpOffDiagJacobian() is still the same with the original Kokkos kernel. 39 : */ 40 : class KernelValue : public Kernel 41 : { 42 : public: 43 : static InputParameters validParams(); 44 : 45 : /** 46 : * Constructor 47 : */ 48 : KernelValue(const InputParameters & parameters); 49 : 50 : /** 51 : * Default methods to prevent compile errors even when these methods were not defined in the 52 : * derived class 53 : */ 54 : ///@{ 55 : /** 56 : * Compute diagonal Jacobian contribution on a quadrature point 57 : * @param j The trial function DOF index 58 : * @param qp The local quadrature point index 59 : * @param datum The AssemblyDatum object of the current thread 60 : * @returns The component of the Jacobian contribution that will be multiplied by the test 61 : * function 62 : */ 63 0 : KOKKOS_FUNCTION Real computeQpJacobian(const unsigned int /* j */, 64 : const unsigned int /* qp */, 65 : AssemblyDatum & /* datum */) const 66 : { 67 0 : return 0; 68 : } 69 : /** 70 : * Get the function pointer of the default computeQpJacobian() 71 : * @returns The function pointer 72 : */ 73 37638 : static auto defaultJacobian() { return &KernelValue::computeQpJacobian; } 74 : ///@} 75 : 76 : /** 77 : * Shims for hook methods that can be leveraged to implement static polymorphism 78 : */ 79 : ///{@ 80 : template <typename Derived> 81 384 : KOKKOS_FUNCTION Real computeQpResidualShim(const Derived & kernel, 82 : const unsigned int qp, 83 : AssemblyDatum & datum) const 84 : { 85 384 : return kernel.computeQpResidual(qp, datum); 86 : } 87 : template <typename Derived> 88 384 : KOKKOS_FUNCTION Real computeQpJacobianShim(const Derived & kernel, 89 : const unsigned int j, 90 : const unsigned int qp, 91 : AssemblyDatum & datum) const 92 : { 93 384 : return kernel.computeQpJacobian(j, qp, datum); 94 : } 95 : ///@} 96 : 97 : /** 98 : * The parallel computation bodies that hide the base class methods to optimize for factoring 99 : * out the test function 100 : */ 101 : ///@{ 102 : template <typename Derived> 103 : KOKKOS_FUNCTION void computeResidualInternal(const Derived & kernel, AssemblyDatum & datum) const; 104 : template <typename Derived> 105 : KOKKOS_FUNCTION void computeJacobianInternal(const Derived & kernel, AssemblyDatum & datum) const; 106 : ///@} 107 : }; 108 : 109 : template <typename Derived> 110 : KOKKOS_FUNCTION void 111 96 : KernelValue::computeResidualInternal(const Derived & kernel, AssemblyDatum & datum) const 112 : { 113 96 : ResidualObject::computeResidualInternal( 114 : datum, 115 192 : [&](Real * local_re, const unsigned int ib, const unsigned int ie) 116 : { 117 480 : for (unsigned int qp = 0; qp < datum.n_qps(); ++qp) 118 : { 119 384 : datum.reinit(); 120 : 121 384 : Real value = datum.JxW(qp) * kernel.computeQpResidualShim(kernel, qp, datum); 122 : 123 1920 : for (unsigned int i = ib; i < ie; ++i) 124 1536 : local_re[i] += value * _test(datum, i, qp); 125 : } 126 : }); 127 96 : } 128 : 129 : template <typename Derived> 130 : KOKKOS_FUNCTION void 131 24 : KernelValue::computeJacobianInternal(const Derived & kernel, AssemblyDatum & datum) const 132 : { 133 24 : Real value = 0; 134 : 135 24 : ResidualObject::computeJacobianInternal( 136 : datum, 137 48 : [&](Real * local_ke, const unsigned int ijb, const unsigned int ije) 138 : { 139 120 : for (unsigned int qp = 0; qp < datum.n_qps(); ++qp) 140 : { 141 96 : datum.reinit(); 142 : 143 96 : unsigned int j_old = libMesh::invalid_uint; 144 : 145 1632 : for (unsigned int ij = ijb; ij < ije; ++ij) 146 : { 147 1536 : unsigned int i = ij % datum.n_jdofs(); 148 1536 : unsigned int j = ij / datum.n_jdofs(); 149 : 150 1536 : if (j != j_old) 151 : { 152 384 : value = datum.JxW(qp) * kernel.computeQpJacobianShim(kernel, j, qp, datum); 153 384 : j_old = j; 154 : } 155 : 156 1536 : local_ke[ij] += value * _test(datum, i, qp); 157 : } 158 : } 159 : }); 160 24 : } 161 : 162 : } // namespace Kokkos 163 : } // namespace Moose