1 /**
2  *  @file utilities.h
3  *  Various templated functions that carry out common vector
4  *  operations (see \ref utils).
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 utils Templated Utility Functions
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 
17 #ifndef CT_UTILITIES_H
18 #define CT_UTILITIES_H
19 
20 #include "ct_defs.h"
21 #include <numeric>
22 
23 namespace Cantera
24 {
25 //! Templated Inner product of two vectors of length 4.
26 /*!
27  * If either \a x or \a y has length greater than 4, only the first 4 elements
28  * will be used.
29  *
30  * @param x   first reference to the templated class V
31  * @param y   second reference to the templated class V
32  * @return This class returns a hard-coded type, doublereal.
33  */
34 template<class V>
dot4(const V & x,const V & y)35 inline doublereal dot4(const V& x, const V& y)
36 {
37     return x[0]*y[0] + x[1]*y[1] + x[2]*y[2] + x[3]*y[3];
38 }
39 
40 //! Templated Inner product of two vectors of length 5
41 /*!
42  * If either \a x or \a y has length greater than 4, only the first 4 elements
43  * will be used.
44  *
45  * @param x   first reference to the templated class V
46  * @param y   second reference to the templated class V
47  * @return This class returns a hard-coded type, doublereal.
48  */
49 template<class V>
dot5(const V & x,const V & y)50 inline doublereal dot5(const V& x, const V& y)
51 {
52     return x[0]*y[0] + x[1]*y[1] + x[2]*y[2] + x[3]*y[3] +
53            x[4]*y[4];
54 }
55 
56 //! Function that calculates a templated inner product.
57 /*!
58  * This inner product is templated twice. The output variable is hard coded
59  * to return a doublereal.
60  *
61  * template<class InputIter, class InputIter2>
62  *
63  * @code
64  *     double x[8], y[8];
65  *     doublereal dsum = dot<double *,double *>(x, &x+7, y);
66  * @endcode
67  *
68  * @param x_begin  Iterator pointing to the beginning, belonging to the
69  *                 iterator class InputIter.
70  * @param x_end    Iterator pointing to the end, belonging to the
71  *                 iterator class InputIter.
72  * @param y_begin Iterator pointing to the beginning of y, belonging to the
73  *               iterator class InputIter2.
74  * @return The return is hard-coded to return a double.
75  */
76 template<class InputIter, class InputIter2>
dot(InputIter x_begin,InputIter x_end,InputIter2 y_begin)77 inline doublereal dot(InputIter x_begin, InputIter x_end,
78                       InputIter2 y_begin)
79 {
80     return std::inner_product(x_begin, x_end, y_begin, 0.0);
81 }
82 
83 //! Multiply elements of an array by a scale factor.
84 /*!
85  * \code
86  * vector_fp in(8, 1.0), out(8);
87  * scale(in.begin(), in.end(), out.begin(), factor);
88  * \endcode
89  *
90  * @param begin  Iterator pointing to the beginning, belonging to the
91  *               iterator class InputIter.
92  * @param end    Iterator pointing to the end, belonging to the
93  *               iterator class InputIter.
94  * @param out    Iterator pointing to the beginning of out, belonging to the
95  *               iterator class OutputIter. This is the output variable
96  *               for this routine.
97  * @param scale_factor  input scale factor belonging to the class S.
98  */
99 template<class InputIter, class OutputIter, class S>
scale(InputIter begin,InputIter end,OutputIter out,S scale_factor)100 inline void scale(InputIter begin, InputIter end,
101                   OutputIter out, S scale_factor)
102 {
103     std::transform(begin, end, out,
104         [scale_factor](double x) { return x * scale_factor; });
105 }
106 
107 //! Templated evaluation of a polynomial of order 6
108 /*!
109  * @param x   Value of the independent variable - First template parameter
110  * @param c   Pointer to the polynomial - Second template parameter
111  */
112 template<class D, class R>
poly6(D x,R * c)113 R poly6(D x, R* c)
114 {
115     return ((((((c[6]*x + c[5])*x + c[4])*x + c[3])*x +
116               c[2])*x + c[1])*x + c[0]);
117 }
118 
119 //! Templated evaluation of a polynomial of order 8
120 /*!
121  * @param x   Value of the independent variable - First template parameter
122  * @param c   Pointer to the polynomial - Second template parameter
123  */
124 template<class D, class R>
poly8(D x,R * c)125 R poly8(D x, R* c)
126 {
127     return ((((((((c[8]*x + c[7])*x + c[6])*x + c[5])*x + c[4])*x + c[3])*x +
128               c[2])*x + c[1])*x + c[0]);
129 }
130 
131 //! Templated evaluation of a polynomial of order 5
132 /*!
133  * @param x   Value of the independent variable - First template parameter
134  * @param c   Pointer to the polynomial - Second template parameter
135  */
136 template<class D, class R>
poly5(D x,R * c)137 R poly5(D x, R* c)
138 {
139     return (((((c[5]*x + c[4])*x + c[3])*x +
140               c[2])*x + c[1])*x + c[0]);
141 }
142 
143 //! Evaluates a polynomial of order 4.
144 /*!
145  * @param x   Value of the independent variable.
146  * @param c   Pointer to the polynomial coefficient array.
147  */
148 template<class D, class R>
poly4(D x,R * c)149 R poly4(D x, R* c)
150 {
151     return ((((c[4]*x + c[3])*x +
152               c[2])*x + c[1])*x + c[0]);
153 }
154 
155 //! Templated evaluation of a polynomial of order 3
156 /*!
157  * @param x   Value of the independent variable - First template parameter
158  * @param c   Pointer to the polynomial - Second template parameter
159  */
160 template<class D, class R>
poly3(D x,R * c)161 R poly3(D x, R* c)
162 {
163     return (((c[3]*x + c[2])*x + c[1])*x + c[0]);
164 }
165 
166 //@}
167 
168 //! Check to see that a number is finite (not NaN, +Inf or -Inf)
169 void checkFinite(const double tmp);
170 
171 //! Check to see that all elements in an array are finite
172 /*!
173  * Throws an exception if any element is NaN, +Inf, or -Inf
174  * @param name    Name to be used in the exception message if the check fails
175  * @param values  Array of *N* values to be checked
176  * @param N       Number of elements in *values*
177  */
178 void checkFinite(const std::string& name, double* values, size_t N);
179 
180 //! Const accessor for a value in a std::map.
181 /*
182  * Similar to std::map.at(key), but returns *default_val* if the key is not
183  * found instead of throwing an exception.
184  */
185 template <class T, class U>
getValue(const std::map<T,U> & m,const T & key,const U & default_val)186 const U& getValue(const std::map<T, U>& m, const T& key, const U& default_val) {
187     typename std::map<T,U>::const_iterator iter = m.find(key);
188     return (iter == m.end()) ? default_val : iter->second;
189 }
190 
191 }
192 
193 #endif
194