LCOV - code coverage report
Current view: top level - include/kokkos/base - KokkosAssembly.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 6f668f Lines: 95 101 94.1 %
Date: 2025-09-22 20:01:15 Functions: 22 23 95.7 %
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 "KokkosTypes.h"
      13             : 
      14             : #include "MooseMesh.h"
      15             : 
      16             : #include "libmesh/elem_range.h"
      17             : #include "libmesh/fe_base.h"
      18             : #include "libmesh/fe_type.h"
      19             : 
      20             : class FEProblemBase;
      21             : 
      22             : namespace Moose
      23             : {
      24             : namespace Kokkos
      25             : {
      26             : 
      27             : /**
      28             :  * The Kokkos assembly class
      29             :  */
      30             : class Assembly : public MeshHolder
      31             : {
      32             : public:
      33             :   /**
      34             :    * Constructor
      35             :    * @param problem The MOOSE problem
      36             :    */
      37             :   Assembly(FEProblemBase & problem);
      38             :   /**
      39             :    * Initialize assembly
      40             :    */
      41             :   void init();
      42             : 
      43             : #ifdef MOOSE_KOKKOS_SCOPE
      44             :   /**
      45             :    * Get the FE type ID
      46             :    * @param type The libMesh FEType object
      47             :    * @returns The FE type ID
      48             :    */
      49        1182 :   unsigned int getFETypeID(FEType type) const { return libmesh_map_find(_fe_type_map, type); }
      50             :   /**
      51             :    * Get the maximum number of quadrature points per element in the current partition
      52             :    * @returns The maximum number of quadrature points per element
      53             :    */
      54       63574 :   KOKKOS_FUNCTION unsigned int getMaxQpsPerElem() const { return _max_qps_per_elem; }
      55             :   /**
      56             :    * Get the total number of elemental quadrature points in a subdomain
      57             :    * @param subdomain The contiguous subdomain ID
      58             :    * @returns The number of quadrature points
      59             :    */
      60        3847 :   KOKKOS_FUNCTION dof_id_type getNumQps(ContiguousSubdomainID subdomain) const
      61             :   {
      62        3847 :     return _n_subdomain_qps[subdomain];
      63             :   }
      64             :   /**
      65             :    * Get the number of quadrature points of an element
      66             :    * @param info The element information object
      67             :    * @returns The number of quadrature points
      68             :    */
      69    21881579 :   KOKKOS_FUNCTION unsigned int getNumQps(ElementInfo info) const { return _n_qps[info.id]; }
      70             :   /**
      71             :    * Get the total number of facial quadrature points in a subdomain
      72             :    * Note: this number does not represent the real number of facial quadrature points but only
      73             :    * counts the facial quadrature points that need global caching, such as face material properties
      74             :    * @param subdomain The contiguous subdomain ID
      75             :    * @returns The number of quadrature points
      76             :    */
      77        1169 :   KOKKOS_FUNCTION dof_id_type getNumFaceQps(ContiguousSubdomainID subdomain) const
      78             :   {
      79        1169 :     return _n_subdomain_qps_face[subdomain];
      80             :   }
      81             :   /**
      82             :    * Get the number of quadrature points of a side of an element
      83             :    * @param info The element information object
      84             :    * @param side The side index
      85             :    * @returns The number of quadrature points
      86             :    */
      87       94030 :   KOKKOS_FUNCTION unsigned int getNumFaceQps(ElementInfo info, unsigned int side) const
      88             :   {
      89       94030 :     return _n_qps_face(side, info.id);
      90             :   }
      91             :   /**
      92             :    * Get the starting offset of quadrature points of an element into the global quadrature point
      93             :    * index
      94             :    * @param info The element information object
      95             :    * @returns The starting offset
      96             :    */
      97    74795355 :   KOKKOS_FUNCTION dof_id_type getQpOffset(ElementInfo info) const { return _qp_offset[info.id]; }
      98             :   /**
      99             :    * Get the starting offset of quadrature points of a side of an element into the global quadrature
     100             :    * point index
     101             :    * @param info The element information object
     102             :    * @param side The side index
     103             :    * @returns The starting offset
     104             :    */
     105       94030 :   KOKKOS_FUNCTION dof_id_type getQpFaceOffset(ElementInfo info, unsigned int side) const
     106             :   {
     107       94030 :     return _qp_offset_face(side, info.id);
     108             :   }
     109             :   /**
     110             :    * Get the number of DOFs of a FE type for an element type
     111             :    * @param elem_type The element type ID
     112             :    * @param fe_type The FE type ID
     113             :    * @returns The number of DOFs
     114             :    */
     115    24238160 :   KOKKOS_FUNCTION unsigned int getNumDofs(unsigned int elem_type, unsigned int fe_type) const
     116             :   {
     117    24238160 :     return _n_dofs(elem_type, fe_type);
     118             :   }
     119             :   /**
     120             :    * Get the shape functions of a FE type for an element type and subdomain
     121             :    * @param subdomain The contiguous subdomain ID
     122             :    * @param elem_type The element type ID
     123             :    * @param fe_type The FE type ID
     124             :    * @returns The shape functions at quadrature points
     125             :    */
     126             :   KOKKOS_FUNCTION const auto &
     127    64338976 :   getPhi(ContiguousSubdomainID subdomain, unsigned int elem_type, unsigned int fe_type) const
     128             :   {
     129    64338976 :     return _phi(subdomain, elem_type, fe_type);
     130             :   }
     131             :   /**
     132             :    * Get the face shape functions of a FE type for an element type and subdomain
     133             :    * @param subdomain The contiguous subdomain ID
     134             :    * @param elem_type The element type ID
     135             :    * @param fe_type The FE type ID
     136             :    * @returns The shape functions of all sides at quadrature points
     137             :    */
     138             :   KOKKOS_FUNCTION const auto &
     139      604920 :   getPhiFace(ContiguousSubdomainID subdomain, unsigned int elem_type, unsigned int fe_type) const
     140             :   {
     141      604920 :     return _phi_face(subdomain, elem_type, fe_type);
     142             :   }
     143             :   /**
     144             :    * Get the gradient of shape functions of a FE type for an element type and subdomain
     145             :    * @param subdomain The contiguous subdomain ID
     146             :    * @param elem_type The element type ID
     147             :    * @param fe_type The FE type ID
     148             :    * @returns The gradient of shape functions at quadrature points
     149             :    */
     150             :   KOKKOS_FUNCTION const auto &
     151    72618736 :   getGradPhi(ContiguousSubdomainID subdomain, unsigned int elem_type, unsigned int fe_type) const
     152             :   {
     153    72618736 :     return _grad_phi(subdomain, elem_type, fe_type);
     154             :   }
     155             :   /**
     156             :    * Get the gradient of face shape functions of a FE type for an element type and subdomain
     157             :    * @param subdomain The contiguous subdomain ID
     158             :    * @param elem_type The element type ID
     159             :    * @param fe_type The FE type ID
     160             :    * @returns The gradient of shape functions of all sides at quadrature points
     161             :    */
     162           0 :   KOKKOS_FUNCTION const auto & getGradPhiFace(ContiguousSubdomainID subdomain,
     163             :                                               unsigned int elem_type,
     164             :                                               unsigned int fe_type) const
     165             :   {
     166           0 :     return _grad_phi_face(subdomain, elem_type, fe_type);
     167             :   }
     168             :   /**
     169             :    * Get the inverse of Jacobian matrix of an element quadrature point
     170             :    * @param info The element information object
     171             :    * @param qp The local quadrature point index
     172             :    * @returns The inverse of Jacobian matrix
     173             :    */
     174    29821856 :   KOKKOS_FUNCTION Real33 getJacobian(ElementInfo info, unsigned int qp) const
     175             :   {
     176    29821856 :     return _jacobian[info.subdomain][getQpOffset(info) + qp];
     177             :   }
     178             :   /**
     179             :    * Get the transformed Jacobian weight of an element quadrature point
     180             :    * @param info The element information object
     181             :    * @param qp The local quadrature point index
     182             :    * @returns The inverse of Jacobian matrix
     183             :    */
     184    11593104 :   KOKKOS_FUNCTION Real getJxW(ElementInfo info, unsigned int qp) const
     185             :   {
     186    11593104 :     return _jxw[info.subdomain][getQpOffset(info) + qp];
     187             :   }
     188             :   /**
     189             :    * Get the coordinate of an element quadrature point
     190             :    * @param info The element information object
     191             :    * @param qp The local quadrature point index
     192             :    * @returns The inverse of Jacobian matrix
     193             :    */
     194    11593104 :   KOKKOS_FUNCTION Real3 getQPoint(ElementInfo info, unsigned int qp) const
     195             :   {
     196    11593104 :     return _xyz[info.subdomain][getQpOffset(info) + qp];
     197             :   }
     198             : 
     199             :   /**
     200             :    * Get the coordinate transform factor for a point in a subdomain
     201             :    * @param subdomain The contiguous subdomain ID
     202             :    * @param point The point coordinate
     203             :    * @returns The coordinate transform factor
     204             :    */
     205             :   KOKKOS_FUNCTION Real coordTransformFactor(const ContiguousSubdomainID subdomain,
     206             :                                             const Real3 point) const;
     207             :   /**
     208             :    * Compute physical transformation data for an element
     209             :    * @param info The element information object
     210             :    * @param qp The local quadrature point index
     211             :    * @param jacobian The pointer to store the inverse of Jacobian matrix
     212             :    * @param JxW The pointer to store transformed Jacobian weight
     213             :    * @param q_points The pointer to store physical quadrature point coordinate
     214             :    */
     215             :   KOKKOS_FUNCTION void computePhysicalMap(const ElementInfo info,
     216             :                                           const unsigned int qp,
     217             :                                           Real33 * const jacobian,
     218             :                                           Real * const JxW,
     219             :                                           Real3 * const q_points) const;
     220             :   /**
     221             :    * Compute physical transformation data for a side
     222             :    * @param info The element information object
     223             :    * @param side The side index
     224             :    * @param qp The local quadrature point index
     225             :    * @param jacobian The pointer to store the inverse of Jacobian matrix
     226             :    * @param JxW The pointer to store transformed Jacobian weight
     227             :    * @param q_points The pointer to store physical quadrature point coordinate
     228             :    */
     229             :   KOKKOS_FUNCTION void computePhysicalMap(const ElementInfo info,
     230             :                                           const unsigned int side,
     231             :                                           const unsigned int qp,
     232             :                                           Real33 * const jacobian,
     233             :                                           Real * const JxW,
     234             :                                           Real3 * const q_points) const;
     235             : 
     236             :   /**
     237             :    * Kokkos function for caching physical maps on element quadrature points
     238             :    */
     239             :   KOKKOS_FUNCTION void operator()(const ThreadID tid) const;
     240             : 
     241             :   /**
     242             :    * Get the list of boundaries to cache face material properties
     243             :    * @returns The list of boundaries
     244             :    */
     245         563 :   const auto & getMaterialBoundaries() const { return _material_boundaries; }
     246             : #endif
     247             : 
     248             : private:
     249             :   /**
     250             :    * Initialize quadrature data
     251             :    */
     252             :   void initQuadrature();
     253             :   /**
     254             :    * Initialize shape data
     255             :    */
     256             :   void initShape();
     257             :   /**
     258             :    * Cache physical maps on element quadrature points
     259             :    */
     260             :   void cachePhysicalMap();
     261             : 
     262             :   /**
     263             :    * Reference of the MOOSE problem
     264             :    */
     265             :   FEProblemBase & _problem;
     266             :   /**
     267             :    * Reference of the MOOSE mesh
     268             :    */
     269             :   MooseMesh & _mesh;
     270             :   /**
     271             :    * FE type ID map
     272             :    */
     273             :   std::map<FEType, unsigned int> _fe_type_map;
     274             : 
     275             :   /**
     276             :    * Mesh dimension
     277             :    */
     278             :   const unsigned int _dimension;
     279             :   /**
     280             :    * Coordinate system type of each subdomain
     281             :    */
     282             :   Array<Moose::CoordinateSystemType> _coord_type;
     283             :   /**
     284             :    * Radial coordinate index in cylindrical coordinate system
     285             :    */
     286             :   unsigned int _rz_radial_coord = libMesh::invalid_uint;
     287             :   /**
     288             :    * General axisymmetric axis of each subdomain in cylindrical coordinate system
     289             :    */
     290             :   Array<Pair<Real3, Real3>> _rz_axis;
     291             : 
     292             :   /**
     293             :    * Starting offset into the global quadrature point index
     294             :    */
     295             :   ///@{
     296             :   Array<dof_id_type> _qp_offset;
     297             :   Array2D<dof_id_type> _qp_offset_face;
     298             :   ///@}
     299             :   /**
     300             :    * Number of quadrature points
     301             :    */
     302             :   ///@{
     303             :   Array<unsigned int> _n_qps;
     304             :   Array2D<unsigned int> _n_qps_face;
     305             : 
     306             :   unsigned int _max_qps_per_elem = 0;
     307             : 
     308             :   Array<dof_id_type> _n_subdomain_qps;
     309             :   Array<dof_id_type> _n_subdomain_qps_face;
     310             :   ///@}
     311             :   /**
     312             :    * Quadrature points and weights for reference elements
     313             :    */
     314             :   ///@{
     315             :   Array2D<Array<Real3>> _q_points;
     316             :   Array2D<Array<Array<Real3>>> _q_points_face;
     317             :   Array2D<Array<Real>> _weights;
     318             :   Array2D<Array<Array<Real>>> _weights_face;
     319             :   ///@}
     320             :   /**
     321             :    * Shape functions for reference elements
     322             :    */
     323             :   ///@{
     324             :   Array3D<Array2D<Real>> _phi;
     325             :   Array3D<Array<Array2D<Real>>> _phi_face;
     326             :   Array3D<Array2D<Real3>> _grad_phi;
     327             :   Array3D<Array<Array2D<Real3>>> _grad_phi_face;
     328             :   Array2D<unsigned int> _n_dofs;
     329             :   ///@}
     330             :   /**
     331             :    * Shape functions for computing reference-to-physical maps
     332             :    */
     333             :   ///@{
     334             :   Array2D<Array2D<Real>> _map_phi;
     335             :   Array2D<Array<Array2D<Real>>> _map_phi_face;
     336             :   Array2D<Array<Array2D<Real>>> _map_psi_face;
     337             :   Array2D<Array2D<Real3>> _map_grad_phi;
     338             :   Array2D<Array<Array2D<Real3>>> _map_grad_phi_face;
     339             :   Array2D<Array<Array2D<Real3>>> _map_grad_psi_face;
     340             :   ///@}
     341             :   /**
     342             :    * Cached physical maps on element quadrature points
     343             :    */
     344             :   ///@{
     345             :   Array<Array<Real33>> _jacobian;
     346             :   Array<Array<Real>> _jxw;
     347             :   Array<Array<Real3>> _xyz;
     348             :   ///@}
     349             : 
     350             :   /**
     351             :    * Boundaries to cache face material properties
     352             :    */
     353             :   std::set<BoundaryID> _material_boundaries;
     354             : };
     355             : 
     356             : #ifdef MOOSE_KOKKOS_SCOPE
     357             : KOKKOS_FUNCTION inline Real
     358      183742 : Assembly::coordTransformFactor(const ContiguousSubdomainID subdomain, const Real3 point) const
     359             : {
     360      183742 :   switch (_coord_type[subdomain])
     361             :   {
     362      180802 :     case Moose::COORD_XYZ:
     363      180802 :       return 1;
     364        2800 :     case Moose::COORD_RZ:
     365        2800 :       if (_rz_radial_coord == libMesh::invalid_uint)
     366           0 :         return 2 * M_PI *
     367           0 :                (point - _rz_axis[subdomain].first).cross_product(_rz_axis[subdomain].second).norm();
     368             :       else
     369        2800 :         return 2 * M_PI * point(_rz_radial_coord);
     370         140 :     case Moose::COORD_RSPHERICAL:
     371         140 :       return 4 * M_PI * point(0) * point(0);
     372           0 :     default:
     373           0 :       return 0;
     374             :   }
     375             : }
     376             : 
     377             : KOKKOS_FUNCTION inline void
     378       94288 : Assembly::computePhysicalMap(const ElementInfo info,
     379             :                              const unsigned int qp,
     380             :                              Real33 * const jacobian,
     381             :                              Real * const JxW,
     382             :                              Real3 * const q_points) const
     383             : {
     384       94288 :   auto sid = info.subdomain;
     385       94288 :   auto eid = info.id;
     386       94288 :   auto elem_type = info.type;
     387       94288 :   auto num_nodes = kokkosMesh().getNumNodes(elem_type);
     388             : 
     389       94288 :   auto & phi = _map_phi(sid, elem_type);
     390       94288 :   auto & grad_phi = _map_grad_phi(sid, elem_type);
     391             : 
     392       94288 :   Real33 J;
     393       94288 :   Real3 xyz;
     394             : 
     395      502712 :   for (unsigned int node = 0; node < num_nodes; ++node)
     396             :   {
     397      408424 :     auto points = kokkosMesh().getNodePoint(kokkosMesh().getContiguousNodeID(eid, node));
     398             : 
     399      408424 :     if (jacobian || JxW)
     400      408424 :       J += grad_phi(node, qp).cartesian_product(points);
     401             : 
     402      408424 :     xyz += phi(node, qp) * points;
     403             :   }
     404             : 
     405       94288 :   if (jacobian)
     406       94288 :     *jacobian = J.inverse(_dimension);
     407       94288 :   if (JxW)
     408       94288 :     *JxW =
     409       94288 :         J.determinant(_dimension) * _weights(sid, elem_type)[qp] * coordTransformFactor(sid, xyz);
     410       94288 :   if (q_points)
     411       94288 :     *q_points = xyz;
     412       94288 : }
     413             : 
     414             : KOKKOS_FUNCTION inline void
     415       89454 : Assembly::computePhysicalMap(const ElementInfo info,
     416             :                              const unsigned int side,
     417             :                              const unsigned int qp,
     418             :                              Real33 * const jacobian,
     419             :                              Real * const JxW,
     420             :                              Real3 * const q_points) const
     421             : {
     422       89454 :   auto sid = info.subdomain;
     423       89454 :   auto eid = info.id;
     424       89454 :   auto elem_type = info.type;
     425       89454 :   auto num_nodes = kokkosMesh().getNumNodes(elem_type);
     426       89454 :   auto num_side_nodes = kokkosMesh().getNumNodes(elem_type, side);
     427             : 
     428       89454 :   auto & phi = _map_phi_face(sid, elem_type)(side);
     429       89454 :   auto & grad_phi = _map_grad_phi_face(sid, elem_type)(side);
     430             : 
     431       89454 :   Real33 J;
     432       89454 :   Real3 xyz;
     433             : 
     434      446218 :   for (unsigned int node = 0; node < num_nodes; ++node)
     435             :   {
     436      356764 :     auto points = kokkosMesh().getNodePoint(kokkosMesh().getContiguousNodeID(eid, node));
     437             : 
     438      356764 :     if (jacobian)
     439      356764 :       J += grad_phi(node, qp).cartesian_product(points);
     440             : 
     441      356764 :     if (JxW || q_points)
     442      356764 :       xyz += phi(node, qp) * points;
     443             :   }
     444             : 
     445       89454 :   if (jacobian)
     446       89454 :     *jacobian = J.inverse(_dimension);
     447       89454 :   if (q_points)
     448       89454 :     *q_points = xyz;
     449             : 
     450       89454 :   if (JxW)
     451             :   {
     452       89454 :     Real33 J;
     453             : 
     454       89454 :     auto & grad_psi = _map_grad_psi_face(sid, elem_type)(side);
     455             : 
     456      267836 :     for (unsigned int node = 0; node < num_side_nodes; ++node)
     457             :     {
     458      178382 :       auto points = kokkosMesh().getNodePoint(kokkosMesh().getContiguousNodeID(eid, side, node));
     459             : 
     460      178382 :       J += grad_psi(node, qp).cartesian_product(points);
     461             :     }
     462             : 
     463       89454 :     *JxW = ::Kokkos::sqrt((J * J.transpose()).determinant(_dimension - 1)) *
     464       89454 :            _weights_face(sid, elem_type)[side][qp] * coordTransformFactor(sid, xyz);
     465             :   }
     466       89454 : }
     467             : #endif
     468             : 
     469             : /**
     470             :  * The Kokkos interface that holds the host reference of the Kokkos assembly and copies it to device
     471             :  * during parallel dispatch.
     472             :  * Maintains synchronization between host and device Kokkos assemblies and provides access to the
     473             :  * appropriate Kokkos assembly depending on the architecture.
     474             :  */
     475             : class AssemblyHolder
     476             : {
     477             : public:
     478             :   /**
     479             :    * Constructor
     480             :    * @param assembly The Kokkos assembly
     481             :    */
     482        5311 :   AssemblyHolder(const Assembly & assembly) : _assembly_host(assembly), _assembly_device(assembly)
     483             :   {
     484        5311 :   }
     485             :   /**
     486             :    * Copy constructor
     487             :    */
     488      257449 :   AssemblyHolder(const AssemblyHolder & holder)
     489      209497 :     : _assembly_host(holder._assembly_host), _assembly_device(holder._assembly_host)
     490             :   {
     491      257449 :   }
     492             : 
     493             : #ifdef MOOSE_KOKKOS_SCOPE
     494             :   /**
     495             :    * Get the const reference of the Kokkos assembly
     496             :    * @returns The const reference of the Kokkos assembly depending on the architecture this function
     497             :    * is being called on
     498             :    */
     499   113422379 :   KOKKOS_FUNCTION const Assembly & kokkosAssembly() const
     500             :   {
     501   113422379 :     KOKKOS_IF_ON_HOST(return _assembly_host;)
     502             : 
     503   113353778 :     return _assembly_device;
     504             :   }
     505             : #endif
     506             : 
     507             : private:
     508             :   /**
     509             :    * Host reference of the Kokkos assembly
     510             :    */
     511             :   const Assembly & _assembly_host;
     512             :   /**
     513             :    * Device copy of the Kokkos assembly
     514             :    */
     515             :   const Assembly _assembly_device;
     516             : };
     517             : 
     518             : } // namespace Kokkos
     519             : } // namespace Moose

Generated by: LCOV version 1.14