Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
5f6a082
add per-stream approach temperature contributions to the numerics
sarangbhagwat Oct 16, 2026
ad1bcef
add unit keys and facility support for approach contributions
sarangbhagwat Oct 16, 2026
a3351f5
document per-stream approach temperature contributions
sarangbhagwat Oct 16, 2026
2659e8c
add the targeting module: composite curves and utility targets
sarangbhagwat Oct 16, 2026
38d609a
add area, units, capital and total cost targets and the supertargetin…
sarangbhagwat Oct 16, 2026
4965f9a
add the facility's targets method and the network report
sarangbhagwat Oct 16, 2026
2e42baa
document targeting and supertargeting
sarangbhagwat Oct 16, 2026
697c456
address review 1 (f1-numerics): accept all-unspecified contributions …
sarangbhagwat Oct 17, 2026
f879105
address review 1 (f1-facility): stop targets() calling the contributi…
sarangbhagwat Oct 17, 2026
7c95ff9
address review 1 (tg-core): keep sensible utility lines inside the gcc
sarangbhagwat Oct 17, 2026
9e9ae32
address review 1 (tg-super): validate P, warn on a sweep with no fini…
sarangbhagwat Oct 17, 2026
08511d1
address review 1 (tg-report): check report states and make the plots …
sarangbhagwat Oct 17, 2026
dfb8441
address review 1 (docs): define agent levels correctly and quote the …
sarangbhagwat Oct 17, 2026
28b41bd
address review 1 (e2e): validate T_min_app, price facility targets ov…
sarangbhagwat Oct 17, 2026
c62f0f3
address review 2 (f1-facility): match unit keys by identity, read the…
sarangbhagwat Oct 17, 2026
f2bc9cd
address review 2 (tg-core): serve point loads at stretch ends, cap le…
sarangbhagwat Oct 17, 2026
b4eeee6
address review 2 (tg-super): keep the shell and tubes the area fills …
sarangbhagwat Oct 17, 2026
4da77b0
address review 2 (tg-report): align unserved balanced curves, place s…
sarangbhagwat Oct 17, 2026
8a26a32
address review 2 (docs): explain the extra unit by the loop, list loo…
sarangbhagwat Oct 17, 2026
7c24a67
address review 3 (tg-core): refuse non-exchanger heat utilities, chec…
sarangbhagwat Oct 17, 2026
df74460
address review 3 (tg-report): keep plot labels inside the axes, lay o…
sarangbhagwat Oct 17, 2026
9573eb7
address review 3 (docs): give the true rule for the flat-stretch opti…
sarangbhagwat Oct 17, 2026
50d83da
address review 3 (e2e): accept keys of unbuilt auxiliaries and idle h…
sarangbhagwat Oct 17, 2026
1c9417a
address review 4 (f1-facility): accept only biosteam's own auxiliary …
sarangbhagwat Oct 17, 2026
d5fc2ab
address review 4 (tg-core): cap agent levels only by streams their he…
sarangbhagwat Oct 17, 2026
8277a17
address review 4 (tg-report): document and test the inf area of a cro…
sarangbhagwat Oct 17, 2026
6c026b3
address review 5 (f1-numerics): pass the scalar T_min_app as the defa…
sarangbhagwat Oct 17, 2026
8c259b5
address review 5 (tg-core): check the shift of utilities, test point …
sarangbhagwat Oct 17, 2026
0e58023
address review 5 (tg-super): refine on both sides of the least tac, n…
sarangbhagwat Oct 17, 2026
d771f83
address review 5 (tg-report): floor the outlet check at a micro-kelvi…
sarangbhagwat Oct 17, 2026
e11f3c6
address review 5 (e2e): say the utility cost target is no bound, flag…
sarangbhagwat Oct 17, 2026
f12aa7f
address review 6 (f1-facility): check the id held at an auxiliary's p…
sarangbhagwat Oct 17, 2026
0a089bf
address review 6 (tg-core): pin which served streams bound a sensible…
sarangbhagwat Oct 17, 2026
1175b80
address review 6 (tg-report): keep balanced curve labels inside the a…
sarangbhagwat Oct 17, 2026
db2d707
address review 7 (f1-facility): accept stage keys of any number, hint…
sarangbhagwat Oct 17, 2026
9c7e4bc
address review 7 (tg-report): place plot labels in one pass, in order…
sarangbhagwat Oct 17, 2026
e57abca
address review 7 (e2e): keep the holders of owner-less stages in targ…
sarangbhagwat Oct 17, 2026
9d86dec
address review 8 (f1-facility): walk nested auxiliaries without biost…
sarangbhagwat Oct 17, 2026
9834722
address review 8 (tg-core): cap a sensible agent's level at a stream …
sarangbhagwat Oct 17, 2026
b6c187b
address review 8 (tg-report): put the unserved note under the x axis,…
sarangbhagwat Oct 17, 2026
0cf7fa4
address review 8 (e2e): warn when HXN.targets() is of stages rebuilt …
sarangbhagwat Oct 17, 2026
fb49239
address review 9 (f1-facility): take exchangers held through heat uti…
sarangbhagwat Oct 18, 2026
8ed92ec
address review 9 (tg-core): pin which streams may bound an agent's le…
sarangbhagwat Oct 18, 2026
6d900f9
address review 9 (tg-super): let area and capital targets take the ag…
sarangbhagwat Oct 18, 2026
f18ff50
address review 9 (tg-report): keep the legend of the composite curves…
sarangbhagwat Oct 18, 2026
915e5cd
address review 9 (e2e): warn of written-over heat utilities only when…
sarangbhagwat Oct 18, 2026
5aa2c7d
isolate the default facility path from the key machinery
sarangbhagwat Oct 18, 2026
c34e710
address review 10 (tg-super): resolve unit keys of h only when some a…
sarangbhagwat Oct 18, 2026
20c52d4
address review 11 (e2e): warn when targets mix a changed inlet with a…
sarangbhagwat Oct 18, 2026
1432e0a
address review 12 (e2e): count the heat utilities of units in paralle…
sarangbhagwat Oct 18, 2026
120dbad
address review 13 (f1-facility): count the streams of a unit in paral…
sarangbhagwat Oct 18, 2026
e1877b7
address review 14 (tg-core): refuse heat utilities their units no lon…
sarangbhagwat Oct 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,15 @@ split, the network is a best-effort one close to the targets. With
`HeatExchangerNetwork(..., stream_splitting=True)`, streams are instead
split into parallel branches there (BioSTEAM splitters and rigorous mixers),
and the network reaches the MER targets (not guaranteed with `avoid_recycle`;
see the documentation for the limits with real thermodynamics).
see the documentation for the limits with real thermodynamics). Each stream
can also carry its own approach temperature contribution
(`HeatExchangerNetwork(..., approach_contributions={unit: dT})`): a match
must then keep the sum of its two streams' contributions instead of
`T_min_app`. `hensmith.targeting` targets what a network of the streams
can achieve before one is synthesized (several utilities priced by BioSTEAM,
area, units, capital and total annualized cost: `HXN.targets()`), finds the
`T_min_app` of the least targeted total annualized cost (`supertarget`), and
compares a synthesized network with its targets (`network_report`).

