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