LCOV - code coverage report
Current view: top level - include/materials - MaterialData.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #32971 (54bef8) with base c6cf66 Lines: 76 81 93.8 %
Date: 2026-05-29 20:35:17 Functions: 158 223 70.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* This file is part of the MOOSE framework
       2             : //* https://mooseframework.inl.gov
       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             : #ifdef MOOSE_KOKKOS_ENABLED
      13             : #include "KokkosMaterialProperty.h"
      14             : #endif
      15             : 
      16             : #include "MaterialProperty.h"
      17             : #include "Moose.h"
      18             : #include "MooseUtils.h"
      19             : 
      20             : // libMesh
      21             : #include "libmesh/elem.h"
      22             : 
      23             : #include <vector>
      24             : #include <memory>
      25             : #include <typeinfo>
      26             : 
      27             : class MaterialPropertyStorage;
      28             : class MooseObject;
      29             : class Material;
      30             : class XFEM;
      31             : class MaterialBase;
      32             : 
      33             : /**
      34             :  * Proxy for accessing MaterialPropertyStorage.
      35             :  * MaterialData stores the values associated with a particular material object
      36             :  */
      37             : class MaterialData
      38             : {
      39             : public:
      40             :   MaterialData(MaterialPropertyStorage & storage, const THREAD_ID tid);
      41             : 
      42             :   /// The max time state supported (2 = older)
      43             :   static constexpr unsigned int max_state = 2;
      44             : 
      45             :   /**
      46             :    * Resize the data to hold properties for n_qpoints quadrature points.
      47             :    */
      48             :   void resize(unsigned int n_qpoints);
      49             : 
      50             :   /**
      51             :    * Returns the number of quadrature points the material properties
      52             :    * support/hold.
      53             :    */
      54    51136971 :   unsigned int nQPoints() const { return _n_qpoints; }
      55             : 
      56             :   /// copy material properties from one element to another
      57             :   void copy(const Elem & elem_to, const Elem & elem_from, unsigned int side);
      58             : 
      59             :   /// material properties for given element (and possible side)
      60             :   void swap(const Elem & elem, unsigned int side = 0);
      61             : 
      62             :   /**
      63             :    * Reinit material properties for given element (and possible side)
      64             :    * @param mats The material objects for which to compute properties
      65             :    * @param execute_stateful Whether to execute material objects that have stateful properties. This
      66             :    * should be \p false when for example executing material objects for mortar contexts in which
      67             :    * stateful properties don't make sense
      68             :    */
      69             :   template <typename MatContainer>
      70             :   void reinit(const MatContainer & mats);
      71             : 
      72             :   /// Calls the reset method of Materials to ensure that they are in a proper state.
      73             :   void reset(const std::vector<std::shared_ptr<MaterialBase>> & mats);
      74             : 
      75             :   /// material properties for given element (and possible side)
      76             :   void swapBack(const Elem & elem, unsigned int side = 0);
      77             : 
      78             :   /**
      79             :    * @returns The properties for the state \p state (defaults to zero).
      80             :    *
      81             :    * This should NEVER be used to modify the size of these objects.
      82             :    */
      83             :   ///{
      84             :   const MaterialProperties & props(const unsigned int state = 0) const;
      85             :   MaterialProperties & props(const unsigned int state = 0);
      86             :   ///@}
      87             : 
      88             :   template <typename T, bool is_ad>
      89             :   bool haveGenericProperty(const std::string & prop_name) const;
      90             : 
      91             :   /// Returns true if the regular material property exists - defined by any material.
      92             :   template <typename T>
      93       46352 :   bool haveProperty(const std::string & prop_name) const
      94             :   {
      95       46352 :     return haveGenericProperty<T, false>(prop_name);
      96             :   }
      97             : 
      98             :   /// Returns true if the AD material property exists - defined by any material.
      99             :   template <typename T>
     100       24735 :   bool haveADProperty(const std::string & prop_name) const
     101             :   {
     102       24735 :     return haveGenericProperty<T, true>(prop_name);
     103             :   }
     104             : 
     105             : #ifdef MOOSE_KOKKOS_SCOPE
     106             :   /**
     107             :    * Get whether a Kokkos material property exists
     108             :    * @tparam T The property data type
     109             :    * @tparam dimension The property dimension
     110             :    * @param prop_name The property name
     111             :    * @returns Whether the Kokkos material property exists
     112             :    */
     113             :   template <typename T, unsigned int dimension>
     114             :   bool haveKokkosProperty(const std::string & prop_name) const;
     115             : #endif
     116             : 
     117             :   /**
     118             :    * Retrieves a material property
     119             :    * @tparam T The type of the property
     120             :    * @tparam is_ad Whether or not the property is AD
     121             :    * @param prop_name The name of the property
     122             :    * @param state The time state (0 = current, 1 = old, etc; defaults to 0)
     123             :    * @param requestor The MooseObject requesting the property
     124             :    * @return The property for the supplied type and name
     125             :    */
     126             :   template <typename T, bool is_ad = false>
     127       61436 :   GenericMaterialProperty<T, is_ad> & getProperty(const std::string & prop_name,
     128             :                                                   const unsigned int state,
     129             :                                                   const MooseObject & requestor)
     130             :   {
     131       61436 :     return getPropertyHelper<T, is_ad, false>(prop_name, state, requestor);
     132             :   }
     133             :   /**
     134             :    * Declares a material property
     135             :    * @tparam T The type of the property
     136             :    * @tparam is_ad Whether or not the property is AD
     137             :    * @param prop_name The name of the property
     138             :    * @param requestor The MooseObject declaring the property
     139             :    * @return The property for the supplied type and name
     140             :    */
     141             :   template <typename T, bool is_ad>
     142       60396 :   GenericMaterialProperty<T, is_ad> & declareProperty(const std::string & prop_name,
     143             :                                                       const MooseObject & requestor)
     144             :   {
     145       60396 :     return getPropertyHelper<T, is_ad, true>(prop_name, 0, requestor);
     146             :   }
     147             : 
     148             : #ifdef MOOSE_KOKKOS_SCOPE
     149             :   /**
     150             :    * Get a Kokkos material property
     151             :    * @tparam T The property data type
     152             :    * @tparam dimension The property dimension
     153             :    * @tparam state The property state
     154             :    * @param prop_name The property name
     155             :    * @return The Kokkos material property
     156             :    */
     157             :   template <typename T, unsigned int dimension, unsigned int state>
     158             :   Moose::Kokkos::MaterialProperty<T, dimension> getKokkosProperty(const std::string & prop_name);
     159             : 
     160             :   /**
     161             :    * Declare a Kokkos material property
     162             :    * @tparam T The property data type
     163             :    * @tparam dimension The property dimension
     164             :    * @param prop_name The property name
     165             :    * @param dims The vector containing the size of each dimension
     166             :    * @param declarer The Kokkos material declaring the property
     167             :    * @param bnd Whether the property is a face property
     168             :    * @param on_demand Whether the property is an on-demand property
     169             :    * @param constant_option Whether the property is constant on element or subdomain
     170             :    * @return The Kokkos material property
     171             :    */
     172             :   template <typename T, unsigned int dimension>
     173             :   Moose::Kokkos::MaterialProperty<T, dimension>
     174             :   declareKokkosProperty(const std::string & prop_name,
     175             :                         const std::vector<unsigned int> & dims,
     176             :                         const MaterialBase * declarer,
     177             :                         const bool bnd,
     178             :                         const bool on_demand,
     179             :                         const Moose::Kokkos::PropertyConstantOption constant_option);
     180             : #endif
     181             : 
     182             :   /**
     183             :    * Returns true if the stateful material is in a swapped state.
     184             :    */
     185   378257333 :   bool isSwapped() const { return _swapped; }
     186             : 
     187             :   /**
     188             :    * Provide read-only access to the underlying MaterialPropertyStorage object.
     189             :    */
     190     1050730 :   const MaterialPropertyStorage & getMaterialPropertyStorage() const { return _storage; }
     191             : 
     192             :   /**
     193             :    * Key that provides access to only the XFEM class.
     194             :    */
     195             :   class XFEMKey
     196             :   {
     197             :     friend class XFEM;
     198             :     XFEMKey() {}
     199             :     XFEMKey(const XFEM &) {}
     200             :   };
     201             : 
     202             :   /**
     203             :    * Provide write-only access to the underlying MaterialPropertyStorage object JUST FOR XFEM.
     204             :    *
     205             :    * This should be removed. To be clear - you should not ever expect to have write access
     206             :    * to this data. It just turned out that XFEM got away with it when we were storing things
     207             :    * as pointers instead of smart pointers...
     208             :    *
     209             :    * These dirty reasons are why this method is named so egregiously.
     210             :    */
     211             :   MaterialPropertyStorage & getMaterialPropertyStorageForXFEM(const XFEMKey) { return _storage; }
     212             : 
     213             :   /**
     214             :    * @return Whether or not a property exists with the name \p name
     215             :    */
     216             :   bool hasProperty(const std::string & prop_name) const;
     217             : 
     218             :   /**
     219             :    * Wrapper for MaterialStorage::getPropertyId. Allows classes with a MaterialData object
     220             :    * (i.e. MaterialPropertyInterface) to access material property IDs.
     221             :    * @param prop_name The name of the material property
     222             :    *
     223             :    * @return An unsigned int corresponding to the property ID of the passed in prop_name
     224             :    */
     225             :   unsigned int getPropertyId(const std::string & prop_name) const;
     226             : 
     227             :   /**
     228             :    * Set _resize_only_if_smaller to perform a non-destructive resize. Setting this
     229             :    * flag to true means that resize(n) will not decrease the size of _props
     230             :    * if n is smaller than the size of the material data object.
     231             :    */
     232             :   void onlyResizeIfSmaller(bool flag) { _resize_only_if_smaller = flag; };
     233             : 
     234             :   /**
     235             :    * Check value of _resize_only_if_smaller
     236             :    */
     237      233882 :   bool isOnlyResizeIfSmaller() const { return _resize_only_if_smaller; };
     238             : 
     239             :   /**
     240             :    * Remove the property storage and element pointer from MaterialPropertyStorage data structures
     241             :    * Use this when elements are deleted so we don't end up with invalid elem pointers (for e.g.
     242             :    * stateful properties) hanging around in our data structures
     243             :    */
     244             :   void eraseProperty(const Elem * elem);
     245             : 
     246             : private:
     247             :   /// Reference to the MaterialStorage class
     248             :   MaterialPropertyStorage & _storage;
     249             : 
     250             :   /// The thread id
     251             :   const THREAD_ID _tid;
     252             : 
     253             :   /// Number of quadrature points
     254             :   unsigned int _n_qpoints;
     255             : 
     256             :   /// The underlying property data
     257             :   std::array<MaterialProperties, max_state + 1> _props;
     258             : 
     259             :   unsigned int addPropertyHelper(const std::string & prop_name,
     260             :                                  const std::type_info & type,
     261             :                                  const unsigned int state,
     262             :                                  const MaterialBase * const declarer);
     263             : 
     264             :   template <typename T, bool is_ad, bool declare>
     265             :   GenericMaterialProperty<T, is_ad> & getPropertyHelper(const std::string & prop_name,
     266             :                                                         const unsigned int state,
     267             :                                                         const MooseObject & requestor);
     268             : 
     269             : #ifdef MOOSE_KOKKOS_ENABLED
     270             :   /**
     271             :    * Helper function for adding a Kokkos material property
     272             :    * @param prop_name The property name
     273             :    * @param type The property data type
     274             :    * @param state The property state
     275             :    * @param shell The managed pointer containing the instance of the property
     276             :    * @return The Kokkos material property
     277             :    */
     278             :   Moose::Kokkos::MaterialPropertyBase &
     279             :   addKokkosPropertyHelper(const std::string & prop_name,
     280             :                           const std::type_info & type,
     281             :                           const unsigned int state,
     282             :                           std::shared_ptr<Moose::Kokkos::MaterialPropertyBase> shell);
     283             : 
     284             :   /**
     285             :    * Helper function for declaring a Kokkos material property
     286             :    * @param prop_name The property name
     287             :    * @param type The property data type
     288             :    * @param declarer The Kokkos material declaring the property
     289             :    * @param dims The vector containing the size of each dimension
     290             :    * @param bnd Whether the property is a face property
     291             :    * @param on_demand Whether the property is an on-demand property
     292             :    * @param constant_option Whether the property is constant on element or subdomain
     293             :    * @param shell The managed pointer containing the instance of the property
     294             :    * @return The Kokkos material property
     295             :    */
     296             :   Moose::Kokkos::MaterialPropertyBase &
     297             :   declareKokkosPropertyHelper(const std::string & prop_name,
     298             :                               const std::type_info & type,
     299             :                               const MaterialBase * declarer,
     300             :                               const std::vector<unsigned int> & dims,
     301             :                               const bool bnd,
     302             :                               const bool on_demand,
     303             :                               const Moose::Kokkos::PropertyConstantOption constant_option,
     304             :                               std::shared_ptr<Moose::Kokkos::MaterialPropertyBase> shell);
     305             : 
     306             :   /**
     307             :    * Helper function for getting a Kokkos material property
     308             :    * @param prop_name The property name
     309             :    * @param state The property state
     310             :    * @param shell The managed pointer containing the instance of the property
     311             :    * @return The Kokkos material property
     312             :    */
     313             :   Moose::Kokkos::MaterialPropertyBase & getKokkosPropertyHelper(
     314             :       const std::string & prop_name,
     315             :       const unsigned int state = 0,
     316             :       std::shared_ptr<Moose::Kokkos::MaterialPropertyBase> shell = nullptr) const;
     317             : 
     318             :   /**
     319             :    * Helper function for checking whether a Kokkos material property exists
     320             :    * @param prop_name The property name
     321             :    * @return Whether the Kokkos material property exists
     322             :    */
     323             :   bool haveKokkosPropertyHelper(const std::string & prop_name) const;
     324             :   /**
     325             :    * Helper function to register load/store functions of a Kokkos material property to the Kokkos
     326             :    * material property storage
     327             :    * @param type The property type index
     328             :    * @param store The store function pointer
     329             :    * @param load The load function pointer
     330             :    */
     331             :   void kokkosRegisterLoadStoreHelper(std::type_index type,
     332             :                                      Moose::Kokkos::PropertyStore store,
     333             :                                      Moose::Kokkos::PropertyLoad load);
     334             : #endif
     335             : 
     336             :   static void mooseErrorHelper(const MooseObject & object, const std::string_view & error);
     337             : 
     338             :   /**
     339             :    * Helper for casting \p requestor to a MaterialBase in addPropertyHelper() (templated)
     340             :    */
     341             :   const MaterialBase & castRequestorToDeclarer(const MooseObject & requestor) const;
     342             : 
     343             :   /// Status of storage swapping (calling swap sets this to true; swapBack sets it to false)
     344             :   bool _swapped;
     345             : 
     346             :   /// Use non-destructive resize of material data (calling resize() will not reduce size).
     347             :   /// Default is false (normal resize behaviour)
     348             :   bool _resize_only_if_smaller;
     349             : 
     350             :   /// maximum state id requested for a property
     351             :   unsigned int getMaxStateRequested(const unsigned int prop_id) const;
     352             : };
     353             : 
     354             : inline const MaterialProperties &
     355      136114 : MaterialData::props(const unsigned int state) const
     356             : {
     357             :   mooseAssert(_props.size() > state, "Invalid state");
     358      136114 :   return _props[state];
     359             : }
     360             : 
     361             : inline MaterialProperties &
     362    27187257 : MaterialData::props(const unsigned int state)
     363             : {
     364             :   mooseAssert(_props.size() > state, "Invalid state");
     365    27187257 :   return _props[state];
     366             : }
     367             : 
     368             : template <typename T, bool is_ad>
     369             : inline bool
     370       76169 : MaterialData::haveGenericProperty(const std::string & prop_name) const
     371             : {
     372       76169 :   if (!hasProperty(prop_name))
     373        7965 :     return false;
     374             : 
     375       68204 :   const auto prop_id = getPropertyId(prop_name);
     376             :   // the property id exists, but the property was not created in this instance of the material type
     377       68204 :   if (prop_id >= props(0).size())
     378         294 :     return false;
     379             : 
     380       67910 :   const PropertyValue * const base_prop = props(0).queryValue(prop_id);
     381       67910 :   return dynamic_cast<const GenericMaterialProperty<T, is_ad> *>(base_prop) != nullptr;
     382             : }
     383             : 
     384             : template <typename T, bool is_ad, bool declare>
     385             : GenericMaterialProperty<T, is_ad> &
     386      121832 : MaterialData::getPropertyHelper(const std::string & prop_name,
     387             :                                 const unsigned int state,
     388             :                                 const MooseObject & requestor)
     389             : {
     390             :   if constexpr (is_ad)
     391             :     mooseAssert(state == 0, "Cannot request/declare AD properties for states other than zero");
     392             :   if constexpr (declare)
     393             :     mooseAssert(state == 0, "Cannot declare properties for states other than zero");
     394             : 
     395             :   // Register/get the ID of the property
     396      182228 :   const auto prop_id = addPropertyHelper(
     397       60396 :       prop_name, typeid(T), state, declare ? &castRequestorToDeclarer(requestor) : nullptr);
     398      121832 :   const auto size = prop_id + 1;
     399             : 
     400             :   // Initialize the states that we need
     401      251580 :   for (const auto state_i : make_range(getMaxStateRequested(prop_id) + 1))
     402             :   {
     403      129748 :     auto & entry = props(state_i);
     404      129748 :     if (entry.size() < size)
     405       59594 :       entry.resize(size, {});
     406             :     // if we are not declaring the property we initialize only what we need (the requested state)
     407      129748 :     if (!entry.hasValue(prop_id) && (declare || state_i == state))
     408             :     {
     409       59535 :       if (state_i == 0)
     410      111724 :         entry.setPointer(
     411      111724 :             prop_id, std::move(std::make_unique<GenericMaterialProperty<T, is_ad>>(prop_id)), {});
     412             :       else
     413        3673 :         entry.setPointer(prop_id, std::move(std::make_unique<MaterialProperty<T>>(prop_id)), {});
     414             :     }
     415             :   }
     416             : 
     417             :   // Should be available now
     418      121832 :   auto & base_prop = props(state)[prop_id];
     419             : 
     420             :   // In the event that this property was already declared/requested, make sure
     421             :   // that the types are consistent
     422      121832 :   auto prop = dynamic_cast<GenericMaterialProperty<T, is_ad> *>(&base_prop);
     423      121832 :   if (!prop)
     424             :   {
     425          12 :     constexpr std::string_view action = declare ? "declared" : "requested";
     426          12 :     constexpr auto is_ad_to_str = [](const bool is_ad_bool)
     427          12 :     { return std::string_view(is_ad_bool ? "AD" : "non-AD"); };
     428          12 :     constexpr std::string_view ad_type = is_ad_to_str(is_ad);
     429             : 
     430          12 :     std::stringstream error;
     431             :     error << "The " << action << " " << ad_type << " "
     432             :           << "material property '" + prop_name + "' of type '" << MooseUtils::prettyCppType<T>()
     433          24 :           << "'\nis already retrieved or declared as a " << is_ad_to_str(base_prop.isAD())
     434          12 :           << " property of type '" << base_prop.type() << "'.";
     435          12 :     mooseErrorHelper(requestor, error.str());
     436           0 :   }
     437             : 
     438      121820 :   return *prop;
     439             : }
     440             : 
     441             : template <typename MatContainer>
     442             : void
     443    17440979 : MaterialData::reinit(const MatContainer & mats)
     444             : {
     445    40317255 :   for (const auto & mat : mats)
     446    22876332 :     mat->computeProperties();
     447    17440923 : }
     448             : 
     449             : #ifdef MOOSE_KOKKOS_SCOPE
     450             : template <typename T, unsigned int dimension>
     451             : bool
     452          17 : MaterialData::haveKokkosProperty(const std::string & prop_name) const
     453             : {
     454          17 :   if (!haveKokkosPropertyHelper(prop_name))
     455           0 :     return false;
     456             : 
     457          17 :   auto & prop = getKokkosPropertyHelper(prop_name);
     458          17 :   return dynamic_cast<Moose::Kokkos::MaterialProperty<T, dimension> *>(&prop) != nullptr;
     459             : }
     460             : 
     461             : template <typename T, unsigned int dimension, unsigned int state>
     462             : Moose::Kokkos::MaterialProperty<T, dimension>
     463        1941 : MaterialData::getKokkosProperty(const std::string & prop_name)
     464             : {
     465             :   // Reserve the storages for the property up to the requested state
     466             :   // If the storages were already reserved, it will do nothing
     467        5147 :   for (unsigned int s = 0; s <= state; ++s)
     468             :   {
     469        3206 :     auto shell = std::make_shared<Moose::Kokkos::MaterialProperty<T, dimension>>();
     470             : 
     471        3206 :     addKokkosPropertyHelper(prop_name, typeid(T), state, shell);
     472             : 
     473             :     // Only instantiate load and store functions for stateful properties to avoid requiring users
     474             :     // to provide custom dataLoad and dataStore for non-trivially-copyable types that are never
     475             :     // used as stateful properties
     476             :     if constexpr (state > 0)
     477        2252 :       kokkosRegisterLoadStoreHelper(shell->propertyType(),
     478             :                                     Moose::Kokkos::propertyStore<T, dimension>,
     479             :                                     Moose::Kokkos::propertyLoad<T, dimension>);
     480             :   }
     481             : 
     482        1941 :   auto & prop_base = getKokkosPropertyHelper(prop_name, state, nullptr);
     483        1941 :   auto prop_cast = dynamic_cast<Moose::Kokkos::MaterialProperty<T, dimension> *>(&prop_base);
     484             : 
     485        1941 :   if (!prop_cast)
     486           0 :     mooseError("The requested ",
     487             :                dimension,
     488             :                "D Kokkos material property '",
     489             :                prop_name,
     490             :                "' of type '",
     491             :                MooseUtils::prettyCppType<T>(),
     492             :                "' was already declared or requested as a ",
     493           0 :                prop_base.dim(),
     494             :                "D property of type '",
     495           0 :                prop_base.type(),
     496             :                "'.");
     497             : 
     498        1941 :   return *prop_cast;
     499             : }
     500             : 
     501             : template <typename T, unsigned int dimension>
     502             : Moose::Kokkos::MaterialProperty<T, dimension>
     503        2996 : MaterialData::declareKokkosProperty(const std::string & prop_name,
     504             :                                     const std::vector<unsigned int> & dims,
     505             :                                     const MaterialBase * declarer,
     506             :                                     const bool bnd,
     507             :                                     const bool on_demand,
     508             :                                     const Moose::Kokkos::PropertyConstantOption constant_option)
     509             : {
     510        2996 :   auto shell = std::make_shared<Moose::Kokkos::MaterialProperty<T, dimension>>();
     511             : 
     512        2996 :   auto & prop_base = declareKokkosPropertyHelper(
     513             :       prop_name, typeid(T), declarer, dims, bnd, on_demand, constant_option, shell);
     514        2990 :   auto prop_cast = dynamic_cast<Moose::Kokkos::MaterialProperty<T, dimension> *>(&prop_base);
     515             : 
     516        2990 :   if (!prop_cast)
     517           2 :     mooseError("The declared ",
     518             :                dimension,
     519             :                "D Kokkos material property '",
     520             :                prop_name,
     521             :                "' of type '",
     522             :                MooseUtils::prettyCppType<T>(),
     523             :                "' was already declared or requested as a ",
     524           2 :                prop_base.dim(),
     525             :                "D property of type '",
     526           2 :                prop_base.type(),
     527             :                "'.");
     528             : 
     529        5976 :   return *prop_cast;
     530        2988 : }
     531             : #endif

Generated by: LCOV version 1.14