# -*- coding: utf-8 -*-
# BioSTEAM: The Biorefinery Simulation and Techno-Economic Analysis Modules
# Copyright (C) 2020-2023, Yoel Cortes-Pena <yoelcortes@gmail.com>
#
# This module is under the UIUC open-source license. See
# github.com/BioSTEAMDevelopmentGroup/biosteam/blob/master/LICENSE.txt
# for license details.
"""
Design and cost algorithms from ordinary vessels.
References
----------
.. [1] Apostolakou, A. A., Kookos, I. K., Marazioti, C., Angelopoulos, K. C.
(2009). Techno-economic analysis of a biodiesel production process from
vegetable oils. Fuel Processing Technology, 90(7–8), 1023–1031.
https://doi.org/10.1016/j.fuproc.2009.04.017
.. [2] 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.
"""
import biosteam as bst
from math import ceil
from warnings import warn
from thermosteam.units_of_measure import AbsoluteUnitsOfMeasure
from ...utils import ExponentialFunctor
__all__ = ('TankPurchaseCostAlgorithm',
'field_erected_tank_purchase_cost',
'compute_number_of_tanks_and_purchase_cost',
'storage_tank_purchase_cost_algorithms',
'mix_tank_purchase_cost_algorithms')
[docs]
class TankPurchaseCostAlgorithm:
r"""
Create a TankPurchaseCostAlgorithm for vessel costing.
Parameters
----------
f_Cp : function
Should return the purchase cost given the volume.
V_min : float
Minimum volume at which cost is considered accurate.
V_max : float
Maximum volume of a vessel.
V_units : str
Units of measure for volume.
Attributes
----------
f_Cp : function
Returns the purchase cost given the volume.
V_min : float
Minimum volume at which cost is considered accurate.
V_max : float
Maximum volume of a vessel.
V_units : AbsoluteUnitsOfMeasure
Units of measure for volume.
Examples
--------
Find the number of mixing tanks and the total purchase cost
at a volume of 1 m^3 using the purchase cost equation from [1]_:
>>> from biosteam.units.design_tools import TankPurchaseCostAlgorithm
>>> TankPurchaseCostAlgorithm(lambda V: 12080 * V **0.525,
... V_min=0.1, V_max=30, V_units='m^3',
... CE=525.4, material='Stainless steel')
TankPurchaseCostAlgorithm(f_Cp=<lambda>, V_min=0.1, V_max=30, CE=525.4, material=Stainless steel, V_units=m^3)
"""
__slots__ = ('f_Cp', 'V_min', 'V_max',
'CE', 'material', 'V_units')
def __init__(self, f_Cp, V_min, V_max, V_units, CE, material):
self.f_Cp = f_Cp
self.V_min = V_min
self.V_max = V_max
self.V_units = AbsoluteUnitsOfMeasure(V_units)
self.CE = CE
self.material = material
def __repr__(self):
f_name = getattr(self.f_Cp, '__name__', str(self.f_Cp))
return f"{type(self).__name__}(f_Cp={f_name}, V_min={self.V_min}, V_max={self.V_max}, CE={self.CE}, material={self.material}, V_units={self.V_units})"
[docs]
def compute_number_of_tanks_and_purchase_cost(total_volume,
purchase_cost_algorithm):
"""
Return number of tanks and purchase cost of a single tank.
Parameters
----------
total_volume : float
Total volume required [m^3].
purchase_cost_algorithm : TankPurchaseCostAlgorithm
All costing options.
"""
V_total = total_volume
V_units = purchase_cost_algorithm.V_units
V_total /= V_units.conversion_factor('m^3')
V_min = purchase_cost_algorithm.V_min
if V_total < V_min:
warn(f"volume ({V_total:.5g} {V_units}) is below "
f"the lower bound ({V_min:.5g} {V_units}) for purchase "
"cost estimation", bst.exceptions.CostWarning)
N = ceil(V_total / purchase_cost_algorithm.V_max)
if N:
V = V_total / N
F_CE = bst.CE / purchase_cost_algorithm.CE
Cp = F_CE * purchase_cost_algorithm.f_Cp(V)
else:
Cp = 0.
return N, Cp
[docs]
def field_erected_tank_purchase_cost(V):
r"""
Return the purchase cost [USD] of a single, field-erected vessel assuming
stainless steel construction material.
Parameters
----------
V : float
Volume of tank [m^3].
Returns
-------
Cp : float
Purchase cost [USD].
Notes
-----
The purchase cost is given by [1]_.
If :math:`V < 2 \cdot 10^3`:
:math:`C_p^{2007} = 32500.0 + 79.35 V`
Otherwise:
:math:`C_p^{2007} = 125000.0 + 47.1 V`
Examples
--------
>>> field_erected_tank_purchase_cost(300)
112610.0
"""
if V < 2e3:
Cp = 65000.0 + 158.7 * V
else:
Cp = 250000.0 + 94.2 * V
return Cp
#: Cost algorithms for storage tank vessel types as in [1]_ [2]_.
storage_tank_purchase_cost_algorithms = {
"Field erected": TankPurchaseCostAlgorithm(
field_erected_tank_purchase_cost,
V_min=0, V_max=50e3, V_units='m^3',
CE=525.4, material='Stainless steel'),
"Floating roof": TankPurchaseCostAlgorithm(
ExponentialFunctor(A=475, n=0.507),
V_min=3e4, V_max=1e6, V_units='gal',
CE=567, material='Carbon steel'),
"Cone roof": TankPurchaseCostAlgorithm(
ExponentialFunctor(A=265, n=0.513),
V_min=1e4, V_max=1e6, V_units='gal',
CE=567, material='Carbon steel'),
"Spherical; 0-30 psig": TankPurchaseCostAlgorithm(
ExponentialFunctor(68, 0.72 ),
V_min=1e4, V_max=1e6, V_units='gal',
CE=567, material='Carbon steel'),
"Spherical; 30–200 psig": TankPurchaseCostAlgorithm(
ExponentialFunctor(53, 0.78),
V_min=1e4, V_max=7.5e5, V_units='gal',
CE=567, material='Carbon steel'),
"Gas holder": TankPurchaseCostAlgorithm(
ExponentialFunctor(3595, 0.43),
V_min=4e3, V_max=4e5, V_units='ft^3',
CE=567, material='Carbon steel')
}
#: Cost algorithms for mix tank vessel types as in [2]_.
mix_tank_purchase_cost_algorithms = {
"Conventional": TankPurchaseCostAlgorithm(
ExponentialFunctor(A=12080, n=0.525),
V_min=0.1, V_max=30, V_units='m^3',
CE=525.4, material='Stainless steel')
}