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 : // 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"
20 : #include "SymmetricRankFourTensor.h"
21 : #include "MooseEnum.h"
22 : #include "MooseVariableConstMonomial.h"
23 : #include "FunctorMaterial.h"
24 : #include "VariableSizeMaterialPropertiesInterface.h"
25 :
26 : #include "libmesh/utility.h"
27 :
28 : registerMooseAction("MooseApp", MaterialOutputAction, "add_output_aux_variables");
29 : registerMooseAction("MooseApp", MaterialOutputAction, "add_aux_kernel");
30 :
31 : InputParameters
32 69279 : MaterialOutputAction::validParams()
33 : {
34 69279 : InputParameters params = Action::validParams();
35 69279 : params.addClassDescription("Outputs material properties to various Outputs objects, based on the "
36 : "parameters set in each Material");
37 : /// A flag to tell this action whether or not to print the unsupported properties
38 : /// Note: A derived class can set this to false, override materialOutput and output
39 : /// a particular property that is not supported by this class.
40 207837 : params.addPrivateParam("print_unsupported_prop_names", true);
41 138558 : params.addParam<bool>("print_automatic_aux_variable_creation",
42 138558 : true,
43 : "Flag to print list of aux variables created for automatic output by "
44 : "MaterialOutputAction.");
45 69279 : return params;
46 0 : }
47 :
48 69074 : MaterialOutputAction::MaterialOutputAction(const InputParameters & params)
49 : : Action(params),
50 69074 : _block_material_data(nullptr),
51 69074 : _boundary_material_data(nullptr),
52 69074 : _output_warehouse(_app.getOutputWarehouse()),
53 138148 : _output_only_on_timestep_end(_app.parameters().get<bool>("use_legacy_material_output"))
54 : {
55 69074 : }
56 :
57 : void
58 126204 : MaterialOutputAction::act()
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 378612 : if (!_app.actionWarehouse().hasActions("add_output"))
65 0 : return;
66 :
67 126204 : 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)
71 126204 : _block_material_data = &_problem->getMaterialData(Moose::BLOCK_MATERIAL_DATA);
72 126204 : _boundary_material_data = &_problem->getMaterialData(Moose::BOUNDARY_MATERIAL_DATA);
73 :
74 : // A complete list of all MaterialBase objects
75 126204 : 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 126204 : bool outputs_has_properties = false;
83 126204 : std::set<std::string> output_object_properties;
84 :
85 252408 : const auto & output_actions = _app.actionWarehouse().getActionListByName("add_output");
86 745726 : for (const auto & act : output_actions)
87 : {
88 : // Extract the Output action
89 619522 : AddOutputAction * action = dynamic_cast<AddOutputAction *>(act);
90 619522 : if (!action)
91 129812 : continue;
92 :
93 : // Add the material property names from the output object parameters to the list of properties
94 : // to output
95 489710 : InputParameters & params = action->getObjectParams();
96 2036288 : if (params.isParamValid("output_material_properties") &&
97 567158 : params.get<bool>("output_material_properties"))
98 : {
99 134 : outputs_has_properties = true;
100 : std::vector<std::string> prop_names =
101 134 : params.get<std::vector<std::string>>("show_material_properties");
102 134 : output_object_properties.insert(prop_names.begin(), prop_names.end());
103 134 : }
104 : }
105 :
106 : // Loop through each material object
107 126204 : std::set<std::string> material_names;
108 126204 : std::set<std::string> unsupported_names;
109 156320 : for (const auto & mat : material_ptrs)
110 : {
111 : // Extract the names of the output objects to which the material properties will be exported
112 30120 : 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 60240 : mat->getParam<std::vector<std::string>>("output_properties");
117 :
118 : // Append the properties listed in the Outputs block
119 30120 : if (outputs_has_properties)
120 160 : 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 30120 : _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 30120 : if (outputs_has_properties || outputs.find("none") == outputs.end())
135 : {
136 : // Get all material properties supplied by this material as a starting point
137 4580 : std::set<std::string> names = mat->getSuppliedItems();
138 4580 : if (const auto fmat_ptr = dynamic_cast<const FunctorMaterial *>(mat.get()))
139 104 : names.insert(fmat_ptr->getSuppliedFunctors().begin(),
140 104 : fmat_ptr->getSuppliedFunctors().end());
141 :
142 18154 : 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 18464 : if (output_properties.empty() ||
147 4890 : std::find(output_properties.begin(), output_properties.end(), name) !=
148 18464 : output_properties.end())
149 : {
150 : // Add the material property for output
151 10612 : auto curr_material_names = materialOutput(name, *mat, get_names_only);
152 10612 : if (curr_material_names.size() == 0)
153 60 : unsupported_names.insert(name);
154 10612 : material_names.insert(curr_material_names.begin(), curr_material_names.end());
155 10612 : }
156 : }
157 : // If the material object has explicitly defined outputs, store the variables associated with
158 : // the output objects
159 4580 : if (outputs.find("none") == outputs.end())
160 : {
161 : // Get all available output names from OutputWarehouse that support material output
162 4420 : const auto & all_output_names = _output_warehouse.getAllMaterialPropertyOutputNames();
163 :
164 : // For reserved name "all", set outputs to match all available output names
165 4420 : if (outputs.find("all") != outputs.end())
166 2040 : 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 8764 : for (const auto & output_name : all_output_names)
171 : {
172 4344 : if (outputs.find(output_name) != outputs.end())
173 3029 : _material_variable_names_map[output_name].insert(_material_variable_names.begin(),
174 : _material_variable_names.end());
175 : else
176 1315 : _material_variable_names_map[output_name].insert({});
177 : }
178 4420 : }
179 4580 : }
180 25540 : else if (output_properties.size())
181 82 : mooseWarning("Material properties output specified is not created because 'outputs' is not "
182 : "set in the Material, and neither is output_material_properties in any of the "
183 : "outputs in the [Outputs] block");
184 30116 : }
185 126230 : if (unsupported_names.size() > 0 && get_names_only &&
186 126290 : getParam<bool>("print_unsupported_prop_names"))
187 : {
188 30 : std::ostringstream oss;
189 60 : for (const auto & name : unsupported_names)
190 30 : oss << "\n " << name;
191 60 : mooseWarning("The types for total ",
192 30 : unsupported_names.size(),
193 : " material properties:",
194 60 : oss.str(),
195 : "\nare not supported for automatic output by ",
196 30 : type(),
197 : ".");
198 30 : }
199 :
200 126200 : if (_current_task == "add_output_aux_variables")
201 : {
202 189774 : auto params = _factory.getValidParams("MooseVariableConstMonomial");
203 : // currently only elemental variables are supported for material property output
204 253032 : params.set<MooseEnum>("order") = "CONSTANT";
205 189774 : params.set<MooseEnum>("family") = "MONOMIAL";
206 :
207 : // Create the AuxVariables
208 63258 : std::ostringstream oss;
209 91895 : for (const auto & var_name : material_names)
210 : {
211 28641 : oss << "\n " << var_name;
212 28641 : if (_problem->hasVariable(var_name))
213 4 : mooseError("The material property output " + var_name +
214 : " has the same name as an existing variable, either use the material"
215 : " declare_suffix parameter to disambiguate or the output_properties parameter"
216 : " to restrict the material properties to output");
217 85911 : _problem->addAuxVariable("MooseVariableConstMonomial", var_name, params);
218 : }
219 :
220 66110 : if (material_names.size() > 0 && getParam<bool>("print_automatic_aux_variable_creation"))
221 1418 : _console << COLOR_CYAN << "The following total " << material_names.size()
222 2836 : << " aux variables:" << oss.str() << "\nare added for automatic output by " << type()
223 1418 : << "." << COLOR_DEFAULT << std::endl;
224 63254 : }
225 : else
226 : {
227 : // When a MaterialBase object has 'output_properties' defined all other properties not listed
228 : // must be added to the hide list for the output objects so that properties that are not desired
229 : // do not appear.
230 65640 : for (const auto & it : _material_variable_names_map)
231 : {
232 2698 : std::set<std::string> hide;
233 2698 : std::set_difference(material_names.begin(),
234 : material_names.end(),
235 : it.second.begin(),
236 : it.second.end(),
237 : std::inserter(hide, hide.begin()));
238 :
239 2698 : _output_warehouse.addInterfaceHideVariables(it.first, hide);
240 2698 : }
241 : }
242 126196 : }
243 :
244 : std::vector<std::string>
245 10612 : MaterialOutputAction::materialOutput(const std::string & property_name,
246 : const MaterialBase & material,
247 : bool get_names_only)
248 : {
249 10612 : std::vector<std::string> names;
250 :
251 : // Material Properties
252 10612 : if (hasProperty<Real>(property_name))
253 10452 : names = outputHelper(
254 5226 : {"MaterialRealAux", "", {}}, property_name, property_name, material, get_names_only);
255 :
256 5386 : else if (hasADProperty<Real>(property_name))
257 4636 : names = outputHelper(
258 2318 : {"ADMaterialRealAux", "", {}}, property_name, property_name, material, get_names_only);
259 :
260 3068 : else if (hasProperty<RealVectorValue>(property_name))
261 686 : names = outputHelper({"MaterialRealVectorValueAux", "xyz", {"component"}},
262 : property_name,
263 1372 : property_name + "_",
264 : material,
265 686 : get_names_only);
266 :
267 2382 : else if (hasADProperty<RealVectorValue>(property_name))
268 208 : names = outputHelper({"ADMaterialRealVectorValueAux", "xyz", {"component"}},
269 : property_name,
270 416 : property_name + "_",
271 : material,
272 208 : get_names_only);
273 :
274 2174 : else if (hasProperty<std::vector<Real>>(property_name))
275 112 : names = outputHelper({"MaterialStdVectorAux", "variable_size", {"index"}},
276 : property_name,
277 224 : property_name + "_",
278 : material,
279 112 : get_names_only);
280 :
281 2062 : else if (hasADProperty<std::vector<Real>>(property_name))
282 52 : names = outputHelper({"ADMaterialStdVectorAux", "variable_size", {"index"}},
283 : property_name,
284 104 : property_name + "_",
285 : material,
286 52 : get_names_only);
287 :
288 2010 : else if (hasProperty<RealTensorValue>(property_name))
289 452 : names = outputHelper({"MaterialRealTensorValueAux", "012", {"row", "column"}},
290 : property_name,
291 904 : property_name + "_",
292 : material,
293 452 : get_names_only);
294 :
295 1558 : else if (hasADProperty<RealTensorValue>(property_name))
296 26 : names = outputHelper({"ADMaterialRealTensorValueAux", "012", {"row", "column"}},
297 : property_name,
298 52 : property_name + "_",
299 : material,
300 26 : get_names_only);
301 :
302 1532 : else if (hasProperty<RankTwoTensor>(property_name))
303 344 : names = outputHelper({"MaterialRankTwoTensorAux", "012", {"i", "j"}},
304 : property_name,
305 688 : property_name + "_",
306 : material,
307 344 : get_names_only);
308 :
309 1188 : else if (hasADProperty<RankTwoTensor>(property_name))
310 78 : names = outputHelper({"ADMaterialRankTwoTensorAux", "012", {"i", "j"}},
311 : property_name,
312 156 : property_name + "_",
313 : material,
314 78 : get_names_only);
315 :
316 1110 : else if (hasProperty<RankFourTensor>(property_name))
317 292 : names = outputHelper({"MaterialRankFourTensorAux", "012", {"i", "j", "k", "l"}},
318 : property_name,
319 584 : property_name + "_",
320 : material,
321 292 : get_names_only);
322 :
323 818 : else if (hasADProperty<RankFourTensor>(property_name))
324 26 : names = outputHelper({"ADMaterialRankFourTensorAux", "012", {"i", "j", "k", "l"}},
325 : property_name,
326 52 : property_name + "_",
327 : material,
328 26 : get_names_only);
329 :
330 792 : else if (hasProperty<SymmetricRankTwoTensor>(property_name))
331 318 : names = outputHelper({"MaterialSymmetricRankTwoTensorAux", "012345", {"component"}},
332 : property_name,
333 636 : property_name + "_",
334 : material,
335 318 : get_names_only);
336 :
337 474 : else if (hasADProperty<SymmetricRankTwoTensor>(property_name))
338 52 : names = outputHelper({"ADMaterialSymmetricRankTwoTensorAux", "012345", {"component"}},
339 : property_name,
340 104 : property_name + "_",
341 : material,
342 52 : get_names_only);
343 :
344 422 : else if (hasProperty<SymmetricRankFourTensor>(property_name))
345 292 : names = outputHelper({"MaterialSymmetricRankFourTensorAux", "012345", {"i", "j"}},
346 : property_name,
347 584 : property_name + "_",
348 : material,
349 292 : get_names_only);
350 :
351 130 : else if (hasADProperty<SymmetricRankFourTensor>(property_name))
352 26 : names = outputHelper({"ADMaterialSymmetricRankFourTensorAux", "012345", {"i", "j"}},
353 : property_name,
354 52 : property_name + "_",
355 : material,
356 26 : get_names_only);
357 :
358 : // Functors
359 104 : else if (hasFunctorProperty<Real>(property_name))
360 52 : names = outputHelper({"FunctorMaterialRealAux", "", {}},
361 : property_name,
362 104 : property_name + "_out",
363 : material,
364 52 : get_names_only);
365 :
366 52 : else if (hasFunctorProperty<ADReal>(property_name))
367 0 : names = outputHelper({"ADFunctorMaterialRealAux", "", {}},
368 : property_name,
369 0 : property_name + "_out",
370 : material,
371 0 : get_names_only);
372 :
373 52 : else if (hasFunctorProperty<RealVectorValue>(property_name))
374 52 : names = outputHelper({"FunctorMaterialRealVectorValueAux", "xyz", {"component"}},
375 : property_name,
376 104 : property_name + "_out_",
377 : material,
378 52 : get_names_only);
379 :
380 0 : else if (hasFunctorProperty<ADRealVectorValue>(property_name))
381 0 : names = outputHelper({"ADFunctorMaterialRealVectorValueAux", "xyz", {"component"}},
382 : property_name,
383 0 : property_name + "_out_",
384 : material,
385 0 : get_names_only);
386 :
387 10612 : return names;
388 34852 : }
389 :
390 : std::vector<std::string>
391 10612 : MaterialOutputAction::outputHelper(const MaterialOutputAction::OutputMetaData & metadata,
392 : const std::string & property_name,
393 : const std::string & var_name_base,
394 : const MaterialBase & material,
395 : bool get_names_only)
396 : {
397 10612 : const auto & [kernel_name, index_symbols, param_names] = metadata;
398 10612 : const auto dim = param_names.size();
399 10612 : const auto size = index_symbols.size();
400 10612 : auto size_inner = size;
401 :
402 : // Handle the case the material property is of a variable input-defined size
403 10612 : bool variable_size = false;
404 10612 : std::string variable_size_symbols;
405 10612 : if (index_symbols == "variable_size")
406 : {
407 164 : variable_size = true;
408 164 : size_inner = 0;
409 164 : const auto * const vsmi =
410 164 : dynamic_cast<const VariableSizeMaterialPropertiesInterface *>(&material);
411 164 : if (vsmi)
412 104 : size_inner = vsmi->getVectorPropertySize(property_name);
413 :
414 164 : if (!size_inner)
415 : {
416 60 : mooseWarning("Vector material property '" + property_name + "' will not be output as we " +
417 : (vsmi ? "have a 0-size vector during the simulation setup."
418 : : "do not know the size of the vector at initialization. Add the "
419 : "'VariableSizeMaterialPropertiesInterface' as a base class of the "
420 : "Material defining the vector property and implement the "
421 : "get...Size(property_name) routine. Note that "
422 : "the size must be known during the simulation setup phase."));
423 60 : return {};
424 : }
425 : // Use indices as symbols
426 364 : for (const auto i : make_range(size_inner))
427 260 : variable_size_symbols += std::to_string(i);
428 : }
429 :
430 10552 : std::vector<std::string> names;
431 : // general 0 to 4 dimensional loop
432 : std::array<std::size_t, 4> i;
433 21740 : for (i[3] = 0; i[3] < (dim < 4 ? 1 : size); ++i[3])
434 24284 : for (i[2] = 0; i[2] < (dim < 3 ? 1 : size); ++i[2])
435 35306 : for (i[1] = 0; i[1] < (dim < 2 ? 1 : size); ++i[1])
436 80430 : for (i[0] = 0; i[0] < (dim < 1 ? 1 : size_inner); ++i[0])
437 : {
438 58220 : std::string var_name = var_name_base;
439 58220 : const auto & symbols = variable_size ? variable_size_symbols : index_symbols;
440 205666 : for (const auto j : make_range(dim))
441 147446 : var_name += Moose::stringify(symbols[i[j]]);
442 :
443 58220 : names.push_back(var_name);
444 :
445 58220 : if (!get_names_only)
446 : {
447 29084 : auto params = getParams(kernel_name, property_name, var_name, material);
448 102765 : for (const auto j : make_range(dim))
449 73681 : params.template set<unsigned int>(param_names[j]) = i[j];
450 29084 : _problem->addAuxKernel(kernel_name, material.name() + var_name, params);
451 29084 : }
452 58220 : }
453 10552 : return names;
454 10612 : }
455 :
456 : InputParameters
457 29084 : MaterialOutputAction::getParams(const std::string & type,
458 : const std::string & property_name,
459 : const std::string & variable_name,
460 : const MaterialBase & material)
461 : {
462 : // Append the list of output variables for the current material
463 29084 : _material_variable_names.insert(variable_name);
464 :
465 : // Set the action parameters
466 29084 : InputParameters params = _factory.getValidParams(type);
467 29084 : if (params.have_parameter<MaterialPropertyName>("property"))
468 86940 : params.set<MaterialPropertyName>("property") = property_name;
469 104 : else if (params.have_parameter<MooseFunctorName>("functor"))
470 312 : params.set<MooseFunctorName>("functor") = property_name;
471 : else
472 0 : mooseError("Internal error. AuxKernel has neither a `functor` nor a `property` parameter.");
473 :
474 87252 : params.set<AuxVariableName>("variable") = variable_name;
475 29084 : if (_output_only_on_timestep_end)
476 0 : params.set<ExecFlagEnum>("execute_on") = EXEC_TIMESTEP_END;
477 : else
478 116336 : params.set<ExecFlagEnum>("execute_on") = {EXEC_INITIAL, EXEC_TIMESTEP_END};
479 :
480 29084 : if (material.boundaryRestricted())
481 543 : params.set<std::vector<BoundaryName>>("boundary") = material.boundaryNames();
482 : else
483 86709 : params.set<std::vector<SubdomainName>>("block") = material.blocks();
484 :
485 29084 : return params;
486 29084 : }
|