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 "LeastSquaresFit.h"
11 : #include "VectorPostprocessorInterface.h"
12 : #include "PolynomialFit.h"
13 :
14 : registerMooseObject("MooseApp", LeastSquaresFit);
15 :
16 : InputParameters
17 14495 : LeastSquaresFit::validParams()
18 : {
19 14495 : InputParameters params = GeneralVectorPostprocessor::validParams();
20 :
21 14495 : params.addRequiredParam<VectorPostprocessorName>(
22 : "vectorpostprocessor",
23 : "The vectorpostprocessor on whose values we perform a least squares fit");
24 14495 : params.addRequiredParam<std::string>("x_name", "The name of the independent variable");
25 14495 : params.addRequiredParam<std::string>("y_name", "The name of the dependent variable");
26 14495 : params.addRequiredParam<unsigned int>("order", "The order of the polynomial fit");
27 43485 : params.addParam<bool>(
28 : "truncate_order",
29 28990 : true,
30 : "Truncate the order of the fitted polynomial if an insufficient number of data points are "
31 : "provided. If this is set to false, an error will be generated in that case.");
32 14495 : params.addParam<unsigned int>("num_samples", "The number of samples to be output");
33 43485 : params.addParam<Real>(
34 28990 : "x_scale", 1.0, "Value used to scale x values (scaling is done after shifting)");
35 43485 : params.addParam<Real>(
36 28990 : "x_shift", 0.0, "Value used to shift x values (shifting is done before scaling)");
37 43485 : params.addParam<Real>(
38 28990 : "y_scale", 1.0, "Value used to scale y values (scaling is done after shifting)");
39 43485 : params.addParam<Real>(
40 28990 : "y_shift", 0.0, "Value used to shift y values (shifting is done before scaling)");
41 14495 : params.addParam<Real>("sample_x_min", "The minimum x value of the of samples to be output");
42 14495 : params.addParam<Real>("sample_x_max", "The maximum x value of the of samples to be output");
43 14495 : MooseEnum output_type("Coefficients Samples", "Coefficients");
44 14495 : params.addParam<MooseEnum>(
45 28990 : "output", output_type, "The quantity to output. Options are: " + output_type.getRawNames());
46 14495 : params.addClassDescription("Performs a polynomial least squares fit on the data contained in "
47 : "another VectorPostprocessor");
48 :
49 28990 : return params;
50 14495 : }
51 :
52 115 : LeastSquaresFit::LeastSquaresFit(const InputParameters & parameters)
53 : : GeneralVectorPostprocessor(parameters),
54 115 : _vpp_name(getParam<VectorPostprocessorName>("vectorpostprocessor")),
55 115 : _order(parameters.get<unsigned int>("order")),
56 115 : _truncate_order(parameters.get<bool>("truncate_order")),
57 115 : _x_name(getParam<std::string>("x_name")),
58 115 : _y_name(getParam<std::string>("y_name")),
59 115 : _x_values(getVectorPostprocessorValue("vectorpostprocessor", _x_name)),
60 115 : _y_values(getVectorPostprocessorValue("vectorpostprocessor", _y_name)),
61 115 : _output_type(getParam<MooseEnum>("output")),
62 115 : _num_samples(0),
63 115 : _x_scale(parameters.get<Real>("x_scale")),
64 115 : _x_shift(parameters.get<Real>("x_shift")),
65 115 : _y_scale(parameters.get<Real>("y_scale")),
66 115 : _y_shift(parameters.get<Real>("y_shift")),
67 115 : _have_sample_x_min(isParamValid("sample_x_min")),
68 115 : _have_sample_x_max(isParamValid("sample_x_max")),
69 115 : _sample_x(NULL),
70 115 : _sample_y(NULL),
71 115 : _coeffs(NULL)
72 : {
73 115 : if (_output_type == "Samples")
74 : {
75 39 : if (isParamValid("num_samples"))
76 39 : _num_samples = getParam<unsigned int>("num_samples");
77 : else
78 0 : mooseError("In LeastSquaresFit num_samples parameter must be provided with output=Samples");
79 :
80 39 : if (_have_sample_x_min)
81 0 : _sample_x_min = getParam<Real>("sample_x_min");
82 39 : if (_have_sample_x_max)
83 0 : _sample_x_max = getParam<Real>("sample_x_max");
84 :
85 39 : _sample_x = &declareVector(_x_name);
86 39 : _sample_y = &declareVector(_y_name);
87 : }
88 : else
89 : {
90 76 : if (isParamValid("num_samples"))
91 0 : mooseWarning("In LeastSquaresFit num_samples parameter is unused with output=Coefficients");
92 76 : _coeffs = &declareVector("coefficients");
93 : }
94 :
95 115 : if (_output_type == "Samples")
96 : {
97 39 : _sample_x->resize(_num_samples);
98 39 : _sample_y->resize(_num_samples);
99 : }
100 : else
101 76 : _coeffs->resize(_order + 1);
102 115 : }
103 :
104 : void
105 109 : LeastSquaresFit::initialize()
106 : {
107 109 : if (_output_type == "Samples")
108 : {
109 36 : _sample_x->clear();
110 36 : _sample_y->clear();
111 : }
112 : else
113 73 : _coeffs->clear();
114 109 : }
115 :
116 : void
117 109 : LeastSquaresFit::execute()
118 : {
119 109 : if (_x_values.size() != _y_values.size())
120 0 : mooseError("Size of data in x_values and y_values must be equal");
121 109 : if (_x_values.size() == 0)
122 0 : mooseError("Size of data in x_values and y_values must be > 0");
123 :
124 : // Create a copy of _x_values that we can modify.
125 109 : std::vector<Real> x_values(_x_values.begin(), _x_values.end());
126 109 : std::vector<Real> y_values(_y_values.begin(), _y_values.end());
127 :
128 979 : for (MooseIndex(_x_values) i = 0; i < _x_values.size(); ++i)
129 : {
130 870 : x_values[i] = (x_values[i] + _x_shift) * _x_scale;
131 870 : y_values[i] = (y_values[i] + _y_shift) * _y_scale;
132 : }
133 :
134 109 : PolynomialFit pf(x_values, y_values, _order, _truncate_order);
135 105 : pf.generate();
136 :
137 105 : if (_output_type == "Samples")
138 : {
139 : Real x_min;
140 36 : if (_have_sample_x_min)
141 0 : x_min = _sample_x_min;
142 : else
143 36 : x_min = *(std::min_element(x_values.begin(), x_values.end()));
144 :
145 : Real x_max;
146 36 : if (_have_sample_x_max)
147 0 : x_max = _sample_x_max;
148 : else
149 36 : x_max = *(std::max_element(x_values.begin(), x_values.end()));
150 :
151 36 : Real x_span = x_max - x_min;
152 :
153 756 : for (unsigned int i = 0; i < _num_samples; ++i)
154 : {
155 720 : Real x = x_min + static_cast<Real>(i) / _num_samples * x_span;
156 720 : _sample_x->push_back(x);
157 720 : _sample_y->push_back(pf.sample(x));
158 : }
159 : }
160 : else
161 69 : *_coeffs = pf.getCoefficients();
162 105 : }
|