Cantera  3.2.0a2
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
9
10namespace Cantera
11{
12
13double linearInterp(double x, const vector<double>& xpts, const vector<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
33double 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 */
63double 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
91double 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
116double 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}
Base class for exceptions thrown by Cantera classes.
Definitions for the classes that are thrown when Cantera experiences an error condition (also contain...
Header for a file containing miscellaneous numerical functions.
#define AssertThrowMsg(expr, procedure,...)
Assertion must be true or an error is thrown.
double linearInterp(double x, const vector< double > &xpts, const vector< double > &fpts)
Linearly interpolate a function defined on a discrete grid.
Definition funcs.cpp:13
double numericalQuadrature(const string &method, const Eigen::ArrayXd &f, const Eigen::ArrayXd &x)
Numerical integration of a function.
Definition funcs.cpp:116
double trapezoidal(const Eigen::ArrayXd &f, const Eigen::ArrayXd &x)
Numerical integration of a function using the trapezoidal rule.
Definition funcs.cpp:33
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
Namespace for the Cantera kernel.
Definition AnyMap.cpp:595
double basicSimpson(const Eigen::ArrayXd &f, const Eigen::ArrayXd &x)
Numerical integration of a function using Simpson's rule.
Definition funcs.cpp:63