Reaktoro
A unified framework for modeling chemically reactive systems
ChemicalScalar.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 // Reaktoro includes
21 #include <Reaktoro/Math/Matrix.hpp>
22 #include <Reaktoro/Common/ThermoScalar.hpp>
23 
24 namespace Reaktoro {
25 
26 // Forward declaration
27 template<typename V, typename N>
28 class ChemicalScalarBase;
29 
36 
38 using ChemicalScalarRef = ChemicalScalarBase<double&, Eigen::Ref<RowVector, 0, Eigen::InnerStride<Eigen::Dynamic>>>; // Relax inner stride (dynamic, instead of default) so that a matrix row can be represented using Ref
39 
42 
47 template<typename V, typename N>
49 {
50 public:
52  V val;
53 
55  V ddT;
56 
58  V ddP;
59 
61  N ddn;
62 
65  : val(), ddT(), ddP(), ddn() {}
66 
69  explicit ChemicalScalarBase(Index nspecies)
70  : ChemicalScalarBase(0.0, 0.0, 0.0, RowVector::Zero(nspecies)) {}
71 
75  ChemicalScalarBase(Index nspecies, double val)
76  : ChemicalScalarBase(val, 0.0, 0.0, RowVector::Zero(nspecies)) {}
77 
83  ChemicalScalarBase(const V& val, const V& ddT, const V& ddP, const N& ddn)
84  : val(val), ddT(ddT), ddP(ddP), ddn(ddn) {}
85 
87  template<typename VR, typename NR>
89  : val(other.val), ddT(other.ddT), ddP(other.ddP), ddn(other.ddn) {}
90 
92  template<typename VR, typename NR>
94  : val(other.val), ddT(other.ddT), ddP(other.ddP), ddn(other.ddn) {}
95 
98  {
99  val = other.val;
100  ddT = other.ddT;
101  ddP = other.ddP;
102  ddn = other.ddn;
103  return *this;
104  }
105 
107  template<typename VR, typename NR>
109  {
110  val = other.val;
111  ddT = other.ddT;
112  ddP = other.ddP;
113  ddn = other.ddn;
114  return *this;
115  }
116 
118  template<typename VR>
120  {
121  val = other.val;
122  ddT = other.ddT;
123  ddP = other.ddP;
124  ddn.fill(0.0);
125  return *this;
126  }
127 
129  auto operator=(double other) -> ChemicalScalarBase&
130  {
131  val = other;
132  ddT = 0.0;
133  ddP = 0.0;
134  ddn.fill(0.0);
135  return *this;
136  }
137 
139  template<typename VR, typename NR>
141  {
142  val += other.val;
143  ddT += other.ddT;
144  ddP += other.ddP;
145  ddn += other.ddn;
146  return *this;
147  }
148 
150  template<typename VR>
152  {
153  val += other.val;
154  ddT += other.ddT;
155  ddP += other.ddP;
156  return *this;
157  }
158 
160  auto operator+=(double other) -> ChemicalScalarBase&
161  {
162  val += other;
163  return *this;
164  }
165 
167  template<typename VR, typename NR>
169  {
170  val -= other.val;
171  ddT -= other.ddT;
172  ddP -= other.ddP;
173  ddn -= other.ddn;
174  return *this;
175  }
176 
178  template<typename VR>
180  {
181  val -= other.val;
182  ddT -= other.ddT;
183  ddP -= other.ddP;
184  return *this;
185  }
186 
188  auto operator-=(double other) -> ChemicalScalarBase&
189  {
190  val -= other;
191  return *this;
192  }
193 
195  template<typename VR, typename NR>
197  {
198  ddT = ddT * other.val + val * other.ddT;
199  ddP = ddP * other.val + val * other.ddP;
200  ddn = ddn * other.val + val * other.ddn;
201  val *= other.val;
202  return *this;
203  }
204 
206  auto operator*=(double other) -> ChemicalScalarBase&
207  {
208  val *= other;
209  ddT *= other;
210  ddP *= other;
211  ddn *= other;
212  return *this;
213  }
214 
216  auto operator/=(double other) -> ChemicalScalarBase&
217  {
218  *this *= 1.0/other;
219  return *this;
220  }
221 
223  explicit operator double() const
224  {
225  return val;
226  }
227 };
228 
233 inline auto amount(double value, Index nspecies, Index ispecies) -> ChemicalScalarBase<double, decltype(tr(unit(nspecies, ispecies)))>
234 {
235  return {value, 0.0, 0.0, tr(unit(nspecies, ispecies))};
236 }
237 
238 template<typename V, typename N>
239 auto operator+(const ChemicalScalarBase<V,N>& l) -> ChemicalScalarBase<V,N>
240 {
241  return l;
242 }
243 
244 template<typename V, typename N>
245 auto operator-(const ChemicalScalarBase<V,N>& l) -> ChemicalScalarBase<double, decltype(-l.ddn)>
246 {
247  return {-l.val, -l.ddT, -l.ddP, -l.ddn};
248 }
249 
250 template<typename VL, typename NL, typename VR, typename NR>
251 auto operator+(const ChemicalScalarBase<VL,NL>& l, const ChemicalScalarBase<VR,NR>& r) -> ChemicalScalarBase<double, decltype(l.ddn + r.ddn)>
252 {
253  return {l.val + r.val, l.ddT + r.ddT, l.ddP + r.ddP, l.ddn + r.ddn};
254 }
255 
256 template<typename VL, typename NL, typename VR>
257 auto operator+(const ChemicalScalarBase<VL,NL>& l, const ThermoScalarBase<VR>& r) -> ChemicalScalarBase<double, decltype(l.ddn)>
258 {
259  return {l.val + r.val, l.ddT + r.ddT, l.ddP + r.ddP, l.ddn};
260 }
261 
262 template<typename VL, typename VR, typename NR>
263 auto operator+(const ThermoScalarBase<VL>& l, const ChemicalScalarBase<VR,NR>& r) -> decltype(r + l)
264 {
265  return r + l;
266 }
267 
268 template<typename V, typename N>
269 auto operator+(const ChemicalScalarBase<V,N>& l, double r) -> ChemicalScalarBase<double, decltype(l.ddn)>
270 {
271  return {l.val + r, l.ddT, l.ddP, l.ddn};
272 }
273 
274 template<typename V, typename N>
275 auto operator+(double l, const ChemicalScalarBase<V,N>& r) -> decltype(r + l)
276 {
277  return r + l;
278 }
279 
280 template<typename VL, typename NL, typename VR, typename NR>
281 auto operator-(const ChemicalScalarBase<VL,NL>& l, const ChemicalScalarBase<VR,NR>& r) -> ChemicalScalarBase<double, decltype(l.ddn - r.ddn)>
282 {
283  return {l.val - r.val, l.ddT - r.ddT, l.ddP - r.ddP, l.ddn - r.ddn};
284 }
285 
286 template<typename VL, typename NL, typename VR>
287 auto operator-(const ChemicalScalarBase<VL,NL>& l, const ThermoScalarBase<VR>& r) -> ChemicalScalarBase<double, decltype(l.ddn)>
288 {
289  return {l.val - r.val, l.ddT - r.ddT, l.ddP - r.ddP, l.ddn};
290 }
291 
292 template<typename VL, typename VR, typename NR>
293 auto operator-(const ThermoScalarBase<VL>& l, const ChemicalScalarBase<VR,NR>& r) -> ChemicalScalarBase<double, decltype(-r.ddn)>
294 {
295  return {l.val - r.val, l.ddT - r.ddT, l.ddP - r.ddP, -r.ddn};
296 }
297 
298 template<typename V, typename N>
299 auto operator-(const ChemicalScalarBase<V,N>& l, double r) -> ChemicalScalarBase<double, decltype(l.ddn)>
300 {
301  return {l.val - r, l.ddT, l.ddP, l.ddn};
302 }
303 
304 template<typename V, typename N>
305 auto operator-(double l, const ChemicalScalarBase<V,N>& r) -> ChemicalScalarBase<double, decltype(-r.ddn)>
306 {
307  return {l - r.val, -r.ddT, -r.ddP, -r.ddn};
308 }
309 
310 template<typename V, typename N>
311 auto operator*(double l, const ChemicalScalarBase<V,N>& r) -> ChemicalScalarBase<double, decltype(l * r.ddn)>
312 {
313  return {l * r.val, l * r.ddT, l * r.ddP, l * r.ddn};
314 }
315 
316 template<typename V, typename N>
317 auto operator*(const ChemicalScalarBase<V,N>& l, double r) -> decltype(r * l)
318 {
319  return r * l;
320 }
321 
322 template<typename VL, typename VR, typename NR>
323 auto operator*(const ThermoScalarBase<VL>& l, const ChemicalScalarBase<VR,NR>& r) -> ChemicalScalarBase<double, decltype(l.val * r.ddn)>
324 {
325  return {l.val * r.val, l.val * r.ddT + l.ddT * r.val, l.val * r.ddP + l.ddP * r.val, l.val * r.ddn};
326 }
327 
328 template<typename VL, typename NL, typename VR>
329 auto operator*(const ChemicalScalarBase<VL,NL>& l, const ThermoScalarBase<VR>& r) -> decltype(r * l)
330 {
331  return r * l;
332 }
333 
334 template<typename VL, typename NL, typename VR, typename NR>
335 auto operator*(const ChemicalScalarBase<VL,NL>& l, const ChemicalScalarBase<VR,NR>& r) -> ChemicalScalarBase<double, decltype(l.val * r.ddn + l.ddn * r.val)>
336 {
337  return {l.val * r.val, l.val * r.ddT + l.ddT * r.val, l.val * r.ddP + l.ddP * r.val, l.val * r.ddn + l.ddn * r.val};
338 }
339 
340 template<typename V, typename N>
341 auto operator/(double l, const ChemicalScalarBase<V,N>& r) -> ChemicalScalarBase<double, decltype(double() * r.ddn)>
342 {
343  const double tmp1 = 1.0/r.val;
344  const double tmp2 = -l * tmp1 * tmp1;
345  return {tmp1 * l, tmp2 * r.ddT, tmp2 * r.ddP, tmp2 * r.ddn};
346 }
347 
348 template<typename V, typename N>
349 auto operator/(const ChemicalScalarBase<V,N>& l, double r) -> decltype((1.0/r) * l)
350 {
351  return (1.0/r) * l;
352 }
353 
354 template<typename VL, typename VR, typename NR>
355 auto operator/(const ThermoScalarBase<VL>& l, const ChemicalScalarBase<VR,NR>& r) -> ChemicalScalarBase<double, decltype(-(l.val * r.ddn) * double())>
356 {
357  const double tmp = 1.0/(r.val * r.val);
358  return {l.val/r.val, (l.ddT * r.val - l.val * r.ddT) * tmp, (l.ddP * r.val - l.val * r.ddP) * tmp, -(l.val * r.ddn) * tmp};
359 }
360 
361 template<typename VL, typename NL, typename VR>
362 auto operator/(const ChemicalScalarBase<VL,NL>& l, const ThermoScalarBase<VR>& r) -> ChemicalScalarBase<double, decltype(l.ddn/r.val)>
363 {
364  const double tmp = 1.0/(r.val * r.val);
365  return {l.val/r.val, (l.ddT * r.val - l.val * r.ddT) * tmp, (l.ddP * r.val - l.val * r.ddP) * tmp, l.ddn/r.val};
366 }
367 
368 template<typename VL, typename NL, typename VR, typename NR>
369 auto operator/(const ChemicalScalarBase<VL,NL>& l, const ChemicalScalarBase<VR,NR>& r) -> ChemicalScalarBase<double, decltype((l.ddn * r.val - l.val * r.ddn) * double())>
370 {
371  const double tmp = 1.0/(r.val * r.val);
372  return {l.val/r.val, (l.ddT * r.val - l.val * r.ddT) * tmp, (l.ddP * r.val - l.val * r.ddP) * tmp, (l.ddn * r.val - l.val * r.ddn) * tmp};
373 }
374 
375 template<typename VL, typename NL, typename VR, typename NR>
376 auto operator<(const ChemicalScalarBase<VL,NL>& l, const ChemicalScalarBase<VR,NR>& r) -> bool
377 {
378  return l.val < r.val;
379 }
380 
381 template<typename V, typename N>
382 auto operator<(const ChemicalScalarBase<V,N>& l, double r) -> bool
383 {
384  return l.val < r;
385 }
386 
387 template<typename V, typename N>
388 auto operator<(double l, const ChemicalScalarBase<V,N>& r) -> bool
389 {
390  return l < r.val;
391 }
392 
393 template<typename VL, typename NL, typename VR, typename NR>
394 auto operator<=(const ChemicalScalarBase<VL,NL>& l, const ChemicalScalarBase<VR,NR>& r) -> bool
395 {
396  return l.val <= r.val;
397 }
398 
399 template<typename V, typename N>
400 auto operator<=(const ChemicalScalarBase<V,N>& l, double r) -> bool
401 {
402  return l.val <= r;
403 }
404 
405 template<typename V, typename N>
406 auto operator<=(double l, const ChemicalScalarBase<V,N>& r) -> bool
407 {
408  return l <= r.val;
409 }
410 
411 template<typename VL, typename NL, typename VR, typename NR>
412 auto operator>(const ChemicalScalarBase<VL,NL>& l, const ChemicalScalarBase<VR,NR>& r) -> bool
413 {
414  return l.val > r.val;
415 }
416 
417 template<typename V, typename N>
418 auto operator>(const ChemicalScalarBase<V,N>& l, double r) -> bool
419 {
420  return l.val > r;
421 }
422 
423 template<typename V, typename N>
424 auto operator>(double l, const ChemicalScalarBase<V,N>& r) -> bool
425 {
426  return l > r.val;
427 }
428 
429 template<typename VL, typename NL, typename VR, typename NR>
430 auto operator>=(const ChemicalScalarBase<VL,NL>& l, const ChemicalScalarBase<VR,NR>& r) -> bool
431 {
432  return l.val >= r.val;
433 }
434 
435 template<typename V, typename N>
436 auto operator>=(const ChemicalScalarBase<V,N>& l, double r) -> bool
437 {
438  return l.val >= r;
439 }
440 
441 template<typename V, typename N>
442 auto operator>=(double l, const ChemicalScalarBase<V,N>& r) -> bool
443 {
444  return l >= r.val;
445 }
446 
447 template<typename VL, typename NL, typename VR, typename NR>
448 auto operator==(const ChemicalScalarBase<VL,NL>& l, const ChemicalScalarBase<VR,NR>& r) -> bool
449 {
450  return l.val == r.val;
451 }
452 
453 template<typename V, typename N>
454 auto operator==(const ChemicalScalarBase<V,N>& l, double r) -> bool
455 {
456  return l.val == r;
457 }
458 
459 template<typename V, typename N>
460 auto operator==(double l, const ChemicalScalarBase<V,N>& r) -> bool
461 {
462  return l == r.val;
463 }
464 
465 template<typename VL, typename NL, typename VR, typename NR>
466 auto operator!=(const ChemicalScalarBase<VL,NL>& l, const ChemicalScalarBase<VR,NR>& r) -> bool
467 {
468  return l.val == r.val;
469 }
470 
471 template<typename V, typename N>
472 auto operator!=(const ChemicalScalarBase<V,N>& l, double r) -> bool
473 {
474  return l.val != r;
475 }
476 
477 template<typename V, typename N>
478 auto operator!=(double l, const ChemicalScalarBase<V,N>& r) -> bool
479 {
480  return l != r.val;
481 }
482 
483 inline auto operator<<(std::ostream& out, const ChemicalScalar& scalar) -> std::ostream&
484 {
485  out << scalar.val;
486  return out;
487 }
488 
489 template<typename V, typename N>
490 auto abs(const ChemicalScalarBase<V,N>& l) -> ChemicalScalarBase<double, decltype(double() * l.ddn)>
491 {
492  const double tmp1 = std::abs(l.val);
493  const double tmp2 = l.val/tmp1;
494  return {tmp1, tmp2 * l.ddT, tmp2 * l.ddP, tmp2 * l.ddn};
495 }
496 
497 template<typename V, typename N>
498 auto sqrt(const ChemicalScalarBase<V,N>& l) -> ChemicalScalarBase<double, decltype(double() * l.ddn)>
499 {
500  const double tmp1 = std::sqrt(l.val);
501  const double tmp2 = 0.5 * tmp1/l.val;
502  return {tmp1, tmp2 * l.ddT, tmp2 * l.ddP, tmp2 * l.ddn};
503 }
504 
505 template<typename V, typename N>
506 auto pow(const ChemicalScalarBase<V,N>& l, double power) -> ChemicalScalarBase<double, decltype(double() * l.ddn)>
507 {
508  const double tmp1 = std::pow(l.val, power);
509  const double tmp2 = power * tmp1/l.val;
510  return {tmp1, tmp2 * l.ddT, tmp2 * l.ddP, tmp2 * l.ddn};
511 }
512 
513 template<typename V, typename N>
514 auto exp(const ChemicalScalarBase<V,N>& l) -> ChemicalScalarBase<double, decltype(double() * l.ddn)>
515 {
516  const double tmp1 = std::exp(l.val);
517  return {tmp1, tmp1 * l.ddT, tmp1 * l.ddP, tmp1 * l.ddn};
518 }
519 
520 template<typename V, typename N>
521 auto log(const ChemicalScalarBase<V,N>& l) -> ChemicalScalarBase<double, decltype(double() * l.ddn)>
522 {
523  const double tmp1 = std::log(l.val);
524  const double tmp2 = 1.0/l.val;
525  return {tmp1, tmp2 * l.ddT, tmp2 * l.ddP, tmp2 * l.ddn};
526 }
527 
528 template<typename V, typename N>
529 auto log10(const ChemicalScalarBase<V,N>& l) -> decltype(log(l)/1.0)
530 {
531  const double ln10 = 2.302585092994046;
532  return log(l)/ln10;
533 }
534 
535 } // namespace Reaktoro
ChemicalScalarBase(ChemicalScalarBase< VR, NR > &other)
Construct a ChemicalScalarBase instance from another.
Definition: ChemicalScalar.hpp:88
auto operator-=(const ChemicalScalarBase< VR, NR > &other) -> ChemicalScalarBase &
Assign-subtraction of a ChemicalScalarBase instance to this.
Definition: ChemicalScalar.hpp:168
auto operator+=(const ChemicalScalarBase< VR, NR > &other) -> ChemicalScalarBase &
Assign-addition of a ChemicalScalarBase instance to this.
Definition: ChemicalScalar.hpp:140
ChemicalScalarBase()
Construct a default ChemicalScalarBase instance.
Definition: ChemicalScalar.hpp:64
A template base class to represent a chemical scalar and its partial derivatives.
Definition: ChemicalScalar.hpp:49
V val
The value of the chemical scalar.
Definition: ChemicalScalar.hpp:52
auto amount(double value, Index nspecies, Index ispecies) -> ChemicalScalarBase< double, decltype(tr(unit(nspecies, ispecies)))>
Return a ChemicalScalar representation of a mole amount of a species.
Definition: ChemicalScalar.hpp:233
auto operator+=(double other) -> ChemicalScalarBase &
Assign-addition of a scalar to this.
Definition: ChemicalScalar.hpp:160
Eigen::RowVectorXd RowVector
< Alias to Eigen type Map<const VectorXd>.
Definition: Matrix.hpp:35
ChemicalScalarBase(Index nspecies, double val)
Construct a ChemicalScalarBase instance with given number of species and a constant value.
Definition: ChemicalScalar.hpp:75
The namespace containing all components of the Reaktoro library.
Definition: ChemicalScalar.hpp:24
ChemicalScalarBase(const ChemicalScalarBase< VR, NR > &other)
Construct a ChemicalScalarBase instance from another.
Definition: ChemicalScalar.hpp:93
N ddn
The partial mole derivatives of the chemical scalar.
Definition: ChemicalScalar.hpp:61
auto operator+=(const ThermoScalarBase< VR > &other) -> ChemicalScalarBase &
Assign-addition of a ThermoScalarBase instance to this.
Definition: ChemicalScalar.hpp:151
ChemicalScalarBase(const V &val, const V &ddT, const V &ddP, const N &ddn)
Construct a ChemicalScalarBase instance with given values and derivatives.
Definition: ChemicalScalar.hpp:83
std::size_t Index
Define a type that represents an index.
Definition: Index.hpp:26
auto operator*=(double other) -> ChemicalScalarBase &
Assign-multiplication of a scalar to this.
Definition: ChemicalScalar.hpp:206
auto operator/=(double other) -> ChemicalScalarBase &
Assign-division of a scalar to this.
Definition: ChemicalScalar.hpp:216
V ddT
The partial temperature derivative of the chemical scalar.
Definition: ChemicalScalar.hpp:55
auto operator=(const ChemicalScalarBase< VR, NR > &other) -> ChemicalScalarBase &
Assign another ChemicalScalarBase instance to this.
Definition: ChemicalScalar.hpp:108
auto operator=(const ThermoScalarBase< VR > &other) -> ChemicalScalarBase &
Assign a ThermoScalarBase instance to this.
Definition: ChemicalScalar.hpp:119
ChemicalScalarBase< double, RowVector > ChemicalScalar
A type that represents a chemical property and its derivatives.
Definition: ChemicalScalar.hpp:35
auto operator*=(const ChemicalScalarBase< VR, NR > &other) -> ChemicalScalarBase &
Assign-multiplication of a ChemicalScalarBase instance to this.
Definition: ChemicalScalar.hpp:196
A template base class to represent a thermodynamic scalar and its partial derivatives.
Definition: ThermoScalar.hpp:45
auto tr(Eigen::MatrixBase< Derived > &mat) -> decltype(mat.transpose())
Return the transpose of the matrix.
Definition: Matrix.hxx:167
auto operator=(ChemicalScalarBase< V, N > &other) -> ChemicalScalarBase &
Assign another ChemicalScalarBase instance to this.
Definition: ChemicalScalar.hpp:97
ChemicalScalarBase(Index nspecies)
Construct a ChemicalScalarBase instance with given number of species.
Definition: ChemicalScalar.hpp:69
auto operator-=(double other) -> ChemicalScalarBase &
Assign-subtraction of a scalar to this.
Definition: ChemicalScalar.hpp:188
V ddP
The partial pressure derivative of the chemical scalar.
Definition: ChemicalScalar.hpp:58
auto unit(Index rows, Index i) -> decltype(Vector::Unit(rows, i))
Return an expression of a unit vector.
Definition: Matrix.hxx:47
auto operator=(double other) -> ChemicalScalarBase &
Assign a scalar to this.
Definition: ChemicalScalar.hpp:129
auto operator-=(const ThermoScalarBase< VR > &other) -> ChemicalScalarBase &
Assign-subtraction of a ThermoScalarBase instance to this.
Definition: ChemicalScalar.hpp:179