LCOV - code coverage report
Current view: top level - include/kokkos/base - KokkosResidualObject.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 329044 Lines: 129 136 94.9 %
Date: 2026-08-03 21:12:22 Functions: 65 105 61.9 %
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 "KokkosDispatcher.h"
      13             : #include "KokkosFESystem.h"
      14             : #include "KokkosVariableValue.h"
      15             : #include "KokkosMaterialPropertyValue.h"
      16             : 
      17             : #include "MooseVariableBase.h"
      18             : #include "ResidualObject.h"
      19             : 
      20             : namespace Moose::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 FESystemHolder
      30             : {
      31             : public:
      32             :   static InputParameters validParams();
      33             : 
      34             :   /// Whether this object's hooks factor out the test function
      35             :   static constexpr bool use_precompute_hooks = false;
      36             : 
      37             :   /**
      38             :    * Constructor
      39             :    * @param field_type The MOOSE variable field type
      40             :    * @param nodal Whether the residual object is a nodal residual object
      41             :    */
      42             :   ResidualObject(const InputParameters & parameters,
      43             :                  Moose::VarFieldType field_type,
      44             :                  bool nodal = false);
      45             :   /**
      46             :    * Copy constructor for parallel dispatch
      47             :    */
      48             :   ResidualObject(const ResidualObject & object);
      49             : 
      50             :   /**
      51             :    * Kokkos function tags
      52             :    */
      53             :   ///@{
      54             :   struct ResidualLoop
      55             :   {
      56             :   };
      57             :   struct JacobianLoop
      58             :   {
      59             :   };
      60             :   struct OffDiagJacobianLoop
      61             :   {
      62             :   };
      63             :   ///@}
      64             : 
      65       45961 :   virtual const MooseVariableBase & variable() const override { return _var; }
      66             : 
      67           0 :   virtual void computeOffDiagJacobian(unsigned int) override final
      68             :   {
      69           0 :     mooseError("computeOffDiagJacobian() is not used for Kokkos residual objects.");
      70             :   }
      71        1860 :   virtual void computeResidualAndJacobian() override
      72             :   {
      73        1860 :     computeResidual();
      74        1860 :     computeJacobian();
      75        1860 :   }
      76             : 
      77             : protected:
      78             :   /**
      79             :    * Reference of the MOOSE variable
      80             :    */
      81             :   MooseVariableFieldBase & _var;
      82             :   /**
      83             :    * Kokkos variable
      84             :    */
      85             :   Variable _kokkos_var;
      86             :   /**
      87             :    * Kokkos thread object
      88             :    */
      89             :   Thread<> _thread;
      90             :   /**
      91             :    * Kokkos functor dispatchers
      92             :    */
      93             :   ///@{
      94             :   std::unique_ptr<DispatcherBase> _residual_dispatcher;
      95             :   std::unique_ptr<DispatcherBase> _jacobian_dispatcher;
      96             :   std::unique_ptr<DispatcherBase> _offdiag_jacobian_dispatcher;
      97             :   ///@}
      98             : 
      99             :   /**
     100             :    * Mesh dimension
     101             :    */
     102             :   const unsigned int _dimension;
     103             : 
     104             :   /**
     105             :    * TODO: Move to TransientInterface
     106             :    */
     107             :   ///@{
     108             :   /**
     109             :    * Time
     110             :    */
     111             :   Scalar<Real> _t;
     112             :   /**
     113             :    * Old time
     114             :    */
     115             :   Scalar<const Real> _t_old;
     116             :   /**
     117             :    * The number of the time step
     118             :    */
     119             :   Scalar<int> _t_step;
     120             :   /**
     121             :    * Time step size
     122             :    */
     123             :   Scalar<Real> _dt;
     124             :   /**
     125             :    * Size of the old time step
     126             :    */
     127             :   Scalar<Real> _dt_old;
     128             :   ///@}
     129             : 
     130             :   /**
     131             :    * Accumulate local elemental residual contribution to tagged vectors
     132             :    * @param local_re The local elemental residual contribution
     133             :    * @param elem The contiguous element ID
     134             :    * @param i The test function index
     135             :    * @param comp The variable component
     136             :    */
     137             :   KOKKOS_FUNCTION void accumulateTaggedElementalResidual(const Real local_re,
     138             :                                                          const ContiguousElementID elem,
     139             :                                                          const unsigned int i,
     140             :                                                          const unsigned int comp = 0) const;
     141             :   /**
     142             :    * Accumulate or set local nodal residual contribution to tagged vectors
     143             :    * @param add Whether to add or set the local residual
     144             :    * @param local_re The local nodal residual contribution
     145             :    * @param node The contiguous node ID
     146             :    * @param comp The variable component
     147             :    */
     148             :   KOKKOS_FUNCTION void accumulateTaggedNodalResidual(const bool add,
     149             :                                                      const Real local_re,
     150             :                                                      const ContiguousNodeID node,
     151             :                                                      const unsigned int comp = 0) const;
     152             :   /**
     153             :    * Accumulate or set local nodal residual contribution to tagged vectors for vector FE variables
     154             :    * @param add Whether to add or set the local residual
     155             :    * @param local_re The local nodal residual contribution
     156             :    * @param node The contiguous node ID
     157             :    * @param i The vector component/node-local DOF index
     158             :    */
     159             :   KOKKOS_FUNCTION void accumulateTaggedVectorNodalResidual(const bool add,
     160             :                                                            const Real local_re,
     161             :                                                            const ContiguousNodeID node,
     162             :                                                            const unsigned int i) const;
     163             :   /**
     164             :    * Accumulate local elemental Jacobian contribution to tagged matrices
     165             :    * @param local_ke The local elemental Jacobian contribution
     166             :    * @param elem The contiguous element ID
     167             :    * @param i The test function DOF index
     168             :    * @param j The trial function DOF index
     169             :    * @param jvar The variable number for column
     170             :    * @param comp The variable component
     171             :    */
     172             :   KOKKOS_FUNCTION void accumulateTaggedElementalMatrix(const Real local_ke,
     173             :                                                        const ContiguousElementID elem,
     174             :                                                        const unsigned int i,
     175             :                                                        const unsigned int j,
     176             :                                                        const unsigned int jvar,
     177             :                                                        const unsigned int comp = 0) const;
     178             :   /**
     179             :    * Accumulate local elemental Jacobian contribution to tagged matrices using automatic
     180             :    * differentiation (AD)
     181             :    * @param local_ke The local elemental Jacobian contribution
     182             :    * @param datum The AssemblyDatum object of the current thread
     183             :    * @param i The test function DOF index
     184             :    * @param comp The variable component
     185             :    */
     186             :   KOKKOS_FUNCTION void accumulateTaggedElementalMatrix(const DNDerivativeType & local_ke,
     187             :                                                        const AssemblyDatum & datum,
     188             :                                                        const unsigned int i,
     189             :                                                        const unsigned int comp = 0) const;
     190             :   /**
     191             :    * Accumulate or set local nodal Jacobian contribution to tagged matrices
     192             :    * @param add Whether to add or set the local Jacobian
     193             :    * @param local_ke The local nodal Jacobian contribution
     194             :    * @param node The contiguous node ID
     195             :    * @param jvar The variable number for column
     196             :    * @param comp The variable component
     197             :    */
     198             :   KOKKOS_FUNCTION void accumulateTaggedNodalMatrix(const bool add,
     199             :                                                    const Real local_ke,
     200             :                                                    const ContiguousNodeID node,
     201             :                                                    const unsigned int jvar,
     202             :                                                    const unsigned int comp = 0) const;
     203             :   /**
     204             :    * Accumulate or set local nodal Jacobian contribution to tagged matrices for vector FE variables
     205             :    * @param add Whether to add or set the local Jacobian
     206             :    * @param local_ke The local nodal Jacobian contribution
     207             :    * @param node The contiguous node ID
     208             :    * @param i The vector component/node-local DOF index for the row
     209             :    * @param j The node-local DOF index for the column
     210             :    * @param jvar The variable number for column
     211             :    */
     212             :   KOKKOS_FUNCTION void accumulateTaggedVectorNodalMatrix(const bool add,
     213             :                                                          const Real local_ke,
     214             :                                                          const ContiguousNodeID node,
     215             :                                                          const unsigned int i,
     216             :                                                          const unsigned int j,
     217             :                                                          const unsigned int jvar) const;
     218             :   /**
     219             :    * Accumulate or set local nodal Jacobian contribution to tagged matrices using automatic
     220             :    * differentiation (AD)
     221             :    * @param add Whether to add or set the local Jacobian
     222             :    * @param local_ke The local elemental Jacobian contribution
     223             :    * @param node The contiguous node ID
     224             :    * @param comp The variable component
     225             :    */
     226             :   KOKKOS_FUNCTION void accumulateTaggedNodalMatrix(const bool add,
     227             :                                                    const DNDerivativeType & local_ke,
     228             :                                                    const ContiguousNodeID node,
     229             :                                                    const unsigned int comp = 0) const;
     230             : 
     231             :   /**
     232             :    * The common loop structure template for computing elemental residual
     233             :    * @param datum The AssemblyDatum object of the current thread
     234             :    * @param body The quadrature point loop body
     235             :    */
     236             :   template <typename function>
     237             :   KOKKOS_FUNCTION void computeResidualInternal(AssemblyDatum & datum, function body) const;
     238             :   /**
     239             :    * The common loop structure template for computing elemental Jacobian
     240             :    * @param datum The AssemblyDatum object of the current thread
     241             :    * @param body The quadrature point loop body
     242             :    */
     243             :   template <typename function>
     244             :   KOKKOS_FUNCTION void computeJacobianInternal(AssemblyDatum & datum, function body) const;
     245             : 
     246             : private:
     247             :   /**
     248             :    * Tags this object operates on
     249             :    */
     250             :   ///@{
     251             :   Array<TagID> _vector_tags;
     252             :   Array<TagID> _matrix_tags;
     253             :   ///@}
     254             : };
     255             : 
     256             : KOKKOS_FUNCTION inline void
     257    22849738 : ResidualObject::accumulateTaggedElementalResidual(const Real local_re,
     258             :                                                   const ContiguousElementID elem,
     259             :                                                   const unsigned int i,
     260             :                                                   const unsigned int comp) const
     261             : {
     262    22849738 :   if (!local_re)
     263     1937092 :     return;
     264             : 
     265    20912646 :   auto & sys = kokkosSystem(_kokkos_var.sys(comp));
     266    20912646 :   auto dof = sys.getElemLocalDofIndex(elem, i, _kokkos_var.var(comp));
     267             : 
     268    42632068 :   for (unsigned int t = 0; t < _vector_tags.size(); ++t)
     269             :   {
     270    21719422 :     auto tag = _vector_tags[t];
     271             : 
     272    21719422 :     if (sys.isResidualTagActive(tag))
     273    21599454 :       ::Kokkos::atomic_add(&sys.getVectorDofValue(dof, tag), local_re);
     274             :   }
     275             : }
     276             : 
     277             : KOKKOS_FUNCTION inline void
     278     1703968 : ResidualObject::accumulateTaggedNodalResidual(const bool add,
     279             :                                               const Real local_re,
     280             :                                               const ContiguousNodeID node,
     281             :                                               const unsigned int comp) const
     282             : {
     283     1703968 :   if (!local_re && add)
     284      659958 :     return;
     285             : 
     286     1044010 :   auto & sys = kokkosSystem(_kokkos_var.sys(comp));
     287     1044010 :   auto dof = sys.getNodeLocalDofIndex(node, 0, _kokkos_var.var(comp));
     288             : 
     289     2434030 :   for (unsigned int t = 0; t < _vector_tags.size(); ++t)
     290             :   {
     291     1390020 :     auto tag = _vector_tags[t];
     292             : 
     293     1390020 :     if (sys.isResidualTagActive(tag))
     294             :     {
     295     1379760 :       if (add)
     296      921576 :         sys.getVectorDofValue(dof, tag) += local_re;
     297             :       else
     298      458184 :         sys.getVectorDofValue(dof, tag) = local_re;
     299             :     }
     300             :   }
     301             : }
     302             : 
     303             : KOKKOS_FUNCTION inline void
     304      108116 : ResidualObject::accumulateTaggedVectorNodalResidual(const bool add,
     305             :                                                     const Real local_re,
     306             :                                                     const ContiguousNodeID node,
     307             :                                                     const unsigned int i) const
     308             : {
     309      108116 :   if (!local_re && add)
     310           0 :     return;
     311             : 
     312      108116 :   auto & sys = kokkosSystem(_kokkos_var.sys());
     313      108116 :   auto dof = sys.getNodeLocalDofIndex(node, i, _kokkos_var.var());
     314             : 
     315      216232 :   for (unsigned int t = 0; t < _vector_tags.size(); ++t)
     316             :   {
     317      108116 :     auto tag = _vector_tags[t];
     318             : 
     319      108116 :     if (sys.isResidualTagActive(tag))
     320             :     {
     321      108116 :       if (add)
     322           0 :         sys.getVectorDofValue(dof, tag) += local_re;
     323             :       else
     324      108116 :         sys.getVectorDofValue(dof, tag) = local_re;
     325             :     }
     326             :   }
     327             : }
     328             : 
     329             : KOKKOS_FUNCTION inline void
     330    19724200 : ResidualObject::accumulateTaggedElementalMatrix(const Real local_ke,
     331             :                                                 const ContiguousElementID elem,
     332             :                                                 const unsigned int i,
     333             :                                                 const unsigned int j,
     334             :                                                 const unsigned int jvar,
     335             :                                                 const unsigned int comp) const
     336             : {
     337    19724200 :   if (!local_ke)
     338     5917810 :     return;
     339             : 
     340    13806390 :   auto & sys = kokkosSystem(_kokkos_var.sys(comp));
     341    13806390 :   auto row = sys.getElemLocalDofIndex(elem, i, _kokkos_var.var(comp));
     342    13806390 :   auto col = sys.getElemGlobalDofIndex(elem, j, jvar);
     343             : 
     344    33786828 :   for (unsigned int t = 0; t < _matrix_tags.size(); ++t)
     345             :   {
     346    19980438 :     auto tag = _matrix_tags[t];
     347             : 
     348    19980438 :     if (sys.isMatrixTagActive(tag) && !sys.hasNodalBCMatrixTag(row, tag))
     349    13067680 :       ::Kokkos::atomic_add(&sys.getMatrixValue(row, col, tag), local_ke);
     350             :   }
     351             : }
     352             : 
     353             : KOKKOS_FUNCTION inline void
     354     1103456 : ResidualObject::accumulateTaggedElementalMatrix(const DNDerivativeType & local_ke,
     355             :                                                 const AssemblyDatum & datum,
     356             :                                                 const unsigned int i,
     357             :                                                 const unsigned int comp) const
     358             : {
     359     1103456 :   auto & sys = kokkosSystem(_kokkos_var.sys(comp));
     360     1103456 :   auto row = sys.getElemLocalDofIndex(datum.elem().id, i, _kokkos_var.var(comp));
     361             : 
     362     2706412 :   for (unsigned int t = 0; t < _matrix_tags.size(); ++t)
     363             :   {
     364     1602956 :     auto tag = _matrix_tags[t];
     365             : 
     366     1602956 :     if (sys.isMatrixTagActive(tag) && !sys.hasNodalBCMatrixTag(row, tag))
     367     4879930 :       for (unsigned int j = 0; j < local_ke.size(); ++j)
     368             :       {
     369     3891220 :         auto col = local_ke.raw_index(j);
     370             : 
     371     3891220 :         ::Kokkos::atomic_add(&sys.getMatrixValue(row, col, tag), local_ke.raw_at(j));
     372             :       }
     373             :   }
     374     1103456 : }
     375             : 
     376             : KOKKOS_FUNCTION inline void
     377      502650 : ResidualObject::accumulateTaggedNodalMatrix(const bool add,
     378             :                                             const Real local_ke,
     379             :                                             const ContiguousNodeID node,
     380             :                                             const unsigned int jvar,
     381             :                                             const unsigned int comp) const
     382             : {
     383      502650 :   if (!local_ke && add)
     384      157350 :     return;
     385             : 
     386      345300 :   auto & sys = kokkosSystem(_kokkos_var.sys(comp));
     387      345300 :   auto row = sys.getNodeLocalDofIndex(node, 0, _kokkos_var.var(comp));
     388      345300 :   auto col = sys.getNodeGlobalDofIndex(node, 0, jvar);
     389             : 
     390      861178 :   for (unsigned int t = 0; t < _matrix_tags.size(); ++t)
     391             :   {
     392      515878 :     auto tag = _matrix_tags[t];
     393             : 
     394      515878 :     if (sys.isMatrixTagActive(tag))
     395             :     {
     396      362788 :       auto & matrix = sys.getMatrix(tag);
     397             : 
     398      362788 :       if (add)
     399      301590 :         matrix(row, col) += local_ke;
     400             :       else
     401             :       {
     402       61198 :         matrix.zero(row);
     403       61198 :         matrix(row, col) = local_ke;
     404             :       }
     405             :     }
     406             :   }
     407             : }
     408             : 
     409             : KOKKOS_FUNCTION inline void
     410        9696 : ResidualObject::accumulateTaggedVectorNodalMatrix(const bool add,
     411             :                                                   const Real local_ke,
     412             :                                                   const ContiguousNodeID node,
     413             :                                                   const unsigned int i,
     414             :                                                   const unsigned int j,
     415             :                                                   const unsigned int jvar) const
     416             : {
     417        9696 :   if (!local_ke && add)
     418           0 :     return;
     419             : 
     420        9696 :   auto & sys = kokkosSystem(_kokkos_var.sys());
     421        9696 :   auto row = sys.getNodeLocalDofIndex(node, i, _kokkos_var.var());
     422        9696 :   auto col = sys.getNodeGlobalDofIndex(node, j, jvar);
     423             : 
     424       29088 :   for (unsigned int t = 0; t < _matrix_tags.size(); ++t)
     425             :   {
     426       19392 :     auto tag = _matrix_tags[t];
     427             : 
     428       19392 :     if (sys.isMatrixTagActive(tag))
     429             :     {
     430        9696 :       auto & matrix = sys.getMatrix(tag);
     431             : 
     432        9696 :       if (add)
     433           0 :         matrix(row, col) += local_ke;
     434             :       else
     435             :       {
     436        9696 :         matrix.zero(row);
     437        9696 :         matrix(row, col) = local_ke;
     438             :       }
     439             :     }
     440             :   }
     441             : }
     442             : 
     443             : KOKKOS_FUNCTION inline void
     444       33390 : ResidualObject::accumulateTaggedNodalMatrix(const bool add,
     445             :                                             const DNDerivativeType & local_ke,
     446             :                                             const ContiguousNodeID node,
     447             :                                             const unsigned int comp) const
     448             : {
     449       33390 :   auto & sys = kokkosSystem(_kokkos_var.sys(comp));
     450       33390 :   auto row = sys.getNodeLocalDofIndex(node, 0, _kokkos_var.var(comp));
     451             : 
     452      100170 :   for (unsigned int t = 0; t < _matrix_tags.size(); ++t)
     453             :   {
     454       66780 :     auto tag = _matrix_tags[t];
     455       66780 :     auto & matrix = sys.getMatrix(tag);
     456             : 
     457       66780 :     if (sys.isMatrixTagActive(tag))
     458             :     {
     459       33390 :       if (!add)
     460       33390 :         matrix.zero(row);
     461             : 
     462       66780 :       for (unsigned int j = 0; j < local_ke.size(); ++j)
     463             :       {
     464       33390 :         auto col = local_ke.raw_index(j);
     465             : 
     466       33390 :         if (add)
     467           0 :           matrix(row, col) += local_ke.raw_at(j);
     468             :         else
     469       33390 :           matrix(row, col) = local_ke.raw_at(j);
     470             :       }
     471             :     }
     472             :   }
     473       33390 : }
     474             : 
     475             : template <typename function>
     476             : KOKKOS_FUNCTION void
     477     4640363 : ResidualObject::computeResidualInternal(AssemblyDatum & datum, function body) const
     478             : {
     479             :   Real local_re[MAX_CACHED_DOF];
     480             : 
     481     4640363 :   unsigned int stride = MAX_CACHED_DOF * datum.num_local_threads();
     482     4640363 :   unsigned int num_batches = datum.n_dofs() / stride;
     483             : 
     484     4640363 :   if (datum.n_dofs() % stride)
     485     4640363 :     ++num_batches;
     486             : 
     487     9280726 :   for (unsigned int batch = 0; batch < num_batches; ++batch)
     488             :   {
     489     4640363 :     unsigned int ib = batch * stride;
     490     4640363 :     unsigned int ie = ::Kokkos::min(ib + stride, datum.n_dofs());
     491             : 
     492     4640363 :     const unsigned int n = ie - ib;
     493     4640363 :     const unsigned int d = n / datum.num_local_threads();
     494     4640363 :     const unsigned int m = n % datum.num_local_threads();
     495     4640363 :     const unsigned int t = datum.local_thread_id();
     496             : 
     497     4640363 :     ib += t * d + (t < m ? t : m);
     498     4640363 :     ie = ib + d + (t < m ? 1 : 0);
     499             : 
     500    26308241 :     for (unsigned int i = ib; i < ie; ++i)
     501    21667878 :       local_re[i - ib] = 0;
     502             : 
     503     4640363 :     body(local_re - ib, ib, ie);
     504             : 
     505    26308241 :     for (unsigned int i = ib; i < ie; ++i)
     506    21667878 :       accumulateTaggedElementalResidual(local_re[i - ib], datum.elem().id, i);
     507             :   }
     508     4640363 : }
     509             : 
     510             : template <typename function>
     511             : KOKKOS_FUNCTION void
     512      510130 : ResidualObject::computeJacobianInternal(AssemblyDatum & datum, function body) const
     513             : {
     514             :   Real local_ke[MAX_CACHED_DOF];
     515             : 
     516     2910470 :   for (unsigned int j = datum.local_thread_id(); j < datum.n_jdofs();
     517     2400340 :        j += datum.num_local_threads())
     518             :   {
     519     2400340 :     unsigned int num_batches = datum.n_idofs() / MAX_CACHED_DOF;
     520             : 
     521     2400340 :     if (datum.n_idofs() % MAX_CACHED_DOF)
     522     2400340 :       ++num_batches;
     523             : 
     524     4800680 :     for (unsigned int batch = 0; batch < num_batches; ++batch)
     525             :     {
     526     2400340 :       unsigned int ib = batch * MAX_CACHED_DOF;
     527     2400340 :       unsigned int ie = ::Kokkos::min(ib + MAX_CACHED_DOF, datum.n_idofs());
     528             : 
     529    16045308 :       for (unsigned int i = ib; i < ie; ++i)
     530    13644968 :         local_ke[i - ib] = 0;
     531             : 
     532     2400340 :       body(local_ke - ib, ib, ie, j);
     533             : 
     534    16045308 :       for (unsigned int i = ib; i < ie; ++i)
     535    13644968 :         accumulateTaggedElementalMatrix(local_ke[i - ib], datum.elem().id, i, j, datum.jvar());
     536             :     }
     537             :   }
     538      510130 : }
     539             : 
     540             : } // namespace Moose::Kokkos

Generated by: LCOV version 1.14