fugacio-sim 0.2.0__tar.gz → 0.3.0__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.
Files changed (81) hide show
  1. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/PKG-INFO +48 -20
  2. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/README.md +45 -17
  3. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/pyproject.toml +2 -2
  4. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/__init__.py +53 -2
  5. fugacio_sim-0.3.0/src/fugacio/sim/distillation.py +939 -0
  6. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/eo/__init__.py +8 -1
  7. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/eo/blocks.py +397 -74
  8. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/eo/flowsheet.py +19 -4
  9. fugacio_sim-0.3.0/src/fugacio/sim/flowsheet.py +704 -0
  10. fugacio_sim-0.3.0/src/fugacio/sim/heat_exchanger.py +358 -0
  11. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/models.py +103 -1
  12. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/properties.py +142 -13
  13. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/stream.py +3 -2
  14. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/units.py +74 -56
  15. fugacio_sim-0.3.0/tests/test_distillation.py +145 -0
  16. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/tests/test_eo.py +62 -0
  17. fugacio_sim-0.3.0/tests/test_flowsheet.py +277 -0
  18. fugacio_sim-0.3.0/tests/test_heat_exchanger.py +110 -0
  19. fugacio_sim-0.3.0/tests/test_plants.py +290 -0
  20. fugacio_sim-0.2.0/src/fugacio/sim/flowsheet.py +0 -286
  21. fugacio_sim-0.2.0/tests/test_flowsheet.py +0 -117
  22. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/.gitignore +0 -0
  23. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/column.py +0 -0
  24. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/control/__init__.py +0 -0
  25. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/control/blocks.py +0 -0
  26. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/control/linearize.py +0 -0
  27. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/control/metrics.py +0 -0
  28. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/control/pid.py +0 -0
  29. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/control/tuning.py +0 -0
  30. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/design.py +0 -0
  31. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/diagrams.py +0 -0
  32. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/dynamics/__init__.py +0 -0
  33. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/dynamics/flowsheet.py +0 -0
  34. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/dynamics/integrate.py +0 -0
  35. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/dynamics/optimize.py +0 -0
  36. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/dynamics/units.py +0 -0
  37. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/economics.py +0 -0
  38. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/eo/optimize.py +0 -0
  39. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/integration/__init__.py +0 -0
  40. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/integration/area.py +0 -0
  41. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/integration/network.py +0 -0
  42. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/integration/streams.py +0 -0
  43. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/integration/targeting.py +0 -0
  44. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/mpc/__init__.py +0 -0
  45. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/mpc/estimation.py +0 -0
  46. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/mpc/linear.py +0 -0
  47. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/mpc/nonlinear.py +0 -0
  48. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/mpc/qp.py +0 -0
  49. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/mpc/riccati.py +0 -0
  50. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/mpc/simulate.py +0 -0
  51. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/optimize.py +0 -0
  52. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/py.typed +0 -0
  53. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/reactive.py +0 -0
  54. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/reactors.py +0 -0
  55. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/separations.py +0 -0
  56. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/utilities.py +0 -0
  57. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/src/fugacio/sim/vle.py +0 -0
  58. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/tests/test_column_rigorous.py +0 -0
  59. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/tests/test_column_shortcut.py +0 -0
  60. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/tests/test_control.py +0 -0
  61. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/tests/test_design.py +0 -0
  62. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/tests/test_dynamic_flowsheet.py +0 -0
  63. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/tests/test_dynamic_optimize.py +0 -0
  64. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/tests/test_dynamic_oracles.py +0 -0
  65. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/tests/test_dynamic_units.py +0 -0
  66. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/tests/test_economics.py +0 -0
  67. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/tests/test_energy_units.py +0 -0
  68. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/tests/test_flowsheet_opt.py +0 -0
  69. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/tests/test_integrate.py +0 -0
  70. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/tests/test_integration.py +0 -0
  71. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/tests/test_integration_oracles.py +0 -0
  72. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/tests/test_mpc.py +0 -0
  73. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/tests/test_mpc_oracles.py +0 -0
  74. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/tests/test_nonideal.py +0 -0
  75. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/tests/test_optimize.py +0 -0
  76. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/tests/test_reactive.py +0 -0
  77. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/tests/test_reactors.py +0 -0
  78. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/tests/test_stream_properties.py +0 -0
  79. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/tests/test_units.py +0 -0
  80. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/tests/test_utilities.py +0 -0
  81. {fugacio_sim-0.2.0 → fugacio_sim-0.3.0}/tests/test_vle.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: fugacio-sim
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: Differentiable steady-state and dynamic process flowsheet simulator (Fugacio).
5
5
  Author-email: Owen Carey <37121709+owenthcarey@users.noreply.github.com>
