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