mirror of
https://github.com/Cantera/cantera.git
synced 2025-02-25 18:55:29 -06:00
Revise flame speed sensitivity example based on Jupyter version
Co-authored-by: Santosh Shanbhogue <santosh.shanbhogue@gmail.com>
This commit is contained in:
parent
e97aed10fc
commit
32a6d3da4e
120
doc/sphinx/_static/images/samples/flame-speed.svg
Normal file
120
doc/sphinx/_static/images/samples/flame-speed.svg
Normal file
@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 393.66 169.33">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.cls-1, .cls-2 {
|
||||
fill: #000;
|
||||
}
|
||||
|
||||
.cls-1, .cls-3 {
|
||||
font-family: SegoeUI, 'Segoe UI';
|
||||
}
|
||||
|
||||
.cls-4 {
|
||||
stroke-width: 2px;
|
||||
}
|
||||
|
||||
.cls-4, .cls-5, .cls-6 {
|
||||
fill: none;
|
||||
}
|
||||
|
||||
.cls-4, .cls-5, .cls-6, .cls-7 {
|
||||
stroke-miterlimit: 10;
|
||||
}
|
||||
|
||||
.cls-4, .cls-7 {
|
||||
stroke: #000;
|
||||
}
|
||||
|
||||
.cls-8 {
|
||||
fill: url(#linear-gradient);
|
||||
}
|
||||
|
||||
.cls-8, .cls-2, .cls-9, .cls-10 {
|
||||
stroke-width: 0px;
|
||||
}
|
||||
|
||||
.cls-5 {
|
||||
stroke: #b31515;
|
||||
}
|
||||
|
||||
.cls-5, .cls-6, .cls-7 {
|
||||
stroke-width: 3px;
|
||||
}
|
||||
|
||||
.cls-6 {
|
||||
stroke: #1da2f4;
|
||||
}
|
||||
|
||||
.cls-7 {
|
||||
fill: #fff;
|
||||
}
|
||||
|
||||
.cls-11, .cls-9, .cls-12 {
|
||||
fill: #b31515;
|
||||
}
|
||||
|
||||
.cls-13, .cls-14, .cls-10 {
|
||||
fill: #1da2f4;
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
.cls-12, .cls-15, .cls-14 {
|
||||
font-family: Cambria-Italic, Cambria;
|
||||
font-size: 24px;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.cls-16 {
|
||||
letter-spacing: -.03em;
|
||||
}
|
||||
</style>
|
||||
<linearGradient id="linear-gradient" x1="159.65" y1="63.5" x2="179.65" y2="63.5" gradientTransform="translate(0 127) scale(1 -1)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#fff"/>
|
||||
<stop offset=".08" stop-color="#ecf7fc"/>
|
||||
<stop offset=".24" stop-color="#bce4f6"/>
|
||||
<stop offset=".47" stop-color="#70c5ec"/>
|
||||
<stop offset=".62" stop-color="#3aafe6"/>
|
||||
<stop offset=".87" stop-color="#0075be"/>
|
||||
<stop offset=".99" stop-color="#fff"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect class="cls-8" x="159.65" y="1.5" width="20" height="124" transform="translate(339.31 127) rotate(180)"/>
|
||||
<path class="cls-7" d="M2.65,1.5h391.01"/>
|
||||
<path class="cls-7" d="M0,125.23h391.01"/>
|
||||
<text class="cls-13" transform="translate(18.51 25.31)"><tspan class="cls-3"><tspan class="cls-16" x="0" y="0">R</tspan><tspan x="12.51" y="0">eactants</tspan></tspan><tspan class="cls-15"><tspan x="36.58" y="28.8">ρ</tspan></tspan></text>
|
||||
<text class="cls-14" transform="translate(67.71 62.11) scale(.58)"><tspan x="0" y="0">u</tspan></text>
|
||||
<text class="cls-14" transform="translate(54.51 82.91)"><tspan x="0" y="0">T</tspan></text>
|
||||
<text class="cls-14" transform="translate(68.28 87.91) scale(.58)"><tspan x="0" y="0">u</tspan></text>
|
||||
<text class="cls-14" transform="translate(55.62 111.71)"><tspan x="0" y="0">S</tspan></text>
|
||||
<text class="cls-14" transform="translate(67.17 116.71) scale(.58)"><tspan x="0" y="0">u</tspan></text>
|
||||
<text class="cls-11" transform="translate(221.53 25.31)"><tspan class="cls-3"><tspan x="0" y="0">Products</tspan></tspan><tspan class="cls-15"><tspan x="32.65" y="28.8">ρ</tspan></tspan></text>
|
||||
<text class="cls-12" transform="translate(266.8 62.11) scale(.58)"><tspan x="0" y="0">b</tspan></text>
|
||||
<text class="cls-12" transform="translate(253.61 82.91)"><tspan x="0" y="0">T</tspan></text>
|
||||
<text class="cls-12" transform="translate(267.38 87.91) scale(.58)"><tspan x="0" y="0">b</tspan></text>
|
||||
<text class="cls-12" transform="translate(254.72 111.71)"><tspan x="0" y="0">S</tspan></text>
|
||||
<text class="cls-12" transform="translate(266.27 116.71) scale(.58)"><tspan x="0" y="0">b</tspan></text>
|
||||
<g>
|
||||
<path class="cls-6" d="M87.15,106h30.46"/>
|
||||
<polygon class="cls-10" points="116.09 111.24 125.15 106 116.09 100.76 116.09 111.24"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="cls-5" d="M283.53,105.55h65.09"/>
|
||||
<polygon class="cls-9" points="347.09 110.78 356.15 105.55 347.09 100.31 347.09 110.78"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="cls-10" d="M139.65,150.5c8.33-7.67,16.67-15.33,25-23"/>
|
||||
<g>
|
||||
<path class="cls-4" d="M139.65,150.5c6.6-6.07,13.2-12.15,19.8-18.22"/>
|
||||
<polygon class="cls-2" points="164.65 127.5 160.08 137.23 159.07 132.64 154.58 131.25 164.65 127.5"/>
|
||||
</g>
|
||||
</g>
|
||||
<text class="cls-1" transform="translate(80.69 161.11)"><tspan x="0" y="0">Flame</tspan></text>
|
||||
</svg>
|
After Width: | Height: | Size: 4.1 KiB |
@ -1,41 +1,157 @@
|
||||
"""
|
||||
r"""
|
||||
Laminar flame speed sensitivity analysis
|
||||
========================================
|
||||
|
||||
Sensitivity analysis for a freely-propagating, premixed methane-air
|
||||
flame. Computes the sensitivity of the laminar flame speed with respect
|
||||
to each reaction rate constant.
|
||||
In this example we simulate a freely-propagating, adiabatic, premixed methane-air flame,
|
||||
calculate its laminar burning velocity and perform a sensitivity analysis of its
|
||||
kinetics with respect to each reaction rate constant.
|
||||
|
||||
Requires: cantera >= 2.5.0
|
||||
Requires: cantera >= 3.0.0, pandas
|
||||
|
||||
.. tags:: Python, combustion, 1D flow, flame speed, premixed flame,
|
||||
sensitivity analysis, plotting
|
||||
|
||||
The figure below illustrates the setup, in a flame-fixed coordinate system. The
|
||||
reactants enter with density :math:`\rho_u`, temperature :math:`T_u` and speed
|
||||
:math:`S_u`. The products exit the flame at speed :math:`S_b`, density :math:`\rho_b`
|
||||
and temperature :math:`T_b`.
|
||||
|
||||
.. image:: /_static/images/samples/flame-speed.svg
|
||||
:width: 50%
|
||||
:alt: Freely Propagating Flame
|
||||
:align: center
|
||||
|
||||
.. tags:: Python, combustion, 1D flow, flame speed, premixed flame, sensitivity analysis
|
||||
"""
|
||||
|
||||
import cantera as ct
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
plt.rcParams['figure.constrained_layout.use'] = True
|
||||
|
||||
# %%
|
||||
# Simulation parameters
|
||||
p = ct.one_atm # pressure [Pa]
|
||||
Tin = 300.0 # unburned gas temperature [K]
|
||||
reactants = 'CH4:0.45, O2:1.0, N2:3.76'
|
||||
# ---------------------
|
||||
|
||||
width = 0.03 # m
|
||||
# Define the gas mixture and kinetics used to compute mixture properties
|
||||
# In this case, we are using the GRI 3.0 model with methane as the fuel
|
||||
mech_file = "gri30.yaml"
|
||||
fuel_comp = {"CH4": 1.0}
|
||||
|
||||
# Solution object used to compute mixture properties
|
||||
gas = ct.Solution('gri30.yaml')
|
||||
gas.TPX = Tin, p, reactants
|
||||
# Inlet temperature in kelvin and inlet pressure in pascals
|
||||
# In this case we are setting the inlet T and P to room temperature conditions
|
||||
To = 300
|
||||
Po = ct.one_atm
|
||||
|
||||
# Flame object
|
||||
f = ct.FreeFlame(gas, width=width)
|
||||
f.set_refine_criteria(ratio=3, slope=0.07, curve=0.14)
|
||||
# Domain width in metres
|
||||
width = 0.014
|
||||
|
||||
f.solve(loglevel=1, auto=True)
|
||||
print(f"\nmixture-averaged flamespeed = {f.velocity[0]:7f} m/s\n")
|
||||
# %%
|
||||
# Simulation setup
|
||||
# ----------------
|
||||
|
||||
# Create the object representing the gas and set its state to match the inlet conditions
|
||||
gas = ct.Solution(mech_file)
|
||||
gas.TP = To, Po
|
||||
gas.set_equivalence_ratio(1.0, fuel_comp, {"O2": 1.0, "N2": 3.76})
|
||||
|
||||
flame = ct.FreeFlame(gas, width=width)
|
||||
flame.set_refine_criteria(ratio=3, slope=0.07, curve=0.14)
|
||||
|
||||
# %%
|
||||
# Solve the flame
|
||||
# ---------------
|
||||
|
||||
flame.solve(loglevel=1, auto=True)
|
||||
|
||||
# %%
|
||||
print(f"\nmixture-averaged flame speed = {flame.velocity[0]:7f} m/s\n")
|
||||
|
||||
|
||||
# %%
|
||||
# Plot temperature and major species profiles
|
||||
# -------------------------------------------
|
||||
#
|
||||
# Check and see if all has gone well.
|
||||
|
||||
# Extract the spatial profiles as a SolutionArray to simplify plotting specific species
|
||||
profile = flame.to_array()
|
||||
|
||||
fig, ax = plt.subplots()
|
||||
|
||||
ax.plot(profile.grid * 100, profile.T, ".-")
|
||||
_ = ax.set(xlabel="Distance [cm]", ylabel="Temperature [K]")
|
||||
|
||||
# %%
|
||||
|
||||
fig, ax = plt.subplots()
|
||||
|
||||
ax.plot(profile.grid * 100, profile("CH4").X, "--", label="CH$_4$")
|
||||
ax.plot(profile.grid * 100, profile("O2").X, label="O$_2$")
|
||||
ax.plot(profile.grid * 100, profile("CO2").X, "--", label="CO$_2$")
|
||||
ax.plot(profile.grid * 100, profile("H2O").X, label="H$_2$O")
|
||||
|
||||
ax.legend(loc="best")
|
||||
plt.xlabel("Distance (cm)")
|
||||
_ = ax.set(xlabel="Distance [cm]", ylabel="Mole fraction [-]")
|
||||
|
||||
# %%
|
||||
# Sensitivity Analysis
|
||||
# --------------------
|
||||
#
|
||||
# See which reactions affect the flame speed the most. The sensitivities can be
|
||||
# efficiently computed using the adjoint method. In the general case, we consider a
|
||||
# system :math:`f(x, p) = 0` where :math:`x` is the system's state vector and :math:`p`
|
||||
# is a vector of parameters. To compute the sensitivities of a scalar function
|
||||
# :math:`g(x, p)` to the parameters, we solve the system:
|
||||
#
|
||||
# .. math::
|
||||
# \left(\frac{\partial f}{\partial x}\right)^T \lambda =
|
||||
# \left(\frac{\partial g}{\partial x}\right)^T
|
||||
#
|
||||
# for the Lagrange multiplier vector :math:`\lambda`. The sensitivities are then
|
||||
# computed as
|
||||
#
|
||||
# .. math::
|
||||
# \left.\frac{dg}{dp}\right|_{f=0} =
|
||||
# \frac{\partial g}{\partial p} - \lambda^T \frac{\partial f}{\partial p}
|
||||
#
|
||||
# In the case of flame speed sensitivity to the reaction rate coefficients,
|
||||
# :math:`g = S_u` and :math:`\partial g/\partial p = 0`. Since
|
||||
# :math:`\partial f/\partial x` is already computed as part of the normal solution
|
||||
# process, computing the sensitivities for :math:`N` reactions only requires :math:`N`
|
||||
# additional evaluations of the residual function to obtain
|
||||
# :math:`\partial f/\partial p`, plus the solution of the linear system for
|
||||
# :math:`\lambda`.
|
||||
#
|
||||
# Calculation of flame speed sensitivities with respect to rate coefficients is
|
||||
# implemented by the method `FreeFlame.get_flame_speed_reaction_sensitivities`. For
|
||||
# other sensitivities, the method `Sim1D.solve_adjoint` can be used.
|
||||
|
||||
# Create a DataFrame to store sensitivity-analysis data
|
||||
sens = pd.DataFrame(index=gas.reaction_equations(), columns=["sensitivity"])
|
||||
|
||||
# Use the adjoint method to calculate sensitivities
|
||||
sens = f.get_flame_speed_reaction_sensitivities()
|
||||
sens.sensitivity = flame.get_flame_speed_reaction_sensitivities()
|
||||
|
||||
print()
|
||||
print('Rxn # k/S*dS/dk Reaction Equation')
|
||||
print('----- ---------- ----------------------------------')
|
||||
for m in range(gas.n_reactions):
|
||||
print(f"{m: 5d} {sens[m]: 10.3e} {gas.reaction(m).equation}")
|
||||
# Show the first 10 sensitivities
|
||||
sens.head(10)
|
||||
|
||||
# %%
|
||||
|
||||
# Sort the sensitivities in order of descending magnitude
|
||||
sens = sens.iloc[(-sens['sensitivity'].abs()).argsort()]
|
||||
|
||||
fig, ax = plt.subplots()
|
||||
|
||||
# Reaction mechanisms can contains thousands of elementary steps. Limit the plot
|
||||
# to the top 15
|
||||
sens.head(15).plot.barh(ax=ax, legend=None)
|
||||
|
||||
ax.invert_yaxis() # put the largest sensitivity on top
|
||||
ax.set_title("Sensitivities for GRI 3.0")
|
||||
ax.set_xlabel(r"Sensitivity: $\frac{\partial\:\ln S_u}{\partial\:\ln k}$")
|
||||
ax.grid(axis='x')
|
||||
|
||||
#sphinx_gallery_thumbnail_number = -1
|
||||
|
Loading…
Reference in New Issue
Block a user