```python
import biosteam as bst # hensmith units plug into BioSTEAM systems
Expand Down
7 changes: 4 additions & 3 deletions docs/_demo_src/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ directories themselves.
| `examples/ch01_quickstart.py` | `_static/images/examples/tutorial_01_quickstart_flowsheet_light.png`, `…_flowsheet_dark.png`, `_static/images/examples/tutorial_01_quickstart_pinch_diagram.png`; `_generated/ch01_results.txt`, `ch01_loads.txt`, `ch01_life_cycles.txt`, `ch01_summary.txt` |
| `examples/ch02_pinch_analysis.py` | `_static/images/examples/tutorial_02_composite_curves.png`, `tutorial_02_grand_composite.png`; `_generated/ch02_threshold.txt`, `ch02_table.txt`, `ch02_compare.txt` |
| `examples/ch03_network_anatomy.py` | `_static/images/examples/tutorial_03_hxn_flowsheet_light.png`, `…_hxn_flowsheet_dark.png`, `tutorial_03_pinch_diagram_minimal.png`; `_generated/ch03_flowsheet.txt`, `ch03_life_cycles.txt`, `ch03_stage.txt`, `ch03_pinch_Ts.txt`, `ch03_accounting.txt` |
| `examples/ch04_configuring.py` | `_static/images/examples/tutorial_04_T_min_app_sweep.png`, `tutorial_04_ten_streams_pinch_diagram.png`; `_generated/ch04_sweep.txt`, `ch04_splitting.txt`, `ch04_ignored.txt`, `ch04_ten_streams.txt` |
| `examples/ch04_configuring.py` | `_static/images/examples/tutorial_04_T_min_app_sweep.png`, `tutorial_04_ten_streams_pinch_diagram.png`; `_generated/ch04_sweep.txt`, `ch04_splitting.txt`, `ch04_contributions.txt`, `ch04_ignored.txt`, `ch04_ten_streams.txt` |
| `examples/ch05_targeting.py` | `_static/images/examples/tutorial_05_composite_curves.png`, `tutorial_05_balanced_composites.png`, `tutorial_05_grand_composite.png`, `tutorial_05_supertargets.png`, `tutorial_05_trade_off.png`; `_generated/ch05_targets.txt`, `ch05_utilities.txt`, `ch05_summary.txt`, `ch05_sweep.txt`, `ch05_trade_off.txt`, `ch05_report.txt` |
| `make_hero_gif.py` | `_static/images/demo/hero_light.gif`, `hero_dark.gif` (8 s loop, 20 fps, 2000 × 720), `hero_light_still.png`, `hero_dark_still.png` (the frame-0 stills served under `prefers-reduced-motion`) |
| `build_demo.py` | `_static/quickstart_demo.html` — the interactive quickstart demo, filled in from `quickstart_demo_template.html` |
| `make_poster.py` | `_static/images/examples/quickstart_demo_poster.png` — the README poster that links to the demo (2400 × 1260) |
Expand Down Expand Up @@ -82,9 +83,9 @@ Three mechanisms, all enforced at regeneration time:
- **Regions.** Each chapter script marks the code the page shows with
`# [start:<region>]` / `# [end:<region>]` comments, and the `.rst` page pulls
it in with `literalinclude` + `:start-after:` / `:end-before:`. The reader
therefore sees code that *was executed*, not a retyped copy. Chapters 02–04
therefore sees code that *was executed*, not a retyped copy. Chapters 02–05
each build the quickstart system in a `system` region whose body is exactly
chapter 01's `build` + `network` + `simulate` bodies, so all four chapters
chapter 01's `build` + `network` + `simulate` bodies, so all five chapters
provably describe one system.
- **Captures.** `_common.capturing(name)` redirects everything printed inside a
block into `_generated/<name>.txt` (and echoes it), and
Expand Down
1 change: 1 addition & 0 deletions docs/_demo_src/build_all.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
'examples/ch02_pinch_analysis.py',
'examples/ch03_network_anatomy.py',
'examples/ch04_configuring.py',
'examples/ch05_targeting.py',
'make_hero_gif.py',
'build_demo.py', # consumes the chapter-01 captures and figures, and the logo
'make_poster.py', # consumes the chapter-01 pinch diagram and the logo
Expand Down
30 changes: 29 additions & 1 deletion docs/_demo_src/examples/ch04_configuring.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
"""Tutorial chapter 04 (docs/source/tutorial/04_configuring.rst): configuring a
HeatExchangerNetwork -- sweeping the minimum approach temperature to expose the
utility/capital trade-off, splitting streams where the targets need it
(``stream_splitting=True``), scoping the analysis with ``ignored=``, and
(``stream_splitting=True``), giving streams their own approach temperature
contributions (``approach_contributions=``), scoping the analysis with
``ignored=``, and
synthesizing a larger ten-stream system (the ten-stream case of the regression
suite, inlined here rather than imported from ``tests``). Regions between
``# [start:x]`` / ``# [end:x]`` are literalinclude'd by the page; everything
Expand Down Expand Up @@ -128,6 +130,32 @@ def main():
HXN.stream_splitting = False
HXN.T_min_app = 5.
# [end:splitting]
with capturing('ch04_contributions'):
# [start:contributions]
HXN.approach_contributions = {
'D1': 1., # the column's condenser and reboiler: phase change
F1: 1., # the flash's heater boils its feed
} # the two product coolers keep T_min_app / 2 = 2.5 K
sys.simulate()
info = HXN.synthesis_info
print(f"status: {info['status']}, {len(HXN.new_HXs)} process exchangers, "
f"{HXN.installed_costs['Heat exchangers']:.4g} USD added installed cost")
print(f'heating {HXN.actual_heat_util_load:.4g} kJ/hr, '
f'cooling {HXN.actual_cool_util_load:.4g} kJ/hr')
contributions = info['approach_contributions'] # by stream, as used
print('contributions by stream [K]:', contributions)
required = {} # each match: its two streams' sum
for c, life_cycle in zip(contributions, HXN.stream_life_cycles):
for stage in life_cycle.life_cycle:
if stage.unit in HXN.new_HXs:
required[stage.unit] = required.get(stage.unit, 0.) + c
for hx in HXN.new_HXs:
print(f'{hx.ID:<10} requires {required[hx]:.1f} K, Q = {hx.Q:.4g} kJ/hr')
print(f"smallest approach {info['min_approach']:.3f} K, "
f"margin over the requirement {info['min_approach_margin']:.2g} K")
HXN.approach_contributions = None
# [end:contributions]
assert info['min_approach_margin'] >= -1e-6 - 1e-9
with capturing('ch04_ten_streams'):
# [start:ten_streams]
bst.settings.set_thermo(['Water', 'Ethanol'], cache=True)
Expand Down
199 changes: 199 additions & 0 deletions docs/_demo_src/examples/ch05_targeting.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
# -*- coding: utf-8 -*-
# hensmith: Heat Exchanger Network Synthesis, Modeling, Integration,
# Thermodynamics, and Heuristics
# Copyright (C) 2020-, Sarang Bhagwat <sarangbhagwat.developer@gmail.com>
#
# This module is under the UIUC open-source license. See
# github.com/BioSTEAMDevelopmentGroup/hensmith/blob/master/LICENSE.txt
# for license details.
"""Tutorial chapter 05 (docs/source/tutorial/05_targeting.rst): targeting and
supertargeting with ``hensmith.targeting`` -- the facility's targets
(``HXN.targets()``), the multiple-utility targets priced by biosteam, the
composite, balanced composite and grand composite curves drawn by the
library, the area, units, capital and total annualized cost targets, the
``T_min_app`` sweep for the least total annualized cost (on the quickstart
system and on a two-stream problem with an interior optimum), and the report
that compares the synthesized network with its targets. Regions between
``# [start:x]`` / ``# [end:x]`` are literalinclude'd by the page; everything
else is plumbing.

