LCOV - code coverage report
Current view: top level - include/kokkos/base - KokkosVariableValue.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #33416 (b10b36) with base 9fbd27 Lines: 107 115 93.0 %
Date: 2026-07-23 16:15:30 Functions: 28 29 96.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 "KokkosDatum.h"
      13             : 
      14             : #include "MooseVariableFieldBase.h"
      15             : #include "SystemBase.h"
      16             : 
      17             : namespace Moose::Kokkos
      18             : {
      19             : 
      20             : /**
      21             :  * The Kokkos wrapper classes for MOOSE-like shape function access
      22             :  */
      23             : ///@{
      24             : class VariablePhiValue
      25             : {
      26             : public:
      27             :   /**
      28             :    * Get the current shape function
      29             :    * @param datum The AssemblyDatum object of the current thread
      30             :    * @param i The element-local DOF index
      31             :    * @param qp The local quadrature point index
      32             :    * @returns The shape function
      33             :    */
      34     4906888 :   KOKKOS_FUNCTION Real operator()(AssemblyDatum & datum, unsigned int i, unsigned int qp) const
      35             :   {
      36     4906888 :     auto & elem = datum.elem();
      37     4906888 :     auto side = datum.side();
      38     4906888 :     auto fe = datum.jfe();
      39             : 
      40           0 :     return side == libMesh::invalid_uint
      41     4906888 :                ? datum.assembly().getPhi(elem.subdomain, elem.type, fe)(i, qp)
      42     4906888 :                : datum.assembly().getPhiFace(elem.subdomain, elem.type, fe)(side)(i, qp);
      43             :   }
      44             : };
      45             : 
      46             : class VariablePhiGradient
      47             : {
      48             : public:
      49             :   /**
      50             :    * Get the gradient of the current shape function
      51             :    * @param datum The AssemblyDatum object of the current thread
      52             :    * @param i The element-local DOF index
      53             :    * @param qp The local quadrature point index
      54             :    * @returns The gradient of the shape function
      55             :    */
      56    25387624 :   KOKKOS_FUNCTION Real3 operator()(AssemblyDatum & datum, unsigned int i, unsigned int qp) const
      57             :   {
      58    25387624 :     auto & elem = datum.elem();
      59    25387624 :     auto side = datum.side();
      60    25387624 :     auto fe = datum.jfe();
      61             : 
      62           0 :     return datum.J(qp) *
      63             :            (side == libMesh::invalid_uint
      64    25387624 :                 ? datum.assembly().getGradPhi(elem.subdomain, elem.type, fe)(i, qp)
      65    50775248 :                 : datum.assembly().getGradPhiFace(elem.subdomain, elem.type, fe)(side)(i, qp));
      66             :   }
      67             : };
      68             : 
      69             : class VariableTestValue
      70             : {
      71             : public:
      72             :   /**
      73             :    * Get the current test function
      74             :    * @param datum The AssemblyDatum object of the current thread
      75             :    * @param i The element-local DOF index
      76             :    * @param qp The local quadrature point index
      77             :    * @returns The test function
      78             :    */
      79   113036280 :   KOKKOS_FUNCTION Real operator()(AssemblyDatum & datum, unsigned int i, unsigned int qp) const
      80             :   {
      81   113036280 :     auto & elem = datum.elem();
      82   113036280 :     auto side = datum.side();
      83   113036280 :     auto fe = datum.ife();
      84             : 
      85           0 :     return side == libMesh::invalid_uint
      86   113036280 :                ? datum.assembly().getPhi(elem.subdomain, elem.type, fe)(i, qp)
      87   113036280 :                : datum.assembly().getPhiFace(elem.subdomain, elem.type, fe)(side)(i, qp);
      88             :   }
      89             : };
      90             : 
      91             : class VariableTestGradient
      92             : {
      93             : public:
      94             :   /**
      95             :    * Get the gradient of the current test function
      96             :    * @param datum The AssemblyDatum object of the current thread
      97             :    * @param i The element-local DOF index
      98             :    * @param qp The local quadrature point index
      99             :    * @returns The gradient of the test function
     100             :    */
     101    68208188 :   KOKKOS_FUNCTION Real3 operator()(AssemblyDatum & datum, unsigned int i, unsigned int qp) const
     102             :   {
     103    68208188 :     auto & elem = datum.elem();
     104    68208188 :     auto side = datum.side();
     105    68208188 :     auto fe = datum.ife();
     106             : 
     107           0 :     return datum.J(qp) *
     108             :            (side == libMesh::invalid_uint
     109    68208188 :                 ? datum.assembly().getGradPhi(elem.subdomain, elem.type, fe)(i, qp)
     110   136416376 :                 : datum.assembly().getGradPhiFace(elem.subdomain, elem.type, fe)(side)(i, qp));
     111             :   }
     112             : };
     113             : 
     114             : using ADVariablePhiValue = VariablePhiValue;
     115             : using ADVariablePhiGradient = VariablePhiGradient;
     116             : using ADVariableTestValue = VariableTestValue;
     117             : using ADVariableTestGradient = VariableTestGradient;
     118             : 
     119             : ///@}
     120             : 
     121             : /**
     122             :  * The Kokkos wrapper classes for MOOSE-like variable value access
     123             :  */
     124             : ///@{
     125             : template <bool is_ad>
     126             : class VariableValueTempl
     127             : {
     128             :   using real_type = std::conditional_t<is_ad, ADReal, Real>;
     129             : 
     130             : public:
     131             :   /**
     132             :    * Default constructor
     133             :    */
     134        8867 :   VariableValueTempl() = default;
     135             :   /**
     136             :    * Constructor
     137             :    * @param var The Kokkos variable
     138             :    * @param dof Whether to get DOF values
     139             :    */
     140        2898 :   VariableValueTempl(Variable var, bool dof = false) : _var(var), _dof(dof) {}
     141             :   /**
     142             :    * Constructor
     143             :    * @param var The MOOSE variable
     144             :    * @param tag The vector tag name
     145             :    * @param dof Whether to get DOF values
     146             :    */
     147        8872 :   VariableValueTempl(const MooseVariableFieldBase & var,
     148             :                      const TagName & tag = Moose::SOLUTION_TAG,
     149        4040 :                      bool dof = false)
     150        4832 :     : _var(var, tag), _dof(dof)
     151             :   {
     152        8872 :   }
     153             :   /**
     154             :    * Constructor
     155             :    * @param vars The MOOSE variables
     156             :    * @param tag The vector tag name
     157             :    * @param dof Whether to get DOF values
     158             :    */
     159             :   ///@{
     160             :   VariableValueTempl(const std::vector<const MooseVariableFieldBase *> & vars,
     161             :                      const TagName & tag = Moose::SOLUTION_TAG,
     162             :                      bool dof = false)
     163             :     : _var(vars, tag), _dof(dof)
     164             :   {
     165             :   }
     166             :   VariableValueTempl(const std::vector<MooseVariableFieldBase *> & vars,
     167             :                      const TagName & tag = Moose::SOLUTION_TAG,
     168             :                      bool dof = false)
     169             :     : _var(vars, tag), _dof(dof)
     170             :   {
     171             :   }
     172             :   ///@}
     173             : 
     174             :   /**
     175             :    * Copy constructor for parallel dispatch
     176             :    */
     177             :   VariableValueTempl(const VariableValueTempl<is_ad> & object);
     178             :   /**
     179             :    * Copy assignment operator
     180             :    */
     181             :   VariableValueTempl<is_ad> & operator=(const VariableValueTempl<is_ad> & object);
     182             : 
     183             :   /**
     184             :    * Get whether the variable was coupled
     185             :    * @returns Whether the variable was coupled
     186             :    */
     187       28032 :   KOKKOS_FUNCTION operator bool() const { return _var.coupled(); }
     188             : 
     189             :   /**
     190             :    * Get the current variable value
     191             :    * @param datum The Datum object of the current thread
     192             :    * @param idx The local quadrature point or DOF index
     193             :    * @param comp The variable component
     194             :    * @returns The variable value
     195             :    */
     196     2592739 :   KOKKOS_FUNCTION auto operator()(Datum & datum, unsigned int idx, unsigned int comp = 0) const
     197             :   {
     198     2592739 :     return get(datum, idx, comp);
     199             :   }
     200             : 
     201             :   /**
     202             :    * Get the current variable value
     203             :    * @param datum The AssemblyDatum object of the current thread
     204             :    * @param idx The local quadrature point or DOF index
     205             :    * @param comp The variable component
     206             :    * @returns The variable value
     207             :    */
     208             :   KOKKOS_FUNCTION auto
     209             :   operator()(AssemblyDatum & datum, unsigned int idx, unsigned int comp = 0) const;
     210             : 
     211             :   /**
     212             :    * Get the Kokkos variable
     213             :    * @returns The Kokkos variable
     214             :    */
     215      460146 :   KOKKOS_FUNCTION const Variable & variable() const { return _var; }
     216             : 
     217             : private:
     218             :   /**
     219             :    * Get the current variable value
     220             :    * @param datum The Datum object of the current thread
     221             :    * @param idx The local quadrature point or DOF index
     222             :    * @param comp The variable component
     223             :    * @param seed The derivative seed (only meaningful for AD)
     224             :    * @returns The variable value
     225             :    */
     226             :   KOKKOS_FUNCTION auto
     227             :   get(Datum & datum, unsigned int idx, unsigned int comp = 0, Real seed = 0) const;
     228             : 
     229             :   /**
     230             :    * Coupled Kokkos variable
     231             :    */
     232             :   Variable _var;
     233             :   /**
     234             :    * Derivative seed of each component for AD
     235             :    */
     236             :   Array<Real> _seed;
     237             :   /**
     238             :    * Flag whether DOF values are requested
     239             :    */
     240             :   bool _dof = false;
     241             : };
     242             : 
     243             : template <bool is_ad>
     244      589864 : VariableValueTempl<is_ad>::VariableValueTempl(const VariableValueTempl<is_ad> & object)
     245      336230 :   : _var(object._var), _seed(object._seed), _dof(object._dof)
     246             : {
     247             :   if constexpr (is_ad)
     248       59425 :     if (_var.coupled())
     249             :     {
     250       57533 :       if (!_seed.isAlloc())
     251       57533 :         _seed.create(_var.components());
     252             : 
     253      115066 :       for (unsigned int comp = 0; comp < _var.components(); ++comp)
     254       57533 :         _seed[comp] =
     255       29058 :             _var.dot() ? _var.mooseVar(comp)->sys().duDotDu(_var.var(comp)) : (_var.old() ? 0 : 1);
     256             : 
     257       57533 :       _seed.copyToDevice();
     258             :     }
     259      589864 : }
     260             : 
     261             : template <bool is_ad>
     262             : VariableValueTempl<is_ad> &
     263        8867 : VariableValueTempl<is_ad>::operator=(const VariableValueTempl<is_ad> & object)
     264             : {
     265        8867 :   _var = object._var;
     266        8867 :   _dof = object._dof;
     267             : 
     268        8867 :   return *this;
     269             : }
     270             : 
     271             : template <bool is_ad>
     272             : KOKKOS_FUNCTION auto
     273    14490855 : VariableValueTempl<is_ad>::operator()(AssemblyDatum & datum,
     274             :                                       unsigned int idx,
     275             :                                       unsigned int comp) const
     276             : {
     277             :   if constexpr (is_ad)
     278             :   {
     279     2369564 :     Real seed =
     280     2369564 :         datum.do_derivatives() && _var.coupled() && _var.sys(comp) == datum.sys() ? _seed[comp] : 0;
     281             : 
     282     2369564 :     return get(datum, idx, comp, seed);
     283             :   }
     284             :   else
     285    12121291 :     return get(datum, idx, comp);
     286             : }
     287             : 
     288             : template <bool is_ad>
     289             : KOKKOS_FUNCTION auto
     290    17083594 : VariableValueTempl<is_ad>::get(Datum & datum,
     291             :                                unsigned int idx,
     292             :                                unsigned int comp,
     293             :                                [[maybe_unused]] Real seed) const
     294             : {
     295             :   KOKKOS_ASSERT(_var.initialized());
     296             : 
     297     2369564 :   real_type value;
     298             : 
     299    17083594 :   if (_var.coupled())
     300             :   {
     301    17064380 :     auto & sys = datum.system(_var.sys(comp));
     302    17064380 :     auto var = _var.var(comp);
     303    17064380 :     auto tag = _var.tag();
     304             : 
     305    17064380 :     if (_dof)
     306             :     {
     307             :       unsigned int dof;
     308             : 
     309     4355794 :       if (datum.isNodal())
     310             :       {
     311     4355154 :         auto node = datum.node();
     312     4355154 :         dof = sys.getNodeLocalDofIndex(node, 0, var);
     313             :       }
     314             :       else
     315             :       {
     316         640 :         auto elem = datum.elem().id;
     317         640 :         dof = sys.getElemLocalDofIndex(elem, idx, var);
     318             :       }
     319             : 
     320             :       if constexpr (is_ad)
     321       68852 :         value = sys.getVectorDofADValue(dof, tag, seed);
     322             :       else
     323     4286942 :         value = sys.getVectorDofValue(dof, tag);
     324             :     }
     325             :     else
     326             :     {
     327    12708586 :       auto & elem = datum.elem();
     328    12708586 :       auto side = datum.side();
     329             : 
     330             :       if constexpr (is_ad)
     331     2285556 :         value = side == libMesh::invalid_uint
     332     4571112 :                     ? sys.getVectorQpADValue(elem, datum.qpOffset(), idx, var, tag, seed)
     333             :                     : sys.getVectorQpADValueFace(elem, side, idx, var, tag, seed);
     334             :       else
     335    10423030 :         value = side == libMesh::invalid_uint
     336    10423030 :                     ? sys.getVectorQpValue(elem, datum.qpOffset() + idx, var, tag)
     337      221894 :                     : sys.getVectorQpValueFace(elem, side, idx, var, tag);
     338             :     }
     339             :   }
     340             :   else
     341       19214 :     value = _var.value(comp);
     342             : 
     343    17083594 :   return value;
     344           0 : }
     345             : 
     346             : template <bool is_ad>
     347             : class VariableGradientTempl
     348             : {
     349             :   using real3_type = std::conditional_t<is_ad, ADReal3, Real3>;
     350             : 
     351             : public:
     352             :   /**
     353             :    * Default constructor
     354             :    */
     355             :   VariableGradientTempl() = default;
     356             :   /**
     357             :    * Constructor
     358             :    * @param var The Kokkos variable
     359             :    */
     360         680 :   VariableGradientTempl(Variable var) : _var(var) {}
     361             :   /**
     362             :    * Constructor
     363             :    * @param var The MOOSE variable
     364             :    * @param tag The vector tag name
     365             :    */
     366        3705 :   VariableGradientTempl(const MooseVariableFieldBase & var,
     367        1657 :                         const TagName & tag = Moose::SOLUTION_TAG)
     368        2048 :     : _var(var, tag)
     369             :   {
     370        3705 :   }
     371             :   /**
     372             :    * Constructor
     373             :    * @param vars The MOOSE variables
     374             :    * @param tag The vector tag name
     375             :    */
     376             :   ///@{
     377             :   VariableGradientTempl(const std::vector<const MooseVariableFieldBase *> & vars,
     378             :                         const TagName & tag = Moose::SOLUTION_TAG)
     379             :     : _var(vars, tag)
     380             :   {
     381             :   }
     382             :   VariableGradientTempl(const std::vector<MooseVariableFieldBase *> & vars,
     383             :                         const TagName & tag = Moose::SOLUTION_TAG)
     384             :     : _var(vars, tag)
     385             :   {
     386             :   }
     387             :   ///@}
     388             : 
     389             :   /**
     390             :    * Copy constructor for parallel dispatch
     391             :    */
     392             :   VariableGradientTempl(const VariableGradientTempl<is_ad> & object);
     393             :   /**
     394             :    * Copy assignment operator
     395             :    */
     396             :   VariableGradientTempl<is_ad> & operator=(const VariableGradientTempl<is_ad> & object);
     397             : 
     398             :   /**
     399             :    * Get whether the variable was coupled
     400             :    * @returns Whether the variable was coupled
     401             :    */
     402             :   KOKKOS_FUNCTION operator bool() const { return _var.coupled(); }
     403             : 
     404             :   /**
     405             :    * Get the current variable gradient
     406             :    * @param datum The Datum object of the current thread
     407             :    * @param qp The local quadrature point index
     408             :    * @param comp The variable component
     409             :    * @returns The variable gradient
     410             :    */
     411             :   KOKKOS_FUNCTION auto operator()(Datum & datum, unsigned int qp, unsigned int comp = 0) const
     412             :   {
     413             :     return get(datum, qp, comp);
     414             :   }
     415             : 
     416             :   /**
     417             :    * Get the current variable gradient
     418             :    * @param datum The AssemblyDatum object of the current thread
     419             :    * @param qp The local quadrature point index
     420             :    * @param comp The variable component
     421             :    * @returns The variable gradient
     422             :    */
     423             :   KOKKOS_FUNCTION auto
     424             :   operator()(AssemblyDatum & datum, unsigned int qp, unsigned int comp = 0) const;
     425             : 
     426             :   /**
     427             :    * Get the Kokkos variable
     428             :    * @returns The Kokkos variable
     429             :    */
     430             :   KOKKOS_FUNCTION const Variable & variable() const { return _var; }
     431             : 
     432             : private:
     433             :   /**
     434             :    * Get the current variable gradient
     435             :    * @param datum The Datum object of the current thread
     436             :    * @param qp The local quadrature point index
     437             :    * @param comp The variable component
     438             :    * @param seed The derivative seed (only meaningful for AD)
     439             :    * @returns The variable gradient
     440             :    */
     441             :   KOKKOS_FUNCTION auto
     442             :   get(Datum & datum, unsigned int qp, unsigned int comp = 0, Real seed = 0) const;
     443             : 
     444             :   /**
     445             :    * Coupled Kokkos variable
     446             :    */
     447             :   Variable _var;
     448             :   /**
     449             :    * Derivative seed of each component for AD
     450             :    */
     451             :   Array<Real> _seed;
     452             : };
     453             : 
     454             : template <bool is_ad>
     455      187636 : VariableGradientTempl<is_ad>::VariableGradientTempl(const VariableGradientTempl<is_ad> & object)
     456      111310 :   : _var(object._var), _seed(object._seed)
     457             : {
     458             :   if constexpr (is_ad)
     459       17931 :     if (_var.coupled())
     460             :     {
     461       17931 :       if (!_seed.isAlloc())
     462       17931 :         _seed.create(_var.components());
     463             : 
     464       35862 :       for (unsigned int comp = 0; comp < _var.components(); ++comp)
     465       17931 :         _seed[comp] =
     466        9068 :             _var.dot() ? _var.mooseVar(comp)->sys().duDotDu(_var.var(comp)) : (_var.old() ? 0 : 1);
     467             : 
     468       17931 :       _seed.copyToDevice();
     469             :     }
     470      187636 : }
     471             : 
     472             : template <bool is_ad>
     473             : VariableGradientTempl<is_ad> &
     474             : VariableGradientTempl<is_ad>::operator=(const VariableGradientTempl<is_ad> & object)
     475             : {
     476             :   _var = object._var;
     477             : 
     478             :   return *this;
     479             : }
     480             : 
     481             : template <bool is_ad>
     482             : KOKKOS_FUNCTION auto
     483    42819028 : VariableGradientTempl<is_ad>::operator()(AssemblyDatum & datum,
     484             :                                          unsigned int qp,
     485             :                                          unsigned int comp) const
     486             : {
     487             :   if constexpr (is_ad)
     488             :   {
     489     2369344 :     Real seed =
     490     2369344 :         datum.do_derivatives() && _var.coupled() && _var.sys(comp) == datum.sys() ? _seed[comp] : 0;
     491             : 
     492     2369344 :     return get(datum, qp, comp, seed);
     493             :   }
     494             :   else
     495    40449684 :     return get(datum, qp, comp);
     496             : }
     497             : 
     498             : template <bool is_ad>
     499             : KOKKOS_FUNCTION auto
     500    42819028 : VariableGradientTempl<is_ad>::get(Datum & datum,
     501             :                                   unsigned int qp,
     502             :                                   unsigned int comp,
     503             :                                   [[maybe_unused]] Real seed) const
     504             : {
     505             :   KOKKOS_ASSERT(_var.initialized());
     506             : 
     507    42819028 :   real3_type grad;
     508             : 
     509    42819028 :   if (_var.coupled())
     510             :   {
     511             :     KOKKOS_ASSERT(!datum.isNodal());
     512             : 
     513    42819028 :     auto & elem = datum.elem();
     514    42819028 :     auto side = datum.side();
     515             : 
     516             :     if constexpr (is_ad)
     517     2369344 :       grad =
     518             :           side == libMesh::invalid_uint
     519     4738688 :               ? datum.system(_var.sys(comp))
     520             :                     .getVectorQpADGrad(
     521             :                         elem, datum.J(qp), datum.qpOffset(), qp, _var.var(comp), _var.tag(), seed)
     522           0 :               : datum.system(_var.sys(comp))
     523             :                     .getVectorQpADGradFace(
     524             :                         elem, side, datum.J(qp), qp, _var.var(comp), _var.tag(), seed);
     525             :     else
     526    40449684 :       grad =
     527             :           side == libMesh::invalid_uint
     528    80899368 :               ? datum.system(_var.sys(comp))
     529    40449684 :                     .getVectorQpGrad(elem, datum.qpOffset() + qp, _var.var(comp), _var.tag())
     530           0 :               : datum.system(_var.sys(comp))
     531             :                     .getVectorQpGradFace(elem, side, datum.J(qp), qp, _var.var(comp), _var.tag());
     532             :   }
     533             : 
     534    42819028 :   return grad;
     535           0 : }
     536             : 
     537             : using VariableValue = VariableValueTempl<false>;
     538             : using ADVariableValue = VariableValueTempl<true>;
     539             : using VariableGradient = VariableGradientTempl<false>;
     540             : using ADVariableGradient = VariableGradientTempl<true>;
     541             : 
     542             : template <>
     543             : struct ArrayDeepCopy<ADVariableValue>
     544             : {
     545             :   static constexpr bool value = true;
     546             : };
     547             : 
     548             : template <>
     549             : struct ArrayDeepCopy<ADVariableGradient>
     550             : {
     551             :   static constexpr bool value = true;
     552             : };
     553             : ///@}
     554             : 
     555             : } // namespace Moose::Kokkos

Generated by: LCOV version 1.14