Cantera
Install
User Guide
Examples
Reference
Develop
Community
4.0.0a2
Toggle main menu visibility
Loading...
Searching...
No Matches
funcs.cpp
Go to the documentation of this file.
1
//! @file funcs.cpp file containing miscellaneous numerical functions.
2
3
// This file is part of Cantera. See License.txt in the top-level directory or
4
// at https://cantera.org/license.txt for license and copyright information.
5
6
#include "
cantera/numerics/funcs.h
"
7
#include "
cantera/numerics/polyfit.h
"
8
#include "
cantera/base/ctexceptions.h
"
9
10
namespace
Cantera
11
{
12
13
double
linearInterp
(
double
x, span<const double> xpts, span<const double> fpts)
14
{
15
AssertThrowMsg
(!xpts.empty(),
"linearInterp"
,
"x data empty"
);
16
AssertThrowMsg
(!fpts.empty(),
"linearInterp"
,
"f(x) data empty"
);
17
AssertThrowMsg
(xpts.size() == fpts.size(),
"linearInterp"
,
18
"len(xpts) = {}, len(fpts) = {}"
, xpts.size(), fpts.size());
19
if
(x <= xpts[0]) {
20
return
fpts[0];
21
}
22
if
(x >= xpts.back()) {
23
return
fpts.back();
24
}
25
auto
loc = lower_bound(xpts.begin(), xpts.end(), x);
26
int
iloc = int(loc - xpts.begin()) - 1;
27
double
ff = fpts[iloc] +
28
(x - xpts[iloc])*(fpts[iloc + 1]
29
- fpts[iloc])/(xpts[iloc + 1] - xpts[iloc]);
30
return
ff;
31
}
32
33
double
trapezoidal
(
const
Eigen::ArrayXd& f,
const
Eigen::ArrayXd& x)
34
{
35
// check length
36
if
(f.size() != x.size()) {
37
throw
CanteraError
(
"trapezoidal"
,
38
"Vector lengths need to be the same."
);
39
}
40
// Vector of f(i+1) + f(i)
41
Eigen::VectorXd f_av = f.tail(f.size() - 1) + f.head(f.size() - 1);
42
// Vector of x(i+1) - x(i)
43
Eigen::VectorXd x_diff = x.tail(x.size() - 1) - x.head(x.size() - 1);
44
// check if the coordinate is a monotonically increase vector.
45
if
((x_diff.array() <= 0.0).any()) {
46
throw
CanteraError
(
"trapezoidal"
,
47
"x (coordinate) needs to be the monotonically increasing."
);
48
}
49
return
f_av.dot(x_diff) / 2.0;
50
}
51
52
//! Numerical integration of a function using Simpson's rule.
53
//! Only for odd number of points. This function is used only
54
//! by calling simpson.
55
/*!
56
* Vector x contains a monotonic sequence of grid points, and
57
* Vector f contains function values defined at these points.
58
* The size of x and f must be the same.
59
*
60
* @param f vector of function value
61
* @param x vector of function coordinate
62
*/
63
double
basicSimpson
(
const
Eigen::ArrayXd& f,
const
Eigen::ArrayXd& x)
64
{
65
if
(f.size() < 2) {
66
throw
CanteraError
(
"basicSimpson"
,
67
"Vector lengths need to be larger than two."
);
68
}
69
if
(f.size()%2 == 0) {
70
throw
CanteraError
(
"basicSimpson"
,
71
"Vector lengths need to be an odd number."
);
72
}
73
74
size_t
N = f.size() - 1;
75
Eigen::VectorXd h = x.tail(N) - x.head(N);
76
77
double
sum = 0.0;
78
for
(
size_t
i = 1; i < N; i+=2) {
79
double
h0 = h[i-1];
80
double
h1 = h[i];
81
double
hph = h1 + h0;
82
double
hdh = h1 / h0;
83
double
hmh = h1 * h0;
84
sum += (hph / 6.0) * (
85
(2.0 - hdh) * f[i - 1] + (pow(hph, 2) / hmh) * f[i] +
86
(2.0 - 1.0 / hdh) * f[i + 1]);
87
}
88
return
sum;
89
}
90
91
double
simpson
(
const
Eigen::ArrayXd& f,
const
Eigen::ArrayXd& x)
92
{
93
Eigen::ArrayXd h = x.tail(x.size() - 1) - x.head(x.size() - 1);
94
if
((h <= 0.0).any()) {
95
throw
CanteraError
(
"simpson"
,
96
"Values of x need to be positive and monotonically increasing."
);
97
}
98
if
(f.size() != x.size()) {
99
throw
CanteraError
(
"simpson"
,
"Vector lengths need to be the same."
);
100
}
101
102
if
(f.size()%2 == 1) {
103
return
basicSimpson
(f, x);
104
}
else
if
(f.size() == 2) {
105
return
0.5 * h[0] * (f[1] + f[0]);
106
}
else
{
107
size_t
N = f.size() - 1;
108
// pick first N-1 point for simpson
109
double
headSimps =
basicSimpson
(f.head(N), x.head(N));
110
// Use trapezoidal rules for the last interval
111
double
tailTrap = 0.5 * h[N-1] * (f[N] + f[N-1]);
112
return
headSimps + tailTrap;
113
}
114
}
115
116
double
numericalQuadrature
(
const
string
& method,
117
const
Eigen::ArrayXd& f,
118
const
Eigen::ArrayXd& x)
119
{
120
if
(method ==
"simpson"
) {
121
return
simpson
(f, x);
122
}
else
if
(method ==
"trapezoidal"
) {
123
return
trapezoidal
(f, x);
124
}
else
{
125
throw
CanteraError
(
"numericalQuadrature"
,
126
"Unknown method of numerical quadrature. "
127
"Please use 'simpson' or 'trapezoidal'"
);
128
}
129
}
130
131
}
Cantera::CanteraError
Base class for exceptions thrown by Cantera classes.
Definition
ctexceptions.h:66
ctexceptions.h
Definitions for the classes that are thrown when Cantera experiences an error condition (also contain...
funcs.h
Header for a file containing miscellaneous numerical functions.
AssertThrowMsg
#define AssertThrowMsg(expr, procedure,...)
Assertion must be true or an error is thrown.
Definition
ctexceptions.h:292
Cantera::numericalQuadrature
double numericalQuadrature(const string &method, const Eigen::ArrayXd &f, const Eigen::ArrayXd &x)
Numerical integration of a function.
Definition
funcs.cpp:116
Cantera::trapezoidal
double trapezoidal(const Eigen::ArrayXd &f, const Eigen::ArrayXd &x)
Numerical integration of a function using the trapezoidal rule.
Definition
funcs.cpp:33
Cantera::simpson
double simpson(const Eigen::ArrayXd &f, const Eigen::ArrayXd &x)
Numerical integration of a function using Simpson's rule with flexibility of taking odd and even numb...
Definition
funcs.cpp:91
Cantera::linearInterp
double linearInterp(double x, span< const double > xpts, span< const double > fpts)
Linearly interpolate a function defined on a discrete grid.
Definition
funcs.cpp:13
Cantera
Namespace for the Cantera kernel.
Definition
AnyMap.cpp:595
Cantera::basicSimpson
double basicSimpson(const Eigen::ArrayXd &f, const Eigen::ArrayXd &x)
Numerical integration of a function using Simpson's rule.
Definition
funcs.cpp:63
polyfit.h
src
numerics
funcs.cpp
Generated by
1.17.0