6
6
  License-Expression: Apache-2.0
@@ -10,7 +10,7 @@ Classifier: Intended Audience :: Science/Research
10
10
  Classifier: Programming Language :: Python :: 3
11
11
  Classifier: Topic :: Scientific/Engineering :: Chemistry
12
12
  Requires-Python: >=3.11
13
- Requires-Dist: fugacio-thermo==0.2.0
13
+ Requires-Dist: fugacio-thermo==0.3.0
14
14
  Requires-Dist: jax>=0.4.34
15
15
  Description-Content-Type: text/markdown
16
16
 
@@ -34,6 +34,15 @@ Any `Stream` has a two-phase-aware enthalpy and entropy (via the
34
34
  just material balances: `molar_enthalpy`, `molar_entropy`, `enthalpy_flow`,
35
35
  `entropy_flow`, `mass_flow`, `molar_mass`.
36
36
 
37
+ ## Property packages
38
+
39
+ Every energy-balanced unit, the rigorous column, the two-sided heat exchanger,
40
+ and the equation-oriented engine take a `model=` argument: a
41
+ `fugacio.thermo.PropertyPackage` built with `package_for(components, method)`
42
+ for any method in `METHODS` (`"pr"`, `"srk"`, `"rk"`, `"vdw"`, `"nrtl"`,
43
+ `"uniquac"`, `"unifac"`, `"dortmund"`, `"pcsaft"`, `"iapws"`). Omitting it keeps
44
+ the Peng-Robinson default.
45
+
37
46
  ## Unit operations (rigorous material + energy balances)
38
47
 
39
48
  - `flash_drum`: isothermal-isobaric vapour/liquid separator.
@@ -43,15 +52,22 @@ just material balances: `molar_enthalpy`, `molar_entropy`, `enthalpy_flow`,
43
52
  - `compressor` / `turbine`: isentropic machines with an efficiency.
44
53
  - `mix`: adiabatic, energy-balanced mixer (exact material balance).
45
54
  - `splitter` / `component_separator`: flow split and idealised component split.
55
+ - `heat_exchanger`: two-sided countercurrent (or parallel) exchanger with
56
+ rigorous T-Q curves on both sides, zone-wise LMTD, and one closing spec
57
+ (`duty`, `t_hot_out`, `t_cold_out`, `min_approach`, or `ua`); each side may
58
+ use its own property package.
46
59
  - `bubble_pressure` / `antoine_psat`: lightweight modified-Raoult helpers.
47
60
 
48
61
  ## Flowsheets with recycle
49
62
 
50
63
  `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.
64
+ `tear = g(tear, theta)` by Wegstein acceleration, Broyden, or full Newton
65
+ (`method=`), and differentiates the *converged* flowsheet by the implicit
66
+ function theorem: a gradient through the recycle costs one adjoint solve
67
+ regardless of iteration count. `Flowsheet` is the declarative builder on top of
68
+ it: register feeds and units in any order and `partition` finds the strongly
69
+ connected blocks (Tarjan), orders them, and selects the tear streams; `solve`
70
+ converges every loop and returns all named streams, differentiable in `theta`.
55
71
 
56
72
  ## Equation-oriented flowsheeting
57
73
 
@@ -64,8 +80,9 @@ the converged plant is differentiable by the implicit function theorem,
64
80
  `degrees_of_freedom` checks the unknown/equation balance, and
65
81
  `optimize_flowsheet_eo` runs nested or full-space simultaneous optimization. The
66
82
  blocks mirror the sequential-modular units (`Mixer`, `Splitter`, `Heater`,
67
- `Valve`, `Pump`, `Compressor`, `Turbine`, `Flash`, `ComponentSeparator`), so the
68
- two engines agree on any flowsheet both can express.
83
+ `Valve`, `Pump`, `Compressor`, `Turbine`, `Flash`, `ComponentSeparator`), plus
84
+ `HeatExchanger`, `StoichiometricReactor`, and `Column` (an embedded rigorous
85
+ MESH column), so the two engines agree on any flowsheet both can express.
69
86
 
70
87
  ```python
71
88
  import jax.numpy as jnp
@@ -92,9 +109,15 @@ sol["vapor"].total
92
109
  - **Shortcut** (Fenske-Underwood-Gilliland): `fenske_min_stages`,
93
110
  `underwood_min_reflux`, `gilliland_stages`, `kirkbride_feed_stage`, and the
94
111
  `shortcut_column` wrapper.
95
- - **Rigorous** `solve_column`: a multistage equilibrium-stage column (Wang-Henke
96
- bubble-point, constant molar overflow) with EOS K-values on every stage,
97
- differentiable through the fixed-point iteration.
112
+ - **Rigorous MESH** `rigorous_column`: simultaneous-correction
113
+ (Naphtali-Sandholm) column with full stage energy balances on any property
114
+ package; multiple feeds (`ColumnFeed`), side draws, stage duties, a pressure
115
+ profile, Murphree efficiency, total/partial/no condenser, kettle/no reboiler,
116
+ and design specs as equations (`reflux_ratio`, `distillate_rate`,
117
+ `bottoms_rate`, `boilup_ratio`, `condenser_duty`, `purity`, `recovery`,
118
+ `component_flow`, `stage_temperature`). `absorber` and `stripper` wrap it.
119
+ - **Constant molar overflow** `solve_column`: the lighter Wang-Henke
120
+ bubble-point column, kept for quick estimates.
98
121
 
99
122
  ## Non-ideal separations & diagrams
100
123
 
@@ -168,16 +191,21 @@ recycle = tear_solve(one_pass, guess, {"T": 320.0, "P": 20e5, "r": 0.5})
168
191
  ```python
169
192
  import jax
170
193
  import jax.numpy as jnp
171
- from fugacio.sim import Stream, solve_column
194
+ from fugacio.sim import ColumnFeed, Stream, distillate_rate, purity, reflux_ratio, rigorous_column
172
195
 
173
196
  feed = Stream.from_fractions(("propane", "n-butane"), jnp.array([0.5, 0.5]), 100.0, 320.0, 10e5)
174
- col = solve_column(feed, n_stages=12, feed_stage=6, reflux=2.0, distillate_rate=50.0)
175
- col.distillate.z # ~[0.97, 0.03] propane overhead
176
-
177
- # Exact gradient of distillate purity w.r.t. reflux ratio:
178
- jax.grad(
179
- lambda r: solve_column(feed, 12, 6, r, 50.0).distillate.z[0]
180
- )(2.0)
197
+ col = rigorous_column([ColumnFeed(feed, 6)], 12, p=10e5,
198
+ specs=[reflux_ratio(2.0), distillate_rate(50.0)])
199
+ col.distillate.z # propane overhead
200
+ col.reboiler_duty, col.t # duty from the stage energy balances; T profile
201
+
202
+ # Impose the purity instead and ask for the reflux it takes, and its energy cost:
203
+ def reboiler_duty(x_target):
204
+ res = rigorous_column([ColumnFeed(feed, 6)], 12, p=10e5,
205
+ specs=[distillate_rate(50.0), purity("distillate", 0, x_target)])
206
+ return res.reboiler_duty
207
+
208
+ jax.grad(reboiler_duty)(0.97) # W per unit mole fraction, exact
181
209
  ```
182
210
 
183
211
  Part of the `fugacio` namespace; installs independently:
@@ -18,6 +18,15 @@ Any `Stream` has a two-phase-aware enthalpy and entropy (via the
18
18
  just material balances: `molar_enthalpy`, `molar_entropy`, `enthalpy_flow`,
19
19
  `entropy_flow`, `mass_flow`, `molar_mass`.
20
20
 
21
+ ## Property packages
22
+
23
+ Every energy-balanced unit, the rigorous column, the two-sided heat exchanger,
24
+ and the equation-oriented engine take a `model=` argument: a
25
+ `fugacio.thermo.PropertyPackage` built with `package_for(components, method)`
26
+ for any method in `METHODS` (`"pr"`, `"srk"`, `"rk"`, `"vdw"`, `"nrtl"`,
27
+ `"uniquac"`, `"unifac"`, `"dortmund"`, `"pcsaft"`, `"iapws"`). Omitting it keeps
28
+ the Peng-Robinson default.
29
+
21
30
  ## Unit operations (rigorous material + energy balances)
22
31
 
23
32
  - `flash_drum`: isothermal-isobaric vapour/liquid separator.
@@ -27,15 +36,22 @@ just material balances: `molar_enthalpy`, `molar_entropy`, `enthalpy_flow`,
27
36
  - `compressor` / `turbine`: isentropic machines with an efficiency.
28
37
  - `mix`: adiabatic, energy-balanced mixer (exact material balance).
29
38
  - `splitter` / `component_separator`: flow split and idealised component split.
39
+ - `heat_exchanger`: two-sided countercurrent (or parallel) exchanger with
40
+ rigorous T-Q curves on both sides, zone-wise LMTD, and one closing spec
41
+ (`duty`, `t_hot_out`, `t_cold_out`, `min_approach`, or `ua`); each side may
42
+ use its own property package.
30
43
  - `bubble_pressure` / `antoine_psat`: lightweight modified-Raoult helpers.
31
44
 
32
45
  ## Flowsheets with recycle
33
46
 
34
47
  `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.
48
+ `tear = g(tear, theta)` by Wegstein acceleration, Broyden, or full Newton
49
+ (`method=`), and differentiates the *converged* flowsheet by the implicit
50
+ function theorem: a gradient through the recycle costs one adjoint solve
51
+ regardless of iteration count. `Flowsheet` is the declarative builder on top of
52
+ it: register feeds and units in any order and `partition` finds the strongly
53
+ connected blocks (Tarjan), orders them, and selects the tear streams; `solve`
54
+ converges every loop and returns all named streams, differentiable in `theta`.
39
55
 
40
56
  ## Equation-oriented flowsheeting
41
57
 
@@ -48,8 +64,9 @@ the converged plant is differentiable by the implicit function theorem,
48
64
  `degrees_of_freedom` checks the unknown/equation balance, and
49
65
  `optimize_flowsheet_eo` runs nested or full-space simultaneous optimization. The
50
66
  blocks mirror the sequential-modular units (`Mixer`, `Splitter`, `Heater`,
51
- `Valve`, `Pump`, `Compressor`, `Turbine`, `Flash`, `ComponentSeparator`), so the
52
- two engines agree on any flowsheet both can express.
67
+ `Valve`, `Pump`, `Compressor`, `Turbine`, `Flash`, `ComponentSeparator`), plus
68
+ `HeatExchanger`, `StoichiometricReactor`, and `Column` (an embedded rigorous
69
+ MESH column), so the two engines agree on any flowsheet both can express.
53
70
 
54
71
  ```python
55
72
  import jax.numpy as jnp
@@ -76,9 +93,15 @@ sol["vapor"].total
76
93
  - **Shortcut** (Fenske-Underwood-Gilliland): `fenske_min_stages`,
77
94
  `underwood_min_reflux`, `gilliland_stages`, `kirkbride_feed_stage`, and the
78
95
  `shortcut_column` wrapper.
79
- - **Rigorous** `solve_column`: a multistage equilibrium-stage column (Wang-Henke
80
- bubble-point, constant molar overflow) with EOS K-values on every stage,
81
- differentiable through the fixed-point iteration.
96
+ - **Rigorous MESH** `rigorous_column`: simultaneous-correction
97
+ (Naphtali-Sandholm) column with full stage energy balances on any property
98
+ package; multiple feeds (`ColumnFeed`), side draws, stage duties, a pressure
99
+ profile, Murphree efficiency, total/partial/no condenser, kettle/no reboiler,
100
+ and design specs as equations (`reflux_ratio`, `distillate_rate`,
101
+ `bottoms_rate`, `boilup_ratio`, `condenser_duty`, `purity`, `recovery`,
102
+ `component_flow`, `stage_temperature`). `absorber` and `stripper` wrap it.
103
+ - **Constant molar overflow** `solve_column`: the lighter Wang-Henke
104
+ bubble-point column, kept for quick estimates.
82
105
 
83
106
  ## Non-ideal separations & diagrams
84
107
 
@@ -152,16 +175,21 @@ recycle = tear_solve(one_pass, guess, {"T": 320.0, "P": 20e5, "r": 0.5})
152
175
  ```python
153
176
  import jax
154
177
  import jax.numpy as jnp
155
- from fugacio.sim import Stream, solve_column
178
+ from fugacio.sim import ColumnFeed, Stream, distillate_rate, purity, reflux_ratio, rigorous_column
156
179
 
157
180
  feed = Stream.from_fractions(("propane", "n-butane"), jnp.array([0.5, 0.5]), 100.0, 320.0, 10e5)
158
- col = solve_column(feed, n_stages=12, feed_stage=6, reflux=2.0, distillate_rate=50.0)
159
- col.distillate.z # ~[0.97, 0.03] propane overhead
160
-
161
- # Exact gradient of distillate purity w.r.t. reflux ratio:
162
- jax.grad(
163
- lambda r: solve_column(feed, 12, 6, r, 50.0).distillate.z[0]
164
- )(2.0)
181
+ col = rigorous_column([ColumnFeed(feed, 6)], 12, p=10e5,
182
+ specs=[reflux_ratio(2.0), distillate_rate(50.0)])
183
+ col.distillate.z # propane overhead
184
+ col.reboiler_duty, col.t # duty from the stage energy balances; T profile
185
+
186
+ # Impose the purity instead and ask for the reflux it takes, and its energy cost:
187
+ def reboiler_duty(x_target):
188
+ res = rigorous_column([ColumnFeed(feed, 6)], 12, p=10e5,
189
+ specs=[distillate_rate(50.0), purity("distillate", 0, x_target)])
190
+ return res.reboiler_duty
191
+
192
+ jax.grad(reboiler_duty)(0.97) # W per unit mole fraction, exact
165
193
  ```
166
194
 
167
195
  Part of the `fugacio` namespace; installs independently:
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "fugacio-sim"
3
- version = "0.2.0"
3
+ version = "0.3.0"
4
4
  description = "Differentiable steady-state and dynamic process flowsheet simulator (Fugacio)."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -22,7 +22,7 @@ classifiers = [
22
22
  "Topic :: Scientific/Engineering :: Chemistry",
23
23
  ]
24
24
  dependencies = [
25
- "fugacio-thermo==0.2.0",
25
+ "fugacio-thermo==0.3.0",
26
26
  "jax>=0.4.34",
27
27
  ]
28
28
 
@@ -116,6 +116,27 @@ from fugacio.sim.diagrams import (
116
116
  residue_curve_map,
117
117
  txy_diagram,
118
118
  )
119
+ from fugacio.sim.distillation import (
120
+ ColumnFeed,
121
+ ColumnSpec,
122
+ RigorousColumnResult,
123
+ SideDraw,
124
+ StageDuty,
125
+ absorber,
126
+ boilup_ratio,
127
+ bottoms_rate,
128
+ component_flow,
129
+ condenser_duty,
130
+ distillate_rate,
131
+ purity,
132
+ reboiler_duty,
133
+ recovery,
134
+ reflux_rate,
135
+ reflux_ratio,
136
+ rigorous_column,
137
+ stage_temperature,
138
+ stripper,
139
+ )
119
140
  from fugacio.sim.dynamics import (
120
141
  DynamicCSTR,
121
142
  DynamicEstimateResult,
@@ -184,7 +205,8 @@ from fugacio.sim.eo import (
184
205
  Valve,
185
206
  optimize_flowsheet_eo,
186
207
  )
187
- from fugacio.sim.flowsheet import Flowsheet, tear_solve
208
+ from fugacio.sim.flowsheet import TEAR_METHODS, Flowsheet, Partition, tear_solve
209
+ from fugacio.sim.heat_exchanger import HeatExchangerResult, heat_exchanger
188
210
  from fugacio.sim.integration import (
189
211
  CompositeCurves,
190
212
  Exchanger,
@@ -213,9 +235,12 @@ from fugacio.sim.integration import (
213
235
  verify_network,
214
236
  )
215
237
  from fugacio.sim.models import (
238
+ METHODS,
216
239
  UnifacModel,
217
240
  eos_model_for,
241
+ helmholtz_package_for,
218
242
  nrtl_model_for,
243
+ package_for,
219
244
  saft_model_for,
220
245
  unifac_model_for,
221
246
  uniquac_model_for,
@@ -331,12 +356,16 @@ from fugacio.sim.vle import antoine_psat, bubble_pressure
331
356
  __all__ = [
332
357
  "CEPCI_DEFAULT",
333
358
  "CEPCI_REF",
359
+ "METHODS",
334
360
  "PID",
335
361
  "STEAM_LEVELS",
362
+ "TEAR_METHODS",
336
363
  "AzeotropeResult",
337
364
  "Block",
338
365
  "ClosedLoop",
366
+ "ColumnFeed",
339
367
  "ColumnResult",
368
+ "ColumnSpec",
340
369
  "ComponentSeparator",
341
370
  "CompositeCurves",
342
371
  "Compressor",
@@ -365,6 +394,7 @@ __all__ = [
365
394
  "GrandComposite",
366
395
  "HeatCascade",
367
396
  "HeatExchangerNetwork",
397
+ "HeatExchangerResult",
368
398
  "HeatStream",
369
399
  "Heater",
370
400
  "HeaterResult",
@@ -383,6 +413,7 @@ __all__ = [
383
413
  "OptimalDtMin",
384
414
  "OptimizeResult",
385
415
  "PIDState",
416
+ "Partition",
386
417
  "PinchResult",
387
418
  "Pump",
388
419
  "PumpResult",
@@ -393,10 +424,13 @@ __all__ = [
393
424
  "ReactiveFlashResult",
394
425
  "ReactorResult",
395
426
  "ResidueCurve",
427
+ "RigorousColumnResult",
396
428
  "Scales",
397
429
  "ShortcutResult",
430
+ "SideDraw",
398
431
  "SpecResult",
399
432
  "Splitter",
433
+ "StageDuty",
400
434
  "StateSpace",
401
435
  "SteamHeatingResult",
402
436
  "SteamTurbineResult",
@@ -412,6 +446,7 @@ __all__ = [
412
446
  "Utility",
413
447
  "Valve",
414
448
  "WorkResult",
449
+ "absorber",
415
450
  "amigo",
416
451
  "annualized_capital",
417
452
  "antoine_psat",
@@ -422,6 +457,8 @@ __all__ = [
422
457
  "bare_module_cost",
423
458
  "batch_reactor",
424
459
  "bode",
460
+ "boilup_ratio",
461
+ "bottoms_rate",
425
462
  "bubble_pressure",
426
463
  "c2d",
427
464
  "capital_cost_target",
@@ -432,10 +469,12 @@ __all__ = [
432
469
  "column_diameter",
433
470
  "column_diameter_for",
434
471
  "column_height",
472
+ "component_flow",
435
473
  "component_separator",
436
474
  "composite_curves",
437
475
  "compressor",
438
476
  "condensate_flash_fraction",
477
+ "condenser_duty",
439
478
  "constant_setpoint",
440
479
  "controller",
441
480
  "conversion",
@@ -447,6 +486,7 @@ __all__ = [
447
486
  "decanter",
448
487
  "discounted_payback",
449
488
  "discretize",
489
+ "distillate_rate",
450
490
  "dlqr",
451
491
  "enthalpy_flow",
452
492
  "entropy_flow",
@@ -463,9 +503,11 @@ __all__ = [
463
503
  "gilliland_stages",
464
504
  "grand_composite_curve",
465
505
  "heat_cascade",
506
+ "heat_exchanger",
466
507
  "heat_exchanger_area",
467
508
  "heat_stream",
468
509
  "heater",
510
+ "helmholtz_package_for",
469
511
  "iae",
470
512
  "imc_tuning",
471
513
  "installed_capital",
@@ -507,6 +549,7 @@ __all__ = [
507
549
  "optimize_flowsheet_eo",
508
550
  "overshoot",
509
551
  "p_only",
552
+ "package_for",
510
553
  "pfr",
511
554
  "pi",
512
555
  "pinch_analysis",
@@ -514,13 +557,19 @@ __all__ = [
514
557
  "pressure_factor",
515
558
  "pump",
516
559
  "purchased_cost",
560
+ "purity",
517
561
  "pxy_diagram",
518
562
  "quadratic_tracking",
519
563
  "reactive_distillation",
520
564
  "reactive_flash",
565
+ "reboiler_duty",
566
+ "recovery",
567
+ "reflux_rate",
568
+ "reflux_ratio",
521
569
  "relative_volatility",
522
570
  "residue_curve",
523
571
  "residue_curve_map",
572
+ "rigorous_column",
524
573
  "rise_time",
525
574
  "saft_model_for",
526
575
  "saturated_steam_temperature",
@@ -534,12 +583,14 @@ __all__ = [
534
583
  "solve_qp",
535
584
  "solve_qp_canonical",
536
585
  "splitter",
586
+ "stage_temperature",
537
587
  "steam_enthalpy",
538
588
  "steam_heating",
539
589
  "steam_quality_after_letdown",
540
590
  "steam_turbine",
541
591
  "step_info",
542
592
  "stoichiometric_reactor",
593
+ "stripper",
543
594
  "supertarget",
544
595
  "surface_tension",
545
596
  "synthesize_network",
@@ -567,4 +618,4 @@ __all__ = [
567
618
  "ziegler_nichols",
568
619
  ]
569
620
 
570
- __version__ = "0.2.0"
621
+ __version__ = "0.3.0"