{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Inheriting from Unit" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Layout" ] }, { "cell_type": "raw", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ ".. figure:: Unit_UML.png\n", " :class: dark-light\n", " :align: center" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**A Unit subclass has class attributes that dictate how an instance is initialized:**\n", " \n", "* `_F_BM_default` : dict[str, float] Default bare module factors for each purchase cost item.\n", "\n", "* `_units` : [dict] Units of measure for the `design_results` items.\n", "\n", "* `_N_ins`=1 : [int] Expected number of input streams.\n", " \n", "* `_N_outs`=1 : [int] Expected number of output streams.\n", " \n", "* `_ins_size_is_fixed`=True : [bool] Whether the number of streams in ins is fixed.\n", " \n", "* `_outs_size_is_fixed`=True : [bool] Whether the number of streams in outs is fixed.\n", "\n", "* `auxiliary_unit_names`=() : tuple[str] Name of attributes that are auxiliary units.\n", "\n", "* `_graphics` : [biosteam Graphics] A Graphics object for diagram representation. Defaults to a box diagram.\n", "\n", "* `_default_equipment_lifetime` : [int] or dict[str, int] Default lifetime of equipment. Defaults to lifetime of production venture.\n", " \n", "* `line` : [str] Label for the unit operation in a diagram. Defaults to the class name.\n", "\n", "**Abstract methods are used to run heat and mass balances, find design requirements, and cost the unit:**\n", "\n", "* `_run()` : Called during System convergece to specify `outs` streams.\n", "\n", "* `_design()` : Called after System convergence to find design requirements. \n", "\n", "* `_cost()` : Called after `_design` to find cost requirements.\n", "\n", "**These abstract methods will rely on the following instance attributes:**\n", "\n", "* `ins` : Inlets[Stream] Input streams.\n", "\n", "* `outs` : Outlets[Stream] Output streams.\n", "\n", "* `power_utility` : [PowerUtility] Used to add electricity rate requirement.\n", "\n", "* `heat_utilities` : list[HeatUtility] Used to add cooling and heating requirements.\n", "\n", "* `design_results` : [dict] All design requirements.\n", "\n", "* `baseline_purchase_costs` : [dict] Itemized purchase costs (without accounting for design, pressure or material factors).\n", "\n", "* `parallel` : [dict] Name-number pairs of baseline purchase costs and auxiliary unit operations in parallel.\n", "\n", "* `F_BM`: [dict] Bare-module factors.\n", "\n", "* `F_D`: [dict] Design factors.\n", "\n", "* `F_P`: [dict] Pressure factors.\n", "\n", "* `F_M`: [dict] Material factors.\n", "\n", "* `equipment_lifetime`: [dict] Lifetime of each equiment.\n", "\n", "* `thermo` : [Thermo] The thermodynamic property package used by the unit." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Subclass example" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The following example depicts inheritance from Unit by creating a new Boiler class:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import biosteam as bst\n", "from math import ceil\n", "bst.nbtutorial()\n", "\n", "class Boiler(bst.Unit):\n", " \"\"\"\n", " Create a Boiler object that partially boils the feed.\n", " \n", " Parameters\n", " ----------\n", " ins :\n", " Inlet fluid.\n", " outs :\n", " * [0] vapor product\n", " * [1] liquid product\n", " V : float\n", " Molar vapor fraction.\n", " P : float\n", " Operating pressure [Pa].\n", " \n", " \"\"\"\n", " # Note that the documentation does not include `ID` or `thermo` in the parameters.\n", " # This is OK, and most subclasses in BioSTEAM are documented this way too.\n", " # Documentation for all unit operations should include the inlet and outlet streams\n", " # listed by index. If there is only one stream in the inlets (or outlets), there is no\n", " # need to list out by index. There is no need to specify the types for the `ins` and `outs` either;\n", " # BioSTEAM automatically adds the correct types for these when creating the documentation.\n", " # Any additional arguments to the unit should also be listed (e.g. V, and P).\n", " \n", " _N_ins = 1 # Number in inlets\n", " _N_outs = 2 # Number in outlets\n", " _units = {'Area': 'm^2'}\n", " \n", " def _init(self, V, P):\n", " # The _init methods adds input parameters for unit creation\n", " self.V = V #: Molar vapor fraction.\n", " self.P = P #: Operating pressure [Pa].\n", " \n", " def _run(self):\n", " # Equivalent to self.ins[0] when the number of inlets is one\n", " feed = self.feed \n", " vap, liq = self.outs\n", " \n", " # Perform vapor-liquid equilibrium\n", " stream = feed.copy()\n", " stream.vle(V=self.V, P=self.P)\n", " \n", " # Update outlet streams\n", " vap.copy_like(stream['g'])\n", " liq.copy_like(stream['l'])\n", " \n", " def _design(self):\n", " # Add heat utility requirement\n", " T_operation = self.outs[0].T\n", " duty = self.H_out - self.H_in\n", " if duty < 0: raise RuntimeError(f'{repr(self)} is cooling.')\n", " heat_utility = self.add_heat_utility(duty, T_operation) # New utility is also in self.heat_utilities\n", " \n", " # Temperature of utility at entrance\n", " T_utility = heat_utility.inlet_utility_stream.T\n", " \n", " # Temeperature gradient\n", " dT = T_utility - T_operation\n", " \n", " # Heat transfer coefficient kJ/(hr*m2*K)\n", " U = 8176.699 \n", " \n", " # Area requirement (m^2)\n", " A = duty /(U * dT)\n", " \n", " # Maximum area per unit\n", " A_max = 743.224\n", " \n", " # Number of units\n", " N = ceil(A / A_max)\n", " \n", " # Design requirements (excluding utilities) are stored here\n", " self.design_results['Area'] = A / N\n", " \n", " # The capital cost of all boilers will be equal to the cost of a single\n", " # boiler by the number of boilers\n", " self.parallel['Boiler'] = N\n", " \n", " def _cost(self):\n", " A = self.design_results['Area']\n", " \n", " # Long-tube vertical boiler cost correlation from \n", " # \"Product process and design\". Warren et. al. (2016) Table 22.32, pg 592\n", " purchase_cost = bst.settings.CEPCI * 3.086 * A **0.55\n", " \n", " # Itemized purchase costs are stored here\n", " self.baseline_purchase_costs['Boiler'] = purchase_cost # Not accounting for material factor\n", " \n", " # Assume design, pressure, and material factors are 1.\n", " self.F_D['Boiler'] = self.F_P['Boiler'] = self.F_M['Boiler'] = 1.\n", " \n", " # Set bare-module factor for boilers\n", " self.F_BM['Boiler'] = 2.45\n", " " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Simulation test" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "tags": [ "nbval-ignore-output" ] }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Boiler: B1\n", "ins...\n", "[0] water \n", " phase: 'l', T: 298.15 K, P: 101325 Pa\n", " flow (kmol/hr): Water 300\n", "outs...\n", "[0] gas \n", " phase: 'l', T: 298.15 K, P: 101325 Pa\n", " flow: 0\n", "[1] liq \n", " phase: 'l', T: 298.15 K, P: 101325 Pa\n", " flow: 0\n" ] } ], "source": [ "import biosteam as bst\n", "bst.settings.set_thermo(['Water'])\n", "water = bst.Stream('water', Water=300)\n", "B1 = Boiler('B1', ins=water, outs=('gas', 'liq'),\n", " V=0.5, P=101325)\n", "B1.diagram()\n", "B1.show()" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Boiler: B1\n", "ins...\n", "[0] water \n", " phase: 'l', T: 298.15 K, P: 101325 Pa\n", " flow (kmol/hr): Water 300\n", "outs...\n", "[0] gas \n", " phase: 'g', T: 373.12 K, P: 101325 Pa\n", " flow (kmol/hr): Water 150\n", "[1] liq \n", " phase: 'l', T: 373.12 K, P: 101325 Pa\n", " flow (kmol/hr): Water 150\n" ] } ], "source": [ "B1.simulate()\n", "B1.show()" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
BoilerUnitsB1
Low pressure steamDutykJ/hr8.21e+06
Flowkmol/hr212
CostUSD/hr50.4
DesignAream^224.4
Purchase costBoilerUSD1.02e+04
Total purchase costUSD1.02e+04
Utility costUSD/hr50.4
\n", "
" ], "text/plain": [ "Boiler Units B1\n", "Low pressure steam Duty kJ/hr 8.21e+06\n", " Flow kmol/hr 212\n", " Cost USD/hr 50.4\n", "Design Area m^2 24.4\n", "Purchase cost Boiler USD 1.02e+04\n", "Total purchase cost USD 1.02e+04\n", "Utility cost USD/hr 50.4" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Note that utility requirements, items in the `design_results` dictionary,\n", "# and purchase costs are automatically included in the results dataframe.\n", "B1.results()" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
BoilerUnitsB1
Low pressure steamDutykJ/hr8.21e+08
Flowkmol/hr2.12e+04
CostUSD/hr5.04e+03
DesignAream^2610
Purchase costBoiler (x4)USD2.38e+05
Total purchase costUSD2.38e+05
Utility costUSD/hr5.04e+03
\n", "
" ], "text/plain": [ "Boiler Units B1\n", "Low pressure steam Duty kJ/hr 8.21e+08\n", " Flow kmol/hr 2.12e+04\n", " Cost USD/hr 5.04e+03\n", "Design Area m^2 610\n", "Purchase cost Boiler (x4) USD 2.38e+05\n", "Total purchase cost USD 2.38e+05\n", "Utility cost USD/hr 5.04e+03" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Note that the number of boilers are automatically accounted for \n", "# through the `parallel` dictionany.\n", "B1.feed.scale(100) # Rescale flow rate x100\n", "B1.simulate()\n", "B1.results()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Graphviz attributes" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "All [graphviz](https://graphviz.readthedocs.io/en/stable/manual.html) attributes for generating a diagram are stored in `_graphics` as a Graphics object. One Graphics object is generated for each Unit subclass:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "graphics = Boiler._graphics\n", "edge_in = graphics.edge_in\n", "edge_out = graphics.edge_out\n", "node = graphics.node" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[{'headport': 'c'}]" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Attributes correspond to each inlet stream respectively\n", "# For example: Attributes for B1.ins[0] would correspond to edge_in[0]\n", "edge_in " ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[{'tailport': 'c'}, {'tailport': 'c'}]" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Attributes correspond to each outlet stream respectively\n", "# For example: Attributes for B1.outs[0] would correspond to edge_out[0]\n", "edge_out" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'shape': 'box',\n", " 'style': 'filled',\n", " 'gradientangle': '0',\n", " 'width': '0.6',\n", " 'height': '0.6',\n", " 'orientation': '0.0',\n", " 'peripheries': '1',\n", " 'margin': 'default',\n", " 'fontname': 'Arial'}" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "node # The node represents the actual unit" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "These attributes can be changed to the user's liking:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "edge_out[0]['tailport'] = 'n'\n", "edge_out[1]['tailport'] = 's'\n", "node['width'] = '1'\n", "node['height'] = '1.2'" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "tags": [ "nbval-ignore-output" ] }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "B1.diagram()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It is also possible to dynamically adjust node and edge attributes by setting the `tailor_node_to_unit` attribute:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "tags": [ "nbval-ignore-output" ] }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def tailor_node_to_unit(node, unit):\n", " if unit.feed.isempty(): node['label'] += '\\n-empty-'\n", "graphics.tailor_node_to_unit = tailor_node_to_unit\n", "B1.diagram()" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "tags": [ "nbval-ignore-output" ] }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "B1.ins[0].empty()\n", "B1.diagram()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "NOTE: The example implementation of the `tailor_node_to_unit` function is not suggested; best to keep diagrams simple." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Cost decorator" ] }, { "cell_type": "markdown", "metadata": { "raw_mimetype": "text/markdown" }, "source": [ "The cost decorator adds a free on board purchase cost based on the exponential scale up equation:\n", "\n", "$New\\ cost = N \\cdot cost \\bigg(\\frac{CE_{new}}{CE}\\bigg) \\bigg(\\frac{S_{new}}{N \\cdot S}\\bigg)^{n}$\n", "\n", "$Electricity\\ rate = kW \\bigg(\\frac{S_{new}}{S}\\bigg)$\n", "\n", "$N = ceil \\bigg( \\frac{S_{new}}{ub} \\bigg)$\n", "\n", "$N\\text{: Number of units}$\n", "\n", "$ub\\text{: Upper bound of size}$\n", "\n", "$CE_{new}\\text{: New Chemical Engineering Plant Cost Index}$\n", "\n", "$CE\\text{: Chemical Engineering Plant Cost Index}$\n", "\n", "$S_{new}\\text{: New size value}$\n", "\n", "$S\\text{: Original size value}$\n", "\n", "$cost\\text{: Free on board purchase cost at size S}$\n", "\n", "$kW\\text{: Electricity rate in kW at size S}$\n", "\n", "$n\\text{: Exponential factor}$\n", "\n", "$lifetime\\text{: Number of operating years until equipment needs to be replaced}$\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Create a Shredder Unit subclass for sugar cane with the following exponential scale up factors [[1]](#References):\n", "\n", "* Chemical Engineering Plant Cost Index: 567.3\n", "* Size: 500,000 kg/hr flow rate\n", "* Purchase cost: $2,500,000\n", "* Electricity rate: 3,000 kW\n", "* Exponential factor: 0.6\n", "* Bare module factor: 1.39\n", "* Equipment lifetime: 30\n", "\n", "Additionally, include a bare module factor of 1.39 as an approximation for this example [[2]](#References)." ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Shredder: U1\n", "ins...\n", "[0] s1 \n", " phase: 'l', T: 298.15 K, P: 101325 Pa\n", " flow (kg/hr): SugarCane 1e+06\n", "outs...\n", "[0] s2 \n", " phase: 'l', T: 298.15 K, P: 101325 Pa\n", " flow (kg/hr): SugarCane 1e+06\n" ] }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
ShredderUnitsU1
ElectricityPowerkW6e+03
CostUSD/hr469
DesignFlow ratekg/hr1e+06
Purchase costShredderUSD4.03e+06
Total purchase costUSD4.03e+06
Utility costUSD/hr469
\n", "
" ], "text/plain": [ "Shredder Units U1\n", "Electricity Power kW 6e+03\n", " Cost USD/hr 469\n", "Design Flow rate kg/hr 1e+06\n", "Purchase cost Shredder USD 4.03e+06\n", "Total purchase cost USD 4.03e+06\n", "Utility cost USD/hr 469" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import biosteam as bst\n", "from biosteam.units.decorators import cost\n", "\n", "# Set up thermo property package\n", "chemicals = bst.Chemicals(['Water', 'Ethanol'])\n", "SugarCane = bst.Chemical.blank('SugarCane', phase_ref='s')\n", "SugarCane.default()\n", "chemicals.append(SugarCane)\n", "bst.settings.set_thermo(chemicals)\n", "\n", "# For year 2018\n", "bst.CE = 603.1 \n", "\n", "# basis will be the total flow rate in kg/hr\n", "@cost('Flow rate', units='kg/hr', cost=2.5e6, CE=567.3,\n", " n=0.6, S=500e3, kW=3000, BM=1.39, lifetime=30)\n", "class Shredder(bst.Unit): pass\n", "# Units without a `_run` method assume one input and output stream\n", "# that share the same flow rates and conditions\n", "\n", "### Test a Shreadder object ###\n", "\n", "# Display flow rate in kg/hr\n", "bst.Stream.display_units.flow = 'kg/hr'\n", "\n", "feed = bst.Stream(SugarCane=1e6, units='kg/hr')\n", "shredder = Shredder(ins=feed)\n", "shredder.simulate()\n", "\n", "shredder.show()\n", "shredder.results()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Cost data is stored as CostItem objects in the `cost_items` dictionary:" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'Shredder': }" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Shredder.cost_items" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CostItem: Flow rate (kg/hr)\n", " S 5e+05\n", " CE 567\n", " cost 2.5e+06\n", " n 0.6\n", " kW 3e+03\n", "\n" ] } ], "source": [ "Shredder.cost_items['Shredder']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Bare module factors and equipment lifetimes are stored separately:" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'Shredder': 30}" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Shredder._default_equipment_lifetime" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Any option can be changed:" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
ShredderUnitsU1
ElectricityPowerkW6e+03
CostUSD/hr469
DesignFlow ratekg/hr1e+06
Purchase costShredderUSD4.83e+06
Total purchase costUSD4.83e+06
Utility costUSD/hr469
\n", "
" ], "text/plain": [ "Shredder Units U1\n", "Electricity Power kW 6e+03\n", " Cost USD/hr 469\n", "Design Flow rate kg/hr 1e+06\n", "Purchase cost Shredder USD 4.83e+06\n", "Total purchase cost USD 4.83e+06\n", "Utility cost USD/hr 469" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Shredder.cost_items['Shredder'].cost = 3e6 # Change base cost\n", "# This also works:\n", "# Shredder.cost_items['Shredder']['cost'] = 3e6\n", "shredder.simulate()\n", "shredder.results()" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
ShredderUnitsU1
ElectricityPowerkW6e+03
CostUSD/hr469
DesignFlow ratekg/hr1e+06
Purchase costShredder (x2)USD6.38e+06
Total purchase costUSD6.38e+06
Utility costUSD/hr469
\n", "
" ], "text/plain": [ "Shredder Units U1\n", "Electricity Power kW 6e+03\n", " Cost USD/hr 469\n", "Design Flow rate kg/hr 1e+06\n", "Purchase cost Shredder (x2) USD 6.38e+06\n", "Total purchase cost USD 6.38e+06\n", "Utility cost USD/hr 469" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Shredder.cost_items['Shredder'].ub = 6e5 # Change size upper bound\n", "shredder.simulate()\n", "shredder.results()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note: It is also possible to decorate a Unit subclass multiple times to add multiple cost items." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It is also possible to extend the decorated cost. In this next example we will add an agitator to a flash vessel with the following exponential scale up factors [[3]](#References):\n", "\n", "* Chemical Engineering Plant Cost Index: 522\n", "* Size: 252,891 kg/hr flow rate\n", "* Purchase cost: $90,000\n", "* Electricity rate: 170 kW\n", "* Exponential factor: 0.5\n", "* Bare module factor: 1.5\n", "* Lifetime: Number of biorefinery operating years" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "tags": [ "nbval-ignore-output" ] }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Flash with agitatorUnitsF1
ElectricityPowerkW25.2
CostUSD/hr1.97
Low pressure steamDutykJ/hr2.82e+07
Flowkmol/hr728
CostUSD/hr173
DesignVessel typeVertical
Lengthft12.5
Diameterft8.5
Weightlb8.14e+03
Wall thicknessin0.438
Flow ratekg/hr3.74e+04
Vessel materialCarbon steel
Purchase costVertical pressure vesselUSD4.2e+04
Platform and laddersUSD1.19e+04
AgitatorUSD4e+04
Heat exchanger - Floating headUSD3.65e+04
Total purchase costUSD1.3e+05
Utility costUSD/hr175
\n", "
" ], "text/plain": [ "Flash with agitator Units F1\n", "Electricity Power kW 25.2\n", " Cost USD/hr 1.97\n", "Low pressure steam Duty kJ/hr 2.82e+07\n", " Flow kmol/hr 728\n", " Cost USD/hr 173\n", "Design Vessel type Vertical\n", " Length ft 12.5\n", " Diameter ft 8.5\n", " Weight lb 8.14e+03\n", " Wall thickness in 0.438\n", " Flow rate kg/hr 3.74e+04\n", " Vessel material Carbon steel\n", "Purchase cost Vertical pressure vessel USD 4.2e+04\n", " Platform and ladders USD 1.19e+04\n", " Agitator USD 4e+04\n", " Heat exchanger - Floating head USD 3.65e+04\n", "Total purchase cost USD 1.3e+05\n", "Utility cost USD/hr 175" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "@cost('Flow rate', 'Agitator', units='kg/hr',\n", " cost=90e3, S=252891, kW=170, CE=522, n=0.5, BM=1.5)\n", "class FlashWithAgitator(bst.Flash):\n", " \n", " def _design(self):\n", " super()._design()\n", " self._decorated_design()\n", " \n", " def _cost(self):\n", " # Run flash cost algorithm\n", " super()._cost()\n", " \n", " # Run decorated cost algorithm\n", " self._decorated_cost()\n", " \n", "# Test\n", "F1 = FlashWithAgitator('F1', bst.Stream('feed', Water=800, Ethanol=500, T=350),\n", " V=0.5, P=101325)\n", "F1.simulate()\n", "F1.results()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Auxiliary units" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A unit operation may be composed of several auxiliary unit operations. To implement auxiliary units, define their names in `auxiliary_unit_names` and instantiate them using the `auxiliary` method. In the following example, we create a new unit class composed of a mix tank, a pump, and a heat exchanger:" ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "tags": [ "nbval-ignore-output" ] }, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "HT1\n", "Mix tank\n", "Auxiliary:c->149739870487:w\n", "\n", "\n", " s5\n", "\n", "\n", "\n", "\n", "\n", "HT1\n", "Pump\n", "Auxiliary:c->HT1\n", "Heat exchanger\n", "Auxiliary:c\n", "\n", "\n", "\n", "\n", "\n", "HT1\n", "Heat exchanger\n", "Auxiliary:c->HT1\n", "Mix tank\n", "Auxiliary:c\n", "\n", "\n", "\n", "\n", "\n", "149739871180:e->HT1\n", "Pump\n", "Auxiliary:c\n", "\n", "\n", " feed\n", "\n", "\n", "\n", "\n", "\n", "HT1\n", "Mix tank\n", "Auxiliary\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "HT1\n", "Mix tank\n", "Auxiliary\n", "\n", "\n", "\n", "\n", "\n", "HT1\n", "Pump\n", "Auxiliary\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "HT1\n", "Pump\n", "Auxiliary\n", "\n", "\n", "\n", "\n", "\n", "HT1\n", "Heat exchanger\n", "Auxiliary\n", "\n", "\n", "HT1\n", "Heat exchanger\n", "Auxiliary\n", "\n", "\n", "\n", "\n", "\n", "149739870487\n", "\n", "\n", "\n", "\n", "149739871180\n", "\n", "\n", "\n", "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "HeatedTank: HT1\n", "ins...\n", "[0] feed \n", " phase: 'l', T: 298.15 K, P: 101325 Pa\n", " flow (kg/hr): Water 3.6e+03\n", "outs...\n", "[0] s5 \n", " phase: 'l', T: 310 K, P: 101325 Pa\n", " flow (kg/hr): Water 3.6e+03\n" ] }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Heated tankUnitsHT1
ElectricityPowerkW0.736
CostUSD/hr0.0575
Low pressure steamDutykJ/hr1.88e+05
Flowkmol/hr4.86
CostUSD/hr1.15
Purchase costMix tank - TankUSD3.07e+04
Pump - PumpUSD4.64e+03
Pump - MotorUSD273
Heat exchanger - Double pipeUSD3.84e+03
Total purchase costUSD3.94e+04
Utility costUSD/hr1.21
\n", "
" ], "text/plain": [ "Heated tank Units HT1\n", "Electricity Power kW 0.736\n", " Cost USD/hr 0.0575\n", "Low pressure steam Duty kJ/hr 1.88e+05\n", " Flow kmol/hr 4.86\n", " Cost USD/hr 1.15\n", "Purchase cost Mix tank - Tank USD 3.07e+04\n", " Pump - Pump USD 4.64e+03\n", " Pump - Motor USD 273\n", " Heat exchanger - Double pipe USD 3.84e+03\n", "Total purchase cost USD 3.94e+04\n", "Utility cost USD/hr 1.21" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "class HeatedTank(bst.Unit):\n", " # Define names of auxiliary units\n", " auxiliary_unit_names = ('mix_tank', 'pump', 'heat_exchanger')\n", " \n", " def _init(self, T):\n", " pump = self.auxiliary(\n", " 'pump', # name of auxiliary unit\n", " bst.Pump, # class of auxiliary unit\n", " ins=self.ins, # inlets to auxiliary unit (can be the same as parent unit)\n", " )\n", " heat_exchanger = self.auxiliary(\n", " 'heat_exchanger', # name\n", " bst.HXutility, # class\n", " ins=pump.outlet, # outlet from pump is the inlet to heat exchanger\n", " T=T, #: additional arguments to HXutility (Temperature [K])\n", " )\n", " self.auxiliary(\n", " 'mix_tank', # name\n", " bst.MixTank, # class\n", " ins=heat_exchanger.outlet, # connect\n", " outs=self.outs, # outlet from auxiliary unit (can be the same as parent unit)\n", " )\n", " \n", " def _run(self):\n", " # Run auxiliary unit operations internally\n", " self.pump._run()\n", " self.heat_exchanger._run()\n", " self.mix_tank._run()\n", " \n", " def _design(self):\n", " # Explicitly design and cost auxiliaries\n", " self.pump._design()\n", " self.heat_exchanger._design()\n", " self.mix_tank._design()\n", " \n", " def _cost(self):\n", " self.pump._cost()\n", " self.heat_exchanger._cost()\n", " self.mix_tank._cost()\n", " \n", "feed = bst.Stream('feed', Water=200)\n", "HT1 = HeatedTank('HT1', ins=feed, T=310)\n", "HT1.simulate()\n", "HT1.diagram(format='svg')\n", "HT1.show()\n", "HT1.results()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that BioSTEAM takes care of adding utilities and costs from auxiliary units to the parent unit. Auxiliary units are displayed by default in unit diagrams, but it is possible to supress this behavior by passing `auxiliaries=0`:" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "tags": [ "nbval-ignore-output" ] }, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAARUAAAB9CAYAAACMPvdhAAAABmJLR0QA/wD/AP+gvaeTAAARWUlEQVR4nO3de1RU1eIH8O+YyiMQX4Eg4AtFF3K5WoalhDcdtVQwNWvhc0mmCYUPHsojU4HrA00TXSUiJmv5y0fZSAXLMRRnTJFrRWI0CRqIiCYJongtcH5/zD3T8JTHlgH8ftZi6ZyzZ599cObrPvvs2SPTarUHQUQkSAdjN4CI2heGChEJxVAhIqE6GrsB7VVSUpKDsdtALWfKlClXjd2G1oKh8pjs3r17pLHbQC2HofI3hspjFBQUhFGjRgEAtFqtfrv0dxHbHle9LXmstnwOWVlZOHz4MOhvHFMhIqEYKkQkFEOFiIRiqBCRUAwVIhKKoUJEQjFUiEgohgoRCcVQISKhGCpEJBRDhYiEYqgQkVAMFSISiqFCREIxVIhIKIYKEQnFUCEioRgqRCQUQ4WIhGKoEJFQDBUiEoqhQkRCMVSISCiGChEJxVAhIqEYKkQkFEOFiIRiqBCRUAwVIhKKoUJEQjFUiEgohgoRCcVQISKhGCpEJBRDhYiEYqgQkVAMFSISqqOxG1CX0tLSTikpKQ779+9/FgB8fX3Penl5XW3pdnh7e78OAAqF4lBLH7sl9ejRAwBw69atOsvY2NgAAG7cuAEA6NWrV4PqLigoqHX78ePH4evri99++60RLSXpNVmb1vA6bbWh8vnnn/dTKBRu0uNbt26ZGbM9JNbPP/8MX19fYzejzcnPzzc3dhsepdWGihQocXFxR62trR8Yuz1UU1FREbRarf6xra0tAODatWv6bYb7Jd9//z2mTp36+BvYjnl7e2cuWLDgV2O3ozatfkyFgdK+7Nq1C1OnTkVsbKyxm9Im5eXlWQDAwIEDS4zdlrq0yp6K4TVjbWMaKpXKWqVS2aenpw9wdnYunDJlyiUPD4+btdXVmLJHjx51UKvVjhqNxs5YYzjt3bp167Bnzx6MGzcO/v7+xm5Oq2L4WgUAuVye7enpWeDq6tpqA6Q2rTJU6hMbGztUqVQOkR5rNBo7jUZjl5mZme3v75/V1LLR0dHDpX9MAIiPjx/JcRzxrl69Wusl0ZNOqVTaxcbGjqq2bYhSqRwSGBiYJv1HeOnSpa4A0LVr1z8PHDjQX7qR4ePjc37ixIlXrays/mr51lfVKkNFoVAcqquHolQqh8jl8uw5c+ZorKys/iotLe2UmJjorFQqhximemPLpqenD5DL5dleXl6XHR0dy/Pz882PHj3a3zi/AePp2bOnsZvwRJICZfv27V87OjqWA0BGRkaPyMjIl1UqlX313nV4eLjc8PH+/fufPX/+vG1YWNg5YwdLqx9TMZSZmWkNAFJIAICVldVfc+bM0QBARkaGdXPKSoECAI6OjuUTJ07Ma5kzoyeds7NzIQAcP37cXqVSWZeWlnYaMWJEsUKhOBQaGvq9VE66gREeHp6qUCgOST++vr5nNRqNXVpaWsPu89dBq9XKmncmrbSnUhfpUmbu3Lm13jpQKBRu0oh4U8pKgSJxcnIqE9f6tsFwnop0mSL9aW1tXetzqPnmzJlzMTw83E4KjbrG/+qah+Ll5XU1Pj5+pFqtdmzOWODmzZv/MWHChLzmjOO0qZ4KUXvl6upaolAoDkVGRiq9vb0zNRqNXUxMjGdwcPCoCxcudG1oPRqNxq457bh9+7b5urVrXj558mSTezyN7qkkJSU5jB07ttDc3LyyqQdtKnd399z09PQB+/bt+/JR142NKSuXy7OVSuWQnJwcS8PeSVuYaETti6ura4mrq2vJuHHjCvLy8ixiYmI8/9eDOQQAwcHBozQajV3113VpaWknQPe6b24btJUVT23bunV0QUHBD7Nnz250fY3qqSQkJAzavXv3yLDQVR7l5eVPNfZgzeXh4VEAAImJic43b940kbarVCprb2/v1/fs2TOoKWXd3NxuAsCuXbv+IQXJkzpQS8YRHR093Nvb+/WMjIwegO5SvE+fPnerlxs9enQ+AFQfO5EeS6/75ni2RyfMczKTHT50aHh0dPSzFRUVjRpnaXBPJSEhYZBCoXCbZG+KkwX5PcNDV70UGf3vUy3ZY/Hw8LiZmZmZLd1qM9zn7OxcOHny5Lzmln333Xf13UcfH5/zj/N8iCRyuTwvPT19QGRk5MvV9xm+Dj09PYvUanVhfHz8yPj4+JHV6siuaw5WY71qb4runTtg+38y+q0MDrKIWP3Bdw29q9SgnsrevXsHffnll24+/c0wf6A5PvinhezGtas9VgYHed69e7dFB3v9/f2zfH19zxp283x8fM4HBgb+p/rs26aUlUbhfX19z77xxhuXH/f5EAHAiBEjiiMjI5VyuTxb2iaXy7P9/f1PG74Orays/goLCztn+Fp1d3fPDQwMTKs+96q5Rlp3RtRwS1nxtfyeQSuWj83Ly2vQcIBMq9UerK/A3r17Bx05csRt1gBzTHU01W//7W4F1mTe0/awsf0jev2GUxYWFhXNPId2xdvb+/WgoCCMGqWbz2Q44av6XZXmbHtc9bbksdryOWRlZeHw4cOt4tPBIoSFhb1gefNX++UuFvptfzx4iPUXyx/e+qtjxfKgINXw4cP/qK+OensqdQUKAPS16IjVbk/Lim9c7x66MuSllu6xEFHL6G7SAWvdnu4wyKyiU3RU1L8UCoVjfeXrDJX6AkXCYCF6Mpg+JUOwq4VsUu9OHRISEtx37NjhUlfZWkOlIYEiYbAQPRk6yIBZ/c2wcJA5jiuPDYmICB95//79GneBawRAUlKSw5EjR9wm2Zs+MlAkfS06YuXQp2URPxT0mDVr1msC2k/UptS3GltbsXDhwjMNKSe3M4HpUzLZRz9dcFi9evVTGzduPG24v0aojB07tjD12+O/nyzI7znGtrOsr8WjOx4PKrX4vyv/1ZqZmFSMGz8h28bG5l6Dz6SdiouLe8HYbaCW09A3ZGs2bNiw4jNnzjg8qlxheSUO5j142LWL5YN58+bVuONUIzHMzc0ro6L/rQoPDfVY/WN+z/fdnpYNsKw7WB5UarE+6572cjkqQ1atShs2bNjtRp9NOxQXF9eo8p07dwYAPHhQ95pUZma6lRjKy8vrLNOaOTjoXq/5+flGbYeLi244ICtL3B3YyZMnN3vSWVvwS2kFNmTd03btaV268YM1ahsbm/9WL1PrmIq5uXllZHS0ytbe8dbazHva3LLa7xZLgZJ7D5Uhq0JPMlDavp07dxp1+YO4uDj069fPaMenuqVef4APfizT9h3oXBiz5cMTtQUKUM/dH32wOPT5fc2Pd2sECwOlfXr//feNevzo6GijHp9q0mqBg1fu42NNOTzH/EsTGRV9xszMrM6Z9PXOU9FdCkWr7Rz7VgkWBgrRk+HPh1psy76nPXL1z4dz5849FxAQcEEmk9W7dN8jp+mbmZlVCZafSyoYKK1MWloali5dCktLS8ycORNpaWm1lsvKykJsbCy6deuGbt26wcfHB1988YV+v/TdP4BuBbhnnnmmyvPVajWCg4NhY2ODuXPnQq1W19kmhUKB+fPnw97eHgqFokHn0bdvX/3f+/fvj/79//48Z3Z2NuLj4+Hk5AQnJycsWrQIX331VZXnOzs7w9nZGcXFxUhISMDgwYOxZMkSfPPNN488dnJyMlxdXev83T2JSv7UIvyHu9ofSlGxfMWKU9OmTWvQomUNmlNiZmZWGRkVpQ4LXeXxwY+/PWNmYlIRFhFxsq0tyNserVu3Dhs2bNA/Tk5ORnJyMoKDgxEeHq7fnpKSgjfffLPKc1NSUpCSkgIAeO21+mcCrF+/Hlu2bNE/PnbsGI4dO4alS5ciJCSkStmVK1ciMTFR/9jPzw9FRUWNP7n/+fbbb/H2229X2ZaamorU1FQAwKRJk6rsCw8Px4kTJwAAJ06cwIkTJ6DVavHqq6/WWr/0+1q0aBE8PT2b3M72JO9uJdZnlT/Umj59f11UhKoxC5Y1eOkD6a6Qi8vQgtBwBsrjYmJiov8xNTWFqakpzMzM9Hd+DKWlpWHDhg0ICQlBYWEhysrKcO3aNQQHB2Pjxo24cOGCvqwUKEqlErdv38bt27fx008/AQDeeustAEBxcbG+/K1bt/D7778DAFQqFbZs2YJly5bh0qVLuHHjBn799VcsW7YMW7duxcWLF/XPU6vVSExMREBAAM6dO4eCggKkp6ejtLT0kedu+E2Fly9fxuXLus/RSYFy+PBh5OTkICcnR9+jWLZsWY16Bg8ejIyMDPzyyy9ISEgAAHz99de1HtMwULi6v86VskqEfV+mterVu3jL1m3Kxq6A2Kj1VMzNzSujoqLOMFBaB+mNFRAQgC5dugAAunTpgvfeew8AcPLkSX3ZkpISlJSUoG/fvsjKykJKSgr27dvXoOOcPq2b27RkyZIqx3nnnXcA6EJH8t133wEAZs2ahd69ewMAevfujenTpzf1NJGbm4vc3Fw4ODggOzsbqampOHDgQJ3lZ8+eDUtLSwDAyJG61QGknouh5ORkBAUFYebMmQwUA0X3K/HP50Zc2RizOa1r166NXkSbU+pbGcN5KtU/HVu9tyJd9tjZ1b6CYFhYWJU3S1RUFDZt2tToNkmXPQMHDqx1/5o1a7B48WIAwNatWwFAHygSw/GRptiyZQt27NjRoLKGY0P1CQoKAgAcPHgQfn5+6N69e5Pb117IZDLt+PHjf/bz87v46NK14xq1T4hPP/0UmzZtwoIFC6BQKKBSqaDRaIzdrAb57LPPsGPHDvj4+CAxMRFJSUk4e/Zss+uNj4/HmDFjAABJSUnNrq89WLx48U/NCRSAodKmSWMhhYWFuHv3LsrKylBWVoY7d+7ofyQBAQEAdP/jv/TSSxg6dChMTExqrbe6efPmAYB+POXGjRsoKipCUVERrl+/juvXr+vLLl26FAD04yESw+9XbqywsDAAwNq1a/HCCy9gyJAh+hnIzeHu7o6FCxcCAGJiYqqcx5PK3t6+2dO1GSpt2LRp0wAA27Zt0w+qArqxli5dumD79u01npOTkwMAuHPnTr3fZ2wYSF5eXgB0s20Nv8JDrVbD1tYWH3/8sX7biy++CEAXAFKQXLt2Dfv372/UuZWV1RwbvHLlin7f7t27G1VfXdzc3LBo0SIAujta1HwMlTbM09MTISEh2LBhA/r16wdLS0tYWlpiypQpeOWVV6rcQo6PjwcAPPfcc+jWrRv69OmDmJgY/f7cXN2KmxMmTACgGwORxhw8PDywfPlyfPjhh3BxcYGNjQ169eqFGTNmYPz48ZgxY4a+ntGjRyMgIABKpRLPP/887O3t4e7uXmOMpS5jx44FoHuzR0REANCFJgDI5XI4OTlh2LBh2Llzp/45hneNmkIaRGZvRQyGShsXERGBvXv36i+FAOCjjz5CbGxslclr06dP1785ASAwMBAZGRk4deoUgL/v8ISGhmL+/PkAUOUNtnLlSnzyySf6SyFA9ybcvHlzjc8KBQcHY+fOnZDLdd/MKY2HNMSKFSswa9YsANDPbZk8eTKioqL0Zfz8/HDs2DH9OMi5c+caVHddbG1t9b069laa75Fr1FLTcI1a49fbEsdqb2vUisCeChEJxVAhIqEYKkQkFEOFiIRiqBCRUAwVIhKKoUJEQjFUiEgohgoRCcVQISKhGCpEJBRDhYiEYqgQkVAMFSISiqFCREIxVIhIKIYKEQnFUCEioRgqRCQUQ4WIhGKoEJFQDBUiEoqhQkRCMVSISCiGChEJxVAhIqEYKkQkFEOFiIRiqBCRUAwVIhKKoUJEQjFUiEgohgoRCcVQISKhGCpEJBRDhYiEYqgQkVAMFSISiqFCREIxVIhIqI7GbkB7dvToUZw+fRoAoNVq6y1b3/6m7jPWc9tavc2p486dOw2q90nCUHlMXFxcCgCgtLTU2E0hQWQyWY1tVlZWsLKyMkJrWi+ZVqs9aOxGEFH7wTEVIhKKoUJEQjFUiEio/wfhKMW7+ldUKwAAAABJRU5ErkJggg==", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "HT1.diagram(auxiliaries=0, format='png')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### References\n", "\n", "\n", "\n", "1. Huang, H., Long, S., & Singh, V. (2016) \"Techno-economic analysis of biodiesel and ethanol co-production from lipid-producing sugarcane\" Biofuels, Bioproducts and Biorefining, 10(3), 299–315. https://doi.org/10.1002/bbb.1640\n", "\n", "2. Seider, W. D., Lewin, D. R., Seader, J. D., Widagdo, S., Gani, R., & Ng, M. K. (2017). Product and Process Design Principles. Wiley. Cost Accounting and Capital Cost Estimation (Chapter 16)\n", "\n", "3. Humbird, D., Davis, R., Tao, L., Kinchin, C., Hsu, D., Aden, A., Dudgeon, D. (2011). Process Design and Economics for Biochemical Conversion of Lignocellulosic Biomass to Ethanol: Dilute-Acid Pretreatment and Enzymatic Hydrolysis of Corn Stover (No. NREL/TP-5100-47764, 1013269). https://doi.org/10.2172/1013269\n" ] } ], "metadata": { "celltoolbar": "Tags", "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.4" } }, "nbformat": 4, "nbformat_minor": 2 }