diff --git a/docs/reference/reactors/rtd/_SUMMARY.md b/docs/reference/reactors/rtd/_SUMMARY.md new file mode 100644 index 0000000..be2cea3 --- /dev/null +++ b/docs/reference/reactors/rtd/_SUMMARY.md @@ -0,0 +1,4 @@ +* [cstr_cumulative](cstr_cumulative.md) +* [cstr_differential](cstr_differential.md) +* [tanks_series_cumulative](tanks_series_cumulative.md) +* [tanks_series_differential](tanks_series_differential.md) diff --git a/docs/reference/reactors/rtd/cstr_cumulative.md b/docs/reference/reactors/rtd/cstr_cumulative.md new file mode 100644 index 0000000..cf87ed1 --- /dev/null +++ b/docs/reference/reactors/rtd/cstr_cumulative.md @@ -0,0 +1,6 @@ +# polykin.reactors.rtd + +::: polykin.reactors.rtd + options: + members: + - cstr_cumulative diff --git a/docs/reference/reactors/rtd/cstr_differential.md b/docs/reference/reactors/rtd/cstr_differential.md new file mode 100644 index 0000000..ed2236e --- /dev/null +++ b/docs/reference/reactors/rtd/cstr_differential.md @@ -0,0 +1,6 @@ +# polykin.reactors.rtd + +::: polykin.reactors.rtd + options: + members: + - cstr_differential diff --git a/docs/reference/reactors/rtd/tanks_series_cumulative.md b/docs/reference/reactors/rtd/tanks_series_cumulative.md new file mode 100644 index 0000000..17e6f90 --- /dev/null +++ b/docs/reference/reactors/rtd/tanks_series_cumulative.md @@ -0,0 +1,6 @@ +# polykin.reactors.rtd + +::: polykin.reactors.rtd + options: + members: + - tanks_series_cumulative diff --git a/docs/reference/reactors/rtd/tanks_series_differential.md b/docs/reference/reactors/rtd/tanks_series_differential.md new file mode 100644 index 0000000..b77cfc6 --- /dev/null +++ b/docs/reference/reactors/rtd/tanks_series_differential.md @@ -0,0 +1,6 @@ +# polykin.reactors.rtd + +::: polykin.reactors.rtd + options: + members: + - tanks_series_differential diff --git a/mkdocs.yml b/mkdocs.yml index c208ef2..d42f37a 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -170,6 +170,8 @@ nav: - Thermal Conductivity: reference/properties/thermal_conductivity/ - Vaporization Enthalpy: reference/properties/vaporization_enthalpy/ - Viscosity: reference/properties/viscosity/ + - Reactors: + - Residence Time Distributions: reference/reactors/rtd/ - Thermodynamics: #- reference/thermo/index.md - Activity Coeff. Models: reference/thermo/acm/ diff --git a/src/polykin/reactors/__init__.py b/src/polykin/reactors/__init__.py new file mode 100644 index 0000000..3fc8c5c --- /dev/null +++ b/src/polykin/reactors/__init__.py @@ -0,0 +1,5 @@ +# PolyKin: A polymerization kinetics library for Python. +# +# Copyright Hugo Vale 2024 + +from .rtd import * diff --git a/src/polykin/reactors/rtd.py b/src/polykin/reactors/rtd.py new file mode 100644 index 0000000..090fe87 --- /dev/null +++ b/src/polykin/reactors/rtd.py @@ -0,0 +1,122 @@ +# PolyKin: A polymerization kinetics library for Python. +# +# Copyright Hugo Vale 2024 + +from math import gamma + +from numpy import exp + +__all__ = ['cstr_differential', + 'cstr_cumulative', + 'tanks_series_differential', + 'tanks_series_cumulative', + ] + + +def cstr_differential(t: float, tavg: float) -> float: + r"""Differential residence time distribution for a single CSTR. + + $$ E(t) = \frac{1}{\bar{t}} e^{-t/\bar{t}} $$ + + **References** + + * Levenspiel, O. "Chemical reaction engineering", John wiley & sons, 1998, + p. 322. + + Parameters + ---------- + t : float + Time. + tavg : float + Average residence time, $\bar{t}$. + + Returns + ------- + float + Differential residence time distribution. + """ + return (1/tavg)*exp(-t/tavg) + + +def cstr_cumulative(t: float, tavg: float) -> float: + r"""Cumulative residence time distribution for a single CSTR. + + $$ F(t) = 1 - e^{-t/\bar{t}} $$ + + **References** + + * Levenspiel, O. "Chemical reaction engineering", John wiley & sons, 1998, + p. 327. + + Parameters + ---------- + t : float + Time. + tavg : float + Average residence time, $\bar{t}$. + + Returns + ------- + float + Cumulative residence time distribution. + """ + return 1 - exp(-t/tavg) + + +def tanks_series_differential(t: float, tavg: float, N: int) -> float: + r"""Differential residence time distribution for a series of equal CSTRs. + + $$ E(t) = \frac{1}{\bar{t}} \left(\frac{t}{\bar{t}} \right)^{N-1} + \frac{N^N}{(N-1)!} e^{-N t / \bar{t}} $$ + + **References** + + * Levenspiel, O. "Chemical reaction engineering", John wiley & sons, 1998, + p. 322. + + Parameters + ---------- + t : float + Time. + tavg : float + Total average residence time, $\bar{t}$. + N : int + Number of tanks in series. + + Returns + ------- + float + Differential residence time distribution. + """ + q = t/tavg + return q**(N-1) * (N**N / gamma(N)) * exp(-N*q) / tavg + + +def tanks_series_cumulative(t: float, tavg: float, N: int) -> float: + r"""Cumulative residence time distribution for a series of equal CSTRs. + + $$ F(t) = 1 - e^{-N t / \bar{t}} \; + \sum_{i=0}^{N-1} \frac{(N t / \bar{t})^i}{i!} $$ + + **References** + + * Levenspiel, O. "Chemical reaction engineering", John wiley & sons, 1998, + p. 327. + + Parameters + ---------- + t : float + Time. + tavg : float + Total average residence time, $\bar{t}$. + N : int + Number of tanks in series. + + Returns + ------- + float + Cumulative residence time distribution. + """ + q = t/tavg + S = sum((N*q)**i / gamma(i+1) for i in range(1, N)) + return 1 - exp(-N*q) * (1 + S) diff --git a/tests/reactors/test_rtd.py b/tests/reactors/test_rtd.py new file mode 100644 index 0000000..6e97e6d --- /dev/null +++ b/tests/reactors/test_rtd.py @@ -0,0 +1,39 @@ +from numpy import exp, isclose + +from polykin.reactors.rtd import * + + +def test_cstr_differential(): + assert isclose(cstr_differential(0, 1), 1) + assert isclose(cstr_differential(1e8, 1), 0) + assert isclose(cstr_differential(1, 1), exp(-1)) + + +def testcstr_cumulative(): + assert isclose(cstr_cumulative(0, 1), 0) + assert isclose(cstr_cumulative(1e8, 1), 1) + assert isclose(cstr_cumulative(1, 1), 0.63, rtol=0.01) + + +def test_tanks_series_differential(): + # N = 1 + N = 1 + assert isclose(tanks_series_differential(0, 1, N), 1) + assert isclose(tanks_series_differential(1e8, 1, N), 0) + assert isclose(tanks_series_differential(1, 1, N), exp(-1)) + # N > 1 + for N in range(2, 10): + assert isclose(tanks_series_differential(0, 1, N), 0) + assert isclose(tanks_series_differential(1e8, 1, N), 0) + assert isclose(tanks_series_differential(1, 1, 20), 1.8, atol=0.1) + + +def test_tanks_series_cumulative(): + for N in range(1, 10): + assert isclose(tanks_series_cumulative(0, 1, N), 0) + assert isclose(tanks_series_cumulative(1e8, 1, N), 1) + assert isclose(tanks_series_cumulative(1, 1, N=1), 0.63, rtol=0.01) + assert isclose(tanks_series_cumulative(0.85, 1, N=2), 0.5, atol=0.01) + assert isclose(tanks_series_cumulative(1, 1, N=20), 0.52, atol=0.01) + assert isclose(tanks_series_cumulative(0.5, 1, N=20), 0.0, atol=0.01) + assert isclose(tanks_series_cumulative(1.6, 1, N=20), 1.0, atol=0.01)