{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# Biomass Gasification\n", "\n", "

Written by Prof. William Smith (University of Guelph) and Allan Leal (ETH Zurich) on Mar 31st, 2023

\n", "\n", "This tutorial demonstrates the use of Reaktoro for biomass gasification in which temperature and exit gas composition are calculated from given Fuel Ultimate Analysis and fuel-to-air ratios." ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [], "source": [ "from reaktoro import *\n", "from numpy import arange" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [], "source": [ "db = NasaDatabase(\"nasa-cea\")" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [], "source": [ "# Inputs -----------------------------------------------------------------------------\n", "massC = 49.30 # g/mol\n", "massH = 5.5 # g/mol\n", "massO = 45.2 # g/mol\n", "HHV = 18.933 # kJ/g\n", "Q = 0.05 # heat loss (%) with respect to HHV\n", "fAirMin = 0.70 # minimum value for fAir (fuel to air mass ratio)\n", "fAirDelta = 0.1 # step-size for fAir values\n", "fAirNum = 30 # number of steps for fAir\n", "output_all_species = True # if false, output only a few species\n", "# ------------------------------------------------------------------------------------" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [], "source": [ "fAirs = [fAirMin + i * fAirDelta for i in range(fAirNum)]\n", "\n", "nC = massC / 12.011\n", "nH = massH / 1.00797\n", "nO = massO / 15.9994\n", "\n", "h0CO2 = -393.522 # kJ/g\n", "h0H2O = -285.83 # kJ/g\n", "\n", "a = nH / nC\n", "b = nO / nC\n", "\n", "formula = ChemicalFormula(f\"CH{a}O{b}\")\n", "\n", "Mfuel = formula.molarMass() * 1000 # from kg/mol to g/mol\n", "Mair = 28.850334 # in g/mol\n", "\n", "factor = Mfuel / Mair\n", "\n", "HHVmol = HHV * Mfuel" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [], "source": [ "h0fuel = HHVmol + h0CO2 + 0.5*h0H2O*a # in J/mol\n", "heatDuty = (1 - Q) * HHVmol + h0CO2 + 0.5*h0H2O*a # in J/mol" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [], "source": [ "stmodelparams = StandardThermoModelParamsConstant()\n", "stmodelparams.G0 = 1.0e+3\n", "stmodel = StandardThermoModelConstant(stmodelparams)\n", "\n", "species = Species()\n", "species = species.withName(\"Fuel\")\n", "species = species.withElements(formula.elements())\n", "species = species.withAggregateState(AggregateState.CondensedPhase)\n", "species = species.withStandardThermoModel(stmodel)\n", "\n", "db.addSpecies(species)" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [], "source": [ "gases = GaseousPhase(speciate(\"C H O N\"))\n", "condensedphases = CondensedPhases(\"Fuel H2O(l) C(gr)\")\n", "\n", "system = ChemicalSystem(db, condensedphases, gases)" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [], "source": [ "specs = EquilibriumSpecs(system)\n", "specs.pressure()\n", "specs.enthalpy()\n", "\n", "solver = EquilibriumSolver(specs)" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [], "source": [ "temperatures = []\n", "\n", "table = Table()\n", "\n", "for fAir in fAirs:\n", " state = ChemicalState(system)\n", " state.temperature(25.0, \"°C\")\n", " state.pressure(1.0, \"bar\")\n", " state.set(\"Fuel\", 1.0, \"mol\")\n", " state.set(\"O2\", fAir * factor * 0.21, \"mol\")\n", " state.set(\"N2\", fAir * factor * 0.79, \"mol\")\n", "\n", " props = ChemicalProps(state)\n", " conditions = EquilibriumConditions(specs)\n", "\n", " conditions.pressure(props.pressure())\n", " conditions.enthalpy(heatDuty, \"kJ\")\n", "\n", " conditions.setLowerBoundTemperature(298.15, \"°C\")\n", " conditions.setUpperBoundTemperature(3000.0, \"°C\")\n", "\n", " result = solver.solve(state, conditions)\n", "\n", " assert result.succeeded()\n", "\n", " table.column(\"Air:Fuel\") << fAir\n", " table.column(\"Temperature\") << state.temperature()\n", " table.column(f\"n(Gases)\") << state.props().phaseProps(\"GaseousPhase\").amount()\n", " \n", " if output_all_species:\n", " for species in system.species():\n", " table.column(f\"n({species.name()})\") << state.speciesAmount(species.name())\n", " else:\n", " table.column(\"n(C(gr))\") << state.speciesAmount(\"C(gr)\")\n", " table.column(\"n(CH4)\") << state.speciesAmount(\"CH4\")\n", " table.column(\"n(CO)\") << state.speciesAmount(\"CO\")\n", " table.column(\"n(CO2)\") << state.speciesAmount(\"CO2\")\n", " table.column(\"n(H2)\") << state.speciesAmount(\"H2\")\n", " table.column(\"n(H2O)\") << state.speciesAmount(\"H2O\")\n", " table.column(\"n(N2)\") << state.speciesAmount(\"N2\")" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [], "source": [ "table.save(\"output.txt\")" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "We now plot the calculated temperatures of the exit stream as a function of the fuel-to-air mass ratio." ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "data": { "application/vnd.plotly.v1+json": { "config": { "plotlyServerURL": "https://plot.ly" }, "data": [ { "mode": "lines+markers", "name": "", "type": "scatter", "x": [ 0.7, 0.8, 0.9, 1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.81, 1.82, 1.83, 1.84, 1.85, 1.86, 1.9, 1.95, 2, 2.05, 2.1, 3 ], "y": [ 871.5116489142578, 883.3821879018018, 893.9233632518628, 903.4086018657514, 912.0415825264807, 919.9772464339276, 927.3356981271936, 934.2116313370262, 940.6808637661424, 946.8049598624581, 952.6345618004478, 958.211830444494, 958.7570953289504, 959.3002284681733, 959.8412616433754, 960.3802261346007, 963.8157964612515, 967.5248552731812, 984.5509025087489, 1010.7921766100616, 1040.8927704045163, 1072.4213776560607, 1103.952082304736, 1563.2381748534008 ] } ], "layout": { "height": 1000, "template": { "data": { "scatter": [ { "line": { "width": 4 }, "marker": { "size": 10, "symbol": "circle" }, "type": "scatter" } ] }, "layout": { "colorway": [ "#4C78A8", "#F58518", "#E45756", "#72B7B2", "#54A24B", "#EECA3B", "#B279A2", "#FF9DA6", "#9D755D", "#BAB0AC" ], "font": { "color": "#2e2e2e", "family": "Arial", "size": 16 }, "legend": { "title": { "text": "" } }, "margin": { "b": 100, "l": 100, "pad": 5, "r": 100, "t": 100 }, "paper_bgcolor": "#f7f7f7", "plot_bgcolor": "#f7f7f7", "title": { "font": { "color": "#636363", "size": 24 }, "x": 0, "xref": "paper", "yanchor": "middle", "yref": "paper" }, "xaxis": { "title": { "font": { "size": 20 } }, "zerolinecolor": "#2e2e2e", "zerolinewidth": 0 }, "yaxis": { "title": { "font": { "size": 20 } }, "zerolinecolor": "#2e2e2e", "zerolinewidth": 0 } } }, "xaxis": { "title": { "text": "Air:Fuel (mass ratio)" } }, "yaxis": { "title": { "text": "Temperature [K]" } } } } }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from reaktplot import *\n", "\n", "fig = Figure()\n", "fig.xaxisTitle(\"Air:Fuel (mass ratio)\")\n", "fig.yaxisTitle(\"Temperature [K]\")\n", "fig.drawLineWithMarkers(fAirs, table[\"Temperature\"], name=\"\")\n", "fig.height(1000)\n", "fig.show()" ] } ], "metadata": { "kernelspec": { "display_name": "rkt", "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.9" }, "orig_nbformat": 4 }, "nbformat": 4, "nbformat_minor": 2 }