LCOV - code coverage report
Current view: top level - src/kokkos/materials - KokkosMaterialPropertyStorage.K (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #32971 (54bef8) with base c6cf66 Lines: 142 151 94.0 %
Date: 2026-05-29 20:35:17 Functions: 13 13 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 "KokkosMaterialPropertyStorage.h"
      11             : 
      12             : #include "FEProblemBase.h"
      13             : #include "MaterialBase.h"
      14             : 
      15             : namespace Moose::Kokkos
      16             : {
      17             : 
      18             : std::unordered_map<std::type_index, PropertyStore> MaterialPropertyStorage::_store_functions;
      19             : std::unordered_map<std::type_index, PropertyLoad> MaterialPropertyStorage::_load_functions;
      20             : 
      21      139779 : MaterialPropertyStorage::MaterialPropertyStorage(MaterialPropertyRegistry & registry,
      22      158688 :                                                  FEProblemBase & problem)
      23      533904 :   : ::MaterialPropertyStorage(registry, problem)
      24             : {
      25      139779 : }
      26             : 
      27             : MaterialPropertyStorage &
      28       10429 : MaterialPropertyStorage::cast(::MaterialPropertyStorage & storage)
      29             : {
      30       10429 :   return static_cast<MaterialPropertyStorage &>(storage);
      31             : }
      32             : 
      33             : MaterialPropertyBase &
      34        6196 : MaterialPropertyStorage::addKokkosProperty(const std::string & prop_name,
      35             :                                            const std::type_info & type,
      36             :                                            const unsigned int state,
      37             :                                            const ::MaterialBase * declarer,
      38             :                                            std::shared_ptr<MaterialPropertyBase> shell)
      39             : {
      40        6196 :   auto id = addProperty(prop_name, type, state, declarer);
      41             : 
      42        6196 :   if (state)
      43        2252 :     return addKokkosPropertyState(prop_name, state, shell);
      44             : 
      45        3944 :   auto & record = _kokkos_prop_records[prop_name];
      46             : 
      47        3944 :   if (record.id == libMesh::invalid_uint)
      48             :   {
      49        2755 :     record.type = MooseUtils::prettyCppType(libMesh::demangle(type.name()));
      50        2755 :     record.id = id;
      51             :   }
      52             : 
      53        3944 :   if (declarer)
      54        2990 :     record.declarers.insert(declarer);
      55             : 
      56        3944 :   if (!_kokkos_props[0].count(prop_name))
      57             :   {
      58        2755 :     _kokkos_props[0][prop_name] = shell;
      59        2755 :     _kokkos_props[0][prop_name]->init(record, {});
      60             :   }
      61             : 
      62        3944 :   return *_kokkos_props[0][prop_name];
      63             : }
      64             : 
      65             : MaterialPropertyBase &
      66        3239 : MaterialPropertyStorage::addKokkosPropertyState(const std::string & prop_name,
      67             :                                                 const unsigned int state,
      68             :                                                 std::shared_ptr<MaterialPropertyBase> shell)
      69             : {
      70        3239 :   auto & record = _kokkos_prop_records[prop_name];
      71             : 
      72        3239 :   if (!_kokkos_props[state].count(prop_name))
      73             :   {
      74         902 :     _kokkos_props[state][prop_name] = shell;
      75         902 :     _kokkos_props[state][prop_name]->init(record, {});
      76             :   }
      77             : 
      78        3239 :   return *_kokkos_props[state][prop_name];
      79             : }
      80             : 
      81             : MaterialPropertyBase &
      82        2996 : MaterialPropertyStorage::declareKokkosProperty(const std::string & prop_name,
      83             :                                                const std::type_info & type,
      84             :                                                const ::MaterialBase * declarer,
      85             :                                                const std::vector<unsigned int> & dims,
      86             :                                                const bool bnd,
      87             :                                                const bool on_demand,
      88             :                                                const PropertyConstantOption constant_option,
      89             :                                                std::shared_ptr<MaterialPropertyBase> shell)
      90             : {
      91        2996 :   auto & record = _kokkos_prop_records[prop_name];
      92        2996 :   auto & blocks = declarer->boundaryRestricted() ? declarer->meshBlockIDs() : declarer->blockIDs();
      93             : 
      94        3310 :   for (const auto & [_, record_dims] : record.dims)
      95         316 :     if (record_dims.size() != dims.size())
      96             :     {
      97           2 :       std::stringstream ss;
      98             : 
      99           2 :       ss << "The declared " << dims.size() << "D Kokkos material property '" << prop_name << "'";
     100           2 :       ss << " was already declared as a " << record_dims.size() << "D property.";
     101             : 
     102           2 :       mooseError(ss.str());
     103           0 :     }
     104             : 
     105        3286 :   for (const auto other : record.declarers)
     106         296 :     if (declarer->boundaryRestricted() && other->boundaryRestricted())
     107             :     {
     108           4 :       if (auto it = record.dims.begin(); it->second != dims)
     109             :       {
     110           2 :         std::stringstream ss;
     111             : 
     112           2 :         ss << "The declared boundary-restricted Kokkos material property '" << prop_name << "'";
     113           8 :         ss << " with dimensions (" << Moose::stringify(dims) << ")";
     114           2 :         ss << " was already declared as a property";
     115           8 :         ss << " with dimensions (" << Moose::stringify(it->second) << ").\n";
     116           0 :         ss << "Currently, boundary-restricted Kokkos material properties should have the same "
     117           2 :               "dimension size across the entire domain.";
     118             : 
     119           2 :         mooseError(ss.str());
     120           0 :       }
     121             : 
     122           2 :       if (auto it = record.constant_option.begin(); it->second != constant_option)
     123             :       {
     124           0 :         static const std::unordered_map<PropertyConstantOption, std::string> option = {
     125           0 :             {PropertyConstantOption::NONE, "NONE"},
     126           0 :             {PropertyConstantOption::ELEMENT, "ELEMENT"},
     127          12 :             {PropertyConstantOption::SUBDOMAIN, "SUBDOMAIN"}};
     128             : 
     129           2 :         std::stringstream ss;
     130           2 :         std::string adding = option.at(constant_option);
     131           2 :         std::string existing = option.at(it->second);
     132             : 
     133           2 :         ss << "The declared boundary-restricted Kokkos material property '" << prop_name << "'";
     134           2 :         ss << " with constant_on = " << adding;
     135           2 :         ss << " was already declared as a property";
     136           2 :         ss << " with constant_on = " << existing << ".\n";
     137           0 :         ss << "Currently, boundary-restricted Kokkos material properties should have the same "
     138           2 :               "constant_on option across the entire domain.";
     139             : 
     140           2 :         mooseError(ss.str());
     141           0 :       }
     142             :     }
     143             : 
     144        7318 :   for (const auto block : blocks)
     145             :   {
     146        4328 :     record.dims[block] = dims;
     147        4328 :     record.constant_option[block] = constant_option;
     148             :   }
     149             : 
     150        2990 :   if (record.declarers.size())
     151             :   {
     152         241 :     if (record.on_demand != on_demand)
     153           0 :       mooseError(
     154             :           "The Kokkos material property '",
     155             :           prop_name,
     156             :           "' is being declared by multiple materials, and some of them are declaring it as an "
     157             :           "on-demand property while others are not.");
     158             :   }
     159             :   else
     160             :   {
     161        2749 :     record.bnd = bnd;
     162        2749 :     record.on_demand = on_demand;
     163             :   }
     164             : 
     165        2990 :   return addKokkosProperty(prop_name, type, 0, declarer, shell);
     166           2 : }
     167             : 
     168             : MaterialPropertyBase &
     169         971 : MaterialPropertyStorage::getKokkosProperty(std::string prop_name, unsigned int state)
     170             : {
     171         971 :   return *_kokkos_props[state][prop_name];
     172             : }
     173             : 
     174             : void
     175        6795 : MaterialPropertyStorage::allocateKokkosProperties()
     176             : {
     177        6795 :   auto & mesh = *_problem.mesh().getKokkosMesh();
     178        6795 :   auto & assembly = _problem.kokkosAssembly();
     179             : 
     180       14492 :   for (unsigned int state = 0; state < numStates(); ++state)
     181       11338 :     for (auto & [name, prop] : _kokkos_props[state])
     182             :     {
     183        3641 :       auto & record = _kokkos_prop_records[name];
     184             : 
     185        3641 :       if (!record.on_demand || _problem.isMatPropRequested(name))
     186        7424 :         for (auto * const declarer : record.declarers)
     187             :         {
     188        1692 :           auto & blocks =
     189        2142 :               declarer->boundaryRestricted() ? declarer->meshBlockIDs() : declarer->blockIDs();
     190             : 
     191        3834 :           prop->allocate(mesh, assembly, blocks, record.bnd, {});
     192             :         }
     193             :     }
     194        6795 : }
     195             : 
     196             : bool
     197          17 : MaterialPropertyStorage::haveKokkosProperty(std::string prop_name, unsigned int state)
     198             : {
     199          17 :   return _kokkos_props[state].count(prop_name);
     200             : }
     201             : 
     202             : void
     203        2252 : MaterialPropertyStorage::registerLoadStore(std::type_index type,
     204             :                                            PropertyStore store,
     205             :                                            PropertyLoad load)
     206             : {
     207        2252 :   _store_functions[type] = store;
     208        2252 :   _load_functions[type] = load;
     209        2252 : }
     210             : 
     211             : void
     212        1773 : MaterialPropertyStorage::shift()
     213             : {
     214        4581 :   for (unsigned int state = maxState(); state != 0; --state)
     215        5616 :     for (auto & [name, prop] : _kokkos_props[state])
     216        2808 :       prop->swap(*_kokkos_props[state - 1][name], {});
     217        1773 : }
     218             : 
     219             : void
     220        2343 : MaterialPropertyStorage::copy()
     221             : {
     222        3905 :   for (unsigned int state : statefulIndexRange())
     223        3124 :     for (auto & [name, prop] : _kokkos_props[state])
     224        1562 :       if (!isRestoredProperty(name))
     225        1419 :         prop->copy(*_kokkos_props[0][name], {});
     226        2343 : }
     227             : 
     228             : } // namespace Moose::Kokkos
     229             : 
     230             : void
     231      109134 : dataStore(std::ostream & stream, Moose::Kokkos::MaterialPropertyStorage & storage, void * context)
     232             : {
     233      109134 :   auto & base = static_cast<MaterialPropertyStorage &>(storage);
     234             : 
     235      109134 :   dataStore(stream, base, context);
     236             : 
     237      109134 :   auto & props = storage._kokkos_props;
     238      109134 :   auto & records = storage._kokkos_prop_records;
     239             : 
     240      109134 :   unsigned int num_stateful_properties = 0;
     241             : 
     242      109554 :   for (auto & prop : props[0])
     243             :   {
     244         420 :     auto name = prop.first;
     245         420 :     auto id = records[name].id;
     246             : 
     247         420 :     if (storage.getPropRecord(id).stateful())
     248         235 :       num_stateful_properties++;
     249         420 :   }
     250             : 
     251      109134 :   dataStore(stream, num_stateful_properties, nullptr);
     252             : 
     253      109554 :   for (auto & prop : props[0])
     254             :   {
     255         420 :     auto name = prop.first;
     256         420 :     auto id = records[name].id;
     257             : 
     258         420 :     if (storage.getPropRecord(id).stateful())
     259             :     {
     260         235 :       dataStore(stream, name, nullptr);
     261             : 
     262         235 :       unsigned int num_states = storage.getPropRecord(id).state + 1;
     263         235 :       dataStore(stream, num_states, nullptr);
     264             : 
     265             :       // Store data in a temporary stream to allow skipping loading
     266         235 :       std::stringstream ss;
     267             : 
     268         765 :       for (unsigned int state = 0; state < num_states; ++state)
     269             :       {
     270         530 :         auto it = storage._store_functions.find(props[state][name]->propertyType());
     271             :         mooseAssert(it != storage._store_functions.end(),
     272             :                     "Store function was not properly registered.");
     273             : 
     274         530 :         it->second(ss, props[state][name].get());
     275             :       }
     276             : 
     277             :       // Write the temporary stream to the output stream
     278         235 :       dataStore(stream, ss, nullptr);
     279         235 :     }
     280         420 :   }
     281      109134 : }
     282             : 
     283             : void
     284       33264 : dataLoad(std::istream & stream, Moose::Kokkos::MaterialPropertyStorage & storage, void * context)
     285             : {
     286       33264 :   auto & base = static_cast<MaterialPropertyStorage &>(storage);
     287             : 
     288             :   // All exceptions are expected to be handled here
     289       33264 :   dataLoad(stream, base, context);
     290             : 
     291       33258 :   auto & props = storage._kokkos_props;
     292       33258 :   auto & records = storage._kokkos_prop_records;
     293             : 
     294             :   unsigned int num_stateful_properties;
     295       33258 :   dataLoad(stream, num_stateful_properties, nullptr);
     296             : 
     297       33410 :   for (unsigned int prop = 0; prop < num_stateful_properties; ++prop)
     298             :   {
     299         152 :     std::string name;
     300         152 :     dataLoad(stream, name, nullptr);
     301             : 
     302             :     unsigned int num_states;
     303         152 :     dataLoad(stream, num_states, nullptr);
     304             : 
     305         152 :     std::stringstream ss;
     306         152 :     dataLoad(stream, ss, nullptr);
     307             : 
     308         152 :     if (records.count(name) && storage.getPropRecord(records[name].id).stateful())
     309         369 :       for (unsigned int state = 0; state < num_states; ++state)
     310             :       {
     311         256 :         auto it = storage._load_functions.find(props[state][name]->propertyType());
     312             :         mooseAssert(it != storage._load_functions.end(),
     313             :                     "Load function was not properly registered.");
     314             : 
     315         256 :         it->second(ss, props[state][name].get());
     316             :       }
     317         152 :   }
     318       33258 : }

Generated by: LCOV version 1.14