LCOV - code coverage report
Current view: top level - include/kokkos/base - KokkosResidualObject.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 6f668f Lines: 77 83 92.8 %
Date: 2025-09-22 20:01:15 Functions: 36 63 57.1 %
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 "KokkosVariableValue.h"
      13             : #include "KokkosMaterialPropertyValue.h"
      14             : 
      15             : #include "MooseVariableBase.h"
      16             : #include "ResidualObject.h"
      17             : 
      18             : namespace Moose
      19             : {
      20             : namespace Kokkos
      21             : {
      22             : 
      23             : /**
      24             :  * The base class for Kokkos residual objects
      25             :  */
      26             : class ResidualObject : public ::ResidualObject,
      27             :                        public MeshHolder,
      28             :                        public AssemblyHolder,
      29             :                        public SystemHolder
      30             : {
      31             : public:
      32             :   static InputParameters validParams();
      33             : 
      34             :   /**
      35             :    * Constructor
      36             :    * @param field_type The MOOSE variable field type
      37             :    * @param nodal Whether the residual object is a nodal residual object
      38             :    */
      39             :   ResidualObject(const InputParameters & parameters,
      40             :                  Moose::VarFieldType field_type,
      41             :                  bool nodal = false);
      42             :   /**
      43             :    * Copy constructor for parallel dispatch
      44             :    */
      45             :   ResidualObject(const ResidualObject & object);
      46             : 
      47             :   /**
      48             :    * Kokkos function tags
      49             :    */
      50             :   ///@{
      51             :   struct ResidualLoop
      52             :   {
      53             :   };
      54             :   struct JacobianLoop
      55             :   {
      56             :   };
      57             :   struct OffDiagJacobianLoop
      58             :   {
      59             :   };
      60             :   ///@}
      61             : 
      62       14815 :   virtual const MooseVariableBase & variable() const override { return _var; }
      63             : 
      64           0 :   virtual void computeOffDiagJacobian(unsigned int) override final
      65             :   {
      66           0 :     mooseError("computeOffDiagJacobian() is not used for Kokkos residual objects.");
      67             :   }
      68           0 :   virtual void computeResidualAndJacobian() override final
      69             :   {
      70           0 :     computeResidual();
      71           0 :     computeJacobian();
      72           0 :   }
      73             : 
      74             : protected:
      75             :   /**
      76             :    * Reference of the MOOSE variable
      77             :    */
      78             :   MooseVariableFieldBase & _var;
      79             :   /**
      80             :    * Kokkos variable
      81             :    */
      82             :   Variable _kokkos_var;
      83             :   /**
      84             :    * Kokkos thread object
      85             :    */
      86             :   Thread _thread;
      87             : 
      88             :   /**
      89             :    * TODO: Move to TransientInterface
      90             :    */
      91             :   ///@{
      92             :   /**
      93             :    * Time
      94             :    */
      95             :   Scalar<Real> _t;
      96             :   /**
      97             :    * Old time
      98             :    */
      99             :   Scalar<const Real> _t_old;
     100             :   /**
     101             :    * The number of the time step
     102             :    */
     103             :   Scalar<int> _t_step;
     104             :   /**
     105             :    * Time step size
     106             :    */
     107             :   Scalar<Real> _dt;
     108             :   /**
     109             :    * Size of the old time step
     110             :    */
     111             :   Scalar<Real> _dt_old;
     112             :   ///@}
     113             : 
     114             :   /**
     115             :    * Accumulate local elemental residual contribution to tagged vectors
     116             :    * @param local_re The local elemental residual contribution
     117             :    * @param elem The contiguous element ID
     118             :    * @param i The test function index
     119             :    * @param comp The variable component
     120             :    */
     121             :   KOKKOS_FUNCTION void accumulateTaggedElementalResidual(const Real local_re,
     122             :                                                          const ContiguousElementID elem,
     123             :                                                          const unsigned int i,
     124             :                                                          const unsigned int comp = 0) const;
     125             :   /**
     126             :    * Accumulate or set local nodal residual contribution to tagged vectors
     127             :    * @param add The flag whether to add or set the local residual
     128             :    * @param local_re The local nodal residual contribution
     129             :    * @param node The contiguous node ID
     130             :    * @param comp The variable component
     131             :    */
     132             :   KOKKOS_FUNCTION void accumulateTaggedNodalResidual(const bool add,
     133             :                                                      const Real local_re,
     134             :                                                      const ContiguousNodeID node,
     135             :                                                      const unsigned int comp = 0) const;
     136             :   /**
     137             :    * Accumulate local elemental Jacobian contribution to tagged matrices
     138             :    * @param local_ke The local elemental Jacobian contribution
     139             :    * @param elem The contiguous element ID
     140             :    * @param i The test function DOF index
     141             :    * @param j The trial function DOF index
     142             :    * @param jvar The variable number for column
     143             :    * @param comp The variable component
     144             :    */
     145             :   KOKKOS_FUNCTION void accumulateTaggedElementalMatrix(const Real local_ke,
     146             :                                                        const ContiguousElementID elem,
     147             :                                                        const unsigned int i,
     148             :                                                        const unsigned int j,
     149             :                                                        const unsigned int jvar,
     150             :                                                        const unsigned int comp = 0) const;
     151             :   /**
     152             :    * Accumulate or set local nodal Jacobian contribution to tagged matrices
     153             :    * @param add The flag whether to add or set the local residual
     154             :    * @param local_ke The local nodal Jacobian contribution
     155             :    * @param node The contiguous node ID
     156             :    * @param jvar The variable number for column
     157             :    * @param comp The Variable component
     158             :    */
     159             :   KOKKOS_FUNCTION void accumulateTaggedNodalMatrix(const bool add,
     160             :                                                    const Real local_ke,
     161             :                                                    const ContiguousNodeID node,
     162             :                                                    const unsigned int jvar,
     163             :                                                    const unsigned int comp = 0) const;
     164             : 
     165             :   /**
     166             :    * The common loop structure template for computing elemental residual
     167             :    * @param datum The ResidualDatum object of the current thread
     168             :    * @param body The quadrature-point loop body
     169             :    */
     170             :   template <typename function>
     171             :   KOKKOS_FUNCTION void computeResidualInternal(ResidualDatum & datum, function body) const;
     172             :   /**
     173             :    * The common loop structure template for computing elemental Jacobian
     174             :    * @param datum The ResidualDatum object of the current thread
     175             :    * @param body The quadrature-point loop body
     176             :    */
     177             :   template <typename function>
     178             :   KOKKOS_FUNCTION void computeJacobianInternal(ResidualDatum & datum, function body) const;
     179             : 
     180             : private:
     181             :   /**
     182             :    * Tags this object operates on
     183             :    */
     184             :   ///@{
     185             :   Array<TagID> _vector_tags;
     186             :   Array<TagID> _matrix_tags;
     187             :   ///@}
     188             :   /**
     189             :    * Flag whether each tag
     190             :    */
     191             :   ///@{
     192             :   Array<bool> _is_extra_vector_tag;
     193             :   Array<bool> _is_extra_matrix_tag;
     194             :   ///@}
     195             : };
     196             : 
     197             : KOKKOS_FUNCTION inline void
     198     9890804 : ResidualObject::accumulateTaggedElementalResidual(const Real local_re,
     199             :                                                   const ContiguousElementID elem,
     200             :                                                   const unsigned int i,
     201             :                                                   const unsigned int comp) const
     202             : {
     203     9890804 :   if (!local_re)
     204      632776 :     return;
     205             : 
     206     9258028 :   auto & sys = kokkosSystem(_kokkos_var.sys());
     207     9258028 :   auto dof = sys.getElemLocalDofIndex(elem, i, _kokkos_var.var(comp));
     208             : 
     209    19203536 :   for (dof_id_type t = 0; t < _vector_tags.size(); ++t)
     210             :   {
     211     9945508 :     auto tag = _vector_tags[t];
     212             : 
     213     9945508 :     if (sys.isResidualTagActive(tag))
     214             :     {
     215             :       bool has_nodal_bc =
     216     9944836 :           _is_extra_vector_tag[t] ? sys.hasNodalBCResidualTag(dof, tag) : sys.hasNodalBC(dof);
     217             : 
     218     9944836 :       if (!has_nodal_bc)
     219     8968728 :         ::Kokkos::atomic_add(&sys.getVectorDofValue(dof, tag), local_re);
     220             :     }
     221             :   }
     222             : }
     223             : 
     224             : KOKKOS_FUNCTION inline void
     225     1535909 : ResidualObject::accumulateTaggedNodalResidual(const bool add,
     226             :                                               const Real local_re,
     227             :                                               const ContiguousNodeID node,
     228             :                                               const unsigned int comp) const
     229             : {
     230     1535909 :   if (!local_re)
     231      926425 :     return;
     232             : 
     233      609484 :   auto & sys = kokkosSystem(_kokkos_var.sys());
     234      609484 :   auto dof = sys.getNodeLocalDofIndex(node, _kokkos_var.var(comp));
     235             : 
     236     1535092 :   for (dof_id_type t = 0; t < _vector_tags.size(); ++t)
     237             :   {
     238      925608 :     auto tag = _vector_tags[t];
     239             : 
     240      925608 :     if (sys.isResidualTagActive(tag))
     241             :     {
     242      925572 :       if (add)
     243      922299 :         sys.getVectorDofValue(dof, tag) += local_re;
     244             :       else
     245        3273 :         sys.getVectorDofValue(dof, tag) = local_re;
     246             :     }
     247             :   }
     248             : }
     249             : 
     250             : KOKKOS_FUNCTION inline void
     251     6128224 : ResidualObject::accumulateTaggedElementalMatrix(const Real local_ke,
     252             :                                                 const ContiguousElementID elem,
     253             :                                                 const unsigned int i,
     254             :                                                 const unsigned int j,
     255             :                                                 const unsigned int jvar,
     256             :                                                 const unsigned int comp) const
     257             : {
     258     6128224 :   if (!local_ke)
     259       27690 :     return;
     260             : 
     261     6100534 :   auto & sys = kokkosSystem(_kokkos_var.sys());
     262     6100534 :   auto row = sys.getElemLocalDofIndex(elem, i, _kokkos_var.var(comp));
     263     6100534 :   auto col = sys.getElemGlobalDofIndex(elem, j, jvar);
     264             : 
     265    15733020 :   for (dof_id_type t = 0; t < _matrix_tags.size(); ++t)
     266             :   {
     267     9632486 :     auto tag = _matrix_tags[t];
     268             : 
     269     9632486 :     if (sys.isMatrixTagActive(tag))
     270             :     {
     271             :       bool has_nodal_bc =
     272     6492326 :           _is_extra_matrix_tag[t] ? sys.hasNodalBCMatrixTag(row, tag) : sys.hasNodalBC(row);
     273             : 
     274     6492326 :       if (!has_nodal_bc)
     275     5720136 :         ::Kokkos::atomic_add(&sys.getMatrixValue(row, col, tag), local_ke);
     276             :     }
     277             :   }
     278             : }
     279             : 
     280             : KOKKOS_FUNCTION inline void
     281      482354 : ResidualObject::accumulateTaggedNodalMatrix(const bool add,
     282             :                                             const Real local_ke,
     283             :                                             const ContiguousNodeID node,
     284             :                                             const unsigned int jvar,
     285             :                                             const unsigned int comp) const
     286             : {
     287      482354 :   if (!local_ke)
     288      157350 :     return;
     289             : 
     290      325004 :   auto & sys = kokkosSystem(_kokkos_var.sys());
     291      325004 :   auto row = sys.getNodeLocalDofIndex(node, _kokkos_var.var(comp));
     292      325004 :   auto col = sys.getNodeGlobalDofIndex(node, jvar);
     293             : 
     294      758310 :   for (dof_id_type t = 0; t < _matrix_tags.size(); ++t)
     295             :   {
     296      433306 :     auto tag = _matrix_tags[t];
     297             : 
     298      433306 :     if (sys.isMatrixTagActive(tag))
     299             :     {
     300      342492 :       auto & matrix = sys.getMatrix(tag);
     301             : 
     302      342492 :       if (add)
     303      301590 :         matrix(row, col) += local_ke;
     304             :       else
     305             :       {
     306       40902 :         matrix.zero(row);
     307       40902 :         matrix(row, col) = local_ke;
     308             :       }
     309             :     }
     310             :   }
     311             : }
     312             : 
     313             : template <typename function>
     314             : KOKKOS_FUNCTION void
     315     2492300 : ResidualObject::computeResidualInternal(ResidualDatum & datum, function body) const
     316             : {
     317             :   Real local_re[MAX_CACHED_DOF];
     318             : 
     319     2492300 :   unsigned int num_batches = datum.n_dofs() / MAX_CACHED_DOF;
     320             : 
     321     2492300 :   if (datum.n_dofs() % MAX_CACHED_DOF)
     322     2492300 :     ++num_batches;
     323             : 
     324     4984600 :   for (unsigned int batch = 0; batch < num_batches; ++batch)
     325             :   {
     326     2492300 :     unsigned int ib = batch * MAX_CACHED_DOF;
     327     2492300 :     unsigned int ie = ::Kokkos::min(ib + MAX_CACHED_DOF, datum.n_dofs());
     328             : 
     329    12383104 :     for (unsigned int i = ib; i < ie; ++i)
     330     9890804 :       local_re[i - ib] = 0;
     331             : 
     332     2492300 :     body(local_re - ib, ib, ie);
     333             : 
     334    12383104 :     for (unsigned int i = ib; i < ie; ++i)
     335     9890804 :       accumulateTaggedElementalResidual(local_re[i - ib], datum.elem().id, i);
     336             :   }
     337     2492300 : }
     338             : 
     339             : template <typename function>
     340             : KOKKOS_FUNCTION void
     341      232256 : ResidualObject::computeJacobianInternal(ResidualDatum & datum, function body) const
     342             : {
     343             :   Real local_ke[MAX_CACHED_DOF];
     344             : 
     345      232256 :   unsigned int num_batches = datum.n_idofs() * datum.n_jdofs() / MAX_CACHED_DOF;
     346             : 
     347      232256 :   if ((datum.n_idofs() * datum.n_jdofs()) % MAX_CACHED_DOF)
     348      232256 :     ++num_batches;
     349             : 
     350      488320 :   for (unsigned int batch = 0; batch < num_batches; ++batch)
     351             :   {
     352      256064 :     unsigned int ijb = batch * MAX_CACHED_DOF;
     353      256064 :     unsigned int ije = ::Kokkos::min(ijb + MAX_CACHED_DOF, datum.n_idofs() * datum.n_jdofs());
     354             : 
     355     3635536 :     for (unsigned int ij = ijb; ij < ije; ++ij)
     356     3379472 :       local_ke[ij - ijb] = 0;
     357             : 
     358      256064 :     body(local_ke - ijb, ijb, ije);
     359             : 
     360     3635536 :     for (unsigned int ij = ijb; ij < ije; ++ij)
     361             :     {
     362     3379472 :       unsigned int i = ij % datum.n_jdofs();
     363     3379472 :       unsigned int j = ij / datum.n_jdofs();
     364             : 
     365     3379472 :       accumulateTaggedElementalMatrix(local_ke[ij - ijb], datum.elem().id, i, j, datum.jvar());
     366             :     }
     367             :   }
     368      232256 : }
     369             : 
     370             : } // namespace Kokkos
     371             : } // namespace Moose
     372             : 
     373             : #define usingKokkosResidualObjectMembers                                                           \
     374             : public:                                                                                            \
     375             :   usingPostprocessorInterfaceMembers;                                                              \
     376             :                                                                                                    \
     377             : protected:                                                                                         \
     378             :   using Moose::Kokkos::ResidualObject::kokkosAssembly;                                             \
     379             :   using Moose::Kokkos::ResidualObject::kokkosSystems;                                              \
     380             :   using Moose::Kokkos::ResidualObject::kokkosSystem;                                               \
     381             :   using Moose::Kokkos::ResidualObject::accumulateTaggedElementalResidual;                          \
     382             :   using Moose::Kokkos::ResidualObject::accumulateTaggedNodalResidual;                              \
     383             :   using Moose::Kokkos::ResidualObject::accumulateTaggedElementalMatrix;                            \
     384             :   using Moose::Kokkos::ResidualObject::accumulateTaggedNodalMatrix;                                \
     385             :   using Moose::Kokkos::ResidualObject::_var;                                                       \
     386             :   using Moose::Kokkos::ResidualObject::_kokkos_var;                                                \
     387             :   using Moose::Kokkos::ResidualObject::_thread;                                                    \
     388             :   using Moose::Kokkos::ResidualObject::_t;                                                         \
     389             :   using Moose::Kokkos::ResidualObject::_t_old;                                                     \
     390             :   using Moose::Kokkos::ResidualObject::_t_step;                                                    \
     391             :   using Moose::Kokkos::ResidualObject::_dt;                                                        \
     392             :   using Moose::Kokkos::ResidualObject::_dt_old;                                                    \
     393             :                                                                                                    \
     394             : public:                                                                                            \
     395             :   using Moose::Kokkos::ResidualObject::ResidualLoop;                                               \
     396             :   using Moose::Kokkos::ResidualObject::JacobianLoop;                                               \
     397             :   using Moose::Kokkos::ResidualObject::OffDiagJacobianLoop

Generated by: LCOV version 1.14