{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Gasoline Blending\n", "\n", "The task is to determine the most profitable blend of gasoline products from given set of refinery streams.\n", "\n", "![](https://www.researchgate.net/profile/Jeffrey-Kelly-2/publication/260356707/figure/fig4/AS:267835926642706@1440868469487/Typical-gasoline-blending-system-Color-figure-can-be-viewed-in-the-online-issue-which_W640.jpg)\n", "\n", "\n", "\n", "" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "# install Pyomo and solvers for Google Colab\n", "import sys\n", "on_colab = \"google.colab\" in sys.modules\n", "if on_colab:\n", " !wget \"https://raw.githubusercontent.com/IDAES/idaes-pse/main/scripts/colab_helper.py\"\n", " import colab_helper\n", " colab_helper.install_idaes()\n", " colab_helper.install_ipopt()" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "import pyomo.environ as pyo\n", "\n", "# Set default font sizes for plots\n", "import matplotlib.pyplot as plt\n", "plt.rcParams['font.size'] = 18" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Gasoline Product Specifications\n", "\n", "The gasoline products include regular and premium gasoline. In addition to the current price, the specifications include\n", "\n", "* **octane** the minimum road octane number. Road octane is the computed as the average of the Research Octane Number (RON) and Motor Octane Number (MON).\n", "* **Reid Vapor Pressure** Upper and lower limits are specified for the Reid vapor pressure. The Reid vapor pressure is the absolute pressure exerted by the liquid at 100°F.\n", "* **benzene** the maximum volume percentage of benzene allowed in the final product. Benzene helps to increase octane rating, but is also a treacherous environmental contaminant.\n" ] }, { "cell_type": "code", "execution_count": 3, "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", "
priceoctaneRVPminRVPmaxbenzene
Regular2.7587.00.015.01.1
Premium2.8591.00.015.01.1
\n", "
" ], "text/plain": [ " price octane RVPmin RVPmax benzene\n", "Regular 2.75 87.0 0.0 15.0 1.1\n", "Premium 2.85 91.0 0.0 15.0 1.1" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "products = pd.DataFrame({\n", " 'Regular' : {'price': 2.75, 'octane': 87, 'RVPmin': 0.0, 'RVPmax': 15.0, 'benzene': 1.1},\n", " 'Premium' : {'price': 2.85, 'octane': 91, 'RVPmin': 0.0, 'RVPmax': 15.0, 'benzene': 1.1},\n", "}).T\n", "\n", "display(products)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Stream Specifications\n", "\n", "A typical refinery produces many intermediate streams that can be incorporated in a blended gasoline product. Here we provide data on seven streams that include:\n", "\n", "* **Butane** n-butane is a C4 product stream produced from the light components of the crude being processed by the refinery. Butane is a highly volatile of gasoline.\n", "* **LSR** Light straight run naptha is a 90°F to 190°F cut from the crude distillation column primarily consisting of straight chain C5-C6 hydrocarbons.\n", "* **Isomerate** is the result of isomerizing LSR to produce branched molecules that results in higher octane number.\n", "* **Reformate** is result of catalytic reforming heavy straight run napthenes to produce a high octane blending component, as well by-product hydrogen used elsewhere in the refinery for hydro-treating.\n", "* **Reformate LB** is a is a low benzene variant of reformate.\n", "* **FCC Naphta** is the product of a fluidized catalytic cracking unit designed to produce gasoline blending components from long chain hydrocarbons present in the crude oil being processed by the refinery.\n", "* **Alkylate** The alkylation unit reacts iso-butane with low-molecular weight alkenes to produce a high octane blending component for gasoline.\n", "\n", "The stream specifications include research octane and motor octane numbers for each blending component, the Reid vapor pressure, the benzene content, cost, and availability (in gallons per day). The road octane number is computed as the average of the RON and MON." ] }, { "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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
RONMONRVPbenzenecostavailoctane
Butane93.092.054.00.000.8530000.092.50
LSR78.076.011.20.732.0535000.077.00
Isomerate83.081.113.50.002.200.082.05
Reformate100.088.23.21.852.8060000.094.10
Reformate LB93.784.02.80.122.750.088.85
FCC Naphtha92.177.11.41.062.6070000.084.60
Alkylate97.395.94.60.002.7540000.096.60
\n", "
" ], "text/plain": [ " RON MON RVP benzene cost avail octane\n", "Butane 93.0 92.0 54.0 0.00 0.85 30000.0 92.50\n", "LSR 78.0 76.0 11.2 0.73 2.05 35000.0 77.00\n", "Isomerate 83.0 81.1 13.5 0.00 2.20 0.0 82.05\n", "Reformate 100.0 88.2 3.2 1.85 2.80 60000.0 94.10\n", "Reformate LB 93.7 84.0 2.8 0.12 2.75 0.0 88.85\n", "FCC Naphtha 92.1 77.1 1.4 1.06 2.60 70000.0 84.60\n", "Alkylate 97.3 95.9 4.6 0.00 2.75 40000.0 96.60" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "streams = pd.DataFrame({\n", " 'Butane' : {'RON': 93.0, 'MON': 92.0, 'RVP': 54.0, 'benzene': 0.00, 'cost': 0.85, 'avail': 30000},\n", " 'LSR' : {'RON': 78.0, 'MON': 76.0, 'RVP': 11.2, 'benzene': 0.73, 'cost': 2.05, 'avail': 35000},\n", " 'Isomerate' : {'RON': 83.0, 'MON': 81.1, 'RVP': 13.5, 'benzene': 0.00, 'cost': 2.20, 'avail': 0},\n", " 'Reformate' : {'RON':100.0, 'MON': 88.2, 'RVP': 3.2, 'benzene': 1.85, 'cost': 2.80, 'avail': 60000},\n", " 'Reformate LB' : {'RON': 93.7, 'MON': 84.0, 'RVP': 2.8, 'benzene': 0.12, 'cost': 2.75, 'avail': 0},\n", " 'FCC Naphtha' : {'RON': 92.1, 'MON': 77.1, 'RVP': 1.4, 'benzene': 1.06, 'cost': 2.60, 'avail': 70000},\n", " 'Alkylate' : {'RON': 97.3, 'MON': 95.9, 'RVP': 4.6, 'benzene': 0.00, 'cost': 2.75, 'avail': 40000},\n", "}).T\n", "\n", "streams['octane'] = (streams['RON'] + streams['MON'])/2\n", "\n", "display(streams)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Questions we want to Answer\n", "\n", "1. What is the maximum profit possible using the current product specifications and available streams?\n", "\n", "2. What are the marginal values of each blending stream? That is, how much would you be willing to pay for each additional gallon of the blending streams?\n", "\n", "3. A marketing team says there is an opportunity to create a mid-grade gasoline product with a road octane number of 89 that would sell for $2.82/gallon, and with all other specifications the same. Would an additional profit be created? What at what price point does the mid-grade product enhance profits?\n", "\n", "4. New environmental regulations have reduced the allowable benzene levels from 1.1 vol% to 0.62 vol%, and the maximum Reid vapor pressure from 15.0 to 9.0. What is the impact on profits?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Blending Model\n", "\n", "This simplified blending model assumes the product attributes can be computed as linear volume weighted averages of the component properties. Let the decision variable $x_{s,p} \\geq 0$ be the volume, in gallons, of blending component $s \\in S$ used in the final product $p \\in P$.\n", "\n", "### Objective\n", "\n", "The objective is maximize profit, which is the difference between product revenue and stream costs. \n", "\n", "\\begin{align}\n", "\\text{profit} & = \\max_{x_{s,p}}\\left( \\sum_{p\\in P} \\text{Price}_p \\sum_{s\\in S} x_{s,p}\n", "- \\sum_{s\\in S} \\text{Cost}_s \\sum_{p\\in P} x_{s,p}\\right) \\\\\n", "& = \\max_{x_{s,p}}\\left(\\sum_{p\\in P}\\sum_{s\\in S}x_{s,p}(\\text{Price}_p - \\text{Cost}_s)\\right)\n", "\\end{align}\n", "\n", "### Raw Materials\n", "\n", "The first constraints in any blending problem are normally the limits on available raw materials.\n", "\n", "The blending constraint for octane can be written as \n", "\n", "\\begin{align}\n", "\\frac{\\sum_{s \\in S} x_{s,p} \\text{Octane}_s}{\\sum_{s \\in S} x_{s,p}} & \\geq \\text{Octane}_p & \\forall p \\in P\n", "\\end{align}\n", "\n", "where $\\text{Octane}_s$ refers to the octane rating of stream $s$, whereas $\\text{Octane}_p$ refers to the octane rating of product $p$. Multiplying through by the denominator, and consolidating terms gives\n", "\n", "\\begin{align}\n", "\\sum_{s \\in S} x_{s,p}\\left(\\text{Octane}_s - \\text{Octane}_p\\right) & \\geq 0 & \\forall p \\in P\n", "\\end{align}\n", "\n", "The same assumptions and development apply to the benzene constraint\n", "\n", "\\begin{align}\n", "\\sum_{s \\in S} x_{s,p}\\left(\\text{Benzene}_s - \\text{Benzene}_p\\right) & \\leq 0 & \\forall p \\in P\n", "\\end{align}\n", "\n", "Reid vapor pressure, however, follows a somewhat different mixing rule. For the Reid vapor pressure we have\n", "\n", "\\begin{align}\n", "\\sum_{s \\in S} x_{s,p}\\left(\\text{RVP}_s^{1.25} - \\text{RVP}_{min,p}^{1.25}\\right) & \\geq 0 & \\forall p \\in P \\\\\n", "\\sum_{s \\in S} x_{s,p}\\left(\\text{RVP}_s^{1.25} - \\text{RVP}_{max,p}^{1.25}\\right) & \\leq 0 & \\forall p \\in P\n", "\\end{align}\n", "\n", "This model is implemented in the following cell." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Pyomo Implementation" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Total Volume = 235000.0 gallons.\n", "Total Profit = 100425.0 dollars.\n", "Profit = 42.7 cents per gallon.\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", "
RegularPremium
Butane2.175457e+048245.428
LSR9.211560e+0325788.439
Isomerate0.000000e+000.000
Reformate1.978387e+0440216.132
Reformate LB0.000000e+000.000
FCC Naphtha7.000000e+040.000
Alkylate-7.275958e-1240000.000
\n", "
" ], "text/plain": [ " Regular Premium\n", "Butane 2.175457e+04 8245.428\n", "LSR 9.211560e+03 25788.439\n", "Isomerate 0.000000e+00 0.000\n", "Reformate 1.978387e+04 40216.132\n", "Reformate LB 0.000000e+00 0.000\n", "FCC Naphtha 7.000000e+04 0.000\n", "Alkylate -7.275958e-12 40000.000" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import pyomo.environ as pyo\n", "\n", "def gas_blending(products, streams):\n", " ''' Gasoline blending optimization problem\n", "\n", " Arguments:\n", " products: DataFrame with columns ['price', 'octane', 'RVPmin', 'RVPmax', 'benzene']\n", " streams: DataFrame with columns ['RON', 'MON', 'RVP', 'benzene', 'cost', 'avail']\n", " max_benzene: maximum benzene content in the final product (float)\n", " max_RVP: maximum Reid vapor pressure in the final product (float)\n", " \n", " Returns:\n", " m: Pyomo model (solved)\n", "\n", " '''\n", "\n", " m = pyo.ConcreteModel(\"Gasoline Blending\")\n", " \n", " m.PRODUCTS = pyo.Set(initialize=products.index)\n", " m.STREAMS = pyo.Set(initialize=streams.index)\n", " \n", " m.x = pyo.Var(m.STREAMS, m.PRODUCTS, domain=pyo.NonNegativeReals)\n", " \n", " @m.Objective(sense=pyo.maximize)\n", " def profit(m):\n", " return sum(sum(m.x[s, p]*(products.loc[p, 'price'] - streams.loc[s, 'cost']) for s in m.STREAMS) for p in m.PRODUCTS)\n", " \n", " @m.Constraint(m.STREAMS)\n", " def raw_material_available(m, s):\n", " return sum(m.x[s, p] for p in m.PRODUCTS) <= streams.loc[s, 'avail']\n", " \n", " @m.Constraint(m.PRODUCTS)\n", " def octane(m, p):\n", " return sum(m.x[s, p]*(streams.loc[s, 'octane'] - products.loc[p, 'octane']) for s in m.STREAMS) >= 0\n", " \n", " @m.Constraint(m.PRODUCTS)\n", " def benzene(m, p):\n", " return sum(m.x[s, p]*(streams.loc[s, 'benzene'] - products.loc[p, 'benzene']) for s in m.STREAMS) <= 0\n", " \n", " @m.Constraint(m.PRODUCTS)\n", " def min_reid_vapor_pressure(m, p):\n", " return sum(m.x[s, p]*(streams.loc[s, 'RVP']**1.25 - products.loc[p, 'RVPmin']**1.25) for s in m.STREAMS) >= 0\n", " \n", " @m.Constraint(m.PRODUCTS)\n", " def max_reid_vapor_pressure(m, p):\n", " return sum(m.x[s, p]*(streams.loc[s, 'RVP']**1.25 - products.loc[p, 'RVPmax']**1.25) for s in m.STREAMS) <= 0\n", "\n", " solver = pyo.SolverFactory('cbc')\n", " solver.solve(m)\n", " \n", " # display results\n", " vol = sum(m.x[s,p]() for s in m.STREAMS for p in m.PRODUCTS)\n", " print(\"Total Volume =\", round(vol, 1), \"gallons.\")\n", " print(\"Total Profit =\", round(m.profit(), 1), \"dollars.\")\n", " print(\"Profit =\", round(100*m.profit()/vol,1), \"cents per gallon.\")\n", "\n", " return m\n", "\n", "m = gas_blending(products, streams)\n", "\n", " \n", "soln = pd.DataFrame({s: {p: m.x[s,p]() for p in m.PRODUCTS} for s in m.STREAMS}).T\n", "display(soln)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Display Results" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Results for each Stream" ] }, { "cell_type": "code", "execution_count": 6, "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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
RegularPremiumTotalAvailableUnused (Slack)
Butane21754.68245.430000.030000.00.0
LSR9211.625788.435000.035000.00.0
Isomerate0.00.00.00.00.0
Reformate19783.940216.160000.060000.00.0
Reformate LB0.00.00.00.00.0
FCC Naphtha70000.00.070000.070000.00.0
Alkylate-0.040000.040000.040000.00.0
\n", "
" ], "text/plain": [ " Regular Premium Total Available Unused (Slack)\n", "Butane 21754.6 8245.4 30000.0 30000.0 0.0\n", "LSR 9211.6 25788.4 35000.0 35000.0 0.0\n", "Isomerate 0.0 0.0 0.0 0.0 0.0\n", "Reformate 19783.9 40216.1 60000.0 60000.0 0.0\n", "Reformate LB 0.0 0.0 0.0 0.0 0.0\n", "FCC Naphtha 70000.0 0.0 70000.0 70000.0 0.0\n", "Alkylate -0.0 40000.0 40000.0 40000.0 0.0" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def get_stream_results(m, streams):\n", " ''' Extract stream results from Pyomo model\n", "\n", " Argument:\n", " m: Pyomo model\n", " streams: DataFrame with columns ['RON', 'MON', 'RVP', 'benzene', 'cost', 'avail']\n", "\n", " Returns:\n", " stream_results: DataFrame with columns ['Total', 'Available', 'Unused (Slack)']\n", " \n", " '''\n", "\n", " # Create empty DataFrame\n", " stream_results = pd.DataFrame()\n", "\n", " # Loop over streams\n", " for s in m.STREAMS:\n", "\n", " # Loop over products\n", " for p in m.PRODUCTS:\n", " stream_results.loc[s,p] = round(m.x[s,p](), 1)\n", " \n", " # Calculate total volume, copy available volume\n", " stream_results.loc[s,'Total'] = round(sum(m.x[s,p]() for p in m.PRODUCTS), 1)\n", " stream_results.loc[s,'Available'] = streams.loc[s,'avail']\n", " \n", " # Calculate unused volume (slack)\n", " stream_results['Unused (Slack)'] = stream_results['Available'] - stream_results['Total']\n", " \n", " # Return DataFrame\n", " return stream_results\n", "\n", "sr = get_stream_results(m, streams)\n", "display(sr)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Results for each Product" ] }, { "cell_type": "code", "execution_count": 7, "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", "
VolumeoctaneRVPbenzene
Regular120750.087.015.01.0
Premium114250.091.010.60.8
\n", "
" ], "text/plain": [ " Volume octane RVP benzene\n", "Regular 120750.0 87.0 15.0 1.0\n", "Premium 114250.0 91.0 10.6 0.8" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def get_product_results(m, streams, products):\n", "\n", " product_results = pd.DataFrame()\n", " for p in m.PRODUCTS:\n", " product_results.loc[p,'Volume'] = round(sum(m.x[s,p]() for s in m.STREAMS), 1)\n", " product_results.loc[p,'octane'] = round(sum(m.x[s,p]()*streams.loc[s,'octane'] for s in m.STREAMS)\n", " /product_results.loc[p,'Volume'], 1)\n", " product_results.loc[p,'RVP'] = round((sum(m.x[s,p]()*streams.loc[s,'RVP']**1.25 for s in m.STREAMS)\n", " /product_results.loc[p,'Volume'])**0.8, 1)\n", " product_results.loc[p,'benzene'] = round(sum(m.x[s,p]()*streams.loc[s,'benzene'] for s in m.STREAMS)\n", " /product_results.loc[p,'Volume'], 1)\n", "\n", " return product_results\n", "\n", "pr = get_product_results(m, streams, products)\n", "display(pr)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Excercise 0.\n", "\n", "What are the marginal blending rates of each stream?\n", "\n", "Perturb the `avail` of each stream and record the results. We can then calculate the partial derivative of profit with respect to each perturbation." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "1 gallon increase in Butane availability:\n", "Total Volume = 235001.0 gallons.\n", "Total Profit = 100427.0 dollars.\n", "Profit = 42.7 cents per gallon.\n", "\n", "1 gallon increase in LSR availability:\n", "Total Volume = 235001.0 gallons.\n", "Total Profit = 100425.5 dollars.\n", "Profit = 42.7 cents per gallon.\n", "\n", "1 gallon increase in Isomerate availability:\n", "Total Volume = 235001.0 gallons.\n", "Total Profit = 100425.4 dollars.\n", "Profit = 42.7 cents per gallon.\n", "\n", "1 gallon increase in Reformate availability:\n", "Total Volume = 235001.0 gallons.\n", "Total Profit = 100425.1 dollars.\n", "Profit = 42.7 cents per gallon.\n", "\n", "1 gallon increase in Reformate LB availability:\n", "Total Volume = 235001.0 gallons.\n", "Total Profit = 100425.0 dollars.\n", "Profit = 42.7 cents per gallon.\n", "\n", "1 gallon increase in FCC Naphtha availability:\n", "Total Volume = 235001.0 gallons.\n", "Total Profit = 100425.1 dollars.\n", "Profit = 42.7 cents per gallon.\n", "\n", "1 gallon increase in Alkylate availability:\n", "Total Volume = 235001.0 gallons.\n", "Total Profit = 100425.2 dollars.\n", "Profit = 42.7 cents per gallon.\n", "\n", "Sensitivity of profit to stream availability, $/gallon:\n" ] }, { "data": { "text/plain": [ "Butane 2.03903\n", "LSR 0.45047\n", "Isomerate 0.42595\n", "Reformate 0.12836\n", "Reformate LB 0.04665\n", "FCC Naphtha 0.08971\n", "Alkylate 0.24160\n", "Name: sensitivity, dtype: float64" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "senstivity = {}\n", "\n", "base_profit = m.profit()\n", "\n", "for s in streams.index:\n", " epsilon = 1\n", " streams_perturb = streams.copy()\n", " streams_perturb.loc[s, 'avail'] += epsilon\n", "\n", " print(\"\\n1 gallon increase in \",s,\" availability:\")\n", " m_perturb = gas_blending(products, streams_perturb)\n", " perturb_profit = m_perturb.profit()\n", " senstivity[s] = (perturb_profit - base_profit)/epsilon\n", "\n", "print(\"\\nSensitivity of profit to stream availability, $/gallon:\")\n", "display(pd.Series(senstivity, name='sensitivity'))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Which feed stream is most valuable and why?" ] }, { "cell_type": "markdown", "metadata": { "tags": [ "exercise" ] }, "source": [ "## Exercise 1.\n", "\n", "The marketing team says there is an opportunity to create a mid-grade gasoline product with a road octane number of 89 that would sell for $2.82/gallon, and with all other specifications the same. Could an additional profit be created?\n", "\n", "Create a new cell (or cells) below to compute a solution to this exercise." ] }, { "cell_type": "code", "execution_count": 9, "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", "
priceoctaneRVPminRVPmaxbenzene
Regular2.7587.00.015.01.1
Midgrade2.8289.00.015.01.1
Premium2.8591.00.015.01.1
\n", "
" ], "text/plain": [ " price octane RVPmin RVPmax benzene\n", "Regular 2.75 87.0 0.0 15.0 1.1\n", "Midgrade 2.82 89.0 0.0 15.0 1.1\n", "Premium 2.85 91.0 0.0 15.0 1.1" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Total Volume = 235000.0 gallons.\n", "Total Profit = 104995.0 dollars.\n", "Profit = 44.7 cents per gallon.\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", " \n", " \n", " \n", " \n", " \n", " \n", "
RegularMidgradePremiumTotalAvailableUnused (Slack)
Butane849.529150.50.030000.030000.00.0
LSR2646.232353.80.035000.035000.00.0
Isomerate0.00.00.00.00.00.0
Reformate2820.757179.30.060000.060000.00.0
Reformate LB0.00.00.00.00.00.0
FCC Naphtha0.070000.00.070000.070000.00.0
Alkylate183.639816.40.040000.040000.00.0
\n", "
" ], "text/plain": [ " Regular Midgrade Premium Total Available Unused (Slack)\n", "Butane 849.5 29150.5 0.0 30000.0 30000.0 0.0\n", "LSR 2646.2 32353.8 0.0 35000.0 35000.0 0.0\n", "Isomerate 0.0 0.0 0.0 0.0 0.0 0.0\n", "Reformate 2820.7 57179.3 0.0 60000.0 60000.0 0.0\n", "Reformate LB 0.0 0.0 0.0 0.0 0.0 0.0\n", "FCC Naphtha 0.0 70000.0 0.0 70000.0 70000.0 0.0\n", "Alkylate 183.6 39816.4 0.0 40000.0 40000.0 0.0" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stderr", "output_type": "stream", "text": [ "/var/folders/3w/vr4xmyqs451dg23xk88pqcg00000gq/T/ipykernel_97102/2558176032.py:6: RuntimeWarning: invalid value encountered in scalar divide\n", " product_results.loc[p,'octane'] = round(sum(m.x[s,p]()*streams.loc[s,'octane'] for s in m.STREAMS)\n", "/var/folders/3w/vr4xmyqs451dg23xk88pqcg00000gq/T/ipykernel_97102/2558176032.py:8: RuntimeWarning: invalid value encountered in scalar divide\n", " product_results.loc[p,'RVP'] = round((sum(m.x[s,p]()*streams.loc[s,'RVP']**1.25 for s in m.STREAMS)\n", "/var/folders/3w/vr4xmyqs451dg23xk88pqcg00000gq/T/ipykernel_97102/2558176032.py:10: RuntimeWarning: invalid value encountered in scalar divide\n", " product_results.loc[p,'benzene'] = round(sum(m.x[s,p]()*streams.loc[s,'benzene'] for s in m.STREAMS)\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", "
VolumeoctaneRVPbenzene
Regular6500.087.015.01.1
Midgrade228500.089.012.80.9
Premium0.0NaNNaNNaN
\n", "
" ], "text/plain": [ " Volume octane RVP benzene\n", "Regular 6500.0 87.0 15.0 1.1\n", "Midgrade 228500.0 89.0 12.8 0.9\n", "Premium 0.0 NaN NaN NaN" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "products1 = pd.DataFrame({\n", " 'Regular' : {'price': 2.75, 'octane': 87, 'RVPmin': 0.0, 'RVPmax': 15.0, 'benzene': 1.1},\n", " 'Midgrade' : {'price': 2.82, 'octane': 89, 'RVPmin': 0.0, 'RVPmax': 15.0, 'benzene': 1.1},\n", " 'Premium' : {'price': 2.85, 'octane': 91, 'RVPmin': 0.0, 'RVPmax': 15.0, 'benzene': 1.1},\n", "}).T\n", "\n", "display(products1)\n", "\n", "m1 = gas_blending(products1, streams)\n", "\n", "sr1 = get_stream_results(m1, streams)\n", "display(sr1)\n", "\n", "pr1 = get_product_results(m1, streams, products1)\n", "display(pr1)" ] }, { "cell_type": "markdown", "metadata": { "tags": [ "exercise" ] }, "source": [ "## Exercise 2.\n", "\n", "New environmental regulations have reduced the allowable benzene levels from 1.1 vol% to 0.62 vol%, and the maximum Reid vapor pressure from 15.0 to 9.0.\n", "\n", "Compared to the base case (i.e., without the midgrade product), how does this change profitability? " ] }, { "cell_type": "code", "execution_count": 10, "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", "
priceoctaneRVPminRVPmaxbenzene
Regular2.7587.00.09.00.62
Premium2.8591.00.09.00.62
\n", "
" ], "text/plain": [ " price octane RVPmin RVPmax benzene\n", "Regular 2.75 87.0 0.0 9.0 0.62\n", "Premium 2.85 91.0 0.0 9.0 0.62" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Total Volume = 137317.1 gallons.\n", "Total Profit = 44493.6 dollars.\n", "Profit = 32.4 cents per gallon.\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", "
RegularPremiumTotalAvailableUnused (Slack)
Butane8187.50.08187.530000.021812.5
LSR28305.30.028305.335000.06694.7
Isomerate0.00.00.00.00.0
Reformate0.00.00.060000.060000.0
Reformate LB0.00.00.00.00.0
FCC Naphtha60824.30.060824.370000.09175.7
Alkylate40000.00.040000.040000.00.0
\n", "
" ], "text/plain": [ " Regular Premium Total Available Unused (Slack)\n", "Butane 8187.5 0.0 8187.5 30000.0 21812.5\n", "LSR 28305.3 0.0 28305.3 35000.0 6694.7\n", "Isomerate 0.0 0.0 0.0 0.0 0.0\n", "Reformate 0.0 0.0 0.0 60000.0 60000.0\n", "Reformate LB 0.0 0.0 0.0 0.0 0.0\n", "FCC Naphtha 60824.3 0.0 60824.3 70000.0 9175.7\n", "Alkylate 40000.0 0.0 40000.0 40000.0 0.0" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stderr", "output_type": "stream", "text": [ "/var/folders/3w/vr4xmyqs451dg23xk88pqcg00000gq/T/ipykernel_97102/2558176032.py:6: RuntimeWarning: invalid value encountered in scalar divide\n", " product_results.loc[p,'octane'] = round(sum(m.x[s,p]()*streams.loc[s,'octane'] for s in m.STREAMS)\n", "/var/folders/3w/vr4xmyqs451dg23xk88pqcg00000gq/T/ipykernel_97102/2558176032.py:8: RuntimeWarning: invalid value encountered in scalar divide\n", " product_results.loc[p,'RVP'] = round((sum(m.x[s,p]()*streams.loc[s,'RVP']**1.25 for s in m.STREAMS)\n", "/var/folders/3w/vr4xmyqs451dg23xk88pqcg00000gq/T/ipykernel_97102/2558176032.py:10: RuntimeWarning: invalid value encountered in scalar divide\n", " product_results.loc[p,'benzene'] = round(sum(m.x[s,p]()*streams.loc[s,'benzene'] for s in m.STREAMS)\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", "
VolumeoctaneRVPbenzene
Regular137317.187.09.00.6
Premium0.0NaNNaNNaN
\n", "
" ], "text/plain": [ " Volume octane RVP benzene\n", "Regular 137317.1 87.0 9.0 0.6\n", "Premium 0.0 NaN NaN NaN" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "products2 = pd.DataFrame({\n", " 'Regular' : {'price': 2.75, 'octane': 87, 'RVPmin': 0.0, 'RVPmax': 9.0, 'benzene': 0.62},\n", " 'Premium' : {'price': 2.85, 'octane': 91, 'RVPmin': 0.0, 'RVPmax': 9.0, 'benzene': 0.62},\n", "}).T\n", "\n", "display(products2)\n", "\n", "m2 = gas_blending(products2, streams)\n", "\n", "sr2 = get_stream_results(m2, streams)\n", "display(sr2)\n", "\n", "pr2 = get_product_results(m2, streams, products2)\n", "display(pr2)" ] }, { "cell_type": "markdown", "metadata": { "tags": [ "exercise" ] }, "source": [ "## Exercise 3.\n", "\n", "Given the new product specifications in Exercise 2, let's consider using different refinery streams. In place of Reformate, the refinery could produce Reformate LB. (That is, one or the other of the two streams could be 60000 gallons per day, but not both). Same for LSR and Isomerate. \n", "\n", "How should the refinery be operated to maximize profitability? Why is this the best solution? What intutition can you develop from the results?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Scenario A: Reformate and LSR (base)" ] }, { "cell_type": "code", "execution_count": 11, "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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
RONMONRVPbenzenecostavailoctane
Butane93.092.054.00.000.8530000.092.50
LSR78.076.011.20.732.0535000.077.00
Isomerate83.081.113.50.002.200.082.05
Reformate100.088.23.21.852.8060000.094.10
Reformate LB93.784.02.80.122.750.088.85
FCC Naphtha92.177.11.41.062.6070000.084.60
Alkylate97.395.94.60.002.7540000.096.60
\n", "
" ], "text/plain": [ " RON MON RVP benzene cost avail octane\n", "Butane 93.0 92.0 54.0 0.00 0.85 30000.0 92.50\n", "LSR 78.0 76.0 11.2 0.73 2.05 35000.0 77.00\n", "Isomerate 83.0 81.1 13.5 0.00 2.20 0.0 82.05\n", "Reformate 100.0 88.2 3.2 1.85 2.80 60000.0 94.10\n", "Reformate LB 93.7 84.0 2.8 0.12 2.75 0.0 88.85\n", "FCC Naphtha 92.1 77.1 1.4 1.06 2.60 70000.0 84.60\n", "Alkylate 97.3 95.9 4.6 0.00 2.75 40000.0 96.60" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Total Volume = 137317.1 gallons.\n", "Total Profit = 44493.6 dollars.\n", "Profit = 32.4 cents per gallon.\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", "
RegularPremiumTotalAvailableUnused (Slack)
Butane8187.50.08187.530000.021812.5
LSR28305.30.028305.335000.06694.7
Isomerate0.00.00.00.00.0
Reformate0.00.00.060000.060000.0
Reformate LB0.00.00.00.00.0
FCC Naphtha60824.30.060824.370000.09175.7
Alkylate40000.00.040000.040000.00.0
\n", "
" ], "text/plain": [ " Regular Premium Total Available Unused (Slack)\n", "Butane 8187.5 0.0 8187.5 30000.0 21812.5\n", "LSR 28305.3 0.0 28305.3 35000.0 6694.7\n", "Isomerate 0.0 0.0 0.0 0.0 0.0\n", "Reformate 0.0 0.0 0.0 60000.0 60000.0\n", "Reformate LB 0.0 0.0 0.0 0.0 0.0\n", "FCC Naphtha 60824.3 0.0 60824.3 70000.0 9175.7\n", "Alkylate 40000.0 0.0 40000.0 40000.0 0.0" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stderr", "output_type": "stream", "text": [ "/var/folders/3w/vr4xmyqs451dg23xk88pqcg00000gq/T/ipykernel_97102/2558176032.py:6: RuntimeWarning: invalid value encountered in scalar divide\n", " product_results.loc[p,'octane'] = round(sum(m.x[s,p]()*streams.loc[s,'octane'] for s in m.STREAMS)\n", "/var/folders/3w/vr4xmyqs451dg23xk88pqcg00000gq/T/ipykernel_97102/2558176032.py:8: RuntimeWarning: invalid value encountered in scalar divide\n", " product_results.loc[p,'RVP'] = round((sum(m.x[s,p]()*streams.loc[s,'RVP']**1.25 for s in m.STREAMS)\n", "/var/folders/3w/vr4xmyqs451dg23xk88pqcg00000gq/T/ipykernel_97102/2558176032.py:10: RuntimeWarning: invalid value encountered in scalar divide\n", " product_results.loc[p,'benzene'] = round(sum(m.x[s,p]()*streams.loc[s,'benzene'] for s in m.STREAMS)\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", "
VolumeoctaneRVPbenzene
Regular137317.187.09.00.6
Premium0.0NaNNaNNaN
\n", "
" ], "text/plain": [ " Volume octane RVP benzene\n", "Regular 137317.1 87.0 9.0 0.6\n", "Premium 0.0 NaN NaN NaN" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def exercise3(reformate_LB=True, isomerate=True):\n", " ''' Sensitivity analysis for gasoline blending problem replacement feedstocks\n", "\n", " Arguments:\n", " reformate_LB: replace Reformate with Reformate LB stream (boolean)\n", " isomerate: replace LSR with Isomerate stream (boolean)\n", "\n", " '''\n", "\n", " if reformate_LB:\n", " reformate = 0\n", " reformate_LB = 60000\n", " else:\n", " reformate = 60000\n", " reformate_LB = 0\n", "\n", " if isomerate:\n", " LSR = 0\n", " isomerate = 35000\n", " else:\n", " LSR = 35000\n", " isomerate = 0\n", "\n", " streams3 = pd.DataFrame({\n", " 'Butane' : {'RON': 93.0, 'MON': 92.0, 'RVP': 54.0, 'benzene': 0.00, 'cost': 0.85, 'avail': 30000},\n", " 'LSR' : {'RON': 78.0, 'MON': 76.0, 'RVP': 11.2, 'benzene': 0.73, 'cost': 2.05, 'avail': LSR},\n", " 'Isomerate' : {'RON': 83.0, 'MON': 81.1, 'RVP': 13.5, 'benzene': 0.00, 'cost': 2.20, 'avail': isomerate},\n", " 'Reformate' : {'RON':100.0, 'MON': 88.2, 'RVP': 3.2, 'benzene': 1.85, 'cost': 2.80, 'avail': reformate},\n", " 'Reformate LB' : {'RON': 93.7, 'MON': 84.0, 'RVP': 2.8, 'benzene': 0.12, 'cost': 2.75, 'avail': reformate_LB},\n", " 'FCC Naphtha' : {'RON': 92.1, 'MON': 77.1, 'RVP': 1.4, 'benzene': 1.06, 'cost': 2.60, 'avail': 70000},\n", " 'Alkylate' : {'RON': 97.3, 'MON': 95.9, 'RVP': 4.6, 'benzene': 0.00, 'cost': 2.75, 'avail': 40000},\n", " }).T\n", "\n", " streams3['octane'] = (streams3['RON'] + streams3['MON'])/2\n", "\n", " display(streams3)\n", "\n", " m3 = gas_blending(products2, streams3)\n", "\n", " sr3 = get_stream_results(m3, streams3)\n", " display(sr3)\n", "\n", " pr3 = get_product_results(m3, streams3, products2)\n", " display(pr3)\n", "\n", " return None\n", "\n", "exercise3(reformate_LB=False, isomerate=False)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Scenario B: Reformate LB and LSR" ] }, { "cell_type": "code", "execution_count": 12, "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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
RONMONRVPbenzenecostavailoctane
Butane93.092.054.00.000.8530000.092.50
LSR78.076.011.20.732.0535000.077.00
Isomerate83.081.113.50.002.200.082.05
Reformate100.088.23.21.852.800.094.10
Reformate LB93.784.02.80.122.7560000.088.85
FCC Naphtha92.177.11.41.062.6070000.084.60
Alkylate97.395.94.60.002.7540000.096.60
\n", "
" ], "text/plain": [ " RON MON RVP benzene cost avail octane\n", "Butane 93.0 92.0 54.0 0.00 0.85 30000.0 92.50\n", "LSR 78.0 76.0 11.2 0.73 2.05 35000.0 77.00\n", "Isomerate 83.0 81.1 13.5 0.00 2.20 0.0 82.05\n", "Reformate 100.0 88.2 3.2 1.85 2.80 0.0 94.10\n", "Reformate LB 93.7 84.0 2.8 0.12 2.75 60000.0 88.85\n", "FCC Naphtha 92.1 77.1 1.4 1.06 2.60 70000.0 84.60\n", "Alkylate 97.3 95.9 4.6 0.00 2.75 40000.0 96.60" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Total Volume = 219412.8 gallons.\n", "Total Profit = 63791.2 dollars.\n", "Profit = 29.1 cents per gallon.\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", "
RegularPremiumTotalAvailableUnused (Slack)
Butane13290.31122.514412.830000.015587.2
LSR35000.00.035000.035000.00.0
Isomerate0.00.00.00.00.0
Reformate0.00.00.00.00.0
Reformate LB60000.00.060000.060000.00.0
FCC Naphtha63818.66181.470000.070000.00.0
Alkylate33236.26763.840000.040000.00.0
\n", "
" ], "text/plain": [ " Regular Premium Total Available Unused (Slack)\n", "Butane 13290.3 1122.5 14412.8 30000.0 15587.2\n", "LSR 35000.0 0.0 35000.0 35000.0 0.0\n", "Isomerate 0.0 0.0 0.0 0.0 0.0\n", "Reformate 0.0 0.0 0.0 0.0 0.0\n", "Reformate LB 60000.0 0.0 60000.0 60000.0 0.0\n", "FCC Naphtha 63818.6 6181.4 70000.0 70000.0 0.0\n", "Alkylate 33236.2 6763.8 40000.0 40000.0 0.0" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
VolumeoctaneRVPbenzene
Regular205345.287.09.00.5
Premium14067.791.09.00.5
\n", "
" ], "text/plain": [ " Volume octane RVP benzene\n", "Regular 205345.2 87.0 9.0 0.5\n", "Premium 14067.7 91.0 9.0 0.5" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "exercise3(reformate_LB=True, isomerate=False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Scenario C: Reformate and Isomerate" ] }, { "cell_type": "code", "execution_count": 13, "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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
RONMONRVPbenzenecostavailoctane
Butane93.092.054.00.000.8530000.092.50
LSR78.076.011.20.732.050.077.00
Isomerate83.081.113.50.002.2035000.082.05
Reformate100.088.23.21.852.8060000.094.10
Reformate LB93.784.02.80.122.750.088.85
FCC Naphtha92.177.11.41.062.6070000.084.60
Alkylate97.395.94.60.002.7540000.096.60
\n", "
" ], "text/plain": [ " RON MON RVP benzene cost avail octane\n", "Butane 93.0 92.0 54.0 0.00 0.85 30000.0 92.50\n", "LSR 78.0 76.0 11.2 0.73 2.05 0.0 77.00\n", "Isomerate 83.0 81.1 13.5 0.00 2.20 35000.0 82.05\n", "Reformate 100.0 88.2 3.2 1.85 2.80 60000.0 94.10\n", "Reformate LB 93.7 84.0 2.8 0.12 2.75 0.0 88.85\n", "FCC Naphtha 92.1 77.1 1.4 1.06 2.60 70000.0 84.60\n", "Alkylate 97.3 95.9 4.6 0.00 2.75 40000.0 96.60" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Total Volume = 171265.3 gallons.\n", "Total Profit = 51312.5 dollars.\n", "Profit = 30.0 cents per gallon.\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", "
RegularPremiumTotalAvailableUnused (Slack)
Butane7447.51528.98976.430000.021023.6
LSR0.00.00.00.00.0
Isomerate18754.016246.035000.035000.00.0
Reformate0.017288.917288.960000.042711.1
Reformate LB0.00.00.00.00.0
FCC Naphtha68754.21245.870000.070000.00.0
Alkylate22591.817408.240000.040000.00.0
\n", "
" ], "text/plain": [ " Regular Premium Total Available Unused (Slack)\n", "Butane 7447.5 1528.9 8976.4 30000.0 21023.6\n", "LSR 0.0 0.0 0.0 0.0 0.0\n", "Isomerate 18754.0 16246.0 35000.0 35000.0 0.0\n", "Reformate 0.0 17288.9 17288.9 60000.0 42711.1\n", "Reformate LB 0.0 0.0 0.0 0.0 0.0\n", "FCC Naphtha 68754.2 1245.8 70000.0 70000.0 0.0\n", "Alkylate 22591.8 17408.2 40000.0 40000.0 0.0" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
VolumeoctaneRVPbenzene
Regular117547.487.09.00.6
Premium53717.991.09.00.6
\n", "
" ], "text/plain": [ " Volume octane RVP benzene\n", "Regular 117547.4 87.0 9.0 0.6\n", "Premium 53717.9 91.0 9.0 0.6" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "exercise3(reformate_LB=False, isomerate=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Scenario D: Reformate LB and Isomerate" ] }, { "cell_type": "code", "execution_count": 14, "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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
RONMONRVPbenzenecostavailoctane
Butane93.092.054.00.000.8530000.092.50
LSR78.076.011.20.732.050.077.00
Isomerate83.081.113.50.002.2035000.082.05
Reformate100.088.23.21.852.800.094.10
Reformate LB93.784.02.80.122.7560000.088.85
FCC Naphtha92.177.11.41.062.6070000.084.60
Alkylate97.395.94.60.002.7540000.096.60
\n", "
" ], "text/plain": [ " RON MON RVP benzene cost avail octane\n", "Butane 93.0 92.0 54.0 0.00 0.85 30000.0 92.50\n", "LSR 78.0 76.0 11.2 0.73 2.05 0.0 77.00\n", "Isomerate 83.0 81.1 13.5 0.00 2.20 35000.0 82.05\n", "Reformate 100.0 88.2 3.2 1.85 2.80 0.0 94.10\n", "Reformate LB 93.7 84.0 2.8 0.12 2.75 60000.0 88.85\n", "FCC Naphtha 92.1 77.1 1.4 1.06 2.60 70000.0 84.60\n", "Alkylate 97.3 95.9 4.6 0.00 2.75 40000.0 96.60" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Total Volume = 217971.0 gallons.\n", "Total Profit = 60022.2 dollars.\n", "Profit = 27.5 cents per gallon.\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", "
RegularPremiumTotalAvailableUnused (Slack)
Butane8480.94490.112971.030000.017029.0
LSR0.00.00.00.00.0
Isomerate35000.00.035000.035000.00.0
Reformate0.00.00.00.00.0
Reformate LB60000.00.060000.060000.00.0
FCC Naphtha45273.624726.470000.070000.00.0
Alkylate12943.927056.140000.040000.00.0
\n", "
" ], "text/plain": [ " Regular Premium Total Available Unused (Slack)\n", "Butane 8480.9 4490.1 12971.0 30000.0 17029.0\n", "LSR 0.0 0.0 0.0 0.0 0.0\n", "Isomerate 35000.0 0.0 35000.0 35000.0 0.0\n", "Reformate 0.0 0.0 0.0 0.0 0.0\n", "Reformate LB 60000.0 0.0 60000.0 60000.0 0.0\n", "FCC Naphtha 45273.6 24726.4 70000.0 70000.0 0.0\n", "Alkylate 12943.9 27056.1 40000.0 40000.0 0.0" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
VolumeoctaneRVPbenzene
Regular161698.487.09.00.3
Premium56272.691.09.00.5
\n", "
" ], "text/plain": [ " Volume octane RVP benzene\n", "Regular 161698.4 87.0 9.0 0.3\n", "Premium 56272.6 91.0 9.0 0.5" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "exercise3(reformate_LB=True, isomerate=True)" ] } ], "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.10.12" } }, "nbformat": 4, "nbformat_minor": 4 }