LCOV - code coverage report
Current view: top level - include/kokkos/mesh - KokkosMesh.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #32971 (54bef8) with base c6cf66 Lines: 49 51 96.1 %
Date: 2026-05-29 20:35:17 Functions: 25 26 96.2 %
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             : #ifdef MOOSE_KOKKOS_SCOPE
      15             : #include "KokkosUtils.h"
      16             : #endif
      17             : 
      18             : using ContiguousSubdomainID = SubdomainID;
      19             : using ContiguousBoundaryID = BoundaryID;
      20             : using ContiguousElementID = dof_id_type;
      21             : using ContiguousNodeID = dof_id_type;
      22             : 
      23             : class MooseMesh;
      24             : 
      25             : namespace Moose::Kokkos
      26             : {
      27             : 
      28             : /**
      29             :  * The Kokkos object that contains the information of an element
      30             :  * The IDs used in Kokkos are different from the MOOSE or libMesh IDs
      31             :  * The Kokkos IDs start from zero in each process and are contiguous
      32             :  */
      33             : struct ElementInfo
      34             : {
      35             :   /**
      36             :    * Element type ID
      37             :    */
      38             :   unsigned int type = libMesh::invalid_uint;
      39             :   /**
      40             :    * Contiguous element ID
      41             :    */
      42             :   ContiguousElementID id = libMesh::DofObject::invalid_id;
      43             :   /**
      44             :    * Contiguous subdomain ID
      45             :    */
      46             :   ContiguousSubdomainID subdomain = std::numeric_limits<ContiguousSubdomainID>::max();
      47             : };
      48             : 
      49             : /**
      50             :  * The Kokkos mesh object
      51             :  */
      52             : class Mesh
      53             : {
      54             : public:
      55             :   /**
      56             :    * Constructor
      57             :    * @param mesh The MOOSE mesh
      58             :    */
      59       51430 :   Mesh(MooseMesh & mesh) : _mesh(mesh) {}
      60             :   /**
      61             :    * Get the underyling MOOSE mesh
      62             :    * @returns The MOOSE mesh
      63             :    */
      64             :   const MooseMesh & getMesh() { return _mesh; }
      65             :   /**
      66             :    * Get whether the mesh was initialized
      67             :    */
      68     5325946 :   [[nodiscard]] bool initialized() const { return _initialized; }
      69             :   /**
      70             :    * Update the mesh
      71             :    */
      72             :   void update();
      73             : 
      74             :   /**
      75             :    * Get the number of subdomains
      76             :    * @returns The number of subdomains
      77             :    */
      78       36100 :   auto getNumSubdomains() const { return _maps->subdomain_id_mapping.size(); }
      79             :   /**
      80             :    * Get the number of local elements types
      81             :    * @returns The number of local element types
      82             :    */
      83        6795 :   auto getNumLocalElementTypes() const { return _maps->elem_type_id_mapping.size(); }
      84             :   /**
      85             :    * Get the element type ID map
      86             :    * @returns The element type ID map
      87             :    */
      88       11655 :   const auto & getElementTypeMap() const { return _maps->elem_type_id_mapping; }
      89             :   /**
      90             :    * Get the number of local elements
      91             :    * @returns The number of local elements
      92             :    */
      93      199162 :   auto getNumLocalElements() const { return _num_local_elems; }
      94             :   /**
      95             :    * Get the number of local elements in a MOOSE subdomain
      96             :    * @param subdomain The MOOSE subdomain ID
      97             :    * @returns The local number of elements in the subdomain
      98             :    */
      99         321 :   auto getNumSubdomainLocalElements(const SubdomainID subdomain) const
     100             :   {
     101         321 :     auto range = libmesh_map_find(_maps->subdomain_elem_id_ranges, subdomain);
     102         321 :     return range.second - range.first;
     103             :   }
     104             :   /**
     105             :    * Get the number of local nodes including semi-local nodes
     106             :    * @returns The number of local nodes including semi-local nodes
     107             :    */
     108        6795 :   auto getNumLocalNodes() const { return _num_local_nodes; }
     109             :   /**
     110             :    * Get the list of local nodes including semi-local nodes
     111             :    * @returns The list of local nodes including semi-local nodes
     112             :    */
     113        6284 :   const auto & getLocalNodes() const { return _maps->local_nodes; }
     114             :   /**
     115             :    * Get the contiguous subdomain ID of a MOOSE subdomain
     116             :    * @param subdomain The MOOSE subdomain ID
     117             :    * @returns The contiguous subdomain ID
     118             :    */
     119             :   ContiguousSubdomainID getContiguousSubdomainID(const SubdomainID subdomain) const;
     120             :   /**
     121             :    * Get the contiguous boundary ID of a boundary
     122             :    * @param boundary The MOOSE boundary ID
     123             :    * @returns The contiguous boundary ID
     124             :    */
     125             :   ContiguousBoundaryID getContiguousBoundaryID(const BoundaryID boundary) const;
     126             :   /**
     127             :    * Get the element type ID of an element
     128             :    * @param elem The libMesh element
     129             :    * @returns The element type ID
     130             :    */
     131             :   unsigned int getElementTypeID(const Elem * elem) const;
     132             :   /**
     133             :    * Get the contiguous element ID of an element
     134             :    * @param elem The libMesh element
     135             :    * @returns The contiguous element ID
     136             :    */
     137             :   ContiguousElementID getContiguousElementID(const Elem * elem) const;
     138             :   /**
     139             :    * Get the range of contiguous element IDs for a subdomain
     140             :    * @param subdomain The MOOSE subdomain ID
     141             :    * @returns The range of contiguous element IDs in the subdomain
     142             :    */
     143       17980 :   auto getSubdomainContiguousElementIDRange(const SubdomainID subdomain) const
     144             :   {
     145       17980 :     const auto & range = libmesh_map_find(_maps->subdomain_elem_id_ranges, subdomain);
     146       17980 :     return libMesh::make_range(range.first, range.second);
     147             :   }
     148             :   /**
     149             :    * Get the contiguous node ID of a node
     150             :    * @param node The libMesh node
     151             :    * @returns The contiguous node ID that starts from zero in each process
     152             :    */
     153             :   ContiguousNodeID getContiguousNodeID(const Node * node) const;
     154             :   /**
     155             :    * Get the list of local contiguous node IDs for a subdomain
     156             :    * NOTE: This list excludes semi-local nodes
     157             :    * @param subdomain The MOOSE subdomain ID
     158             :    * @returns The list of local contiguous node IDs in the subdomain
     159             :    */
     160       11994 :   const auto & getSubdomainContiguousNodeIDs(const SubdomainID subdomain) const
     161             :   {
     162       11994 :     return libmesh_map_find(_maps->subdomain_node_ids, subdomain);
     163             :   }
     164             :   /**
     165             :    * Get the list of local contiguous node IDs for a boundary
     166             :    * NOTE: This list excludes semi-local nodes
     167             :    * @param boundary The MOOSE boundary ID
     168             :    * @returns The list of local contiguous node IDs on the boundary
     169             :    */
     170       13668 :   const auto & getBoundaryContiguousNodeIDs(const BoundaryID boundary) const
     171             :   {
     172       13668 :     return libmesh_map_find(_maps->boundary_node_ids, boundary);
     173             :   }
     174             : #ifdef MOOSE_KOKKOS_SCOPE
     175             :   /**
     176             :    * Get the element information object
     177             :    * @param elem The contiguous element ID
     178             :    * @returns The element information object
     179             :    */
     180    91022215 :   KOKKOS_FUNCTION const auto & getElementInfo(ContiguousElementID elem) const
     181             :   {
     182    91022215 :     return _elem_info[elem];
     183             :   }
     184             :   /**
     185             :    * Get the neighbor contiguous element ID
     186             :    * @param elem The contiguous element ID
     187             :    * @param side The side index
     188             :    * @returns The neighbor contiguous element ID
     189             :    */
     190      578628 :   KOKKOS_FUNCTION ContiguousElementID getNeighbor(ContiguousElementID elem, unsigned int side) const
     191             :   {
     192      578628 :     return _elem_neighbor(side, elem);
     193             :   }
     194             :   /**
     195             :    * Get the number of sides of an element type
     196             :    * @param elem_type The element type ID
     197             :    * @returns The number of sides of the element type
     198             :    */
     199           0 :   KOKKOS_FUNCTION unsigned int getNumSides(unsigned int elem_type) const
     200             :   {
     201           0 :     return _num_sides[elem_type];
     202             :   }
     203             :   /**
     204             :    * Get the number of nodes of an element type
     205             :    * @param elem_type The element type ID
     206             :    * @returns The number of nodes of the element type
     207             :    */
     208     1682796 :   KOKKOS_FUNCTION unsigned int getNumNodes(unsigned int elem_type) const
     209             :   {
     210     1682796 :     return _num_nodes[elem_type];
     211             :   }
     212             :   /**
     213             :    * Get the number of nodes on a side of an element type
     214             :    * @param elem_type The element type ID
     215             :    * @param side The side index
     216             :    * @returns The number of nodes on the side of the element type
     217             :    */
     218     1063280 :   KOKKOS_FUNCTION unsigned int getNumNodes(unsigned int elem_type, unsigned int side) const
     219             :   {
     220     1063280 :     return _num_side_nodes[elem_type][side];
     221             :   }
     222             :   /**
     223             :    * Get the extra element ID of an element
     224             :    * @param elem The contiguous element ID
     225             :    * @param index The extra element ID index
     226             :    * @returns The extra element ID
     227             :    */
     228         500 :   KOKKOS_FUNCTION dof_id_type getExtraElementID(ContiguousElementID elem, unsigned int index) const
     229             :   {
     230             :     KOKKOS_ASSERT(index < _extra_elem_ids.n(1));
     231             : 
     232         500 :     return _extra_elem_ids(elem, index);
     233             :   }
     234             :   /**
     235             :    * Get the starting contiguous element ID of a subdomain
     236             :    * @param subdomain The contiguous subdomain ID
     237             :    * @returns The starting contiguous element ID
     238             :    */
     239    22175078 :   KOKKOS_FUNCTION dof_id_type getStartingContiguousElementID(ContiguousSubdomainID subdomain) const
     240             :   {
     241    22175078 :     return _starting_elem_id[subdomain];
     242             :   }
     243             :   /**
     244             :    * Get the contiguous node ID for an element
     245             :    * @param elem The contiguous element ID
     246             :    * @param node The node index
     247             :    * @returns The contiguous node ID
     248             :    */
     249     6956460 :   KOKKOS_FUNCTION ContiguousNodeID getContiguousNodeID(ContiguousElementID elem,
     250             :                                                        unsigned int node) const
     251             :   {
     252     6956460 :     return _nodes(node, elem);
     253             :   }
     254             :   /**
     255             :    * Get the contiguous node ID for a side
     256             :    * @param elem The contiguous element ID
     257             :    * @param side The side index
     258             :    * @param node The node index
     259             :    * @returns The contiguous node ID
     260             :    */
     261     2137244 :   KOKKOS_FUNCTION ContiguousNodeID getContiguousNodeID(ElementInfo info,
     262             :                                                        unsigned int side,
     263             :                                                        unsigned int node) const
     264             :   {
     265     2137244 :     return _nodes(_local_side_node[info.type](node, side), info.id);
     266             :   }
     267             :   /**
     268             :    * Get the coordinate of a node
     269             :    * @param node The contiguous node ID
     270             :    * @returns The node coordinate
     271             :    */
     272     9534070 :   KOKKOS_FUNCTION Real3 getNodePoint(ContiguousNodeID node) const { return _points[node]; }
     273             :   /**
     274             :    * Get whether a node is on a boundary
     275             :    * @param node The contiguous node ID
     276             :    * @param boundary The contiguous boundary ID
     277             :    * @returns Whether the node is on the boundary
     278             :    */
     279             :   KOKKOS_FUNCTION bool isBoundaryNode(ContiguousNodeID node, ContiguousBoundaryID boundary) const;
     280             : #endif
     281             : 
     282             : private:
     283             :   /**
     284             :    * Initialize host maps
     285             :    */
     286             :   void initMap();
     287             :   /**
     288             :    * Initialize device element data
     289             :    */
     290             :   void initElement();
     291             : 
     292             :   /**
     293             :    * Reference of the MOOSE mesh
     294             :    */
     295             :   MooseMesh & _mesh;
     296             :   /**
     297             :    * Flag whether the mesh was initialized
     298             :    */
     299             :   bool _initialized = false;
     300             : 
     301             :   /**
     302             :    * The wrapper of host maps
     303             :    */
     304             :   struct MeshMap
     305             :   {
     306             :     /**
     307             :      * Map from the MOOSE subdomain ID to the contiguous subdomain ID
     308             :      */
     309             :     std::unordered_map<SubdomainID, ContiguousSubdomainID> subdomain_id_mapping;
     310             :     /**
     311             :      * Map from the MOOSE boundary ID to the contiguous boundary ID
     312             :      */
     313             :     std::unordered_map<BoundaryID, ContiguousBoundaryID> boundary_id_mapping;
     314             :     /**
     315             :      * Map from the MOOSE element type to the element type ID
     316             :      */
     317             :     std::unordered_map<ElemType, unsigned int> elem_type_id_mapping;
     318             :     /**
     319             :      * List of local nodes including semi-local nodes
     320             :      */
     321             :     std::vector<Node *> local_nodes;
     322             :     /**
     323             :      * Map from the libMesh semi-local node to the contiguous node ID
     324             :      */
     325             :     std::unordered_map<const Node *, ContiguousNodeID> semi_local_node_id_mapping;
     326             :     /**
     327             :      * Range of the contiguous element IDs in each subdomain
     328             :      */
     329             :     std::unordered_map<SubdomainID, std::pair<ContiguousElementID, ContiguousElementID>>
     330             :         subdomain_elem_id_ranges;
     331             :     /**
     332             :      * List of the contiguous node IDs in each subdomain
     333             :      * NOTE: This list excludes semi-local nodes
     334             :      */
     335             :     std::unordered_map<SubdomainID, std::vector<ContiguousNodeID>> subdomain_node_ids;
     336             :     /**
     337             :      * List of the contiguous node IDs on each boundary
     338             :      * NOTE: This list excludes semi-local nodes
     339             :      */
     340             :     std::unordered_map<BoundaryID, std::set<ContiguousNodeID>> boundary_node_ids;
     341             :   };
     342             :   /**
     343             :    * A shared pointer holding all the host maps to avoid deep copy
     344             :    */
     345             :   std::shared_ptr<MeshMap> _maps;
     346             : 
     347             :   /**
     348             :    * Element integer for Kokkos contiguous element ID
     349             :    */
     350             :   unsigned int _elem_id_integer = libMesh::invalid_uint;
     351             :   /**
     352             :    * Node integer for Kokkos contiguous node ID
     353             :    */
     354             :   unsigned int _node_id_integer = libMesh::invalid_uint;
     355             :   /**
     356             :    * Number of local elements
     357             :    */
     358             :   dof_id_type _num_local_elems = 0;
     359             :   /**
     360             :    * Number of local nodes including semi-local nodes
     361             :    */
     362             :   dof_id_type _num_local_nodes = 0;
     363             :   /**
     364             :    * Element information
     365             :    */
     366             :   Array<ElementInfo> _elem_info;
     367             :   /**
     368             :    * Neighbor contiguous element IDs of each element
     369             :    */
     370             :   Array2D<ContiguousElementID> _elem_neighbor;
     371             :   /**
     372             :    * Starting contiguous element ID of each subdomain
     373             :    */
     374             :   Array<ContiguousElementID> _starting_elem_id;
     375             :   /**
     376             :    * Extra element IDs
     377             :    */
     378             :   Array2D<dof_id_type> _extra_elem_ids;
     379             :   /**
     380             :    * Number of sides of each element type
     381             :    */
     382             :   Array<unsigned int> _num_sides;
     383             :   /**
     384             :    * Number of nodes of each element type
     385             :    */
     386             :   Array<unsigned int> _num_nodes;
     387             :   /**
     388             :    * Number of nodes per side of each element side
     389             :    */
     390             :   Array<Array<unsigned int>> _num_side_nodes;
     391             :   /**
     392             :    * Map from local side node index to local element node index
     393             :    */
     394             :   Array<Array2D<unsigned int>> _local_side_node;
     395             :   /**
     396             :    * Node coordinates
     397             :    */
     398             :   Array<Real3> _points;
     399             :   /**
     400             :    * Contiguous node IDs of each element
     401             :    */
     402             :   Array2D<ContiguousNodeID> _nodes;
     403             :   /**
     404             :    * Contiguous node IDs on each boundary
     405             :    */
     406             :   Array<Array<ContiguousNodeID>> _boundary_nodes;
     407             : };
     408             : 
     409             : #ifdef MOOSE_KOKKOS_SCOPE
     410             : KOKKOS_FUNCTION inline bool
     411      664470 : Mesh::isBoundaryNode(ContiguousNodeID node, ContiguousBoundaryID boundary) const
     412             : {
     413      664470 :   if (!_boundary_nodes[boundary].size())
     414      106880 :     return false;
     415             : 
     416      557590 :   auto begin = &_boundary_nodes[boundary].begin();
     417      557590 :   auto end = &_boundary_nodes[boundary].end();
     418      557590 :   auto target = Utils::find(node, begin, end);
     419             : 
     420      557590 :   return target != end;
     421             : }
     422             : #endif
     423             : 
     424             : /**
     425             :  * The Kokkos interface that holds the host reference of the Kokkos mesh and copies it to device
     426             :  * during parallel dispatch
     427             :  * Maintains synchronization between host and device Kokkos mesh and provides access to the
     428             :  * appropriate Kokkos mesh depending on the architecture
     429             :  */
     430             : class MeshHolder
     431             : {
     432             : public:
     433             :   /**
     434             :    * Constructor
     435             :    * @param mesh The Kokkos mesh
     436             :    */
     437       63245 :   MeshHolder(const Mesh & mesh) : _mesh_host(mesh), _mesh_device(mesh) {}
     438             :   /**
     439             :    * Copy constructor
     440             :    */
     441     1416947 :   MeshHolder(const MeshHolder & holder)
     442      816625 :     : _mesh_host(holder._mesh_host), _mesh_device(holder._mesh_host)
     443             :   {
     444     1416947 :   }
     445             : 
     446             : #ifdef MOOSE_KOKKOS_SCOPE
     447             :   /**
     448             :    * Get the const reference of the Kokkos mesh
     449             :    * @returns The const reference of the Kokkos mesh depending on the architecture this function
     450             :    * is being called on
     451             :    */
     452   121828825 :   KOKKOS_FUNCTION const Mesh & kokkosMesh() const
     453             :   {
     454   121828825 :     KOKKOS_IF_ON_HOST(
     455             :         if (!_mesh_host.initialized()) mooseError(
     456             :             "kokkosMesh() was called too early. Kokkos mesh is available after problem "
     457             :             "initialization. Override initialSetup() if you need to setup your object data "
     458             :             "using the Kokkos mesh.");
     459             : 
     460             :         return _mesh_host;)
     461             : 
     462   116502879 :     return _mesh_device;
     463             :   }
     464             : #endif
     465             : 
     466             : private:
     467             :   /**
     468             :    * Host reference of the Kokkos mesh
     469             :    */
     470             :   const Mesh & _mesh_host;
     471             :   /**
     472             :    * Device copy of the Kokkos mesh
     473             :    */
     474             :   const Mesh _mesh_device;
     475             : };
     476             : 
     477             : } // namespace Moose::Kokkos

Generated by: LCOV version 1.14