LCOV - code coverage report
Current view: top level - src/kokkos/base - KokkosAssembly.K (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 329044 Lines: 329 337 97.6 %
Date: 2026-08-03 21:12:22 Functions: 7 7 100.0 %
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             : #include "KokkosAssembly.h"
      11             : 
      12             : #include "MooseMesh.h"
      13             : #include "FEProblemBase.h"
      14             : #include "NonlinearSystemBase.h"
      15             : #include "LinearSystem.h"
      16             : #include "AuxiliarySystem.h"
      17             : #include "Assembly.h"
      18             : #include "BoundaryRestrictable.h"
      19             : 
      20             : #include "libmesh/fe_interface.h"
      21             : #include "libmesh/reference_elem.h"
      22             : 
      23             : namespace Moose::Kokkos
      24             : {
      25             : 
      26       47924 : Assembly::Assembly(FEProblemBase & problem)
      27       45530 :   : MeshHolder(*problem.mesh().getKokkosMesh()),
      28       45530 :     _problem(problem),
      29       45530 :     _mesh(problem.mesh()),
      30      136590 :     _dimension(_mesh.dimension())
      31             : {
      32       47924 : }
      33             : 
      34             : void
      35        2622 : Assembly::init()
      36             : {
      37             :   // Cache mesh information
      38             : 
      39        2622 :   const auto num_subdomains = kokkosMesh().getNumSubdomains();
      40             : 
      41        2622 :   _coord_type.create(num_subdomains);
      42             : 
      43        5974 :   for (auto subdomain : _mesh.meshSubdomains())
      44        3352 :     _coord_type[kokkosMesh().getContiguousSubdomainID(subdomain)] = _mesh.getCoordSystem(subdomain);
      45             : 
      46        2622 :   _coord_type.copyToDevice();
      47             : 
      48        2622 :   if (_mesh.usingGeneralAxisymmetricCoordAxes())
      49             :   {
      50           0 :     _rz_axis.create(num_subdomains);
      51             : 
      52           0 :     for (auto subdomain : _mesh.meshSubdomains())
      53           0 :       _rz_axis[kokkosMesh().getContiguousSubdomainID(subdomain)] =
      54           0 :           _mesh.getGeneralAxisymmetricCoordAxis(subdomain);
      55             : 
      56           0 :     _rz_axis.copyToDevice();
      57             :   }
      58             :   else
      59        2622 :     _rz_radial_coord = _mesh.getAxisymmetricRadialCoord();
      60             : 
      61             :   // Initialize quadrature and shape data
      62             : 
      63        2622 :   initQuadrature();
      64        2622 :   initShape();
      65        2622 :   cachePhysicalMap();
      66        2622 : }
      67             : 
      68             : void
      69        2622 : Assembly::initQuadrature()
      70             : {
      71        2622 :   const auto num_subdomains = kokkosMesh().getNumSubdomains();
      72        2622 :   const auto num_elem_types = kokkosMesh().getNumLocalElementTypes();
      73             : 
      74        2622 :   _q_points.create(num_subdomains, num_elem_types);
      75        2622 :   _q_points_face.create(num_subdomains, num_elem_types);
      76        2622 :   _weights.create(num_subdomains, num_elem_types);
      77        2622 :   _weights_face.create(num_subdomains, num_elem_types);
      78             : 
      79             :   // Find boundaries where material properties should be computed
      80             : 
      81        1208 :   auto & boundary_objects =
      82        1414 :       _problem.getKokkosMaterialPropertyStorageConsumers(Moose::BOUNDARY_MATERIAL_DATA);
      83             : 
      84        3476 :   for (auto object : boundary_objects)
      85             :   {
      86         854 :     auto boundary_restriction = dynamic_cast<const BoundaryRestrictable *>(object);
      87             : 
      88         854 :     if (boundary_restriction)
      89        1810 :       for (auto boundary : boundary_restriction->boundaryIDs())
      90         956 :         _material_boundaries.insert(boundary);
      91             :     else
      92           0 :       mooseError("Kokkos assembly error: ", object->name(), " is not boundary-restricted.");
      93             :   }
      94             : 
      95             :   // Cache quadrature data
      96             : 
      97        2622 :   std::map<SubdomainID, std::map<ElemType, unsigned int>> n_qps;
      98        2622 :   std::map<SubdomainID, std::map<ElemType, std::vector<unsigned int>>> n_qps_face;
      99             : 
     100        2622 :   _max_qps_per_elem = 0;
     101             : 
     102        5974 :   for (auto subdomain : _mesh.meshSubdomains())
     103             :   {
     104        3352 :     auto sid = kokkosMesh().getContiguousSubdomainID(subdomain);
     105             : 
     106        3352 :     auto & assembly = _problem.assembly(0, 0);
     107        3352 :     auto qrule = assembly.writeableQRule(_dimension, subdomain, {});
     108        3352 :     auto qrule_face = assembly.writeableQRuleFace(_dimension, subdomain, {});
     109             : 
     110        6696 :     for (auto & [elem_type, elem_type_id] : kokkosMesh().getElementTypeMap())
     111             :     {
     112        3344 :       auto elem = &libMesh::ReferenceElem::get(elem_type);
     113             : 
     114        3344 :       _q_points_face(sid, elem_type_id).create(elem->n_sides());
     115        3344 :       _weights_face(sid, elem_type_id).create(elem->n_sides());
     116             : 
     117             :       // Cache volume quadrature of each reference element
     118             : 
     119        3344 :       qrule->init(*elem, /* p-level */ 0);
     120        3344 :       n_qps[subdomain][elem_type] = qrule->n_points();
     121             : 
     122        3344 :       _q_points(sid, elem_type_id).create(qrule->n_points());
     123        3344 :       _weights(sid, elem_type_id).create(qrule->n_points());
     124             : 
     125       15778 :       for (const auto qp : make_range(qrule->n_points()))
     126             :       {
     127       12434 :         _q_points(sid, elem_type_id)[qp] = qrule->qp(qp);
     128       12434 :         _weights(sid, elem_type_id)[qp] = qrule->w(qp);
     129             :       }
     130             : 
     131             :       // Cache face quadrature of each reference element
     132             : 
     133       16088 :       for (const auto side : elem->side_index_range())
     134             :       {
     135       12744 :         qrule_face->init(*elem->side_ptr(side), /* p-level */ 0);
     136       12744 :         n_qps_face[subdomain][elem_type].push_back(qrule_face->n_points());
     137             : 
     138       12744 :         _q_points_face(sid, elem_type_id)[side].create(qrule_face->n_points());
     139       12744 :         _weights_face(sid, elem_type_id)[side].create(qrule_face->n_points());
     140             : 
     141       37434 :         for (const auto qp : make_range(qrule_face->n_points()))
     142             :         {
     143       24690 :           _q_points_face(sid, elem_type_id)[side][qp] = qrule_face->qp(qp);
     144       24690 :           _weights_face(sid, elem_type_id)[side][qp] = qrule_face->w(qp);
     145             :         }
     146             :       }
     147             : 
     148        3344 :       _max_qps_per_elem = std::max(_max_qps_per_elem, n_qps[subdomain][elem_type]);
     149             :     }
     150             :   }
     151             : 
     152        2622 :   const auto num_elems = _mesh.nActiveLocalElem();
     153             : 
     154        2622 :   _n_subdomain_qps.create(num_subdomains);
     155        2622 :   _n_subdomain_qps_face.create(num_subdomains);
     156        2622 :   _n_subdomain_qps = 0;
     157        2622 :   _n_subdomain_qps_face = 0;
     158             : 
     159        2622 :   _n_qps.create(num_elems);
     160        2622 :   _n_qps_face.create(_mesh.getMaxSidesPerElem(), num_elems);
     161        2622 :   _n_qps_face = 0;
     162             : 
     163        2622 :   _qp_offset.create(num_elems);
     164        2622 :   _qp_offset_face.create(_mesh.getMaxSidesPerElem(), num_elems);
     165        2622 :   _qp_offset_face = libMesh::DofObject::invalid_id;
     166             : 
     167        2622 :   _elem_face_property_idx.create(_mesh.getMaxSidesPerElem(), num_elems);
     168        2622 :   _elem_face_property_idx = libMesh::DofObject::invalid_id;
     169             : 
     170        2622 :   _n_elem_face_properties.create(num_subdomains);
     171        2622 :   _n_elem_face_properties = 0;
     172             : 
     173      681222 :   for (auto elem : *_mesh.getActiveLocalElementRange())
     174             :   {
     175      678600 :     auto eid = kokkosMesh().getContiguousElementID(elem);
     176      678600 :     auto sid = kokkosMesh().getContiguousSubdomainID(elem->subdomain_id());
     177             : 
     178      678600 :     _n_qps[eid] = n_qps[elem->subdomain_id()][elem->type()];
     179      678600 :     _qp_offset[eid] = _n_subdomain_qps[sid];
     180      678600 :     _n_subdomain_qps[sid] += _n_qps[eid];
     181             : 
     182     3383492 :     for (const auto side : elem->side_index_range())
     183     2704892 :       _n_qps_face(side, eid) = n_qps_face[elem->subdomain_id()][elem->type()][side];
     184             :   }
     185             : 
     186        3476 :   for (auto boundary : _material_boundaries)
     187        6769 :     for (auto elem_id : _mesh.getBoundaryActiveSemiLocalElemIds(boundary))
     188             :     {
     189        5915 :       auto elem = _mesh.elemPtr(elem_id);
     190             : 
     191        5915 :       if (elem->processor_id() == _problem.processor_id())
     192             :       {
     193        5037 :         auto sid = kokkosMesh().getContiguousSubdomainID(elem->subdomain_id());
     194        5037 :         auto eid = kokkosMesh().getContiguousElementID(elem);
     195        5037 :         auto side = _mesh.sideWithBoundaryID(elem, boundary);
     196             : 
     197        5037 :         _qp_offset_face(side, eid) = _n_subdomain_qps_face[sid];
     198        5037 :         _n_subdomain_qps_face[sid] += _n_qps_face(side, eid);
     199             : 
     200        5037 :         _elem_face_property_idx(side, eid) = _n_elem_face_properties[sid];
     201        5037 :         ++_n_elem_face_properties[sid];
     202             :       }
     203         854 :     }
     204             : 
     205        2622 :   _q_points.copyToDeviceNested();
     206        2622 :   _q_points_face.copyToDeviceNested();
     207        2622 :   _weights.copyToDeviceNested();
     208        2622 :   _weights_face.copyToDeviceNested();
     209             : 
     210        2622 :   _n_qps.copyToDevice();
     211        2622 :   _n_qps_face.copyToDevice();
     212        2622 :   _n_subdomain_qps.copyToDevice();
     213        2622 :   _n_subdomain_qps_face.copyToDevice();
     214        2622 :   _qp_offset.copyToDevice();
     215        2622 :   _qp_offset_face.copyToDevice();
     216             : 
     217        2622 :   _elem_face_property_idx.copyToDevice();
     218        2622 :   _n_elem_face_properties.copyToDevice();
     219        2622 : }
     220             : 
     221             : void
     222        2622 : Assembly::initShape()
     223             : {
     224             :   // Generate the list of unique FE types
     225             : 
     226        2622 :   std::set<FEType> fe_types;
     227             : 
     228        5273 :   auto getFETypes = [&](::System & system)
     229             :   {
     230        9774 :     for (const auto var : make_range(system.n_vars()))
     231             :     {
     232        4501 :       const auto fe_type = system.variable_type(var);
     233        4501 :       const auto field_type = FEInterface::field_type(fe_type);
     234             : 
     235        4501 :       if (field_type == libMesh::TYPE_VECTOR)
     236             :       {
     237         172 :         if (fe_type.family != libMesh::LAGRANGE_VEC)
     238           0 :           mooseError("Kokkos currently only supports LAGRANGE_VEC for vector FE families.");
     239             :       }
     240             :       else
     241             :       {
     242        4329 :         if (fe_type.family != libMesh::LAGRANGE && fe_type.family != libMesh::L2_LAGRANGE &&
     243         338 :             fe_type.family != libMesh::MONOMIAL && fe_type.family != libMesh::SCALAR)
     244           0 :           mooseError("Kokkos currently only supports LAGRANGE, L2_LAGRNAGE, MONOMIAL, SCALAR for "
     245             :                      "scalar FE families.");
     246             :       }
     247             : 
     248        4501 :       fe_types.insert(fe_type);
     249             :     }
     250        5273 :   };
     251             : 
     252        5078 :   for (const auto nl : make_range(_problem.numNonlinearSystems()))
     253        2456 :     getFETypes(_problem.getNonlinearSystemBase(nl).system());
     254             : 
     255        2817 :   for (const auto linear : make_range(_problem.numLinearSystems()))
     256         195 :     getFETypes(_problem.getLinearSystem(linear).system());
     257             : 
     258        2622 :   getFETypes(_problem.getAuxiliarySystem().system());
     259             : 
     260        2622 :   _fe_type_map.clear();
     261             : 
     262        5653 :   for (auto & fet : fe_types)
     263        3031 :     _fe_type_map[fet] = _fe_type_map.size();
     264             : 
     265             :   // Cache reference shape data
     266             : 
     267        2622 :   const auto num_subdomains = kokkosMesh().getNumSubdomains();
     268        2622 :   const auto num_elem_types = kokkosMesh().getNumLocalElementTypes();
     269             : 
     270        2622 :   _phi.create(num_subdomains, num_elem_types, _fe_type_map.size());
     271        2622 :   _phi_face.create(num_subdomains, num_elem_types, _fe_type_map.size());
     272        2622 :   _grad_phi.create(num_subdomains, num_elem_types, _fe_type_map.size());
     273        2622 :   _grad_phi_face.create(num_subdomains, num_elem_types, _fe_type_map.size());
     274        2622 :   _vector_phi.create(num_subdomains, num_elem_types, _fe_type_map.size());
     275        2622 :   _vector_phi_face.create(num_subdomains, num_elem_types, _fe_type_map.size());
     276        2622 :   _vector_grad_phi.create(num_subdomains, num_elem_types, _fe_type_map.size());
     277        2622 :   _vector_grad_phi_face.create(num_subdomains, num_elem_types, _fe_type_map.size());
     278        2622 :   _is_vector_fe_type.create(_fe_type_map.size());
     279             : 
     280        2622 :   _map_phi.create(num_subdomains, num_elem_types);
     281        2622 :   _map_phi_face.create(num_subdomains, num_elem_types);
     282        2622 :   _map_psi_face.create(num_subdomains, num_elem_types);
     283        2622 :   _map_grad_phi.create(num_subdomains, num_elem_types);
     284        2622 :   _map_grad_phi_face.create(num_subdomains, num_elem_types);
     285        2622 :   _map_grad_psi_face.create(num_subdomains, num_elem_types);
     286             : 
     287        2622 :   _normal_dx_dxi.create(num_subdomains, num_elem_types);
     288        2622 :   _normal_dx_deta.create(num_subdomains, num_elem_types);
     289             : 
     290        2622 :   _n_dofs.create(num_elem_types, _fe_type_map.size());
     291        2622 :   _n_dofs = 0;
     292             : 
     293        5653 :   for (auto & [fe_type, fe_type_id] : _fe_type_map)
     294        3031 :     _is_vector_fe_type[fe_type_id] = FEInterface::field_type(fe_type) == libMesh::TYPE_VECTOR;
     295             : 
     296        5974 :   for (auto subdomain : _mesh.meshSubdomains())
     297             :   {
     298        3352 :     auto sid = kokkosMesh().getContiguousSubdomainID(subdomain);
     299             : 
     300        3352 :     auto & assembly = _problem.assembly(0, 0);
     301        3352 :     auto qrule = assembly.writeableQRule(_dimension, subdomain, {});
     302        3352 :     auto qrule_face = assembly.writeableQRuleFace(_dimension, subdomain, {});
     303             : 
     304        7317 :     for (auto & [fe_type, fe_type_id] : _fe_type_map)
     305             :     {
     306        3965 :       const bool is_vector_fe = FEInterface::field_type(fe_type) == libMesh::TYPE_VECTOR;
     307             : 
     308        3965 :       std::unique_ptr<FEBase> fe;
     309        3965 :       std::unique_ptr<FEBase> fe_face;
     310        3965 :       std::unique_ptr<FEVectorBase> vector_fe;
     311        3965 :       std::unique_ptr<FEVectorBase> vector_fe_face;
     312             : 
     313        3965 :       if (is_vector_fe)
     314             :       {
     315         150 :         vector_fe = FEVectorBase::build(_dimension, fe_type);
     316         150 :         vector_fe_face = FEVectorBase::build(_dimension, fe_type);
     317             : 
     318         150 :         vector_fe->attach_quadrature_rule(qrule);
     319         150 :         vector_fe_face->attach_quadrature_rule(qrule_face);
     320             :       }
     321             :       else
     322             :       {
     323        3815 :         fe = FEBase::build(_dimension, fe_type);
     324        3815 :         fe_face = FEBase::build(_dimension, fe_type);
     325             : 
     326        3815 :         fe->attach_quadrature_rule(qrule);
     327        3815 :         fe_face->attach_quadrature_rule(qrule_face);
     328             :       }
     329             : 
     330        7918 :       for (auto & [elem_type, elem_type_id] : kokkosMesh().getElementTypeMap())
     331             :       {
     332        3953 :         auto elem = &libMesh::ReferenceElem::get(elem_type);
     333             : 
     334        3953 :         if (is_vector_fe)
     335             :         {
     336         146 :           auto & phi = vector_fe->get_phi();
     337         146 :           auto & grad_phi = vector_fe->get_dphi();
     338             : 
     339         146 :           vector_fe->reinit(elem);
     340             : 
     341         146 :           _n_dofs(elem_type_id, fe_type_id) = phi.size();
     342             : 
     343         146 :           _vector_phi(sid, elem_type_id, fe_type_id).create(phi.size(), qrule->n_points());
     344         146 :           _vector_grad_phi(sid, elem_type_id, fe_type_id).create(phi.size(), qrule->n_points());
     345             : 
     346        1339 :           for (const auto i : index_range(phi))
     347        7408 :             for (const auto qp : make_range(qrule->n_points()))
     348             :             {
     349        6215 :               _vector_phi(sid, elem_type_id, fe_type_id)(i, qp) = phi[i][qp];
     350        6215 :               _vector_grad_phi(sid, elem_type_id, fe_type_id)(i, qp) = grad_phi[i][qp];
     351             :             }
     352             : 
     353         146 :           _vector_phi_face(sid, elem_type_id, fe_type_id).create(elem->n_sides());
     354         146 :           _vector_grad_phi_face(sid, elem_type_id, fe_type_id).create(elem->n_sides());
     355             : 
     356         672 :           for (const auto side : elem->side_index_range())
     357             :           {
     358         526 :             auto & phi = vector_fe_face->get_phi();
     359         526 :             auto & grad_phi = vector_fe_face->get_dphi();
     360             : 
     361         526 :             vector_fe_face->reinit(elem, side);
     362             : 
     363         526 :             _vector_phi_face(sid, elem_type_id, fe_type_id)(side).create(phi.size(),
     364             :                                                                          qrule_face->n_points());
     365         526 :             _vector_grad_phi_face(sid, elem_type_id, fe_type_id)(side).create(
     366             :                 phi.size(), qrule_face->n_points());
     367             : 
     368        5124 :             for (const auto i : index_range(phi))
     369       14844 :               for (const auto qp : make_range(qrule_face->n_points()))
     370             :               {
     371       10246 :                 _vector_phi_face(sid, elem_type_id, fe_type_id)(side)(i, qp) = phi[i][qp];
     372       10246 :                 _vector_grad_phi_face(sid, elem_type_id, fe_type_id)(side)(i, qp) = grad_phi[i][qp];
     373             :               }
     374             :           }
     375             :         }
     376             :         else
     377             :         {
     378        3807 :           auto & phi = fe->get_phi();
     379        3807 :           auto & grad_phi = fe->get_dphi();
     380             : 
     381        3807 :           fe->reinit(elem);
     382             : 
     383        3807 :           _n_dofs(elem_type_id, fe_type_id) = phi.size();
     384             : 
     385        3807 :           _phi(sid, elem_type_id, fe_type_id).create(phi.size(), qrule->n_points());
     386        3807 :           _grad_phi(sid, elem_type_id, fe_type_id).create(phi.size(), qrule->n_points());
     387             : 
     388       17447 :           for (const auto i : index_range(phi))
     389       74100 :             for (const auto qp : make_range(qrule->n_points()))
     390             :             {
     391       60460 :               _phi(sid, elem_type_id, fe_type_id)(i, qp) = phi[i][qp];
     392       60460 :               _grad_phi(sid, elem_type_id, fe_type_id)(i, qp) = grad_phi[i][qp];
     393             :             }
     394             : 
     395        3807 :           _phi_face(sid, elem_type_id, fe_type_id).create(elem->n_sides());
     396        3807 :           _grad_phi_face(sid, elem_type_id, fe_type_id).create(elem->n_sides());
     397             : 
     398       18539 :           for (const auto side : elem->side_index_range())
     399             :           {
     400       14732 :             auto & phi = fe_face->get_phi();
     401       14732 :             auto & grad_phi = fe_face->get_dphi();
     402             : 
     403       14732 :             fe_face->reinit(elem, side);
     404             : 
     405       14732 :             _phi_face(sid, elem_type_id, fe_type_id)(side).create(phi.size(),
     406             :                                                                   qrule_face->n_points());
     407       14732 :             _grad_phi_face(sid, elem_type_id, fe_type_id)(side).create(phi.size(),
     408             :                                                                        qrule_face->n_points());
     409             : 
     410       69526 :             for (const auto i : index_range(phi))
     411      173916 :               for (const auto qp : make_range(qrule_face->n_points()))
     412             :               {
     413      119122 :                 _phi_face(sid, elem_type_id, fe_type_id)(side)(i, qp) = phi[i][qp];
     414      119122 :                 _grad_phi_face(sid, elem_type_id, fe_type_id)(side)(i, qp) = grad_phi[i][qp];
     415             :               }
     416             :           }
     417             :         }
     418             :       }
     419        3965 :     }
     420             : 
     421        6696 :     for (auto & [elem_type, elem_type_id] : kokkosMesh().getElementTypeMap())
     422             :     {
     423        3344 :       auto elem = &libMesh::ReferenceElem::get(elem_type);
     424        3344 :       auto fe_type = FEType(elem->default_order(), LAGRANGE);
     425        3344 :       auto shape_deriv_ptr = libMesh::FEInterface::shape_deriv_function(fe_type, elem);
     426             : 
     427        3344 :       std::unique_ptr<FEBase> fe(FEBase::build(_dimension, fe_type));
     428        3344 :       std::unique_ptr<FEBase> fe_face(FEBase::build(_dimension, fe_type));
     429             : 
     430        3344 :       fe->attach_quadrature_rule(qrule);
     431        3344 :       fe_face->attach_quadrature_rule(qrule_face);
     432             : 
     433        3344 :       auto & phi = fe->get_phi();
     434        3344 :       auto & grad_phi = fe->get_dphi();
     435             : 
     436        3344 :       fe->reinit(elem);
     437             : 
     438        3344 :       _map_phi(sid, elem_type_id).create(phi.size(), qrule->n_points());
     439        3344 :       _map_grad_phi(sid, elem_type_id).create(phi.size(), qrule->n_points());
     440             : 
     441       16922 :       for (const auto i : index_range(phi))
     442       69731 :         for (const auto qp : make_range(qrule->n_points()))
     443             :         {
     444       56153 :           _map_phi(sid, elem_type_id)(i, qp) = phi[i][qp];
     445       56153 :           _map_grad_phi(sid, elem_type_id)(i, qp) = grad_phi[i][qp];
     446             :         }
     447             : 
     448        3344 :       _map_phi_face(sid, elem_type_id).create(elem->n_sides());
     449        3344 :       _map_grad_phi_face(sid, elem_type_id).create(elem->n_sides());
     450        3344 :       _map_psi_face(sid, elem_type_id).create(elem->n_sides());
     451        3344 :       _map_grad_psi_face(sid, elem_type_id).create(elem->n_sides());
     452             : 
     453        3344 :       _normal_dx_dxi(sid, elem_type_id).create(elem->n_sides());
     454        3344 :       _normal_dx_deta(sid, elem_type_id).create(elem->n_sides());
     455             : 
     456       16088 :       for (const auto side : elem->side_index_range())
     457             :       {
     458       12744 :         auto side_ptr = elem->build_side_ptr(side);
     459             : 
     460       12744 :         auto & phi = fe_face->get_phi();
     461       12744 :         auto & grad_phi = fe_face->get_dphi();
     462             : 
     463       12744 :         fe_face->reinit(elem, side);
     464             : 
     465       12744 :         _map_phi_face(sid, elem_type_id)(side).create(phi.size(), qrule_face->n_points());
     466       12744 :         _map_grad_phi_face(sid, elem_type_id)(side).create(phi.size(), qrule_face->n_points());
     467             : 
     468       66754 :         for (const auto i : index_range(phi))
     469      166504 :           for (const auto qp : make_range(qrule_face->n_points()))
     470             :           {
     471      112494 :             _map_phi_face(sid, elem_type_id)(side)(i, qp) = phi[i][qp];
     472      112494 :             _map_grad_phi_face(sid, elem_type_id)(side)(i, qp) = grad_phi[i][qp];
     473             :           }
     474             : 
     475       12744 :         auto & psi = fe_face->get_fe_map().get_psi();
     476       12744 :         auto & dpsidxi = fe_face->get_fe_map().get_dpsidxi();
     477       12744 :         auto & dpsideta = fe_face->get_fe_map().get_dpsideta();
     478             : 
     479       12744 :         _map_psi_face(sid, elem_type_id)(side).create(psi.size(), qrule_face->n_points());
     480       12744 :         _map_grad_psi_face(sid, elem_type_id)(side).create(psi.size(), qrule_face->n_points());
     481             : 
     482       38958 :         for (const auto i : index_range(psi))
     483       80296 :           for (const auto qp : make_range(qrule_face->n_points()))
     484             :           {
     485       54082 :             _map_psi_face(sid, elem_type_id)(side)(i, qp) = psi[i][qp];
     486       54082 :             if (elem->dim() > 1)
     487       53280 :               _map_grad_psi_face(sid, elem_type_id)(side)(i, qp)(0) = dpsidxi[i][qp];
     488       54082 :             if (elem->dim() > 2)
     489        8160 :               _map_grad_psi_face(sid, elem_type_id)(side)(i, qp)(1) = dpsideta[i][qp];
     490             :           }
     491             : 
     492       12744 :         _normal_dx_dxi(sid, elem_type_id)(side).create(phi.size(), qrule_face->n_points());
     493       12744 :         _normal_dx_deta(sid, elem_type_id)(side).create(phi.size(), qrule_face->n_points());
     494             : 
     495       37434 :         for (const auto qp : make_range(qrule_face->n_points()))
     496             :         {
     497       24690 :           Point reference_point;
     498             : 
     499       24690 :           if (_dimension == 1)
     500         802 :             reference_point = side ? Point(1) : Point(-1);
     501       23888 :           else if (_dimension == 2)
     502       66968 :             for (const auto i : index_range(psi))
     503       45120 :               reference_point.add_scaled(side_ptr->point(i), psi[i][qp]);
     504             : 
     505      137184 :           for (const auto i : index_range(phi))
     506             :           {
     507      112494 :             if (_dimension < 3)
     508       96174 :               _normal_dx_dxi(sid, elem_type_id)(side)(i, qp) =
     509       51922 :                   shape_deriv_ptr(fe_type, elem, i, 0, reference_point, false);
     510      112494 :             if (_dimension == 2)
     511       94512 :               _normal_dx_deta(sid, elem_type_id)(side)(i, qp) =
     512       51056 :                   shape_deriv_ptr(fe_type, elem, i, 1, reference_point, false);
     513             :           }
     514             :         }
     515       12744 :       }
     516        3344 :     }
     517             :   }
     518             : 
     519        2622 :   _phi.copyToDeviceNested();
     520        2622 :   _phi_face.copyToDeviceNested();
     521        2622 :   _grad_phi.copyToDeviceNested();
     522        2622 :   _grad_phi_face.copyToDeviceNested();
     523        2622 :   _vector_phi.copyToDeviceNested();
     524        2622 :   _vector_phi_face.copyToDeviceNested();
     525        2622 :   _vector_grad_phi.copyToDeviceNested();
     526        2622 :   _vector_grad_phi_face.copyToDeviceNested();
     527        2622 :   _is_vector_fe_type.copyToDevice();
     528             : 
     529        2622 :   _map_phi.copyToDeviceNested();
     530        2622 :   _map_phi_face.copyToDeviceNested();
     531        2622 :   _map_psi_face.copyToDeviceNested();
     532        2622 :   _map_grad_phi.copyToDeviceNested();
     533        2622 :   _map_grad_phi_face.copyToDeviceNested();
     534        2622 :   _map_grad_psi_face.copyToDeviceNested();
     535             : 
     536        2622 :   _normal_dx_dxi.copyToDeviceNested();
     537        2622 :   _normal_dx_deta.copyToDeviceNested();
     538             : 
     539        2622 :   _n_dofs.copyToDevice();
     540        2622 : }
     541             : 
     542             : void
     543        2622 : Assembly::cachePhysicalMap()
     544             : {
     545        2622 :   const auto num_subdomains = kokkosMesh().getNumSubdomains();
     546        2622 :   const auto num_elems = kokkosMesh().getNumLocalElements();
     547             : 
     548        2622 :   _jacobian.create(num_subdomains);
     549        2622 :   _jxw.create(num_subdomains);
     550        2622 :   _xyz.create(num_subdomains);
     551             : 
     552        5974 :   for (auto subdomain : _mesh.meshSubdomains())
     553             :   {
     554        3352 :     auto sid = kokkosMesh().getContiguousSubdomainID(subdomain);
     555             : 
     556        3352 :     _jacobian[sid].createDevice(_n_subdomain_qps[sid]);
     557        3352 :     _jxw[sid].createDevice(_n_subdomain_qps[sid]);
     558        3352 :     _xyz[sid].createDevice(_n_subdomain_qps[sid]);
     559             :   }
     560             : 
     561        2622 :   _jacobian.copyToDeviceNested();
     562        2622 :   _jxw.copyToDeviceNested();
     563        2622 :   _xyz.copyToDeviceNested();
     564             : 
     565        2622 :   ::Kokkos::RangePolicy<ExecSpace, ::Kokkos::IndexType<ThreadID>> policy(0, num_elems);
     566        2622 :   ::Kokkos::parallel_for(policy, *this);
     567        2622 :   ::Kokkos::fence();
     568        2622 : }
     569             : 
     570             : KOKKOS_FUNCTION void
     571      403307 : Assembly::operator()(const ThreadID tid) const
     572             : {
     573      403307 :   auto info = kokkosMesh().getElementInfo(tid);
     574      403307 :   auto offset = getQpOffset(info);
     575             : 
     576      403307 :   auto jacobian = &_jacobian[info.subdomain][offset];
     577      403307 :   auto jxw = &_jxw[info.subdomain][offset];
     578      403307 :   auto xyz = &_xyz[info.subdomain][offset];
     579             : 
     580     1069721 :   for (unsigned int qp = 0; qp < getNumQps(info); ++qp)
     581      666414 :     computePhysicalMap(info, qp, &jacobian[qp], &jxw[qp], &xyz[qp]);
     582      403307 : }
     583             : 
     584             : } // namespace Moose::Kokkos

Generated by: LCOV version 1.14