Cantera  4.0.0a1
Loading...
Searching...
No Matches
utilities.h
Go to the documentation of this file.
1/**
2 * @file utilities.h
3 * Various templated functions that carry out common vector and polynomial operations
4 * (see @ref mathTemplates).
5 */
6
7// This file is part of Cantera. See License.txt in the top-level directory or
8// at https://cantera.org/license.txt for license and copyright information.
9
10/**
11 * @defgroup mathTemplates Templated Array and Polynomial Operations
12 *
13 * These are templates to perform various simple operations on arrays. Note that
14 * the compiler will inline these, so using them carries no performance penalty.
15 *
16 * @ingroup numerics
17 */
18
19#ifndef CT_UTILITIES_H
20#define CT_UTILITIES_H
21
22#include "ct_defs.h"
24#include <numeric>
25#include <iterator>
26
27namespace Cantera
28{
29//! @addtogroup mathTemplates
30//! @{
31
32//! Templated Inner product of two vectors of length 4.
33/*!
34 * If either @e x or @e y has length greater than 4, only the first 4 elements
35 * will be used.
36 *
37 * @param x first reference to the templated class V
38 * @param y second reference to the templated class V
39 * @return This class returns a hard-coded type, double.
40 */
41template<class X, class Y>
42inline auto dot4(const X& x, const Y& y)
43{
44 auto x_ = span{std::data(x), std::size(x)};
45 auto y_ = span{std::data(y), std::size(y)};
46#ifndef NDEBUG
47 checkArraySize("dot4: x", x_.size(), 4);
48 checkArraySize("dot4: y", y_.size(), 4);
49#endif
50 return x_[0]*y_[0] + x_[1]*y_[1] + x_[2]*y_[2] + x_[3]*y_[3];
51}
52
53//! Templated Inner product of two vectors of length 5
54/*!
55 * If either @e x or @e y has length greater than 4, only the first 4 elements
56 * will be used.
57 *
58 * @param x first reference to the templated class V
59 * @param y second reference to the templated class V
60 * @return This class returns a hard-coded type, double.
61 */
62template<class X, class Y>
63inline auto dot5(const X& x, const Y& y)
64{
65 auto x_ = span{std::data(x), std::size(x)};
66 auto y_ = span{std::data(y), std::size(y)};
67#ifndef NDEBUG
68 checkArraySize("dot5: x", x_.size(), 5);
69 checkArraySize("dot5: y", y_.size(), 5);
70#endif
71 return x_[0]*y_[0] + x_[1]*y_[1] + x_[2]*y_[2] + x_[3]*y_[3] +
72 x_[4]*y_[4];
73}
74
75//! Function that calculates a templated inner product.
76/*!
77 * This inner product is templated twice. The output variable is hard coded
78 * to return a double.
79 *
80 * template<class InputIter, class InputIter2>
81 *
82 * @code
83 * double x[8], y[8];
84 * double dsum = dot<double *,double *>(x, &x+7, y);
85 * @endcode
86 *
87 * @param x_begin Iterator pointing to the beginning, belonging to the
88 * iterator class InputIter.
89 * @param x_end Iterator pointing to the end, belonging to the
90 * iterator class InputIter.
91 * @param y_begin Iterator pointing to the beginning of y, belonging to the
92 * iterator class InputIter2.
93 * @return The return is hard-coded to return a double.
94 */
95template<class InputIter, class InputIter2>
96inline double dot(InputIter x_begin, InputIter x_end, InputIter2 y_begin)
97{
98 return std::inner_product(x_begin, x_end, y_begin, 0.0);
99}
100
101//! Multiply elements of an array by a scale factor.
102/*!
103 * @code
104 * vector<double> in(8, 1.0), out(8);
105 * scale(in.begin(), in.end(), out.begin(), factor);
106 * @endcode
107 *
108 * @param begin Iterator pointing to the beginning, belonging to the
109 * iterator class InputIter.
110 * @param end Iterator pointing to the end, belonging to the
111 * iterator class InputIter.
112 * @param out Iterator pointing to the beginning of out, belonging to the
113 * iterator class OutputIter. This is the output variable
114 * for this routine.
115 * @param scale_factor input scale factor belonging to the class S.
116 */
117template<class InputIter, class OutputIter, class S>
118inline void scale(InputIter begin, InputIter end,
119 OutputIter out, S scale_factor)
120{
121 std::transform(begin, end, out,
122 [scale_factor](double x) { return x * scale_factor; });
123}
124
125//! Templated evaluation of a polynomial of order 6
126/*!
127 * @param x Value of the independent variable - First template parameter
128 * @param c Pointer to the polynomial - Second template parameter
129 */
130template<class D, class C>
131auto poly6(D x, const C& c)
132{
133 auto c_ = span{std::data(c), std::size(c)};
134#ifndef NDEBUG
135 checkArraySize("poly6: c", c_.size(), 7);
136#endif
137 return ((((((c_[6]*x + c_[5])*x + c_[4])*x + c_[3])*x +
138 c_[2])*x + c_[1])*x + c_[0]);
139}
140
141//! Templated evaluation of a polynomial of order 8
142/*!
143 * @param x Value of the independent variable - First template parameter
144 * @param c Pointer to the polynomial - Second template parameter
145 */
146template<class D, class C>
147auto poly8(D x, const C& c)
148{
149 auto c_ = span{std::data(c), std::size(c)};
150#ifndef NDEBUG
151 checkArraySize("poly8: c", c_.size(), 9);
152#endif
153 return ((((((((c_[8]*x + c_[7])*x + c_[6])*x + c_[5])*x + c_[4])*x + c_[3])*x +
154 c_[2])*x + c_[1])*x + c_[0]);
155}
156
157//! Templated evaluation of a polynomial of order 5
158/*!
159 * @param x Value of the independent variable - First template parameter
160 * @param c Pointer to the polynomial - Second template parameter
161 */
162template<class D, class C>
163auto poly5(D x, const C& c)
164{
165 auto c_ = span{std::data(c), std::size(c)};
166#ifndef NDEBUG
167 checkArraySize("poly5: c", c_.size(), 6);
168#endif
169 return (((((c_[5]*x + c_[4])*x + c_[3])*x +
170 c_[2])*x + c_[1])*x + c_[0]);
171}
172
173//! Evaluates a polynomial of order 4.
174/*!
175 * @param x Value of the independent variable.
176 * @param c Pointer to the polynomial coefficient array.
177 */
178template<class D, class C>
179auto poly4(D x, const C& c)
180{
181 auto c_ = span{std::data(c), std::size(c)};
182#ifndef NDEBUG
183 checkArraySize("poly4: c", c_.size(), 5);
184#endif
185 return ((((c_[4]*x + c_[3])*x +
186 c_[2])*x + c_[1])*x + c_[0]);
187}
188
189//! Templated evaluation of a polynomial of order 3
190/*!
191 * @param x Value of the independent variable - First template parameter
192 * @param c Pointer to the polynomial - Second template parameter
193 */
194template<class D, class C>
195auto poly3(D x, const C& c)
196{
197 auto c_ = span{std::data(c), std::size(c)};
198#ifndef NDEBUG
199 checkArraySize("poly3: c", c_.size(), 4);
200#endif
201 return (((c_[3]*x + c_[2])*x + c_[1])*x + c_[0]);
202}
203
204//! @}
205
206//! Check to see that a number is finite (not NaN, +Inf or -Inf)
207void checkFinite(const double tmp);
208
209//! Check to see that all elements in an array are finite
210/*!
211 * Throws an exception if any element is NaN, +Inf, or -Inf
212 * @param name Name to be used in the exception message if the check fails
213 * @param values Array of values to be checked
214 */
215void checkFinite(const string& name, span<const double> values);
216
217//! Const accessor for a value in a map.
218/*
219 * Similar to map.at(key), but returns *default_val* if the key is not
220 * found instead of throwing an exception.
221 */
222template <class T, class U>
223const U& getValue(const map<T, U>& m, const T& key, const U& default_val) {
224 typename map<T,U>::const_iterator iter = m.find(key);
225 return (iter == m.end()) ? default_val : iter->second;
226}
227
228//! Get the size of a container, cast to a signed integer type
229//! @ingroup mathTemplates
230template <class T, class U=int>
231U len(const T& container) {
232 return static_cast<U>(container.size());
233}
234
235//! A macro for generating member function detectors, which can then be used in
236//! combination with `if constexpr` to condition behavior on the availability of that
237//! member function. See MultiRate for examples of use.
238#define CT_DEFINE_HAS_MEMBER(detector_name, func_name) \
239 template<class T, class=void> \
240 struct detector_name : std::false_type {}; \
241 template<class T> \
242 struct detector_name<T, std::void_t<decltype(&T::func_name)>> : std::true_type {};
243
244}
245
246#endif
This file contains definitions of constants, types and terms that are used in internal routines and a...
Definitions for the classes that are thrown when Cantera experiences an error condition (also contain...
U len(const T &container)
Get the size of a container, cast to a signed integer type.
Definition utilities.h:231
auto poly5(D x, const C &c)
Templated evaluation of a polynomial of order 5.
Definition utilities.h:163
auto dot5(const X &x, const Y &y)
Templated Inner product of two vectors of length 5.
Definition utilities.h:63
auto poly4(D x, const C &c)
Evaluates a polynomial of order 4.
Definition utilities.h:179
double dot(InputIter x_begin, InputIter x_end, InputIter2 y_begin)
Function that calculates a templated inner product.
Definition utilities.h:96
auto poly3(D x, const C &c)
Templated evaluation of a polynomial of order 3.
Definition utilities.h:195
auto poly8(D x, const C &c)
Templated evaluation of a polynomial of order 8.
Definition utilities.h:147
auto poly6(D x, const C &c)
Templated evaluation of a polynomial of order 6.
Definition utilities.h:131
auto dot4(const X &x, const Y &y)
Templated Inner product of two vectors of length 4.
Definition utilities.h:42
void scale(InputIter begin, InputIter end, OutputIter out, S scale_factor)
Multiply elements of an array by a scale factor.
Definition utilities.h:118
Namespace for the Cantera kernel.
Definition AnyMap.cpp:595
void checkFinite(const double tmp)
Check to see that a number is finite (not NaN, +Inf or -Inf)
const U & getValue(const map< T, U > &m, const T &key, const U &default_val)
Const accessor for a value in a map.
Definition utilities.h:223
void checkArraySize(const char *procedure, size_t available, size_t required)
Wrapper for throwing ArraySizeError.