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 : #include "ElementExtremeMaterialPropertyReporter.h" 11 : 12 : #include "metaphysicl/raw_type.h" 13 : #include "libmesh/parallel.h" 14 : #include "libmesh/parallel_algebra.h" 15 : 16 : #include <algorithm> 17 : #include <limits> 18 : 19 : registerMooseObject("MooseApp", ElementExtremeMaterialPropertyReporter); 20 : registerMooseObject("MooseApp", ADElementExtremeMaterialPropertyReporter); 21 : 22 : template <bool is_ad> 23 : InputParameters 24 6222 : ElementExtremeMaterialPropertyReporterTempl<is_ad>::validParams() 25 : { 26 6222 : InputParameters params = ElementReporter::validParams(); 27 : 28 24888 : params.addRequiredParam<MaterialPropertyName>("material_property", 29 : "Material property for which to find the extreme. " 30 : "The value of this property is always reported."); 31 24888 : MooseEnum type_options("max=0 min=1"); 32 24888 : params.addRequiredParam<MooseEnum>("value_type", 33 : type_options, 34 : "Type of extreme value to report: 'max' " 35 : "reports the maximum value and 'min' reports " 36 : "the minimum value."); 37 : 38 24888 : params.addParam<std::vector<MaterialPropertyName>>( 39 : "additional_reported_properties", 40 : {}, 41 : "Additional material properties reported at the location of the extreme value"); 42 6222 : params.addClassDescription( 43 : "Determines the location of the minimum or maximum value of a material property over a " 44 : "volume, and provides its coordinates and optionally other requested data at that location."); 45 : 46 12444 : return params; 47 6222 : } 48 : 49 : template <bool is_ad> 50 52 : ElementExtremeMaterialPropertyReporterTempl<is_ad>::ElementExtremeMaterialPropertyReporterTempl( 51 : const InputParameters & parameters) 52 : : ElementReporter(parameters), 53 52 : _mat_prop(getGenericMaterialProperty<Real, is_ad>("material_property")), 54 104 : _type(getParam<MooseEnum>("value_type").template getEnum<ExtremeType>()), 55 52 : _extreme_value(declareValueByName<Real>("extreme_value")), 56 52 : _coordinates(declareValueByName<Point>("coordinates")), 57 104 : _qp(0) 58 : { 59 : const auto & mat_prop_names = 60 104 : getParam<std::vector<MaterialPropertyName>>("additional_reported_properties"); 61 : // TODO: Add more options for the type of reported properties. Currently these have to be 62 : // either Real (if using the non-AD version of this, or ADReal if using the AD version). 63 : // ElementMaterialSampler can get multiple types (int, real, unsigned), maybe do 64 : // something like that and also get AD and non-AD verisons. 65 156 : for (const auto & mpn : mat_prop_names) 66 : { 67 104 : _additional_reported_properties.push_back(&getGenericMaterialPropertyByName<Real, is_ad>(mpn)); 68 104 : _additional_reported_property_values.push_back(&declareValueByName<Real>(mpn)); 69 : } 70 52 : } 71 : 72 : template <bool is_ad> 73 : void 74 48 : ElementExtremeMaterialPropertyReporterTempl<is_ad>::initialize() 75 : { 76 48 : switch (_type) 77 : { 78 24 : case ExtremeType::MAX: 79 24 : _extreme_value = -std::numeric_limits<Real>::max(); 80 24 : break; 81 : 82 24 : case ExtremeType::MIN: 83 24 : _extreme_value = std::numeric_limits<Real>::max(); 84 24 : break; 85 : } 86 48 : _coordinates = Point(0., 0., 0.); 87 144 : for (const auto i : index_range(_additional_reported_properties)) 88 96 : *_additional_reported_property_values[i] = 0.0; 89 48 : } 90 : 91 : template <bool is_ad> 92 : void 93 128 : ElementExtremeMaterialPropertyReporterTempl<is_ad>::execute() 94 : { 95 256 : for (_qp = 0; _qp < _qrule->n_points(); ++_qp) 96 128 : computeQpValue(); 97 128 : } 98 : 99 : template <bool is_ad> 100 : void 101 128 : ElementExtremeMaterialPropertyReporterTempl<is_ad>::computeQpValue() 102 : { 103 128 : const Real raw_mat_val = MetaPhysicL::raw_value(_mat_prop[_qp]); 104 128 : switch (_type) 105 : { 106 64 : case ExtremeType::MAX: 107 64 : if (raw_mat_val > _extreme_value) 108 : { 109 32 : _extreme_value = raw_mat_val; 110 32 : _coordinates = _q_point[_qp]; 111 96 : for (const auto i : index_range(_additional_reported_properties)) 112 64 : *_additional_reported_property_values[i] = 113 64 : MetaPhysicL::raw_value((*_additional_reported_properties[i])[_qp]); 114 : } 115 64 : break; 116 : 117 64 : case ExtremeType::MIN: 118 64 : if (raw_mat_val < _extreme_value) 119 : { 120 40 : _extreme_value = raw_mat_val; 121 40 : _coordinates = _q_point[_qp]; 122 120 : for (const auto i : index_range(_additional_reported_properties)) 123 80 : *_additional_reported_property_values[i] = 124 80 : MetaPhysicL::raw_value((*_additional_reported_properties[i])[_qp]); 125 : } 126 64 : break; 127 : } 128 128 : } 129 : 130 : template <bool is_ad> 131 : void 132 44 : ElementExtremeMaterialPropertyReporterTempl<is_ad>::finalize() 133 : { 134 44 : unsigned int rank = 0; 135 : 136 44 : switch (_type) 137 : { 138 22 : case ExtremeType::MAX: 139 22 : _communicator.maxloc(_extreme_value, rank); 140 22 : break; 141 22 : case ExtremeType::MIN: 142 22 : _communicator.minloc(_extreme_value, rank); 143 22 : break; 144 : } 145 : 146 44 : const auto prop_size = _additional_reported_property_values.size(); 147 44 : std::vector<Real> ev_rep_prop_vals(prop_size, 0.); 148 : 149 44 : _communicator.broadcast(_coordinates, rank); 150 44 : if (rank == processor_id()) 151 96 : for (const auto i : make_range(prop_size)) 152 64 : ev_rep_prop_vals[i] = *_additional_reported_property_values[i]; 153 44 : _communicator.broadcast(ev_rep_prop_vals, rank, /*identical_sizes=*/true); 154 132 : for (const auto i : make_range(prop_size)) 155 88 : *_additional_reported_property_values[i] = ev_rep_prop_vals[i]; 156 44 : } 157 : 158 : template <bool is_ad> 159 : void 160 4 : ElementExtremeMaterialPropertyReporterTempl<is_ad>::threadJoin(const UserObject & uo) 161 : { 162 4 : const auto & rpt = static_cast<const ElementExtremeMaterialPropertyReporterTempl<is_ad> &>(uo); 163 4 : const auto prop_size = _additional_reported_property_values.size(); 164 : 165 4 : switch (_type) 166 : { 167 2 : case ExtremeType::MAX: 168 2 : if (rpt._extreme_value > _extreme_value) 169 : { 170 0 : _extreme_value = rpt._extreme_value; 171 0 : _coordinates = rpt._coordinates; 172 0 : for (const auto i : make_range(prop_size)) 173 0 : *_additional_reported_property_values[i] = *(rpt._additional_reported_property_values[i]); 174 : } 175 2 : break; 176 : 177 2 : case ExtremeType::MIN: 178 2 : if (rpt._extreme_value < _extreme_value) 179 : { 180 0 : _extreme_value = rpt._extreme_value; 181 0 : _coordinates = rpt._coordinates; 182 0 : for (const auto i : make_range(prop_size)) 183 0 : *_additional_reported_property_values[i] = *(rpt._additional_reported_property_values[i]); 184 : } 185 2 : break; 186 : } 187 4 : } 188 : 189 : template class ElementExtremeMaterialPropertyReporterTempl<false>; 190 : template class ElementExtremeMaterialPropertyReporterTempl<true>;