From 0ffce107d6e4e7088f3f75d0841bdcbf97296e5b Mon Sep 17 00:00:00 2001 From: Joy Zhang Date: Thu, 26 Jan 2023 14:38:25 -0600 Subject: [PATCH 01/12] merge remote changes --- Bioindustrial-Park | 2 +- thermosteam | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Bioindustrial-Park b/Bioindustrial-Park index fcd8f5a6..3b1d3e32 160000 --- a/Bioindustrial-Park +++ b/Bioindustrial-Park @@ -1 +1 @@ -Subproject commit fcd8f5a617ed4f77c2d1b94aee0a8b77fb09d00a +Subproject commit 3b1d3e32f810501bcdc80a2c5fcb5a28a67d113c diff --git a/thermosteam b/thermosteam index 5c0c7a8c..3d4770b7 160000 --- a/thermosteam +++ b/thermosteam @@ -1 +1 @@ -Subproject commit 5c0c7a8c5c69ef9c6940bf0ef42ce14a5a4a7555 +Subproject commit 3d4770b7e2e9e5b632541bba5bcb8981e52377f1 From 11754ee7ac60f709152f0b4821f962003de4c926 Mon Sep 17 00:00:00 2001 From: Joy Zhang Date: Sun, 29 Jan 2023 11:17:32 -0600 Subject: [PATCH 02/12] Update `System.isdynamic` property --- biosteam/_system.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/biosteam/_system.py b/biosteam/_system.py index 01830cc9..e00f4b1c 100644 --- a/biosteam/_system.py +++ b/biosteam/_system.py @@ -1476,9 +1476,10 @@ def method(self, method): @property def isdynamic(self) -> bool: """Whether the system contains any dynamic Unit.""" - try: - return self._isdynamic - except: + if hasattr(self, '_isdynamic'): + if self._isdynamic is not None: + return self._isdynamic + else: isdynamic = False for i in self.units: if i._isdynamic: From e253b29a144078f363986fddc077be93f319e03b Mon Sep 17 00:00:00 2001 From: Joy Zhang Date: Tue, 31 Jan 2023 11:05:27 -0600 Subject: [PATCH 03/12] update `scope` docstrings --- biosteam/utils/scope.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/biosteam/utils/scope.py b/biosteam/utils/scope.py index 41c41706..c8937414 100644 --- a/biosteam/utils/scope.py +++ b/biosteam/utils/scope.py @@ -32,7 +32,7 @@ class Scope(): See Also -------- - `pandas.MultiIndex ` + `pandas.MultiIndex `_ """ def __init__(self, subject, variables, header=None, **kwargs): @@ -59,6 +59,7 @@ def __call__(self, t): log.append(self.getter(var)) def reset_cache(self): + """Clears all recorded data.""" self._ts = [] self._record = {var:[] for var in self._record.keys()} @@ -151,12 +152,12 @@ class SystemScope(): interpolator : callable, optional An interpolation method that takes in time-series data and returns an interpolant. Used to export the data at certain time points. - When none specified, will use `scipy.interpolate.InterpolatedUnivariateSpline` + When none specified, will use :class:`scipy.interpolate.InterpolatedUnivariateSpline` with k=1 (i.e., linear) and will raise error when trying to extrapolate. See Also -------- - `scipy.interpolate.InterpolatedUnivariateSpline ` + `scipy.interpolate.InterpolatedUnivariateSpline `_ """ def __init__(self, system, *subjects, interpolator=None, **kwargs): self.system = system @@ -178,6 +179,7 @@ def __call__(self, t): s.scope(t) def reset_cache(self): + '''Clears all recorded data.''' self._ts = [] self.sol = None for s in self.subjects: From e2605d5a77481675c524643b2a3b4bd9fa3b74d4 Mon Sep 17 00:00:00 2001 From: Joy Zhang Date: Tue, 14 Mar 2023 11:52:57 -0500 Subject: [PATCH 04/12] fix typo --- biosteam/utils/scope.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biosteam/utils/scope.py b/biosteam/utils/scope.py index 41c41706..c4715e3d 100644 --- a/biosteam/utils/scope.py +++ b/biosteam/utils/scope.py @@ -81,7 +81,7 @@ def _n_cols(self, make_header=False): if isa(data, (float, int, str)): ni = 1 else: ni = len(data) n.append(ni) - names += ['f{var}_i' for i in range(ni)] + names += [f'{var}_{i}' for i in range(ni)] return n, names else: for var in self._record.keys(): From b890b1aa5fca2b3d9d40062cf4159778711c7829 Mon Sep 17 00:00:00 2001 From: Joy Zhang Date: Tue, 2 May 2023 15:57:23 -0500 Subject: [PATCH 05/12] empirical costing for small vacuum pump --- biosteam/units/design_tools/vacuum.py | 30 +++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/biosteam/units/design_tools/vacuum.py b/biosteam/units/design_tools/vacuum.py index 4ce5933f..8efc6b74 100644 --- a/biosteam/units/design_tools/vacuum.py +++ b/biosteam/units/design_tools/vacuum.py @@ -76,10 +76,32 @@ def compute_vacuum_system_power_and_cost( F_vol_air = F_mass_air = 0 F_vol_cfm = 0.5886*F_vol + F_vol_air if F_vol_cfm < 3.01: - factor = 3.01/F_vol_cfm - F_vol_cfm = 3.01 - else: - factor = 1 + # factor = 3.01/F_vol_cfm + # F_vol_cfm = 3.01 + # https://www.amazon.com/stores/page/D93FDADF-4140-467A-92A3-751750064722?ingress=2&visitId=1d2a88aa-ecda-43a9-a273-d2917f91b76c&ref_=ast_bln + name = 'Liquid-ring pump' + grade = 'Oil seal' + if F_vol_cfm < 1.5: + base_cost = 105 * 1.08 # 2023 price + tax & shipping + work = 1/5 * 0.7457 # hp to kW + else: + base_cost = 223 * 1.08 + work = 1/3 * 0.7457 + cost = bst.CE / 708. * base_cost # use 2021 CEPCI + has_condenser = False + agent = None + steam = 0. + N = 1 + return {'Work': work, + 'Cost': N * cost, + 'Name': f"{name}, {grade.lower()}", + 'In parallel': N, + 'Condenser': has_condenser, + 'Steam flow rate': steam, + 'Heating agent': agent} + # else: + # factor = 1 + factor = 1 F_mass_kgph = (F_mass + 0.4536*F_mass_air)*factor # kg/hr F_mass_lbph = 2.205 * F_mass_kgph vacuum_systems = get_prefered_vacuum_systems(vacuum_system_preference) From ae8c24ccc3a899d9a99fa3c035b0a5c28b8862cb Mon Sep 17 00:00:00 2001 From: Yalin Li Date: Thu, 4 May 2023 21:53:55 -0500 Subject: [PATCH 06/12] try adding one dependency to fix exposan failed test --- requirements_test.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/requirements_test.txt b/requirements_test.txt index a00dec10..061c25ff 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,7 +1,8 @@ +importlib_metadata pytest-cov coveralls nbval SALib pyglet ipykernel -CoolProp +CoolProp \ No newline at end of file From 2e131f7fdf2726f94cff39e50c37b4a5f29155bb Mon Sep 17 00:00:00 2001 From: Yalin Li Date: Thu, 4 May 2023 22:31:08 -0500 Subject: [PATCH 07/12] revert changes on importlib_metadata, not sure if it is useful --- requirements_test.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/requirements_test.txt b/requirements_test.txt index 061c25ff..3d1211a7 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,4 +1,3 @@ -importlib_metadata pytest-cov coveralls nbval From d7e6a150952189656cfb5ae0bb9996578d82a827 Mon Sep 17 00:00:00 2001 From: Yalin Date: Thu, 28 Sep 2023 10:50:58 -0400 Subject: [PATCH 08/12] fix name attr for valve graphics --- biosteam/_graphics.py | 1 + 1 file changed, 1 insertion(+) diff --git a/biosteam/_graphics.py b/biosteam/_graphics.py index ce26646c..5a5d5d57 100644 --- a/biosteam/_graphics.py +++ b/biosteam/_graphics.py @@ -307,6 +307,7 @@ def tailor_valve_node(node, unit): # pragma: no coverage # TODO: Remove this fallback once fix for valve svg output in digraph.py node.clear() node.update(box_node) + node['name'] = '' node['fillcolor'] = bst.preferences.unit_color node['fontcolor'] = bst.preferences.unit_label_color node['color'] = bst.preferences.unit_periphery_color From 778a855c658f8a28c16ee309993f478dda3b1038 Mon Sep 17 00:00:00 2001 From: Joy Zhang Date: Fri, 29 Sep 2023 09:36:35 -0700 Subject: [PATCH 09/12] update costing function for new vacuum pump design --- biosteam/units/design_tools/vacuum.py | 55 +++++++++++++++------------ tests/test_vacuum.py | 31 +++++++++++++++ 2 files changed, 61 insertions(+), 25 deletions(-) create mode 100644 tests/test_vacuum.py diff --git a/biosteam/units/design_tools/vacuum.py b/biosteam/units/design_tools/vacuum.py index 8efc6b74..7e7ee58b 100644 --- a/biosteam/units/design_tools/vacuum.py +++ b/biosteam/units/design_tools/vacuum.py @@ -8,7 +8,12 @@ .. [1] Seider, W. D.; Lewin, D. R.; Seader, J. D.; Widagdo, S.; Gani, R.; Ng, M. K. Cost Accounting and Capital Cost Estimation. In Product and Process Design Principles; Wiley, 2017; pp 426–485. - +.. [2] Amazon. Robinair (15115) VacuMaster Single Stage Vacuum Pump - Single-Stage, 1.5 CFM. + https://www.amazon.com/Robinair-15115-VacuMaster-Single-Vacuum/dp/B005CO9FDW?ref_=ast_sto_dp. + Accessed on 09/28/2023. +.. [3] Amazon. Robinair (15300) VacuMaster Economy Vacuum Pump - 2-Stage, 3 CFM. + https://www.amazon.com/Robinair-15300-VacuMaster-Economy-Vacuum/dp/B000O1E5UQ?ref_=ast_sto_dp + Accessed on 09/28/2023. """ from numpy import log as ln @@ -26,6 +31,7 @@ # System types of vacuum systems # Volumetric flowrate ranges, (cfm) and lower limit of suction (torr) +# Rotary vane pumps based on ref. [2], [3] _steamjet_ejectors = { 'One stage': ((10, 1000000), 100), 'Two stage': ((10, 1000000), 15), @@ -38,11 +44,20 @@ 'Three stage rotary lobe': ((60, 240), 1.5), 'Three stage claw': ((60, 270), 0.3), 'Screw compressor': ((50, 1400), 0.1)} +_rotary_vane = { + 'One stage': ((0, 1.51), 0.115), + 'Two stage': ((1.5, 3.01), 0.035)} _default_vacuum_systems = {'Liquid-ring pump': _liquid_ring, 'Steam-jet ejector': _steamjet_ejectors, - 'Dry-vacuum pump': _dry_vacuum} - + 'Dry-vacuum pump': _dry_vacuum, + 'Rotary-vane pump': _rotary_vane} + +_default_rotary_vane_work_cost = { + 'One stage': (1/5 * 0.7457, 127*1.08), # hp to kW; 2023 USD (including tax & shipping) + 'Two stage': (1/3 * 0.7457, 248*1.08) + } + _air_density = 1.2041 # kg/m3 dry air # %% Calculate vacuum system requirements @@ -75,30 +90,9 @@ def compute_vacuum_system_power_and_cost( else: F_vol_air = F_mass_air = 0 F_vol_cfm = 0.5886*F_vol + F_vol_air - if F_vol_cfm < 3.01: + # if F_vol_cfm < 3.01: # factor = 3.01/F_vol_cfm # F_vol_cfm = 3.01 - # https://www.amazon.com/stores/page/D93FDADF-4140-467A-92A3-751750064722?ingress=2&visitId=1d2a88aa-ecda-43a9-a273-d2917f91b76c&ref_=ast_bln - name = 'Liquid-ring pump' - grade = 'Oil seal' - if F_vol_cfm < 1.5: - base_cost = 105 * 1.08 # 2023 price + tax & shipping - work = 1/5 * 0.7457 # hp to kW - else: - base_cost = 223 * 1.08 - work = 1/3 * 0.7457 - cost = bst.CE / 708. * base_cost # use 2021 CEPCI - has_condenser = False - agent = None - steam = 0. - N = 1 - return {'Work': work, - 'Cost': N * cost, - 'Name': f"{name}, {grade.lower()}", - 'In parallel': N, - 'Condenser': has_condenser, - 'Steam flow rate': steam, - 'Heating agent': agent} # else: # factor = 1 factor = 1 @@ -114,6 +108,12 @@ def compute_vacuum_system_power_and_cost( steam = 0.41631 * F_mass_kgph # [kmol/hr] 7.5 weight steam/ weight gas work = 0. has_condenser = grade != 'One stage' + elif name == 'Rotary-vane pump': + has_condenser = False + agent = None + steam = 0. + N = 1 + work = _default_rotary_vane_work_cost[grade][0] else: has_condenser = False agent = None @@ -273,5 +273,10 @@ def calculate_vacuum_cost(vacuum_sys, grade, F_mass_lbph, F_vol_cfm, P_suction): elif grade == 'Screw compressor': Cp = 10875*S**0.38 Cost = Cp + elif vacuum_sys == 'Rotary-vane pump': + Cost = _default_rotary_vane_work_cost[grade][1] / 708. * 567. # !!! 708 is the 2021 CEPCI, need to be updated to 2023 CEPCI return Cost + + + \ No newline at end of file diff --git a/tests/test_vacuum.py b/tests/test_vacuum.py new file mode 100644 index 00000000..7e010a16 --- /dev/null +++ b/tests/test_vacuum.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# BioSTEAM: The Biorefinery Simulation and Techno-Economic Analysis Modules +# Copyright (C) 2020-2023, Yoel Cortes-Pena +# +# This module is under the UIUC open-source license. See +# github.com/BioSTEAMDevelopmentGroup/biosteam/blob/master/LICENSE.txt +# for license details. +""" +""" + +import pytest +import biosteam as bst + +def test_rotary_vane_vacuum_pump(): + + bst.settings.set_thermo(['Water', 'CH4']) + gas = bst.Stream('gas', CH4=2, Water=0.1) + vac = bst.VacuumSystem(F_mass=gas.F_mass, F_vol=gas.F_vol, + P_suction=31325., vessel_volume=1.9e-3) + assert "Rotary-vane pump, one stage" in vac.baseline_purchase_costs + #!!! TODO: add test to purchase cost after updating CEPCI + + vac = bst.VacuumSystem(F_mass=gas.F_mass*10, F_vol=gas.F_vol*10, + P_suction=31325., vessel_volume=1.9e-3) + assert "Rotary-vane pump, two stage" in vac.baseline_purchase_costs + pass + +if __name__ == '__main__': + test_rotary_vane_vacuum_pump() + + From 07415d32bcf653d6a1c29a455e97ce6c81755bed Mon Sep 17 00:00:00 2001 From: Joy Zhang Date: Thu, 19 Oct 2023 17:35:13 -0700 Subject: [PATCH 10/12] updated applicable range of pump sizing --- biosteam/units/_pump.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/biosteam/units/_pump.py b/biosteam/units/_pump.py index 3f6f6141..8a6f5641 100644 --- a/biosteam/units/_pump.py +++ b/biosteam/units/_pump.py @@ -214,7 +214,8 @@ def _design(self): N = max(ceil(q_i / 1500), N) pump_type = 'Gear' elif (head_i <= 20000 - and power_i <= 200 + # and power_i <= 200 + and 1 <= power_i <= 200 and nu <= 0.01): N = max(ceil(q_i / 500), N) pump_type = 'MeteringPlunger' @@ -246,7 +247,6 @@ def _cost(self): h = Design['Head'] p = Design['Power'] I = bst.CE/567 - # TODO: Add cost equation for small pumps # Head and flow rate is too small, so make conservative estimate on cost if q < 50: q = 50 From dc7a6c5f67884df34158abcdb35d95ce94d9083c Mon Sep 17 00:00:00 2001 From: Joy Zhang Date: Tue, 13 Feb 2024 10:08:30 -0800 Subject: [PATCH 11/12] debug multiple recycle streams --- biosteam/_system.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biosteam/_system.py b/biosteam/_system.py index 07a72e73..db592014 100644 --- a/biosteam/_system.py +++ b/biosteam/_system.py @@ -1621,7 +1621,7 @@ def recycle(self, recycle): elif isa(recycle, Stream): self._recycle = recycle elif isa(recycle, abc.Iterable): - real_recycles = [i for i in recycle if isa(recycle, Stream)] + real_recycles = [i for i in recycle if isa(i, Stream)] if len(real_recycles) == 0: self.method = 'fixed-point' permanent = self.unit_set From b124a347b316ee971b8a622a42803cf639190695 Mon Sep 17 00:00:00 2001 From: Joy Zhang Date: Tue, 13 Feb 2024 13:16:28 -0800 Subject: [PATCH 12/12] merge submodule changes --- Bioindustrial-Park | 2 +- thermosteam | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Bioindustrial-Park b/Bioindustrial-Park index 387e9cbf..6ce4a98b 160000 --- a/Bioindustrial-Park +++ b/Bioindustrial-Park @@ -1 +1 @@ -Subproject commit 387e9cbf4f6eff7f65d2adcb6213043c81ff4754 +Subproject commit 6ce4a98bedda8be410e66e41658063ea893926d0 diff --git a/thermosteam b/thermosteam index d38ba6d1..8db0ad96 160000 --- a/thermosteam +++ b/thermosteam @@ -1 +1 @@ -Subproject commit d38ba6d11c32cf293440b973790fe11178026aa3 +Subproject commit 8db0ad9614c7839e065e5a7b080265b5947546d5