#!/usr/bin/env python # coding: utf-8 # This notebook shows how to treat surface reactions in reacting systems where diffusion is a much faster process in comparison to the chemical reactions (surface is treated as a "homogenized" concentration). # In[ ]: import matplotlib.pyplot as plt from collections import defaultdict from chempy import ReactionSystem, Species, Reaction from chempy.units import to_unitless, SI_base_registry, rescale, default_constants as const, default_units as u from chempy.kinetics.ode import ( _create_odesys as create_odesys, ) get_ipython().run_line_magic('matplotlib', 'inline') # In[ ]: ads_token = '(ads)' phases = {'(aq)': 0, ads_token: 1} ads_comp = -1 vacancy = Species('vacancy(ads)', composition={ads_comp: 1}, phase_idx=phases[ads_token], latex_name='vacancy(ads)') def substance_factory(name): if name == vacancy.name: return vacancy s = Species.from_formula(name, phases=phases) if name.endswith(ads_token): s.composition[ads_comp] = 1 return s rsys = ReactionSystem.from_string(""" vacancy(ads) + H2O2 -> H2O2(ads); 'k_ads_H2O2' H2O2(ads) + vacancy(ads) -> 2 OH(ads); 'k_split_H2O2ads' OH(ads) + H2O2 -> H2O + HO2 + vacancy(ads); 'k_abst_OHads_H2O2' HO2 + HO2 -> O2 + H2O2; 'k_disprop_HO2' """, substance_factory=substance_factory) rsys # In[ ]: ureg = SI_base_registry.copy() ureg['length'] = u.dm odesys, odesys_extra = create_odesys(rsys, unit_registry=ureg) # In[ ]: powder_mass = 42*u.g specific_surf_area = 35*u.m**2/u.g # e.g. from BET sample_volume = 250*u.cm3 surf_volume_ratio = powder_mass*specific_surf_area/sample_volume adsorption_cross_section = 0.162*u.nm**2 # N2 at 77K on active carbon conc_vacancy = rescale(surf_volume_ratio/(adsorption_cross_section * const.Avogadro_constant), u.molar) conc_vacancy # In[ ]: c0 = defaultdict(lambda: 0*u.M, H2O2=.2*u.M, **{'vacancy(ads)': conc_vacancy}) tend = 3600*u.s result, result_extra = odesys_extra['unit_aware_solve']( (1e-7*u.s, tend), c0, dict( k_ads_H2O2=.1/u.M/u.s, k_split_H2O2ads=.2/u.M/u.s, k_abst_OHads_H2O2=.3/u.M/u.s, k_disprop_HO2=.4/u.M/u.s ), integrator='cvode' ) # In[ ]: fig, axes = plt.subplots(1, 2, figsize=(14, 4)) result.plot(ax=axes[0]) result.plot(ax=axes[1], xscale='log', yscale='log') for ax in axes: #ax.set_ylabel('Concentration / M') #ax.set_xlabel('Time / min') ax.set_ylim(to_unitless([1e-6*u.molar, c0['H2O2']], result_extra['unit_conc'])) ax.set_xlim(to_unitless([1*u.s, tend], result_extra['unit_time']))