Cantera 2.6.0
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
10using namespace std;
11
12namespace Cantera
13{
14
15doublereal linearInterp(doublereal x, const vector_fp& xpts,
16 const vector_fp& fpts)
17{
18 if (x <= xpts[0]) {
19 return fpts[0];
20 }
21 if (x >= xpts.back()) {
22 return fpts.back();
23 }
24 auto loc = lower_bound(xpts.begin(), xpts.end(), x);
25 int iloc = int(loc - xpts.begin()) - 1;
26 doublereal ff = fpts[iloc] +
27 (x - xpts[iloc])*(fpts[iloc + 1]
28 - fpts[iloc])/(xpts[iloc + 1] - xpts[iloc]);
29 return ff;
30}
31
32double trapezoidal(const Eigen::ArrayXd& f, const Eigen::ArrayXd& x)
33{
34 // check length
35 if (f.size() != x.size()) {
36 throw CanteraError("trapezoidal",
37 "Vector lengths need to be the same.");
38 }
39 // Vector of f(i+1) + f(i)
40 Eigen::VectorXd f_av = f.tail(f.size() - 1) + f.head(f.size() - 1);
41 // Vector of x(i+1) - x(i)
42 Eigen::VectorXd x_diff = x.tail(x.size() - 1) - x.head(x.size() - 1);
43 // check if the coordinate is a monotonically increase vector.
44 if ((x_diff.array() <= 0.0).any()) {
45 throw CanteraError("trapezoidal",
46 "x (coordinate) needs to be the monotonically increasing.");
47 }
48 return f_av.dot(x_diff) / 2.0;
49}
50
51//! Numerical integration of a function using Simpson's rule.
52//! Only for odd number of points. This function is used only
53//! by calling simpson.
54/*!
55 * Vector x contanins a monotonic sequence of grid points, and
56 * Vector f contains function values defined at these points.
57 * The size of x and f must be the same.
58 *
59 * @param f vector of function value
60 * @param x vector of function coordinate
61 */
62double basicSimpson(const Eigen::ArrayXd& f, const Eigen::ArrayXd& x)
63{
64 if (f.size() < 2) {
65 throw CanteraError("basicSimpson",
66 "Vector lengths need to be larger than two.");
67 }
68 if (f.size()%2 == 0) {
69 throw CanteraError("basicSimpson",
70 "Vector lengths need to be an odd number.");
71 }
72
73 size_t N = f.size() - 1;
74 Eigen::VectorXd h = x.tail(N) - x.head(N);
75
76 double sum = 0.0;
77 for (size_t i = 1; i < N; i+=2) {
78 double h0 = h[i-1];
79 double h1 = h[i];
80 double hph = h1 + h0;
81 double hdh = h1 / h0;
82 double hmh = h1 * h0;
83 sum += (hph / 6.0) * (
84 (2.0 - hdh) * f[i - 1] + (pow(hph, 2) / hmh) * f[i] +
85 (2.0 - 1.0 / hdh) * f[i + 1]);
86 }
87 return sum;
88}
89
90double simpson(const Eigen::ArrayXd& f, const Eigen::ArrayXd& x)
91{
92 Eigen::ArrayXd h = x.tail(x.size() - 1) - x.head(x.size() - 1);
93 if ((h <= 0.0).any()) {
94 throw CanteraError("simpson",
95 "Values of x need to be positive and monotonically increasing.");
96 }
97 if (f.size() != x.size()) {
98 throw CanteraError("simpson", "Vector lengths need to be the same.");
99 }
100
101 if (f.size()%2 == 1) {
102 return basicSimpson(f, x);
103 } else if (f.size() == 2) {
104 return 0.5 * h[0] * (f[1] + f[0]);
105 } else {
106 size_t N = f.size() - 1;
107 // pick first N-1 point for simpson
108 double headSimps = basicSimpson(f.head(N), x.head(N));
109 // Use trapezoidal rules for the last interval
110 double tailTrap = 0.5 * h[N-1] * (f[N] + f[N-1]);
111 return headSimps + tailTrap;
112 }
113}
114
115double numericalQuadrature(const std::string& method,
116 const Eigen::ArrayXd& f,
117 const Eigen::ArrayXd& x)
118{
119 if (method == "simpson") {
120 return simpson(f, x);
121 } else if (method == "trapezoidal") {
122 return trapezoidal(f, x);
123 } else {
124 throw CanteraError("numericalQuadrature",
125 "Unknown method of numerical quadrature. "
126 "Please use 'simpson' or 'trapezoidal'");
127 }
128}
129
130}
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:61
Definitions for the classes that are thrown when Cantera experiences an error condition (also contain...
Header for a file containing miscellaneous numerical functions.
Namespace for the Cantera kernel.
Definition: AnyMap.h:29
doublereal linearInterp(doublereal x, const vector_fp &xpts, const vector_fp &fpts)
Linearly interpolate a function defined on a discrete grid.
Definition: funcs.cpp:15
double trapezoidal(const Eigen::ArrayXd &f, const Eigen::ArrayXd &x)
Numerical integration of a function using the trapezoidal rule.
Definition: funcs.cpp:32
std::vector< double > vector_fp
Turn on the use of stl vectors for the basic array type within cantera Vector of doubles.
Definition: ct_defs.h:184
double numericalQuadrature(const std::string &method, const Eigen::ArrayXd &f, const Eigen::ArrayXd &x)
Numerical integration of a function.
Definition: funcs.cpp:115
double basicSimpson(const Eigen::ArrayXd &f, const Eigen::ArrayXd &x)
Numerical integration of a function using Simpson's rule.
Definition: funcs.cpp:62
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:90