Skip to content

Commit

Permalink
more robust systems
Browse files Browse the repository at this point in the history
  • Loading branch information
yoelcortes committed Sep 17, 2024
1 parent f80a8c3 commit a8376f2
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 66 deletions.
14 changes: 8 additions & 6 deletions biosteam/_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -456,14 +456,15 @@ def find_blowdown_recycle(facilities):
if isa(i, bst.BlowdownMixer): return i.outs[0]

def find_recycles(path):
all_units = set(path)
past_outlets = set()
recycles = []
recycles = set()
for i in path:
for s in i.ins:
if s in past_outlets or s.isfeed(): continue
recycles.append(s)
if s in past_outlets or s.source not in all_units: continue
recycles.add(s)
past_outlets.update(i.outs)
return recycles
return list(recycles)

# %% LCA

Expand Down Expand Up @@ -1676,7 +1677,7 @@ def flatten(self):
break
if stop: break
self._path = tuple(path)
self._recycle = find_recycles(self._path)
self._recycle = find_recycles(path)

def to_unit_group(self, name: Optional[str]=None):
"""Return a UnitGroup object of all units within the system."""
Expand Down Expand Up @@ -3309,7 +3310,8 @@ def _to_network(self):
path = [(i._to_network() if isa(i, System) else i) for i in self._path]
network = Network.__new__(Network)
network.path = path
network.recycle = self._recycle
recycle = self._recycle
network.recycle = set(recycle) if isinstance(recycle, list) else recycle
network.units = set(self.unit_path)
return network

Expand Down
5 changes: 3 additions & 2 deletions biosteam/_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -881,10 +881,11 @@ def _check_run(self):
self.baseline_purchase_costs,
self.purchase_costs,
self.installed_costs]):
raise UnitInheritanceError(
warn(
f'`{type(self).__name__}._run` method added unit results '
'(e.g., purchase costs, heat and power utilities); unit results '
'should only be added in `_design` or `_cost` methods'
'should only be added in `_design` or `_cost` methods',
RuntimeWarning
)

def materialize_connections(self):
Expand Down
14 changes: 8 additions & 6 deletions biosteam/evaluation/_feature.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,7 @@ def describe(self, number_format='.3g', distribution=True, bounds=True) -> str:
name = self.name
if self.element:
name = self.element_name + ' - ' + name
if self.units:
units = (' [' + str(self.units) + ']')
else:
units = ''
description = name + units
description = name
if distribution:
if getattr(self, 'distribution', None):
dist_name = type(self.distribution).__name__
Expand All @@ -119,11 +115,17 @@ def describe(self, number_format='.3g', distribution=True, bounds=True) -> str:
lb, ub = bounds
values = ', '.join([format(i, number_format)
for i in (lb, baseline, ub)])
description += f' ({values})'
if self.units:
description += f' ({values} {str(self.units)})'
else:
description += f' ({values})'
if description:
first_letter = description[0]
if first_letter.islower():
description = first_letter.upper() + description[1:]
if not bounds and self.units:
units = (' [' + str(self.units) + ']')
description += units
return description


Expand Down
4 changes: 2 additions & 2 deletions biosteam/evaluation/_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -713,11 +713,11 @@ def single_point_sensitivity(self,
relative_error = error / np.maximum.reduce([np.abs(baseline_1[index]), np.abs(baseline_2[index])])
for i, idx in enumerate(index):
if relative_error[i] > etol:
raise RuntimeError(
print(RuntimeError(
f"inconsistent model; {metrics[idx]} has a value of "
f"{baseline_1[idx]} before evaluating sensitivity and "
f"{baseline_2[idx]} after"
)
))
baseline = 0.5 * (baseline_1 + baseline_2)
if array:
return baseline, values_lb, values_ub
Expand Down
2 changes: 1 addition & 1 deletion biosteam/facilities/hxn/_heat_exchanger_network.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ def _cost(self):
unit = i.unit
if s_out: unit.ins[i.index] = s_out
s_out = unit.outs[i.index]
self.HXN_sys = sys = bst.System.from_units(None, all_units)
self.HXN_sys = sys = bst.System(ID=None, path=all_units)
sys.set_tolerance(method='fixedpoint', subsystems=True)

original_purchase_costs = [hx.purchase_cost for hx in hxs]
Expand Down
74 changes: 26 additions & 48 deletions tests/test_autogenerated_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -395,12 +395,10 @@ def test_two_recycle_loops_with_complete_overlap():
P3,
Network(
[M1,
Network(
[M2,
S2],
recycle=inner_recycle),
M2,
S2,
S1],
recycle=recycle)])
recycle={recycle, inner_recycle})])
assert network == actual_network
recycle_loop_sys.simulate()
x_nested_solution = np.vstack([recycle.mol, inner_recycle.mol])
Expand Down Expand Up @@ -438,31 +436,16 @@ def test_two_recycle_loops_with_partial_overlap():
P3,
Network(
[M1,
Network(
[M2,
S2,
S3],
recycle=inner_recycle),
S1],
recycle=recycle)])
actual_network_alternative = Network(
[P1,
P2,
P3,
Network(
[Network(
[M1,
M2,
S2,
S1],
recycle=S1-1),
M2,
S2,
S1,
S3],
recycle=S3-1)])
assert network == actual_network or network == actual_network_alternative
recycle={recycle, inner_recycle})])
assert network == actual_network
recycle_loop_sys.simulate()
x_nested_solution = np.vstack([recycle.mol, inner_recycle.mol])
recycle_loop_sys.flatten()
assert recycle_loop_sys.path == (P1, P2, P3, M1, M2, S2, S3, S1)
assert recycle_loop_sys.path == (P1, P2, P3, M1, M2, S2, S1, S3)
recycle_loop_sys.empty_recycles()
recycle_loop_sys.simulate()
x_flat_solution = np.vstack([recycle.mol, inner_recycle.mol])
Expand Down Expand Up @@ -607,30 +590,25 @@ def test_nested_recycle_loops():
Network(
[M1,
P2,
Network(
[H1,
M3],
recycle=M3-0),
H1,
M3,
H1,
P4,
Network(
[M4,
M5,
Network(
[H2,
M6,
S1],
recycle=S1-0),
S2,
P8,
S3,
Network(
[M7,
S4,
H3],
recycle=H3-0)],
recycle=H3-1),
M4,
M5,
H2,
M6,
S1,
H2,
S2,
H3,
P8,
S3,
M7,
S4,
H3,
S5],
recycle=S5-1),
recycle={S5-1, S4-1}),
M8])
assert network == actual_network
x_nested_solution = np.vstack([i.mol for i in recycles])
Expand Down
2 changes: 1 addition & 1 deletion thermosteam

0 comments on commit a8376f2

Please sign in to comment.