LCOV - code coverage report
Current view: top level - include/materials - MaterialData.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 6f668f Lines: 71 74 95.9 %
Date: 2025-09-22 20:01:15 Functions: 149 209 71.3 %
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    74158369 :   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       48948 :   bool haveProperty(const std::string & prop_name) const
      94             :   {
      95       48948 :     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       25670 :   bool haveADProperty(const std::string & prop_name) const
     101             :   {
     102       25670 :     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       65013 :   GenericMaterialProperty<T, is_ad> & getProperty(const std::string & prop_name,
     128             :                                                   const unsigned int state,
     129             :                                                   const MooseObject & requestor)
     130             :   {
     131       65013 :     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       64264 :   GenericMaterialProperty<T, is_ad> & declareProperty(const std::string & prop_name,
     143             :                                                       const MooseObject & requestor)
     144             :   {
     145       64264 :     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             :    * @return The Kokkos material property
     169             :    */
     170             :   template <typename T, unsigned int dimension>
     171             :   Moose::Kokkos::MaterialProperty<T, dimension>
     172             :   declareKokkosProperty(const std::string & prop_name,
     173             :                         const std::vector<unsigned int> & dims,
     174             :                         const MaterialBase * declarer,
     175             :                         const bool bnd);
     176             : #endif
     177             : 
     178             :   /**
     179             :    * Returns true if the stateful material is in a swapped state.
     180             :    */
     181   440268588 :   bool isSwapped() const { return _swapped; }
     182             : 
     183             :   /**
     184             :    * Provide read-only access to the underlying MaterialPropertyStorage object.
     185             :    */
     186     1537966 :   const MaterialPropertyStorage & getMaterialPropertyStorage() const { return _storage; }
     187             : 
     188             :   /**
     189             :    * Key that provides access to only the XFEM class.
     190             :    */
     191             :   class XFEMKey
     192             :   {
     193             :     friend class XFEM;
     194             :     XFEMKey() {}
     195             :     XFEMKey(const XFEM &) {}
     196             :   };
     197             : 
     198             :   /**
     199             :    * Provide write-only access to the underlying MaterialPropertyStorage object JUST FOR XFEM.
     200             :    *
     201             :    * This should be removed. To be clear - you should not ever expect to have write access
     202             :    * to this data. It just turned out that XFEM got away with it when we were storing things
     203             :    * as pointers instead of smart pointers...
     204             :    *
     205             :    * These dirty reasons are why this method is named so egregiously.
     206             :    */
     207             :   MaterialPropertyStorage & getMaterialPropertyStorageForXFEM(const XFEMKey) { return _storage; }
     208             : 
     209             :   /**
     210             :    * @return Whether or not a property exists with the name \p name
     211             :    */
     212             :   bool hasProperty(const std::string & prop_name) const;
     213             : 
     214             :   /**
     215             :    * Wrapper for MaterialStorage::getPropertyId. Allows classes with a MaterialData object
     216             :    * (i.e. MaterialPropertyInterface) to access material property IDs.
     217             :    * @param prop_name The name of the material property
     218             :    *
     219             :    * @return An unsigned int corresponding to the property ID of the passed in prop_name
     220             :    */
     221             :   unsigned int getPropertyId(const std::string & prop_name) const;
     222             : 
     223             :   /**
     224             :    * Set _resize_only_if_smaller to perform a non-destructive resize. Setting this
     225             :    * flag to true means that resize(n) will not decrease the size of _props
     226             :    * if n is smaller than the size of the material data object.
     227             :    */
     228             :   void onlyResizeIfSmaller(bool flag) { _resize_only_if_smaller = flag; };
     229             : 
     230             :   /**
     231             :    * Check value of _resize_only_if_smaller
     232             :    */
     233      641080 :   bool isOnlyResizeIfSmaller() const { return _resize_only_if_smaller; };
     234             : 
     235             :   /**
     236             :    * Remove the property storage and element pointer from MaterialPropertyStorage data structures
     237             :    * Use this when elements are deleted so we don't end up with invalid elem pointers (for e.g.
     238             :    * stateful properties) hanging around in our data structures
     239             :    */
     240             :   void eraseProperty(const Elem * elem);
     241             : 
     242             : private:
     243             :   /// Reference to the MaterialStorage class
     244             :   MaterialPropertyStorage & _storage;
     245             : 
     246             :   /// The thread id
     247             :   const THREAD_ID _tid;
     248             : 
     249             :   /// Number of quadrature points
     250             :   unsigned int _n_qpoints;
     251             : 
     252             :   /// The underlying property data
     253             :   std::array<MaterialProperties, max_state + 1> _props;
     254             : 
     255             :   unsigned int addPropertyHelper(const std::string & prop_name,
     256             :                                  const std::type_info & type,
     257             :                                  const unsigned int state,
     258             :                                  const MaterialBase * const declarer);
     259             : 
     260             :   template <typename T, bool is_ad, bool declare>
     261             :   GenericMaterialProperty<T, is_ad> & getPropertyHelper(const std::string & prop_name,
     262             :                                                         const unsigned int state,
     263             :                                                         const MooseObject & requestor);
     264             : 
     265             : #ifdef MOOSE_KOKKOS_ENABLED
     266             :   /**
     267             :    * Helper function for adding a Kokkos material property
     268             :    * @param prop_name The property name
     269             :    * @param type The property data type
     270             :    * @param state The property state
     271             :    * @param shell The managed pointer containing the instance of the property
     272             :    * @return The Kokkos material property
     273             :    */
     274             :   Moose::Kokkos::MaterialPropertyBase &
     275             :   addKokkosPropertyHelper(const std::string & prop_name,
     276             :                           const std::type_info & type,
     277             :                           const unsigned int state,
     278             :                           std::shared_ptr<Moose::Kokkos::MaterialPropertyBase> shell);
     279             : 
     280             :   /**
     281             :    * Helper function for declaring a Kokkos material property
     282             :    * @param prop_name The property name
     283             :    * @param type The property data type
     284             :    * @param declarer The Kokkos material declaring the property
     285             :    * @param dims The vector containing the size of each dimension
     286             :    * @param bnd Whether the property is a face property
     287             :    * @param shell The managed pointer containing the instance of the property
     288             :    * @return The Kokkos material property
     289             :    */
     290             :   Moose::Kokkos::MaterialPropertyBase &
     291             :   declareKokkosPropertyHelper(const std::string & prop_name,
     292             :                               const std::type_info & type,
     293             :                               const MaterialBase * declarer,
     294             :                               const std::vector<unsigned int> & dims,
     295             :                               const bool bnd,
     296             :                               std::shared_ptr<Moose::Kokkos::MaterialPropertyBase> shell);
     297             : 
     298             :   /**
     299             :    * Helper function for getting a Kokkos material property
     300             :    * @param prop_name The property name
     301             :    * @param state The property state
     302             :    * @param shell The managed pointer containing the instance of the property
     303             :    * @return The Kokkos material property
     304             :    */
     305             :   Moose::Kokkos::MaterialPropertyBase & getKokkosPropertyHelper(
     306             :       const std::string & prop_name,
     307             :       const unsigned int state = 0,
     308             :       std::shared_ptr<Moose::Kokkos::MaterialPropertyBase> shell = nullptr) const;
     309             : 
     310             :   /**
     311             :    * Helper function for checking whether a Kokkos material property exists
     312             :    * @param prop_name The property name
     313             :    * @return Whether the Kokkos material property exists
     314             :    */
     315             :   bool haveKokkosPropertyHelper(const std::string & prop_name) const;
     316             :   /**
     317             :    * Helper function to register load/store functions of a Kokkos material property to the Kokkos
     318             :    * material property storage
     319             :    * @param type The property type index
     320             :    * @param store The store function pointer
     321             :    * @param load The load function pointer
     322             :    */
     323             :   void kokkosRegisterLoadStoreHelper(std::type_index type,
     324             :                                      Moose::Kokkos::PropertyStore store,
     325             :                                      Moose::Kokkos::PropertyLoad load);
     326             : #endif
     327             : 
     328             :   static void mooseErrorHelper(const MooseObject & object, const std::string_view & error);
     329             : 
     330             :   /**
     331             :    * Helper for casting \p requestor to a MaterialBase in addPropertyHelper() (templated)
     332             :    */
     333             :   const MaterialBase & castRequestorToDeclarer(const MooseObject & requestor) const;
     334             : 
     335             :   /// Status of storage swapping (calling swap sets this to true; swapBack sets it to false)
     336             :   bool _swapped;
     337             : 
     338             :   /// Use non-destructive resize of material data (calling resize() will not reduce size).
     339             :   /// Default is false (normal resize behaviour)
     340             :   bool _resize_only_if_smaller;
     341             : 
     342             :   /// maximum state id requested for a property
     343             :   unsigned int getMaxStateRequested(const unsigned int prop_id) const;
     344             : };
     345             : 
     346             : inline const MaterialProperties &
     347      142860 : MaterialData::props(const unsigned int state) const
     348             : {
     349             :   mooseAssert(_props.size() > state, "Invalid state");
     350      142860 :   return _props[state];
     351             : }
     352             : 
     353             : inline MaterialProperties &
     354    43180267 : MaterialData::props(const unsigned int state)
     355             : {
     356             :   mooseAssert(_props.size() > state, "Invalid state");
     357    43180267 :   return _props[state];
     358             : }
     359             : 
     360             : template <typename T, bool is_ad>
     361             : inline bool
     362       80064 : MaterialData::haveGenericProperty(const std::string & prop_name) const
     363             : {
     364       80064 :   if (!hasProperty(prop_name))
     365        8474 :     return false;
     366             : 
     367       71590 :   const auto prop_id = getPropertyId(prop_name);
     368             :   // the property id exists, but the property was not created in this instance of the material type
     369       71590 :   if (prop_id >= props(0).size())
     370         320 :     return false;
     371             : 
     372       71270 :   const PropertyValue * const base_prop = props(0).queryValue(prop_id);
     373       71270 :   return dynamic_cast<const GenericMaterialProperty<T, is_ad> *>(base_prop) != nullptr;
     374             : }
     375             : 
     376             : template <typename T, bool is_ad, bool declare>
     377             : GenericMaterialProperty<T, is_ad> &
     378      129277 : MaterialData::getPropertyHelper(const std::string & prop_name,
     379             :                                 const unsigned int state,
     380             :                                 const MooseObject & requestor)
     381             : {
     382             :   if constexpr (is_ad)
     383             :     mooseAssert(state == 0, "Cannot request/declare AD properties for states other than zero");
     384             :   if constexpr (declare)
     385             :     mooseAssert(state == 0, "Cannot declare properties for states other than zero");
     386             : 
     387             :   // Register/get the ID of the property
     388      193541 :   const auto prop_id = addPropertyHelper(
     389       64264 :       prop_name, typeid(T), state, declare ? &castRequestorToDeclarer(requestor) : nullptr);
     390      129277 :   const auto size = prop_id + 1;
     391             : 
     392             :   // Initialize the states that we need
     393      267113 :   for (const auto state_i : make_range(getMaxStateRequested(prop_id) + 1))
     394             :   {
     395      137836 :     auto & entry = props(state_i);
     396      137836 :     if (entry.size() < size)
     397       63366 :       entry.resize(size, {});
     398             :     // if we are not declaring the property we initialize only what we need (the requested state)
     399      137836 :     if (!entry.hasValue(prop_id) && (declare || state_i == state))
     400             :     {
     401       63319 :       if (state_i == 0)
     402      118590 :         entry.setPointer(
     403      118590 :             prop_id, std::move(std::make_unique<GenericMaterialProperty<T, is_ad>>(prop_id)), {});
     404             :       else
     405        4024 :         entry.setPointer(prop_id, std::move(std::make_unique<MaterialProperty<T>>(prop_id)), {});
     406             :     }
     407             :   }
     408             : 
     409             :   // Should be available now
     410      129277 :   auto & base_prop = props(state)[prop_id];
     411             : 
     412             :   // In the event that this property was already declared/requested, make sure
     413             :   // that the types are consistent
     414      129277 :   auto prop = dynamic_cast<GenericMaterialProperty<T, is_ad> *>(&base_prop);
     415      129277 :   if (!prop)
     416             :   {
     417          16 :     constexpr std::string_view action = declare ? "declared" : "requested";
     418          16 :     constexpr auto is_ad_to_str = [](const bool is_ad_bool)
     419          16 :     { return std::string_view(is_ad_bool ? "AD" : "non-AD"); };
     420          16 :     constexpr std::string_view ad_type = is_ad_to_str(is_ad);
     421             : 
     422          16 :     std::stringstream error;
     423             :     error << "The " << action << " " << ad_type << " "
     424             :           << "material property '" + prop_name + "' of type '" << MooseUtils::prettyCppType<T>()
     425          32 :           << "'\nis already retrieved or declared as a " << is_ad_to_str(base_prop.isAD())
     426          16 :           << " property of type '" << base_prop.type() << "'.";
     427          16 :     mooseErrorHelper(requestor, error.str());
     428           0 :   }
     429             : 
     430      129261 :   return *prop;
     431             : }
     432             : 
     433             : template <typename MatContainer>
     434             : void
     435    22466147 : MaterialData::reinit(const MatContainer & mats)
     436             : {
     437    54017518 :   for (const auto & mat : mats)
     438    31551449 :     mat->computeProperties();
     439    22466069 : }
     440             : 
     441             : #ifdef MOOSE_KOKKOS_SCOPE
     442             : template <typename T, unsigned int dimension>
     443             : bool
     444             : MaterialData::haveKokkosProperty(const std::string & prop_name) const
     445             : {
     446             :   if (!haveKokkosPropertyHelper(prop_name))
     447             :     return false;
     448             : 
     449             :   auto & prop = getKokkosPropertyHelper(prop_name);
     450             :   return dynamic_cast<Moose::Kokkos::MaterialProperty<T, dimension> *>(&prop) != nullptr;
     451             : }
     452             : 
     453             : template <typename T, unsigned int dimension, unsigned int state>
     454             : Moose::Kokkos::MaterialProperty<T, dimension>
     455        1129 : MaterialData::getKokkosProperty(const std::string & prop_name)
     456             : {
     457             :   // Reserve the storages for the property up to the requested state
     458             :   // If the storages were already reserved, it will do nothing
     459        3246 :   for (unsigned int s = 0; s <= state; ++s)
     460             :   {
     461        2117 :     auto shell = std::make_shared<Moose::Kokkos::MaterialProperty<T, dimension>>();
     462             : 
     463        2117 :     addKokkosPropertyHelper(prop_name, typeid(T), state, shell);
     464             : 
     465             :     // Only instantiate load and store functions for stateful properties to avoid requiring users
     466             :     // to provide custom dataLoad and dataStore for non-trivially-copyable types that are never
     467             :     // used as stateful properties
     468             :     if constexpr (state > 0)
     469        1760 :       kokkosRegisterLoadStoreHelper(shell->propertyType(),
     470             :                                     Moose::Kokkos::propertyStore<T, dimension>,
     471             :                                     Moose::Kokkos::propertyLoad<T, dimension>);
     472             :   }
     473             : 
     474        1129 :   auto & prop_base = getKokkosPropertyHelper(prop_name, state, nullptr);
     475        1129 :   auto prop_cast = dynamic_cast<Moose::Kokkos::MaterialProperty<T, dimension> *>(&prop_base);
     476             : 
     477        1129 :   if (!prop_cast)
     478           0 :     mooseError("The requested ",
     479             :                dimension,
     480             :                "D Kokkos material property '",
     481             :                prop_name,
     482             :                "' of type '",
     483             :                MooseUtils::prettyCppType<T>(),
     484             :                "' was already declared or requested as a ",
     485           0 :                prop_base.dim(),
     486             :                "D property of type '",
     487             :                prop_base.type(),
     488             :                "'.");
     489             : 
     490        1129 :   return *prop_cast;
     491             : }
     492             : 
     493             : template <typename T, unsigned int dimension>
     494             : Moose::Kokkos::MaterialProperty<T, dimension>
     495        1027 : MaterialData::declareKokkosProperty(const std::string & prop_name,
     496             :                                     const std::vector<unsigned int> & dims,
     497             :                                     const MaterialBase * declarer,
     498             :                                     const bool bnd)
     499             : {
     500        1027 :   auto shell = std::make_shared<Moose::Kokkos::MaterialProperty<T, dimension>>();
     501             : 
     502        1027 :   auto & prop_base = declareKokkosPropertyHelper(prop_name, typeid(T), declarer, dims, bnd, shell);
     503        1023 :   auto prop_cast = dynamic_cast<Moose::Kokkos::MaterialProperty<T, dimension> *>(&prop_base);
     504             : 
     505        1023 :   if (!prop_cast)
     506           4 :     mooseError("The declared ",
     507             :                dimension,
     508             :                "D Kokkos material property '",
     509             :                prop_name,
     510             :                "' of type '",
     511             :                MooseUtils::prettyCppType<T>(),
     512             :                "' was already declared or requested as a ",
     513           2 :                prop_base.dim(),
     514             :                "D property of type '",
     515             :                prop_base.type(),
     516             :                "'.");
     517             : 
     518        2042 :   return *prop_cast;
     519        1021 : }
     520             : #endif

Generated by: LCOV version 1.14