{ "cells": [ { "cell_type": "markdown", "id": "ef5af16a", "metadata": {}, "source": [ "# Life cycle assessment" ] }, { "cell_type": "markdown", "id": "4be88dc1", "metadata": {}, "source": [ "For a sustainable bioeconomy, it is critical to assess the environmental impact of a production process. This chapter goes over BioSTEAM's life cycle assessment (LCA) capabilities through a cradle-to-biorefinery-gate LCA of a sugarcane biorefinery that produces electricity and ethanol. We focus on the global warning potential (GWP) because it is central to policy implementation." ] }, { "cell_type": "markdown", "id": "41a97b18", "metadata": {}, "source": [ "## Quantifying GWP of a surgarcane biorefinery" ] }, { "cell_type": "markdown", "id": "6e734ebd", "metadata": {}, "source": [ "A biorefinery system defines the life cycle inventory. Apart from the model itself, only the characterization factors for inputs and outputs are needed to perform LCA. These can be retrieved from standard public models like the Greenhouse Gases, Regulated Emissions, and Energy Use in Transportation (Argonne GREET Model). Here we load a sugarcane to ethanol biorefinery, define characterization factors from GREET, and perform LCA using energy based, revenue base, and displacement allocation methods (i.e. system expansion)." ] }, { "cell_type": "markdown", "id": "a6552fc1", "metadata": {}, "source": [ "Define the impact indicator and the characterization factors:" ] }, { "cell_type": "code", "execution_count": 1, "id": "f7b4a80e", "metadata": {}, "outputs": [], "source": [ "### Load system\n", "import biosteam as bst\n", "from warnings import filterwarnings; filterwarnings('ignore') \n", "from biorefineries import sugarcane as sc\n", "sc.load(pellet_bagasse=False) # Do not dry and pellet bagasse feed to the boiler\n", "system = sc.sugarcane_sys\n", "\n", "### Set characterization factors on a per kg basis, as available in GREET 2020\n", "\n", "# Key for GWP characterization factor; we make it informative\n", "# but any value can work, even just a number.\n", "# Note that the impact assessment methodology used in GREET is the\n", "# Tool for the Reduction and Assessment of Chemical and other \n", "# Environmental Impacts (TRACI)\n", "GWP = 'GWP 100yr' \n", "bst.settings.define_impact_indicator(key=GWP, units='kg*CO2e')\n", "\n", "# Sugarcane for ethanol production, adjusted for moisture content (0.75 originally, 0.70 in the model).\n", "sc.sugarcane.set_CF(GWP, 0.02931 * 0.30 / 0.25, basis='kg', units='kg*CO2e') \n", "\n", "# Production of phosphoric acid from P2O5\n", "sc.H3PO4.set_CF(GWP, 1.) # Basis defaults to kg; units default to defined units\n", "\n", "# NG-Fired Simple-Cycle Gas Turbine CHP Plant, no transmission included\n", "bst.settings.set_electricity_CF(GWP, 0.36, basis='kWhr', units='kg*CO2e')\n", "\n", "# Lime production from lime stone, adjusted for dilution\n", "lime_dilution = 1 - sc.lime.get_mass_composition('Water')\n", "sc.lime.set_CF(GWP, 1.28 * lime_dilution)\n", "\n", "# Gasoline blendstock from Crude Oil for US Refineries\n", "sc.denaturant.set_CF(GWP, 0.84)\n", "\n", "# Assume all other feeds are negligible." ] }, { "cell_type": "markdown", "id": "4b45cd58", "metadata": {}, "source": [ "Compute the GWP per kg of ethanol using energy, revenue, and displacement allocation:" ] }, { "cell_type": "code", "execution_count": 2, "id": "4cb5b7e7", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Cradle to biorefinery gate GWP of sugarcane ethanol:\n", " Displacement allocation: -0.44 [kg CO2e / kg]\n", " Energy allocation: 0.39 [kg CO2e / kg]\n", " Economic allocation: 0.43 [kg CO2e / kg]\n" ] } ], "source": [ "# Displacement allocation [kg-CO2e / kg-ethanol]\n", "GWP_sugarcane_ethanol_displacement = system.get_net_impact(key=GWP) / system.get_mass_flow(sc.ethanol) \n", "\n", "# Energy allocation by gasoline gallon equivalent (GGE)\n", "GWP_per_GGE = system.get_property_allocated_impact(\n", " key=GWP, name='energy', basis='GGE', # Energy basis defaults to 'kJ'\n", " ignored={sc.yeast, sc.filter_cake}\n", ") # kg-CO2e / GGE\n", "\n", "GWP_sugarcane_ethanol_energy = (\n", " GWP_per_GGE * sc.ethanol.get_property('LHV', 'GGE/hr') / sc.ethanol.F_mass\n", ") # kg-CO2e / kg sugarcane ethanol\n", "\n", "# Economic/revenue allocation\n", "GWP_per_USD = system.get_property_allocated_impact(\n", " key=GWP, name='revenue', basis='USD', # Revenue basis defaults to USD\n", ") # kg-CO2e / USD\n", "\n", "GWP_sugarcane_ethanol_revenue = (\n", " GWP_per_USD * sc.ethanol.price\n", ") # kg-CO2e / kg-ethanol\n", "\n", "print(\n", " \"Cradle to biorefinery gate GWP of sugarcane ethanol:\\n \"\n", " f\"Displacement allocation: {GWP_sugarcane_ethanol_displacement:.2f} [kg CO2e / kg]\\n \"\n", " f\"Energy allocation: {GWP_sugarcane_ethanol_energy:.2f} [kg CO2e / kg]\\n \"\n", " f\"Economic allocation: {GWP_sugarcane_ethanol_revenue:.2f} [kg CO2e / kg]\"\n", ")" ] }, { "cell_type": "markdown", "id": "ff612602", "metadata": {}, "source": [ "Let's double check our results by performing the computation manually:" ] }, { "cell_type": "code", "execution_count": 3, "id": "646473d4", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Cradle to biorefinery gate GWP of sugarcane ethanol:\n", " Displacement allocation: -0.44 [kg CO2e / kg]\n", " Energy allocation: 0.39 [kg CO2e / kg]\n", " Economic allocation: 0.43 [kg CO2e / kg]\n" ] } ], "source": [ "# Displacement allocation\n", "GWP_total_displacement = (\n", " system.get_total_feeds_impact(GWP)\n", " + system.get_net_electricity_impact(GWP)\n", ") # kg-CO2e / yr\n", "annual_ethanol_flow_rate = system.get_mass_flow(sc.ethanol) \n", "GWP_sugarcane_ethanol_displacement = GWP_total_displacement / annual_ethanol_flow_rate\n", "\n", "# Energy allocation by gasoline gallon equivalent (GGE)\n", "total_impact_per_kg_ethanol = system.get_total_feeds_impact(GWP) / annual_ethanol_flow_rate\n", "sec_per_hr = 60 * 60\n", "kJ_per_GGE = 120276\n", "kW_to_GGE = sec_per_hr / kJ_per_GGE\n", "net_electricity_production = (\n", " system.get_electricity_production()\n", " - system.get_electricity_consumption()\n", ")\n", "GGE_electricity = kW_to_GGE * net_electricity_production\n", "GGE_ethanol = sc.ethanol.get_property('LHV', 'GGE/hr') * system.operating_hours # GGE / yr\n", "ethanol_energy_allocation = GGE_ethanol / (GGE_electricity + GGE_ethanol)\n", "GWP_sugarcane_ethanol_energy = ethanol_energy_allocation * total_impact_per_kg_ethanol\n", "\n", "# Revenue allocation\n", "revenue_electricity = net_electricity_production * bst.settings.electricity_price\n", "revenue_ethanol = annual_ethanol_flow_rate * sc.ethanol.price\n", "ethanol_revenue_allocation = revenue_ethanol / (revenue_ethanol + revenue_electricity)\n", "GWP_sugarcane_ethanol_revenue = ethanol_revenue_allocation * total_impact_per_kg_ethanol\n", "\n", "print(\n", " \"Cradle to biorefinery gate GWP of sugarcane ethanol:\\n \"\n", " f\"Displacement allocation: {GWP_sugarcane_ethanol_displacement:.2f} [kg CO2e / kg]\\n \"\n", " f\"Energy allocation: {GWP_sugarcane_ethanol_energy:.2f} [kg CO2e / kg]\\n \"\n", " f\"Economic allocation: {GWP_sugarcane_ethanol_revenue:.2f} [kg CO2e / kg]\"\n", ")" ] }, { "cell_type": "markdown", "id": "518658db", "metadata": {}, "source": [ "The displacement and energy allocation for vinasse was assumed to be negligible. Note that biogenic emissions do not contribute any GWP while that non-biogenic emissions associated to the bioreinfery do. In this example, all emissions are biogenic. The GWP computed here using energy allocation is very close to the value available in the [Ecoinvent life cycle inventory](https://ecoinvent.org/) (2020 database) for a modern autonomous sugarcane ethanol plant in Brazil (value not shown here to avoid proprietary issues)." ] }, { "cell_type": "markdown", "id": "56642593", "metadata": {}, "source": [ "## Life cycle inventory and impact breakdown" ] }, { "cell_type": "markdown", "id": "9a8e9776", "metadata": {}, "source": [ "A breakdown of the inventory and impacts comes in handy for inpecting values and verifying results. The `biosteam.report` module includes a few helpful functions for this:" ] }, { "cell_type": "code", "execution_count": 4, "id": "85290edd", "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", "
Inventory [kg/yr]
InputsH3PO43.43e+05
Denaturant2.41e+06
Lime6.86e+05
Sugarcane1.6e+09
OutputsEthanol1.12e+08
Electricity [kWhr/yr]3e+08
\n", "
" ], "text/plain": [ " Inventory [kg/yr]\n", "Inputs H3PO4 3.43e+05\n", " Denaturant 2.41e+06\n", " Lime 6.86e+05\n", " Sugarcane 1.6e+09\n", "Outputs Ethanol 1.12e+08\n", " Electricity [kWhr/yr] 3e+08" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from biosteam import report\n", "report.lca_inventory_table(\n", " systems=[system], \n", " key=GWP,\n", " items=[sc.ethanol], # For including products without characterization factors\n", ")" ] }, { "cell_type": "code", "execution_count": 5, "id": "1fe890ee", "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", "
Characterization factor [kg*CO2e/kg]GWP 100yr [kg*CO2e/kg*ethanol]
InputsH3PO410.00306
Denaturant0.840.0181
Lime0.05890.000361
Sugarcane0.03520.503
Total inputs0.524
Outputs displacedElectricity0.36 kg*CO2e/kWhr0.966
Total outputs displaced0.966
Total-0.442
\n", "
" ], "text/plain": [ " Characterization factor [kg*CO2e/kg] GWP 100yr [kg*CO2e/kg*ethanol]\n", "Inputs H3PO4 1 0.00306\n", " Denaturant 0.84 0.0181\n", " Lime 0.0589 0.000361\n", " Sugarcane 0.0352 0.503\n", "Total inputs 0.524\n", "Outputs displaced Electricity 0.36 kg*CO2e/kWhr 0.966\n", "Total outputs displaced 0.966\n", "Total -0.442" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "report.lca_displacement_allocation_table(\n", " systems=[system], \n", " key=GWP,\n", " items=[sc.ethanol], # For dividing yearly impact by ethanol production \n", ")" ] }, { "cell_type": "code", "execution_count": 6, "id": "d588975f", "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", "
Energy allocation factors
Electricity0.243
Ethanol0.679
Fiber fines0.000433
Filter cake0.0134
Yeast0.0643
\n", "
" ], "text/plain": [ " Energy allocation factors\n", "Electricity 0.243\n", "Ethanol 0.679\n", "Fiber fines 0.000433\n", "Filter cake 0.0134\n", "Yeast 0.0643" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "report.lca_property_allocation_factor_table(\n", " systems=[system],\n", " property='energy',\n", ")" ] }, { "cell_type": "code", "execution_count": 7, "id": "9e54e454", "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", "
Revenue allocation factors
Electricity0.181
Ethanol0.819
\n", "
" ], "text/plain": [ " Revenue allocation factors\n", "Electricity 0.181\n", "Ethanol 0.819" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "report.lca_property_allocation_factor_table(\n", " systems=[system],\n", " property='revenue',\n", ")" ] }, { "cell_type": "code", "execution_count": 8, "id": "fc0728e0", "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", "
Displacement allocation factors
Electricity1.84
Ethanol-0.843
\n", "
" ], "text/plain": [ " Displacement allocation factors\n", "Electricity 1.84\n", "Ethanol -0.843" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "report.lca_displacement_allocation_factor_table(\n", " systems=[system],\n", " items=[sc.ethanol],\n", " key=GWP,\n", ")" ] }, { "cell_type": "markdown", "id": "9914248e", "metadata": {}, "source": [ "## Excluding co-heat and power generation in system boundary" ] }, { "cell_type": "markdown", "id": "5e200cce", "metadata": {}, "source": [ "While cooling water and steam utilities were produced on-site at the biorefinery, it is also common to assume utilities are provided outside the system boundaries. In BioSTEAM, characterization factors of heat utilities can be defined on an energy or mass basis. As an example, the system boundaries are redefined to exclude the co-heat and power system and solve for the GWP displacement of bagasse when used for on-site generation of steam and electricity:" ] }, { "cell_type": "code", "execution_count": 9, "id": "13e3916d", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "GWP displacement of burning bagasse for on-site steam and power: 0.45 [kg CO2e / kg]\n", " \n" ] } ], "source": [ "### Create the system without co-heat and power and simulate\n", "BT = bst.main_flowsheet(bst.BoilerTurbogenerator)\n", "BT.ins.empty()\n", "system_no_CHP = bst.System.from_units(\n", " 'system_no_CHP', \n", " units=[i for i in system.units if i is not BT],\n", " operating_hours=system.operating_hours,\n", ")\n", "system_no_CHP.simulate()\n", "\n", "### Redefine characterization factors\n", "\n", "# NG-Fired Simple-Cycle Gas Turbine CHP Plant, transmission included!\n", "bst.settings.set_electricity_CF(GWP, 0.38) # Basis defaults to kWhr; units default to defined units\n", "\n", "# Steam Production via Small Boiler from North American Natural Gas \n", "bst.settings.set_utility_agent_CF('low_pressure_steam', GWP, 88.44, basis='MMBtu', units='kg*CO2e')\n", "\n", "# Displacement allocation\n", "GWP_total_new = (\n", " system_no_CHP.get_total_feeds_impact(GWP)\n", " + system_no_CHP.get_net_electricity_impact(GWP)\n", " + system_no_CHP.get_net_heat_utility_impact('low_pressure_steam', GWP)\n", ") # kg CO2 eq. / yr\n", "annual_bagasse_flow_rate = system_no_CHP.get_mass_flow(sc.bagasse)\n", "GWP_total_displacement = (\n", " system.get_total_feeds_impact(GWP)\n", " + system.get_net_electricity_impact(GWP)\n", ") # kg CO2 eq. / yr\n", "GWP_bagasse_displacement = (GWP_total_new - GWP_total_displacement) / annual_bagasse_flow_rate # kg CO2 eq. / kg bagasse\n", "print(f\"GWP displacement of burning bagasse for on-site steam and power: {GWP_bagasse_displacement:.2f} [kg CO2e / kg]\\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": 5 }