https://mooseframework.inl.gov
Loading...
Searching...
No Matches
EquilibriumConstantInterpolator.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
11#include "MooseError.h"
12#include "MooseUtils.h"
13#include "libmesh/utility.h"
14#include <memory> // std::make_unique
15
17 const std::vector<Real> & temperature,
18 const std::vector<Real> & logk,
19 const std::string type,
20 const Real no_value)
21 : LeastSquaresFitBase(), _linear_interp(nullptr)
22{
23 // The number of temperature points and logk points must be equal
24 if (temperature.size() != logk.size())
25 mooseError("The temperature and logk data sets must be equal in length in "
26 "EquilibriumConstantInterpolator");
27
28 // A value of 500.0 in logk signifies 'no value', so should not be used in the fit
29 std::vector<Real> useful_temperature, useful_logk;
30 for (unsigned int i = 0; i < temperature.size(); ++i)
31 if (!MooseUtils::absoluteFuzzyEqual(logk[i], no_value))
32 {
33 useful_temperature.push_back(temperature[i]);
34 useful_logk.push_back(logk[i]);
35 }
36
37 LeastSquaresFitBase::setVariables(useful_temperature, useful_logk);
38
39 // Set the type of fit
40 if (type == "fourth-order")
42 else if (type == "maier-kelly")
44 else if (type == "piecewise-linear")
45 {
47 try
48 {
49 _linear_interp = std::make_unique<LinearInterpolation>(useful_temperature, useful_logk);
50 }
51 catch (std::domain_error & e)
52 {
53 mooseError("EquilibriumConstantInterpolation: ", e.what());
54 }
55 }
56 else
57 mooseError("Type ", type, " is not supported in EquilibriumConstantInterpolator");
58
59 // Set the number of coefficients for the fit
60 if (useful_temperature.size() >= 5)
61 _num_coeff = 5;
62 else if (useful_temperature.size() >= 1 && _fit_type == FitTypeEnum::PIECEWISELINEAR)
63 _num_coeff = 2;
64 else
65 {
66 _num_coeff = 2;
68 }
69
70 // If the type is Maier-Kelly and the first temperature point is zero, suggest that
71 // the user should use a fourth-order polynomial
72 if (MooseUtils::absoluteFuzzyEqual(useful_temperature[0], 0.0) && type == "maier-kelly")
73 mooseError("A Maier-Kelly fit cannot be used when the temperature points include 0. Use a "
74 "fourth-order fit instead");
75}
76
77void
79{
80 const unsigned int num_rows = _x.size();
81 const unsigned int num_cols = _num_coeff;
82 _matrix.resize(num_rows * num_cols);
83
84 // Type of function depends on fit type
85 switch (_fit_type)
86 {
88 {
89 for (unsigned int row = 0; row < num_rows; ++row)
90 {
91 _matrix[row] = 1.0;
92 _matrix[num_rows + row] = _x[row];
93 _matrix[(2 * num_rows) + row] = Utility::pow<2>(_x[row]);
94 _matrix[(3 * num_rows) + row] = Utility::pow<3>(_x[row]);
95 _matrix[(4 * num_rows) + row] = Utility::pow<4>(_x[row]);
96 }
97 break;
98 }
99
101 {
102 for (unsigned int row = 0; row < num_rows; ++row)
103 {
104 _matrix[row] = std::log(_x[row]);
105 _matrix[num_rows + row] = 1.0;
106 _matrix[(2 * num_rows) + row] = _x[row];
107 _matrix[(3 * num_rows) + row] = 1.0 / _x[row];
108 _matrix[(4 * num_rows) + row] = 1.0 / Utility::pow<2>(_x[row]);
109 }
110 break;
111 }
112
114 break; // _matrix is not used in piecewiselinear
115
116 default: // FitTypeEnum::LINEAR
117 {
118 for (unsigned int row = 0; row < num_rows; ++row)
119 {
120 _matrix[row] = 1.0;
121 _matrix[num_rows + row] = _x[row];
122 }
123 break;
124 }
125 }
126}
127
128Real
130{
131 switch (_fit_type)
132 {
134 return _coeffs[0] + _coeffs[1] * T + _coeffs[2] * Utility::pow<2>(T) +
135 _coeffs[3] * Utility::pow<3>(T) + _coeffs[4] * Utility::pow<4>(T);
136
138 return _coeffs[0] * std::log(T) + _coeffs[1] + _coeffs[2] * T + _coeffs[3] / T +
139 _coeffs[4] / Utility::pow<2>(T);
140
142 return _linear_interp->sample(T);
143
144 default: // FitTypeEnum::LINEAR
145 return _coeffs[0] + _coeffs[1] * T;
146 }
147}
148
149Real
151{
152 switch (_fit_type)
153 {
155 return _coeffs[1] + 2.0 * _coeffs[2] * T + 3.0 * _coeffs[3] * Utility::pow<2>(T) +
156 4.0 * _coeffs[4] * Utility::pow<3>(T);
157
159 return _coeffs[0] / T + _coeffs[2] - _coeffs[3] / Utility::pow<2>(T) -
160 2.0 * _coeffs[4] / Utility::pow<3>(T);
161
163 return _linear_interp->sampleDerivative(T);
164
165 default: // FitTypeEnum::LINEAR:
166 return _coeffs[1];
167 }
168}
169
170ADReal
172{
173 using std::log;
174 switch (_fit_type)
175 {
177 return _coeffs[0] + _coeffs[1] * T + _coeffs[2] * Utility::pow<2>(T) +
178 _coeffs[3] * Utility::pow<3>(T) + _coeffs[4] * Utility::pow<4>(T);
179
181 return _coeffs[0] * log(T) + _coeffs[1] + _coeffs[2] * T + _coeffs[3] / T +
182 _coeffs[4] / Utility::pow<2>(T);
183
185 return _coeffs[0] + _coeffs[1] * T;
186
187 default:
188 mooseError("Dual cannot be used for specified fit type in EquilibriumConstantInterpolator");
189 }
190}
DualNumber< Real, DNDerivativeType, true > ADReal
const double T
void mooseError(Args &&... args)
enum EquilibriumConstantInterpolator::FitTypeEnum _fit_type
std::unique_ptr< LinearInterpolation > _linear_interp
helper object to perform the linear interpolation of the function data
Real sampleDerivative(Real T)
Sample derivative of function at temperature T.
EquilibriumConstantInterpolator(const std::vector< Real > &temperature, const std::vector< Real > &logk, const std::string type, const Real no_value=500.0)
std::vector< Real > _x
std::vector< Real > _coeffs
unsigned int _num_coeff
void setVariables(const std::vector< Real > &x, const std::vector< Real > &y)
std::vector< Real > _matrix