Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add references field to yaml input standard #777

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -1589,6 +1589,32 @@ for yaml in mglob(env, "data", "yaml"):
dest = pjoin("build", "data", yaml.name)
build(env.Command(dest, yaml.path, Copy("$TARGET", "$SOURCE")))

# Copy Chemkin input files
ck_sources = [
dict(input='data/inputs/gri30.inp',
thermo='data/thermo/gri30_thermo.dat',
transport='data/transport/gri30_tran.dat',
bibtex='data/bibtex/gri30.bib'),
dict(input='data/inputs/air.inp',
transport='data/transport/gri30_tran.dat'),
dict(input='data/inputs/argon.inp',
thermo='data/thermo/gri30_thermo.dat',
transport='data/transport/gri30_tran.dat'),
dict(input='data/inputs/airNASA9.inp',
thermo='data/thermo/airDataNASA9.dat',
bibtex='data/bibtex/nasa9.bib'),
dict(input='data/inputs/h2o2.inp',
transport='data/transport/gri30_tran.dat'),
dict(thermo='data/thermo/nasathermo.dat',
bibtex='data/bibtex/nasa7.bib')
]

for mech in ck_sources:
for key in ['input', 'thermo', 'transport', 'bibtex']:
if key in mech:
build(env.Command('build/chemkin/{}'.format(mech[key].split('/')[-1]),
mech[key], Copy('$TARGET', '$SOURCE')))

if addInstallActions:
# Put headers in place
headerBase = 'include/cantera'
Expand Down
9 changes: 9 additions & 0 deletions data/bibtex/gri30.bib
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
@misc{gri30,
title = "GRI-Mech 3.0",
author = "Gregory P. Smith and David M. Golden and Michael Frenklach and
Nigel W. Moriarty and Boris Eiteneer and Mikhail Goldenberg and
C. Thomas Bowman and Ronald K. Hanson and Soonho Song and
William C. {Gardiner Jr.} and Vitali V. Lissianski and Zhiwei Qin",
year = 1999,
howpublished = "\url{http://combustion.berkeley.edu/gri-mech/version30/text30.html}"
}
20 changes: 20 additions & 0 deletions data/bibtex/nasa7.bib
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
@misc{nasa7,
title = "NASA thermodynamic database",
note = "7-term polynomial coefficients in 1971 format",
howpublished = "\url{https://shepherd.caltech.edu/EDL/PublicResources/sdt/cti/NASA7/nasa7.dat}"
}
@techreport{gordon1971,
title = "Computer Program for Calculation of Complex Chemical Equilibrium
Composition, Rocket Performance, Incident and Reflected Shocks and
Chapman-Jouguet Detonations",
author = "S. Gordon and B. J. McBride",
year = 1971,
number = "NASA SP-273"
}
@techreport{mcbride1993,
title = "Coefficients for Calculating Thermodynamic and Transport Properties
of Individual Species",
author = "B. J. McBride and S. Gordon and M. A. Reno",
year = 1993,
number = "NASA TM-4513"
}
12 changes: 12 additions & 0 deletions data/bibtex/nasa9.bib
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
@misc{nasa9,
title = "NASA thermodynamic database",
note = "9-term coefficients in 1996 format",
howpublished = "\url{https://shepherd.caltech.edu/EDL/PublicResources/sdt/cti/NASA7/nasa7.dat}"
}
@techreport{mcbride2002,
title = "Nasa Glenn coefficients for Calculating Thermodynamic Properties
of Individual Species",
author = "B. J. McBride and M. J. Zehe and S. Gordon",
year = 2002,
number = "NASA TP2002-211556"
}
2 changes: 2 additions & 0 deletions data/inputs/air.inp
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
! Ideal gas properties of air. Includes several reactions among
! the included species.
ELEMENTS
O N AR
END
Expand Down
2 changes: 2 additions & 0 deletions data/inputs/argon.inp
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
! Pure argon phase. Thermo and transport properties are taken
! from GRI-Mech 3.0.
ELEMENTS
AR
END
Expand Down
1 change: 1 addition & 0 deletions data/inputs/h2o2.inp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
! Hydrogen-Oxygen submechanism extracted from GRI-Mech 3.0.
ELEMENTS
O H AR
END
Expand Down
2 changes: 2 additions & 0 deletions data/inputs/silane.inp
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
! Source unknown. Data originially added by Dave Goodwin in an early
! version of Cantera.
ELEMENTS
SI H HE
END
Expand Down
4 changes: 2 additions & 2 deletions data/thermo/nasathermo.dat
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
THERMO NO_TMID
300.0 1000.0 5000.0
!
! This is the NASA thermodynamic database, which is available for download
! from http://www.galcit.caltech.edu/EDL/public/thermo.html. The original
Expand All @@ -14,6 +12,8 @@ THERMO NO_TMID
! Report TM-4513, October 1993.
!-----------------------------------------------------------------------------
!
THERMO NO_TMID
300.0 1000.0 5000.0
Electron gas L10/92E 1. 0. 0. 0.G 200.000 6000.0005.48579903-04 1
2.50000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 2
-7.45375000E+02-1.17246902E+01 2.50000000E+00 0.00000000E+00 0.00000000E+00 3
Expand Down
5 changes: 5 additions & 0 deletions interfaces/cython/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ testFiles = localenv.RecursiveInstall('#interfaces/cython/cantera/test/data',
'#test/data')
build(testFiles)

