1 /**
2  *  @file Func1.h
3  */
4 
5 // This file is part of Cantera. See License.txt in the top-level directory or
6 // at https://cantera.org/license.txt for license and copyright information.
7 
8 #ifndef CT_FUNC1_H
9 #define CT_FUNC1_H
10 
11 #include "cantera/base/ct_defs.h"
12 #include "cantera/base/ctexceptions.h"
13 
14 #include <iostream>
15 
16 namespace Cantera
17 {
18 
19 const int FourierFuncType = 1;
20 const int PolyFuncType = 2;
21 const int ArrheniusFuncType = 3;
22 const int GaussianFuncType = 4;
23 const int SumFuncType = 20;
24 const int DiffFuncType = 25;
25 const int ProdFuncType = 30;
26 const int RatioFuncType = 40;
27 const int PeriodicFuncType = 50;
28 const int CompositeFuncType = 60;
29 const int TimesConstantFuncType = 70;
30 const int PlusConstantFuncType = 80;
31 const int SinFuncType = 100;
32 const int CosFuncType = 102;
33 const int ExpFuncType = 104;
34 const int PowFuncType = 106;
35 const int ConstFuncType = 110;
36 const int TabulatedFuncType = 120;
37 
38 class TimesConstant1;
39 
40 /**
41  * Base class for 'functor' classes that evaluate a function of one variable.
42  */
43 class Func1
44 {
45 public:
46     Func1();
47 
~Func1()48     virtual ~Func1() {}
49 
50     Func1(const Func1& right);
51 
52     Func1& operator=(const Func1& right);
53 
54     //! Duplicate the current function.
55     /*!
56      * This duplicates the current function, returning a reference to the newly
57      * created function.
58      */
59     virtual Func1& duplicate() const;
60 
61     virtual int ID() const;
62 
63     //! Calls method eval to evaluate the function
64     doublereal operator()(doublereal t) const;
65 
66     /// Evaluate the function.
67     virtual doublereal eval(doublereal t) const;
68 
69     //! Creates a derivative to the current function
70     /*!
71      * This will create a new derivative function and return a reference to the
72      * function.
73      */
74     virtual Func1& derivative() const;
75 
76     //! Routine to determine if two functions are the same.
77     /*!
78      * Two functions are the same if they are the same function. This means
79      * that the ID and stored constant is the same. This means that the m_f1
80      * and m_f2 are identical if they are non-null.
81      */
82     bool isIdentical(Func1& other) const;
83 
84     virtual doublereal isProportional(TimesConstant1& other);
85     virtual doublereal isProportional(Func1& other);
86 
87     virtual std::string write(const std::string& arg) const;
88 
89     //! accessor function for the stored constant
90     doublereal c() const;
91 
92     //! Function to set the stored constant
93     void setC(doublereal c);
94 
95     //! accessor function for m_f1
96     Func1& func1() const;
97 
98     //! accessor function for m_f2
99     Func1& func2() const;
100 
101     //! Return the order of the function, if it makes sense
102     virtual int order() const;
103 
104     Func1& func1_dup() const;
105 
106     Func1& func2_dup() const;
107 
108     Func1* parent() const;
109 
110     void setParent(Func1* p);
111 
112 protected:
113     doublereal m_c;
114     Func1* m_f1;
115     Func1* m_f2;
116     Func1* m_parent;
117 };
118 
119 
120 Func1& newSumFunction(Func1& f1, Func1& f2);
121 Func1& newDiffFunction(Func1& f1, Func1& f2);
122 Func1& newProdFunction(Func1& f1, Func1& f2);
123 Func1& newRatioFunction(Func1& f1, Func1& f2);
124 Func1& newCompositeFunction(Func1& f1, Func1& f2);
125 Func1& newTimesConstFunction(Func1& f1, doublereal c);
126 Func1& newPlusConstFunction(Func1& f1, doublereal c);
127 
128 
129 //! implements the sin() function
130 /*!
131  * The argument to sin() is in radians
132  */
133 class Sin1 : public Func1
134 {
135 public:
136     Sin1(doublereal omega = 1.0) :
Func1()137         Func1() {
138         m_c = omega;
139     }
140 
Sin1(const Sin1 & b)141     Sin1(const Sin1& b) :
142         Func1(b) {
143     }
144 
145     Sin1& operator=(const Sin1& right) {
146         if (&right == this) {
147             return *this;
148         }
149         Func1::operator=(right);
150         return *this;
151     }
152 
duplicate()153     virtual Func1& duplicate() const {
154         Sin1* nfunc = new Sin1(*this);
155         return (Func1&) *nfunc;
156     }
157 
158     virtual std::string write(const std::string& arg) const;
159 
ID()160     virtual int ID() const {
161         return SinFuncType;
162     }
163 
eval(doublereal t)164     virtual doublereal eval(doublereal t) const {
165         return sin(m_c*t);
166     }
167 
168     virtual Func1& derivative() const;
169 };
170 
171 
172 //! implements the cos() function
173 /*!
174  * The argument to cos() is in radians
175  */
176 class Cos1 : public Func1
177 {
178 public:
179     Cos1(doublereal omega = 1.0) :
Func1()180         Func1() {
181         m_c = omega;
182     }
183 
Cos1(const Cos1 & b)184     Cos1(const Cos1& b) :
185         Func1(b) {
186     }
187 
188     Cos1& operator=(const Cos1& right) {
189         if (&right == this) {
190             return *this;
191         }
192         Func1::operator=(right);
193         return *this;
194     }
195 
duplicate()196     virtual Func1& duplicate() const {
197         Cos1* nfunc = new Cos1(*this);
198         return (Func1&) *nfunc;
199     }
200     virtual std::string write(const std::string& arg) const;
ID()201     virtual int ID() const {
202         return CosFuncType;
203     }
eval(doublereal t)204     virtual doublereal eval(doublereal t) const {
205         return cos(m_c * t);
206     }
207     virtual Func1& derivative() const;
208 };
209 
210 
211 //! implements the exponential function
212 class Exp1 : public Func1
213 {
214 public:
215     Exp1(doublereal A = 1.0) :
Func1()216         Func1() {
217         m_c = A;
218     }
219 
Exp1(const Exp1 & b)220     Exp1(const Exp1& b) :
221         Func1(b) {
222     }
223     Exp1& operator=(const Exp1& right) {
224         if (&right == this) {
225             return *this;
226         }
227         Func1::operator=(right);
228         return *this;
229     }
230     virtual std::string write(const std::string& arg) const;
ID()231     virtual int ID() const {
232         return ExpFuncType;
233     }
duplicate()234     virtual Func1& duplicate() const {
235         return *(new Exp1(m_c));
236     }
eval(doublereal t)237     virtual doublereal eval(doublereal t) const {
238         return exp(m_c*t);
239     }
240 
241     virtual Func1& derivative() const;
242 };
243 
244 
245 //! implements the power function (pow)
246 class Pow1 : public Func1
247 {
248 public:
Pow1(doublereal n)249     Pow1(doublereal n) :
250         Func1() {
251         m_c = n;
252     }
253 
Pow1(const Pow1 & b)254     Pow1(const Pow1& b) :
255         Func1(b) {
256     }
257     Pow1& operator=(const Pow1& right) {
258         if (&right == this) {
259             return *this;
260         }
261         Func1::operator=(right);
262         return *this;
263     }
264     virtual std::string write(const std::string& arg) const;
ID()265     virtual int ID() const {
266         return PowFuncType;
267     }
duplicate()268     virtual Func1& duplicate() const {
269         return *(new Pow1(m_c));
270     }
eval(doublereal t)271     virtual doublereal eval(doublereal t) const {
272         return pow(t, m_c);
273     }
274     virtual Func1& derivative() const;
275 };
276 
277 
278 //! The Tabulated1 class implements a tabulated function
279 class Tabulated1 : public Func1
280 {
281 public:
282     //! Constructor.
283     /*!
284      * @param n      Size of tabulated value arrays
285      * @param tvals   Pointer to time value array
286      * @param fvals   Pointer to function value array
287      * @param method Interpolation method ('linear' or 'previous')
288      */
289     Tabulated1(size_t n, const double* tvals, const double* fvals,
290                const std::string& method = "linear");
291 
292     virtual std::string write(const std::string& arg) const;
ID()293     virtual int ID() const {
294         return TabulatedFuncType;
295     }
296     virtual double eval(double t) const;
duplicate()297     virtual Func1& duplicate() const {
298         if (m_isLinear) {
299             return *(new Tabulated1(m_tvec.size(), &m_tvec[0], &m_fvec[0],
300                                     "linear"));
301         } else {
302             return *(new Tabulated1(m_tvec.size(), &m_tvec[0], &m_fvec[0],
303                                     "previous"));
304         }
305     }
306 
307     virtual Func1& derivative() const;
308 private:
309     vector_fp m_tvec; //!< Vector of time values
310     vector_fp m_fvec; //!< Vector of function values
311     bool m_isLinear; //!< Boolean indicating interpolation method
312 };
313 
314 
315 //! The Const1 class implements a constant
316 class Const1 : public Func1
317 {
318 public:
319     //! Constructor.
320     /*!
321      * @param A   Constant
322      */
Const1(double A)323     Const1(double A) :
324         Func1() {
325         m_c = A;
326     }
327 
Const1(const Const1 & b)328     Const1(const Const1& b) :
329         Func1(b) {
330     }
331 
332     Const1& operator=(const Const1& right) {
333         if (&right == this) {
334             return *this;
335         }
336         Func1::operator=(right);
337         return *this;
338     }
339 
340     virtual std::string write(const std::string& arg) const;
ID()341     virtual int ID() const {
342         return ConstFuncType;
343     }
eval(doublereal t)344     virtual doublereal eval(doublereal t) const {
345         return m_c;
346     }
duplicate()347     virtual Func1& duplicate() const {
348         return *(new Const1(m_c));
349     }
350 
derivative()351     virtual Func1& derivative() const {
352         Func1* z = new Const1(0.0);
353         return *z;
354     }
355 };
356 
357 
358 /**
359  * Sum of two functions.
360  */
361 class Sum1 : public Func1
362 {
363 public:
Sum1(Func1 & f1,Func1 & f2)364     Sum1(Func1& f1, Func1& f2) :
365         Func1() {
366         m_f1 = &f1;
367         m_f2 = &f2;
368         m_f1->setParent(this);
369         m_f2->setParent(this);
370     }
371 
~Sum1()372     virtual ~Sum1() {
373         delete m_f1;
374         delete m_f2;
375     }
376 
Sum1(const Sum1 & b)377     Sum1(const Sum1& b) :
378         Func1(b) {
379         *this = Sum1::operator=(b);
380     }
381 
382     Sum1& operator=(const Sum1& right) {
383         if (&right == this) {
384             return *this;
385         }
386         Func1::operator=(right);
387         m_f1 = &m_f1->duplicate();
388         m_f2 = &m_f2->duplicate();
389         m_f1->setParent(this);
390         m_f2->setParent(this);
391         m_parent = 0;
392         return *this;
393     }
394 
ID()395     virtual int ID() const {
396         return SumFuncType;
397     }
398 
eval(doublereal t)399     virtual doublereal eval(doublereal t) const {
400         return m_f1->eval(t) + m_f2->eval(t);
401     }
402 
duplicate()403     virtual Func1& duplicate() const {
404         Func1& f1d = m_f1->duplicate();
405         Func1& f2d = m_f2->duplicate();
406         return newSumFunction(f1d, f2d);
407     }
408 
derivative()409     virtual Func1& derivative() const {
410         Func1& d1 = m_f1->derivative();
411         Func1& d2 = m_f2->derivative();
412         return newSumFunction(d1, d2);
413     }
order()414     virtual int order() const {
415         return 0;
416     }
417 
418     virtual std::string write(const std::string& arg) const;
419 };
420 
421 
422 /**
423  * Difference of two functions.
424  */
425 class Diff1 : public Func1
426 {
427 public:
Diff1(Func1 & f1,Func1 & f2)428     Diff1(Func1& f1, Func1& f2) {
429         m_f1 = &f1;
430         m_f2 = &f2;
431         m_f1->setParent(this);
432         m_f2->setParent(this);
433     }
434 
~Diff1()435     virtual ~Diff1() {
436         delete m_f1;
437         delete m_f2;
438     }
439 
Diff1(const Diff1 & b)440     Diff1(const Diff1& b) :
441         Func1(b) {
442         *this = Diff1::operator=(b);
443     }
444 
445     Diff1& operator=(const Diff1& right) {
446         if (&right == this) {
447             return *this;
448         }
449         Func1::operator=(right);
450         m_f1 = &m_f1->duplicate();
451         m_f2 = &m_f2->duplicate();
452         m_f1->setParent(this);
453         m_f2->setParent(this);
454         m_parent = 0;
455         return *this;
456     }
457 
ID()458     virtual int ID() const {
459         return DiffFuncType;
460     }
461 
eval(doublereal t)462     virtual doublereal eval(doublereal t) const {
463         return m_f1->eval(t) - m_f2->eval(t);
464     }
465 
duplicate()466     virtual Func1& duplicate() const {
467         Func1& f1d = m_f1->duplicate();
468         Func1& f2d = m_f2->duplicate();
469         return newDiffFunction(f1d, f2d);
470     }
derivative()471     virtual Func1& derivative() const {
472         return newDiffFunction(m_f1->derivative(), m_f2->derivative());
473     }
order()474     virtual int order() const {
475         return 0;
476     }
477 
478     virtual std::string write(const std::string& arg) const;
479 };
480 
481 
482 /**
483  * Product of two functions.
484  */
485 class Product1 : public Func1
486 {
487 public:
Product1(Func1 & f1,Func1 & f2)488     Product1(Func1& f1, Func1& f2) :
489         Func1() {
490         m_f1 = &f1;
491         m_f2 = &f2;
492         m_f1->setParent(this);
493         m_f2->setParent(this);
494     }
495 
~Product1()496     virtual ~Product1() {
497         delete m_f1;
498         delete m_f2;
499     }
500 
Product1(const Product1 & b)501     Product1(const Product1& b) :
502         Func1(b) {
503         *this = Product1::operator=(b);
504     }
505 
506     Product1& operator=(const Product1& right) {
507         if (&right == this) {
508             return *this;
509         }
510         Func1::operator=(right);
511         m_f1 = &m_f1->duplicate();
512         m_f2 = &m_f2->duplicate();
513         m_f1->setParent(this);
514         m_f2->setParent(this);
515         m_parent = 0;
516         return *this;
517     }
518 
ID()519     virtual int ID() const {
520         return ProdFuncType;
521     }
522 
duplicate()523     virtual Func1& duplicate() const {
524         Func1& f1d = m_f1->duplicate();
525         Func1& f2d = m_f2->duplicate();
526         return newProdFunction(f1d, f2d);
527     }
528 
529     virtual std::string write(const std::string& arg) const;
530 
eval(doublereal t)531     virtual doublereal eval(doublereal t) const {
532         return m_f1->eval(t) * m_f2->eval(t);
533     }
534 
derivative()535     virtual Func1& derivative() const {
536         Func1& a1 = newProdFunction(m_f1->duplicate(), m_f2->derivative());
537         Func1& a2 = newProdFunction(m_f2->duplicate(), m_f1->derivative());
538         return newSumFunction(a1, a2);
539     }
order()540     virtual int order() const {
541         return 1;
542     }
543 };
544 
545 /**
546  * Product of two functions.
547  */
548 class TimesConstant1 : public Func1
549 {
550 public:
TimesConstant1(Func1 & f1,doublereal A)551     TimesConstant1(Func1& f1, doublereal A) :
552         Func1() {
553         m_f1 = &f1;
554         m_c = A;
555         m_f1->setParent(this);
556     }
557 
~TimesConstant1()558     virtual ~TimesConstant1() {
559         delete m_f1;
560     }
561 
TimesConstant1(const TimesConstant1 & b)562     TimesConstant1(const TimesConstant1& b) :
563         Func1(b) {
564         *this = TimesConstant1::operator=(b);
565     }
566 
567     TimesConstant1& operator=(const TimesConstant1& right) {
568         if (&right == this) {
569             return *this;
570         }
571         Func1::operator=(right);
572         m_f1 = &m_f1->duplicate();
573         m_f1->setParent(this);
574         m_parent = 0;
575         return *this;
576     }
ID()577     virtual int ID() const {
578         return TimesConstantFuncType;
579     }
580 
duplicate()581     virtual Func1& duplicate() const {
582         Func1& f1 = m_f1->duplicate();
583         Func1* dup = new TimesConstant1(f1, m_c);
584         return *dup;
585     }
586 
isProportional(TimesConstant1 & other)587     virtual doublereal isProportional(TimesConstant1& other) {
588         if (func1().isIdentical(other.func1())) {
589             return (other.c()/c());
590         } else {
591             return 0.0;
592         }
593     }
594 
isProportional(Func1 & other)595     virtual doublereal isProportional(Func1& other) {
596         if (func1().isIdentical(other)) {
597             return 1.0/c();
598         } else {
599             return 0.0;
600         }
601     }
602 
eval(doublereal t)603     virtual doublereal eval(doublereal t) const {
604         return m_f1->eval(t) * m_c;
605     }
606 
derivative()607     virtual Func1& derivative() const {
608         Func1& f1d = m_f1->derivative();
609         Func1* d = &newTimesConstFunction(f1d, m_c);
610         return *d;
611     }
612 
613     virtual std::string write(const std::string& arg) const;
614 
order()615     virtual int order() const {
616         return 0;
617     }
618 };
619 
620 /**
621  * A function plus a constant.
622  */
623 class PlusConstant1 : public Func1
624 {
625 public:
PlusConstant1(Func1 & f1,doublereal A)626     PlusConstant1(Func1& f1, doublereal A) :
627         Func1() {
628         m_f1 = &f1;
629         m_c = A;
630         m_f1->setParent(this);
631     }
632 
~PlusConstant1()633     virtual ~PlusConstant1() {
634         delete m_f1;
635     }
636 
PlusConstant1(const PlusConstant1 & b)637     PlusConstant1(const PlusConstant1& b) :
638         Func1(b) {
639         *this = PlusConstant1::operator=(b);
640     }
641 
642     PlusConstant1& operator=(const PlusConstant1& right) {
643         if (&right == this) {
644             return *this;
645         }
646         Func1::operator=(right);
647         m_f1 = &m_f1->duplicate();
648         m_f1->setParent(this);
649         m_parent = 0;
650         return *this;
651     }
652 
ID()653     virtual int ID() const {
654         return PlusConstantFuncType;
655     }
656 
duplicate()657     virtual Func1& duplicate() const {
658         Func1& f1 = m_f1->duplicate();
659         Func1* dup = new PlusConstant1(f1, m_c);
660         return *dup;
661     }
662 
eval(doublereal t)663     virtual doublereal eval(doublereal t) const {
664         return m_f1->eval(t) + m_c;
665     }
derivative()666     virtual Func1& derivative() const {
667         return m_f1->derivative();
668     }
669     virtual std::string write(const std::string& arg) const;
670 
order()671     virtual int order() const {
672         return 0;
673     }
674 };
675 
676 
677 /**
678  * Ratio of two functions.
679  */
680 class Ratio1 : public Func1
681 {
682 public:
Ratio1(Func1 & f1,Func1 & f2)683     Ratio1(Func1& f1, Func1& f2) :
684         Func1() {
685         m_f1 = &f1;
686         m_f2 = &f2;
687         m_f1->setParent(this);
688         m_f2->setParent(this);
689     }
690 
~Ratio1()691     virtual ~Ratio1() {
692         delete m_f1;
693         delete m_f2;
694     }
695 
Ratio1(const Ratio1 & b)696     Ratio1(const Ratio1& b) :
697         Func1(b) {
698         *this = Ratio1::operator=(b);
699     }
700 
701     Ratio1& operator=(const Ratio1& right) {
702         if (&right == this) {
703             return *this;
704         }
705         Func1::operator=(right);
706         m_f1 = &m_f1->duplicate();
707         m_f2 = &m_f2->duplicate();
708         m_f1->setParent(this);
709         m_f2->setParent(this);
710         m_parent = 0;
711         return *this;
712     }
713 
ID()714     virtual int ID() const {
715         return RatioFuncType;
716     }
717 
eval(doublereal t)718     virtual doublereal eval(doublereal t) const {
719         return m_f1->eval(t) / m_f2->eval(t);
720     }
721 
duplicate()722     virtual Func1& duplicate() const {
723         Func1& f1d = m_f1->duplicate();
724         Func1& f2d = m_f2->duplicate();
725         return newRatioFunction(f1d, f2d);
726     }
727 
derivative()728     virtual Func1& derivative() const {
729         Func1& a1 = newProdFunction(m_f1->derivative(), m_f2->duplicate());
730         Func1& a2 = newProdFunction(m_f1->duplicate(), m_f2->derivative());
731         Func1& s = newDiffFunction(a1, a2);
732         Func1& p = newProdFunction(m_f2->duplicate(), m_f2->duplicate());
733         return newRatioFunction(s, p);
734     }
735 
736     virtual std::string write(const std::string& arg) const;
737 
order()738     virtual int order() const {
739         return 1;
740     }
741 };
742 
743 /**
744  * Composite function.
745  */
746 class Composite1 : public Func1
747 {
748 public:
Composite1(Func1 & f1,Func1 & f2)749     Composite1(Func1& f1, Func1& f2) :
750         Func1() {
751         m_f1 = &f1;
752         m_f2 = &f2;
753         m_f1->setParent(this);
754         m_f2->setParent(this);
755     }
756 
~Composite1()757     virtual ~Composite1() {
758         delete m_f1;
759         delete m_f2;
760     }
761 
Composite1(const Composite1 & b)762     Composite1(const Composite1& b) :
763         Func1(b) {
764         *this = Composite1::operator=(b);
765     }
766 
767     Composite1& operator=(const Composite1& right) {
768         if (&right == this) {
769             return *this;
770         }
771         Func1::operator=(right);
772         m_f1 = &m_f1->duplicate();
773         m_f2 = &m_f2->duplicate();
774         m_f1->setParent(this);
775         m_f2->setParent(this);
776         m_parent = 0;
777         return *this;
778     }
779 
ID()780     virtual int ID() const {
781         return CompositeFuncType;
782     }
783 
eval(doublereal t)784     virtual doublereal eval(doublereal t) const {
785         return m_f1->eval(m_f2->eval(t));
786     }
787 
duplicate()788     virtual Func1& duplicate() const {
789         Func1& f1d = m_f1->duplicate();
790         Func1& f2d = m_f2->duplicate();
791         return newCompositeFunction(f1d, f2d);
792     }
793 
derivative()794     virtual Func1& derivative() const {
795         Func1* d1 = &m_f1->derivative();
796 
797         Func1* d3 = &newCompositeFunction(*d1, m_f2->duplicate());
798         Func1* d2 = &m_f2->derivative();
799         Func1* p = &newProdFunction(*d3, *d2);
800         return *p;
801     }
802 
803     virtual std::string write(const std::string& arg) const;
804 
order()805     virtual int order() const {
806         return 2;
807     }
808 };
809 
810 // The functors below are the old-style ones. They still work,
811 // but can't do derivatives.
812 
813 /**
814  * A Gaussian.
815  * \f[
816  * f(t) = A e^{-[(t - t_0)/\tau]^2}
817  * \f]
818  * where \f[ \tau = \frac{fwhm}{2\sqrt{\ln 2}} \f]
819  * @param A peak value
820  * @param t0 offset
821  * @param fwhm full width at half max
822  */
823 class Gaussian : public Func1
824 {
825 public:
Gaussian(double A,double t0,double fwhm)826     Gaussian(double A, double t0, double fwhm) :
827         Func1() {
828         m_A = A;
829         m_t0 = t0;
830         m_tau = fwhm/(2.0*std::sqrt(std::log(2.0)));
831     }
832 
Gaussian(const Gaussian & b)833     Gaussian(const Gaussian& b) :
834         Func1(b) {
835         *this = Gaussian::operator=(b);
836     }
837 
838     Gaussian& operator=(const Gaussian& right) {
839         if (&right == this) {
840             return *this;
841         }
842         Func1::operator=(right);
843         m_A = right.m_A;
844         m_t0 = right.m_t0;
845         m_tau = right.m_tau;
846         m_parent = 0;
847         return *this;
848     }
849 
duplicate()850     virtual Func1& duplicate() const {
851         Gaussian* np = new Gaussian(*this);
852         return *((Func1*)np);
853     }
854 
eval(doublereal t)855     virtual doublereal eval(doublereal t) const {
856         doublereal x = (t - m_t0)/m_tau;
857         return m_A * std::exp(-x*x);
858     }
859 
860 protected:
861     doublereal m_A, m_t0, m_tau;
862 };
863 
864 
865 /**
866  * Polynomial of degree n.
867  */
868 class Poly1 : public Func1
869 {
870 public:
Poly1(size_t n,const double * c)871     Poly1(size_t n, const double* c) :
872         Func1() {
873         m_cpoly.resize(n+1);
874         std::copy(c, c+m_cpoly.size(), m_cpoly.begin());
875     }
876 
Poly1(const Poly1 & b)877     Poly1(const Poly1& b) :
878         Func1(b) {
879         *this = Poly1::operator=(b);
880     }
881 
882     Poly1& operator=(const Poly1& right) {
883         if (&right == this) {
884             return *this;
885         }
886         Func1::operator=(right);
887         m_cpoly = right.m_cpoly;
888         m_parent = 0;
889         return *this;
890     }
891 
duplicate()892     virtual Func1& duplicate() const {
893         Poly1* np = new Poly1(*this);
894         return *((Func1*)np);
895     }
896 
eval(doublereal t)897     virtual doublereal eval(doublereal t) const {
898         doublereal r = m_cpoly[m_cpoly.size()-1];
899         for (size_t n = 1; n < m_cpoly.size(); n++) {
900             r *= t;
901             r += m_cpoly[m_cpoly.size() - n - 1];
902         }
903         return r;
904     }
905 
906 protected:
907     vector_fp m_cpoly;
908 };
909 
910 
911 /**
912  * Fourier cosine/sine series.
913  *
914  * \f[
915  * f(t) = \frac{A_0}{2} +
916  * \sum_{n=1}^N A_n \cos (n \omega t) + B_n \sin (n \omega t)
917  * \f]
918  */
919 class Fourier1 : public Func1
920 {
921 public:
Fourier1(size_t n,double omega,double a0,const double * a,const double * b)922     Fourier1(size_t n, double omega, double a0,
923              const double* a, const double* b) :
924         Func1() {
925         m_omega = omega;
926         m_a0_2 = 0.5*a0;
927         m_ccos.resize(n);
928         m_csin.resize(n);
929         std::copy(a, a+n, m_ccos.begin());
930         std::copy(b, b+n, m_csin.begin());
931     }
932 
Fourier1(const Fourier1 & b)933     Fourier1(const Fourier1& b) :
934         Func1(b) {
935         *this = Fourier1::operator=(b);
936     }
937 
938     Fourier1& operator=(const Fourier1& right) {
939         if (&right == this) {
940             return *this;
941         }
942         Func1::operator=(right);
943         m_omega = right.m_omega;
944         m_a0_2 = right.m_a0_2;
945         m_ccos = right.m_ccos;
946         m_csin = right.m_csin;
947         m_parent = 0;
948         return *this;
949     }
950 
duplicate()951     virtual Func1& duplicate() const {
952         Fourier1* np = new Fourier1(*this);
953         return *((Func1*)np);
954     }
955 
eval(doublereal t)956     virtual doublereal eval(doublereal t) const {
957         size_t n, nn;
958         doublereal sum = m_a0_2;
959         for (n = 0; n < m_ccos.size(); n++) {
960             nn = n + 1;
961             sum += m_ccos[n]*std::cos(m_omega*nn*t)
962                    + m_csin[n]*std::sin(m_omega*nn*t);
963         }
964         return sum;
965     }
966 
967 protected:
968     doublereal m_omega, m_a0_2;
969     vector_fp m_ccos, m_csin;
970 };
971 
972 
973 /**
974  * Sum of Arrhenius terms.
975  * \f[
976  * f(T) = \sum_{n=1}^N A_n T^b_n \exp(-E_n/T)
977  * \f]
978  */
979 class Arrhenius1 : public Func1
980 {
981 public:
Arrhenius1(size_t n,const double * c)982     Arrhenius1(size_t n, const double* c) :
983         Func1() {
984         m_A.resize(n);
985         m_b.resize(n);
986         m_E.resize(n);
987         for (size_t i = 0; i < n; i++) {
988             size_t loc = 3*i;
989             m_A[i] = c[loc];
990             m_b[i] = c[loc+1];
991             m_E[i] = c[loc+2];
992         }
993     }
994 
Arrhenius1(const Arrhenius1 & b)995     Arrhenius1(const Arrhenius1& b) :
996         Func1() {
997         *this = Arrhenius1::operator=(b);
998     }
999 
1000     Arrhenius1& operator=(const Arrhenius1& right) {
1001         if (&right == this) {
1002             return *this;
1003         }
1004         Func1::operator=(right);
1005         m_A = right.m_A;
1006         m_b = right.m_b;
1007         m_E = right.m_E;
1008         m_parent = 0;
1009         return *this;
1010     }
1011 
duplicate()1012     virtual Func1& duplicate() const {
1013         Arrhenius1* np = new Arrhenius1(*this);
1014         return *((Func1*)np);
1015     }
1016 
eval(doublereal t)1017     virtual doublereal eval(doublereal t) const {
1018         doublereal sum = 0.0;
1019         for (size_t n = 0; n < m_A.size(); n++) {
1020             sum += m_A[n]*std::pow(t,m_b[n])*std::exp(-m_E[n]/t);
1021         }
1022         return sum;
1023     }
1024 
1025 protected:
1026     vector_fp m_A, m_b, m_E;
1027 };
1028 
1029 /**
1030  *  Periodic function. Takes any function and makes it periodic with period T.
1031  */
1032 class Periodic1 : public Func1
1033 {
1034 public:
Periodic1(Func1 & f,doublereal T)1035     Periodic1(Func1& f, doublereal T) :
1036         Func1() {
1037         m_func = &f;
1038         m_c = T;
1039     }
1040 
Periodic1(const Periodic1 & b)1041     Periodic1(const Periodic1& b) :
1042         Func1() {
1043         *this = Periodic1::operator=(b);
1044     }
1045 
1046     Periodic1& operator=(const Periodic1& right) {
1047         if (&right == this) {
1048             return *this;
1049         }
1050         Func1::operator=(right);
1051         m_func = &right.m_func->duplicate();
1052         return *this;
1053     }
1054 
duplicate()1055     virtual Func1& duplicate() const {
1056         Periodic1* np = new Periodic1(*this);
1057         return *((Func1*)np);
1058     }
1059 
~Periodic1()1060     virtual ~Periodic1() {
1061         delete m_func;
1062     }
1063 
eval(doublereal t)1064     virtual doublereal eval(doublereal t) const {
1065         int np = int(t/m_c);
1066         doublereal time = t - np*m_c;
1067         return m_func->eval(time);
1068     }
1069 
1070 protected:
1071     Func1* m_func;
1072 };
1073 
1074 }
1075 
1076 #endif
1077