fugacio-sim 0.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fugacio_sim-0.0.1/.gitignore +32 -0
- fugacio_sim-0.0.1/PKG-INFO +150 -0
- fugacio_sim-0.0.1/README.md +134 -0
- fugacio_sim-0.0.1/pyproject.toml +37 -0
- fugacio_sim-0.0.1/src/fugacio/sim/__init__.py +529 -0
- fugacio_sim-0.0.1/src/fugacio/sim/column.py +466 -0
- fugacio_sim-0.0.1/src/fugacio/sim/control/__init__.py +110 -0
- fugacio_sim-0.0.1/src/fugacio/sim/control/blocks.py +159 -0
- fugacio_sim-0.0.1/src/fugacio/sim/control/linearize.py +190 -0
- fugacio_sim-0.0.1/src/fugacio/sim/control/metrics.py +152 -0
- fugacio_sim-0.0.1/src/fugacio/sim/control/pid.py +195 -0
- fugacio_sim-0.0.1/src/fugacio/sim/control/tuning.py +174 -0
- fugacio_sim-0.0.1/src/fugacio/sim/design.py +312 -0
- fugacio_sim-0.0.1/src/fugacio/sim/diagrams.py +346 -0
- fugacio_sim-0.0.1/src/fugacio/sim/dynamics/__init__.py +76 -0
- fugacio_sim-0.0.1/src/fugacio/sim/dynamics/flowsheet.py +292 -0
- fugacio_sim-0.0.1/src/fugacio/sim/dynamics/integrate.py +517 -0
- fugacio_sim-0.0.1/src/fugacio/sim/dynamics/optimize.py +255 -0
- fugacio_sim-0.0.1/src/fugacio/sim/dynamics/units.py +580 -0
- fugacio_sim-0.0.1/src/fugacio/sim/economics.py +384 -0
- fugacio_sim-0.0.1/src/fugacio/sim/flowsheet.py +286 -0
- fugacio_sim-0.0.1/src/fugacio/sim/integration/__init__.py +89 -0
- fugacio_sim-0.0.1/src/fugacio/sim/integration/area.py +447 -0
- fugacio_sim-0.0.1/src/fugacio/sim/integration/network.py +429 -0
- fugacio_sim-0.0.1/src/fugacio/sim/integration/streams.py +169 -0
- fugacio_sim-0.0.1/src/fugacio/sim/integration/targeting.py +348 -0
- fugacio_sim-0.0.1/src/fugacio/sim/models.py +221 -0
- fugacio_sim-0.0.1/src/fugacio/sim/mpc/__init__.py +116 -0
- fugacio_sim-0.0.1/src/fugacio/sim/mpc/estimation.py +413 -0
- fugacio_sim-0.0.1/src/fugacio/sim/mpc/linear.py +608 -0
- fugacio_sim-0.0.1/src/fugacio/sim/mpc/nonlinear.py +336 -0
- fugacio_sim-0.0.1/src/fugacio/sim/mpc/qp.py +409 -0
- fugacio_sim-0.0.1/src/fugacio/sim/mpc/riccati.py +279 -0
- fugacio_sim-0.0.1/src/fugacio/sim/mpc/simulate.py +302 -0
- fugacio_sim-0.0.1/src/fugacio/sim/optimize.py +758 -0
- fugacio_sim-0.0.1/src/fugacio/sim/properties.py +186 -0
- fugacio_sim-0.0.1/src/fugacio/sim/py.typed +0 -0
- fugacio_sim-0.0.1/src/fugacio/sim/reactive.py +398 -0
- fugacio_sim-0.0.1/src/fugacio/sim/reactors.py +516 -0
- fugacio_sim-0.0.1/src/fugacio/sim/separations.py +146 -0
- fugacio_sim-0.0.1/src/fugacio/sim/stream.py +71 -0
- fugacio_sim-0.0.1/src/fugacio/sim/units.py +356 -0
- fugacio_sim-0.0.1/src/fugacio/sim/utilities.py +358 -0
- fugacio_sim-0.0.1/src/fugacio/sim/vle.py +58 -0
- fugacio_sim-0.0.1/tests/test_column_rigorous.py +108 -0
- fugacio_sim-0.0.1/tests/test_column_shortcut.py +96 -0
- fugacio_sim-0.0.1/tests/test_control.py +298 -0
- fugacio_sim-0.0.1/tests/test_design.py +86 -0
- fugacio_sim-0.0.1/tests/test_dynamic_flowsheet.py +119 -0
- fugacio_sim-0.0.1/tests/test_dynamic_optimize.py +122 -0
- fugacio_sim-0.0.1/tests/test_dynamic_oracles.py +95 -0
- fugacio_sim-0.0.1/tests/test_dynamic_units.py +277 -0
- fugacio_sim-0.0.1/tests/test_economics.py +109 -0
- fugacio_sim-0.0.1/tests/test_energy_units.py +139 -0
- fugacio_sim-0.0.1/tests/test_flowsheet.py +117 -0
- fugacio_sim-0.0.1/tests/test_flowsheet_opt.py +73 -0
- fugacio_sim-0.0.1/tests/test_integrate.py +220 -0
- fugacio_sim-0.0.1/tests/test_integration.py +235 -0
- fugacio_sim-0.0.1/tests/test_integration_oracles.py +106 -0
- fugacio_sim-0.0.1/tests/test_mpc.py +489 -0
- fugacio_sim-0.0.1/tests/test_mpc_oracles.py +90 -0
- fugacio_sim-0.0.1/tests/test_nonideal.py +195 -0
- fugacio_sim-0.0.1/tests/test_optimize.py +151 -0
- fugacio_sim-0.0.1/tests/test_reactive.py +183 -0
- fugacio_sim-0.0.1/tests/test_reactors.py +229 -0
- fugacio_sim-0.0.1/tests/test_stream_properties.py +94 -0
- fugacio_sim-0.0.1/tests/test_units.py +77 -0
- fugacio_sim-0.0.1/tests/test_utilities.py +146 -0
- fugacio_sim-0.0.1/tests/test_vle.py +22 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Byte-compiled / build artifacts
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
.eggs/
|
|
6
|
+
build/
|
|
7
|
+
dist/
|
|
8
|
+
|
|
9
|
+
# Virtual environments
|
|
10
|
+
.venv/
|
|
11
|
+
venv/
|
|
12
|
+
|
|
13
|
+
# Tooling caches
|
|
14
|
+
.pytest_cache/
|
|
15
|
+
.mypy_cache/
|
|
16
|
+
.ruff_cache/
|
|
17
|
+
.import_linter_cache/
|
|
18
|
+
.jax_cache/
|
|
19
|
+
.coverage
|
|
20
|
+
coverage.xml
|
|
21
|
+
htmlcov/
|
|
22
|
+
|
|
23
|
+
# Docs build
|
|
24
|
+
site/
|
|
25
|
+
# Material social-cards plugin cache (downloaded fonts + generated card layers)
|
|
26
|
+
.cache/
|
|
27
|
+
|
|
28
|
+
# OS / editor
|
|
29
|
+
.DS_Store
|
|
30
|
+
*.swp
|
|
31
|
+
.idea/
|
|
32
|
+
.vscode/
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fugacio-sim
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: Differentiable steady-state and dynamic process flowsheet simulator (Fugacio).
|
|
5
|
+
Author-email: Owen Carey <37121709+owenthcarey@users.noreply.github.com>
|
|
6
|
+
License-Expression: Apache-2.0
|
|
7
|
+
Keywords: chemical-engineering,flowsheet,jax,process-simulation,vapor-liquid-equilibrium
|
|
8
|
+
Classifier: Development Status :: 2 - Pre-Alpha
|
|
9
|
+
Classifier: Intended Audience :: Science/Research
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
12
|
+
Requires-Python: >=3.11
|
|
13
|
+
Requires-Dist: fugacio-thermo
|
|
14
|
+
Requires-Dist: jax>=0.4.34
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
|
|
17
|
+
# fugacio-sim
|
|
18
|
+
|
|
19
|
+
Differentiable process-simulation layer for the
|
|
20
|
+
[Fugacio](https://github.com/fugacio/fugacio) stack: flowsheet and
|
|
21
|
+
unit-operation models built on top of `fugacio.thermo`.
|
|
22
|
+
|
|
23
|
+
The core abstraction is the `Stream`, a JAX pytree whose molar flows,
|
|
24
|
+
temperature, and pressure are differentiable leaves (component names are static
|
|
25
|
+
metadata). Because the underlying EOS phase equilibrium is differentiable, unit
|
|
26
|
+
operations are too: you can take a gradient of any downstream quantity (a product
|
|
27
|
+
flow, a recovery, a purity) with respect to feed conditions or operating
|
|
28
|
+
variables, which is the basis for gradient-based flowsheet optimisation.
|
|
29
|
+
|
|
30
|
+
## Stream properties
|
|
31
|
+
|
|
32
|
+
Any `Stream` has a two-phase-aware enthalpy and entropy (via the
|
|
33
|
+
`fugacio.thermo` energy core), so unit operations close *energy* balances, not
|
|
34
|
+
just material balances: `molar_enthalpy`, `molar_entropy`, `enthalpy_flow`,
|
|
35
|
+
`entropy_flow`, `mass_flow`, `molar_mass`.
|
|
36
|
+
|
|
37
|
+
## Unit operations (rigorous material + energy balances)
|
|
38
|
+
|
|
39
|
+
- `flash_drum`: isothermal-isobaric vapour/liquid separator.
|
|
40
|
+
- `heater`: heater/cooler on a temperature **or** a duty specification.
|
|
41
|
+
- `valve`: isenthalpic (Joule-Thomson) pressure letdown.
|
|
42
|
+
- `pump`: incompressible-liquid pump with an efficiency.
|
|
43
|
+
- `compressor` / `turbine`: isentropic machines with an efficiency.
|
|
44
|
+
- `mix`: adiabatic, energy-balanced mixer (exact material balance).
|
|
45
|
+
- `splitter` / `component_separator`: flow split and idealised component split.
|
|
46
|
+
- `bubble_pressure` / `antoine_psat`: lightweight modified-Raoult helpers.
|
|
47
|
+
|
|
48
|
+
## Flowsheets with recycle
|
|
49
|
+
|
|
50
|
+
`tear_solve` closes a recycle by solving the tear fixed point
|
|
51
|
+
`tear = g(tear, theta)` with a Wegstein-accelerated iteration, and
|
|
52
|
+
differentiates the *converged* flowsheet by the implicit function theorem: a
|
|
53
|
+
gradient through the recycle costs one adjoint solve regardless of iteration
|
|
54
|
+
count. `Flowsheet` is a small declarative builder on top of it.
|
|
55
|
+
|
|
56
|
+
## Distillation
|
|
57
|
+
|
|
58
|
+
- **Shortcut** (Fenske-Underwood-Gilliland): `fenske_min_stages`,
|
|
59
|
+
`underwood_min_reflux`, `gilliland_stages`, `kirkbride_feed_stage`, and the
|
|
60
|
+
`shortcut_column` wrapper.
|
|
61
|
+
- **Rigorous** `solve_column`: a multistage equilibrium-stage column (Wang-Henke
|
|
62
|
+
bubble-point, constant molar overflow) with EOS K-values on every stage,
|
|
63
|
+
differentiable through the fixed-point iteration.
|
|
64
|
+
|
|
65
|
+
## Non-ideal separations & diagrams
|
|
66
|
+
|
|
67
|
+
Built on the `fugacio.thermo` property system (via the `eos_model_for`,
|
|
68
|
+
`nrtl_model_for`, `uniquac_model_for`, `unifac_model_for`, and `saft_model_for`
|
|
69
|
+
bridges, the last building a molecular PC-SAFT model from component names):
|
|
70
|
+
|
|
71
|
+
- `flash_vle`, `decanter`, `three_phase_flash`: activity-based VLE / LLE / VLLE
|
|
72
|
+
drums for real, non-ideal mixtures.
|
|
73
|
+
- `pxy_diagram`, `txy_diagram`, `azeotrope_pressure`, `azeotrope_temperature`:
|
|
74
|
+
binary phase diagrams and azeotrope finders.
|
|
75
|
+
- `residue_curve`, `residue_curve_map`: ternary open-evaporation trajectories for
|
|
76
|
+
laying out distillation boundaries.
|
|
77
|
+
|
|
78
|
+
## Reactors
|
|
79
|
+
|
|
80
|
+
Energy-balanced reactor unit operations over one or more `fugacio.thermo`
|
|
81
|
+
`Reaction`s, each runnable isothermally (reporting the heat `duty`) or
|
|
82
|
+
adiabatically (solving the outlet temperature) and returning a `ReactorResult`:
|
|
83
|
+
`equilibrium_reactor` (chemical equilibrium), `stoichiometric_reactor` (specified
|
|
84
|
+
extent or conversion), and kinetic `cstr`, `pfr`, and `batch_reactor` sized by
|
|
85
|
+
volume (and time). `conversion` is a small helper on the inlet/outlet streams.
|
|
86
|
+
|
|
87
|
+
## Reactive separations
|
|
88
|
+
|
|
89
|
+
Reaction coupled to phase separation, both differentiable through the joint solve:
|
|
90
|
+
`reactive_flash` (simultaneous chemical + vapour-liquid equilibrium in a drum) and
|
|
91
|
+
`reactive_distillation` (a rate-based column with per-stage reaction source terms).
|
|
92
|
+
|
|
93
|
+
## Example: differentiate a flash drum
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
import jax
|
|
97
|
+
import jax.numpy as jnp
|
|
98
|
+
from fugacio.sim import Stream, flash_drum
|
|
99
|
+
|
|
100
|
+
feed = Stream.from_fractions(
|
|
101
|
+
("methane", "propane", "n-pentane"),
|
|
102
|
+
jnp.array([0.5, 0.3, 0.2]),
|
|
103
|
+
flow=100.0, t=320.0, p=20e5,
|
|
104
|
+
)
|
|
105
|
+
vapor, liquid = flash_drum(feed, 320.0, 20e5)
|
|
106
|
+
vapor.total, liquid.total # ~74.7 and ~25.3 mol/s
|
|
107
|
+
|
|
108
|
+
# Sensitivity of vapour product flow to drum temperature:
|
|
109
|
+
d_vapor_dT = jax.grad(lambda T: flash_drum(feed, T, 20e5)[0].total)
|
|
110
|
+
d_vapor_dT(320.0)
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Example: a recycle, differentiated end-to-end
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
import jax.numpy as jnp
|
|
117
|
+
from fugacio.sim import Stream, flash_drum, mix, splitter, tear_solve
|
|
118
|
+
|
|
119
|
+
components = ("methane", "propane", "n-pentane")
|
|
120
|
+
fresh = Stream.from_fractions(components, jnp.array([0.5, 0.3, 0.2]), 100.0, 320.0, 20e5)
|
|
121
|
+
|
|
122
|
+
def one_pass(recycle, theta):
|
|
123
|
+
mixed = mix([fresh, recycle], t=320.0)
|
|
124
|
+
_vapor, liquid = flash_drum(mixed, theta["T"], theta["P"])
|
|
125
|
+
recycled, _purge = splitter(liquid, jnp.array([theta["r"], 1.0 - theta["r"]]))
|
|
126
|
+
return recycled
|
|
127
|
+
|
|
128
|
+
guess = Stream.from_fractions(components, jnp.array([0.1, 0.3, 0.6]), 30.0, 320.0, 20e5)
|
|
129
|
+
recycle = tear_solve(one_pass, guess, {"T": 320.0, "P": 20e5, "r": 0.5})
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Example: a rigorous distillation column
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
import jax
|
|
136
|
+
import jax.numpy as jnp
|
|
137
|
+
from fugacio.sim import Stream, solve_column
|
|
138
|
+
|
|
139
|
+
feed = Stream.from_fractions(("propane", "n-butane"), jnp.array([0.5, 0.5]), 100.0, 320.0, 10e5)
|
|
140
|
+
col = solve_column(feed, n_stages=12, feed_stage=6, reflux=2.0, distillate_rate=50.0)
|
|
141
|
+
col.distillate.z # ~[0.97, 0.03] propane overhead
|
|
142
|
+
|
|
143
|
+
# Exact gradient of distillate purity w.r.t. reflux ratio:
|
|
144
|
+
jax.grad(
|
|
145
|
+
lambda r: solve_column(feed, 12, 6, r, 50.0).distillate.z[0]
|
|
146
|
+
)(2.0)
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Part of the `fugacio` namespace; installs independently:
|
|
150
|
+
`pip install fugacio-sim`.
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# fugacio-sim
|
|
2
|
+
|
|
3
|
+
Differentiable process-simulation layer for the
|
|
4
|
+
[Fugacio](https://github.com/fugacio/fugacio) stack: flowsheet and
|
|
5
|
+
unit-operation models built on top of `fugacio.thermo`.
|
|
6
|
+
|
|
7
|
+
The core abstraction is the `Stream`, a JAX pytree whose molar flows,
|
|
8
|
+
temperature, and pressure are differentiable leaves (component names are static
|
|
9
|
+
metadata). Because the underlying EOS phase equilibrium is differentiable, unit
|
|
10
|
+
operations are too: you can take a gradient of any downstream quantity (a product
|
|
11
|
+
flow, a recovery, a purity) with respect to feed conditions or operating
|
|
12
|
+
variables, which is the basis for gradient-based flowsheet optimisation.
|
|
13
|
+
|
|
14
|
+
## Stream properties
|
|
15
|
+
|
|
16
|
+
Any `Stream` has a two-phase-aware enthalpy and entropy (via the
|
|
17
|
+
`fugacio.thermo` energy core), so unit operations close *energy* balances, not
|
|
18
|
+
just material balances: `molar_enthalpy`, `molar_entropy`, `enthalpy_flow`,
|
|
19
|
+
`entropy_flow`, `mass_flow`, `molar_mass`.
|
|
20
|
+
|
|
21
|
+
## Unit operations (rigorous material + energy balances)
|
|
22
|
+
|
|
23
|
+
- `flash_drum`: isothermal-isobaric vapour/liquid separator.
|
|
24
|
+
- `heater`: heater/cooler on a temperature **or** a duty specification.
|
|
25
|
+
- `valve`: isenthalpic (Joule-Thomson) pressure letdown.
|
|
26
|
+
- `pump`: incompressible-liquid pump with an efficiency.
|
|
27
|
+
- `compressor` / `turbine`: isentropic machines with an efficiency.
|
|
28
|
+
- `mix`: adiabatic, energy-balanced mixer (exact material balance).
|
|
29
|
+
- `splitter` / `component_separator`: flow split and idealised component split.
|
|
30
|
+
- `bubble_pressure` / `antoine_psat`: lightweight modified-Raoult helpers.
|
|
31
|
+
|
|
32
|
+
## Flowsheets with recycle
|
|
33
|
+
|
|
34
|
+
`tear_solve` closes a recycle by solving the tear fixed point
|
|
35
|
+
`tear = g(tear, theta)` with a Wegstein-accelerated iteration, and
|
|
36
|
+
differentiates the *converged* flowsheet by the implicit function theorem: a
|
|
37
|
+
gradient through the recycle costs one adjoint solve regardless of iteration
|
|
38
|
+
count. `Flowsheet` is a small declarative builder on top of it.
|
|
39
|
+
|
|
40
|
+
## Distillation
|
|
41
|
+
|
|
42
|
+
- **Shortcut** (Fenske-Underwood-Gilliland): `fenske_min_stages`,
|
|
43
|
+
`underwood_min_reflux`, `gilliland_stages`, `kirkbride_feed_stage`, and the
|
|
44
|
+
`shortcut_column` wrapper.
|
|
45
|
+
- **Rigorous** `solve_column`: a multistage equilibrium-stage column (Wang-Henke
|
|
46
|
+
bubble-point, constant molar overflow) with EOS K-values on every stage,
|
|
47
|
+
differentiable through the fixed-point iteration.
|
|
48
|
+
|
|
49
|
+
## Non-ideal separations & diagrams
|
|
50
|
+
|
|
51
|
+
Built on the `fugacio.thermo` property system (via the `eos_model_for`,
|
|
52
|
+
`nrtl_model_for`, `uniquac_model_for`, `unifac_model_for`, and `saft_model_for`
|
|
53
|
+
bridges, the last building a molecular PC-SAFT model from component names):
|
|
54
|
+
|
|
55
|
+
- `flash_vle`, `decanter`, `three_phase_flash`: activity-based VLE / LLE / VLLE
|
|
56
|
+
drums for real, non-ideal mixtures.
|
|
57
|
+
- `pxy_diagram`, `txy_diagram`, `azeotrope_pressure`, `azeotrope_temperature`:
|
|
58
|
+
binary phase diagrams and azeotrope finders.
|
|
59
|
+
- `residue_curve`, `residue_curve_map`: ternary open-evaporation trajectories for
|
|
60
|
+
laying out distillation boundaries.
|
|
61
|
+
|
|
62
|
+
## Reactors
|
|
63
|
+
|
|
64
|
+
Energy-balanced reactor unit operations over one or more `fugacio.thermo`
|
|
65
|
+
`Reaction`s, each runnable isothermally (reporting the heat `duty`) or
|
|
66
|
+
adiabatically (solving the outlet temperature) and returning a `ReactorResult`:
|
|
67
|
+
`equilibrium_reactor` (chemical equilibrium), `stoichiometric_reactor` (specified
|
|
68
|
+
extent or conversion), and kinetic `cstr`, `pfr`, and `batch_reactor` sized by
|
|
69
|
+
volume (and time). `conversion` is a small helper on the inlet/outlet streams.
|
|
70
|
+
|
|
71
|
+
## Reactive separations
|
|
72
|
+
|
|
73
|
+
Reaction coupled to phase separation, both differentiable through the joint solve:
|
|
74
|
+
`reactive_flash` (simultaneous chemical + vapour-liquid equilibrium in a drum) and
|
|
75
|
+
`reactive_distillation` (a rate-based column with per-stage reaction source terms).
|
|
76
|
+
|
|
77
|
+
## Example: differentiate a flash drum
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
import jax
|
|
81
|
+
import jax.numpy as jnp
|
|
82
|
+
from fugacio.sim import Stream, flash_drum
|
|
83
|
+
|
|
84
|
+
feed = Stream.from_fractions(
|
|
85
|
+
("methane", "propane", "n-pentane"),
|
|
86
|
+
jnp.array([0.5, 0.3, 0.2]),
|
|
87
|
+
flow=100.0, t=320.0, p=20e5,
|
|
88
|
+
)
|
|
89
|
+
vapor, liquid = flash_drum(feed, 320.0, 20e5)
|
|
90
|
+
vapor.total, liquid.total # ~74.7 and ~25.3 mol/s
|
|
91
|
+
|
|
92
|
+
# Sensitivity of vapour product flow to drum temperature:
|
|
93
|
+
d_vapor_dT = jax.grad(lambda T: flash_drum(feed, T, 20e5)[0].total)
|
|
94
|
+
d_vapor_dT(320.0)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Example: a recycle, differentiated end-to-end
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
import jax.numpy as jnp
|
|
101
|
+
from fugacio.sim import Stream, flash_drum, mix, splitter, tear_solve
|
|
102
|
+
|
|
103
|
+
components = ("methane", "propane", "n-pentane")
|
|
104
|
+
fresh = Stream.from_fractions(components, jnp.array([0.5, 0.3, 0.2]), 100.0, 320.0, 20e5)
|
|
105
|
+
|
|
106
|
+
def one_pass(recycle, theta):
|
|
107
|
+
mixed = mix([fresh, recycle], t=320.0)
|
|
108
|
+
_vapor, liquid = flash_drum(mixed, theta["T"], theta["P"])
|
|
109
|
+
recycled, _purge = splitter(liquid, jnp.array([theta["r"], 1.0 - theta["r"]]))
|
|
110
|
+
return recycled
|
|
111
|
+
|
|
112
|
+
guess = Stream.from_fractions(components, jnp.array([0.1, 0.3, 0.6]), 30.0, 320.0, 20e5)
|
|
113
|
+
recycle = tear_solve(one_pass, guess, {"T": 320.0, "P": 20e5, "r": 0.5})
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Example: a rigorous distillation column
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
import jax
|
|
120
|
+
import jax.numpy as jnp
|
|
121
|
+
from fugacio.sim import Stream, solve_column
|
|
122
|
+
|
|
123
|
+
feed = Stream.from_fractions(("propane", "n-butane"), jnp.array([0.5, 0.5]), 100.0, 320.0, 10e5)
|
|
124
|
+
col = solve_column(feed, n_stages=12, feed_stage=6, reflux=2.0, distillate_rate=50.0)
|
|
125
|
+
col.distillate.z # ~[0.97, 0.03] propane overhead
|
|
126
|
+
|
|
127
|
+
# Exact gradient of distillate purity w.r.t. reflux ratio:
|
|
128
|
+
jax.grad(
|
|
129
|
+
lambda r: solve_column(feed, 12, 6, r, 50.0).distillate.z[0]
|
|
130
|
+
)(2.0)
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Part of the `fugacio` namespace; installs independently:
|
|
134
|
+
`pip install fugacio-sim`.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "fugacio-sim"
|
|
3
|
+
version = "0.0.1"
|
|
4
|
+
description = "Differentiable steady-state and dynamic process flowsheet simulator (Fugacio)."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.11"
|
|
7
|
+
license = "Apache-2.0"
|
|
8
|
+
authors = [
|
|
9
|
+
{ name = "Owen Carey", email = "37121709+owenthcarey@users.noreply.github.com" },
|
|
10
|
+
]
|
|
11
|
+
keywords = [
|
|
12
|
+
"process-simulation",
|
|
13
|
+
"flowsheet",
|
|
14
|
+
"chemical-engineering",
|
|
15
|
+
"jax",
|
|
16
|
+
"vapor-liquid-equilibrium",
|
|
17
|
+
]
|
|
18
|
+
classifiers = [
|
|
19
|
+
"Development Status :: 2 - Pre-Alpha",
|
|
20
|
+
"Intended Audience :: Science/Research",
|
|
21
|
+
"Programming Language :: Python :: 3",
|
|
22
|
+
"Topic :: Scientific/Engineering :: Chemistry",
|
|
23
|
+
]
|
|
24
|
+
dependencies = [
|
|
25
|
+
"fugacio-thermo",
|
|
26
|
+
"jax>=0.4.34",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
[build-system]
|
|
30
|
+
requires = ["hatchling"]
|
|
31
|
+
build-backend = "hatchling.build"
|
|
32
|
+
|
|
33
|
+
[tool.hatch.build.targets.wheel]
|
|
34
|
+
packages = ["src/fugacio"]
|
|
35
|
+
|
|
36
|
+
[tool.uv.sources]
|
|
37
|
+
fugacio-thermo = { workspace = true }
|