LCOV - code coverage report
Current view: top level - include/kokkos/bcs - KokkosNodalBC.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 6f668f Lines: 48 53 90.6 %
Date: 2025-09-22 20:01:15 Functions: 22 26 84.6 %
Legend: Lines: hit not hit

          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 "KokkosNodalBCBase.h"
      13             : 
      14             : namespace Moose
      15             : {
      16             : namespace Kokkos
      17             : {
      18             : 
      19             : /**
      20             :  * The base class for a user to derive their own Kokkos nodal boundary conditions.
      21             :  *
      22             :  * The polymorphic design of the original MOOSE is reproduced statically by leveraging the Curiously
      23             :  * Recurring Template Pattern (CRTP), a programming idiom that involves a class template inheriting
      24             :  * from a template instantiation of itself. When the user derives their Kokkos object from this
      25             :  * class, the inheritance structure will look like:
      26             :  *
      27             :  * class UserNodalBC final : public Moose::Kokkos::NodalBC<UserNodalBC>
      28             :  *
      29             :  * It is important to note that the template argument should point to the last derived class.
      30             :  * Therefore, if the user wants to define a derived class that can be further inherited, the derived
      31             :  * class should be a class template as well. Otherwise, it is recommended to mark the derived class
      32             :  * as final to prevent its inheritence by mistake.
      33             :  *
      34             :  * The user is expected to define computeQpResidual(), computeQpJacobian(), and
      35             :  * computeQpOffDiagJacobian() as inlined public methods in their derived class (not virtual
      36             :  * override). The signature of computeQpResidual() expected to be defined in the derived class is as
      37             :  * follows:
      38             :  *
      39             :  * @param node The contiguous node ID
      40             :  * @returns The residual contribution
      41             :  *
      42             :  * KOKKOS_FUNCTION Real computeQpResidual(const ContiguousNodeID node) const;
      43             :  *
      44             :  * The signatures of computeQpJacobian() and computeOffDiagQpJacobian() can be found in the code
      45             :  * below, and their definition in the derived class is optional. If they are defined in the derived
      46             :  * class, they will hide the default definitions in the base class.
      47             :  */
      48             : template <typename Derived>
      49             : class NodalBC : public NodalBCBase
      50             : {
      51             : public:
      52             :   static InputParameters validParams();
      53             : 
      54             :   /**
      55             :    * Constructor
      56             :    */
      57             :   NodalBC(const InputParameters & parameters);
      58             : 
      59             :   /**
      60             :    * Dispatch residual calculation
      61             :    */
      62             :   virtual void computeResidual() override;
      63             :   /**
      64             :    * Dispatch diagonal and off-diagonal Jacobian calculation
      65             :    */
      66             :   virtual void computeJacobian() override;
      67             : 
      68             :   /**
      69             :    * Default methods to prevent compile errors even when these methods were not defined in the
      70             :    * derived class
      71             :    */
      72             :   ///@{
      73             :   /**
      74             :    * Compute diagonal Jacobian contribution on a node
      75             :    * @param node The contiguous node ID
      76             :    * @returns The diagonal Jacobian contribution
      77             :    */
      78       37780 :   KOKKOS_FUNCTION Real computeQpJacobian(const ContiguousNodeID /* node */) const { return 1; }
      79             :   /**
      80             :    * Compute off-diagonal Jacobian contribution on a node
      81             :    * @param jvar The variable number for column
      82             :    * @param node The contiguous node ID
      83             :    * @returns The off-diagonal Jacobian contribution
      84             :    */
      85           0 :   KOKKOS_FUNCTION Real computeQpOffDiagJacobian(const unsigned int /* jvar */,
      86             :                                                 const ContiguousNodeID /* node */) const
      87             :   {
      88           0 :     return 0;
      89             :   }
      90             :   ///@}
      91             : 
      92             :   /**
      93             :    * The parallel computation entry functions called by Kokkos
      94             :    */
      95             :   ///@{
      96             :   KOKKOS_FUNCTION void operator()(ResidualLoop, const ThreadID tid) const;
      97             :   KOKKOS_FUNCTION void operator()(JacobianLoop, const ThreadID tid) const;
      98             :   KOKKOS_FUNCTION void operator()(OffDiagJacobianLoop, const ThreadID tid) const;
      99             :   ///@}
     100             : 
     101             : protected:
     102             :   /**
     103             :    * Current solution at nodes
     104             :    */
     105             :   const VariableNodalValue _u;
     106             : 
     107             : private:
     108             :   /**
     109             :    * Flag whether computeQpOffDiagJacobian() was not defined in the derived class
     110             :    */
     111             :   const bool _default_offdiag;
     112             : };
     113             : 
     114             : template <typename Derived>
     115             : InputParameters
     116       29742 : NodalBC<Derived>::validParams()
     117             : {
     118       29742 :   InputParameters params = NodalBCBase::validParams();
     119       29742 :   return params;
     120             : }
     121             : 
     122             : template <typename Derived>
     123        1201 : NodalBC<Derived>::NodalBC(const InputParameters & parameters)
     124             :   : NodalBCBase(parameters, Moose::VarFieldType::VAR_FIELD_STANDARD),
     125         915 :     _u(kokkosSystems(), _var),
     126         915 :     _default_offdiag(&Derived::computeQpOffDiagJacobian == &NodalBC::computeQpOffDiagJacobian)
     127             : {
     128        1201 :   addMooseVariableDependency(&_var);
     129        1201 : }
     130             : 
     131             : template <typename Derived>
     132             : void
     133       47629 : NodalBC<Derived>::computeResidual()
     134             : {
     135       47629 :   ::Kokkos::RangePolicy<ResidualLoop, ExecSpace, ::Kokkos::IndexType<ThreadID>> policy(
     136             :       0, numKokkosBoundaryNodes());
     137       47629 :   ::Kokkos::parallel_for(policy, *static_cast<Derived *>(this));
     138       47629 :   ::Kokkos::fence();
     139       47629 : }
     140             : 
     141             : template <typename Derived>
     142             : void
     143        8014 : NodalBC<Derived>::computeJacobian()
     144             : {
     145        8014 :   ::Kokkos::RangePolicy<JacobianLoop, ExecSpace, ::Kokkos::IndexType<ThreadID>> policy(
     146             :       0, numKokkosBoundaryNodes());
     147        8014 :   ::Kokkos::parallel_for(policy, *static_cast<Derived *>(this));
     148        8014 :   ::Kokkos::fence();
     149             : 
     150        8014 :   if (!_default_offdiag)
     151             :   {
     152          70 :     auto & sys = kokkosSystem(_kokkos_var.sys());
     153             : 
     154         140 :     _thread.resize({sys.getCoupling(_kokkos_var.var()).size(), numKokkosBoundaryNodes()});
     155             : 
     156          70 :     ::Kokkos::RangePolicy<OffDiagJacobianLoop, ExecSpace, ::Kokkos::IndexType<ThreadID>> policy(
     157             :         0, _thread.size());
     158          70 :     ::Kokkos::parallel_for(policy, *static_cast<Derived *>(this));
     159          70 :     ::Kokkos::fence();
     160          70 :   }
     161        8014 : }
     162             : 
     163             : template <typename Derived>
     164             : KOKKOS_FUNCTION void
     165      270427 : NodalBC<Derived>::operator()(ResidualLoop, const ThreadID tid) const
     166             : {
     167      270427 :   auto bc = static_cast<const Derived *>(this);
     168      270427 :   auto node = kokkosBoundaryNodeID(tid);
     169      270427 :   auto & sys = kokkosSystem(_kokkos_var.sys());
     170             : 
     171      270427 :   if (!sys.isNodalDefined(node, _kokkos_var.var()))
     172           0 :     return;
     173             : 
     174      270427 :   Real local_re = bc->computeQpResidual(node);
     175             : 
     176      270427 :   accumulateTaggedNodalResidual(false, local_re, node);
     177             : }
     178             : 
     179             : template <typename Derived>
     180             : KOKKOS_FUNCTION void
     181       38176 : NodalBC<Derived>::operator()(JacobianLoop, const ThreadID tid) const
     182             : {
     183       38176 :   auto bc = static_cast<const Derived *>(this);
     184       38176 :   auto node = kokkosBoundaryNodeID(tid);
     185       38176 :   auto & sys = kokkosSystem(_kokkos_var.sys());
     186             : 
     187       38176 :   if (!sys.isNodalDefined(node, _kokkos_var.var()))
     188           0 :     return;
     189             : 
     190       38176 :   Real local_ke = bc->computeQpJacobian(node);
     191             : 
     192             :   // This initializes the row to zero except the diagonal
     193       38176 :   accumulateTaggedNodalMatrix(false, local_ke, node, _kokkos_var.var());
     194             : }
     195             : 
     196             : template <typename Derived>
     197             : KOKKOS_FUNCTION void
     198         414 : NodalBC<Derived>::operator()(OffDiagJacobianLoop, const ThreadID tid) const
     199             : {
     200         414 :   auto bc = static_cast<const Derived *>(this);
     201         414 :   auto node = kokkosBoundaryNodeID(_thread(tid, 1));
     202         414 :   auto & sys = kokkosSystem(_kokkos_var.sys());
     203         414 :   auto jvar = sys.getCoupling(_kokkos_var.var())[_thread(tid, 0)];
     204             : 
     205         414 :   if (!sys.isNodalDefined(node, _kokkos_var.var()))
     206           0 :     return;
     207             : 
     208         414 :   Real local_ke = bc->computeQpOffDiagJacobian(jvar, node);
     209             : 
     210         414 :   accumulateTaggedNodalMatrix(true, local_ke, node, jvar);
     211             : }
     212             : 
     213             : } // namespace Kokkos
     214             : } // namespace Moose
     215             : 
     216             : #define usingKokkosNodalBCMembers(T)                                                               \
     217             :   usingKokkosNodalBCBaseMembers;                                                                   \
     218             :                                                                                                    \
     219             : protected:                                                                                         \
     220             :   using Moose::Kokkos::NodalBC<T>::_u;                                                             \
     221             :                                                                                                    \
     222             : public:                                                                                            \
     223             :   using Moose::Kokkos::NodalBC<T>::operator()

Generated by: LCOV version 1.14