python docs/_demo_src/examples/ch05_targeting.py
"""
import sys
import pathlib
sys.path.insert(0, str(pathlib.Path(__file__).resolve().parents[1]))
import _common # noqa: E402 (sets NUMBA_DISABLE_JIT / DISABLE_PREFERENCES, Agg)
from _common import capturing, save


# [start:imports]
import numpy as np
import matplotlib.pyplot as plt
from hensmith import (supertarget, network_report, plot_composite_curves,
plot_grand_composite_curve, plot_supertargets)
# [end:imports]


def knots(T, H):
"""Knots [K, kJ/hr] of a polyline without its zero-length steps and
without the points inside a straight run, so that two polylines tracing
the same curve on different grids compare knot by knot."""
T, H = np.asarray(T, float), np.asarray(H, float)
step = np.r_[True, (np.abs(np.diff(T)) > 1e-9) | (np.abs(np.diff(H)) > 1e-6)]
T, H = T[step], H[step]
if T.size < 3: return T, H
a, b, c = slice(None, -2), slice(1, -1), slice(2, None)
cross = (T[b] - T[a]) * (H[c] - H[a]) - (H[b] - H[a]) * (T[c] - T[a])
bend = np.abs(cross) > 1e-9 * np.abs(T[c] - T[a]) * np.abs(H[c] - H[a])
keep = np.r_[True, bend, True]
return T[keep], H[keep]


def main():
# [start:system]
import biosteam as bst
from hensmith import HeatExchangerNetwork

bst.settings.set_thermo(['Water', 'Methanol', 'Glycerol'], cache=True)
bst.main_flowsheet.set_flowsheet('quickstart')
feed1 = bst.Stream('feed1', flow=(8000, 100, 25))
feed2 = bst.Stream('feed2', flow=(10000, 1000, 10))
D1 = bst.ShortcutColumn('D1', ins=feed1,
outs=('distillate', 'bottoms_product'),
LHK=('Methanol', 'Water'),
y_top=0.99, x_bot=0.01, k=2,
is_divided=True)
D1_H1 = bst.HXutility('D1_H1', ins=D1.outs[1], T=300)
D1_H2 = bst.HXutility('D1_H2', ins=D1.outs[0], T=300)
F1 = bst.Flash('F1', ins=feed2, outs=('vapor', 'liquid'), V=0.9, P=101325)
HXN = HeatExchangerNetwork('HXN', T_min_app=5.)
sys = bst.System.from_units('sys', units=[D1, D1_H1, D1_H2, F1, HXN])
sys.simulate()
# [end:system]
with capturing('ch05_targets'):
# [start:targets]
targets = HXN.targets() # the facility's streams at its T_min_app
print(targets)
print('streams:', targets.labels)
print(f'shifted pinch: {targets.pinch_T:.2f} K')
info = HXN.synthesis_info
print('equal to the synthesis targets:',
targets.Q_hot == info['Q_hot_target'], targets.Q_cold == info['Q_cold_target'])
print(f'heating utility of the network: {HXN.actual_heat_util_load:.4g} kJ/hr')
# [end:targets]
with capturing('ch05_utilities'):
# [start:utilities]
utilities = targets.utility_targets() # biosteam's default agents
print('agent duty utility duty level process T [K] cost')
print(' [kJ/hr] [kJ/hr] [K] in -> out [USD/hr]')
for u in utilities:
print(f'{u.ID:<18} {u.duty:<10.4g} {u.utility_duty:<12.4g} {u.level:<6.2f} '
f'{u.T_in:.2f} -> {u.T_out:.2f} {u.cost:.2f}')
print(f'utility cost target: {sum(u.cost for u in utilities):.2f} USD/hr')
for u in utilities:
print(f'{u.ID}: {u.flow:.4g} kmol/hr, from {u.T_utility_in:.2f} to {u.T_utility_out:.2f} K')
# [end:utilities]
# [start:composites]
fig, ax = plot_composite_curves(targets)
fig_balanced, ax_balanced = plot_composite_curves(targets, kind='balanced',
utilities=utilities)
# [end:composites]
save(fig, 'tutorial_05_composite_curves.png')
save(fig_balanced, 'tutorial_05_balanced_composites.png')
plt.close(fig); plt.close(fig_balanced)
# [start:gcc]
fig, ax = plot_grand_composite_curve(targets, utilities=utilities)
# [end:gcc]
save(fig, 'tutorial_05_grand_composite.png')
plt.close(fig)
with capturing('ch05_summary'):
# [start:supertargets]
print('units:', targets.units_target(utilities))
capital = targets.capital_cost_target(utilities)
print(f"{capital['N_area_shells']} of {capital['N_shells']} shells share the area: "
f"{capital['shell_area']:.4g} m2 each, {capital['type']}")
summary = targets.summary() # 10 % over 10 years; 8000 h/yr (no system hours)
for key, value in summary.items(): # numbers, and the shell type
print(f'{key:<24} {value}' if isinstance(value, str) else f'{key:<24} {value:.6g}')
# [end:supertargets]
with capturing('ch05_sweep'):
# [start:sweep]
sweep = supertarget(targets, np.arange(1., 31.))
print(sweep)
print('T_min_app Q_hot Q_cold area units installed capital operating TAC')
print('[K] [kJ/hr] [kJ/hr] [m2] [USD] [USD/yr] [USD/yr] [USD/yr]')
optimum = sweep.optimum
after = sweep.records[sweep.records.index(optimum) + 1] # the next point evaluated
for r in sweep.records:
if r['T_min_app'] in (1., 2., 5., 10., 15., 20., 25., 30.) or r is optimum or r is after:
print(f"{r['T_min_app']:<9.4g} {r['Q_hot']:<9.4g} {r['Q_cold']:<9.4g} "
f"{r['area']:<6.0f} {r['N_units']:<5d} {r['installed_cost']:<9.4g} "
f"{r['annualized_capital_cost']:<9.4g} {r['operating_cost']:<9.4g} {r['TAC']:.0f}")
print(f'optimum {sweep.T_min_app:.4g} K, at the bound of the sweep: {sweep.at_bound}')
fig, ax = plot_supertargets(sweep)
# [end:sweep]
save(fig, 'tutorial_05_supertargets.png')
plt.close(fig)
with capturing('ch05_trade_off'):
# [start:trade_off]
import thermosteam as tmo
from hensmith import PinchTargets
fluid = tmo.Chemical('Fluid', search_db=False, phase='l', MW=1.,
Cn=3.6, default=True) # 1000 kmol/hr: 1 kW/K
bst.settings.set_thermo([fluid])
bst.main_flowsheet.set_flowsheet('trade_off')
H1 = bst.HXutility('H1', ins=bst.Stream('H1_in', Fluid=1e5, T=400.),
T=320., rigorous=False) # 100 kW/K, 400 -> 320 K
C1 = bst.HXutility('C1', ins=bst.Stream('C1_in', Fluid=1e5, T=310.),
T=390., rigorous=False) # 100 kW/K, 310 -> 390 K
H1.simulate(); C1.simulate()
pair = PinchTargets.from_heat_utilities([H1.heat_utilities[0], C1.heat_utilities[0]])
water = bst.HeatUtility.get_heating_agent('low_pressure_steam').thermo
steam = bst.UtilityAgent('steam_450K', Water=1, T=450., P=1e6, phase='g',
heat_transfer_price=4e-7, thermo=water)
refrigerant = bst.UtilityAgent('water_280K', Water=1, T=280., P=1e3, phase='l',
heat_transfer_price=2e-7, thermo=water)
pair_sweep = supertarget(pair, np.arange(11., 61.), heating_agents=[steam],
cooling_agents=[refrigerant])
print(pair_sweep)
for key in ('Q_hot', 'area', 'N_units', 'installed_cost', 'annualized_capital_cost',
'operating_cost', 'TAC'):
print(f'{key:<24} {pair_sweep.optimum[key]:.6g}')
fig, ax = plot_supertargets(pair_sweep)
# [end:trade_off]
save(fig, 'tutorial_05_trade_off.png')
plt.close(fig)
with capturing('ch05_report'):
# [start:report]
report = network_report(HXN)
target = report['targets'] # targets.summary() with the same options
print(' network target')
print(f"utility cost [USD/hr] {report['utility_cost']:<10.2f} {target['utility_cost']:.2f}")
print(f"units {report['N_units']:<10d} {target['N_units']}")
print(f"area [m2] {report['area']:<10.0f} {target['area']:.0f}")
print(f"area, biosteam [m2] {report['area_biosteam']:.0f}")
print(f"installed cost [USD] {report['installed_cost']:<10.4g} {target['installed_cost']:.4g}")
print(f"TAC [USD/yr] {report['TAC']:<10.0f} {target['TAC']:.0f}")
print('exchanger area biosteam [m2]')
for ID, (area, area_biosteam) in report['exchanger_areas'].items():
print(f'{ID:<11} {area:<5.0f} {area_biosteam:.0f}')
# [end:report]
# plumbing checks: the library's curves are chapter 2's
from examples.ch02_pinch_analysis import composite_curves, grand_composite
ours = targets.composite_curves()
theirs = composite_curves(targets.table, T_min_app=5.)
for (T, H), (T2, H2) in zip((ours[:2], ours[2:]), (theirs[:2], theirs[2:])):
(T, H), (T2, H2) = knots(T, H), knots(T2, H2)
assert T.size == T2.size, (T.size, T2.size)
assert np.allclose(T, T2, rtol=0, atol=1e-6) and np.allclose(H, H2, rtol=1e-9, atol=1e-3)
T, H = targets.grand_composite_curve()
H2, T2 = grand_composite(targets.table)
assert np.array_equal(T, T2) and np.array_equal(H, H2)
assert targets.Q_hot == info['Q_hot_target'] and targets.Q_cold == info['Q_cold_target']
assert report['Q_hot'] >= targets.Q_hot * (1 - 1e-9) and report['status'] == 'mer'
assert abs(report['utility_cost'] - target['utility_cost']) < 1e-6 * target['utility_cost']
assert abs(pair_sweep.T_min_app - 21.595) <= 0.02 and not pair_sweep.at_bound


if __name__ == '__main__':
main()
17 changes: 14 additions & 3 deletions docs/source/API/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ API Reference

.. currentmodule:: hensmith

hensmith exports six names. :class:`HeatExchangerNetwork` is the BioSTEAM
facility most users need; the functions and classes of
hensmith exports thirteen names. :class:`HeatExchangerNetwork` is the
BioSTEAM facility most users need; the functions and classes of
``hensmith.hxn_synthesis`` are the pinch analysis and synthesis machinery
behind it, usable on their own.
behind it, usable on their own; and those of ``hensmith.targeting`` target
utilities, area, units, capital and total annualized cost, find the
``T_min_app`` of the least targeted total annualized cost, and compare a
network with its targets.

.. autosummary::

Expand All @@ -16,12 +19,20 @@ behind it, usable on their own.
synthesize_network
StreamLifeCycle
plot_pinch_diagram
PinchTargets
supertarget
Supertargets
network_report
plot_composite_curves
plot_grand_composite_curve
plot_supertargets

.. toctree::
:maxdepth: 2

heat_exchanger_network
hxn_synthesis
targeting

.. note::

Expand Down
Loading
Loading