From b65eb706b78154a459d5a2139ccb524d32480cba Mon Sep 17 00:00:00 2001
From: Jesse Carter <jesse.carter@gmail.com>
Date: Fri, 17 Jan 2025 16:43:04 -0700
Subject: [PATCH 1/5] allow material property names to be passed to
 ElementMaterialSampler, closes #29705

---
 .../ElementMaterialSampler.C                  | 70 +++++++++-----
 ...ultiple_blocks_elem_ids_out_props_0001.csv |  9 ++
 ...ultiple_blocks_elem_ids_out_props_0002.csv |  9 ++
 ...sampler_multiple_blocks_out_props_0001.csv | 17 ++++
 ...sampler_multiple_blocks_out_props_0002.csv | 17 ++++
 .../gold/property_sampler_out_props_0001.csv  | 17 ++++
 .../gold/property_sampler_out_props_0002.csv  | 17 ++++
 .../property_sampler.i                        | 72 ++++++++++++++
 .../property_sampler_multiple_blocks.i        | 93 ++++++++++++++++++
 ...roperty_sampler_multiple_blocks_elem_ids.i | 94 +++++++++++++++++++
 .../element_material_sampler/tests            | 27 +++++-
 11 files changed, 419 insertions(+), 23 deletions(-)
 create mode 100644 test/tests/vectorpostprocessors/element_material_sampler/gold/property_sampler_multiple_blocks_elem_ids_out_props_0001.csv
 create mode 100644 test/tests/vectorpostprocessors/element_material_sampler/gold/property_sampler_multiple_blocks_elem_ids_out_props_0002.csv
 create mode 100644 test/tests/vectorpostprocessors/element_material_sampler/gold/property_sampler_multiple_blocks_out_props_0001.csv
 create mode 100644 test/tests/vectorpostprocessors/element_material_sampler/gold/property_sampler_multiple_blocks_out_props_0002.csv
 create mode 100644 test/tests/vectorpostprocessors/element_material_sampler/gold/property_sampler_out_props_0001.csv
 create mode 100644 test/tests/vectorpostprocessors/element_material_sampler/gold/property_sampler_out_props_0002.csv
 create mode 100644 test/tests/vectorpostprocessors/element_material_sampler/property_sampler.i
 create mode 100644 test/tests/vectorpostprocessors/element_material_sampler/property_sampler_multiple_blocks.i
 create mode 100644 test/tests/vectorpostprocessors/element_material_sampler/property_sampler_multiple_blocks_elem_ids.i

