Chemical kineticsExperimental dataAutoignitionData standard

Fundamental experimental measurements of quantities such as ignition delay times, laminar flame
speeds, and species profiles (among others) serve important roles in understanding fuel
chemistry and validating chemical kinetic models. However, despite both the importance and
abundance of such information in the literature, the community lacks a widely adopted standard
format for this data. This impedes both sharing and wide use by the community. Here we introduce
a new chemical kinetics experimental data format, ChemKED, and the related Python-based package
for validating and working with ChemKED-formatted files called PyKED. We also review past and
related efforts, and motivate the need for a new solution. ChemKED currently supports the
representation of autoignition delay time measurements from shock tubes and rapid compression
machines. ChemKED-formatted files contain all of the information needed to simulate experimental
data points, including the uncertainty of the data. ChemKED is based on the YAML data
serialization language, and is intended as a human- and machine-readable standard for easy
creation and automated use. Development of ChemKED and PyKED occurs openly on GitHub under the
BSD 3-clause license, and contributions from the community are welcome. Plans for future
development include support for experimental data from laminar flame, jet stirred reactor, and
speciation measurements.

§ INTRODUCTION

Fundamental combustion experiments provide vital data for understanding fuel
chemistry and validating chemical kinetic models. Important measured quantities
include autoignition delay times, laminar flame speeds, and species profiles,
among others. However, despite both the importance and abundance of such
information in the literature, the combustionchemical kinetics community
lacks an accepted, commonly used standard for recording and sharing data from
fundamental combustion experiments.[Interestingly, this contrasts the
situation for chemical kinetic models, where the CHEMKIN Kee:1996ck
format dominates. Competing standards such as the
Cantera Cantera:2.3.0 CTI format or
FlameMaster FlameMaster:ref lag behind considerably,
although use of the former continually grows due to Cantera's open availability.

Instead, such data is typically found in under-documented comma-separated value
(CSV) files and Excel spreadsheets, or contained in PDF tables rather than as
supplementary material associated with a paper. In the worst case, data is only
available in figures and must be digitized by the use of software such as
WebPlotDigitizer WebPlotDigitizer. These practices limit wide use
of the valuable, extensive experimental data available in the literature.
Frenklach:2007bm further explained the benefits of standardized,
widely available data for combustion. In brief, much of fundamental
combustionchemical kinetics research drives towards the ultimate goal of
developing predictive kinetic models—and ultimately this depends on a
community infrastructure for data and methods.

The combustion community has not yet widely adopted a standard format for
experimental data, but some researchers and groups have proposed solutions to
this problem. Most notably, Frenklach developed the PrIMe (Process
Informatics Model) data
format Frenklach:2007bm,You:2011hy and an associated online database,
the PrIMe Data Warehouse (available at <http://primekinetics.org>).
PrIMe files encode fundamental
combustion experimental data, along with kinetic models and calculated
quantities, using the eXtensible Markup Language (XML) standard.

PrIMe Frenklach:2007bm,You:2011hy
has a number of features that make
it a strong standardization format, but it suffers from several flaws that
prevent wide adoption. First, the PrIMe standard does not require or support all
the information needed to simulate an experiment, including a machine-readable
definition of ignition or a standard way to express detailed facility-specific
effects necessary to properly simulate certain experiments. Second, PrIMe uses
internal identifiers for bibliographic references and
speciesreactions, rather than standard identifiers (e.g., DOIs for
scholarly products, InCHI or SMILES for species). This limits the usability of PrIMe files outside
the PrIMe ecosystem.

Third, XML is intended to be a machine-readable markup language rather than a data format.
As a general-purpose document markup language, XML can represent detailed
information about a dataset, but implementing this detail requires XML-formatted
files to be much more verbose than files formatted with a language focused
only on representing data structures. The verbosity inherent in the XML format
limits the human readability of database files constructed in XML and presents a barrier to
creating and working with them.

Finally, the closed and opaque natures of the PrIMe standard and associated Data Warehouse limit
contributions and community development of the PrIMe standard and compatible data files and tools.
In this sense, we mean “closed” as a contrast to open source, open science, and open data, as
defined by the Open Knowledge Institute <cit.> or the Open Source
Initiative <cit.>. Although most commonly applied to software, the distinction between
open and closed is becoming increasingly important in science and research. In brief, the Open
Knowledge Institute defines open knowledge as “free to access, use, modify, and
share…— subject, at most, to measures that preserve provenance and
openness” <cit.>, while the Open Source Institute focuses on software and declares
that a project must provide free and unrestricted access to the source code, allow free
redistribution, permit derived works, and not discriminate
against any people or areas of work, along with a few other criteria <cit.>.

More recently, Varga and coworkers Varga2015a,Varga2017 developed the
ReSpecTh standard (available at
which builds on the PrIMe format. ReSpecTh adds important
features that make files better standalone representations of experimental
data—i.e., more informative by themselves rather than in concert with a larger
system. For example, where PrIMe uses internal bibliographic references,
ReSpecTh adds a field for typical bibliographic data, including the DOI of
the cited article. The ReSpecTh standard also
provides machine-readable formats for describing ignition experiments, including
a field for the definition of autoignition and the ability to specify
facility-specific effects. It can also describe speciation measurements in
perfectly stirred reactors, flow reactors, and burner-stabilized flames, as well as
burning velocity data. To support this, ReSpecTh files allow the specification of species by
standard identifiers, including InChI or SMILES. Finally, each ReSpecTh file
has a unique DOI and URL assigned to it.

However, ReSpecTh experimental files are another
XML-based format, and, as such, suffer from the same readability issues as PrIMe.
Moreover, potential users must register using a valid institutional email address
to access the growing database.

Nonetheless, databases of fundamental combustion experiments
have proved quite useful. For instance, Olm and colleagues used their
ReSpecTh-based database to quantify the performance of literature
hydrogen Olm:2014gn and syngas Olm:2015ch kinetic models,
and more recently develop improved models for hydrogen Varga:2015hy,
hydrogensyngas Varga:2016gj,
methanolformaldehyde Olm:2017a,
and ethanol Olm:2016et. In all six cases, they converted numerous
experimental datasets from the literature into the ReSpecTh standard.
Their database currently contains 93326
experimental data points in 1396 ReSpecTh XML files respecth.

Despite the development of these standards, limited examples exist in the
literature of open data sharing using the formats. To the best
of our knowledge, the largest such publicly available database is hosted by
the Clean Combustion Research Center at King Abdullah University of Science and
Technology (KAUST): CloudFlame (available at <https://cloudflame.kaust.edu.sa>).
Started in 2013 Goteng:2013cf,Goteng:2014,ReynoChiasson:2015, CloudFlame
serves as an openly accessible database for experimental data, available in a standard
CSV format, and also provides a cloud infrastructure for running simulations
based on stored models and data. While an admirable and useful effort,
CloudFlame, like ReSpecTh and PrIMe, is a closed system controlled by a single
institution rather than by the community at large.

We therefore believe there remains a need for an open, community-focused and
developed, combustionchemical kinetics data format. In this work, we
present a new, open-source, human- and machine-readable data standard for
fundamental combustion experiments, , and offer tools for easily working
with data encoded in this format. Niemeyer recently introduced an initial
version of the  format Niemeyer:2016wf, and in this work we
further formalize and develop the standard. We also discuss a related Python
software tool for validating and working with  files: . Our
motivations resemble those of the PrIMe and ReSpecTh teams: the  project
will enable easy sharing and use of fundamental combustion data, for the
(primary) purposes of developing and validating predictive chemical kinetic
models. However, we make usability a major design focus, and plan to share all
data and software openly to cultivate a community of user-contributors.

§ OVERVIEW OF CHEMKED FORMAT

This section provides an introduction to the current version of the  database format, v0.3.0,
which represents a functional standard for documenting autoignition measurements in shock tubes and
rapid compression machines. Here we describe the fields that a user creating a  file is likely
to use. There are several fields that are used internally in the schema that are not described here,
but can be found in the online documentation for the
schema.[<https://pr-omethe-us.github.io/PyKED/schema-docs.html>] In
Section <ref>, we provide examples of  files and representative use cases. We
indicate |yaml| keywords or values using text with gray background, and |Python| code
using text with a yellow background.

files use the YAML data serialization format yaml:1.2. This
format offers the advantages of being relatively easy for humans to read and write,
encoded in plain text (ASCII or UTF-8 format), and
having parsers in most common programming languages, including Python, C++, Java,
Perl, MATLAB, and many others. The YAML syntax is quite simple: the basic file
structure consists of mappings, delimited by a colon. The key for the mapping is
on the left of the colon, and the value on the right can be a single value,
a sequence of values, a nested mapping, or some combination of these:

key1: value  # Single-value mapping
key2:  # Sequence format
- value
- value
key3:  # Nested mapping
key4: 0
key5:  # Sequence of mappings
- key-s1: 0
key-s2: value
- key-s2: value
key-s1: 0

The |value| can be a string, integer, or floating-point number. We designed
the  format to include all information necessary to simulate a
given experiment. A  file is generally broken into two main sections: a section containing the
“meta” information about the experiment and the  file itself, and a section containing the
actual experimental data to be encoded.

§.§ Apparatus information and metadata

We will first describe the fields in the “meta” section.
This section uses a mapping that is called the |author| mapping in the schema. As this mapping
is used for any fields that specify an author throughout the schema, we describe it first.
The |author| mapping contains the following fields:

* |name| (required, string): The author's full name

* |ORCID| (optional, string): the author's unique ORCID code

In general, the meta information describes the experimental facility and type of experiment, the
reference from which the data was taken, and the author of the  file itself. For each of the
keys below, we have indicated whether the key is required or optional, and the type of value
associated with the key. The keys in the meta section include:

* |apparatus| (required, mapping): Information about the specific experimental
apparatus used to conduct the experiment. The fields in this mapping are:

* |facility| (optional, string): A unique name or identifier for the apparatus,
if the institution has several that are similar

* |institution| (optional, string): The institution where the experimental
apparatus was located when the experiments were performed

* |kind| (required, string): The type of apparatus used to
perform the experiment. Currently, only |shock tube| or
|rapid compression machine| are supported.

* |chemked-version| (required, string): The version of the
schema to which this file conforms

* |experiment-type| (required, string): Currently, only
|ignition delay| is supported

* |file-author| (required, |author|-type mapping): The
author of the  file

* |file-version| (required, integer): The version of the

* |reference| (required, mapping): The reference information for
the published article associated with the data in the file. The fields in this
mapping are:

* |authors| (required, sequence): A sequence of |author|

* |detail| (optional, string): A description of from where the
data originated (e.g., figure or table number)

* |doi| (optional, string): The article DOI

* |journal| (optional, string): The name of the publishing

* |pages| (optional, string): The article pages

* |volume| (optional, integer): The journal volume number

* |year| (required, integer): The year of publication

Several of these keys bear further discussion. The |chemked-version| is present in the file so
that PyKED can determine whether the file conforms to a supported version of the schema. Although
quite similar in name, the |file-version| represents the number of versions that have been
created of the current file; it is an integer that should be incremented whenever changes are made
to the file. Finally, the |reference| mapping is required in every file, even those that
represent data that has not been published. However, the |reference| mapping only requires the
|authors| sequence and the |year|, so that  files can be used internally within
research groups to represent unpublished data prior to publication.

§.§ Ignition delay experimental data

The second section of the file encodes the experimental data as a sequence of mappings. The
top-level key for the sequence is called |datapoints|. For the current version of the
schema, only autoignition delay experiments are supported. The following information
is required in each element of the sequence:

* |temperature| (required, sequence): The temperature of the
experiment, with units and optionally uncertainty

* |ignition-delay| (required, sequence): The ignition delay of the
experiment, with units and optionally uncertainty

* |pressure| (required, sequence): The pressure of the experiment,
with units and optionally uncertainty

* |first-stage-ignition-delay| (optional, sequence): If two stages of ignition are
present in the experiment, this is the length of the first stage of ignition, and the
|ignition-delay| is then the overall ignition delay

* |equivalence-ratio| (optional, float): The value of the equivalence ratio

* |composition| (required, mapping): The composition of the
mixture in the experiment, described via a nested mapping with the fields:

* |kind| (required, string): one of |mole fraction|, |mole percent|, or |mass fraction|

* |species|: sequence of mappings, with the fields:

* |species-name| (required, string): The name of the species

* |amount| (required, sequence): The mole fraction or percent, or the mass fraction, optionally with uncertainty

* |InChI|, |SMILES|, or |atomic-composition|
(required, string or sequence): The InChI
or SMILES string representing the molecule, or its atomic
composition as a sequence

* |ignition-type| (required, mapping): The method used to detect
ignition in the experiments. The required fields are

* |type| (required, string): How ignition delay was
measured; one of |d/dt max| (indicates the ignition point was
found at the maximum of the time derivative of the |target|),
|max| or |min| (indicates the ignition point was at the
maximum or minimum of the |target|), |1/2 max| (
indicates the half-maximum point of |target|), or |d/dt max extrapolated|
(indicates the maximum slope of the target extrapolated to the baseline)

* |target| (required, string): The target for the ignition
|type| measurement; one of |temperature|, |pressure|,
|OH|, |OH*|, |CH|, or |CH*|

Each of the
quantities in an element must be specified with units. This should be done as a
single string associated with the first element of the sequence. The units of
the quantity are validated to ensure appropriate dimensionality
for the quantity. In addition, each of the quantities in an element can
optionally be assigned an uncertainty. This uncertainty can be either absolute
or relative, and is specified as an element of the sequence of the associated key.
For example, the absolute uncertainty of the temperature and the relative
uncertainty of the ignition delay might be specified as:

- temperature:
- 1100 kelvin
- uncertainty-type: absolute
uncertainty: 10 kelvin
- 10 us
- uncertainty-type: relative
uncertainty: 0.1

Frequently, experimental series hold certain properties constant, such as initial mixture
composition or pressure, and use the same method to detect ignition delay.  files support a
|common-properties| convenience section where these common details may be defined once, and
referenced in each element of the |datapoints| sequence. This block uses the ability of YAML
files to define an anchor with the |   | symbol and refer to that section later with the
|*| symbol:

composition:    comp
kind: mole fraction
ignition-type:    ign
- composition: *comp
ignition-type: *ign
- 1000 kelvin

The |common-properties| section is not required, but can save space and
help avoid errors when several data points share some common values. However, even if
properties are specified in the |common-properties| section, they must also be
explicitly specified and referenced in the |datapoints| section for each data point,
as seen in the previous code.

§.§.§ Shock tube experiments

There is one additional key that can be used to describe the facility-specific effects during a
shock tube experiment:

* |pressure-rise| (optional, sequence): The pressure rise in the driven section after
the passage of the reflected shock, in dimensions of inverse time. Must include units and,
optionally, uncertainty

§.§.§ Rapid compression machine experiments

Rapid compression machine experiments typically report several additional pieces of information in
addition to the ignition delay. As for shock tube experiments, these describe some of the
facility-specific effects during an experiment. The keys to describe this information are:

* |volume-history| (optional, mapping): Specify the volume history of the reaction
chamber as a function of time during a rapid compression machine experiment. The fields in this
mapping are:

* |volume| (required, mapping): A mapping describing the volume in the history[Future versions
of  will support specifying additional time histories for rapid compression machine and shock tube
experiments (e.g., pressure, volume, light emission, OH emission). These will follow the specification format given for volume.]
The fields in this mapping are:

* |units| (required, string): the units of the volume, with dimensions length

* |column| (required, integer): the zero-based index of the column storing the
volume information in the |values| array (e.g., 0 or 1)

* |time| (required, mapping): A mapping describing the time in the history.
The fields in this mapping are:

* |units| (required, string): the units of the time

* |column| (required, integer): the zero-based index of the column storing the
time information in the |values| array (e.g., 0 or 1)

* |values| (required, sequence): A sequence of time-volume pairs describing the values
of the volume at different times

* |compressed-temperature| (optional, sequence): The estimated temperature at the end
of the compression stroke

* |compression-time| (optional, sequence): The time taken during the compression

* |compressed-pressure| (optional, sequence): The measured pressure at the end of the
compression stroke

§.§ Public database of  files

We have begun building an open repository of  files, available online at
We welcome submissions from the community; these can be made via the standard pull request
on GitHub. The authors also encourage questions and problems to be submitted either via
email or as issues on GitHub. In particular, researchers interested in converters for
internal data formats to the  format are encouraged to reach out;
the  package (described in more detail in Sec. <ref>)
currently provides converters to and from the ReSpecTh format Varga2017.
While we plan to continue growing this database—and hope for submissions from
the community—others can freely download files, or in fact copy (“fork” in GitHub
parlance) the entire database for their own purposes.

§ PYKED ARCHITECTURE

is a Python package that provides the reference implementation
of the interface to  files PyKED.  reads  files, validates
their structure and content, and allows the user to interact with the data contained
in the  file.

provides the basic user interface to a  file through the
|ChemKED| class. The |ChemKED| class constructor takes the name
of a  file or a Python dictionary containing the contents of a  file
as its argument. When the file or dictionary is loaded,  validates its
format and contents using the Python package Cerberus cerberus. The
schema used for validation of the  files is available publicly in the
directory of the PyKED source code
The schema comprises multiple YAML files to ease its extension to describe other
experimental measurements.

The fields of the  file are stored as instance attributes of the
|ChemKED| class. The following attributes are available:

* |chemked_version|, |file_version|, |file_author|,
|experiment_type|: Store the “meta” values from the  file

* |reference|: Instance of a |namedtuple| containing all
the information from the literature reference associated with the data

* |apparatus|: Instance of a |namedtuple| containing all
the information about the apparatus used to perform the experiment

* |datapoints|: A Python |list| of |DataPoint| instances

The |DataPoint| class stores the information associated with a single data
point in the  file (i.e., a single element of the |datapoints|
sequence). Similar to the |ChemKED| class,
the |DataPoint| stores information as instance attributes:

* |equivalence_ratio|: The value of the equivalence ratio, if
present. For informational purposes only—no validation is done of the

* |composition|: A list of dictionaries of the species and their
respective amounts. The values are validated so that |mole percent|,
|mole fraction|, or |mass fraction| cannot be mixed for a single
data point, and so that the sum of the values is approximately 1.0, or
100.0 for |mole percent|.

* |composition_type|: A string indicating the type of composition
information for the data point—one of |'mole percent'|,
|'mole fraction'|, or |'mass fraction'|

* |ignition_type|: A dictionary specifying the method of the
measurement of ignition delay

* |volume_history|: If the |volume-history| of an RCM
experiment is provided in the  file, it is stored in this attribute as
a |namedtuple|, and the actual values are stored in NumPy arrays

Other instance attributes are stored as instances of the |Quantity| class from the
Pint Grecco2016 package, possibly with an associated uncertainty. These include the
|ignition_delay|, |temperature|, |pressure|, |pressure_rise|,
|compression_time|, |compressed_temperature|, and |compressed_pressure|
attributes, each of which represents the similarly-named field in the  schema.

The |DataPoint| class defines two instance methods:
|get_cantera_mole_fraction()| and |get_cantera_mass_fraction()|.
These methods output the composition of the reactant mixture to a
format that can be used to set the composition of a
Cantera |Solution| Cantera:2.3.0.
The |composition| specification does not contain the molecular
weights of the components, so conversion between mole fractions and mass
fractions is not currently possible. (Future versions of  may support this
feature via, e.g., online lookup of species using their InChISMILES

The |ChemKED| class defines three instance methods:
|get_dataframe()|, |write_file()|, and |convert_to_ReSpecTh()|.
The |get_dataframe()| method returns an instance of a
Pandas |DataFrame| pandas that contains the information in the
list of |DataPoint|s. The user can specify the columns included in the
|DataFrame| by passing a list of column names to the
|output_columns| argument of the |get_dataframe()| method. The
possible columns are not case-sensitive and are:

* |'Temperature'|

* |'Pressure'|

* |'Ignition Delay'|

* |'Composition'|

* |'Equivalence Ratio'|

* |'Reference'|

* |'Apparatus'|

* |'Experiment Type'|

* |'File Author'|

* |'File Version'|

* |'ChemKED Version'|

In addition, specific fields from the |`Reference'| and |`Apparatus'|
columns can be included by specifying the name after a colon. These options

* |'Reference:Volume'|

* |'Reference:Journal'|

* |'Reference:DOI'|

* |'Reference:Authors'|

* |'Reference:Detail'|

* |'Reference:Year'|

* |'Reference:Pages'|

* |'Apparatus:Kind'|

* |'Apparatus:Facility'|

* |'Apparatus:Institution'|

Only the first author is included in the |DataFrame| when |Reference| or
|Reference:Authors| is selected because the whole author list may be
quite long.

The |write_file()| method writes a new  YAML file based on the instance attributes
of the class, while |convert_to_ReSpecTh()| converts the |ChemKED|
instance to a ReSpecTh XML file. In the latter case, some information may be lost or the conversion
may not be possible, as  files support some data that ReSpecTh files do not support. We note
that the reverse is also true: not all ReSpecTh files may be
equivalently converted to  files because not
all of the data that can be stored in a ReSpecTh format is (currently) supported by the  format.

PyKED relies on well-established scientific Python software tools.
These include NumPy vanderWalt:2011np and Pandas pandas,McKinney2010
for array manipulation, Pint Grecco2016 for interpreting and converting
between units, PyYAML pyyaml for parsing YAML
files, and Cerberus for validating  files cerberus.
Furthermore,  includes extensive unit, integration, and functional tests
that ensure all aspects of the software operate as intended; others have pointed
out the importance of automated testing in scientific software Wilson:bestpractices.
relies on pytest pytest:3.0.1 for automated testing, and currently has
100% line and branch coverage for all executable code in the repository. This
means that the tests execute every line of code at least once, and evaluate
every branch statement (e.g., if-then-else statements) to execute every condition
at least once.

Travis-CI[<https://travis-ci.org/pr-omethe-us/PyKED>] and
Appveyor[<https://ci.appveyor.com/project/Prometheus/pyked>] provide continuous
integration (CI) service for Linux, macOS, and Windows platforms. The CI services run the test suite
on every change to the source code, build and distribute binary installer packages for every
release, and build and publish the online documentation automatically. This automation ensures that
test failures are caught quickly, keeps the documentation up-to-date with the latest changes, and
streamlines the release of new versions.

is licensed under the permissive, open-source BSD 3-clause license. The
source code is publicly available on GitHub at <https://github.com/pr-omethe-us/PyKED>,
and versioned releases are automatically archived via Zenodo PyKED.
can be installed via binary packages or the source code; the online documentation
provides detailed installation instructions at

§ USAGE EXAMPLES

The following usage examples provide a guide to the use of . They are by no means an exhaustive
treatment, and are meant to demonstrate the basic capabilities of the software. Both examples shown
below are also available as Jupyter Notebook files from the GitHub repository for
PyKED[<https://github.com/pr-omethe-us/PyKED/blob/master/docs/rcm-example.ipynb> and
<https://github.com/pr-omethe-us/PyKED/blob/master/docs/shock-tube-example.ipynb>] and in the
Supplementary Material associated with this article.

§.§ RCM modeling with varying reactor volume

The  file that will be used in this example can be found in the
directory of the
Examining that file, we find the first section specifies the information about
the  file itself:

name: Kyle E Niemeyer
ORCID: 0000-0003-4425-7097
file-version: 0
chemked-version: 0.1.6

Then, we find the information regarding the article in the literature from which
this data was taken. In this case, the dataset comes from the work of

doi: 10.1002/kin.20180
- name: Gaurav Mittal
- name: Chih-Jen Sung
ORCID: 0000-0003-2046-8076
- name: Richard A Yetter
journal: International Journal of Chemical Kinetics
year: 2006
volume: 38
pages: 516-529
detail: Fig. 6, open circle
experiment-type: ignition delay
kind: rapid compression machine
institution: Case Western Reserve University
facility: CWRU RCM

Finally, this file contains just a single datapoint, which describes the experimental
ignition delay, initial mixture composition, initial temperature, initial pressure,
compression time, ignition type, and volume history that specifies
how the volume of the reactor varies with time, for simulating the compression
stroke and post-compression processes:

- temperature:
- 297.4 kelvin
- 1.0 ms
- 958.0 torr
kind: mole fraction
- species-name: H2
InChI: 1S/H2/h1H
- 0.12500
- species-name: O2
InChI: 1S/O2/c1-2
- 0.06250
- species-name: N2
InChI: 1S/N2/c1-2
- 0.18125
- species-name: Ar
InChI: 1S/Ar
- 0.63125
target: pressure
type: d/dt max
- 38.0 ms
units: s
column: 0
units: cm3
column: 1
- [0.00E+000, 5.47669375000E+002]
- [1.00E-003, 5.46608789894E+002]
- [2.00E-003, 5.43427034574E+002]

The values for the |volume-history| are truncated here to save space. One application of the
data stored in this file is to perform a simulation using Cantera Cantera:2.3.0 to
calculate the ignition delay, including the facility-dependent effects represented in the volume
trace. All information required to perform this simulation is present in the  file, with the
exception of a chemical kinetic model for H2CO combustion.

In Python, additional functionality can be imported into a script or session by the |import|
keyword. Cantera, NumPy, and PyKED must be imported into the session so that we can work with the
code. In the case of Cantera and NumPy, we will use many functions from these libraries, so we
assign them abbreviations (|ct| and |np|, respectively) for convenience. From PyKED, we
will only be using the |ChemKED| class, so this is all that is imported:

import cantera as ct
import numpy as np
from pyked import ChemKED

Next, we have to load the ChemKED file and retrieve the first element of the |datapoints|
list. Although this file only encodes a single experiment, the |datapoints| attribute will
always be a list (in this case, of length 1). As mentioned previously, the elements of the
|datapoints| list are instances of the |DataPoint| class, which we store in the variable

ck = ChemKED('testfile_rcm.yaml')
dp = ck.datapoints[0]

The initial temperature, pressure, and mixture composition can be read from the
instance of the |DataPoint| class.  uses instances of the Pint |Quantity| class to
store values with units, while Cantera expects a floating-point value in SI
units as input. Therefore, we use the built-in capabilities of Pint to convert
the units from those specified in the  file to SI units, and we use the |magnitude|
attribute of the |Quantity| class to take only the numerical part. We also retrieve the
initial mixture mole fractions in a format Cantera will understand:

T_initial = dp.temperature.to('K').magnitude
P_initial = dp.pressure.to('Pa').magnitude
X_initial = dp.get_cantera_mole_fraction()

With these properties defined, we have to create the objects in Cantera that represent the physical
state of the system to be studied. In Cantera, the |Solution| class stores the thermodynamic,
kinetic, and transport data from the GRI Mech 3.0 <cit.> model included with Cantera.
After the |Solution| object is created, we can set the initial temperature, pressure,
and mole fractions using the |TPX| attribute of the |Solution| class:

# Load the mechanism and set the initial state of the mixture
gas = ct.Solution('gri30.cti')
gas.TPX = T_initial, P_initial, X_initial

With the thermodynamic and kinetic data loaded and the initial conditions defined, we  need to
install the |Solution| instance into an |IdealGasReactor| which implements the equations
for mass, energy, and species conservation. In addition, we create a |Reservoir| to represent
the environment external to the reaction chamber. The input file used for the environment,
, is included with Cantera and represents an average composition of air.

# Create the reactor and the outside environment
reac = ct.IdealGasReactor(gas)
env = ct.Reservoir(ct.Solution('air.xml'))

To apply the effect of the volume trace to the |IdealGasReactor|, a |Wall| must be
installed between the reactor and environment and assigned a velocity. The |Wall| allows the
environment to do work on the reactor (or vice versa) and change the reactor's thermodynamic state;
we use a |Reservoir| for the environment because in Cantera, |Reservoir|s always have a
constant thermodynamic state and composition. Using a |Reservoir| accelerates the solution
compared to using two |IdealGasReactor|s, since the composition and state of the environment
are typically not necessary for the solution of autoignition problems. Although we do not show the
details here, a reference implementation of a class that computes the wall velocity given the volume
history of the reactor is available in CanSen cansen, in the
|cansen.profiles.VolumeProfile| class.

from cansen.profiles import VolumeProfile
# Retrieve the time and volume from the history in the datapoint
exp_time = dp.volume_history.time.magnitude
exp_volume = dp.volume_history.volume.magnitude
keywords = 'vproTime': exp_time, 'vproVol': exp_volume
# Install the Wall between the reactor and environment
ct.Wall(reac, env, velocity=VolumeProfile(keywords))

Then, the |IdealGasReactor| is installed in a |ReactorNet|. The |ReactorNet|
implements the connection to the numerical solver (CVODES hindmarsh_sundials:_2005 is
used in Cantera) to solve the energy and species equations. For this example, it is best practice
to set the maximum time step allowed in the solution to be the minimum time difference in
the time array from the volume trace:

netw = ct.ReactorNet([reac])

To calculate the ignition delay, we will follow the definition specified in the  file for
this experiment, where the experimentalists used the maximum of the time derivative of the pressure
to define the ignition delay. To calculate this derivative, we need to store the state variables
and the composition on each time step, so we initialize several Python lists to act as storage:

# Initialize lists to store solution information
time = []
temperature = []
pressure = []
volume = []
mass_fractions = []

Finally, the problem is integrated using the |step| method of the |ReactorNet|. The
|step| method takes one timestep forward on each call, with step size determined by the CVODES
solver (CVODES uses an adaptive time-stepping algorithm). On each step, we add the relevant
variables to their respective lists. The problem is integrated until a user-specified end time, in
this case 50, although in principle, the user could end the simulation on any
condition they choose:

# Integrate for 50 ms
while netw.time < 0.05:

At this point, the user would post-process the information in the |pressure| list to calculate
the derivative by whatever algorithm they choose. Here, we plot pressure versus time from the
simulation, and compare the simulated and experimental volume traces,
using the Matplotlib library <cit.> and shown in Figure <ref>:

import matplotlib.pyplot as plt

plt.plot(time, pressure)
plt.ylabel('Pressure [Pa]')
plt.xlabel('Time [s]')

plt.plot(exp_time, exp_volume/exp_volume[0], label='Experimental volume', linestyle='–')
plt.plot(time, volume, label='Simulated volume')
plt.ylabel('Volume [m^3]')
plt.xlabel('Time [s]')

Simulated pressure trace

Experimental and simulated volume histories

Results from RCM example

§.§ Shock tube modeling with constant volume

The  file used in this example can be found in the  directory of the
The data in this file comes from Stranic et al. Stranic:2012, describing
shock-tube ignition delays for tert-butanol. We have omitted the file
meta information below for space; the format is largely similar to the example in
Section <ref>.
This  file specifies multiple data points with some common
conditions, including a common mixture composition and common definition of
ignition delay. Therefore, a |common-properties| section is specified, followed by the
|datapoints| list (as before, we have truncated the |datapoints| list for space):

composition:    comp
kind: mole fraction
- species-name: t-butanol
InChI: 1S/C4H10O/c1-4(2,3)5/h5H,1-3H3
- 0.003333333
- species-name: O2
InChI:  1S/O2/c1-2
- 0.04
- species-name: Ar
InChI:  1S/Ar
- 0.956666667
ignition-type:    ign
target: OH*
type: 1/2 max
- temperature:
- 1459 kelvin
- 347 us
- 1.60 atm
composition: *comp
ignition-type: *ign
equivalence-ratio: 0.5
- temperature:
- 1389 kelvin
- 756 us
- 1.67 atm
composition: *comp
ignition-type: *ign
equivalence-ratio: 0.5

In this example, we will run constant-volume simulations at each
pressure and temperature condition in the |datapoints| list. Once again,
the  file specifies all information required for the simulations except
for the chemical kinetic model, and Cantera can be used to simulate autoignition. The setup steps
match those from the previous example, with one exception: in this example, we also import
Python's built-in multiprocessing library so that we can run the simulations on multiple cores.
We import the |Pool| class, which offers tools to manage a set of jobs on a
pool of processors:

import cantera as ct
from multiprocessing import Pool
from pyked import ChemKED

Then, we define a function that will be mapped onto each job. This function takes the initial
temperature, pressure, and mole fractions as input and returns the simulated ignition delay time,
defined as the time the temperature increases by 400 over the initial temperature, a
simplified definition for this example. In general, the user could process the mole fraction of
OH^* (provided that the kinetic model includes accurate chemistry for OH^*) to match the
definition of ignition delay in the experiments. We use the chemical kinetic model
for butanol isomers from Sarathy et al. <cit.>, represented as

def run_simulation(T, P, X):
gas = ct.Solution('LLNL_sarathy_butanol.cti')
gas.TPX = T, P, X
reac = ct.IdealGasReactor(gas)
netw = ct.ReactorNet([reac])
while reac.T < T + 400:

return netw.time

Then, we load the ChemKED file and generate a list of initial conditions that will be mapped onto
the |run_simulation()| function. We first define a convenience function to collect the input
from a single datapoint and return a Python tuple with the conditions (tuples are lightweight groups
of data in Python). Then, we use the built-in |map| function to apply the
|collect_input| function to each of the elements in the |ck.datapoints| list:

ck = ChemKED('Stranic2012-tbuoh.yaml')

def collect_input(dp):
T_initial = dp.temperature.to('K').magnitude
P_initial = dp.pressure.to('Pa').magnitude
X_initial = dp.get_cantera_mole_fraction()
return (T_initial, P_initial, X_initial)

initial_conditions = list(map(collect_input, ck.datapoints))

Finally, we create the processor |Pool| (with four processes) and send the jobs out to run:

with Pool(processes=4) as pool:
ignition_delays = pool.starmap(run_simulation, initial_conditions)

for (T, P, X), tau in zip(initial_conditions, ignition_delays):
print(f'The ignition delay for T_initial=T K, P_initial=P Pa is: tau seconds')

The simulated ignition delay results are returned in the |ignition_delays| list. The results
are printed to the screen using a Python formatted string (f-string). We can also visually
compare the results using Matplotlib <cit.>, as
Figure <ref> shows:

import matplotlib.pyplot as plt

inv_temps = [1000/i[0] for i in initial_conditions]
exp_ignition_delays = [dp.ignition_delay.to('ms').magnitude for dp in ck.datapoints]
sim_ignition_delays = np.array(ignition_delays)*1.0E3

plt.scatter(inv_temps, exp_ignition_delays, label='Experimental ignition delays')
plt.scatter(inv_temps, sim_ignition_delays, label='Simulated ignition delays', marker='s')
plt.ylabel('Ignition delay [ms]')
plt.xlabel('1000/T [1/K]')

Comparison of experimental and simulated ignition delays of
tert-butanol from shock tube example.

§ CONCLUSIONS AND FUTURE WORK

In this article, we presented the  data format for describing measurements
taken from fundamental combustion experiments, recognizing that the community
has a need for an open and standardized data serialization format.  files
are formatted using the YAML language and are plain-text, human- and
machine-readable, and easy to construct.

We also presented a Python-based tool, , for validating and working
with  files.  provides the reference implementation of the validator
for  files and utilizes several common packages from Python's scientific
computing community.  and  currently support ignition delay
measurements from rapid compression machines and shock tubes, including
facility-specific effects from each type of experiment.

Finally, we presented several examples using  to interpret and interact with data
stored in  files. Both examples are also available online as Jupyter Notebook files in the
GitHub repository and in the Supplementary Material. The first example simulates a
rapid compression machine experiment, including the facility-specific effects critical to
accurately predict ignition delay experiments. The second example demonstrates the use of built-in
Python libraries to automatically simulate several shock tube experiments in parallel,
with initial conditions loaded directly from the  file.

We are actively developing  and , and we welcome contributions from the community.
All development occurs under the BSD 3-clause open source license and the code is housed
on GitHub at <https://github.com/pr-omethe-us/PyKED>. Future directions for development are
outlined in the public roadmap.[<https://github.com/pr-omethe-us/PyKED/wiki/Roadmap>]
The highest priority issues are currently adding support for other types of fundamental experiments,
including speciation measurements in shock tubes, jet-stirred reactors, and flow reactors, and
laminar flame speed and flame extinction measurements. Questions, comments, or suggestions are
welcomed and can be posted as issues in the GitHub repository or emailed to the authors. In
particular, we welcome proposals for new experimental types; see issue #60 in the  repository
for an example of how this may be

Missing 'biblatex' package
The bibliography requires the 'biblatex' package.

howpublishedSandia National Laboratories Report SAND96-8216
titleCHEMKIN-III: A FORTRAN chemical kinetics package for the analysis of gas-phase chemical and plasma kinetics

titleCantera: An object-oriented software toolkit for chemical kinetics, thermodynamics, and transport processes

howpublishedRWTH Aachen, <https://www.itv.rwth-aachen.de/index.php?id=13   L=1>
noteVersion 4.0.0
titleFlameMaster: A C++ computer program for 0-D combustion and 1-D laminar flame calculations

titleWebPlotDigitizer v3.11

journaltitleProc. Combust. Inst.
titleTransforming data into knowledge—process informatics for combustion chemistry

journaltitleInt. J. Chem. Kinet.
titleProcess informatics tools for predictive modeling: Hydrogen combustion
family=Open Knowledge Institute,

noteAccessed: 8 Octover 2017
titleOpen Definition 2.1
family=Open Source Initiative,

noteAccessed: 7 October 2017
titleThe Open Source Definition

booktitleProceedings of the 7th European Combustion Meeting
notePaper P1-04
titleReSpecTh: a joint reaction kinetics, spectroscopy, and thermochemistry information system
venueBudapest, Hungary

titleReSpecTh Kinetics Data Format Specification v2.0

journaltitleCombust. Flame
titleComparison of the performance of several recent hydrogen combustion mechanisms

journaltitleCombust. Flame
titleComparison of the performance of several recent syngas combustion mechanisms

journaltitleProceedings of the Combustion Institute
titleOptimization of a hydrogen combustion mechanism using both direct and indirect measurements

journaltitleInt. J. Chem. Kinet.
titleDevelopment of a Joint Hydrogen and Syngas Combustion Mechanism Based on an Optimization Approach

journaltitleCombustion and Flame
titleUncertainty quantification of a newly optimized methanol and formaldehyde combustion mechanism

journaltitleInt. J. Chem. Kinet.
titleDevelopment of an Ethanol Combustion Mechanism Based on a Hierarchical Optimization Approach

noteAccessed: 14 Nov 2017
titleExperimental and theoretical combustion data in XML format

booktitle2013 International Conference on Information Science and Cloud Computing Companion
titleCloudFlame: Cyberinfrastructure for Combustion Research

booktitle23rd International Symposium on Gas Kinetics and Related Phenomena
titleA Hybrid Cloud System for Combustion Kinetics Simulation

Ghent, Belgium

booktitle9th International Conference on Chemical Kinetics
titleCloudFlame and PrIMe: accelerating combustion research in the cloud

booktitleProceedings of the 15th Python in Science Conference (SciPy 2016)
titlePyTeCK: a Python-based automatic testing package for chemical kinetic models
venueAustin, TX, USA
family=döt Net,

titleYAML Ain't Markup Language (YAML™) Version 1.2

titlePyKED v0.3.0 [software]

family=van der Walt,

journaltitleComput. Sci. Eng.
titleThe NumPy Array: A Structure for Efficient Numerical Computation

booktitleProceedings of the 9th Python in Science Conference
titleData Structures for Statistical Computing in Python

journaltitlePLOS Biology
titleBest Practices for Scientific Computing

journaltitleInternational Journal of Chemical Kinetics
titleAutoignition of H2/CO at Elevated Pressures in a Rapid Compression Machine

titleGRI-Mech 3.0

journaltitleACM Transactions on Mathematical Software
notebibtex: Hindmarsh2005
titleSUNDIALS: Suite of nonlinear and differential/algebraic equation solvers

IEEE COMPUTER SOC

abstractMatplotlib is a 2D graphics package used for Python for application development, interactive scripting, and publication-quality image generation across user interfaces and operating systems.
journaltitleComputing In Science & Engineering
titleMatplotlib: A 2D graphics environment

journaltitleCombustion and Flame
titleShock tube measurements of ignition delay times for the butanol isomers

journaltitleCombust. Flame
titleA comprehensive chemical kinetic combustion model for the four butanol isomers