Reaktoro 
A unified framework for modeling chemically reactive systems
ThermoScalar.hpp
1 // Reaktoro is a unified framework for modeling chemically reactive systems.
2 //
3 // Copyright (C) 2014-2015 Allan Leal
4 //
5 // This program is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18 #pragma once
19 
20 // C++ includes
21 #include <cmath>
22 #include <iostream>
23 
24 // Reaktoro includes
25 #include <Reaktoro/Math/Matrix.hpp>
26 
27 namespace Reaktoro {
28 
29 // Forward declaration
30 template<typename V>
31 class ThermoScalarBase;
32 
39 using ThermoScalar = ThermoScalarBase<double>;
40 
44 template<typename V>
45 class ThermoScalarBase
46 {
47 public:
49  V val;
50 
52  V ddT;
53 
55  V ddP;
56 
59  : ThermoScalarBase(0.0) {}
60 
63  explicit ThermoScalarBase(double val)
64  : ThermoScalarBase(val, 0.0, 0.0) {}
65 
70  ThermoScalarBase(const V& val, const V& ddT, const V& ddP)
71  : val(val), ddT(ddT), ddP(ddP) {}
72 
74  template<typename VR>
76  : val(other.val), ddT(other.ddT), ddP(other.ddP) {}
77 
79  template<typename VR>
81  {
82  val = other.val;
83  ddT = other.ddT;
84  ddP = other.ddP;
85  return *this;
86  }
87 
89  auto operator=(double other) -> ThermoScalarBase&
90  {
91  val = other;
92  ddT = 0.0;
93  ddP = 0.0;
94  return *this;
95  }
96 
98  template<typename VR>
100  {
101  val += other.val;
102  ddT += other.ddT;
103  ddP += other.ddP;
104  return *this;
105  }
106 
108  template<typename VR>
110  {
111  val -= other.val;
112  ddT -= other.ddT;
113  ddP -= other.ddP;
114  return *this;
115  }
116 
118  template<typename VR>
120  {
121  ddT = ddT * other.val + val * other.ddT;
122  ddP = ddP * other.val + val * other.ddP;
123  val *= other.val;
124  return *this;
125  }
126 
128  template<typename VR>
130  {
131  const double tmp1 = 1.0/other.val;
132  const double tmp2 = tmp1 * tmp1;
133  ddT = (ddT * other.val - val * other.ddT) * tmp2;
134  ddP = (ddP * other.val - val * other.ddP) * tmp2;
135  val *= tmp1;
136  return *this;
137  }
138 
140  auto operator+=(double other) -> ThermoScalarBase&
141  {
142  val += other;
143  return *this;
144  }
145 
147  auto operator-=(double other) -> ThermoScalarBase&
148  {
149  val -= other;
150  return *this;
151  }
152 
154  auto operator*=(double other) -> ThermoScalarBase&
155  {
156  val *= other;
157  ddT *= other;
158  ddP *= other;
159  return *this;
160  }
161 
163  auto operator/=(double other) -> ThermoScalarBase&
164  {
165  *this *= 1.0/other;
166  return *this;
167  }
168 
170  explicit operator double() const
171  {
172  return val;
173  }
174 };
175 
177 class Temperature : public ThermoScalar
178 {
179 public:
182 
184  Temperature(double val) : ThermoScalarBase(val, 1.0, 0.0) {}
185 
187  explicit operator double() const
188  {
189  return val;
190  }
191 };
192 
194 class Pressure : public ThermoScalar
195 {
196 public:
198  Pressure() : Pressure(0.0) {}
199 
201  Pressure(double val) : ThermoScalarBase(val, 0.0, 1.0) {}
202 
204  explicit operator double() const
205  {
206  return val;
207  }
208 };
209 
210 template<typename V>
211 auto operator+(const ThermoScalarBase<V>& l) -> ThermoScalarBase<double>
212 {
213  return l;
214 }
215 
216 template<typename VL, typename VR>
217 auto operator+(const ThermoScalarBase<VL>& l, const ThermoScalarBase<VR>& r) -> ThermoScalarBase<double>
218 {
219  return {l.val + r.val, l.ddT + r.ddT, l.ddP + r.ddP};
220 }
221 
222 template<typename V>
223 auto operator+(double l, const ThermoScalarBase<V>& r) -> ThermoScalarBase<double>
224 {
225  return {l + r.val, r.ddT, r.ddP};
226 }
227 
228 template<typename V>
229 auto operator+(const ThermoScalarBase<V>& l, double r) -> ThermoScalarBase<double>
230 {
231  return r + l;
232 }
233 
234 template<typename V>
235 auto operator-(const ThermoScalarBase<V>& l) -> ThermoScalarBase<double>
236 {
237  return {-l.val, -l.ddT, -l.ddP};
238 }
239 
240 template<typename VL, typename VR>
241 auto operator-(const ThermoScalarBase<VL>& l, const ThermoScalarBase<VR>& r) -> ThermoScalarBase<double>
242 {
243  return {l.val - r.val, l.ddT - r.ddT, l.ddP - r.ddP};
244 }
245 
246 template<typename V>
247 auto operator-(const ThermoScalarBase<V>& l, double r) -> ThermoScalarBase<double>
248 {
249  return {l.val - r, l.ddT, l.ddP};
250 }
251 
252 template<typename V>
253 auto operator-(double l, const ThermoScalarBase<V>& r) -> ThermoScalarBase<double>
254 {
255  return {l - r.val, -r.ddT, -r.ddP};
256 }
257 
258 template<typename VL, typename VR>
259 auto operator*(const ThermoScalarBase<VL>& l, const ThermoScalarBase<VR>& r) -> ThermoScalarBase<double>
260 {
261  return {l.val * r.val, l.val * r.ddT + l.ddT * r.val, l.val * r.ddP + l.ddP * r.val};
262 }
263 
264 template<typename V>
265 auto operator*(double l, const ThermoScalarBase<V>& r) -> ThermoScalarBase<double>
266 {
267  return {l * r.val, l * r.ddT, l * r.ddP};
268 }
269 
270 template<typename V>
271 auto operator*(const ThermoScalarBase<V>& l, double r) -> ThermoScalarBase<double>
272 {
273  return r * l;
274 }
275 
276 template<typename VL, typename VR>
277 auto operator/(const ThermoScalarBase<VL>& l, const ThermoScalarBase<VR>& r) -> ThermoScalarBase<double>
278 {
279  const double tmp1 = 1.0/r.val;
280  const double tmp2 = tmp1 * tmp1;
281  return {tmp1 * l.val, tmp2 * (l.ddT * r.val - l.val * r.ddT), tmp2 * (l.ddP * r.val - l.val * r.ddP)};
282 }
283 
284 template<typename V>
285 auto operator/(double l, const ThermoScalarBase<V>& r) -> ThermoScalarBase<double>
286 {
287  const double tmp1 = 1.0/r.val;
288  const double tmp2 = -l*tmp1*tmp1;
289  return {tmp1 * l, tmp2 * r.ddT, tmp2 * r.ddP};
290 }
291 
292 template<typename V>
293 auto operator/(const ThermoScalarBase<V>& l, double r) -> ThermoScalarBase<double>
294 {
295  return (1.0/r) * l;
296 }
297 
298 template<typename VL, typename VR>
299 auto operator<(const ThermoScalarBase<VL>& l, const ThermoScalarBase<VR>& r) -> bool
300 {
301  return l.val < r.val;
302 }
303 
304 template<typename VL, typename VR>
305 auto operator<=(const ThermoScalarBase<VL>& l, const ThermoScalarBase<VR>& r) -> bool
306 {
307  return l.val <= r.val;
308 }
309 
310 template<typename VL, typename VR>
311 auto operator>(const ThermoScalarBase<VL>& l, const ThermoScalarBase<VR>& r) -> bool
312 {
313  return l.val > r.val;
314 }
315 
316 template<typename VL, typename VR>
317 auto operator>=(const ThermoScalarBase<VL>& l, const ThermoScalarBase<VR>& r) -> bool
318 {
319  return l.val >= r.val;
320 }
321 
322 template<typename VL, typename VR>
323 auto operator==(const ThermoScalarBase<VL>& l, const ThermoScalarBase<VR>& r) -> bool
324 {
325  return l.val == r.val;
326 }
327 
328 template<typename VL, typename VR>
329 auto operator!=(const ThermoScalarBase<VL>& l, const ThermoScalarBase<VR>& r) -> bool
330 {
331  return l.val != r.val;
332 }
333 
334 template<typename V>
335 auto operator<(double l, const ThermoScalarBase<V>& r) -> bool
336 {
337  return l < r.val;
338 }
339 
340 template<typename V>
341 auto operator<(const ThermoScalarBase<V>& l, double r) -> bool
342 {
343  return l.val < r;
344 }
345 
346 template<typename V>
347 auto operator<=(double l, const ThermoScalarBase<V>& r) -> bool
348 {
349  return l <= r.val;
350 }
351 
352 template<typename V>
353 auto operator<=(const ThermoScalarBase<V>& l, double r) -> bool
354 {
355  return l.val <= r;
356 }
357 
358 template<typename V>
359 auto operator>(double l, const ThermoScalarBase<V>& r) -> bool
360 {
361  return l > r.val;
362 }
363 
364 template<typename V>
365 auto operator>(const ThermoScalarBase<V>& l, double r) -> bool
366 {
367  return l.val > r;
368 }
369 
370 template<typename V>
371 auto operator>=(double l, const ThermoScalarBase<V>& r) -> bool
372 {
373  return l >= r.val;
374 }
375 
376 template<typename V>
377 auto operator>=(const ThermoScalarBase<V>& l, double r) -> bool
378 {
379  return l.val >= r;
380 }
381 
382 template<typename V>
383 auto operator==(double l, const ThermoScalarBase<V>& r) -> bool
384 {
385  return l == r.val;
386 }
387 
388 template<typename V>
389 auto operator==(const ThermoScalarBase<V>& l, double r) -> bool
390 {
391  return l.val == r;
392 }
393 
394 template<typename V>
395 auto operator!=(double l, const ThermoScalarBase<V>& r) -> bool
396 {
397  return l != r.val;
398 }
399 
400 template<typename V>
401 auto operator!=(const ThermoScalarBase<V>& l, double r) -> bool
402 {
403  return l.val != r;
404 }
405 
406 template<typename V>
407 auto operator<<(std::ostream& out, const ThermoScalarBase<V>& scalar) -> std::ostream&
408 {
409  out << scalar.val;
410  return out;
411 }
412 
413 template<typename V>
414 auto abs(const ThermoScalarBase<V>& l) -> ThermoScalarBase<double>
415 {
416  if(l.val == 0.0) return {};
417  const double tmp1 = std::abs(l.val);
418  const double tmp2 = l.val/tmp1;
419  return {tmp1, tmp2 * l.ddT, tmp2 * l.ddP};
420 }
421 
422 template<typename V>
423 auto sqrt(const ThermoScalarBase<V>& l) -> ThermoScalarBase<double>
424 {
425  if(l.val == 0.0) return {};
426  const double tmp1 = std::sqrt(l.val);
427  const double tmp2 = 0.5 * tmp1/l.val;
428  return {tmp1, tmp2 * l.ddT, tmp2 * l.ddP};
429 }
430 
431 template<typename V>
432 auto pow(const ThermoScalarBase<V>& l, double power) -> ThermoScalarBase<double>
433 {
434  if(l.val == 0.0) return {};
435  const double tmp1 = std::pow(l.val, power - 1);
436  const double tmp2 = power * tmp1;
437  return {tmp1 * l.val, tmp2 * l.ddT, tmp2 * l.ddP};
438 }
439 
440 template<typename VL, typename VR>
441 auto pow(const ThermoScalarBase<VL>& l, const ThermoScalarBase<VR>& power) -> ThermoScalarBase<double>
442 {
443  if(l.val == 0.0) return {};
444  const double logl = std::log(l.val);
445  const double powl = std::pow(l.val, power.val);
446  const double tmp = power.val/l.val;
447  return {powl, powl * (logl * power.ddT + tmp * l.ddT), powl * (logl * power.ddP + tmp * l.ddP)};
448 }
449 
450 template<typename V>
451 auto exp(const ThermoScalarBase<V>& l) -> ThermoScalarBase<double>
452 {
453  const double tmp = std::exp(l.val);
454  return {tmp, tmp * l.ddT, tmp * l.ddP};
455 }
456 
457 template<typename V>
458 auto log(const ThermoScalarBase<V>& l) -> ThermoScalarBase<double>
459 {
460  const double tmp1 = std::log(l.val);
461  const double tmp2 = 1.0/l.val;
462  return {tmp1, tmp2 * l.ddT, tmp2 * l.ddP};
463 }
464 
465 template<typename V>
466 auto log10(const ThermoScalarBase<V>& l) -> ThermoScalarBase<double>
467 {
468  const double ln10 = 2.302585092994046;
469  return log(l)/ln10;
470 }
471 
472 } // namespace Reaktoro
V val
The value of the thermodynamic property.
Definition: ThermoScalar.hpp:49
ThermoScalarBase(double val)
Construct a custom ThermoScalarBase instance with given value only.
Definition: ThermoScalar.hpp:63
V ddP
The partial pressure derivative of the thermodynamic property.
Definition: ThermoScalar.hpp:55
auto operator=(const ThermoScalarBase< VR > &other) -> ThermoScalarBase &
Assign another ThermoScalarBase instance to this ThermoScalarBase instance.
Definition: ThermoScalar.hpp:80
Temperature()
Construct a default Temperature instance.
Definition: ThermoScalar.hpp:181
Pressure()
Construct a default Pressure instance.
Definition: ThermoScalar.hpp:198
auto operator*=(double other) -> ThermoScalarBase &
Assign-multiplication of a ThermoScalar instance.
Definition: ThermoScalar.hpp:154
auto operator+=(double other) -> ThermoScalarBase &
Assign-addition of a scalar.
Definition: ThermoScalar.hpp:140
auto operator/=(double other) -> ThermoScalarBase &
Assign-division of a ThermoScalar instance.
Definition: ThermoScalar.hpp:163
auto operator*=(const ThermoScalarBase< VR > &other) -> ThermoScalarBase &
Assign-multiplication of a ThermoScalar instance.
Definition: ThermoScalar.hpp:119
ThermoScalarBase()
Construct a default ThermoScalar instance.
Definition: ThermoScalar.hpp:58
V ddT
The partial temperature derivative of the thermodynamic property.
Definition: ThermoScalar.hpp:52
Pressure(double val)
Construct a Pressure instance with given value.
Definition: ThermoScalar.hpp:201
Temperature(double val)
Construct a Temperature instance with given value.
Definition: ThermoScalar.hpp:184
A template base class to represent a thermodynamic scalar and its partial derivatives.
Definition: ScalarTypes.hpp:29
auto operator/=(const ThermoScalarBase< VR > &other) -> ThermoScalarBase &
Assign-division of a ThermoScalar instance.
Definition: ThermoScalar.hpp:129
auto operator=(double other) -> ThermoScalarBase &
Assign a scalar to this ThermoScalarBase instance.
Definition: ThermoScalar.hpp:89
A type that describes temperature in units of K.
Definition: ThermoScalar.hpp:177
ThermoScalarBase< double > ThermoScalar
A type that defines a scalar thermo property.
Definition: ScalarTypes.hpp:40
auto operator-=(const ThermoScalarBase< VR > &other) -> ThermoScalarBase &
Assign-subtraction of a ThermoScalar instance.
Definition: ThermoScalar.hpp:109
auto operator-=(double other) -> ThermoScalarBase &
Assign-subtraction of a scalar.
Definition: ThermoScalar.hpp:147
ThermoScalarBase(const V &val, const V &ddT, const V &ddP)
Construct a custom ThermoScalarBase instance with given value and derivatives.
Definition: ThermoScalar.hpp:70
ThermoScalarBase(const ThermoScalarBase< VR > &other)
Construct a copy of a ThermoScalar instance.
Definition: ThermoScalar.hpp:75
auto operator+=(const ThermoScalarBase< VR > &other) -> ThermoScalarBase &
Assign-addition of a ThermoScalar instance.
Definition: ThermoScalar.hpp:99
A type that describes pressure in units of Pa.
Definition: ThermoScalar.hpp:194
The namespace containing all components of the Reaktoro library.
Definition: ChemicalScalar.hpp:24