LCOV - code coverage report
Current view: top level - include/materials - MaterialBase.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #31706 (f8ed4a) with base bb0a08 Lines: 88 95 92.6 %
Date: 2025-11-03 17:23:24 Functions: 88 99 88.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             : // MOOOSE includes
      13             : #include "MooseObject.h"
      14             : #include "BlockRestrictable.h"
      15             : #include "BoundaryRestrictable.h"
      16             : #include "SetupInterface.h"
      17             : #include "MooseVariableDependencyInterface.h"
      18             : #include "ScalarCoupleable.h"
      19             : #include "FunctionInterface.h"
      20             : #include "DistributionInterface.h"
      21             : #include "UserObjectInterface.h"
      22             : #include "TransientInterface.h"
      23             : #include "PostprocessorInterface.h"
      24             : #include "VectorPostprocessorInterface.h"
      25             : #include "DependencyResolverInterface.h"
      26             : #include "Restartable.h"
      27             : #include "MeshChangedInterface.h"
      28             : #include "OutputInterface.h"
      29             : #include "RandomInterface.h"
      30             : #include "ElementIDInterface.h"
      31             : #include "MaterialProperty.h"
      32             : #include "MaterialData.h"
      33             : #include "MathUtils.h"
      34             : #include "Assembly.h"
      35             : #include "GeometricSearchInterface.h"
      36             : #include "ADFunctorInterface.h"
      37             : #include "SolutionInvalidInterface.h"
      38             : #include "MaterialPropertyInterface.h"
      39             : 
      40             : #define usingMaterialBaseMembers                                                                   \
      41             :   usingMooseObjectMembers;                                                                         \
      42             :   usingTransientInterfaceMembers;                                                                  \
      43             :   using MaterialBase::_subproblem;                                                                 \
      44             :   using MaterialBase::_fe_problem;                                                                 \
      45             :   using MaterialBase::_tid;                                                                        \
      46             :   using MaterialBase::_assembly;                                                                   \
      47             :   using MaterialBase::_qp;                                                                         \
      48             :   using MaterialBase::_coord;                                                                      \
      49             :   using MaterialBase::_normals;                                                                    \
      50             :   using MaterialBase::_mesh
      51             : 
      52             : // forward declarations
      53             : class MaterialBase;
      54             : class MooseMesh;
      55             : class SubProblem;
      56             : class FaceInfo;
      57             : class FEProblemBase;
      58             : 
      59             : /**
      60             :  * MaterialBases compute MaterialProperties.
      61             :  */
      62             : class MaterialBase : public MooseObject,
      63             :                      public BlockRestrictable,
      64             :                      public BoundaryRestrictable,
      65             :                      public SetupInterface,
      66             :                      public MooseVariableDependencyInterface,
      67             :                      public ScalarCoupleable,
      68             :                      public FunctionInterface,
      69             :                      public DistributionInterface,
      70             :                      public UserObjectInterface,
      71             :                      public TransientInterface,
      72             :                      public PostprocessorInterface,
      73             :                      public VectorPostprocessorInterface,
      74             :                      public DependencyResolverInterface,
      75             :                      public Restartable,
      76             :                      public MeshChangedInterface,
      77             :                      public OutputInterface,
      78             :                      public RandomInterface,
      79             :                      public ElementIDInterface,
      80             :                      protected GeometricSearchInterface,
      81             :                      protected ADFunctorInterface
      82             : {
      83             : public:
      84             :   static InputParameters validParams();
      85             : 
      86             :   MaterialBase(const InputParameters & parameters);
      87             : 
      88             : #ifdef MOOSE_KOKKOS_ENABLED
      89             :   /**
      90             :    * Special constructor used for Kokkos functor copy during parallel dispatch
      91             :    */
      92             :   MaterialBase(const MaterialBase & object, const Moose::Kokkos::FunctorCopy & key);
      93             : #endif
      94             : 
      95             :   /**
      96             :    * Initialize stateful properties (if material has some)
      97             :    *
      98             :    * This is _only_ called if this material has properties that are
      99             :    * requested as stateful
     100             :    */
     101             :   virtual void initStatefulProperties(const unsigned int n_points);
     102             : 
     103           0 :   virtual bool isInterfaceMaterial() { return false; };
     104             : 
     105             :   /**
     106             :    * Performs the quadrature point loop, calling computeQpProperties
     107             :    */
     108             :   virtual void computeProperties() = 0;
     109             : 
     110             :   /**
     111             :    * Resets the properties at each quadrature point (see resetQpProperties), only called if 'compute
     112             :    * = false'.
     113             :    *
     114             :    * This method is called internally by MOOSE, you probably don't want to mess with this.
     115             :    */
     116             :   virtual void resetProperties();
     117             : 
     118             :   /**
     119             :    * A method for (re)computing the properties of a MaterialBase.
     120             :    *
     121             :    * This is intended to be called from other objects, by first calling
     122             :    * MaterialPropertyInterface::getMaterial and then calling this method on the MaterialBase object
     123             :    * returned.
     124             :    */
     125             :   virtual void computePropertiesAtQp(unsigned int qp);
     126             : 
     127             :   ///@{
     128             :   /**
     129             :    * Declare the property named "name"
     130             :    */
     131             :   template <typename T>
     132       42829 :   MaterialProperty<T> & declarePropertyByName(const std::string & prop_name)
     133             :   {
     134       42829 :     return declareGenericPropertyByName<T, false>(prop_name);
     135             :   }
     136             :   template <typename T>
     137             :   MaterialProperty<T> & declareProperty(const std::string & name);
     138             :   template <typename T>
     139       12358 :   ADMaterialProperty<T> & declareADPropertyByName(const std::string & prop_name)
     140             :   {
     141       12358 :     return declareGenericPropertyByName<T, true>(prop_name);
     142             :   }
     143             :   template <typename T>
     144             :   ADMaterialProperty<T> & declareADProperty(const std::string & name);
     145             : 
     146             :   template <typename T, bool is_ad>
     147       36188 :   auto & declareGenericProperty(const std::string & prop_name)
     148             :   {
     149             :     if constexpr (is_ad)
     150       10529 :       return declareADProperty<T>(prop_name);
     151             :     else
     152       25659 :       return declareProperty<T>(prop_name);
     153             :   }
     154             :   template <typename T, bool is_ad>
     155             :   GenericMaterialProperty<T, is_ad> & declareGenericPropertyByName(const std::string & prop_name);
     156             :   ///@}
     157             : 
     158             :   /**
     159             :    * Return a material property that is initialized to zero by default and does
     160             :    * not need to (but can) be declared by another material.
     161             :    */
     162             :   template <typename T, bool is_ad>
     163             :   const GenericMaterialProperty<T, is_ad> &
     164             :   getGenericZeroMaterialProperty(const std::string & name);
     165             :   template <typename T, bool is_ad>
     166             :   const GenericMaterialProperty<T, is_ad> &
     167             :   getGenericZeroMaterialPropertyByName(const std::string & prop_name);
     168             : 
     169             :   /**
     170             :    * Return a constant zero anonymous material property
     171             :    */
     172             :   template <typename T, bool is_ad>
     173             :   const GenericMaterialProperty<T, is_ad> & getGenericZeroMaterialProperty();
     174             : 
     175             :   /// for backwards compatibility
     176             :   template <typename T, typename... Ts>
     177             :   const MaterialProperty<T> & getZeroMaterialProperty(Ts... args)
     178             :   {
     179             :     return getGenericZeroMaterialProperty<T, false>(args...);
     180             :   }
     181             : 
     182             :   /// for backwards compatibility
     183             :   template <typename T, typename... Ts>
     184             :   const MaterialProperty<T> & getZeroMaterialPropertyByName(Ts... args)
     185             :   {
     186             :     return getGenericZeroMaterialPropertyByName<T, false>(args...);
     187             :   }
     188             : 
     189             :   /**
     190             :    * Return a set of properties accessed with getMaterialProperty
     191             :    * @return A reference to the set of properties with calls to getMaterialProperty
     192             :    */
     193       23291 :   virtual const std::set<std::string> & getRequestedItems() override { return _requested_props; }
     194             : 
     195             :   /**
     196             :    * Return a set of properties accessed with declareProperty
     197             :    * @return A reference to the set of properties with calls to declareProperty
     198             :    */
     199      240582 :   virtual const std::set<std::string> & getSuppliedItems() override { return _supplied_props; }
     200             : 
     201             :   /**
     202             :    * Get the prop ids corresponding to \p declareProperty
     203             :    * @return A reference to the set of properties with calls to \p declareProperty
     204             :    */
     205      708081 :   const std::set<unsigned int> & getSuppliedPropIDs() { return _supplied_prop_ids; }
     206             : 
     207             :   void checkStatefulSanity() const;
     208             : 
     209             :   /**
     210             :    * Get the list of output objects that this class is restricted
     211             :    * @return A vector of OutputNames
     212             :    */
     213             :   std::set<OutputName> getOutputs();
     214             : 
     215             :   /**
     216             :    * Returns true of the MaterialData type is not associated with volume data
     217             :    */
     218             :   virtual bool isBoundaryMaterial() const = 0;
     219             : 
     220             :   /**
     221             :    * Subdomain setup evaluating material properties when required
     222             :    */
     223             :   virtual void subdomainSetup() override;
     224             : 
     225             :   /**
     226             :    * Retrieve the set of material properties that _this_ object depends on.
     227             :    *
     228             :    * @return The IDs corresponding to the material properties that
     229             :    * MUST be reinited before evaluating this object
     230             :    */
     231             :   virtual const std::unordered_set<unsigned int> & getMatPropDependencies() const = 0;
     232             : 
     233             :   /**
     234             :    * @return Whether this material has stateful properties
     235             :    */
     236         689 :   bool hasStatefulProperties() const { return _has_stateful_property; }
     237             : 
     238             :   /**
     239             :    * @return Whether this material has restored properties
     240             :    */
     241             :   bool hasRestoredProperties() const;
     242             : 
     243             :   /**
     244             :    * Whether this material supports ghosted computations. This is important for finite volume
     245             :    * calculations in which variables have defined values on ghost cells/elements and for which these
     246             :    * ghost values may need to flow through material calculations to be eventually consumed by FV
     247             :    * flux kernels or boundary conditions
     248             :    */
     249           0 :   virtual bool ghostable() const { return false; }
     250             : 
     251       21816 :   void setFaceInfo(const FaceInfo & fi) { _face_info = &fi; }
     252             : 
     253             :   /**
     254             :    * Build the materials required by a set of consumer objects
     255             :    */
     256             :   template <typename Consumers>
     257             :   static std::deque<MaterialBase *>
     258             :   buildRequiredMaterials(const Consumers & mat_consumers,
     259             :                          const std::vector<std::shared_ptr<MaterialBase>> & mats,
     260             :                          const bool allow_stateful);
     261             : 
     262             :   /**
     263             :    * Set active properties of this material
     264             :    * Note: This function is called by FEProblemBase::setActiveMaterialProperties in an element loop
     265             :    *       typically when switching subdomains.
     266             :    */
     267             :   void setActiveProperties(const std::unordered_set<unsigned int> & needed_props);
     268             : 
     269             :   /**
     270             :    * @return Whether or not this material should forcefully call
     271             :    * initStatefulProperties() even if it doesn't produce properties
     272             :    * that needs state.
     273             :    *
     274             :    * Please don't set this to true :(
     275             :    */
     276      246558 :   bool forceStatefulInit() const { return _force_stateful_init; }
     277             : 
     278             : protected:
     279             :   /**
     280             :    * Users must override this method.
     281             :    */
     282             :   virtual void computeQpProperties();
     283             : 
     284             :   /**
     285             :    * Resets the properties prior to calculation of traditional materials (only if 'compute =
     286             :    * false').
     287             :    *
     288             :    * This method must be overridden in your class. This is called just prior to the re-calculation
     289             :    * of
     290             :    * traditional material properties to ensure that the properties are in a proper state for
     291             :    * calculation.
     292             :    */
     293             :   virtual void resetQpProperties();
     294             : 
     295             :   /**
     296             :    * Initialize stateful properties at quadrature points.  Note when using this function you only
     297             :    * need to address
     298             :    * the "current" material properties not the old ones directly, i.e. if you have a property named
     299             :    * "_diffusivity"
     300             :    * and an older property named "_diffusivity_old".  You only need to initialize diffusivity.
     301             :    * MOOSE will use
     302             :    * copy that initial value to the old and older values as necessary.
     303             :    *
     304             :    * This is _only_ called if this material has properties that are
     305             :    * requested as stateful
     306             :    */
     307             :   virtual void initQpStatefulProperties();
     308             : 
     309             :   virtual const MaterialData & materialData() const = 0;
     310             :   virtual MaterialData & materialData() = 0;
     311             :   virtual Moose::MaterialDataType materialDataType() = 0;
     312             : 
     313           0 :   virtual const FEProblemBase & miProblem() const { return _fe_problem; }
     314           0 :   virtual FEProblemBase & miProblem() { return _fe_problem; }
     315             : 
     316             :   virtual const QBase & qRule() const = 0;
     317             : 
     318             :   /**
     319             :    * Check whether a material property is active
     320             :    */
     321        5548 :   bool isPropertyActive(const unsigned int prop_id) const
     322             :   {
     323        5548 :     return _active_prop_ids.count(prop_id) > 0;
     324             :   }
     325             : 
     326             :   SubProblem & _subproblem;
     327             : 
     328             :   FEProblemBase & _fe_problem;
     329             :   THREAD_ID _tid;
     330             :   Assembly & _assembly;
     331             : 
     332             :   unsigned int _qp;
     333             : 
     334             :   const MooseArray<Real> & _coord;
     335             :   /// normals at quadrature points (valid only in boundary materials)
     336             :   const MooseArray<Point> & _normals;
     337             : 
     338             :   MooseMesh & _mesh;
     339             : 
     340             :   /// Coordinate system
     341             :   const Moose::CoordinateSystemType & _coord_sys;
     342             : 
     343             :   /// Set of properties accessed via get method
     344             :   std::set<std::string> _requested_props;
     345             : 
     346             :   /// Set of properties declared
     347             :   std::set<std::string> _supplied_props;
     348             : 
     349             :   /// The ids of the supplied properties, i.e. the indices where they
     350             :   /// are stored in the _material_data->props().  Note: these ids ARE
     351             :   /// NOT IN THE SAME ORDER AS THE _supplied_props set, which is
     352             :   /// ordered alphabetically by name.  The intention of this container
     353             :   /// is to allow rapid copying of MaterialProperty values in
     354             :   /// MaterialBase::computeProperties() without looking up the ids from
     355             :   /// the name strings each time.
     356             :   std::set<unsigned int> _supplied_prop_ids;
     357             : 
     358             :   /// The ids of the current active supplied properties
     359             :   std::unordered_set<unsigned int> _active_prop_ids;
     360             : 
     361             :   /// If False MOOSE does not compute this property
     362             :   const bool _compute;
     363             : 
     364             :   enum QP_Data_Type
     365             :   {
     366             :     CURR,
     367             :     PREV
     368             :   };
     369             : 
     370             :   /// The minimum states requested (0 = current, 1 = old, 2 = older)
     371             :   /// This is sparse and is used to keep track of whether or not stateful
     372             :   /// properties are requested without state 0 being requested
     373             :   std::unordered_map<unsigned int, unsigned int> _props_to_min_states;
     374             : 
     375             :   /// Small helper function to call store{Subdomain,Boundary}MatPropName
     376             :   void registerPropName(const std::string & prop_name, bool is_get, const unsigned int state);
     377             : 
     378             :   /// Check and throw an error if the execution has progressed past the construction stage
     379             :   void checkExecutionStage();
     380             : 
     381             :   std::vector<unsigned int> _displacements;
     382             : 
     383             :   bool _has_stateful_property;
     384             : 
     385             :   bool _overrides_init_stateful_props = true;
     386             : 
     387             :   const FaceInfo * _face_info = nullptr;
     388             : 
     389             :   /// Suffix to append to the name of the material property/ies when declaring it/them
     390             :   const MaterialPropertyName _declare_suffix;
     391             : 
     392             : private:
     393             :   /**
     394             :    * Helper method for adding a material property name to the material property requested set
     395             :    */
     396             :   void markMatPropRequested(const std::string & name);
     397             : 
     398             :   /**
     399             :    * Adds to a map based on block ids of material properties for which a zero
     400             :    * value can be returned. These properties are optional and will not trigger a
     401             :    * missing material property error.
     402             :    *
     403             :    * @param block_id The block id for the MaterialProperty
     404             :    * @param name The name of the property
     405             :    */
     406             :   void storeSubdomainZeroMatProp(SubdomainID block_id, const MaterialPropertyName & name);
     407             : 
     408             :   /**
     409             :    * Adds to a map based on boundary ids of material properties for which a zero
     410             :    * value can be returned. These properties are optional and will not trigger a
     411             :    * missing material property error.
     412             :    *
     413             :    * @param boundary_id The block id for the MaterialProperty
     414             :    * @param name The name of the property
     415             :    */
     416             :   void storeBoundaryZeroMatProp(BoundaryID boundary_id, const MaterialPropertyName & name);
     417             : 
     418             :   /**
     419             :    * @return The maximum number of quadrature points in use on any element in this problem.
     420             :    */
     421             :   unsigned int getMaxQps() const;
     422             : 
     423             :   /// Whether or not to force stateful init; see forceStatefulInit()
     424             :   const bool _force_stateful_init;
     425             : 
     426             :   /// To let it access the declaration suffix
     427             :   friend class FunctorMaterial;
     428             : };
     429             : 
     430             : template <typename T>
     431             : MaterialProperty<T> &
     432       42829 : MaterialBase::declareProperty(const std::string & name)
     433             : {
     434             :   // Check if the supplied parameter is a valid input parameter key
     435       42829 :   std::string prop_name = name;
     436       42829 :   if (_pars.have_parameter<MaterialPropertyName>(name))
     437         750 :     prop_name = _pars.get<MaterialPropertyName>(name);
     438             : 
     439       85658 :   return declarePropertyByName<T>(prop_name);
     440       42829 : }
     441             : 
     442             : template <typename T, bool is_ad>
     443             : GenericMaterialProperty<T, is_ad> &
     444       65464 : MaterialBase::declareGenericPropertyByName(const std::string & prop_name)
     445             : {
     446      131138 :   const auto prop_name_modified =
     447       65464 :       _declare_suffix.empty()
     448       65464 :           ? prop_name
     449       66094 :           : MooseUtils::join(std::vector<std::string>({prop_name, _declare_suffix}), "_");
     450             : 
     451             :   // Call this before so that the ID is valid
     452       65464 :   auto & prop = materialData().declareProperty<T, is_ad>(prop_name_modified, *this);
     453             : 
     454       65464 :   registerPropName(prop_name_modified, false, 0);
     455       65464 :   return prop;
     456       65674 : }
     457             : 
     458             : template <typename T, bool is_ad>
     459             : const GenericMaterialProperty<T, is_ad> &
     460        4362 : MaterialBase::getGenericZeroMaterialProperty(const std::string & name)
     461             : {
     462             :   // Check if the supplied parameter is a valid input parameter key
     463        4362 :   std::string prop_name = name;
     464        4362 :   if (_pars.have_parameter<MaterialPropertyName>(name))
     465           0 :     prop_name = _pars.get<MaterialPropertyName>(name);
     466             : 
     467        8724 :   return getGenericZeroMaterialPropertyByName<T, is_ad>(prop_name);
     468        4362 : }
     469             : 
     470             : template <typename T, bool is_ad>
     471             : const GenericMaterialProperty<T, is_ad> &
     472        9522 : MaterialBase::getGenericZeroMaterialPropertyByName(const std::string & prop_name)
     473             : {
     474        9522 :   checkExecutionStage();
     475        9522 :   auto & preload_with_zero = materialData().getProperty<T, is_ad>(prop_name, 0, *this);
     476             : 
     477        9522 :   _requested_props.insert(prop_name);
     478        9522 :   registerPropName(prop_name, true, 0);
     479        9522 :   markMatPropRequested(prop_name);
     480             : 
     481             :   // Register this material on these blocks and boundaries as a zero property with relaxed
     482             :   // consistency checking
     483       19044 :   for (std::set<SubdomainID>::const_iterator it = blockIDs().begin(); it != blockIDs().end(); ++it)
     484        9522 :     storeSubdomainZeroMatProp(*it, prop_name);
     485       19044 :   for (std::set<BoundaryID>::const_iterator it = boundaryIDs().begin(); it != boundaryIDs().end();
     486        9522 :        ++it)
     487        9522 :     storeBoundaryZeroMatProp(*it, prop_name);
     488             : 
     489             :   // set values for all qpoints to zero
     490             :   // (in multiapp scenarios getMaxQps can return different values in each app; we need the max)
     491        9522 :   unsigned int nqp = getMaxQps();
     492        9522 :   if (nqp > preload_with_zero.size())
     493        7500 :     preload_with_zero.resize(nqp);
     494       52734 :   for (unsigned int qp = 0; qp < nqp; ++qp)
     495       43212 :     MathUtils::mooseSetToZero(preload_with_zero[qp]);
     496             : 
     497        9522 :   return preload_with_zero;
     498             : }
     499             : 
     500             : template <typename T, bool is_ad>
     501             : const GenericMaterialProperty<T, is_ad> &
     502         612 : MaterialBase::getGenericZeroMaterialProperty()
     503             : {
     504             :   // static zero property storage
     505         612 :   static GenericMaterialProperty<T, is_ad> zero(MaterialPropertyInterface::zero_property_id);
     506             : 
     507             :   // resize to accomodate maximum number of qpoints
     508             :   // (in multiapp scenarios getMaxQps can return different values in each app; we need the max)
     509         612 :   unsigned int nqp = getMaxQps();
     510         612 :   if (nqp > zero.size())
     511          30 :     zero.resize(nqp);
     512             : 
     513             :   // set values for all qpoints to zero
     514        3060 :   for (unsigned int qp = 0; qp < nqp; ++qp)
     515        2448 :     MathUtils::mooseSetToZero(zero[qp]);
     516             : 
     517         612 :   return zero;
     518             : }
     519             : 
     520             : template <typename T>
     521             : ADMaterialProperty<T> &
     522       12358 : MaterialBase::declareADProperty(const std::string & name)
     523             : {
     524             :   // Check if the supplied parameter is a valid input parameter key
     525       12358 :   std::string prop_name = name;
     526       12358 :   if (_pars.have_parameter<MaterialPropertyName>(name))
     527         677 :     prop_name = _pars.get<MaterialPropertyName>(name);
     528             : 
     529       24716 :   return declareADPropertyByName<T>(prop_name);
     530       12358 : }
     531             : 
     532             : template <typename Consumers>
     533             : std::deque<MaterialBase *>
     534        3487 : MaterialBase::buildRequiredMaterials(const Consumers & mat_consumers,
     535             :                                      const std::vector<std::shared_ptr<MaterialBase>> & mats,
     536             :                                      const bool allow_stateful)
     537             : {
     538        3487 :   std::deque<MaterialBase *> required_mats;
     539             : 
     540        3487 :   std::unordered_set<unsigned int> needed_mat_props;
     541        7494 :   for (const auto & consumer : mat_consumers)
     542             :   {
     543        4007 :     const auto & mp_deps = consumer->getMatPropDependencies();
     544        4007 :     needed_mat_props.insert(mp_deps.begin(), mp_deps.end());
     545             :   }
     546             : 
     547             :   // A predicate of calling this function is that these materials come in already sorted by
     548             :   // dependency with the front of the container having no other material dependencies and following
     549             :   // materials potentially depending on the ones in front of them. So we can start at the back and
     550             :   // iterate forward checking whether the current material supplies anything that is needed, and if
     551             :   // not we discard it
     552       17798 :   for (auto it = mats.rbegin(); it != mats.rend(); ++it)
     553             :   {
     554       14311 :     auto * const mat = it->get();
     555       14311 :     bool supplies_needed = false;
     556             : 
     557       14311 :     const auto & supplied_props = mat->getSuppliedPropIDs();
     558             : 
     559             :     // Do O(N) with the small container
     560       43881 :     for (const auto supplied_prop : supplied_props)
     561             :     {
     562       32539 :       if (needed_mat_props.count(supplied_prop))
     563             :       {
     564        2969 :         supplies_needed = true;
     565        2969 :         break;
     566             :       }
     567             :     }
     568             : 
     569       14311 :     if (!supplies_needed)
     570       11342 :       continue;
     571             : 
     572        2969 :     if (!allow_stateful && mat->hasStatefulProperties())
     573           0 :       ::mooseError(
     574             :           "Someone called buildRequiredMaterials with allow_stateful = false but a material "
     575             :           "dependency ",
     576           0 :           mat->name(),
     577             :           " computes stateful properties.");
     578             : 
     579        2969 :     const auto & mp_deps = mat->getMatPropDependencies();
     580        2969 :     needed_mat_props.insert(mp_deps.begin(), mp_deps.end());
     581        2969 :     required_mats.push_front(mat);
     582             :   }
     583             : 
     584        6974 :   return required_mats;
     585        3487 : }

Generated by: LCOV version 1.14