.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "examples/shock_tube/ZND.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_shock_tube_ZND.py: .. _ref_shock_ZND_reactor: ========================================================== Perform ZND analysis of a combustible hydrogen mixture ========================================================== The ZND (Zeldovich-von Neumann-Deoring) model is commonly applied to study the evolution of the gas mixture behind a detonation wave. The ZND model is a transient reactor, and the solutions describe the state of the gas mixture (particle) as it moving away from the detonation front in the shock tube reactor. Use the ``ZNDCalculator()`` method to create a ZND shock tube reactor. The shock tube reactor models, such as the IncidentShcok, the ReflectedShock and the ZNDCalculator models, are initiated by a stream, which is simply a mixture with the addition of the shock wave velocity. You already know how to create a stream if you know how to create a mixture. You can specify the shock wave velocity using the combination of the ``velocity`` method of the initial gas stream and the ``location`` parameter when you instantiate the ``incidentShock`` or the ``ReflectedShock`` object. This example shows how to use the Chemkin ZND shock tube model to study the gas mixture evolution behind an incident detonation wave front. The speed of the incident shock wave is estimated by the ZND model automatically by finding the stable detonation wave speed corresponding to the given gas mixture before the incident shock front. Once the solution is obtained, you can extract the induction zone length behind the wave front and utilize this information to gain insights about the characteristic size of the cellular structure in multi-dimensional flow as well as the stability of the cellular structure. .. GENERATED FROM PYTHON SOURCE LINES 54-56 .. code-block:: Python :dedent: 1 .. GENERATED FROM PYTHON SOURCE LINES 58-60 Import PyChemkin packages and start the logger ============================================== .. GENERATED FROM PYTHON SOURCE LINES 60-84 .. code-block:: Python from pathlib import Path import time import ansys.chemkin.core as ck # Chemkin from ansys.chemkin.core import Color # chemkin plug flow reactor model from ansys.chemkin.core.shock.shocktubereactors import ZNDCalculator as Znd from ansys.chemkin.core.inlet import Stream from ansys.chemkin.core.logger import logger from ansys.chemkin.core.utilities import find_file 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 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 85-90 Create a chemistry set ====================== The mechanism used here is the MFL 2021 hydrogen mechanism. The mechanism comes with the standard Ansys Chemkin installation in the ``/reaction/data/ModelFuelLibrary/Skeletal`` directory. .. GENERATED FROM PYTHON SOURCE LINES 90-100 .. code-block:: Python # set mechanism directory (the default Chemkin mechanism data directory) data_dir = Path(ck.ansys_dir) / "reaction" / "data" / "ModelFuelLibrary" / "Skeletal" mechanism_dir = data_dir # create a chemistry set based on the MFL 2021 hydrogen mechanism MyGasMech = ck.Chemistry(label="hydrogen") # set mechanism input files # including the full file path is recommended MyGasMech.chemfile = find_file(mechanism_dir, "Hydrogen_chem_MFL", "inp") .. GENERATED FROM PYTHON SOURCE LINES 101-103 Preprocess the hydrogen chemistry set ===================================== .. GENERATED FROM PYTHON SOURCE LINES 103-107 .. code-block:: Python # preprocess the mechanism files ierror = MyGasMech.preprocess() .. GENERATED FROM PYTHON SOURCE LINES 108-119 Instantiate and set up the stream ================================= Create a combustible gas stream by assigning the mole fractions of the species. Here, several gas streams are created with different recipes consisting of H\ :sub:`2`\ , O\ :sub:`2` and N\ :sub:`2`\ . You can pick any one of the streams to instantiate the ``ZNDCalculator``. You can compare the "induction lengths" by different streams to see how the combustion intensity (reversely proportion to the amount of N\ :sub:`2` dilution) impacts the size of the induction zone behind the detonation wave front. .. GENERATED FROM PYTHON SOURCE LINES 119-146 .. code-block:: Python stream_a = Stream(MyGasMech) # initial gas state before the incident shock front # 1 [atm] stream_a.pressure = ck.P_ATM # 300 [K] stream_a.temperature = 300.0 # 50% hydrogen + 50% oxygen by volume stream_a.x = [("h2", 1.0), ("o2", 1.0)] # stream_b = Stream(MyGasMech) # a diluted initial gas state before the incident shock front # 1 [atm] stream_b.pressure = ck.P_ATM # 300 [K] stream_b.temperature = 300.0 # the 50% hydrogen + 50% oxygen mixture diluted by 40% nitrogen by volume stream_b.x = [("h2", 0.3), ("o2", 0.3), ("n2", 0.4)] # stream_c = Stream(MyGasMech) # a diluted initial gas state before the incident shock front # 1 [atm] stream_c.pressure = ck.P_ATM # 300 [K] stream_c.temperature = 300.0 # the 50% hydrogen + 50% oxygen mixture diluted by 40% nitrogen by volume stream_c.x = [("h2", 0.2), ("o2", 0.2), ("n2", 0.6)] .. GENERATED FROM PYTHON SOURCE LINES 147-153 Create the shock tube reactor object ==================================== Use the ``ZNDCalculator()`` method to create an incident shock reactor. The required input parameter is the stream representing the state of the initial gas mixture before the incident shock front. In this case, ``stream_a`` is used to initialize the ZND model ``ZNDIncident``. .. GENERATED FROM PYTHON SOURCE LINES 153-156 .. code-block:: Python ZNDIncident = Znd(stream_c, label="ZND") .. GENERATED FROM PYTHON SOURCE LINES 157-163 Set up additional reactor model parameters ========================================== For the ZND calculator model, the required reactor parameters is the total simulation time [sec]. The initial gas mixture conditions are defined by the stream when the ``ZNDIncident`` is instantiated. .. GENERATED FROM PYTHON SOURCE LINES 163-167 .. code-block:: Python # set total simulation time (particle time) [sec] ZNDIncident.time = 3.0e-6 .. GENERATED FROM PYTHON SOURCE LINES 168-172 Set solver controls =================== You can overwrite the default solver controls by using solver related methods, for example, ``tolerances``. .. GENERATED FROM PYTHON SOURCE LINES 172-176 .. code-block:: Python # tolerances are given in tuple: (absolute tolerance, relative tolerance) ZNDIncident.tolerances = (1.0e-10, 1.0e-6) .. GENERATED FROM PYTHON SOURCE LINES 177-185 Run the ZND analysis ==================================================== Use the ``run()`` method to start the ZND analysis. .. note :: You can use two ``time`` calls (one before the run and one after the run) to get the simulation run time (wall time). .. GENERATED FROM PYTHON SOURCE LINES 185-201 .. code-block:: Python # set the start wall time start_time = time.time() # run the ZND model runstatus = ZNDIncident.run() # compute the total runtime runtime = time.time() - start_time # check run status if runstatus != 0: # Run failed. print(Color.RED + ">>> Run failed. <<<", end=Color.END) exit() # run succeeded. print(Color.GREEN + ">>> Run completed. <<<", end=Color.END) print(f"Total simulation duration: {runtime * 1.0e3} [msec]") .. GENERATED FROM PYTHON SOURCE LINES 202-224 Postprocess the solution ======================== 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 time) are available for distance, temperature, pressure, velocity, density, and species mass fractions. - The mixtures permit the use of all property and rate utilities to extract information such as viscosity, density, total thermicity, speed of sound, Mach number, and mole fractions. You can use the ``get_solution_variable_profile()`` method to get the raw solution profiles. You can get solution mixtures using either the ``get_solution_stream_at_index()`` method for the solution mixture at the given saved location or the ``get_solution_stream()`` method for the solution mixture at the given distance. (In this case, the mixture is constructed by interpolation.) You can get ZND analysis information about the induction zone length by using the ``get_inductionlength_size()`` and the ``get_induction_lengths()`` methods. The induction zone length can be used to derive the characteristic cell size and the stability of the multi-dimensional cellular wave structure. .. GENERATED FROM PYTHON SOURCE LINES 224-270 .. code-block:: Python # postprocess the solution profiles ZNDIncident.process_solution() # get the number of solution time points solutionpoints = ZNDIncident.get_solution_size() print(f"number of solution points = {solutionpoints}") # get information about the induction length numb_induct_length = ZNDIncident.get_inductionlength_size() print(f"number of induction length = {numb_induct_length}") if numb_induct_length > 0: induct_legth, sigmamax = ZNDIncident.get_induction_lengths(numb_induct_length) for i in range(numb_induct_length): print(f"Induction length # {i + 1}:") print(f" Induction length = {induct_legth[i] * 1.0e1} [mm].") print(f" Local max thermicity = {sigmamax[i]} [1/sec].\n") # estimated detonation wave cell structure parameters cell_width, chi = ZNDIncident.calculate_cell_width_ng() print(f"Instability parameter Chi = {chi}") # stable = Chi > 1 print(f"Estimated cell size = {cell_width} [cm].") # get the grid profile [cm] xprofile = ZNDIncident.get_solution_variable_profile("distance") # get the temperature profile [K] tempprofile = ZNDIncident.get_solution_variable_profile("temperature") # get the pressure profile [dynes/cm2] pressprofile = ZNDIncident.get_solution_variable_profile("pressure") # get the velocity profile [cm/sec] velprofile = ZNDIncident.get_solution_variable_profile("velocity") # get the total thermiocity profile [1/sec] sigmaprofile = ZNDIncident.get_solution_variable_profile("thermicity") # create arrays for the gas Mach number profile machprofile = np.zeros_like(xprofile, dtype=np.double) # loop over all solution time points for i in range(solutionpoints): # get the mixture at the time point solutionmixture = ZNDIncident.get_solution_stream_at_index(solution_index=i) # gas speed of sound [cm/sec] soundspeed = solutionmixture.sound_speed() # gas Mach number machprofile[i] = velprofile[i] / soundspeed # convert pressure from [dynes/cm2] to [bar] pressprofile[i] /= 1.0e6 .. GENERATED FROM PYTHON SOURCE LINES 271-276 Plot the solution profiles ========================== Plot the temperature, pressure, total thermicity, and the gas Mach number profiles as a function of distance behind the wave front. .. GENERATED FROM PYTHON SOURCE LINES 276-302 .. code-block:: Python plt.subplots(2, 2, sharex="col", figsize=(12, 6)) plt.suptitle("ZND Analysis", fontsize=16) plt.subplot(221) plt.plot(xprofile, tempprofile, "r-") plt.ylabel("Temperature [K]") plt.subplot(222) plt.plot(xprofile, pressprofile, "b-") plt.ylabel("Pressure [bar]") plt.subplot(223) plt.plot(xprofile, machprofile, "g-") plt.xlabel("distance behind shock [cm]") plt.ylabel("Mach Number [-]") plt.subplot(224) plt.plot(xprofile, sigmaprofile, "m-") plt.xlabel("distance behind shock [cm]") plt.ylabel("Total Thermicity [1/sec]") # clean up ck.done() # plot results if interactive: plt.show() else: plt.savefig("plot_shock_ZND_reactor.png", bbox_inches="tight") .. _sphx_glr_download_examples_shock_tube_ZND.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: ZND.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: ZND.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: ZND.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_