Skip to content

Commit c9e20b1

Browse files
committed
Changing coverage-dependent thermo cantera yaml output.
Now it just modifies the part of the yaml file that has changed, instead of reading and writing the whole thing. Will probably still do some refactoring, but making an intermediate commit to check it's working so far. Second commit: (squashed) A refactor of the coverage-dependence-thermo to cantera yaml code. Moved the _add_coverage_dependence_to_cantera_yaml function, and made it pass strings instead of dictionaries.
1 parent 589fe73 commit c9e20b1

1 file changed

Lines changed: 64 additions & 32 deletions

File tree

rmgpy/rmg/main.py

Lines changed: 64 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import logging
3838
import marshal
3939
import os
40+
import re
4041
import resource
4142
import shutil
4243
import sys
@@ -1223,6 +1224,7 @@ def execute(self, initialize=True, **kwargs):
12231224
# generate Cantera files chem.yaml & chem_annotated.yaml in a designated `cantera` output folder
12241225
try:
12251226
if any([s.contains_surface_site() for s in self.reaction_model.core.species]):
1227+
# Surface (catalytic) chemistry
12261228
self.generate_cantera_files(
12271229
os.path.join(self.output_directory, "chemkin", "chem-gas.inp"),
12281230
surface_file=(os.path.join(self.output_directory, "chemkin", "chem-surface.inp")),
@@ -1231,43 +1233,34 @@ def execute(self, initialize=True, **kwargs):
12311233
os.path.join(self.output_directory, "chemkin", "chem_annotated-gas.inp"),
12321234
surface_file=(os.path.join(self.output_directory, "chemkin", "chem_annotated-surface.inp")),
12331235
)
1234-
if self.thermo_coverage_dependence:
1235-
# add thermo coverage dependence to Cantera files
1236-
chem_yaml_path = os.path.join(self.output_directory, "cantera", "chem.yaml")
1237-
with open(chem_yaml_path, 'r') as f:
1238-
content = yaml.load(f, Loader=yaml.FullLoader)
1239-
1240-
content['phases'][1]['reference-state-coverage'] = 0.11
1241-
content['phases'][1]['thermo'] = 'coverage-dependent-surface'
1242-
cantera_names = [s['name'] for s in content["species"]]
12431236

1237+
if self.thermo_coverage_dependence:
1238+
# Build coverage_deps: {species_name: string_to_add_to_yaml}
1239+
coverage_deps = {}
12441240
for s in self.reaction_model.core.species:
12451241
if s.contains_surface_site() and s.thermo.thermo_coverage_dependence:
1246-
for dep_sp, parameters in s.thermo.thermo_coverage_dependence.items():
1247-
mol = Molecule().from_adjacency_list(dep_sp)
1242+
s_name = s.to_chemkin()
1243+
for dep_sp_adj, parameters in s.thermo.thermo_coverage_dependence.items():
1244+
mol = Molecule().from_adjacency_list(dep_sp_adj)
12481245
for sp in self.reaction_model.core.species:
12491246
if sp.is_isomorphic(mol, strict=False):
1250-
parameters['units'] = {'energy':'J', 'quantity':'mol'}
1251-
parameters['enthalpy-coefficients'] = [value.value_si for value in parameters['enthalpy-coefficients']]
1252-
parameters['entropy-coefficients'] = [value.value_si for value in parameters['entropy-coefficients']]
1253-
try:
1254-
content["species"][cantera_names.index(s.to_chemkin())]['coverage-dependencies'][sp.to_chemkin()] = parameters
1255-
except KeyError:
1256-
content["species"][cantera_names.index(s.to_chemkin())]['coverage-dependencies'] = {sp.to_chemkin(): parameters}
1257-
1258-
annotated_yaml_path = os.path.join(self.output_directory, "cantera", "chem_annotated.yaml")
1259-
with open(annotated_yaml_path, 'r') as f:
1260-
annotated_content = yaml.load(f, Loader=yaml.FullLoader)
1261-
1262-
annotated_content['phases'] = content['phases']
1263-
annotated_content['species'] = content['species']
1264-
1265-
with open(chem_yaml_path, 'w') as output_f:
1266-
yaml.dump(content, output_f, sort_keys=False, default_flow_style=None)
1267-
1268-
with open(annotated_yaml_path, 'w') as output_f:
1269-
yaml.dump(annotated_content, output_f, sort_keys=False, default_flow_style=None)
1270-
1247+
if s_name not in coverage_deps:
1248+
coverage_deps[s_name] = ' coverage-dependencies:'
1249+
coverage_deps[s_name] += f"""
1250+
{sp.to_chemkin()}:
1251+
model: {parameters['model']}
1252+
enthalpy-coefficients: {[v.value_si for v in parameters['enthalpy-coefficients']]}
1253+
entropy-coefficients: {[v.value_si for v in parameters['entropy-coefficients']]}
1254+
units: {{energy: J, quantity: mol}}
1255+
"""
1256+
break
1257+
1258+
for yaml_path in [
1259+
os.path.join(self.output_directory, "cantera", "chem.yaml"),
1260+
os.path.join(self.output_directory, "cantera", "chem_annotated.yaml"),
1261+
]:
1262+
_add_coverage_dependence_to_cantera_yaml(yaml_path, coverage_deps)
1263+
12711264
else: # gas phase only
12721265
self.generate_cantera_files(os.path.join(self.output_directory, "chemkin", "chem.inp"))
12731266
self.generate_cantera_files(os.path.join(self.output_directory, "chemkin", "chem_annotated.inp"))
@@ -2431,6 +2424,45 @@ def obj(y):
24312424
self.scaled_condition_list.append(scaled_new_cond)
24322425
return
24332426

2427+
def _add_coverage_dependence_to_cantera_yaml(yaml_path, coverage_deps):
2428+
"""Modify a Cantera YAML file in-place to add coverage-dependent surface thermo.
2429+
2430+
Makes targeted text insertions rather than loading and re-dumping the whole
2431+
file, so original formatting is preserved everywhere except the new lines.
2432+
2433+
Args:
2434+
yaml_path: path to the Cantera YAML file to modify
2435+
coverage_deps: dict mapping species ChemKin names to their coverage-dependency string.
2436+
"""
2437+
with open(yaml_path, 'r') as f:
2438+
content = f.read()
2439+
2440+
# --- Modify the surface phase ---
2441+
# Replace 'ideal-surface' with 'coverage-dependent-surface' and add reference-state-coverage.
2442+
content = content.replace(
2443+
' thermo: ideal-surface\n',
2444+
' thermo: coverage-dependent-surface\n reference-state-coverage: 0.11\n',
2445+
1,
2446+
)
2447+
2448+
# --- Insert coverage-dependencies block after each relevant species entry ---
2449+
for species_name, deps in coverage_deps.items():
2450+
match = re.search(r'^- name: ' + re.escape(species_name) + r'\n', content, re.MULTILINE)
2451+
if not match:
2452+
logging.warning(
2453+
f"Species {species_name} not found in {yaml_path}; skipping coverage-dependency insertion."
2454+
)
2455+
continue
2456+
2457+
after = match.end()
2458+
end_match = re.search(r'\n(?=(?:- |\n|\w))', content[after:])
2459+
if end_match:
2460+
insert_pos = after + end_match.start() + 1
2461+
content = content[:insert_pos] + deps + content[insert_pos:]
2462+
else:
2463+
content = content.rstrip('\n') + '\n' + deps
2464+
with open(yaml_path, 'w') as f:
2465+
f.write(content)
24342466

24352467
def log_conditions(rmg_memories, index):
24362468
"""

0 commit comments

Comments
 (0)