diff --git a/framework/src/vectorpostprocessors/ElementMaterialSampler.C b/framework/src/vectorpostprocessors/ElementMaterialSampler.C
index 4adb96a7205f..3ba0920e286e 100644
--- a/framework/src/vectorpostprocessors/ElementMaterialSampler.C
+++ b/framework/src/vectorpostprocessors/ElementMaterialSampler.C
@@ -26,10 +26,12 @@ InputParameters
 ElementMaterialSampler::validParams()
 {
   InputParameters params = ElementVectorPostprocessor::validParams();
-  params.addClassDescription("Records all Real-valued material properties of a material object on "
-                             "quadrature points on elements at the indicated execution points.");
-  params.addRequiredParam<MaterialName>("material",
+  params.addClassDescription("Records all Real-valued material properties of a material object, "
+                             "or Real-valued material properties of the supplied property names "
+                             "on quadrature points on elements at the indicated execution points.");
+  params.addParam<MaterialName>("material",
                                         "Material for which all properties will be recorded.");
+  params.addParam<std::vector<MaterialPropertyName>>("property", "Material property names that will be recorded.");
   params.addParam<std::vector<dof_id_type>>(
       "elem_ids",
       "Subset of element IDs to print data for. If omitted, all elements will be printed.");
@@ -44,35 +46,61 @@ ElementMaterialSampler::ElementMaterialSampler(const InputParameters & parameter
     _y_coords(declareVector("y")),
     _z_coords(declareVector("z"))
 {
-  auto & mat = getMaterialByName(getParam<MaterialName>("material"), true);
-  auto & prop_names = mat.getSuppliedItems();
-  if (mat.isBoundaryMaterial())
-    mooseError(name(), ": boundary materials (i.e. ", mat.name(), ") cannot be used");
+  // Check either "material" or "property" was set but not both
+  if (parameters.isParamSetByUser("material") && parameters.isParamSetByUser("property"))
+    mooseError("Setting both 'material' and 'property' is not allowed. Use one or the other.");
+  if (!parameters.isParamSetByUser("material") && !parameters.isParamSetByUser("property"))
+    mooseError("Either 'material' and 'property' needs to be set.");
+
+  // List of property names to collect
+  std::vector<MaterialName> prop_names;
 
   // Get list of elements from user
   if (parameters.isParamValid("elem_ids"))
   {
     const auto & ids = getParam<std::vector<dof_id_type>>("elem_ids");
     _elem_filter = std::set<dof_id_type>(ids.begin(), ids.end());
+  }
+
+  // If Material is used, get all properties.
+  if (parameters.isParamSetByUser("material"))
+  {
+    auto & mat = getMaterialByName(getParam<MaterialName>("material"), true);
+    if (mat.isBoundaryMaterial())
+      mooseError(name(), ": boundary materials (i.e. ", mat.name(), ") cannot be used");
 
-    // check requested materials are available
-    for (const auto & id : ids)
+    // Get property names from the Material
+    auto & props = mat.getSuppliedItems();  // returns std::set
+    prop_names = std::vector<MaterialName>(props.begin(), props.end());
+
+    // Check requested materials are available
+    if (_elem_filter)
     {
-      auto el = _mesh.getMesh().query_elem_ptr(id);
-
-      // We'd better have found the requested element on *some*
-      // processor.
-      bool found_elem = (el != nullptr);
-      this->comm().max(found_elem);
-
-      // We might not have el on this processor in a distributed mesh,
-      // but it should be somewhere and it ought to have a material
-      // defined for its subdomain
-      if (!found_elem || (el && !mat.hasBlocks(el->subdomain_id())))
-        mooseError(name(), ": material ", mat.name(), " is not defined on element ", id);
+      for (const auto & id : *_elem_filter)
+      {
+        auto el = _mesh.getMesh().query_elem_ptr(id);
+
+        // We'd better have found the requested element on *some*
+        // processor.
+        bool found_elem = (el != nullptr);
+        this->comm().max(found_elem);
+
+        // We might not have el on this processor in a distributed mesh,
+        // but it should be somewhere and it ought to have a material
+        // defined for its subdomain
+        if (!found_elem || (el && !mat.hasBlocks(el->subdomain_id())))
+          mooseError(name(), ": material ", mat.name(), " is not defined on element ", id);
+      }
     }
+
+  } else {
+
+    // Properties supplied by user
+    auto & props = getParam<std::vector<MaterialPropertyName>>("property");
+    prop_names = std::vector<MaterialName>(props.begin(), props.end());
   }
 
+  // Check properties are valid and store references
   for (auto & prop : prop_names)
   {
     if (hasMaterialProperty<Real>(prop))
diff --git a/test/tests/vectorpostprocessors/element_material_sampler/gold/property_sampler_multiple_blocks_elem_ids_out_props_0001.csv b/test/tests/vectorpostprocessors/element_material_sampler/gold/property_sampler_multiple_blocks_elem_ids_out_props_0001.csv
new file mode 100644
index 000000000000..0f2e1c38372a
--- /dev/null
+++ b/test/tests/vectorpostprocessors/element_material_sampler/gold/property_sampler_multiple_blocks_elem_ids_out_props_0001.csv
@@ -0,0 +1,9 @@
+elem_id,prop1,prop2,propt,propx,qp_id,x,y,z
+0,1,2,1,0.10566243270259,0,0.10566243270259,0.10566243270259,0
+0,1,2,1,0.39433756729741,1,0.39433756729741,0.10566243270259,0
+0,1,2,1,0.10566243270259,2,0.10566243270259,0.39433756729741,0
+0,1,2,1,0.39433756729741,3,0.39433756729741,0.39433756729741,0
+1,10,20,1,0.60566243270259,0,0.60566243270259,0.10566243270259,0
+1,10,20,1,0.89433756729741,1,0.89433756729741,0.10566243270259,0
+1,10,20,1,0.60566243270259,2,0.60566243270259,0.39433756729741,0
+1,10,20,1,0.89433756729741,3,0.89433756729741,0.39433756729741,0
diff --git a/test/tests/vectorpostprocessors/element_material_sampler/gold/property_sampler_multiple_blocks_elem_ids_out_props_0002.csv b/test/tests/vectorpostprocessors/element_material_sampler/gold/property_sampler_multiple_blocks_elem_ids_out_props_0002.csv
new file mode 100644
index 000000000000..0e53c20bffbd
--- /dev/null
+++ b/test/tests/vectorpostprocessors/element_material_sampler/gold/property_sampler_multiple_blocks_elem_ids_out_props_0002.csv
@@ -0,0 +1,9 @@
+elem_id,prop1,prop2,propt,propx,qp_id,x,y,z
+0,1,2,2,0.10566243270259,0,0.10566243270259,0.10566243270259,0
+0,1,2,2,0.39433756729741,1,0.39433756729741,0.10566243270259,0
+0,1,2,2,0.10566243270259,2,0.10566243270259,0.39433756729741,0
+0,1,2,2,0.39433756729741,3,0.39433756729741,0.39433756729741,0
+1,10,20,2,0.60566243270259,0,0.60566243270259,0.10566243270259,0
+1,10,20,2,0.89433756729741,1,0.89433756729741,0.10566243270259,0
+1,10,20,2,0.60566243270259,2,0.60566243270259,0.39433756729741,0
+1,10,20,2,0.89433756729741,3,0.89433756729741,0.39433756729741,0
diff --git a/test/tests/vectorpostprocessors/element_material_sampler/gold/property_sampler_multiple_blocks_out_props_0001.csv b/test/tests/vectorpostprocessors/element_material_sampler/gold/property_sampler_multiple_blocks_out_props_0001.csv
new file mode 100644
index 000000000000..6b2ff13f61cb
--- /dev/null
+++ b/test/tests/vectorpostprocessors/element_material_sampler/gold/property_sampler_multiple_blocks_out_props_0001.csv
@@ -0,0 +1,17 @@
+elem_id,prop1,prop2,propt,propx,qp_id,x,y,z
+0,1,2,1,0.10566243270259,0,0.10566243270259,0.10566243270259,0
+0,1,2,1,0.39433756729741,1,0.39433756729741,0.10566243270259,0
+0,1,2,1,0.10566243270259,2,0.10566243270259,0.39433756729741,0
+0,1,2,1,0.39433756729741,3,0.39433756729741,0.39433756729741,0
+1,10,20,1,0.60566243270259,0,0.60566243270259,0.10566243270259,0
+1,10,20,1,0.89433756729741,1,0.89433756729741,0.10566243270259,0
+1,10,20,1,0.60566243270259,2,0.60566243270259,0.39433756729741,0
+1,10,20,1,0.89433756729741,3,0.89433756729741,0.39433756729741,0
+2,1,2,1,0.10566243270259,0,0.10566243270259,0.60566243270259,0
+2,1,2,1,0.39433756729741,1,0.39433756729741,0.60566243270259,0
+2,1,2,1,0.10566243270259,2,0.10566243270259,0.89433756729741,0
+2,1,2,1,0.39433756729741,3,0.39433756729741,0.89433756729741,0
+3,10,20,1,0.60566243270259,0,0.60566243270259,0.60566243270259,0
+3,10,20,1,0.89433756729741,1,0.89433756729741,0.60566243270259,0
+3,10,20,1,0.60566243270259,2,0.60566243270259,0.89433756729741,0
+3,10,20,1,0.89433756729741,3,0.89433756729741,0.89433756729741,0
diff --git a/test/tests/vectorpostprocessors/element_material_sampler/gold/property_sampler_multiple_blocks_out_props_0002.csv b/test/tests/vectorpostprocessors/element_material_sampler/gold/property_sampler_multiple_blocks_out_props_0002.csv
new file mode 100644
index 000000000000..5a485962130b
--- /dev/null
+++ b/test/tests/vectorpostprocessors/element_material_sampler/gold/property_sampler_multiple_blocks_out_props_0002.csv
@@ -0,0 +1,17 @@
+elem_id,prop1,prop2,propt,propx,qp_id,x,y,z
+0,1,2,2,0.10566243270259,0,0.10566243270259,0.10566243270259,0
+0,1,2,2,0.39433756729741,1,0.39433756729741,0.10566243270259,0
+0,1,2,2,0.10566243270259,2,0.10566243270259,0.39433756729741,0
+0,1,2,2,0.39433756729741,3,0.39433756729741,0.39433756729741,0
+1,10,20,2,0.60566243270259,0,0.60566243270259,0.10566243270259,0
+1,10,20,2,0.89433756729741,1,0.89433756729741,0.10566243270259,0
+1,10,20,2,0.60566243270259,2,0.60566243270259,0.39433756729741,0
+1,10,20,2,0.89433756729741,3,0.89433756729741,0.39433756729741,0
+2,1,2,2,0.10566243270259,0,0.10566243270259,0.60566243270259,0
+2,1,2,2,0.39433756729741,1,0.39433756729741,0.60566243270259,0
+2,1,2,2,0.10566243270259,2,0.10566243270259,0.89433756729741,0
+2,1,2,2,0.39433756729741,3,0.39433756729741,0.89433756729741,0
+3,10,20,2,0.60566243270259,0,0.60566243270259,0.60566243270259,0
+3,10,20,2,0.89433756729741,1,0.89433756729741,0.60566243270259,0
+3,10,20,2,0.60566243270259,2,0.60566243270259,0.89433756729741,0
+3,10,20,2,0.89433756729741,3,0.89433756729741,0.89433756729741,0
diff --git a/test/tests/vectorpostprocessors/element_material_sampler/gold/property_sampler_out_props_0001.csv b/test/tests/vectorpostprocessors/element_material_sampler/gold/property_sampler_out_props_0001.csv
new file mode 100644
index 000000000000..af0e159a2361
--- /dev/null
+++ b/test/tests/vectorpostprocessors/element_material_sampler/gold/property_sampler_out_props_0001.csv
@@ -0,0 +1,17 @@
+elem_id,prop1,prop2,propt,qp_id,x,y,z
+0,1,2,1,0,0.10566243270259,0.10566243270259,0
+0,1,2,1,1,0.39433756729741,0.10566243270259,0
+0,1,2,1,2,0.10566243270259,0.39433756729741,0
+0,1,2,1,3,0.39433756729741,0.39433756729741,0
+1,1,2,1,0,0.60566243270259,0.10566243270259,0
+1,1,2,1,1,0.89433756729741,0.10566243270259,0
+1,1,2,1,2,0.60566243270259,0.39433756729741,0
+1,1,2,1,3,0.89433756729741,0.39433756729741,0
+2,1,2,1,0,0.10566243270259,0.60566243270259,0
+2,1,2,1,1,0.39433756729741,0.60566243270259,0
+2,1,2,1,2,0.10566243270259,0.89433756729741,0
+2,1,2,1,3,0.39433756729741,0.89433756729741,0
+3,1,2,1,0,0.60566243270259,0.60566243270259,0
+3,1,2,1,1,0.89433756729741,0.60566243270259,0
+3,1,2,1,2,0.60566243270259,0.89433756729741,0
+3,1,2,1,3,0.89433756729741,0.89433756729741,0
diff --git a/test/tests/vectorpostprocessors/element_material_sampler/gold/property_sampler_out_props_0002.csv b/test/tests/vectorpostprocessors/element_material_sampler/gold/property_sampler_out_props_0002.csv
new file mode 100644
index 000000000000..e3fb43bc8876
--- /dev/null
+++ b/test/tests/vectorpostprocessors/element_material_sampler/gold/property_sampler_out_props_0002.csv
@@ -0,0 +1,17 @@
+elem_id,prop1,prop2,propt,qp_id,x,y,z
+0,1,2,2,0,0.10566243270259,0.10566243270259,0
+0,1,2,2,1,0.39433756729741,0.10566243270259,0
+0,1,2,2,2,0.10566243270259,0.39433756729741,0
+0,1,2,2,3,0.39433756729741,0.39433756729741,0
+1,1,2,2,0,0.60566243270259,0.10566243270259,0
+1,1,2,2,1,0.89433756729741,0.10566243270259,0
+1,1,2,2,2,0.60566243270259,0.39433756729741,0
+1,1,2,2,3,0.89433756729741,0.39433756729741,0
+2,1,2,2,0,0.10566243270259,0.60566243270259,0
+2,1,2,2,1,0.39433756729741,0.60566243270259,0
+2,1,2,2,2,0.10566243270259,0.89433756729741,0
+2,1,2,2,3,0.39433756729741,0.89433756729741,0
+3,1,2,2,0,0.60566243270259,0.60566243270259,0
+3,1,2,2,1,0.89433756729741,0.60566243270259,0
+3,1,2,2,2,0.60566243270259,0.89433756729741,0
+3,1,2,2,3,0.89433756729741,0.89433756729741,0
diff --git a/test/tests/vectorpostprocessors/element_material_sampler/property_sampler.i b/test/tests/vectorpostprocessors/element_material_sampler/property_sampler.i
new file mode 100644
index 000000000000..771c460d833c
--- /dev/null
+++ b/test/tests/vectorpostprocessors/element_material_sampler/property_sampler.i
@@ -0,0 +1,72 @@
+[Mesh]
+  [gen]
+    type = GeneratedMeshGenerator
+    dim = 2
+    xmin = 0
+    xmax = 1
+    ymin = 0
+    ymax = 1
+    nx = 2
+    ny = 2
+  []
+[]
+
+[Variables]
+  [./u]
+  [../]
+[]
+
+[Kernels]
+  [./diff]
+    type = Diffusion
+    variable = u
+  [../]
+  [./time]
+    type = TimeDerivative
+    variable = u
+  [../]
+[]
+
+[BCs]
+  [./left]
+    type = DirichletBC
+    variable = u
+    boundary = left
+    value = 0
+  [../]
+  [./right]
+    type = DirichletBC
+    variable = u
+    boundary = right
+    value = 1
+  [../]
+[]
+
+[Materials]
+  [mat1]
+    type = GenericFunctionMaterial
+    prop_names = 'prop1 prop2 propt'
+    prop_values = '1 2 t'
+  []
+[]
+
+[Executioner]
+  type = Transient
+  num_steps = 2
+  dt = 1.0
+  solve_type = PJFNK
+  petsc_options_iname = '-pc_type -pc_hypre_type'
+  petsc_options_value = 'hypre boomeramg'
+[]
+
+[VectorPostprocessors]
+  [props]
+    type = ElementMaterialSampler
+    property = 'prop1 prop2 propt'
+    execute_on = 'initial timestep_end'
+  []
+[]
+
+[Outputs]
+  csv = true
+[]
diff --git a/test/tests/vectorpostprocessors/element_material_sampler/property_sampler_multiple_blocks.i b/test/tests/vectorpostprocessors/element_material_sampler/property_sampler_multiple_blocks.i
new file mode 100644
index 000000000000..a651fd76f8d0
--- /dev/null
+++ b/test/tests/vectorpostprocessors/element_material_sampler/property_sampler_multiple_blocks.i
@@ -0,0 +1,93 @@
+[Mesh]
+  [gen]
+    type = GeneratedMeshGenerator
+    dim = 2
+    xmin = 0
+    xmax = 1
+    ymin = 0
+    ymax = 1
+    nx = 2
+    ny = 2
+  []
+  [left]
+    type = ParsedSubdomainMeshGenerator
+    input = gen
+    combinatorial_geometry = 'x < 0.5'
+    block_id = 1
+    block_name = LEFT_SIDE
+  []
+  [right]
+    type = ParsedSubdomainMeshGenerator
+    input = left
+    combinatorial_geometry = 'x > 0.5'
+    block_id = 2
+    block_name = RIGHT_SIDE
+  []
+[]
+
+[Variables]
+  [./u]
+  [../]
+[]
+
+[Kernels]
+  [./diff]
+    type = Diffusion
+    variable = u
+  [../]
+  [./time]
+    type = TimeDerivative
+    variable = u
+  [../]
+[]
+
+[BCs]
+  [./left]
+    type = DirichletBC
+    variable = u
+    boundary = left
+    value = 0
+  [../]
+  [./right]
+    type = DirichletBC
+    variable = u
+    boundary = right
+    value = 1
+  [../]
+[]
+
+[Materials]
+  [mat1]
+    type = GenericFunctionMaterial
+    prop_names = 'prop1 prop2 propt propx'
+    prop_values = '1 2 t x'
+    block = 1
+  []
+  [mat2]
+    type = GenericFunctionMaterial
+    prop_names = 'prop1 prop2 propt propx'
+    prop_values = '10 20 t x'
+    block = 2
+  []
+[]
+
+[Executioner]
+  type = Transient
+  num_steps = 2
+  dt = 1.0
+  solve_type = PJFNK
+  petsc_options_iname = '-pc_type -pc_hypre_type'
+  petsc_options_value = 'hypre boomeramg'
+[]
+
+[VectorPostprocessors]
+  [props]
+    type = ElementMaterialSampler
+    property = 'prop1 prop2 propt propx'
+    execute_on = 'initial timestep_end'
+  []
+[]
+
+[Outputs]
+  csv = true
+[]
diff --git a/test/tests/vectorpostprocessors/element_material_sampler/property_sampler_multiple_blocks_elem_ids.i b/test/tests/vectorpostprocessors/element_material_sampler/property_sampler_multiple_blocks_elem_ids.i
new file mode 100644
index 000000000000..fd7f4af1b61c
--- /dev/null
+++ b/test/tests/vectorpostprocessors/element_material_sampler/property_sampler_multiple_blocks_elem_ids.i
@@ -0,0 +1,94 @@
+[Mesh]
+  [gen]
+    type = GeneratedMeshGenerator
+    dim = 2
+    xmin = 0
+    xmax = 1
+    ymin = 0
+    ymax = 1
+    nx = 2
+    ny = 2
+  []
+  [left]
+    type = ParsedSubdomainMeshGenerator
+    input = gen
+    combinatorial_geometry = 'x < 0.5'
+    block_id = 1
+    block_name = LEFT_SIDE
+  []
+  [right]
+    type = ParsedSubdomainMeshGenerator
+    input = left
+    combinatorial_geometry = 'x > 0.5'
+    block_id = 2
+    block_name = RIGHT_SIDE
+  []
+[]
+
+[Variables]
+  [./u]
+  [../]
+[]
+
+[Kernels]
+  [./diff]
+    type = Diffusion
+    variable = u
+  [../]
+  [./time]
+    type = TimeDerivative
+    variable = u
+  [../]
+[]
+
+[BCs]
+  [./left]
+    type = DirichletBC
+    variable = u
+    boundary = left
+    value = 0
+  [../]
+  [./right]
+    type = DirichletBC
+    variable = u
+    boundary = right
+    value = 1
+  [../]
+[]
+
+[Materials]
+  [mat1]
+    type = GenericFunctionMaterial
+    prop_names = 'prop1 prop2 propt propx'
+    prop_values = '1 2 t x'
+    block = 1
+  []
+  [mat2]
+    type = GenericFunctionMaterial
+    prop_names = 'prop1 prop2 propt propx'
+    prop_values = '10 20 t x'
+    block = 2
+  []
+[]
+
+[Executioner]
+  type = Transient
+  num_steps = 2
+  dt = 1.0
+  solve_type = PJFNK
+  petsc_options_iname = '-pc_type -pc_hypre_type'
+  petsc_options_value = 'hypre boomeramg'
+[]
+
+[VectorPostprocessors]
+  [props]
+    type = ElementMaterialSampler
+    property = 'prop1 prop2 propt propx'
+    elem_ids = '0 1'
+    execute_on = 'initial timestep_end'
+  []
+[]
+
+[Outputs]
+  csv = true
+[]
diff --git a/test/tests/vectorpostprocessors/element_material_sampler/tests b/test/tests/vectorpostprocessors/element_material_sampler/tests
index 08d007c95cab..ed1165f1a586 100644
--- a/test/tests/vectorpostprocessors/element_material_sampler/tests
+++ b/test/tests/vectorpostprocessors/element_material_sampler/tests
@@ -24,9 +24,32 @@
     csvdiff = 'all_elements_block_restricted_out_vpp_0001.csv all_elements_block_restricted_out_vpp_0002.csv'
 
     requirement = 'The system shall be able to output material properties calculated at quadrature '
-                  'points on all active elements within the specified subdomains.'  
+                  'points on all active elements within the specified subdomains.'
+  []
+  [material_properties]
+    type = 'CSVDiff'
+    input = 'property_sampler.i'
+    csvdiff = 'property_sampler_out_props_0001.csv property_sampler_out_props_0002.csv'
+
+    requirement = 'The system shall be able to output material properties calculated at quadrature '
+                  'points on all active elements when supplied with the property names.'
+  []
+  [material_properties_multiple_blocks]
+    type = 'CSVDiff'
+    input = 'property_sampler_multiple_blocks.i'
+    csvdiff = 'property_sampler_multiple_blocks_out_props_0001.csv property_sampler_multiple_blocks_out_props_0002.csv'
+
+    requirement = 'The system shall be able to output material properties calculated at quadrature '
+                  'points on all active elements when supplied with the property names defined on different blocks.'
+  []
+  [material_properties_multiple_blocks_elem_ids]
+    type = 'CSVDiff'
+    input = 'property_sampler_multiple_blocks_elem_ids.i'
+    csvdiff = 'property_sampler_multiple_blocks_elem_ids_out_props_0001.csv property_sampler_multiple_blocks_elem_ids_out_props_0002.csv'
+
+    requirement = 'The system shall be able to output material properties calculated at quadrature '
+                  'points on the given elements when supplied with the property names defined on different blocks.'
   []
-  
   [errors]
     requirement = 'The system shall issue an error if material output samples are attempted for '
                   'elements:'

From 427233eae769fefb88d9ab3a6f17b3e98a055dc9 Mon Sep 17 00:00:00 2001
From: Jesse Carter <jesse.carter@gmail.com>
Date: Fri, 17 Jan 2025 17:26:18 -0700
Subject: [PATCH 2/5] apply style changes, closes #29705

---
 .../vectorpostprocessors/ElementMaterialSampler.C   | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/framework/src/vectorpostprocessors/ElementMaterialSampler.C b/framework/src/vectorpostprocessors/ElementMaterialSampler.C
index 3ba0920e286e..b503d51c978e 100644
--- a/framework/src/vectorpostprocessors/ElementMaterialSampler.C
+++ b/framework/src/vectorpostprocessors/ElementMaterialSampler.C
@@ -29,9 +29,9 @@ ElementMaterialSampler::validParams()
   params.addClassDescription("Records all Real-valued material properties of a material object, "
                              "or Real-valued material properties of the supplied property names "
                              "on quadrature points on elements at the indicated execution points.");
-  params.addParam<MaterialName>("material",
-                                        "Material for which all properties will be recorded.");
-  params.addParam<std::vector<MaterialPropertyName>>("property", "Material property names that will be recorded.");
+  params.addParam<MaterialName>("material", "Material for which all properties will be recorded.");
+  params.addParam<std::vector<MaterialPropertyName>>(
+      "property", "Material property names that will be recorded.");
   params.addParam<std::vector<dof_id_type>>(
       "elem_ids",
       "Subset of element IDs to print data for. If omitted, all elements will be printed.");
@@ -70,7 +70,7 @@ ElementMaterialSampler::ElementMaterialSampler(const InputParameters & parameter
       mooseError(name(), ": boundary materials (i.e. ", mat.name(), ") cannot be used");
 
     // Get property names from the Material
-    auto & props = mat.getSuppliedItems();  // returns std::set
+    auto & props = mat.getSuppliedItems(); // returns std::set
     prop_names = std::vector<MaterialName>(props.begin(), props.end());
 
     // Check requested materials are available
@@ -92,8 +92,9 @@ ElementMaterialSampler::ElementMaterialSampler(const InputParameters & parameter
           mooseError(name(), ": material ", mat.name(), " is not defined on element ", id);
       }
     }
-
-  } else {
+  }
+  else
+  {
 
     // Properties supplied by user
     auto & props = getParam<std::vector<MaterialPropertyName>>("property");

From 0ab3a0eb8140d556ca7b27c56293af7237c338eb Mon Sep 17 00:00:00 2001
From: Jesse Carter <jesse.carter@gmail.com>
Date: Tue, 21 Jan 2025 07:23:38 -0700
Subject: [PATCH 3/5] disable mesh renumbering so distributed mesh tests don't
 diff, ref ##29705

---
 .../element_material_sampler/property_sampler.i                  | 1 +
 .../element_material_sampler/property_sampler_multiple_blocks.i  | 1 +
 .../property_sampler_multiple_blocks_elem_ids.i                  | 1 +
 3 files changed, 3 insertions(+)

diff --git a/test/tests/vectorpostprocessors/element_material_sampler/property_sampler.i b/test/tests/vectorpostprocessors/element_material_sampler/property_sampler.i
index 771c460d833c..a96238766f70 100644
--- a/test/tests/vectorpostprocessors/element_material_sampler/property_sampler.i
+++ b/test/tests/vectorpostprocessors/element_material_sampler/property_sampler.i
@@ -1,4 +1,5 @@
 [Mesh]
+  allow_renumbering = false
   [gen]
     type = GeneratedMeshGenerator
     dim = 2
diff --git a/test/tests/vectorpostprocessors/element_material_sampler/property_sampler_multiple_blocks.i b/test/tests/vectorpostprocessors/element_material_sampler/property_sampler_multiple_blocks.i
index a651fd76f8d0..02122333adac 100644
--- a/test/tests/vectorpostprocessors/element_material_sampler/property_sampler_multiple_blocks.i
+++ b/test/tests/vectorpostprocessors/element_material_sampler/property_sampler_multiple_blocks.i
@@ -1,4 +1,5 @@
 [Mesh]
+  allow_renumbering = false
   [gen]
     type = GeneratedMeshGenerator
     dim = 2
diff --git a/test/tests/vectorpostprocessors/element_material_sampler/property_sampler_multiple_blocks_elem_ids.i b/test/tests/vectorpostprocessors/element_material_sampler/property_sampler_multiple_blocks_elem_ids.i
index fd7f4af1b61c..689c5ff32153 100644
--- a/test/tests/vectorpostprocessors/element_material_sampler/property_sampler_multiple_blocks_elem_ids.i
+++ b/test/tests/vectorpostprocessors/element_material_sampler/property_sampler_multiple_blocks_elem_ids.i
@@ -1,4 +1,5 @@
 [Mesh]
+  allow_renumbering = false
   [gen]
     type = GeneratedMeshGenerator
     dim = 2

From b1c939f559c9314f8af4ba04c692553604f85eaf Mon Sep 17 00:00:00 2001
From: Jesse Carter <jesse.carter@gmail.com>
Date: Tue, 21 Jan 2025 07:26:43 -0700
Subject: [PATCH 4/5] test for failure when sampling property that does not
 exist on block, ref #29705

---
 .../element_material_sampler/tests                    | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/test/tests/vectorpostprocessors/element_material_sampler/tests b/test/tests/vectorpostprocessors/element_material_sampler/tests
index ed1165f1a586..3576b18dad8d 100644
--- a/test/tests/vectorpostprocessors/element_material_sampler/tests
+++ b/test/tests/vectorpostprocessors/element_material_sampler/tests
@@ -76,7 +76,16 @@
       cli_args = 'VectorPostprocessors/vpp/material=foo'
       expect_err = 'Unable to locate active object: foo'
 
-      detail = 'the material does not exist on the mesh.'
+      detail = 'the material does not exist on the mesh, or'
+    []
+
+    [block_restrict_property_sample]
+      type = 'RunException'
+      input = 'property_sampler_multiple_blocks.i'
+      cli_args = ' Materials/mat1/prop_names=prop1 Materials/mat1/prop_values=1 Materials/mat2/prop_names=prop2 Materials/mat2/prop_values=2 VectorPostprocessors/props/property=prop1'
+      expect_err = "Material property 'prop1', requested by 'props' is not defined on block RIGHT_SIDE"
+
+      detail = 'the property does not exist on the block.'
     []
   []
 []

From 2ca615ee472c0618f7a2b7c84e04f9b905f3267c Mon Sep 17 00:00:00 2001
From: Jesse Carter <jesse.carter@gmail.com>
Date: Tue, 21 Jan 2025 07:28:00 -0700
Subject: [PATCH 5/5] address review comments, ref #29705

---
 framework/src/vectorpostprocessors/ElementMaterialSampler.C | 6 +++---
 .../vectorpostprocessors/element_material_sampler/tests     | 6 +++---
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/framework/src/vectorpostprocessors/ElementMaterialSampler.C b/framework/src/vectorpostprocessors/ElementMaterialSampler.C
index b503d51c978e..95d919c2dd33 100644
--- a/framework/src/vectorpostprocessors/ElementMaterialSampler.C
+++ b/framework/src/vectorpostprocessors/ElementMaterialSampler.C
@@ -47,9 +47,9 @@ ElementMaterialSampler::ElementMaterialSampler(const InputParameters & parameter
     _z_coords(declareVector("z"))
 {
   // Check either "material" or "property" was set but not both
-  if (parameters.isParamSetByUser("material") && parameters.isParamSetByUser("property"))
+  if (parameters.isParamValid("material") && parameters.isParamValid("property"))
     mooseError("Setting both 'material' and 'property' is not allowed. Use one or the other.");
-  if (!parameters.isParamSetByUser("material") && !parameters.isParamSetByUser("property"))
+  if (!parameters.isParamValid("material") && !parameters.isParamValid("property"))
     mooseError("Either 'material' and 'property' needs to be set.");
 
   // List of property names to collect
@@ -63,7 +63,7 @@ ElementMaterialSampler::ElementMaterialSampler(const InputParameters & parameter
   }
 
   // If Material is used, get all properties.
-  if (parameters.isParamSetByUser("material"))
+  if (parameters.isParamValid("material"))
   {
     auto & mat = getMaterialByName(getParam<MaterialName>("material"), true);
     if (mat.isBoundaryMaterial())
diff --git a/test/tests/vectorpostprocessors/element_material_sampler/tests b/test/tests/vectorpostprocessors/element_material_sampler/tests
index 3576b18dad8d..fb46af183962 100644
--- a/test/tests/vectorpostprocessors/element_material_sampler/tests
+++ b/test/tests/vectorpostprocessors/element_material_sampler/tests
@@ -32,7 +32,7 @@
     csvdiff = 'property_sampler_out_props_0001.csv property_sampler_out_props_0002.csv'
 
     requirement = 'The system shall be able to output material properties calculated at quadrature '
-                  'points on all active elements when supplied with the property names.'
+                  'points, on all active elements, when supplied with the property names.'
   []
   [material_properties_multiple_blocks]
     type = 'CSVDiff'
@@ -40,7 +40,7 @@
     csvdiff = 'property_sampler_multiple_blocks_out_props_0001.csv property_sampler_multiple_blocks_out_props_0002.csv'
 
     requirement = 'The system shall be able to output material properties calculated at quadrature '
-                  'points on all active elements when supplied with the property names defined on different blocks.'
+                  'points, on all active elements, when supplied with the property names defined on different blocks.'
   []
   [material_properties_multiple_blocks_elem_ids]
     type = 'CSVDiff'
@@ -48,7 +48,7 @@
     csvdiff = 'property_sampler_multiple_blocks_elem_ids_out_props_0001.csv property_sampler_multiple_blocks_elem_ids_out_props_0002.csv'
 
     requirement = 'The system shall be able to output material properties calculated at quadrature '
-                  'points on the given elements when supplied with the property names defined on different blocks.'
+                  'points, on the given elements, when supplied with the property names defined on different blocks.'
   []
   [errors]
     requirement = 'The system shall issue an error if material output samples are attempted for '