LCOV - code coverage report
Current view: top level - include/materials - MaterialBase.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #32971 (54bef8) with base c6cf66 Lines: 89 96 92.7 %
Date: 2026-05-29 20:35:17 Functions: 94 105 89.5 %
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       39457 :   MaterialProperty<T> & declarePropertyByName(const std::string & prop_name)
     133             :   {
     134       39457 :     return declareGenericPropertyByName<T, false>(prop_name);
     135             :   }
     136             :   template <typename T>
     137             :   MaterialProperty<T> & declareProperty(const std::string & name);
     138             :   template <typename T>
     139       11257 :   ADMaterialProperty<T> & declareADPropertyByName(const std::string & prop_name)
     140             :   {
     141       11257 :     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       33731 :   auto & declareGenericProperty(const std::string & prop_name)
     148             :   {
     149             :     if constexpr (is_ad)
     150        9577 :       return declareADProperty<T>(prop_name);
     151             :     else
     152       24154 :       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       24552 :   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      226893 :   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      167266 :   const std::set<unsigned int> & getSuppliedPropIDs() const { 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         654 :   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       19392 :   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             :    * Whether this material has active properties
     270             :    */
     271      113804 :   bool hasActiveProperties() { return _active_prop_ids.size() > 0; }
     272             : 
     273             :   /**
     274             :    * @return Whether or not this material should forcefully call
     275             :    * initStatefulProperties() even if it doesn't produce properties
     276             :    * that needs state.
     277             :    *
     278             :    * Please don't set this to true :(
     279             :    */
     280       32822 :   bool forceStatefulInit() const { return _force_stateful_init; }
     281             : 
     282             : protected:
     283             :   /**
     284             :    * Users must override this method.
     285             :    */
     286             :   virtual void computeQpProperties();
     287             : 
     288             :   /**
     289             :    * Resets the properties prior to calculation of traditional materials (only if 'compute =
     290             :    * false').
     291             :    *
     292             :    * This method must be overridden in your class. This is called just prior to the re-calculation
     293             :    * of
     294             :    * traditional material properties to ensure that the properties are in a proper state for
     295             :    * calculation.
     296             :    */
     297             :   virtual void resetQpProperties();
     298             : 
     299             :   /**
     300             :    * Initialize stateful properties at quadrature points.  Note when using this function you only
     301             :    * need to address
     302             :    * the "current" material properties not the old ones directly, i.e. if you have a property named
     303             :    * "_diffusivity"
     304             :    * and an older property named "_diffusivity_old".  You only need to initialize diffusivity.
     305             :    * MOOSE will use
     306             :    * copy that initial value to the old and older values as necessary.
     307             :    *
     308             :    * This is _only_ called if this material has properties that are
     309             :    * requested as stateful
     310             :    */
     311             :   virtual void initQpStatefulProperties();
     312             : 
     313             :   virtual const MaterialData & materialData() const = 0;
     314             :   virtual MaterialData & materialData() = 0;
     315             :   virtual Moose::MaterialDataType materialDataType() = 0;
     316             : 
     317           0 :   virtual const FEProblemBase & miProblem() const { return _fe_problem; }
     318           0 :   virtual FEProblemBase & miProblem() { return _fe_problem; }
     319             : 
     320             :   virtual const QBase & qRule() const = 0;
     321             : 
     322             :   /**
     323             :    * Check whether a material property is active
     324             :    */
     325        5128 :   bool isPropertyActive(const unsigned int prop_id) const
     326             :   {
     327        5128 :     return _active_prop_ids.count(prop_id) > 0;
     328             :   }
     329             : 
     330             :   SubProblem & _subproblem;
     331             : 
     332             :   FEProblemBase & _fe_problem;
     333             :   THREAD_ID _tid;
     334             :   Assembly & _assembly;
     335             : 
     336             :   unsigned int _qp;
     337             : 
     338             :   const MooseArray<Real> & _coord;
     339             :   /// normals at quadrature points (valid only in boundary materials)
     340             :   const MooseArray<Point> & _normals;
     341             : 
     342             :   MooseMesh & _mesh;
     343             : 
     344             :   /// Coordinate system
     345             :   const Moose::CoordinateSystemType & _coord_sys;
     346             : 
     347             :   /// Set of properties accessed via get method
     348             :   std::set<std::string> _requested_props;
     349             : 
     350             :   /// Set of properties declared
     351             :   std::set<std::string> _supplied_props;
     352             : 
     353             :   /// The ids of the supplied properties, i.e. the indices where they
     354             :   /// are stored in the _material_data->props().  Note: these ids ARE
     355             :   /// NOT IN THE SAME ORDER AS THE _supplied_props set, which is
     356             :   /// ordered alphabetically by name.  The intention of this container
     357             :   /// is to allow rapid copying of MaterialProperty values in
     358             :   /// MaterialBase::computeProperties() without looking up the ids from
     359             :   /// the name strings each time.
     360             :   std::set<unsigned int> _supplied_prop_ids;
     361             : 
     362             :   /// The ids of the current active supplied properties
     363             :   std::unordered_set<unsigned int> _active_prop_ids;
     364             : 
     365             :   /// If False MOOSE does not compute this property
     366             :   const bool _compute;
     367             : 
     368             :   enum QP_Data_Type
     369             :   {
     370             :     CURR,
     371             :     PREV
     372             :   };
     373             : 
     374             :   /// The minimum states requested (0 = current, 1 = old, 2 = older)
     375             :   /// This is sparse and is used to keep track of whether or not stateful
     376             :   /// properties are requested without state 0 being requested
     377             :   std::unordered_map<unsigned int, unsigned int> _props_to_min_states;
     378             : 
     379             :   /// Small helper function to call store{Subdomain,Boundary}MatPropName
     380             :   void registerPropName(const std::string & prop_name, bool is_get, const unsigned int state);
     381             : 
     382             :   /// Check and throw an error if the execution has progressed past the construction stage
     383             :   void checkExecutionStage();
     384             : 
     385             :   std::vector<unsigned int> _displacements;
     386             : 
     387             :   bool _has_stateful_property;
     388             : 
     389             :   bool _overrides_init_stateful_props = true;
     390             : 
     391             :   const FaceInfo * _face_info = nullptr;
     392             : 
     393             :   /// Suffix to append to the name of the material property/ies when declaring it/them
     394             :   const MaterialPropertyName _declare_suffix;
     395             : 
     396             : private:
     397             :   /**
     398             :    * Helper method for adding a material property name to the material property requested set
     399             :    */
     400             :   void markMatPropRequested(const std::string & name);
     401             : 
     402             :   /**
     403             :    * Adds to a map based on block ids of material properties for which a zero
     404             :    * value can be returned. These properties are optional and will not trigger a
     405             :    * missing material property error.
     406             :    *
     407             :    * @param block_id The block id for the MaterialProperty
     408             :    * @param name The name of the property
     409             :    */
     410             :   void storeSubdomainZeroMatProp(SubdomainID block_id, const MaterialPropertyName & name);
     411             : 
     412             :   /**
     413             :    * Adds to a map based on boundary ids of material properties for which a zero
     414             :    * value can be returned. These properties are optional and will not trigger a
     415             :    * missing material property error.
     416             :    *
     417             :    * @param boundary_id The block id for the MaterialProperty
     418             :    * @param name The name of the property
     419             :    */
     420             :   void storeBoundaryZeroMatProp(BoundaryID boundary_id, const MaterialPropertyName & name);
     421             : 
     422             :   /**
     423             :    * @return The maximum number of quadrature points in use on any element in this problem.
     424             :    */
     425             :   unsigned int getMaxQps() const;
     426             : 
     427             :   /// Whether or not to force stateful init; see forceStatefulInit()
     428             :   const bool _force_stateful_init;
     429             : 
     430             :   /// To let it access the declaration suffix
     431             :   friend class FunctorMaterial;
     432             : };
     433             : 
     434             : template <typename T>
     435             : MaterialProperty<T> &
     436       39457 : MaterialBase::declareProperty(const std::string & name)
     437             : {
     438             :   // Check if the supplied parameter is a valid input parameter key
     439       39457 :   std::string prop_name = name;
     440       39457 :   if (_pars.have_parameter<MaterialPropertyName>(name))
     441         693 :     prop_name = _pars.get<MaterialPropertyName>(name);
     442             : 
     443       78914 :   return declarePropertyByName<T>(prop_name);
     444       39457 : }
     445             : 
     446             : template <typename T, bool is_ad>
     447             : GenericMaterialProperty<T, is_ad> &
     448       60396 : MaterialBase::declareGenericPropertyByName(const std::string & prop_name)
     449             : {
     450      120987 :   const auto prop_name_modified =
     451       60396 :       _declare_suffix.empty()
     452       60396 :           ? prop_name
     453       60981 :           : MooseUtils::join(std::vector<std::string>({prop_name, _declare_suffix}), "_");
     454             : 
     455             :   // Call this before so that the ID is valid
     456       60396 :   auto & prop = materialData().declareProperty<T, is_ad>(prop_name_modified, *this);
     457             : 
     458       60396 :   registerPropName(prop_name_modified, false, 0);
     459       60396 :   return prop;
     460       60591 : }
     461             : 
     462             : template <typename T, bool is_ad>
     463             : const GenericMaterialProperty<T, is_ad> &
     464        4023 : MaterialBase::getGenericZeroMaterialProperty(const std::string & name)
     465             : {
     466             :   // Check if the supplied parameter is a valid input parameter key
     467        4023 :   std::string prop_name = name;
     468        4023 :   if (_pars.have_parameter<MaterialPropertyName>(name))
     469           0 :     prop_name = _pars.get<MaterialPropertyName>(name);
     470             : 
     471        8046 :   return getGenericZeroMaterialPropertyByName<T, is_ad>(prop_name);
     472        4023 : }
     473             : 
     474             : template <typename T, bool is_ad>
     475             : const GenericMaterialProperty<T, is_ad> &
     476        8727 : MaterialBase::getGenericZeroMaterialPropertyByName(const std::string & prop_name)
     477             : {
     478        8727 :   checkExecutionStage();
     479        8727 :   auto & preload_with_zero = materialData().getProperty<T, is_ad>(prop_name, 0, *this);
     480             : 
     481        8727 :   _requested_props.insert(prop_name);
     482        8727 :   registerPropName(prop_name, true, 0);
     483        8727 :   markMatPropRequested(prop_name);
     484             : 
     485             :   // Register this material on these blocks and boundaries as a zero property with relaxed
     486             :   // consistency checking
     487       17454 :   for (std::set<SubdomainID>::const_iterator it = blockIDs().begin(); it != blockIDs().end(); ++it)
     488        8727 :     storeSubdomainZeroMatProp(*it, prop_name);
     489       17454 :   for (std::set<BoundaryID>::const_iterator it = boundaryIDs().begin(); it != boundaryIDs().end();
     490        8727 :        ++it)
     491        8727 :     storeBoundaryZeroMatProp(*it, prop_name);
     492             : 
     493             :   // set values for all qpoints to zero
     494             :   // (in multiapp scenarios getMaxQps can return different values in each app; we need the max)
     495        8727 :   unsigned int nqp = getMaxQps();
     496        8727 :   if (nqp > preload_with_zero.size())
     497        6879 :     preload_with_zero.resize(nqp);
     498       48393 :   for (unsigned int qp = 0; qp < nqp; ++qp)
     499       39666 :     MathUtils::mooseSetToZero(preload_with_zero[qp]);
     500             : 
     501        8727 :   return preload_with_zero;
     502             : }
     503             : 
     504             : template <typename T, bool is_ad>
     505             : const GenericMaterialProperty<T, is_ad> &
     506         540 : MaterialBase::getGenericZeroMaterialProperty()
     507             : {
     508             :   // static zero property storage
     509         540 :   static GenericMaterialProperty<T, is_ad> zero(MaterialPropertyInterface::zero_property_id);
     510             : 
     511             :   // resize to accomodate maximum number of qpoints
     512             :   // (in multiapp scenarios getMaxQps can return different values in each app; we need the max)
     513         540 :   unsigned int nqp = getMaxQps();
     514         540 :   if (nqp > zero.size())
     515          26 :     zero.resize(nqp);
     516             : 
     517             :   // set values for all qpoints to zero
     518        2700 :   for (unsigned int qp = 0; qp < nqp; ++qp)
     519        2160 :     MathUtils::mooseSetToZero(zero[qp]);
     520             : 
     521         540 :   return zero;
     522             : }
     523             : 
     524             : template <typename T>
     525             : ADMaterialProperty<T> &
     526       11257 : MaterialBase::declareADProperty(const std::string & name)
     527             : {
     528             :   // Check if the supplied parameter is a valid input parameter key
     529       11257 :   std::string prop_name = name;
     530       11257 :   if (_pars.have_parameter<MaterialPropertyName>(name))
     531         628 :     prop_name = _pars.get<MaterialPropertyName>(name);
     532             : 
     533       22514 :   return declareADPropertyByName<T>(prop_name);
     534       11257 : }
     535             : 
     536             : template <typename Consumers>
     537             : std::deque<MaterialBase *>
     538        3244 : MaterialBase::buildRequiredMaterials(const Consumers & mat_consumers,
     539             :                                      const std::vector<std::shared_ptr<MaterialBase>> & mats,
     540             :                                      const bool allow_stateful)
     541             : {
     542        3244 :   std::deque<MaterialBase *> required_mats;
     543             : 
     544        3244 :   std::unordered_set<unsigned int> needed_mat_props;
     545        6968 :   for (const auto & consumer : mat_consumers)
     546             :   {
     547        3724 :     const auto & mp_deps = consumer->getMatPropDependencies();
     548        3724 :     needed_mat_props.insert(mp_deps.begin(), mp_deps.end());
     549             :   }
     550             : 
     551             :   // A predicate of calling this function is that these materials come in already sorted by
     552             :   // dependency with the front of the container having no other material dependencies and following
     553             :   // materials potentially depending on the ones in front of them. So we can start at the back and
     554             :   // iterate forward checking whether the current material supplies anything that is needed, and if
     555             :   // not we discard it
     556       16538 :   for (auto it = mats.rbegin(); it != mats.rend(); ++it)
     557             :   {
     558       13294 :     auto * const mat = it->get();
     559       13294 :     bool supplies_needed = false;
     560             : 
     561       13294 :     const auto & supplied_props = mat->getSuppliedPropIDs();
     562             : 
     563             :     // Do O(N) with the small container
     564       40736 :     for (const auto supplied_prop : supplied_props)
     565             :     {
     566       30220 :       if (needed_mat_props.count(supplied_prop))
     567             :       {
     568        2778 :         supplies_needed = true;
     569        2778 :         break;
     570             :       }
     571             :     }
     572             : 
     573       13294 :     if (!supplies_needed)
     574       10516 :       continue;
     575             : 
     576        2778 :     if (!allow_stateful && mat->hasStatefulProperties())
     577           0 :       ::mooseError(
     578             :           "Someone called buildRequiredMaterials with allow_stateful = false but a material "
     579             :           "dependency ",
     580           0 :           mat->name(),
     581             :           " computes stateful properties.");
     582             : 
     583        2778 :     const auto & mp_deps = mat->getMatPropDependencies();
     584        2778 :     needed_mat_props.insert(mp_deps.begin(), mp_deps.end());
     585        2778 :     required_mats.push_front(mat);
     586             :   }
     587             : 
     588        6488 :   return required_mats;
     589        3244 : }

Generated by: LCOV version 1.14