https://mooseframework.inl.gov
MaterialOutputAction.C
Go to the documentation of this file.
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 // MOOSE includes
11 #include "MaterialOutputAction.h"
12 #include "FEProblem.h"
13 #include "FEProblemBase.h"
14 #include "MooseApp.h"
15 #include "AddOutputAction.h"
16 #include "MaterialBase.h"
17 #include "RankTwoTensor.h"
18 #include "SymmetricRankTwoTensor.h"
19 #include "RankFourTensor.h"
21 #include "MooseEnum.h"
23 #include "FunctorMaterial.h"
25 
26 #include "libmesh/utility.h"
27 
28 registerMooseAction("MooseApp", MaterialOutputAction, "add_output_aux_variables");
29 registerMooseAction("MooseApp", MaterialOutputAction, "add_aux_kernel");
30 
33 {
35  params.addClassDescription("Outputs material properties to various Outputs objects, based on the "
36  "parameters set in each Material");
40  params.addPrivateParam("print_unsupported_prop_names", true);
41  params.addParam<bool>("print_automatic_aux_variable_creation",
42  true,
43  "Flag to print list of aux variables created for automatic output by "
44  "MaterialOutputAction.");
45  return params;
46 }
47 
49  : Action(params),
50  _block_material_data(nullptr),
51  _boundary_material_data(nullptr),
52  _output_warehouse(_app.getOutputWarehouse()),
53  _output_only_on_timestep_end(_app.parameters().get<bool>("use_legacy_material_output"))
54 {
55 }
56 
57 void
59 {
60  mooseAssert(_problem,
61  "FEProblemBase pointer is nullptr, it is needed for auto material property output");
62 
63  // Do nothing if the application does not have output
64  if (!_app.actionWarehouse().hasActions("add_output"))
65  return;
66 
67  bool get_names_only = _current_task == "add_output_aux_variables" ? true : false;
68 
69  // Set the pointers to the MaterialData objects (Note, these pointers are not available at
70  // construction)
73 
74  // A complete list of all MaterialBase objects
75  const auto & material_ptrs = _problem->getMaterialWarehouse().getObjects();
76 
77  // Handle setting of material property output in [Outputs] sub-blocks
78  // Output objects can enable material property output, the following code examines the parameters
79  // for each Output object and sets a flag if any Output object has output set and also builds a
80  // list if the
81  // properties are limited via the 'show_material_properties' parameters
82  bool outputs_has_properties = false;
83  std::set<std::string> output_object_properties;
84 
85  const auto & output_actions = _app.actionWarehouse().getActionListByName("add_output");
86  for (const auto & act : output_actions)
87  {
88  // Extract the Output action
89  AddOutputAction * action = dynamic_cast<AddOutputAction *>(act);
90  if (!action)
91  continue;
92 
93  // Add the material property names from the output object parameters to the list of properties
94  // to output
95  InputParameters & params = action->getObjectParams();
96  if (params.isParamValid("output_material_properties") &&
97  params.get<bool>("output_material_properties"))
98  {
99  outputs_has_properties = true;
100  std::vector<std::string> prop_names =
101  params.get<std::vector<std::string>>("show_material_properties");
102  output_object_properties.insert(prop_names.begin(), prop_names.end());
103  }
104  }
105 
106  // Loop through each material object
107  std::set<std::string> material_names;
108  std::set<std::string> unsupported_names;
109  for (const auto & mat : material_ptrs)
110  {
111  // Extract the names of the output objects to which the material properties will be exported
112  std::set<OutputName> outputs = mat->getOutputs();
113 
114  // Extract the property names that will actually be output
115  std::vector<std::string> output_properties =
116  mat->getParam<std::vector<std::string>>("output_properties");
117 
118  // Append the properties listed in the Outputs block
119  if (outputs_has_properties)
120  output_properties.insert(output_properties.end(),
121  output_object_properties.begin(),
122  output_object_properties.end());
123 
124  // Clear the list of variable names for the current material object, this list will be populated
125  // with all the
126  // variables names for the current material object and is needed for purposes of controlling the
127  // which output objects
128  // show the material property data
129  _material_variable_names.clear();
130 
131  // Create necessary outputs for the properties if:
132  // (1) The Outputs block has material output enabled
133  // (2) If the MaterialBase object itself has set the 'outputs' parameter
134  if (outputs_has_properties || outputs.find("none") == outputs.end())
135  {
136  // Get all material properties supplied by this material as a starting point
137  std::set<std::string> names = mat->getSuppliedItems();
138  if (const auto fmat_ptr = dynamic_cast<const FunctorMaterial *>(mat.get()))
139  names.insert(fmat_ptr->getSuppliedFunctors().begin(),
140  fmat_ptr->getSuppliedFunctors().end());
141 
142  for (const auto & name : names)
143  {
144  // Output the property only if the name is contained in the 'output_properties'
145  // list or if the list is empty (all properties)
146  if (output_properties.empty() ||
147  std::find(output_properties.begin(), output_properties.end(), name) !=
148  output_properties.end())
149  {
150  // Add the material property for output
151  auto curr_material_names = materialOutput(name, *mat, get_names_only);
152  if (curr_material_names.size() == 0)
153  unsupported_names.insert(name);
154  material_names.insert(curr_material_names.begin(), curr_material_names.end());
155  }
156  }
157  // If the material object has explicitly defined outputs, store the variables associated with
158  // the output objects
159  if (outputs.find("none") == outputs.end())
160  {
161  // Get all available output names from OutputWarehouse that support material output
162  const auto & all_output_names = _output_warehouse.getAllMaterialPropertyOutputNames();
163 
164  // For reserved name "all", set outputs to match all available output names
165  if (outputs.find("all") != outputs.end())
166  outputs = all_output_names;
167 
168  // Iterate through all available output names and update _material_variable_names_map
169  // based on which of these output names are found in 'outputs' parameter
170  for (const auto & output_name : all_output_names)
171  {
172  if (outputs.find(output_name) != outputs.end())
173  _material_variable_names_map[output_name].insert(_material_variable_names.begin(),
175  else
176  _material_variable_names_map[output_name].insert({});
177  }
178  }
179  }
180  else if (output_properties.size())
181  mooseWarning("Material properties output specified is not created because 'outputs' is not "
182  "set in the Material, and neither is Outputs/output_material_properties");
183  }
184  if (unsupported_names.size() > 0 && get_names_only &&
185  getParam<bool>("print_unsupported_prop_names"))
186  {
187  std::ostringstream oss;
188  for (const auto & name : unsupported_names)
189  oss << "\n " << name;
190  mooseWarning("The types for total ",
191  unsupported_names.size(),
192  " material properties:",
193  oss.str(),
194  "\nare not supported for automatic output by ",
195  type(),
196  ".");
197  }
198 
199  if (_current_task == "add_output_aux_variables")
200  {
201  auto params = _factory.getValidParams("MooseVariableConstMonomial");
202  // currently only elemental variables are supported for material property output
203  params.set<MooseEnum>("order") = "CONSTANT";
204  params.set<MooseEnum>("family") = "MONOMIAL";
205 
206  // Create the AuxVariables
207  std::ostringstream oss;
208  for (const auto & var_name : material_names)
209  {
210  oss << "\n " << var_name;
211  if (_problem->hasVariable(var_name))
212  mooseError("The material property output " + var_name +
213  " has the same name as an existing variable, either use the material"
214  " declare_suffix parameter to disambiguate or the output_properties parameter"
215  " to restrict the material properties to output");
216  _problem->addAuxVariable("MooseVariableConstMonomial", var_name, params);
217  }
218 
219  if (material_names.size() > 0 && getParam<bool>("print_automatic_aux_variable_creation"))
220  _console << COLOR_CYAN << "The following total " << material_names.size()
221  << " aux variables:" << oss.str() << "\nare added for automatic output by " << type()
222  << "." << COLOR_DEFAULT << std::endl;
223  }
224  else
225  {
226  // When a MaterialBase object has 'output_properties' defined all other properties not listed
227  // must be added to the hide list for the output objects so that properties that are not desired
228  // do not appear.
229  for (const auto & it : _material_variable_names_map)
230  {
231  std::set<std::string> hide;
232  std::set_difference(material_names.begin(),
233  material_names.end(),
234  it.second.begin(),
235  it.second.end(),
236  std::inserter(hide, hide.begin()));
237 
239  }
240  }
241 }
242 
243 std::vector<std::string>
244 MaterialOutputAction::materialOutput(const std::string & property_name,
245  const MaterialBase & material,
246  bool get_names_only)
247 {
248  std::vector<std::string> names;
249 
250  // Material Properties
251  if (hasProperty<Real>(property_name))
252  names = outputHelper(
253  {"MaterialRealAux", "", {}}, property_name, property_name, material, get_names_only);
254 
255  else if (hasADProperty<Real>(property_name))
256  names = outputHelper(
257  {"ADMaterialRealAux", "", {}}, property_name, property_name, material, get_names_only);
258 
259  else if (hasProperty<RealVectorValue>(property_name))
260  names = outputHelper({"MaterialRealVectorValueAux", "xyz", {"component"}},
261  property_name,
262  property_name + "_",
263  material,
264  get_names_only);
265 
266  else if (hasADProperty<RealVectorValue>(property_name))
267  names = outputHelper({"ADMaterialRealVectorValueAux", "xyz", {"component"}},
268  property_name,
269  property_name + "_",
270  material,
271  get_names_only);
272 
273  else if (hasProperty<std::vector<Real>>(property_name))
274  names = outputHelper({"MaterialStdVectorAux", "variable_size", {"index"}},
275  property_name,
276  property_name + "_",
277  material,
278  get_names_only);
279 
280  else if (hasADProperty<std::vector<Real>>(property_name))
281  names = outputHelper({"ADMaterialStdVectorAux", "variable_size", {"index"}},
282  property_name,
283  property_name + "_",
284  material,
285  get_names_only);
286 
287  else if (hasProperty<RealTensorValue>(property_name))
288  names = outputHelper({"MaterialRealTensorValueAux", "012", {"row", "column"}},
289  property_name,
290  property_name + "_",
291  material,
292  get_names_only);
293 
294  else if (hasADProperty<RealTensorValue>(property_name))
295  names = outputHelper({"ADMaterialRealTensorValueAux", "012", {"row", "column"}},
296  property_name,
297  property_name + "_",
298  material,
299  get_names_only);
300 
301  else if (hasProperty<RankTwoTensor>(property_name))
302  names = outputHelper({"MaterialRankTwoTensorAux", "012", {"i", "j"}},
303  property_name,
304  property_name + "_",
305  material,
306  get_names_only);
307 
308  else if (hasADProperty<RankTwoTensor>(property_name))
309  names = outputHelper({"ADMaterialRankTwoTensorAux", "012", {"i", "j"}},
310  property_name,
311  property_name + "_",
312  material,
313  get_names_only);
314 
315  else if (hasProperty<RankFourTensor>(property_name))
316  names = outputHelper({"MaterialRankFourTensorAux", "012", {"i", "j", "k", "l"}},
317  property_name,
318  property_name + "_",
319  material,
320  get_names_only);
321 
322  else if (hasADProperty<RankFourTensor>(property_name))
323  names = outputHelper({"ADMaterialRankFourTensorAux", "012", {"i", "j", "k", "l"}},
324  property_name,
325  property_name + "_",
326  material,
327  get_names_only);
328 
329  else if (hasProperty<SymmetricRankTwoTensor>(property_name))
330  names = outputHelper({"MaterialSymmetricRankTwoTensorAux", "012345", {"component"}},
331  property_name,
332  property_name + "_",
333  material,
334  get_names_only);
335 
336  else if (hasADProperty<SymmetricRankTwoTensor>(property_name))
337  names = outputHelper({"ADMaterialSymmetricRankTwoTensorAux", "012345", {"component"}},
338  property_name,
339  property_name + "_",
340  material,
341  get_names_only);
342 
343  else if (hasProperty<SymmetricRankFourTensor>(property_name))
344  names = outputHelper({"MaterialSymmetricRankFourTensorAux", "012345", {"i", "j"}},
345  property_name,
346  property_name + "_",
347  material,
348  get_names_only);
349 
350  else if (hasADProperty<SymmetricRankFourTensor>(property_name))
351  names = outputHelper({"ADMaterialSymmetricRankFourTensorAux", "012345", {"i", "j"}},
352  property_name,
353  property_name + "_",
354  material,
355  get_names_only);
356 
357  // Functors
358  else if (hasFunctorProperty<Real>(property_name))
359  names = outputHelper({"FunctorMaterialRealAux", "", {}},
360  property_name,
361  property_name + "_out",
362  material,
363  get_names_only);
364 
365  else if (hasFunctorProperty<ADReal>(property_name))
366  names = outputHelper({"ADFunctorMaterialRealAux", "", {}},
367  property_name,
368  property_name + "_out",
369  material,
370  get_names_only);
371 
372  else if (hasFunctorProperty<RealVectorValue>(property_name))
373  names = outputHelper({"FunctorMaterialRealVectorValueAux", "xyz", {"component"}},
374  property_name,
375  property_name + "_out_",
376  material,
377  get_names_only);
378 
379  else if (hasFunctorProperty<ADRealVectorValue>(property_name))
380  names = outputHelper({"ADFunctorMaterialRealVectorValueAux", "xyz", {"component"}},
381  property_name,
382  property_name + "_out_",
383  material,
384  get_names_only);
385 
386  return names;
387 }
388 
389 std::vector<std::string>
391  const std::string & property_name,
392  const std::string & var_name_base,
393  const MaterialBase & material,
394  bool get_names_only)
395 {
396  const auto & [kernel_name, index_symbols, param_names] = metadata;
397  const auto dim = param_names.size();
398  const auto size = index_symbols.size();
399  auto size_inner = size;
400 
401  // Handle the case the material property is of a variable input-defined size
402  bool variable_size = false;
403  std::string variable_size_symbols;
404  if (index_symbols == "variable_size")
405  {
406  variable_size = true;
407  size_inner = 0;
408  const auto * const vsmi =
409  dynamic_cast<const VariableSizeMaterialPropertiesInterface *>(&material);
410  if (vsmi)
411  size_inner = vsmi->getVectorPropertySize(property_name);
412 
413  if (!size_inner)
414  {
415  mooseWarning("Vector material property '" + property_name + "' will not be output as we " +
416  (vsmi ? "have a 0-size vector during the simulation setup."
417  : "do not know the size of the vector at initialization. Add the "
418  "'VariableSizeMaterialPropertiesInterface' as a base class of the "
419  "Material defining the vector property and implement the "
420  "get...Size(property_name) routine. Note that "
421  "the size must be known during the simulation setup phase."));
422  return {};
423  }
424  // Use indices as symbols
425  for (const auto i : make_range(size_inner))
426  variable_size_symbols += std::to_string(i);
427  }
428 
429  std::vector<std::string> names;
430  // general 0 to 4 dimensional loop
431  std::array<std::size_t, 4> i;
432  for (i[3] = 0; i[3] < (dim < 4 ? 1 : size); ++i[3])
433  for (i[2] = 0; i[2] < (dim < 3 ? 1 : size); ++i[2])
434  for (i[1] = 0; i[1] < (dim < 2 ? 1 : size); ++i[1])
435  for (i[0] = 0; i[0] < (dim < 1 ? 1 : size_inner); ++i[0])
436  {
437  std::string var_name = var_name_base;
438  const auto & symbols = variable_size ? variable_size_symbols : index_symbols;
439  for (const auto j : make_range(dim))
440  var_name += Moose::stringify(symbols[i[j]]);
441 
442  names.push_back(var_name);
443 
444  if (!get_names_only)
445  {
446  auto params = getParams(kernel_name, property_name, var_name, material);
447  for (const auto j : make_range(dim))
448  params.template set<unsigned int>(param_names[j]) = i[j];
449  _problem->addAuxKernel(kernel_name, material.name() + var_name, params);
450  }
451  }
452  return names;
453 }
454 
456 MaterialOutputAction::getParams(const std::string & type,
457  const std::string & property_name,
458  const std::string & variable_name,
459  const MaterialBase & material)
460 {
461  // Append the list of output variables for the current material
462  _material_variable_names.insert(variable_name);
463 
464  // Set the action parameters
466  if (params.have_parameter<MaterialPropertyName>("property"))
467  params.set<MaterialPropertyName>("property") = property_name;
468  else if (params.have_parameter<MooseFunctorName>("functor"))
469  params.set<MooseFunctorName>("functor") = property_name;
470  else
471  mooseError("Internal error. AuxKernel has neither a `functor` nor a `property` parameter.");
472 
473  params.set<AuxVariableName>("variable") = variable_name;
475  params.set<ExecFlagEnum>("execute_on") = EXEC_TIMESTEP_END;
476  else
477  params.set<ExecFlagEnum>("execute_on") = {EXEC_INITIAL, EXEC_TIMESTEP_END};
478 
479  if (material.boundaryRestricted())
480  params.set<std::vector<BoundaryName>>("boundary") = material.boundaryNames();
481  else
482  params.set<std::vector<SubdomainName>>("block") = material.blocks();
483 
484  return params;
485 }
virtual std::vector< std::string > materialOutput(const std::string &property_name, const MaterialBase &material, bool get_names_only)
A function to be overriden by derived actions to handle a set of material property types...
std::map< OutputName, std::set< std::string > > _material_variable_names_map
Map of output names and list of variables associated with the output.
static InputParameters validParams()
unsigned int size(THREAD_ID tid=0) const
Return how many kernels we store in the current warehouse.
OutputWarehouse & _output_warehouse
Reference to the OutputWarehouse.
KOKKOS_INLINE_FUNCTION const T * find(const T &target, const T *const begin, const T *const end)
Find a value in an array.
Definition: KokkosUtils.h:30
A MultiMooseEnum object to hold "execute_on" flags.
Definition: ExecFlagEnum.h:21
virtual bool boundaryRestricted() const
Returns true if this object has been restricted to a boundary.
void addPrivateParam(const std::string &name, const T &value)
These method add a parameter to the InputParameters object which can be retrieved like any other para...
std::vector< std::pair< R1, R2 > > get(const std::string &param1, const std::string &param2) const
Combine two vector parameters into a single vector of pairs.
Factory & _factory
The Factory associated with the MooseApp.
T * get(const std::unique_ptr< T > &u)
The MooseUtils::get() specializations are used to support making forwards-compatible code changes fro...
Definition: MooseUtils.h:1133
T & set(const std::string &name, bool quiet_mode=false)
Returns a writable reference to the named parameters.
std::set< std::string > _material_variable_names
variables for the current MaterialBase object
InputParameters getValidParams(const std::string &name) const
Get valid parameters for the object.
Definition: Factory.C:68
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
Definition: Moose.h:159
const ExecFlagType EXEC_TIMESTEP_END
Definition: Moose.C:36
const std::list< Action * > & getActionListByName(const std::string &task) const
Retrieve a constant list of Action pointers associated with the passed in task.
Base class for actions.
Definition: Action.h:33
Creates AuxVariables and AuxKernels for automatic output of material properties.
std::set< OutputName > getAllMaterialPropertyOutputNames() const
Returns all output names that support material output.
Action for creating output objects.
const std::string & name() const
Get the name of the class.
Definition: MooseBase.h:103
static InputParameters validParams()
Definition: Action.C:26
InputParameters & getObjectParams()
Retrieve the parameters of the object to be created by this action.
InputParameters getParams(const std::string &type, const std::string &property_name, const std::string &variable_name, const MaterialBase &material)
A method for retrieving and partially filling the InputParameters object for an AuxVariable.
const std::string & type() const
Get the type of this class.
Definition: MooseBase.h:93
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:33
const std::string & _current_task
The current action (even though we have separate instances for each action)
Definition: Action.h:165
ActionWarehouse & actionWarehouse()
Return a writable reference to the ActionWarehouse associated with this app.
Definition: MooseApp.h:211
bool hasProperty(const std::string &property_name)
Helper method for testing if the material exists as a block or boundary material. ...
MooseApp & _app
The MOOSE application this is associated with.
Definition: MooseBase.h:357
std::string stringify(const T &t)
conversion to string
Definition: Conversion.h:64
virtual std::size_t getVectorPropertySize(const MaterialPropertyName &) const =0
Return the size of the variable size vector material property that the material defines.
bool have_parameter(std::string_view name) const
A wrapper around the Parameters base class method.
bool hasADProperty(const std::string &property_name)
Helper method for testing if the material exists as a block or boundary material. ...
MaterialOutputAction(const InputParameters &params)
Interface class to return the size of material properties that do not have a fixed size...
const MaterialData * _block_material_data
Pointer the MaterialData object storing the block restricted materials.
const std::vector< SubdomainName > & blocks() const
Return the block names for this object.
bool hasActions(const std::string &task) const
Check if Actions associated with passed in task exist.
void mooseWarning(Args &&... args) const
Emits a warning prefixed with object name and type.
Definition: MooseBase.h:299
IntRange< T > make_range(T beg, T end)
const bool _output_only_on_timestep_end
Output only on TIMESTEP_END, not on INITIAL?
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type and optionally a file path to the top-level block p...
Definition: MooseBase.h:271
void addClassDescription(const std::string &doc_string)
This method adds a description of the class that will be displayed in the input file syntax dump...
std::shared_ptr< FEProblemBase > & _problem
Convenience reference to a problem this action works on.
Definition: Action.h:171
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an optional parameter and a documentation string to the InputParameters object...
void addInterfaceHideVariables(const std::string &output_name, const std::set< std::string > &variable_names)
Insert variable names for hiding via the OutoutInterface.
virtual void act() override
Method to add objects to the simulation or perform other setup tasks.
const ConsoleStream _console
An instance of helper class to write streams to the Console objects.
std::vector< std::string > outputHelper(const OutputMetaData &metadata, const std::string &property_name, const std::string &var_name_base, const MaterialBase &material, bool get_names_only)
Universal output object setup function.
const std::vector< BoundaryName > & boundaryNames() const
Return the boundary names for this object.
Meta data describing the setup of an output object.
MaterialBases compute MaterialProperties.
Definition: MaterialBase.h:62
registerMooseAction("MooseApp", MaterialOutputAction, "add_output_aux_variables")
const MaterialData * _boundary_material_data
Pointer the MaterialData object storing the boundary restricted materials.
bool isParamValid(const std::string &name) const
This method returns parameters that have been initialized in one fashion or another, i.e.
const ExecFlagType EXEC_INITIAL
Definition: Moose.C:30