.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "examples/premixed_flame/premixedburnerflame.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_examples_premixed_flame_premixedburnerflame.py: .. _ref_premixed_burner_stabilized_flame: =========================================== Simulate a burner stabilized premixed flame =========================================== The *burner stabilized premixed flame* model is frequently used as a numerical tool to develop and to validate combustion mechanisms in the context of a burner stabilized flat flame. The premixed burner stabilized flat flame experiments are important because, in addition to the reaction pathways and rate parameters, they provide opportunities to learn about the impact of the transport processes on the combustion chemistry and flame structure. The premixed burner stabilized flame model calculates the temperature and the species concentrations along the burner centerline, and the results will be compared against the measurements. The burner stabilized flame model assumes that the flow is laminar and the temperature at the burner rim is constant (in order to anchor the flame). This example shows how to use the burner stabilized premixed flame model to calculate the species profiles of a C\ :sub:`2`\ H\ :sub:`4`\ -O\ :sub:`2`\ -AR mixture along the burner centerline with the measured temperature profile data. Since the transport processes are critical for flame calculations, transport data must be included in the mechanism data and preprocessed. .. GENERATED FROM PYTHON SOURCE LINES 47-49 .. code-block:: Python :dedent: 1 .. GENERATED FROM PYTHON SOURCE LINES 51-53 Import PyChemkin packages and start the logger ============================================== .. GENERATED FROM PYTHON SOURCE LINES 53-80 .. code-block:: Python from pathlib import Path import time import ansys.chemkin.core as ck # Chemkin from ansys.chemkin.core import Color from ansys.chemkin.core.inlet import Stream # external gaseous inlet from ansys.chemkin.core.logger import logger # Chemkin 1-D premixed burner-stabilized flame model (steady-state) from ansys.chemkin.core.premixedflames.premixedflame import ( BurnedStabilizedGivenTemperature as Burner, ) import matplotlib.pyplot as plt # plotting import numpy as np # number crunching # check working directory current_dir = str(Path.cwd()) logger.debug("working directory: " + current_dir) # set verbose mode ck.set_verbose(True) # set interactive mode for plotting the results # interactive = True: display plot # interactive = False: save plot as a PNG file global interactive interactive = True .. GENERATED FROM PYTHON SOURCE LINES 81-92 Create the first chemistry set ============================== The mechanism to load is the GRI 3.0 mechanism for methane combustion. This mechanism and its associated data files come with the standard Ansys Chemkin installation in the ``/reaction/data`` directory. .. note:: The transport data *must* be included and preprocessed because the transport processes, *convection and diffusion*, are important to sustain the flame structure. .. GENERATED FROM PYTHON SOURCE LINES 92-103 .. code-block:: Python # set mechanism directory (the default Chemkin mechanism data directory) data_dir = Path(ck.ansys_dir) / "reaction" / "data" mechanism_dir = data_dir # including the full file path is recommended chemfile = str(mechanism_dir / "grimech30_chem.inp") thermfile = str(mechanism_dir / "grimech30_thermo.dat") tranfile = str(mechanism_dir / "grimech30_transport.dat") # create a chemistry set based on GRI 3.0 MyGasMech = ck.Chemistry(chem=chemfile, therm=thermfile, tran=tranfile, label="GRI 3.0") .. GENERATED FROM PYTHON SOURCE LINES 104-106 Preprocess the chemistry set ============================ .. GENERATED FROM PYTHON SOURCE LINES 106-114 .. code-block:: Python # preprocess the mechanism files ierror = MyGasMech.preprocess() if ierror != 0: print("Error: Failed to preprocess the mechanism.") print(f" Error code = {ierror}.") exit() .. GENERATED FROM PYTHON SOURCE LINES 115-131 Set up the (C\ :sub:`2`\ H\ :sub:`4` + O\ :sub:`2`\ + AR ) mixture to the flat burner ===================================================================================== Instantiate a stream named ``premixed`` for the inlet gas mixture. This stream is a mixture with the addition of the inlet flow rate. You specify the inlet gas properties in the same way you set up a mixture. You can simply use a composition *"recipe"* to create the C\ :sub:`2`\ H\ :sub:`4` + O\ :sub:`2`\ + AR mixture. You use the ``mass_flowrate()`` method to assign the burner inlet mass flow rate. .. note:: By default, the burner flow area is set to unity (1.0 [cm\ :sup:`2`\ ]) because the flame models use the mass flux [g/cm\ :sup:`2`\ -sec] in the calculations instead of the flow rate [g/sec]. If the mass flow rate is used, the actual burner cross-sectional flow area must be provided by using the ``flowarea()`` stream method. .. GENERATED FROM PYTHON SOURCE LINES 131-148 .. code-block:: Python # create the fuel-air stream for the premixed flame speed calculation premixed = Stream(MyGasMech, label="premixed") # set inlet premixed stream molar composition premixed.x = [("C2H4", 0.163), ("O2", 0.237), ("AR", 0.6)] # setting inlet pressure [dynes/cm2] premixed.pressure = 1.0 * ck.P_ATM # set inlet/unburnt gas temperature [K] premixed.temperature = 300.0 # inlet temperature # set the burner outlet cross sectional flow area to unity (1 [cm2]) # because the flame models use the mass flux in the calculation instead of # the mass flow rate premixed.flowarea = 1.0 # set value for the inlet mass flow rate [g/sec] premixed.velocity = 0.0147 .. GENERATED FROM PYTHON SOURCE LINES 149-161 Instantiate the laminar flat flame burner ========================================= Set up the premixed burner stabilized flame model by using the stream representing the premixed fuel-oxidizer mixture.There are many options and parameters related to the treatment of the species boundary condition and the transport properties. All the available options and parameters are described in the *Chemkin Input* manual. .. note:: The stream parameter used to instantiate a ``Burner`` object consists of the properties of the unburned fuel-oxidizer mixture leaving the burner outlet. .. GENERATED FROM PYTHON SOURCE LINES 161-164 .. code-block:: Python flatflame = Burner(premixed, label="ethylene flame") .. GENERATED FROM PYTHON SOURCE LINES 165-171 Set up the temperature profile along the burner centerline ========================================================== Use the ``set_temperature_profile()`` method to set up the temperature profile data. The temperature profile along the burner centerline is typically obtained from the corresponding experiments. .. GENERATED FROM PYTHON SOURCE LINES 171-223 .. code-block:: Python tpro_data_points = 21 gridpoints = np.zeros(tpro_data_points, dtype=np.double) temp_data = np.zeros_like(gridpoints, dtype=np.double) gridpoints = [ 0.0, 0.01, 0.02, 0.0345643, 0.0602659, 0.100148, 0.118759, 0.135598, 0.15421, 0.179911, 0.211817, 0.233087, 0.260561, 0.293353, 0.348301, 0.436928, 0.517578, 0.7161, 0.935894, 1.16632, 1.2, ] temp_data = [ 300.0, 450.0, 600.0, 828.498, 1104.4, 1496.7, 1634.65, 1714.85, 1768.33, 1801.12, 1807.2, 1803.78, 1799.51, 1788.35, 1778.09, 1767.01, 1760.23, 1744.13, 1737.55, 1730.99, 1729.31, ] flatflame.set_temperature_profile(x=gridpoints, temp=temp_data) .. GENERATED FROM PYTHON SOURCE LINES 224-237 Set up initial mesh and grid adaption options ============================================= The premixed flame models provides several methods to set up the initial mesh. In this case, the temperature profile is given by the experimental data. The ``use_TPRO_grid()`` method lets the flame model recycle the grid points of the temperature profile as the initial mesh at the start of the calculation. The flame models would add more grid points to where they are needed as determined by the solution quality parameters specified by the ``set_solution_quality()`` method. The ``end_position`` argument is a required input as it defines the length of the calculation domain. Typically, the length of the calculation domain is between 1 to 10 [cm]. .. GENERATED FROM PYTHON SOURCE LINES 237-250 .. code-block:: Python # set the maximum total number of grid points allowed # in the calculation (optional) flatflame.set_max_grid_points(250) # define the calculation domain [cm] flatflame.end_position = 1.2 # maximum number of grid points can be added during # each grid adaption event (optional) flatflame.set_max_adaptive_points(10) # set the maximum values of the gradient and # the curvature of the solution profiles (optional) flatflame.set_solution_quality(gradient=0.1, curvature=0.1) .. GENERATED FROM PYTHON SOURCE LINES 251-265 Set transport property options =============================== Ansys Chemkin offers three methods for computing mixture properties: - **Mixture averaged** - **Multi-component** - **Constant Lewis number When the system pressure is not too low, the mixture averaged method should be adequate. The multi-component method, although it is slightly more accurate, makes the simulation time longer and is harder to converge. Using the constant Lewis number method implies that all the species would have the same transport properties. .. GENERATED FROM PYTHON SOURCE LINES 265-269 .. code-block:: Python # use the mixture averaged method to evaluate the mixture transport properties flatflame.use_mixture_averaged_transport() .. GENERATED FROM PYTHON SOURCE LINES 270-275 Set species composition boundary option ======================================= There two types of boundary condition treatments for the species composition available from the premixed flame models: ``comp`` and ``flux``. You can find the descriptions of these two treatments in the *Chemkin Input* manual. .. GENERATED FROM PYTHON SOURCE LINES 275-281 .. code-block:: Python # specify the species composition boundary treatment ('comp' or 'flux') # use 'flux' to ensure that the "net" species mass fluxes are zero at # the burner outlet. flatflame.set_species_boundary_types(mode="flux") .. GENERATED FROM PYTHON SOURCE LINES 282-289 Set solver parameters ===================== The steady-state solver parameters for the premixed flame model are optional because all the solver parameters have their own default values. Change the solver parameters when the premixed flame simulation does not converge with the default settings. .. GENERATED FROM PYTHON SOURCE LINES 289-295 .. code-block:: Python # reset the tolerances in the steady-state solver (optional) flatflame.steady_state_tolerances = (1.0e-9, 1.0e-4) # reset the gas species floor value in the steady-state solver (optional) flatflame.set_species_floor(-1.0e-3) .. GENERATED FROM PYTHON SOURCE LINES 296-305 Run the premixed flame calculation ================================== Use the ``run()`` method to run the freely propagating premixed flame (flame speed) model. This method solves the reactors one by one in the order that they are added to the network. After the premixed flame calculation concludes successfully, use the ``process_solution()`` method to postprocess the solutions. You can create other property profiles by looping through the solution streams with proper mixture methods. .. GENERATED FROM PYTHON SOURCE LINES 305-318 .. code-block:: Python # set the start wall time start_time = time.time() status = flatflame.run() if status != 0: print(Color.RED + "Failed to solve the reactor network." + Color.END) exit() # get the number of solution grid points solutionpoints = flatflame.get_solution_size() print(f"Number of solution points = {solutionpoints}.") .. GENERATED FROM PYTHON SOURCE LINES 319-328 Refine the solution profiles =============================== When the simulation is hard to converge in one go, you can use a number of continuations to gradually get to the solution of the intended condition. For example, you can get to the solution of a very fuel-lean mixture by starting with a slightly fuel-rich mixture flame and use the ``continuation()`` method to run the more difficult fuel-lean case from the converged solution. .. GENERATED FROM PYTHON SOURCE LINES 328-341 .. code-block:: Python # tightening the convergence criteria flatflame.set_solution_quality(gradient=0.05, curvature=0.1) # restart the flame simulation by continuation flatflame.continuation() # compute the total runtime runtime = time.time() - start_time print() print(f"Total simulation duration: {runtime} [sec].") print() .. GENERATED FROM PYTHON SOURCE LINES 342-369 Postprocess the premixed flame results ====================================== The postprocessing step parses the solution and packages the solution values at each time point into a mixture. There are two ways to access the solution profiles: - The raw solution profiles (value as a function of distance) are available for distance, temperature, pressure, volume, and species mass fractions. -The streams permit the use of all property and rate utilities to extract information such as viscosity, density, and mole fractions. You can use the ``get_solution_variable_profile()`` method to get the raw solution profiles. The solution streams are accessed using either the ``get_solution_stream_at_grid()`` method for the solution stream at the given grid point or the ``get_solution_stream()`` method for the solution stream at the given location. (In this case, the stream is constructed by interpolation.) .. note:: - Use the ``get_solution_size()`` method to get the number of grid points in the solution profiles before creating the arrays. - The ``mass_flowrate`` from the solution streams is actually the *mass flux* [g/cm\ :sup:`2`\ -sec]. It can used to derive the velocity at the corresponding location by dividing it by the local gas mixture density [g/cm\ :sup:`3`\ ]. .. GENERATED FROM PYTHON SOURCE LINES 369-395 .. code-block:: Python # postprocess the solutions flatflame.process_solution() # get the number of solution grid points solutionpoints = flatflame.get_solution_size() print(f"Number of final solution points = {solutionpoints}.") # get the grid profile mesh = flatflame.get_solution_variable_profile("distance") # get the temperature profile tempprofile = flatflame.get_solution_variable_profile("temperature") # get OH mass fraction profile oh_profile = flatflame.get_solution_variable_profile("OH") # create arrays for mixture conductivity and mixture-pecific heat capacity cp_profile = np.zeros_like(mesh, dtype=np.double) condprofile = np.zeros_like(mesh, dtype=np.double) # loop over all solution grid points for i in range(solutionpoints): # get the stream at the grid point solutionstream = flatflame.get_solution_stream_at_grid(grid_index=i) # get mixture-specific heat capacity profile [erg/mole-K] cp_profile[i] = solutionstream.cpbl() / ck.ERGS_PER_JOULE * 1.0e-3 # get thermal conductivity profile [ergs/cm-K-sec] condprofile[i] = solutionstream.mixture_conductivity() * 1.0e-5 .. GENERATED FROM PYTHON SOURCE LINES 396-404 Plot the premixed flame solution profiles ========================================= Plot the solution profiles of the premixed flame. .. note :: You can get profiles of the thermodynamic and the transport properties by applying ``Mixture`` utility methods to the solution stream. .. GENERATED FROM PYTHON SOURCE LINES 404-424 .. code-block:: Python plt.subplots(2, 2, sharex="col", figsize=(12, 6)) plt.subplot(221) plt.plot(mesh, tempprofile, "r-") plt.ylabel("Temperature [K]") plt.subplot(222) plt.plot(mesh, cp_profile, "b-") plt.ylabel("Mixture Cp [kJ/mole]") plt.subplot(223) plt.plot(mesh, oh_profile, "g-") plt.xlabel("Distance [cm]") plt.ylabel("OH Mass Fraction") plt.subplot(224) plt.plot(mesh, condprofile, "m-") plt.xlabel("Distance [cm]") plt.ylabel("Mixture conductivity [W/m-K]") # plot results if interactive: plt.show() else: plt.savefig("plot_premixed_burner_stabilised_flame.png", bbox_inches="tight") .. _sphx_glr_download_examples_premixed_flame_premixedburnerflame.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: premixedburnerflame.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: premixedburnerflame.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: premixedburnerflame.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_