{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Getting started" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Initialize streams" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[Stream](../API/thermosteam/Stream.txt) objects define material flow rates along with its thermodynamic state. Before creating streams, a [Thermo](../API/thermosteam/Thermo.txt) property package must be defined. Alternatively, we can just pass chemical names and BioSTEAM will automatically create a property package based on ideal mixing rules and UNIFAC activity coefficients for phase equilibrium. More complex packages can be defined through Thermosteam, BioSTEAM's premier thermodynamic engine. Please visit [Thermosteam 101](./Thermosteam_101.ipynb) for details. In this example, a simple feed stream with a few common chemicals will be initialized:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Stream: s1\n", "phase: 'l', T: 298.15 K, P: 101325 Pa\n", "flow (kmol/hr): Water 50\n", " Methanol 20\n" ] } ], "source": [ "import biosteam as bst\n", "from biosteam import settings\n", "bst.nbtutorial() # Light-mode html diagrams and filter warnings\n", "settings.set_thermo(['Water', 'Methanol'])\n", "feed = bst.Stream(Water=50, Methanol=20)\n", "feed.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Set prices for performing techno-economic analysis later:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "231.24018" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "feed.price = 0.15 # USD/kg\n", "feed.cost # USD/hr" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Process settings" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[Process settings](../API/settings.txt) include price of feeds and products, conditions of utilities, and the chemical engineering plant cost index. These should be set before simulating a system." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Set the chemical engineering plant cost index:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "567.5" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "settings.CEPCI # Default year is 2017" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "settings.CEPCI = 603.1 # To year 2018" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Set [PowerUtility](../API/PowerUtility.txt) options:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.0782" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "settings.electricity_price # Default price (USD/kWhr)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "settings.electricity_price = 0.065 # Adjust price" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Set [HeatUtility](../API/HeatUtility.txt) options via [UtilityAgent](../API/UtilityAgent.txt) objects, which are [Stream](../API/thermosteam/Stream.txt) objects with additional attributes to describe a utility agent:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[,\n", " ,\n", " ,\n", " ]" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "settings.cooling_agents # All available cooling agents" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "UtilityAgent: cooling_water\n", "heat_transfer_efficiency: 1.000\n", "heat_transfer_price: 0 USD/kJ\n", "regeneration_price: 0.000488 USD/kmol\n", "T_limit: 325 K\n", "phase: 'l'\n", "T: 305.37 K\n", "P: 101325 Pa\n", "flow (kmol/hr): Water 1\n" ] } ], "source": [ "cooling_water = settings.get_cooling_agent('cooling_water')\n", "cooling_water.show() # A UtilityAgent" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.00048785" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Price of regenerating the utility in USD/kmol\n", "cooling_water.regeneration_price" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "5e-06" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Other utilities may be priced for amount of heat transfered in USD/kJ\n", "chilled_water = settings.get_cooling_agent('chilled_water')\n", "chilled_water.heat_transfer_price" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "cooling_water.T = 302 # Change the temperature of cooling water (K)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[,\n", " ,\n", " ]" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "settings.heating_agents # All available heating agents" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "UtilityAgent: low_pressure_steam\n", "heat_transfer_efficiency: 0.950\n", "heat_transfer_price: 0 USD/kJ\n", "regeneration_price: 0.238 USD/kmol\n", "T_limit: None\n", "phase: 'g'\n", "T: 412.19 K\n", "P: 344738 Pa\n", "flow (kmol/hr): Water 1\n" ] } ], "source": [ "lps = settings.get_heating_agent('low_pressure_steam') # A UtilityAgent\n", "lps.show() # Note that because utility changes phase, T_limit is None" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "lps.regeneration_price = 0.20 # Adjust price (USD/kmol)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Remove propane as a refrigerant:" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[,\n", " ,\n", " ]" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "settings.cooling_agents = settings.cooling_agents[:-1]\n", "settings.cooling_agents" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Add ammonia as a refrigerant:" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "# Assume cost from Table 17.1 in Warren D.Seider's\n", "# Product and Process Design Principles Synthesis, Analysis and Evaluation. Wiley (2016)\n", "Ammonia = bst.Chemical('Ammonia') # Load ammonia properties\n", "P = 101325 * 1.2 # Pressure should be above atmospheric\n", "T = Ammonia.Tsat(P) # Temperature should be at the bubble point for latent cooling\n", "ammonia = bst.UtilityAgent(\n", " 'ammonia',\n", " Ammonia=1,\n", " P=P,\n", " T=T,\n", " phase='l',\n", " thermo=bst.Thermo([Ammonia]),\n", " heat_transfer_price=13.17e-6,\n", ")\n", "settings.cooling_agents.append(ammonia)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that BioSTEAM only recognizes utility agents contained in `settings.cooling_agents` and `settings.heating_agents`. The order of utility agents dictates their priority. For example, BioSTEAM will attempt to use cooling water before chilled water because it is first in the list. Heating agents should be ordered from coolest to hottest and cooling agents should be ordered from hottest to coolest." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Find design requirements and cost with Unit objects" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[Creating a Unit](./Creating_a_Unit.ipynb) can be flexible. But in summary, a [Unit](../API/Unit.txt) object is initialized with an ID, and unit-specific arguments. BioSTEAM includes [essential unit operations](../API/units/index.txt) with rigorous modeling and design algorithms. Here we create a [Flash](../API/units/Flash.txt) object as an example:" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Flash: F1\n", "ins...\n", "[0] s1 \n", " phase: 'l', T: 298.15 K, P: 101325 Pa\n", " flow (kmol/hr): Water 50\n", " Methanol 20\n", "outs...\n", "[0] s2 \n", " phase: 'l', T: 298.15 K, P: 101325 Pa\n", " flow: 0\n", "[1] s3 \n", " phase: 'l', T: 298.15 K, P: 101325 Pa\n", " flow: 0\n" ] } ], "source": [ "# Specify vapor fraction and isobaric conditions\n", "F1 = bst.Flash('F1', ins=feed, V=0.1, P=101325)\n", "F1.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that the outlets, `outs`, is populated by empty streams." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To simulate the flash, use the `simulate` method:" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "scrolled": true, "tags": [ "nbval-ignore-output" ] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Flash: F1\n", "ins...\n", "[0] s1 \n", " phase: 'l', T: 298.15 K, P: 101325 Pa\n", " flow (kmol/hr): Water 50\n", " Methanol 20\n", "outs...\n", "[0] s2 \n", " phase: 'g', T: 352.84 K, P: 101325 Pa\n", " flow (kmol/hr): Water 2.59\n", " Methanol 4.41\n", "[1] s3 \n", " phase: 'l', T: 352.84 K, P: 101325 Pa\n", " flow (kmol/hr): Water 47.4\n", " Methanol 15.6\n" ] } ], "source": [ "F1.simulate()\n", "F1.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You may get a \"CostWarning\" that notifies you whether purchase cost correlations are out of range for the given design. This is ok for the example, but its important to make sure that the process is well designed and cost correlations are suitable for the domain." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `results` method returns simulation results:" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "tags": [ "nbval-skip" ] }, "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", "
FlashUnitsF1
Low pressure steamDutykJ/hr5.92e+05
Flowkmol/hr15.3
CostUSD/hr3.06
DesignVessel typeHorizontal
Lengthft6.44
Diameterft4
Weightlb1.38e+03
Wall thicknessin0.312
Vessel materialCarbon steel
Purchase costHorizontal pressure vesselUSD1.12e+04
Platform and laddersUSD3.21e+03
Heat exchanger - Double pipeUSD4.3e+03
Total purchase costUSD1.87e+04
Utility costUSD/hr3.06
\n", "
" ], "text/plain": [ "Flash Units F1\n", "Low pressure steam Duty kJ/hr 5.92e+05\n", " Flow kmol/hr 15.3\n", " Cost USD/hr 3.06\n", "Design Vessel type Horizontal\n", " Length ft 6.44\n", " Diameter ft 4\n", " Weight lb 1.38e+03\n", " Wall thickness in 0.312\n", " Vessel material Carbon steel\n", "Purchase cost Horizontal pressure vessel USD 1.12e+04\n", " Platform and ladders USD 3.21e+03\n", " Heat exchanger - Double pipe USD 4.3e+03\n", "Total purchase cost USD 1.87e+04\n", "Utility cost USD/hr 3.06" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "F1.results() # Default returns DataFrame object with units" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Unit operations also have useful properties for accessing streams and utility requirements:" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "tags": [ "nbval-skip" ] }, "outputs": [ { "data": { "text/plain": [ "591521.1044683269" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "F1.net_duty # Duty with heat transfer losses [kJ / hr]" ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "tags": [ "nbval-skip" ] }, "outputs": [ { "data": { "text/plain": [ "0.0" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "F1.net_power # Electricity consumption [kW]" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "tags": [ "nbval-skip" ] }, "outputs": [ { "data": { "text/plain": [ "[, , ]" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "[F1.feed, F1.vapor, F1.liquid] # Inlet feed and vapor and liquid outlets" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Although BioSTEAM includes a large set of essential unit operations, many process specific unit operations are not yet available. In this case, you can create new [Unit subclasses](./Inheriting_from_Unit.ipynb) to model unit operations not yet available in BioSTEAM." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Solve recycle loops and process specifications with System objects" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Designing a chemical process is no easy task. A simple recycle process consisting of a flash with a partial liquid recycle is presented here:" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "scrolled": true }, "outputs": [], "source": [ "recycle = bst.Stream('liquid_recycle')\n", "feed = bst.Stream('feed', Methanol=100, Water=450)\n", "M1 = bst.Mixer('M1', ins=(recycle, feed))\n", "F1 = bst.Flash('F1',\n", " ins=M1-0, # -pipe- notation equivalent to M1.outs[0]\n", " outs=('vapor_product', 'liquid'),\n", " V=0.1, P=101325\n", ")\n", "S1 = bst.Splitter('S1',\n", " ins=F1-1, # -pipe- notation equivalent to F1.outs[1]\n", " outs=(recycle, 'liquid_product'),\n", " split=0.5 # Split to 0th output stream\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that [-pipe- notation](./-pipe-_notation.ipynb) was used to retrieve streams and connect units." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can [find unit operations and manage flowsheets](./Managing_flowsheets.ipynb) with the `main_flowsheet`:" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "tags": [ "nbval-ignore-output" ] }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "bst.main_flowsheet.diagram()\n", "# Note that empty streams are dashed and the \n", "# width of streams depend on their flow rates (by mass)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[System](../API/System.txt) objects take care of solving recycle loops and simulating all unit operations.\n", "Although there are many ways of [creating a system](./Creating_a_System.ipynb), the most recommended way is to use the flowsheet:" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "System: sys\n", "ins...\n", "[0] feed \n", " phase: 'l', T: 298.15 K, P: 101325 Pa\n", " flow (kmol/hr): Water 450\n", " Methanol 100\n", "outs...\n", "[0] vapor_product \n", " phase: 'l', T: 298.15 K, P: 101325 Pa\n", " flow: 0\n", "[1] liquid_product \n", " phase: 'l', T: 298.15 K, P: 101325 Pa\n", " flow: 0\n" ] } ], "source": [ "sys = bst.main_flowsheet.create_system('sys')\n", "sys.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Simulate the System object:" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "scrolled": true, "tags": [ "nbval-ignore-output" ] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "System: sys\n", "Highest convergence error among components in recycle\n", "stream S1-0 after 4 loops:\n", "- flow rate 3.12e-01 kmol/hr (0.57%)\n", "- temperature 3.56e-02 K (0.0099%)\n", "ins...\n", "[0] feed \n", " phase: 'l', T: 298.15 K, P: 101325 Pa\n", " flow (kmol/hr): Water 450\n", " Methanol 100\n", "outs...\n", "[0] vapor_product \n", " phase: 'g', T: 359.26 K, P: 101325 Pa\n", " flow (kmol/hr): Water 53.4\n", " Methanol 46.7\n", "[1] liquid_product \n", " phase: 'l', T: 359.26 K, P: 101325 Pa\n", " flow (kmol/hr): Water 397\n", " Methanol 53.6\n" ] } ], "source": [ "sys.simulate()\n", "sys.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note how the recycle stream converged and all unit operations (including the flash vessel) were simulated. Let's have a look at system-level results:" ] }, { "cell_type": "code", "execution_count": 27, "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", "
SystemUnitssys
Low pressure steamDutykJ/hr6.76e+06
Flowkmol/hr175
CostUSD/hr34.9
Total purchase costUSD3.87e+04
Installed equipment costUSD1.15e+05
Utility costUSD/hr34.9
Material costUSD/hr0
SalesUSD/hr0
\n", "
" ], "text/plain": [ "System Units sys\n", "Low pressure steam Duty kJ/hr 6.76e+06\n", " Flow kmol/hr 175\n", " Cost USD/hr 34.9\n", "Total purchase cost USD 3.87e+04\n", "Installed equipment cost USD 1.15e+05\n", "Utility cost USD/hr 34.9\n", "Material cost USD/hr 0\n", "Sales USD/hr 0" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sys.results()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Once your system has been simulated, you can save a system report to view detailed results in an excel spreadsheet:" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [], "source": [ "# Try this on your computer and open excel\n", "# sys.save_report('Example.xlsx') " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that the cash flow analysis did not appear in the report because it requires a [TEA](../API/TEA.txt) object with all the necessary parameters (e.g., depreciation schedule, plant lifetime, construction schedule) to perform the analysis. A [TEA](../API/TEA.txt) object may also solve for economic indicators such as internal rate of return, minimum product selling price (MPSP), and maximum feedstock purchase price (MFPP). [Techno-economic analysis](./Techno-economic_analysis.ipynb) is discussed in detail later in the tutorial due to the extensive nature of the cash flow analysis." ] } ], "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 }