Cantera  2.0
utilities.h
Go to the documentation of this file.
1 /**
2  * @file utilities.h
3  * Various templated functions that carry out common vector
4  * operations (see \ref globalUtilFuncs).
5  */
6 
7 // Copyright 2001 California Institute of Technology
8 /**
9  * @defgroup utils Templated Utility Functions
10  *
11  * These are templates to perform various simple operations on arrays.
12  * Note that the compiler will inline these, so using them carries no
13  * performance penalty.
14  */
15 
16 #ifndef CT_UTILITIES_H
17 #define CT_UTILITIES_H
18 
19 #include "ct_defs.h"
20 
21 #include <algorithm>
22 
23 //! Unary operator to multiply the argument by a constant.
24 /*!
25  * The form of this operator is designed for use by std::transform.
26  * @see @ref scale().
27  */
28 template<class T> struct timesConstant : public std::unary_function<T, double> {
29  //! Constructor
30  /*!
31  * @param c Constant of templated type T
32  * that will be stored internally within the object
33  * and used in the multiplication operation
34  */
35  timesConstant(T c) : m_c(c) {}
36 
37  //! Parenthesis operator returning a double
38  /*!
39  * @param x Variable of templated type T that will be
40  * used in the multiplication operator
41  *
42  * @return Returns a value of type double from the internal
43  * multiplication
44  */
45  double operator()(T x) {
46  return m_c * x;
47  }
48 
49  //! Stored constant value of time T
50  T m_c;
51 };
52 
53 
54 namespace Cantera
55 {
56 //! Templated Inner product of two vectors of length 4.
57 /*!
58  * If either \a x
59  * or \a y has length greater than 4, only the first 4 elements
60  * will be used.
61  *
62  * @param x first reference to the templated class V
63  * @param y second reference to the templated class V
64  * @return
65  * This class returns a hard-coded type, doublereal.
66  */
67 template<class V>
68 inline doublereal dot4(const V& x, const V& y)
69 {
70  return x[0]*y[0] + x[1]*y[1] + x[2]*y[2] + x[3]*y[3];
71 }
72 
73 
74 //! Templated Inner product of two vectors of length 5
75 /*!
76  * If either \a x
77  * or \a y has length greater than 4, only the first 4 elements
78  * will be used.
79  *
80  * @param x first reference to the templated class V
81  * @param y second reference to the templated class V
82  * @return
83  * This class returns a hard-coded type, doublereal.
84  */
85 template<class V>
86 inline doublereal dot5(const V& x, const V& y)
87 {
88  return x[0]*y[0] + x[1]*y[1] + x[2]*y[2] + x[3]*y[3] +
89  x[4]*y[4];
90 }
91 
92 //! Templated Inner product of two vectors of length 6
93 /*!
94  * If either \a x
95  * or \a y has length greater than 4, only the first 4 elements
96  * will be used.
97  *
98  * @param x first reference to the templated class V
99  * @param y second reference to the templated class V
100  * @return
101  * This class returns a hard-coded type, doublereal.
102  */
103 template<class V>
104 inline doublereal dot6(const V& x, const V& y)
105 {
106  return x[0]*y[0] + x[1]*y[1] + x[2]*y[2] + x[3]*y[3] +
107  x[4]*y[4] + x[5]*y[5];
108 }
109 
110 //! Function that calculates a templated inner product.
111 /*!
112  * This inner product is templated twice. The output variable is hard coded
113  * to return a doublereal.
114  *
115  * template<class InputIter, class InputIter2>
116  *
117  * @code
118  * double x[8], y[8];
119  * doublereal dsum = dot<double *,double *>(x, &x+7, y);
120  * @endcode
121  *
122  * @param x_begin Iterator pointing to the beginning, belonging to the
123  * iterator class InputIter.
124  * @param x_end Iterator pointing to the end, belonging to the
125  * iterator class InputIter.
126  * @param y_begin Iterator pointing to the beginning of y, belonging to the
127  * iterator class InputIter2.
128  * @return
129  * The return is hard-coded to return a double.
130  */
131 template<class InputIter, class InputIter2>
132 inline doublereal dot(InputIter x_begin, InputIter x_end,
133  InputIter2 y_begin)
134 {
135  return inner_product(x_begin, x_end, y_begin, 0.0);
136 }
137 
138 //! Multiply elements of an array by a scale factor.
139 /*!
140  * \code
141  * vector_fp in(8, 1.0), out(8);
142  * scale(in.begin(), in.end(), out.begin(), factor);
143  * \endcode
144  *
145  * @param begin Iterator pointing to the beginning, belonging to the
146  * iterator class InputIter.
147  * @param end Iterator pointing to the end, belonging to the
148  * iterator class InputIter.
149  * @param out Iterator pointing to the beginning of out, belonging to the
150  * iterator class OutputIter. This is the output variable
151  * for this routine.
152  * @param scale_factor input scale factor belonging to the class S.
153  */
154 template<class InputIter, class OutputIter, class S>
155 inline void scale(InputIter begin, InputIter end,
156  OutputIter out, S scale_factor)
157 {
158  std::transform(begin, end, out, timesConstant<S>(scale_factor));
159 }
160 
161 /*!
162  * Multiply elements of an array, y, by a scale factor, f and add the
163  * result to an existing array, x. This is essentially a templated daxpy_
164  * operation.
165  *
166  * The template arguments are: template<class InputIter,
167  * class OutputIter, class S>
168  *
169  * Simple Code Example of the functionality;
170  * @code
171  * double x[10], y[10], f;
172  * for (i = 0; i < n; i++) {
173  * y[i] += f * x[i]
174  * }
175  * @endcode
176  * Example of the function call to implement the simple code example
177  * @code
178  * double x[10], y[10], f;
179  * increment_scale(x, x+10, y, f);
180  * @endcode
181  *
182  * It is templated with three parameters. The first template
183  * is the iterator, InputIter, which controls access to y[].
184  * The second template is the iterator OutputIter, which controls
185  * access to y[]. The third iterator is S, which is f.
186  *
187  * @param begin InputIter Iterator for beginning of y[]
188  * @param end inputIter Iterator for end of y[]
189  * @param out OutputIter Iterator for beginning of x[]
190  * @param scale_factor Scale Factor to multiply y[i] by
191  */
192 template<class InputIter, class OutputIter, class S>
193 inline void increment_scale(InputIter begin, InputIter end,
194  OutputIter out, S scale_factor)
195 {
196  for (; begin != end; ++begin, ++out) {
197  *out += scale_factor * *begin;
198  }
199 }
200 
201 
202 //! Multiply each entry in x by the corresponding entry in y.
203 /*!
204  * The template arguments are: template<class InputIter, class OutputIter>
205  *
206  * Simple code Equivalent:
207  * \code
208  * double x[10], y[10]
209  * for (n = 0; n < 10; n++) {
210  * x[n] *= y[n];
211  * }
212  * \endcode
213  * Example of function call usage to implement the simple code example:
214  * \code
215  * double x[10], y[10]
216  * multiply_each(x, x+10, y);
217  * \endcode
218  *
219  * @param x_begin Iterator pointing to the beginning of the vector x, belonging to the
220  * iterator class InputIter.
221  * @param x_end Iterator pointing to the end of the vector x, belonging to the
222  * iterator class InputIter. The difference between end and begin
223  * determines the loop length
224  * @param y_begin Iterator pointing to the beginning of the vector y, belonging to the
225  * iterator class outputIter.
226  */
227 template<class InputIter, class OutputIter>
228 inline void multiply_each(OutputIter x_begin, OutputIter x_end,
229  InputIter y_begin)
230 {
231  for (; x_begin != x_end; ++x_begin, ++y_begin) {
232  *x_begin *= *y_begin;
233  }
234 }
235 
236 //! Invoke method 'resize' with argument \a m for a sequence of objects (templated version)
237 /*!
238  * The template arguments are: template<class InputIter>
239  *
240  * Simple code Equivalent:
241  * \code
242  * vector<vector<double> *> VV;
243  * for (n = 0; n < 20; n++) {
244  * vector<double> *vp = VV[n];
245  * vp->resize(m);
246  * }
247  * \endcode
248  * Example of function call usage to implement the simple code example:
249  * \code
250  * vector<vector<double> *> VV;
251  * resize_each(m, &VV[0], &VV[20]);
252  * \endcode
253  *
254  * @param m Integer specifying the size that each object should be resized to.
255  * @param begin Iterator pointing to the beginning of the sequence of object, belonging to the
256  * iterator class InputIter.
257  * @param end Iterator pointing to the end of the sequence of objects, belonging to the
258  * iterator class InputIter. The difference between end and begin
259  * determines the loop length
260  *
261  * @note This is currently unused.
262  */
263 template<class InputIter>
264 inline void resize_each(int m, InputIter begin, InputIter end)
265 {
266  for (; begin != end; ++begin) {
267  begin->resize(m);
268  }
269 }
270 
271 //! The maximum absolute value (templated version)
272 /*!
273  * The template arguments are: template<class InputIter>
274  *
275  * Simple code Equivalent:
276  * \code
277  * double x[10] amax = 0.0;
278  * for (int n = 0; n < 10; n++) {
279  * if (fabs(x[n]) > amax) amax = fabs(x[10]);
280  * }
281  * return amax;
282  * \endcode
283  * Example of function call usage to implement the simple code example:
284  * \code
285  * double x[10]
286  * double amax = absmax(x, x+10);
287  * \endcode
288  *
289  * @param begin Iterator pointing to the beginning of the x vector, belonging to the
290  * iterator class InputIter.
291  * @param end Iterator pointing to the end of the x vector, belonging to the
292  * iterator class InputIter. The difference between end and begin
293  * determines the loop length
294  */
295 template<class InputIter>
296 inline doublereal absmax(InputIter begin, InputIter end)
297 {
298  doublereal amax = 0.0;
299  for (; begin != end; ++begin)
300  if (fabs(*begin) > amax) {
301  amax = fabs(*begin);
302  }
303  return amax;
304 }
305 
306 //! Normalize the values in a sequence, such that they sum to 1.0 (templated version)
307 /*!
308  * The template arguments are: template<class InputIter, class OutputIter>
309  *
310  * Simple Equivalent:
311  * \code
312  * double x[10], y[10], sum = 0.0;
313  * for (int n = 0; n < 10; n++) {
314  * sum += x[10];
315  * }
316  * for (int n = 0; n < 10; n++) {
317  * y[n] = x[n]/sum;
318  * }
319  * \endcode
320  * Example of function call usage:
321  * \code
322  * double x[10], y[10];
323  * normalize(x, x+10, y);
324  * \endcode
325  *
326  * @param begin Iterator pointing to the beginning of the x vector, belonging to the
327  * iterator class InputIter.
328  * @param end Iterator pointing to the end of the x vector, belonging to the
329  * iterator class InputIter. The difference between end and begin
330  * determines the loop length
331  * @param out Iterator pointing to the beginning of the output vector, belonging to the
332  * iterator class OutputIter.
333  */
334 template<class InputIter, class OutputIter>
335 inline void normalize(InputIter begin, InputIter end,
336  OutputIter out)
337 {
338  doublereal sum = accumulate(begin, end, 0.0);
339  for (; begin != end; ++begin, ++out) {
340  *out = *begin/sum;
341  }
342 }
343 
344 //! Templated divide of each element of \a x by the corresponding element of \a y.
345 /*!
346  * The template arguments are: template<class InputIter, class OutputIter>
347  *
348  * Simple Equivalent:
349  * \code
350  * double x[10], y[10];
351  * for (n = 0; n < 10; n++) {
352  * x[n] /= y[n];
353  * }
354  * \endcode
355  * Example of code usage:
356  * \code
357  * double x[10], y[10];
358  * divide_each(x, x+10, y);
359  * \endcode
360  *
361  * @param x_begin Iterator pointing to the beginning of the x vector, belonging to the
362  * iterator class OutputIter.
363  * @param x_end Iterator pointing to the end of the x vector, belonging to the
364  * iterator class OutputIter. The difference between end and begin
365  * determines the number of inner iterations.
366  * @param y_begin Iterator pointing to the beginning of the yvector, belonging to the
367  * iterator class InputIter.
368  */
369 template<class InputIter, class OutputIter>
370 inline void divide_each(OutputIter x_begin, OutputIter x_end,
371  InputIter y_begin)
372 {
373  for (; x_begin != x_end; ++x_begin, ++y_begin) {
374  *x_begin /= *y_begin;
375  }
376 }
377 
378 //! Increment each entry in \a x by the corresponding entry in \a y.
379 /*!
380  * The template arguments are: template<class InputIter, class OutputIter>
381  *
382  * @param x_begin Iterator pointing to the beginning of the x vector, belonging to the
383  * iterator class OutputIter.
384  * @param x_end Iterator pointing to the end of the x vector, belonging to the
385  * iterator class OutputIter. The difference between end and begin
386  * determines the number of inner iterations.
387  * @param y_begin Iterator pointing to the beginning of the yvector, belonging to the
388  * iterator class InputIter.
389  */
390 template<class InputIter, class OutputIter>
391 inline void sum_each(OutputIter x_begin, OutputIter x_end,
392  InputIter y_begin)
393 {
394  for (; x_begin != x_end; ++x_begin, ++y_begin) {
395  *x_begin += *y_begin;
396  }
397 }
398 
399 //! Copies a contiguous range in a sequence to indexed
400 //! positions in another sequence.
401 /*!
402  * The template arguments are: template<class InputIter, class OutputIter, class IndexIter>
403  *
404  * Example:
405  *
406  * \code
407  * vector<double> x(3), y(20), ;
408  * vector<int> index(3);
409  * index[0] = 9;
410  * index[1] = 2;
411  * index[3] = 16;
412  * scatter_copy(x.begin(), x.end(), y.begin(), index.begin());
413  * \endcode
414  *
415  * This routine is templated 3 times.
416  * InputIter is an iterator for the source vector
417  * OutputIter is an iterator for the destination vector
418  * IndexIter is an iterator for the index into the destination vector.
419  *
420  * @param begin Iterator pointing to the beginning of the source vector, belonging to the
421  * iterator class InputIter.
422  * @param end Iterator pointing to the end of the source vector, belonging to the
423  * iterator class InputIter. The difference between end and begin
424  * determines the number of inner iterations.
425  * @param result Iterator pointing to the beginning of the output vector, belonging to the
426  * iterator class outputIter.
427  * @param index Iterator pointing to the beginning of the index vector, belonging to the
428  * iterator class IndexIter.
429  */
430 template<class InputIter, class OutputIter, class IndexIter>
431 inline void scatter_copy(InputIter begin, InputIter end,
432  OutputIter result, IndexIter index)
433 {
434  for (; begin != end; ++begin, ++index) {
435  *(result + *index) = *begin;
436  }
437 }
438 
439 
440 //! Multiply selected elements in an array by a contiguous
441 //! sequence of multipliers.
442 /*!
443  * The template arguments are: template<class InputIter, class RandAccessIter, class IndexIter>
444  *
445  * Example:
446  * \code
447  * double multipliers[] = {8.9, -2.0, 5.6};
448  * int index[] = {7, 4, 13};
449  * vector_fp data(20);
450  * ...
451  * // Multiply elements 7, 4, and 13 in data by multipliers[0], multipliers[1],and multipliers[2],
452  * // respectively
453  * scatter_mult(multipliers, multipliers + 3, data.begin(), index);
454  * \endcode
455  *
456  * @param mult_begin Iterator pointing to the beginning of the multiplier vector, belonging to the
457  * iterator class InputIter.
458  * @param mult_end Iterator pointing to the end of the multiplier vector, belonging to the
459  * iterator class InputIter. The difference between end and begin
460  * determines the number of inner iterations.
461  * @param data Iterator pointing to the beginning of the output vector, belonging to the
462  * iterator class RandAccessIter, that will be selectively multiplied.
463  * @param index Iterator pointing to the beginning of the index vector, belonging to the
464  * iterator class IndexIter.
465  */
466 template<class InputIter, class RandAccessIter, class IndexIter>
467 inline void scatter_mult(InputIter mult_begin, InputIter mult_end,
468  RandAccessIter data, IndexIter index)
469 {
470  for (; mult_begin != mult_end; ++mult_begin, ++index) {
471  *(data + *index) *= *mult_begin;
472  }
473 }
474 
475 
476 //! Divide selected elements in an array by a contiguous sequence of divisors.
477 /*!
478  * The template arguments are: template<class InputIter, class OutputIter, class IndexIter>
479  *
480  * Example:
481  * \code
482  * double divisors[] = {8.9, -2.0, 5.6};
483  * int index[] = {7, 4, 13};
484  * vector_fp data(20);
485  * ...
486  * // divide elements 7, 4, and 13 in data by divisors[7] divisors[4], and divisors[13]
487  * // respectively
488  * scatter_divide(divisors, divisors + 3, data.begin(), index);
489  * \endcode
490  *
491  * @param begin Iterator pointing to the beginning of the source vector, belonging to the
492  * iterator class InputIter.
493  * @param end Iterator pointing to the end of the source vector, belonging to the
494  * iterator class InputIter. The difference between end and begin
495  * determines the number of inner iterations.
496  * @param result Iterator pointing to the beginning of the output vector, belonging to the
497  * iterator class outputIter.
498  * @param index Iterator pointing to the beginning of the index vector, belonging to the
499  * iterator class IndexIter.
500  */
501 template<class InputIter, class OutputIter, class IndexIter>
502 inline void scatter_divide(InputIter begin, InputIter end,
503  OutputIter result, IndexIter index)
504 {
505  for (; begin != end; ++begin, ++index) {
506  *(result + *index) /= *begin;
507  }
508 }
509 
510 //! Compute \f[ \sum_k x_k \log x_k. \f].
511 /*!
512  * The template arguments are: template<class InputIter>
513  *
514  * A small number (1.0E-20) is added before taking the log. This templated
515  * class does the indicated sun. The template must be an iterator.
516  *
517  * @param begin Iterator pointing to the beginning, belonging to the
518  * iterator class InputIter.
519  * @param end Iterator pointing to the end, belonging to the
520  * iterator class InputIter.
521  * @return
522  * The return from this class is a double.
523  */
524 template<class InputIter>
525 inline doublereal sum_xlogx(InputIter begin, InputIter end)
526 {
527  doublereal sum = 0.0;
528  for (; begin != end; ++begin) {
529  sum += (*begin) * std::log(*begin + Tiny);
530  }
531  return sum;
532 }
533 
534 //! Compute \f[ \sum_k x_k \log Q_k. \f].
535 /*!
536  * The template arguments are: template<class InputIter1, class InputIter2>
537  *
538  * This class is templated twice. The first template, InputIter1
539  * is the iterator that points to $x_k$. The second iterator
540  * InputIter2, point to $Q_k$.
541  * A small number (1.0E-20) is added before taking the log.
542  *
543  * @param begin Iterator pointing to the beginning, belonging to the
544  * iterator class InputIter1.
545  * @param end Iterator pointing to the end, belonging to the
546  * iterator class InputIter1.
547  * @param Q_begin Iterator pointing to the beginning of Q_k, belonging to the
548  * iterator class InputIter2.
549  * @return
550  * The return from this class is hard coded to a doublereal.
551  */
552 template<class InputIter1, class InputIter2>
553 inline doublereal sum_xlogQ(InputIter1 begin, InputIter1 end,
554  InputIter2 Q_begin)
555 {
556  doublereal sum = 0.0;
557  for (; begin != end; ++begin, ++Q_begin) {
558  sum += (*begin) * std::log(*Q_begin + Tiny);
559  }
560  return sum;
561 }
562 
563 //! Scale a templated vector by a constant factor.
564 /*!
565  * The template arguments are: template<class OutputIter>
566  *
567  * This function is essentially a wrapper around the stl
568  * function %scale(). The function is has one template
569  * parameter, OutputIter. OutputIter is a templated iterator
570  * that points to the vector to be scaled.
571  *
572  * @param N Length of the vector
573  * @param alpha scale factor - double
574  * @param x Templated Iterator to the start of the vector
575  * to be scaled.
576  */
577 template<class OutputIter>
578 inline void scale(int N, double alpha, OutputIter x)
579 {
580  scale(x, x+N, x, alpha);
581 }
582 
583 
584 //! Templated evaluation of a polynomial of order 6
585 /*!
586  * @param x Value of the independent variable - First template parameter
587  * @param c Pointer to the polynomial - Second template parameter
588  */
589 template<class D, class R>
590 R poly6(D x, R* c)
591 {
592  return ((((((c[6]*x + c[5])*x + c[4])*x + c[3])*x +
593  c[2])*x + c[1])*x + c[0]);
594 }
595 
596 //! Templated evaluation of a polynomial of order 8
597 /*!
598  * @param x Value of the independent variable - First template parameter
599  * @param c Pointer to the polynomial - Second template parameter
600  */
601 template<class D, class R>
602 R poly8(D x, R* c)
603 {
604  return ((((((((c[8]*x + c[7])*x + c[6])*x + c[5])*x + c[4])*x + c[3])*x +
605  c[2])*x + c[1])*x + c[0]);
606 }
607 
608 //! Templated evaluation of a polynomial of order 10
609 /*!
610  * @param x Value of the independent variable - First template parameter
611  * @param c Pointer to the polynomial - Second template parameter
612  */
613 template<class D, class R>
614 R poly10(D x, R* c)
615 {
616  return ((((((((((c[10]*x + c[9])*x + c[8])*x + c[7])*x
617  + c[6])*x + c[5])*x + c[4])*x + c[3])*x
618  + c[2])*x + c[1])*x + c[0]);
619 }
620 
621 //! Templated evaluation of a polynomial of order 5
622 /*!
623  * @param x Value of the independent variable - First template parameter
624  * @param c Pointer to the polynomial - Second template parameter
625  */
626 template<class D, class R>
627 R poly5(D x, R* c)
628 {
629  return (((((c[5]*x + c[4])*x + c[3])*x +
630  c[2])*x + c[1])*x + c[0]);
631 }
632 
633 //! Evaluates a polynomial of order 4.
634 /*!
635  * @param x Value of the independent variable.
636  * @param c Pointer to the polynomial coefficient array.
637  */
638 template<class D, class R>
639 R poly4(D x, R* c)
640 {
641  return ((((c[4]*x + c[3])*x +
642  c[2])*x + c[1])*x + c[0]);
643 }
644 
645 //! Templated evaluation of a polynomial of order 3
646 /*!
647  * @param x Value of the independent variable - First template parameter
648  * @param c Pointer to the polynomial - Second template parameter
649  */
650 template<class D, class R>
651 R poly3(D x, R* c)
652 {
653  return (((c[3]*x + c[2])*x + c[1])*x + c[0]);
654 }
655 
656 //! Templated deep copy of a std vector of pointers
657 /*!
658  * Performs a deep copy of a std vectors of pointers to an object. This template assumes that
659  * that the templated object has a functioning copy constructor.
660  * It also assumes that pointers are zero when they are not malloced.
661  *
662  * @param fromVec Vector of pointers to a templated class. This will be
663  * deep-copied to the other vector
664  * @param toVec Vector of pointers to a templated class. This will be
665  * overwritten and on return will be a copy of the fromVec
666  */
667 template<class D>
668 void deepStdVectorPointerCopy(const std::vector<D*> &fromVec, std::vector<D*> &toVec)
669 {
670  size_t is = toVec.size();
671  for (size_t i = 0; i < is; is++) {
672  if (toVec[i]) {
673  delete(toVec[i]);
674  }
675  }
676  is = fromVec.size();
677  toVec.resize(is);
678  for (size_t i = 0; i < is; is++) {
679  toVec[i] = new D(*(fromVec[i]));
680  }
681 }
682 
683 //@}
684 }
685 
686 #endif