Skip to content

Commit

Permalink
[YAML] Add --extra option to ck2yaml
Browse files Browse the repository at this point in the history
The --extra option takes a YAML file as input and adds the following abilities:
- specify alternative description string
- copy (user-defined) custom fields to YAML output
  • Loading branch information
Ingmar Schoegl authored and ischoegl committed Jan 14, 2020
1 parent f79d619 commit a0da08d
Showing 1 changed file with 75 additions and 12 deletions.
87 changes: 75 additions & 12 deletions interfaces/cython/cantera/ck2yaml.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@
[--transport=<filename>]
[--surface=<filename>]
[--name=<name>]
[--extra=<filename>]
[--output=<filename>]
[--permissive]
[--quiet]
[--no-validate]
[-d | --debug]
Example:
Expand All @@ -34,6 +37,10 @@
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').
The '--extra=<filename>' option takes a YAML file as input. This option can be
used to specify an alternative file description, or to define custom fields that
are attached to the YAML output.
"""

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

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

return reaction, revReaction

def load_extra_file(self, path):
"""
Load YAML-formatted entries from ``path`` on disk.
"""
with open(path, 'rt', encoding="utf-8") as stream:
yml = yaml.round_trip_load(stream)

# do not overwrite reserved field names
reserved = {'generator', 'input-files', 'cantera-version', 'date',
'units', 'phases', 'species', 'reactions'}
reserved &= set(yml.keys())
if reserved:
raise InputError("A YAML file provided as '--extra' input "
"(i.e. '{}') must not redefine reserved field names: "
"{}".format(path, reserved))

# replace header lines
if 'description' in yml:
if isinstance(yml['description'], str):
self.header_lines = yml.pop('description').split('\n')
else:
raise InputError("The alternate description provided in "
"'{}' needs to be a string".format(path))

# remainder
self.extra = yml

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 +1391,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 @@ -1838,8 +1873,8 @@ def write_yaml(self, name='gas', out_name='mech.yaml'):
if surf.reactions:
n_reacting_phases += 1

# header from original file
desc = '\n'.join(line.rstrip() for line in self.headerLines)
# Write header lines
desc = '\n'.join(line.rstrip() for line in self.header_lines)
desc = desc.strip('\n')
desc = textwrap.dedent(desc)
if desc.strip():
Expand All @@ -1857,6 +1892,13 @@ def write_yaml(self, name='gas', out_name='mech.yaml'):
metadata.yaml_set_comment_before_after_key('generator', before='\n')
emitter.dump(metadata, dest)

# Write extra entries
if self.extra:
extra = BlockMap(self.extra)
key = list(self.extra.keys())[0]
extra.yaml_set_comment_before_after_key(key, before='\n')
emitter.dump(extra, dest)

units = FlowMap([('length', 'cm'), ('time', 's')])
units['quantity'] = self.output_quantity_units
units['activation-energy'] = self.output_energy_units
Expand Down Expand Up @@ -1946,8 +1988,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', extra_file=None,
out_name=None, quiet=False, permissive=None):

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

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

if out_name:
out_name = os.path.expanduser(out_name)
else:
Expand All @@ -2027,15 +2082,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', extra_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, extra_file, out_name, quiet, permissive)

def main(argv):

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

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

if '--extra' in options:
extra_file = options['--extra']
if not extra_file.endswith('.yaml') and not extra_file.endswith('.yml'):
extra_file += '.yaml'
else:
extra_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 +2150,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, extra_file,
out_name, quiet, permissive)

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

0 comments on commit a0da08d

Please sign in to comment.