3737import logging
3838import marshal
3939import os
40+ import re
4041import resource
4142import shutil
4243import 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
24352467def log_conditions (rmg_memories , index ):
24362468 """
0 commit comments