ckFiles = localenv.RecursiveInstall('#interfaces/cython/cantera/examples/input',
'#build/chemkin')
build(ckFiles)

inputFiles = ['inputs/h2o2.inp', 'inputs/gri30.inp',
'transport/gri30_tran.dat', 'thermo/gri30_thermo.dat']
for f in inputFiles:
Expand Down Expand Up @@ -96,6 +100,7 @@ for f in (mglob(localenv, 'cantera', 'py') +
mglob(localenv, 'cantera/examples/reactors', 'py') +
mglob(localenv, 'cantera/examples/onedim', 'py') +
mglob(localenv, 'cantera/examples/surface_chemistry', 'py') +
mglob(localenv, 'cantera/examples/input', 'py') +
mglob(localenv, 'cantera/examples/misc', 'py')):
localenv.Depends(mod, f)

Expand Down
154 changes: 140 additions & 14 deletions interfaces/cython/cantera/ck2yaml.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
[--transport=<filename>]
[--surface=<filename>]
[--name=<name>]
[--bibtex=<filename>]
[--output=<filename>]
[--permissive]
[-d | --debug]
Expand All @@ -32,8 +33,10 @@
'surface'.

The '--permissive' option allows certain recoverable parsing errors (e.g.
duplicate transport data) to be ignored. The '--name=<name>' option
is used to override default phase names (i.e. 'gas').
duplicate transport data) to be ignored. Further, the '--name=<name>' option
is used to override default phase names (i.e. 'gas'). The '--bibtex=<filename>'
option attaches references to the yaml output, where fields are based on BibTeX
style input.
"""

from collections import defaultdict, OrderedDict
Expand Down Expand Up @@ -742,7 +745,8 @@ def __init__(self):
self.species_dict = {} # bulk and surface species
self.surfaces = []
self.reactions = []
self.headerLines = []
self.header_lines = []
self.bibtex = {} # for bibtex entries
self.files = [] # input file names

def warn(self, message):
Expand Down Expand Up @@ -1328,6 +1332,86 @@ def parse_expression(expression, dest):

return reaction, revReaction

def load_bibtex_file(self, path):
ischoegl marked this conversation as resolved.
Show resolved Hide resolved
"""
Load and separate BibTeX-formatted entries from ``path`` on disk.
"""
def text_strip(text):
text = text.strip()
if text[0] == '"' and text[-1] == '"':
return text.strip('"')
elif text[0] == '{' and text[-1] == '}':
return text.strip('{}')
elif text.isdigit():
return text
else:
raise NotImplementedError(
"Cannot parse '{}': this minimal BibTeX parser does not "
"support @string definitions and otherwise adheres to the "
"BibTeX format as described in "
"http://www.bibtex.org/Format/".format(text))

def parse_citation(entry):
# split entry into tagged key/value blocks and retrieve entry type
blocks = '\n'.join([e.strip() for e in entry[1:]])
blocks = blocks.rstrip('}').rstrip(',\n ').split(',\n')
out = {'entry_type': entry[0].split('{')[0].strip(' ').lower()}

for block in blocks:
# retrieve key
parts = block.split('=')
key = parts[0].strip().lower()
block = '='.join(parts[1:])

# build value
try:
value = ''.join([text_strip(b)
for b in block.replace('\n', ' ').split('#')])
except NotImplementedError as err:
raise InputError("Encountered invalid syntax in "
"BibTeX entry:\n{}".format('\n'.join(entry))) from err

# reformat author list
if key == 'author':
authors = [a.strip().replace('{', '').replace('}', '')
for a in value.split(' and ')]
if len(authors) > 1:
value = ', '.join(authors[:-1]) + ' and ' + authors[-1]

out[key] = value if len(value) > 1 else value[0]
return out

def read_citation(bib_file):
entry = []
count = 0
while not(entry) or count > 0:
line = strip_nonascii(bib_file.readline()).rstrip()
count += line.count('{') - line.count('}')
count -= line.count('\{') - line.count('\}')
entry.append(line)
if line == "":
break

if entry[0]:
regex = r"^@+([a-zA-z]+){+([ A-Za-z0-9_-]+)[ ,]"
bib = re.findall(regex, entry[0].strip())
if bib and entry[-1].rstrip()[-1] == '}' and count == 0:
return bib[0][1].strip(), parse_citation(entry)
else:
raise InputError("Encountered invalid syntax in "
"BibTeX entry:\n{}".format('\n'.join(entry)))
else:
return None, None

with open(path, 'r', errors='ignore') as bib_file:

while True:
label, entry = read_citation(bib_file)
if label is not None:
self.bibtex[label] = entry
else:
break

def load_chemkin_file(self, path, skip_undeclared_species=True, surface=False):
"""
Load a Chemkin-format input file from ``path`` on disk.
Expand Down Expand Up @@ -1356,7 +1440,7 @@ def readline():
while line is not None:
tokens = line.split() or ['']
if inHeader and not line.strip():
self.headerLines.append(comment.rstrip())
self.header_lines.append(comment.rstrip())

