https://mooseframework.inl.gov
Loading...
Searching...
No Matches
DirectPerturbationReporter.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
12
14
17{
19 params.addClassDescription("Compute local sensitivities using the direct perturbation method.");
20
21 params.addRequiredParam<SamplerName>("sampler",
22 "Direct Perturbation sampler used to generate samples.");
23 params.addParam<std::vector<VectorPostprocessorName>>(
24 "vectorpostprocessors",
25 {},
26 "List of VectorPostprocessor(s) to utilize for sensitivity computations.");
27 params.addParam<std::vector<ReporterName>>(
28 "reporters", {}, "List of Reporter values to utilize for sensitivity computations.");
29
30 params.addParam<bool>("relative_sensitivity",
31 false,
32 "If the reporter should return relative or absolute sensitivities.");
33
34 return params;
35}
36
38 : GeneralReporter(parameters),
39 _sampler(getSampler<DirectPerturbationSampler>("sampler")),
40 _relative_sensitivity(getParam<bool>("relative_sensitivity")),
41 _initialized(false)
42{
43 if (getParam<std::vector<ReporterName>>("reporters").empty() &&
44 getParam<std::vector<VectorPostprocessorName>>("vectorpostprocessors").empty())
46 "The 'vectorpostprocessors' and/or 'reporters' parameters must be defined and non-empty.");
47}
48
49void
51{
52 // It is enough to do this once
53 if (_initialized)
54 return;
55
56 // Sensitivities from Reporters
57 std::vector<std::string> unsupported_types;
58 for (const auto & r_name : getParam<std::vector<ReporterName>>("reporters"))
59 {
60 if (hasReporterValueByName<std::vector<Real>>(r_name))
61 declareValueHelper<Real>(r_name);
62 else if (hasReporterValueByName<std::vector<std::vector<Real>>>(r_name))
63 declareValueHelper<std::vector<Real>>(r_name);
64 else
65 unsupported_types.push_back(r_name.getCombinedName());
66 }
67
68 if (!unsupported_types.empty())
69 paramError("reporters",
70 "The following reporter value(s) do not have a type supported by the "
71 "DirectPerturbationReporter:\n",
72 MooseUtils::join(unsupported_types, ", "));
73
74 // Sensitivities from VPPs
75 for (const auto & vpp_name :
76 getParam<std::vector<VectorPostprocessorName>>("vectorpostprocessors"))
77 for (const auto & vec_name :
79 declareValueHelper<Real>(ReporterName(vpp_name, vec_name));
80 _initialized = true;
81}
82
83template <typename DataType>
84void
86{
87 // We create a reporter value for the sensitivities based on the input
88 const auto & data = getReporterValueByName<std::vector<DataType>>(r_name);
89 const std::string s_name = r_name.getObjectName() + "_" + r_name.getValueName();
90 declareValueByName<std::vector<DataType>, DirectPerturbationReporterContext<DataType>>(
92}
93
94template <typename DataType>
96 const libMesh::ParallelObject & other,
97 const MooseObject & producer,
98 ReporterState<std::vector<DataType>> & state,
100 const std::vector<DataType> & data,
101 const bool relative_sensitivity)
102 : ReporterGeneralContext<std::vector<DataType>>(other, producer, state),
103 _sampler(sampler),
104 _data(data),
105 _relative_sensitivity(relative_sensitivity)
106{
107 this->_state.value().resize(_sampler.getNumberOfCols());
108}
109
110template <typename DataType>
111void
113{
114 const dof_id_type offset = _sampler.getLocalRowBegin();
115 const dof_id_type num_columns = _sampler.getNumberOfCols();
116
117 // If we are computing the relative sensitivity, we will need
118 // the reference value. So the process that has that will communicate it
119 // to everybody. We reuse the initialization function for the reference
120 // value as well
121 // _data can be empty on a rank with zero local rows.
122 auto reference_value = _data.empty() ? DataType() : initializeDataType(_data[0]);
123 if (_relative_sensitivity)
124 {
125 // The reference point is sampler row 0, which is always local to rank 0.
126 if (this->processor_id() == 0)
127 reference_value = _data[0];
128 this->comm().broadcast(reference_value);
129 }
130
131 for (const auto param_i : make_range(num_columns))
132 {
133 // If we need relative coefficients we need to normalize the difference
134 const auto interval = _relative_sensitivity ? _sampler.getRelativeInterval(param_i)
135 : _sampler.getAbsoluteInterval(param_i);
136
137 dof_id_type left_i;
138 dof_id_type right_i;
139 // Depending on which method we use, the indices will change
140 if (_sampler.perturbationMethod() == "central_difference")
141 {
142 left_i = 2 * param_i + 1;
143 right_i = 2 * param_i + 2;
144 }
145 else
146 {
147 left_i = param_i + 1;
148 right_i = 0;
149 }
150
151 const bool left_i_in_owned_range =
152 _sampler.getLocalRowBegin() <= left_i && left_i < _sampler.getLocalRowEnd();
153 const bool right_i_in_owned_range =
154 _sampler.getLocalRowBegin() <= right_i && right_i < _sampler.getLocalRowEnd();
155
156 if (left_i_in_owned_range || right_i_in_owned_range)
157 {
158 const dof_id_type copy_i = left_i_in_owned_range ? left_i - offset : right_i - offset;
159 this->_state.value()[param_i] = initializeDataType(_data[copy_i]);
160 }
161
162 // We add the contribution from one side
163 if (left_i_in_owned_range)
164 addSensitivityContribution(
165 this->_state.value()[param_i], _data[left_i - offset], reference_value, interval);
166
167 // We add the contribution from the other side
168 if (right_i_in_owned_range)
169 addSensitivityContribution(
170 this->_state.value()[param_i], _data[right_i - offset], reference_value, -interval);
171 }
172
173 // We gather the contributions across all processors
174 this->vectorSum();
175}
176
177template <typename DataType>
178void
180 DataType & add_to,
181 const DataType & to_add,
182 const DataType & reference_value,
183 const Real interval) const
184{
185 // DataType is a numeric type that we can sum (excluding bool)
186 if constexpr (std::is_arithmetic<DataType>::value && !std::is_same<DataType, bool>::value)
187 {
188 add_to += to_add / (_relative_sensitivity ? interval * reference_value : interval);
189 return;
190 }
191 // DataType is a vector type
192 else if constexpr (is_std_vector<DataType>::value)
193 {
194 // It can still be anything in the vector elements, so we will check this later
195 using VectorValueType = typename DataType::value_type;
196
197 mooseAssert(add_to.size() == to_add.size(), "The vectors for summation have different sizes!");
198
199 // Check if the vector elements are of a numeric type
200 if constexpr (std::is_arithmetic<VectorValueType>::value &&
201 !std::is_same<VectorValueType, bool>::value)
202 {
203 for (const auto index : index_range(add_to))
204 add_to[index] +=
205 to_add[index] / (_relative_sensitivity ? interval * reference_value[index] : interval);
206 return;
207 }
208 // Check if the vector elements are also vectors
209 else if constexpr (is_std_vector<VectorValueType>::value)
210 {
211 // This is as deep as we will go for now
212 using InnerValueType = typename VectorValueType::value_type;
213
214 // Check if the inner vector elements are of a numeric type
215 if constexpr (std::is_arithmetic<InnerValueType>::value &&
216 !std::is_same<InnerValueType, bool>::value)
217 {
218 // Iterate over each inner vector in the outer vector
219 for (auto & inner_index : index_range(add_to))
220 {
221 mooseAssert(add_to[inner_index].size() == to_add[inner_index].size(),
222 "The vectors for summation have different sizes!");
223 for (const auto index : index_range(add_to[inner_index]))
224 add_to[inner_index][index] +=
225 to_add[inner_index][index] /
226 (_relative_sensitivity ? interval * reference_value[inner_index][index] : interval);
227 }
228 return;
229 }
230 else
231 static_assert(Moose::always_false<DataType>,
232 "Sensitivity coefficient computation is not implemented for the given type!");
233 }
234 }
235 else
236 static_assert(Moose::always_false<DataType>,
237 "Sensitivity coefficient computation is not implemented for the given type!");
238}
239
240template <typename DataType>
241DataType
243 const DataType & example_output) const
244{
245 // DataType is a numeric type so we just return 0
246 if constexpr (std::is_arithmetic<DataType>::value && !std::is_same<DataType, bool>::value)
247 return 0.0;
248 // DataType is a vector type
249 else if constexpr (is_std_vector<DataType>::value)
250 {
251 // It can still be anything in the vector elements, so we will check this later
252 using VectorValueType = typename DataType::value_type;
253
254 // Check if the vector elements are of a numeric type
255 if constexpr (std::is_arithmetic<VectorValueType>::value &&
256 !std::is_same<VectorValueType, bool>::value)
257 return std::vector<VectorValueType>(example_output.size(), 0);
258 // Check if the vector elements are also vectors
259 else if constexpr (is_std_vector<VectorValueType>::value)
260 {
261 // This is as deep as we will go for now
262 using InnerValueType = typename VectorValueType::value_type;
263
264 // Check if the inner vector elements are of a numeric type
265 if constexpr (std::is_arithmetic<InnerValueType>::value &&
266 !std::is_same<InnerValueType, bool>::value)
267 {
268 auto return_vector = std::vector<VectorValueType>(example_output.size());
269 // Iterate over each inner vector in the outer vector
270 for (auto & inner_index : index_range(example_output))
271 return_vector[inner_index].resize(example_output.size(), 0.0);
272 return return_vector;
273 }
274 }
275 else
276 static_assert(Moose::always_false<DataType>,
277 "Sensitivity coefficient computation is not implemented for the given type!");
278 }
279 else
280 static_assert(Moose::always_false<DataType>,
281 "Sensitivity coefficient initialization is not implemented for the given type!");
282}
registerMooseObject("StochasticToolsApp", DirectPerturbationReporter)
const ReporterMode REPORTER_MODE_ROOT
Reporter context for computing direct perturbation-based sensitivity coefficients.
DirectPerturbationSampler & _sampler
Reference to the direct perturbation sampler.
DirectPerturbationReporterContext(const libMesh::ParallelObject &other, const MooseObject &producer, ReporterState< std::vector< DataType > > &state, DirectPerturbationSampler &sampler, const std::vector< DataType > &data, const bool relative_sensitivity)
Constructor.
void addSensitivityContribution(DataType &add_to, const DataType &to_add, const DataType &reference_value, const Real interval) const
Compute direct perturbation sensitivity, split into a separate function due to the different operator...
DataType initializeDataType(const DataType &example_output) const
Initialize the sensitivity container, split into a separate function due to the different constructor...
Reporter class for computing and displaying local sensitivity coefficients around a nominal value usi...
DirectPerturbationSampler & _sampler
Direct perturbation sampler.
const bool _relative_sensitivity
If relative sensitivity should be computed.
DirectPerturbationReporter(const InputParameters &parameters)
static InputParameters validParams()
void declareValueHelper(const ReporterName &r_name)
Helper for adding direct perturbation-based reporter values.
bool _initialized
Whether or not initialize() has been called for reporter value declaration.
virtual void initialize() override final
A class used to generate samples for a direct perturbation analysis.
const VectorPostprocessor & getVectorPostprocessorObjectByName(const std::string &object_name, const THREAD_ID tid=0) const
static InputParameters validParams()
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
void paramError(const std::string &param, Args... args) const
void mooseError(Args &&... args) const
const T & getParam(const std::string &name) const
bool hasReporterValueByName(const ReporterName &reporter_name) const
const std::string & getObjectName() const
const std::string & getValueName() const
T & value(const std::size_t time_index=0)
dof_id_type getNumberOfCols() const
FEProblemBase & _fe_problem
const std::set< std::string > & getVectorNames() const