https://mooseframework.inl.gov
GeneralSensorPostprocessor.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 #include <vector>
10 #include <cmath>
11 #include <algorithm>
12 #include <numeric>
13 
15 #include "Function.h"
16 #include "MooseRandom.h"
17 #include "LinearInterpolation.h"
18 #include "SplineInterpolation.h"
19 
21 
24 {
26  params.addRequiredParam<PostprocessorName>("input_signal", "The input signal postprocessor");
27  params.addParam<FunctionName>(
28  "drift_function", 0.0, "Drift function describing signal drift over time");
29  params.addParam<Real>("vector_size", 1000000000.0, "The maximum size of vector to be saved");
30  params.addClassDescription("This is a GeneralSensorPostprocessor, and functions as a base class "
31  "for other sensor postprocessors");
32  params.addParam<FunctionName>(
33  "efficiency_function", 0.8, "Efficiency function describing efficiency over time");
34  params.addParam<FunctionName>(
35  "noise_std_dev_function",
36  0.5,
37  "Standard deviation of noise function describing noise standard deviation over time");
38  params.addParam<FunctionName>(
39  "signalToNoise_function", 0.2, "Signal to noise ratio for the modeled sensor");
40  params.addParam<FunctionName>(
41  "delay_function", 0.1, "Delay function describing the delay over time");
42  params.addParam<FunctionName>(
43  "uncertainty_std_dev_function",
44  0.1,
45  "Standard deviation of uncertainty function describing uncertainty std dev over time");
46  params.addParam<FunctionName>("R_function", 1, "The function R for the integration term.");
47  params.addParam<Real>("proportional_weight", 1, "The weight assigned to the proportional term");
48  params.addParam<Real>("integral_weight", 0, "The weight assigned to the integral term");
49  params.addParam<unsigned int>("seed", 1, "Seed for the random number generator");
50  return params;
51 }
52 
54  : GeneralPostprocessor(parameters),
55  _input_signal(getPostprocessorValue("input_signal")),
56  _drift_function(getFunction("drift_function")),
57  _vector_size(getParam<Real>("vector_size")),
58  _pp_old(getPostprocessorValueOld("input_signal")),
59  _efficiency_function(getFunction("efficiency_function")),
60  _noise_std_dev_function(getFunction("noise_std_dev_function")),
61  _delay_function(getFunction("delay_function")),
62  _signalToNoise_function(getFunction("signalToNoise_function")),
63  _uncertainty_std_dev_function(getFunction("uncertainty_std_dev_function")),
64  _R_function(getFunction("R_function")),
65  _proportional_weight(getParam<Real>("proportional_weight")),
66  _integral_weight(getParam<Real>("integral_weight")),
67  _time_values(declareRestartableData<std::vector<Real>>("time_values")),
68  _input_signal_values(declareRestartableData<std::vector<Real>>("input_signal_values")),
69  _integrand(declareRestartableData<std::vector<Real>>("integrand")),
70  _R_function_values(declareRestartableData<std::vector<Real>>("R_function_values")),
71  _seed(getParam<unsigned int>("seed")),
72  _delay_value(0)
73 {
74 }
75 
76 void
78 {
79  Real drift_value = _drift_function.value(_t);
80  Real efficiency_value = _efficiency_function.value(_t);
81  Real signalToNoise_value = _signalToNoise_function.value(_t);
82  // setting seed for random number generator
83  _rng.seed(_seed);
84  Real noise_std_dev = _noise_std_dev_function.value(_t);
85  Real noise_value = _rng.randNormal(0, noise_std_dev);
86  Real uncertainty_std_dev = _uncertainty_std_dev_function.value(_t);
87  Real uncertainty_value = _rng.randNormal(0, uncertainty_std_dev);
88 
89  // if the problem is steady-state
90  if (!_fe_problem.isTransient())
91  {
92  // output
93  _sensor_value = drift_value +
94  efficiency_value * (_input_signal + signalToNoise_value * noise_value) +
95  uncertainty_value;
96  }
97 
98  // if the problem is transient
99  else
100  {
101  _time_values.push_back(_t);
103 
104  // Check if the size is greater than _vector_size
106  {
107  // Remove the first 10 elements if size is larger
108  _time_values.erase(_time_values.begin(), _time_values.begin() + 10);
110  }
111  Real _input_signal_delayed = getDelayedInputSignal();
112 
113  // computing integral term
114  Real term_for_integration = _input_signal + signalToNoise_value * noise_value;
115  _integrand.push_back(term_for_integration);
117 
118  // output
119  Real proportional_value = _input_signal_delayed + signalToNoise_value * noise_value;
120  _sensor_value = drift_value +
121  efficiency_value * (_proportional_weight * proportional_value +
123  uncertainty_value;
124  }
125 }
126 
129 {
130  return _sensor_value;
131 }
132 
133 std::vector<Real>
134 GeneralSensorPostprocessor::elementwiseMultiply(std::vector<Real> & vec1, std::vector<Real> & vec2)
135 {
136  // Ensure both vectors have the same size
137  mooseAssert(vec1.size() == vec2.size(),
138  "Vectors must have the same size for element-wise multiplication.");
139  // Create a result vector
140  std::vector<Real> result;
141  // Perform element-wise multiplication
142  result.reserve(vec1.size());
143  for (const auto i : index_range(vec1))
144  result.push_back(vec1[i] * vec2[i]);
145  return result;
146 }
147 
148 Real
150 {
151  // delayed input signal
152  Real t_desired = _t - _delay_value;
153  Real input_signal_delayed;
154 
155  if (t_desired < _time_values[0])
156  input_signal_delayed = 0;
157 
158  else if (t_desired == _time_values[0])
159  input_signal_delayed = _input_signal;
160 
161  // linear interpolation
162  else if (t_desired > _time_values[0] && t_desired <= _t && t_desired >= _t - _dt)
163  input_signal_delayed = _input_signal + (t_desired - _t) * (_pp_old - _input_signal) / (-_dt);
164 
165  else if (t_desired > _time_values[0] && t_desired < _t - _dt)
166  {
167  LinearInterpolation time_and_input_signal(_time_values, _input_signal_values);
168  input_signal_delayed = time_and_input_signal.sample(t_desired);
169  }
170 
171  else
172  mooseError("Unhandled case in interpolation values.");
173 
174  return input_signal_delayed;
175 }
176 
177 vector<Real>
179 {
181  return _R_function_values;
182 }
183 
184 Real
185 GeneralSensorPostprocessor::getIntegral(std::vector<Real> integrand)
186 {
187  Real integration_value;
188  getRVector();
189  // calculate the total integrand vector including previous integrand and exponential terms
191 
192  // if there are more than two datapoints, do simpson's 3/8 rule for integration
193  // else do trapezoidal rule
194  if (_time_values.size() > 2)
195  {
197  // number of intervals
198  Real n;
199 
200  // if number of datapoints is less than 30, use spline interpolation to get 30 intervals
201  if (_time_values.size() < 30)
202  n = 30;
203  else
204  {
205  n = _time_values.size();
206  // if interval is not a multiple of 3, make it
207  while (static_cast<int>(n) % 3 != 0)
208  n = n + 1;
209  }
210 
211  Real h = (_time_values.back() - _time_values[0]) / n; // distance between time values
212  // time vector for simpson integration
213  vector<Real> time_vec_simp;
214  // integrand vector for simpson integration
215  vector<Real> integrand_vec_simp;
216 
217  for (Real i = 0; i < n + 1; i++)
218  {
219  Real new_time = _time_values[0] + i * h;
220  time_vec_simp.push_back(new_time);
221  Real new_integrand = spline.SplineInterpolation::sample(new_time);
222  integrand_vec_simp.push_back(new_integrand);
223  }
224 
225  // initialize integral with endpoints
226  integration_value = integrand_vec_simp[0] + integrand_vec_simp[n];
227 
228  // Sum for points not at endpoints
229  for (int i = 1; i < n; ++i)
230  {
231  if (i % 3 == 0)
232  // Every third point
233  integration_value += 2 * integrand_vec_simp[i];
234  else
235  integration_value += 3 * integrand_vec_simp[i];
236  }
237 
238  // Multiply by 3h/8
239  integration_value *= (3 * h) / 8.0;
240  }
241 
242  else
243  {
244  // performing integration by trapezoidal rule, not accurate
245  // LinearInterpolation object with two vectors
247  // integrate the vectors
248  integration_value = integral.integrate();
249  }
250 
251  return integration_value;
252 }
const Function & _signalToNoise_function
Signal to noise function.
std::vector< Real > & _input_signal_values
Input Signal vector for calculating delay.
std::vector< Real > elementwiseMultiply(std::vector< Real > &vec1, std::vector< Real > &vec2)
Function for element-wise multiplication of vectors.
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
const Function & _uncertainty_std_dev_function
Uncertainty std dev function.
void seed(std::size_t i, unsigned int seed)
const Function & _efficiency_function
Efficiency function.
T sample(const T &x) const
virtual PostprocessorValue getValue() const override
virtual void initialize() override
void addRequiredParam(const std::string &name, const std::string &doc_string)
Real integrand(const Point &p)
Real randNormal(std::size_t i, Real mean, Real sigma)
const Function & _R_function
Function R for integration term.
registerMooseObject("MiscApp", GeneralSensorPostprocessor)
virtual vector< Real > getRVector()
Function to calculate R vector.
const Function & _drift_function
The drift function to be evaluated and returned.
static InputParameters validParams()
std::vector< Real > & _R_function_values
vector to store R function values
const Function & _noise_std_dev_function
Noise standard deviation function.
Real PostprocessorValue
Real getIntegral(std::vector< Real > integrand)
Function to calculate integral term.
std::vector< Real > & _integrand
Vector to store integrand data for numerical integration.
Real _sensor_value
for getValue() output
const Real _proportional_weight
A weighing factor for the proportional term.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const PostprocessorValue & _pp_old
The old value of the postprocessor.
Real _delay_value
Variable to store delay value.
FEProblemBase & _fe_problem
const PostprocessorValue & _input_signal
A postprocessor used as the sensor input signal.
void mooseError(Args &&... args) const
void addClassDescription(const std::string &doc_string)
std::vector< Real > & _time_values
Time vector for calculating delay.
virtual bool isTransient() const override
GeneralSensorPostprocessor(const InputParameters &parameters)
virtual Real value(Real t, const Point &p) const
Real _integration_value
the output of the integrand
A generalized sensor Postprocessor.
const Real _integral_weight
A weighing factor for the integral term.
void ErrorVector unsigned int
auto index_range(const T &sizable)
const Real _vector_size
Size of vector to be stored.
const unsigned int _seed
To get fixed seed random numbers.
static InputParameters validParams()
Real getDelayedInputSignal()
Function to calculate delayed input signal.