diff --git a/biosteam/_preferences.py b/biosteam/_preferences.py index 055e8317..8fe3d424 100644 --- a/biosteam/_preferences.py +++ b/biosteam/_preferences.py @@ -54,7 +54,7 @@ class DisplayPreferences: 'label_color', 'label_color', 'depth_colors', 'stream_width', 'unit_color', 'unit_label_color', 'unit_periphery_color', 'fill_cluster', 'graphviz_format', 'tooltips_full_results', - 'graphviz_html_height') + 'graphviz_html_height', 'show_all_streams') def __init__(self): #: Whether to label the ID of streams with sources and sinks in process @@ -118,6 +118,9 @@ def __init__(self): 'unit': ('225px', '400px'), } + #: Whether to show all streams, including empty feeds and products. + self.show_all_streams = True + def temporary(self): """Return a TemporaryPreferences object that will revert back to original preferences after context management.""" @@ -236,7 +239,7 @@ def dark_mode(self, stream='#98a2ad', label='#e5e5e5', bg='transparent', unit_periphery_color, fill_cluster, save) def light_mode(self, stream='#4e4e4e', label='#4e4e4e', bg='#ffffffff', - cluster=['#7ac0832f', '#ffffff9f'], unit_color='white:#CDCDCD', + cluster=['#d5edf02f', '#ffffffdf'], unit_color='white:#CDCDCD', unit_label_color='black', unit_periphery_color='#4e4e4e', fill_cluster=True, save=False): """Set diagram display colors to light mode.""" diff --git a/biosteam/_system.py b/biosteam/_system.py index f373bfa7..d1bb4667 100644 --- a/biosteam/_system.py +++ b/biosteam/_system.py @@ -3023,7 +3023,7 @@ def results(self, with_units=True): return series # Report summary - def save_report(self, file: Optional[str]='report.xlsx', dpi: Optional[str]='300', **stream_properties): + def save_report(self, file: Optional[str]='report.xlsx', dpi: Optional[str]='900', **stream_properties): """ Save a system report as an xlsx file. diff --git a/biosteam/_unit.py b/biosteam/_unit.py index f7fe2af7..1820425f 100644 --- a/biosteam/_unit.py +++ b/biosteam/_unit.py @@ -336,7 +336,7 @@ def __init_subclass__(cls, "must implement a '_run' method unless the " "'isabstract' keyword argument is True" ) - if '__init__' in dct: + if '__init__' in dct or '_init' in dct: init = dct['__init__'] annotations = init.__annotations__ for i in ('ins', 'outs'): diff --git a/biosteam/digraph/digraph.py b/biosteam/digraph/digraph.py index 825fb5a9..3b29a262 100644 --- a/biosteam/digraph/digraph.py +++ b/biosteam/digraph/digraph.py @@ -267,7 +267,7 @@ def update_digraph_from_path(f, path, recycle, depth, unit_names, streams = [i for i in all_streams if (not i.sink or i.sink in units) and (not i.source or i.source in units)] other_streams.update(all_streams.difference(streams)) connections = get_all_connections(recycles, excluded_connections) - add_connections(f, connections, unit_names, color='#f98f60', fontcolor='#f98f60') + add_connections(f, connections, unit_names, color='#f1777f', fontcolor='#f1777f') connections = get_all_connections(streams, excluded_connections) add_connections(f, connections, unit_names) depth += 1 @@ -395,6 +395,7 @@ def add_connection(f: Digraph, connection, unit_names, pen_width=None, **edge_op # Make stream nodes / unit-stream edges / unit-unit edges if has_sink and not has_source: # Feed stream case + if not preferences.show_all_streams and stream.isempty(): return f.node(ref, width='0.15', height='0.15', @@ -408,6 +409,7 @@ def add_connection(f: Digraph, connection, unit_names, pen_width=None, **edge_op f.edge(ref, unit_names[sink], labeltooltip=tooltip) elif has_source and not has_sink: # Product stream case + if not preferences.show_all_streams and stream.isempty(): return f.node(ref, width='0.15', height='0.2', @@ -428,8 +430,6 @@ def add_connection(f: Digraph, connection, unit_names, pen_width=None, **edge_op **inlet_options, penwidth=penwidth, **outlet_options) label = ID if preferences.label_streams else '' f.edge(unit_names[source], unit_names[sink], label=label, labeltooltip=tooltip) - else: - f.node(ID) elif has_sink and has_source: # Missing process stream case inlet_options = sink._graphics.get_inlet_options(sink, sink_index) diff --git a/biosteam/facilities/_boiler_turbogenerator.py b/biosteam/facilities/_boiler_turbogenerator.py index cb939910..313fb9ef 100644 --- a/biosteam/facilities/_boiler_turbogenerator.py +++ b/biosteam/facilities/_boiler_turbogenerator.py @@ -37,25 +37,16 @@ class BoilerTurbogenerator(bst.Facility): Parameters ---------- ins : - [0] Liquid/solid feed that will be burned. - - [1] Gas feed that will be burned. - - [2] Make-up water. - - [3] Natural gas to satisfy steam and power requirement. - - [4] Lime for flue gas desulfurization. - - [5] Boiler chemicals. - + * [0] Liquid/solid feed that will be burned. + * [1] Gas feed that will be burned. + * [2] Make-up water. + * [3] Natural gas to satisfy steam and power requirement. + * [4] Lime for flue gas desulfurization. + * [5] Boiler chemicals. outs : - [0] Total emissions produced. - - [1] Blowdown water. - - [2] Ash disposal. - + * [0] Total emissions produced. + * [1] Blowdown water. + * [2] Ash disposal. boiler_efficiency : float, optional Fraction of heat transferred to steam. Defaults to 0.8. turbo_generator_efficiency : float, optional @@ -74,13 +65,12 @@ class BoilerTurbogenerator(bst.Facility): Whether to purchase natural gas to satisfy system electricity demand if there is not enough heat from process feeds (i.e., inlets 0 and 1). If True, natural gas is purchased to satisfy system heat and electricity demand - (even if there is not enough heat from the feed wastes and gas); - if False, natural gas is only purchased to satisfy system heat demand - (i.e., electricity will be purchased from the grid if there is not - enough heat from the feeds). + when there is not enough heat from the feed and gas. + If False, natural gas is only purchased to satisfy system heat demand + and electricity will be purchased from the grid if there is not + enough heat from the feeds. In either case, if there is excess heat from the process feeds, - electricity will still be produced - (i.e., this argument only affects the calculation of natural gas flow). + electricity will still be produced. boiler_efficiency_basis : str, optional Basis of boiler efficiency. Defaults to 'LHV' (i.e., lower heating value). 'HHV' (i.e., higher heating value) is also a valid basis. diff --git a/biosteam/units/distillation.py b/biosteam/units/distillation.py index e83174ad..c722e57e 100644 --- a/biosteam/units/distillation.py +++ b/biosteam/units/distillation.py @@ -12,7 +12,7 @@ .. autoclass:: biosteam.units.distillation.BinaryDistillation .. autoclass:: biosteam.units.distillation.ShortcutColumn .. autoclass:: biosteam.units.distillation.MESHDistillation -.. autocalss:: biosteam.units.distillation.AdiabaticMultiStageVLEColumn +.. autoclass:: biosteam.units.distillation.AdiabaticMultiStageVLEColumn References ---------- @@ -2158,26 +2158,6 @@ class MESHDistillation(MultiStageEquilibrium, new_graphics=False): Create a distillation column that rigorously converges MESH (Mass, Equilibrium, Summation, and Enthalpy) equations. - The convergence algorithm decouples the equilibrium relationships, - mass balances, and energy balances using a custom version of the Wang-Henke - bubble point method. This algorithm is authored by Yoel Cortes-Pena, but is - not yet peer reviewed. The main difference is that the tridiagonal matrix of - mass balances across stages is used to solve for flow rates instead of mass - fractions and an internal loop is added to converge phase fractions based - on the energy balance. - - The initialization algorithm first converges a "collapsed" column without - adiabatic stages which have no feeds or side draws. This collapsed column - is initialized by solving for liquid and vapor flow rates assuming no phase - change across adiabatic stages and unity partition coefficients at - reboilers/condensers (in which case the stripping factor is equal to the - boil-up ratio). - - The Murphree efficiency (i.e. stage efficiency) is based on the - modified O'Connell correlation [2]_. The diameter is based on tray - separation and flooding velocity [1]_ [3]_. Purchase costs are based on - correlations compiled by Warren et. al. [4]_. - Parameters ---------- ins : @@ -2235,8 +2215,9 @@ class MESHDistillation(MultiStageEquilibrium, new_graphics=False): Examples -------- - # Simulate distillation column with 5 stages, a 0.673 reflux ratio, - # 2.57 boilup ratio, and feed at stage 2: + Simulate distillation column with 5 stages, a 0.673 reflux ratio, + 2.57 boilup ratio, and feed at stage 2: + >>> import biosteam as bst >>> bst.settings.set_thermo(['Water', 'Ethanol'], cache=True) >>> feed = bst.Stream('feed', Ethanol=80, Water=100, T=80.215 + 273.15) @@ -2280,6 +2261,28 @@ class MESHDistillation(MultiStageEquilibrium, new_graphics=False): Total purchase cost USD 1.24e+05 Utility cost USD/hr 48.1 + Notes + ----- + The convergence algorithm decouples the equilibrium relationships, + mass balances, and energy balances using a custom version of the Wang-Henke + bubble point method. This algorithm is authored by Yoel Cortes-Pena, but is + not yet peer reviewed. The main difference is that the tridiagonal matrix of + mass balances across stages is used to solve for flow rates instead of mass + fractions and an internal loop is added to converge phase fractions based + on the energy balance. + + The initialization algorithm first converges a "collapsed" column without + adiabatic stages which have no feeds or side draws. This collapsed column + is initialized by solving for liquid and vapor flow rates assuming no phase + change across adiabatic stages and unity partition coefficients at + reboilers/condensers (in which case the stripping factor is equal to the + boil-up ratio). + + The Murphree efficiency (i.e. stage efficiency) is based on the + modified O'Connell correlation [2]_. The diameter is based on tray + separation and flooding velocity [1]_ [3]_. Purchase costs are based on + correlations compiled by Warren et. al. [4]_. + """ auxiliary_unit_names = ( diff --git a/biosteam/units/splitting.py b/biosteam/units/splitting.py index a3df6991..512e2bbc 100644 --- a/biosteam/units/splitting.py +++ b/biosteam/units/splitting.py @@ -10,7 +10,6 @@ .. contents:: :local: -.. autoclass:: biosteam.units.splitting.Splitter .. autoclass:: biosteam.units.splitting.Splitter .. autoclass:: biosteam.units.splitting.PhaseSplitter .. autoclass:: biosteam.units.splitting.MockSplitter diff --git a/biosteam/utils/piping.py b/biosteam/utils/piping.py index 1d1a5304..2391b83b 100644 --- a/biosteam/utils/piping.py +++ b/biosteam/utils/piping.py @@ -834,7 +834,9 @@ def superposition(parent, port): @superposition(Stream, 'sink') -class SuperpositionInlet(Stream): # Both parent and auxiliary unit inlet. +class SuperpositionInlet(Stream): + """Create a SuperpositionInlet that references an inlet from another + unit operation.""" __slots__ = () def __init__(self, port, sink=None): @@ -843,7 +845,9 @@ def __init__(self, port, sink=None): @superposition(Stream, 'source') -class SuperpositionOutlet(Stream): # Both parent and auxiliary unit outlet. +class SuperpositionOutlet(Stream): + """Create a SuperpositionOutlet that references an outlet from another + unit operation.""" __slots__ = () def __init__(self, port, source=None): diff --git a/biosteam/wastewater/high_rate/polishing_filter.py b/biosteam/wastewater/high_rate/polishing_filter.py index e46e1b6a..0b9027d2 100644 --- a/biosteam/wastewater/high_rate/polishing_filter.py +++ b/biosteam/wastewater/high_rate/polishing_filter.py @@ -55,8 +55,8 @@ class PolishingFilter(bst.Unit): HLR : float Hydraulic loading rate of influent, [m3/m2/hr]. X_decomp : float - Fraction of the influent COD converted to biogas (`filter_type`=="anaerobic") - or CO2 (`filter_type`=="aerobic"). + Fraction of the influent COD converted to biogas (`filter_type` == "anaerobic") + or CO2 (`filter_type` == "aerobic"). X_growth : float Fraction of the influent COD converted to biomass growth. split : dict