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