if tokens[0].upper().startswith('ELEM'):
inHeader = False
Expand Down Expand Up @@ -1839,12 +1923,33 @@ def write_yaml(self, name='gas', out_name='mech.yaml'):
n_reacting_phases += 1

# header from original file
desc = '\n'.join(line.rstrip() for line in self.headerLines)
desc = '\n'.join(line.rstrip() for line in self.header_lines)
desc = desc.strip('\n')
desc = textwrap.dedent(desc)
if desc.strip():
emitter.dump({'description': yaml.scalarstring.PreservedScalarString(desc)}, dest)

# bibtex entries
if self.bibtex:
entries = BlockMap()
for key, val in self.bibtex.items():
tags = []
comment = val.pop('entry_type')
for k, v in val.items():
if v.isdigit():
out = int(v)
elif not v.count(" ") and len(v) > 50:
out = yaml.scalarstring.PreservedScalarString(v)
else:
out = v
tags.append((k, out))
entries[key] = BlockMap(tags)
entries.yaml_add_eol_comment(comment, key)
bib = BlockMap([('references', entries)])
if desc.strip():
bib.yaml_set_comment_before_after_key('references', before='\n')
emitter.dump(bib, dest)

# Additional information regarding conversion
files = [os.path.basename(f) for f in self.files]
metadata = BlockMap([
Expand All @@ -1853,7 +1958,7 @@ def write_yaml(self, name='gas', out_name='mech.yaml'):
('cantera-version', '2.5.0a3'),
('date', formatdate(localtime=True)),
])
if desc.strip():
if desc.strip() or self.bibtex:
metadata.yaml_set_comment_before_after_key('generator', before='\n')
emitter.dump(metadata, dest)

Expand Down Expand Up @@ -1946,8 +2051,8 @@ def write_yaml(self, name='gas', out_name='mech.yaml'):

@staticmethod
def convert_mech(input_file, thermo_file=None, transport_file=None,
surface_file=None, phase_name='gas', out_name=None,
quiet=False, permissive=None):
surface_file=None, phase_name='gas', bibtex_file=None,
out_name=None, quiet=False, permissive=None):

parser = Parser()
if quiet:
Expand Down Expand Up @@ -2013,6 +2118,19 @@ def convert_mech(input_file, thermo_file=None, transport_file=None,
surface_file, parser.line_number, err))
raise

if bibtex_file:
parser.files.append(bibtex_file)
bibtex_file = os.path.expanduser(bibtex_file)
if not os.path.exists(bibtex_file):
raise IOError('Missing input file: {0!r}'.format(bibtex_file))
try:
# Read input mechanism files
parser.load_bibtex_file(bibtex_file)
except Exception as err:
logging.warning("\nERROR: Unable to parse '{0}':\n{1}\n".format(
bibtex_file, err))
raise

if out_name:
out_name = os.path.expanduser(out_name)
else:
Expand All @@ -2027,15 +2145,16 @@ def convert_mech(input_file, thermo_file=None, transport_file=None,
return surface_names


def convert_mech(input_file, thermo_file=None, transport_file=None, surface_file=None,
phase_name='gas', out_name=None, quiet=False, permissive=None):
def convert_mech(input_file, thermo_file=None, transport_file=None,
surface_file=None, phase_name='gas', bibtex_file=None,
out_name=None, quiet=False, permissive=None):
return Parser.convert_mech(input_file, thermo_file, transport_file, surface_file,
phase_name, out_name, quiet, permissive)
phase_name, bibtex_file, out_name, quiet, permissive)

def main(argv):

longOptions = ['input=', 'thermo=', 'transport=', 'surface=', 'name=',
'output=', 'permissive', 'help', 'debug', 'quiet',
'bibtex=', 'output=', 'permissive', 'help', 'debug', 'quiet',
'no-validate', 'id=']

try:
Expand Down Expand Up @@ -2077,6 +2196,13 @@ def main(argv):
' must be provided.\nRun "ck2yaml.py --help" to see usage help.')
sys.exit(1)

if '--bibtex' in options:
bibtex_file = options['--bibtex']
if not bibtex_file.endswith('.bib'):
bibtex_file += '.bib'
else:
bibtex_file = None

if '--output' in options:
out_name = options['--output']
if not out_name.endswith('.yaml') and not out_name.endswith('.yml'):
Expand All @@ -2087,8 +2213,8 @@ def main(argv):
out_name = os.path.splitext(thermo_file)[0] + '.yaml'

surfaces = Parser.convert_mech(input_file, thermo_file, transport_file,
surface_file, phase_name, out_name,
quiet, permissive)
surface_file, phase_name, bibtex_file,
out_name, quiet, permissive)

# Do full validation by importing the resulting mechanism
if not input_file:
Expand Down
Loading