https://mooseframework.inl.gov
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 
77 void
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 
128 Real
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 
149 Real
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 
170 ADReal
172 {
173  switch (_fit_type)
174  {
176  return _coeffs[0] + _coeffs[1] * T + _coeffs[2] * Utility::pow<2>(T) +
177  _coeffs[3] * Utility::pow<3>(T) + _coeffs[4] * Utility::pow<4>(T);
178 
180  return _coeffs[0] * std::log(T) + _coeffs[1] + _coeffs[2] * T + _coeffs[3] / T +
181  _coeffs[4] / Utility::pow<2>(T);
182 
183  case FitTypeEnum::LINEAR:
184  return _coeffs[0] + _coeffs[1] * T;
185 
186  default:
187  mooseError("Dual cannot be used for specified fit type in EquilibriumConstantInterpolator");
188  }
189 }
bool absoluteFuzzyEqual(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
void mooseError(Args &&... args)
enum EquilibriumConstantInterpolator::FitTypeEnum _fit_type
static const std::string temperature
Definition: NS.h:59
std::unique_ptr< LinearInterpolation > _linear_interp
helper object to perform the linear interpolation of the function data
DualNumber< Real, DNDerivativeType, true > ADReal
unsigned int _num_coeff
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
void setVariables(const std::vector< Real > &x, const std::vector< Real > &y)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
std::vector< Real > _coeffs
std::vector< Real > _matrix