'H2(aq)':1e-6, 'O2(aq)':1e-4, } rate_scale=10e-8 thresh=0.0 reactions = [ # decomp_network.reaction(name='Aerobic decomposition',reactant_pools={'SOM':1.0},product_pools={'HCO3-':1.0},reactiontype='SOMDECOMP', # rate_constant=1e-8,rate_units='1/sec',turnover_name='RATE_CONSTANT', # # inhibition_terms=[decomp_network.inhibition(species='O2(aq)',k=6.25e-8,type='THRESHOLD 1.0d20')]), # monod_terms=[decomp_network.monod(species='O2(aq)',k=conc_scales['O2(aq)'],threshold=thresh)]), decomp_network.reaction(name='Hydrolysis',stoich='1.0 SOM -> 0.9 DOM1',reactiontype='SOMDECOMP',turnover_name='RATE_CONSTANT', rate_constant=rate_scale,rate_units='1/sec', # Jianqiu Zheng et al., 2019: One third of fermented C is converted to CO2 inhibition_terms=[decomp_network.inhibition(species='DOM1',type='MONOD',k=conc_scales['DOM1']), # decomp_network.inhibition(species='O2(aq)',type='MONOD',k=1e-11), ]), # Calculating these as per unit carbon, so dividing by the 6 carbons in a glucose # C6H12O6 + 4 H2O -> 2 CH3COO- + 2 HCO3- + 4 H+ + 4 H2 # Should it be inhibited by H2? decomp_network.reaction(name='fermentation',reactant_pools={'DOM1':6/6},product_pools={'Acetate-':2/6,'HCO3-':2/6,'H+':4/6,'H2(aq)':4*2/6,'Tracer':2/6}, # balancing pH of FeIII release requires an extra 5.5 H+ to be released here rate_constant=rate_scale,reactiontype='MICROBIAL', # Jianqiu Zheng et al., 2019: One third of fermented C is converted to CO2 inhibition_terms=[decomp_network.inhibition(species='O2(aq)',k=conc_scales['O2(aq)'],type='MONOD'),decomp_network.inhibition(species='Acetate-',k=conc_scales['Acetate-'],type='MONOD')], monod_terms=[decomp_network.monod(species='DOM1',k=conc_scales['DOM1'],threshold=thresh)]), # CH2O + H2O -> CO2 + 4H+ + 4 e- # O2 + 4H+ + 4 e- -> 2H2O decomp_network.reaction(name='DOM oxidation (O2)',stoich='1.0 DOM1 + 1.0 O2(aq) -> 1.0 HCO3- + 1.0 H+ + 1.0 Tracer', monod_terms=[decomp_network.monod(species='O2(aq)',k=conc_scales['O2(aq)'],threshold=thresh),decomp_network.monod(species='DOM1',k=conc_scales['DOM1'],threshold=thresh)],
def make_network(Mn_peroxidase_Mn3_leakage=1e-5, leaf_Mn_mgkg=25.0, change_constraints={}, Mn2_scale=1e-5, Mn3_scale=1e-5, NH4_scale=1e-2, DOM_scale=1.0, CEC=40.0, change_rate={}, DOM_sorption_k=1.0): Mn_molarmass = 54.94 #g/mol C_molarmass = 12.01 leaf_Cfrac_mass = 0.4 # Converting from mol Mn/mol leaf C to mg Mn/kg leaf dry mass leaf_Mn_frac = leaf_Mn_mgkg / ((Mn_molarmass * 1e3) / (C_molarmass * 1e-3 / leaf_Cfrac_mass)) reactions = [ decomp_network.reaction( name='Hydrolysis', reactant_pools={'Cellulose': 1.0}, product_pools={'DOM1': 1.0}, rate_constant=2e-1, rate_units='y', # inhibition_terms=[decomp_network.inhibition(species='DOM1',type='MONOD',k=1e-1)], reactiontype='SOMDECOMP'), # Need a way to make a soluble reactive compound from lignin. Treating it like hydrolysis, but allowing only a small amount to be generated # Model runs faster if Mn limitation is on this step (source limit) instead of limiting decomposition rate of DOM2 and building up inhibiting DOM2 concentrations decomp_network.reaction( name='Lignin exposure', reactant_pools={'Lignin': 1.0}, product_pools={'DOM2': 1.0}, rate_constant=2e-1, rate_units='y', inhibition_terms=[ decomp_network.inhibition(species='DOM2', type='MONOD', k=1e0), decomp_network.inhibition( species='Cellulose', type='MONOD', k=40 ), # Suggested by Sun et al 2019, which found that MnP activity only increased late in decomposition decomp_network.inhibition(species='Mn++', type='INVERSE_MONOD', k=Mn2_scale), decomp_network.inhibition(species='NH4+', k=NH4_scale, type='MONOD') ], reactiontype='SOMDECOMP'), # Direct depolymerization of lignin into DOM1. Basically to allow some decomposition to occur in absence of Mn++ so lignin doesn't build up indefinitely # Still deciding whether to do this way or by DOM2 oxidation? Or leaching of DOM2? Or not at all? decomp_network.reaction(name='Lignin depolymerization', reactant_pools={'Lignin': 1.0}, product_pools={'DOM1': 1.0}, rate_constant=2e-1, rate_units='y', inhibition_terms=[ decomp_network.inhibition(species='Mn++', type='MONOD', k=Mn2_scale) ], reactiontype='SOMDECOMP'), # Mn reduction turns DOM2 (lignin-based) into DOM1 (odixized, decomposable) # decomp_network.reaction(name='Lignin Mn reduction',reactant_pools={'DOM2':1.0,'Mn+++':1.0},product_pools={'Mn++':1.0,'H+':1.0,'DOM1':1.0}, # monod_terms=[decomp_network.monod(species='DOM2',k=2e-11,threshold=1.1e-20),decomp_network.monod(species='Mn+++',k=1.3e-18,threshold=1.1e-25)], # # inhibition_terms=[decomp_network.inhibition(species='O2(aq)',k=6.25e-8,type='MONOD')], # rate_constant=2e-10,reactiontype='MICROBIAL'), # Mn oxidation (Mn peroxidase?) # decomp_network.reaction(name='Mn oxidation',reactant_pools={'O2(aq)':1.0,'H+':4.0,'Mn++':4.0},product_pools={'Mn+++':4.0}, # monod_terms=[decomp_network.monod(species='O2(aq)',k=1e-5,threshold=1.1e-15),decomp_network.monod(species='Mn++',k=1.3e-12,threshold=1.1e-15)], # # inhibition_terms=[decomp_network.inhibition(species='O2(aq)',k=6.25e-8,type='MONOD')], # rate_constant=8e-10,reactiontype='MICROBIAL'), # Mn Peroxidase: Quasi-closed reaction loop for Mn2/3 with some leakage. # 1 DOM2 + 1 Mn++ + x H+ -> 1 DOM1 + (1-x) Mn++ + x Mn+++ decomp_network.reaction(name='Mn Peroxidase', reactant_pools={ 'DOM2': 1.0, 'Mn++': Mn_peroxidase_Mn3_leakage, 'H+': Mn_peroxidase_Mn3_leakage }, product_pools={ 'DOM1': 1.0, 'Mn+++': Mn_peroxidase_Mn3_leakage }, monod_terms=[ decomp_network.monod(species='DOM2', k=1e-1, threshold=1.1e-20), decomp_network.monod(species='Mn++', k=Mn2_scale * 1e1, threshold=1.1e-20) ], inhibition_terms=[ decomp_network.inhibition(species='NH4+', k=NH4_scale, type='MONOD') ], rate_constant=5e-6, reactiontype='MICROBIAL'), # CH2O + H2O -> CO2 + 4H+ + 4 e- # O2 + 4H+ + 4 e- -> 2H2O decomp_network.reaction(name='DOM aerobic respiration', reactant_pools={ 'DOM1': 1.0, 'O2(aq)': 1.0 }, product_pools={ 'HCO3-': 1.0, 'H+': 1.0, 'Tracer': 1.0, 'Mn++': leaf_Mn_frac }, monod_terms=[ decomp_network.monod(species='O2(aq)', k=1e-4, threshold=1.1e-12), decomp_network.monod(species='DOM1', k=DOM_scale, threshold=1.1e-14) ], rate_constant=1.0e-5, reactiontype='MICROBIAL'), # CH2O + H2O -> CO2 + 4H+ + 4 e- # O2 + 4H+ + 4 e- -> 2H2O # Aerobic respiration of DOM2, to allow some lignin decomposition in absence of Mn. Assume it is very slow decomp_network.reaction(name='DOM2 aerobic respiration', reactant_pools={ 'DOM2': 1.0, 'O2(aq)': 1.0 }, product_pools={ 'HCO3-': 1.0, 'H+': 1.0, 'Tracer': 1.0, 'Mn++': leaf_Mn_frac }, monod_terms=[ decomp_network.monod(species='O2(aq)', k=1e-4, threshold=1.1e-12), decomp_network.monod(species='DOM2', k=1e0, threshold=1.1e-14) ], inhibition_terms=[ decomp_network.inhibition(species='Mn++', type='MONOD', k=Mn2_scale) ], rate_constant=1.0e-5, reactiontype='MICROBIAL'), # Manganese reduction reaction # CH2O + 2 H2O -> HCO3- + 5 H+ + 4 e- # 4 Mn+++ + 4 e- -> 4 Mn++ # Microbial-mediated manganese reduction, happens under anoxic conditions only decomp_network.reaction( name='DOM1 Mn+++ reduction', stoich= '1.0 DOM1 + 4.0 Mn+++ -> 1.0 HCO3- + 4.0 Mn++ + 5.0 H+ + 1.0 Tracer', monod_terms=[ decomp_network.monod(species='DOM1', k=DOM_scale / 10), decomp_network.monod(species='Mn+++', k=Mn3_scale) ], inhibition_terms=[ decomp_network.inhibition(species='O2(aq)', k=1e-8, type='MONOD') ], rate_constant=2e-10, reactiontype='MICROBIAL'), # Abiotic Mn reduction, happens under oxic conditions decomp_network.reaction( name='DOM1 Mn+++ abiotic reduction', stoich= '1.0 DOM1 + 4.0 Mn+++ -> 1.0 HCO3- + 4.0 Mn++ + 5.0 H+ + 1.0 Tracer', rate_constant=2e-5, reactiontype='GENERAL'), # Microbial oxidation of Mn(II) under oxic conditions. See Tebo et al 2004. Mostly done by bacteria. Reduces O2 to water. Function unknown but might be chemoautotrophic # Mn++ + 0.5 O2 + H2O -> Mn(+4)O2 + 2 H+ (but this includes an intermediate Mn3O4 step) # or Mn++ + 0.25 O2 + 1.5 H2O -> Mn(+3)OOH + 2 H+ # or 3 Mn++ + 0.5 O2 + 3 H2O -> Mn(+3)3O4 + 6 H+ # Simplified version assuming further oxidation happens in Birnessite precipitation step: # Mn++ + H+ + 0.25 O2 -> Mn+++ + 0.5 H2O # then (implicitly) 7 Mn+++ + 1.25 O2 + 15.5 H2O -> Mn7O13*5H2O + 21 H+ decomp_network.reaction( name='Bacterial Mn++ oxidation', stoich='Mn++ + H+ + 0.25 O2(aq) -> Mn+++ + 0.5 H2O', monod_terms=[ decomp_network.monod(species='Mn++', k=Mn2_scale), decomp_network.monod(species='O2(aq)', k=1e-4, threshold=1.1e-12) ], rate_constant=8e-8, reactiontype='MICROBIAL' ), # Rate constant estimated from Fig 8 in Tebo et al 2004 # C2H3O2- + 2 H2O -> 2 CO2 + 7 H+ + 8 e- # 2 O2 + 8 H+ + 8 e- -> 4 H2O # decomp_network.reaction(name='Acetate aerobic respiration',reactant_pools={'Acetate-':1.0,'O2(aq)':2.0},product_pools={'HCO3-':2.0,'H+':2.0,'Tracer':2.0}, # monod_terms=[decomp_network.monod(species='O2(aq)',k=1e-5,threshold=1.1e-12),decomp_network.monod(species='Acetate-',k=1e-8,threshold=1.1e-14)], # rate_constant=1.0e-9,reactiontype='MICROBIAL'), # # PFLOTRAN will not let you do isotherm sorption if there are any secondary species :-( - reaction_database.F90 line 3424 # decomp_network.sorption_isotherm(name='DOM sorption',mineral='Rock(s)',sorbed_species='DOM1',k=0.1,langmuir_b=1.0,sorbed_name='Sorbed DOM1'), # Root uptake of Mn++. Does this need a charge balancing release of anions? # According to Haynes (1990), imbalance in root anion vs cation uptake is usually balanced by H+ or OH- release. I guess in this case we need to assume that all other ions are balanced except for Mn? decomp_network.reaction(name='Root uptake of Mn++', stoich='1.0 Mn++ -> 1.0 Tracer2 + 2 H+', monod_terms=[ decomp_network.monod(species='Mn++', k=1e-7, threshold=1.1e-20) ], biomass='Root_biomass', biomass_yield=0.0, rate_constant=1.0e-5, reactiontype='MICROBIAL'), # Cation exchange decomp_network.ion_exchange(name='Cation exchange', cations={ 'Mn++': 5.0, 'Mn+++': 0.6, 'Al+++': 10.0, 'Mg++': 1.1, 'Ca++': 1.0, 'Na+': 0.5, 'K+': 0.1, 'H+': 1.1 }, CEC=CEC, mineral=None), # sorption rate is microbial DOM1 -> DOM3 (d/dt = V1*sorption_capacity*DOM1/(DOM1+k)) # Desorption rate is general DOM3 -> DOM1 (d/dt = V2*DOM3) # Equilibrium sorption = V1/V2*sorption_capacity*DOM/(k+DOM) so actual maximum sorption is V1/V2*sorption_capacity decomp_network.reaction(name='DOM sorption', stoich='DOM1 -> DOM3', monod_terms=[ decomp_network.monod(species='DOM1', k=DOM_sorption_k) ], biomass='Sorption_capacity', biomass_yield=0.0, rate_constant=1.0e-10, reactiontype='MICROBIAL'), decomp_network.reaction(name='DOM desorption', stoich='DOM3 -> DOM1', reactiontype='GENERAL', rate_constant=1.0e-10), ] # End of reactions list import copy pools_copy = copy.deepcopy(pools) for n, p in enumerate(pools_copy): if p['name'] in change_rate: pools_copy[n]['rate'] = change_rate[p['name']] return decomp_network.decomp_network( pools=decomp_network.change_constraints(pools_copy, change_constraints), reactions=reactions)
# Fe(II) is probably sorbing onto OM, or staying dissolved # Fe(III) should precipitate in this system, so if it's dissolved it would be complexed with something # Per Persson has papers on Fe partitioning in soils as a function of pH # Derek Lovely has done a lot of Fe reduction lab work to look at reduction rates # Kinetics of water-rock interaction (textbook) has lots of rate constants. Look for chapter by Eric Rodin # Aaron Thompson does work on Fe oxides and redox fluctuations hydrolysis = decomp_network.reaction( name='Hydrolysis', reactant_pools={'cellulose': 1.0}, product_pools={'DOM1': 1.0}, rate_constant=1e-1, rate_units= 'y', # Jianqiu Zheng et al., 2019: One third of fermented C is converted to CO2 inhibition_terms=[ decomp_network.inhibition(species='DOM1', type='MONOD', k=1e-5) ]) # Calculating these as per unit carbon, so dividing by the 6 carbons in a glucose # C6H12O6 + 4 H2O -> 2 CH3COO- + 2 HCO3- + 4 H+ + 4 H2 fermentation = decomp_network.reaction( name='fermentation', reactant_pools={'DOM1': 6 / 6}, product_pools={ 'Acetate-': 2 / 6, 'HCO3-': 2 / 6, 'H+': 4 / 6 + 4 * 2 / 6, 'Tracer': 2 / 6 }, # balancing pH of FeIII release requires an extra 5.5 H+ to be released here rate_constant=1e-10, reactiontype=
def make_reactions(conc_scales=conc_scales,anox_inhib_conc=anox_inhib_conc,Fe_inhibit_CH4=True,rate_scale=1e-8): # Turn off inhibition of methanogenesis by Fe+++ by setting inhibition constant very high if Fe_inhibit_CH4: Fe_CH4_inhib=1.0 else: Fe_CH4_inhib=1e10 reactions = [ # decomp_network.reaction(name='Aerobic decomposition',reactant_pools={'cellulose':1.0},product_pools={'HCO3-':1.0},reactiontype='SOMDECOMP', # rate_constant=0.0,rate_units='1/d',turnover_name='RATE_DECOMPOSITION', # # inhibition_terms=[decomp_network.inhibition(species='O2(aq)',k=6.25e-8,type='THRESHOLD 1.0d20')]), # monod_terms=[decomp_network.monod(species='O2(aq)',k=conc_scales['O2(aq)'],threshold=1.1e-9)]), # From Dave Graham: SOM-C + H2O -> DOM-C decomp_network.reaction(name='Hydrolysis',stoich='1.0 cellulose -> 1.0 DOM1',reactiontype='SOMDECOMP', rate_constant=rate_scale,rate_units='y', # Jianqiu Zheng et al., 2019: One third of fermented C is converted to CO2 inhibition_terms=[decomp_network.inhibition(species='DOM1',type='MONOD',k=conc_scales['DOM1']), # decomp_network.inhibition(species='O2(aq)',k=6.25e-11,type='THRESHOLD -1.0d10') # decomp_network.inhibition(species='O2(aq)',type='MONOD',k=1e-11), ]), # Calculating these as per unit carbon, so dividing by the 6 carbons in a glucose # C6H12O6 + 4 H2O -> 2 CH3COO- + 2 HCO3- + 4 H+ + 4 H2 # Dave Graham: DOM-C + 0.67 H2O -> 0.33 CH3COO- + 0.33 HCO3- + 0.67 H+ + 0.67 H2 # Should it be inhibited by H2? decomp_network.reaction(name='fermentation',reactant_pools={'DOM1':1/6,'H2O':2/3},product_pools={'Acetate-':1/3,'HCO3-':1/3,'H+':2/3,'H2(aq)':2/3,'Tracer':1/3}, # balancing pH of FeIII release requires an extra 5.5 H+ to be released here rate_constant=rate_scale*40,reactiontype='MICROBIAL', # Jianqiu Zheng et al., 2019: One third of fermented C is converted to CO2 inhibition_terms=[decomp_network.inhibition(species='O2(aq)',k=anox_inhib_conc,type='MONOD'),decomp_network.inhibition(species='Acetate-',k=conc_scales['Acetate-'],type='MONOD')], monod_terms=[decomp_network.monod(species='DOM1',k=conc_scales['DOM1'],threshold=1.1e-15)]), # CH2O + H2O -> CO2 + 4H+ + 4 e- # O2 + 4H+ + 4 e- -> 2H2O decomp_network.reaction(name='DOM aerobic respiration',stoich='1.0 DOM1 + 1.0 O2(aq) + 1.0 H2O -> 1.0 HCO3- + 1.0 H+ + 1.0 Tracer', monod_terms=[decomp_network.monod(species='O2(aq)',k=conc_scales['O2(aq)'],threshold=0.0),decomp_network.monod(species='DOM1',k=conc_scales['DOM1'],threshold=1.1e-16)], rate_constant=rate_scale*50,reactiontype='MICROBIAL'), # C2H3O2- + 2 H2O -> 2 CO2 + 7 H+ + 8 e- # 2 O2 + 8 H+ + 8 e- -> 4 H2O decomp_network.reaction(name='Acetate aerobic respiration',stoich='1.0 Acetate- + 2.0 O2(aq) -> 2.0 HCO3- + 2.0 H+ + 2.0 Tracer ', monod_terms=[decomp_network.monod(species='O2(aq)',k=conc_scales['O2(aq)'],threshold=0.0),decomp_network.monod(species='Acetate-',k=conc_scales['Acetate-'],threshold=1.1e-16)], rate_constant=rate_scale*50,reactiontype='MICROBIAL'), # C2H3O2- + 2 H2O -> 2 CO2 + 7 H+ + 8 e- # 8 Fe+++ + 8 e- -> 8 Fe++ decomp_network.reaction(name='Fe(III) reduction',stoich='1.0 Acetate- + 8.0 Fe+++ + 4.0 H2O -> 2.0 HCO3- + 8.0 Fe++ + 9.0 H+ + 2.0 Tracer', monod_terms=[decomp_network.monod(species='Acetate-',k=conc_scales['Acetate-'],threshold=1.1e-15),decomp_network.monod(species='Fe+++',k=conc_scales['Fe+++'],threshold=1.1e-15)], inhibition_terms=[decomp_network.inhibition(species='O2(aq)',k=anox_inhib_conc,type='MONOD')], rate_constant=rate_scale*3,reactiontype='MICROBIAL'), # Oxidation of Fe++ # Currently assuming backward reaction rate is zero decomp_network.reaction(name='Fe(II) abiotic oxidation',stoich='1.0 Fe++ + 0.25 O2(aq) + 1.0 H+ <-> 1.0 Fe+++ + 0.5 H2O', rate_constant=0.0,backward_rate_constant=0.0,reactiontype='GENERAL'), decomp_network.reaction(name='Fe(II) microbial oxidation',stoich='1.0 Fe++ + 0.25 O2(aq) + 1.0 H+ -> 1.0 Fe+++ + 0.5 H2O', monod_terms=[decomp_network.monod(species='O2(aq)',k=conc_scales['O2(aq)'],threshold=0.0),decomp_network.monod(species='Fe++',k=conc_scales['Fe++'],threshold=1.1e-15)], rate_constant=rate_scale*200,reactiontype='MICROBIAL'), # Acetoclastic methanogenesis # C2H3O2- + H+ -> CH4 + HCO3- + H+ # pH dependence: Dunfield et al 1992 has some bell curves. Kotsyurbenko et al 2007 has info on different pathways at different pH. Le Mer and Roger 2001 is a big review with a bit on pH thresholds # See methane_ph.py: Optimization against Kotsyurbenko data yields K_M=5.54 and K_I=5.54 for acetaclastic, and k_M=6.75 for hydrogenotrophic # Also gives rate constant of hydro = 0.415 that of acetaclastic decomp_network.reaction(name='Acetaclastic methanogenesis',stoich='1.0 Acetate- + H2O -> 1.0 CH4(aq) + 1.0 HCO3- + 1.0 Tracer', monod_terms=[decomp_network.monod(species='Acetate-',k=conc_scales['Acetate-'],threshold=1.1e-15), ], inhibition_terms=[decomp_network.inhibition(species='O2(aq)',k=anox_inhib_conc,type='MONOD'), decomp_network.inhibition(species='Fe+++',k=conc_scales['Fe+++']*Fe_CH4_inhib,type='MONOD'), decomp_network.inhibition(species='H+',k=10**-5.54,type='MONOD'), decomp_network.inhibition(species='H+',k=10**-5.54,type='INVERSE_MONOD')], rate_constant=rate_scale*2,reactiontype='MICROBIAL'), # Hydrogenotrophic methanogenesis decomp_network.reaction(name='Hydrogenotrophic methanogenesis',stoich='4.0 H2(aq) + 1.0 HCO3- + 1.0 H+ -> 1.0 CH4(aq) + 3.0 H2O', monod_terms=[decomp_network.monod(species='H2(aq)',k=conc_scales['H2(aq)'],threshold=1.1e-15),decomp_network.monod(species='HCO3-',k=conc_scales['HCO3-'],threshold=1.1e-15)], # inhibition_terms=[decomp_network.inhibition(species='O2(aq)',k=conc_scales['O2(aq)'],type='MONOD'),decomp_network.inhibition(species='Fe+++',k=conc_scales['Fe+++'],type='MONOD')], inhibition_terms=[decomp_network.inhibition(species='O2(aq)',k=anox_inhib_conc,type='MONOD'), decomp_network.inhibition(species='Fe+++',k=conc_scales['Fe+++']*Fe_CH4_inhib,type='MONOD'), decomp_network.inhibition(species='H+',k=10**-6.75,type='MONOD'), # decomp_network.inhibition(species='NO3-',k=conc_scales['NO3-'],type='MONOD'), # decomp_network.inhibition(species='SO4--',k=conc_scales['SO4--'],type='MONOD') ], rate_constant=rate_scale*3*0.32,reactiontype='MICROBIAL'), # H2 oxidation if oxygen available decomp_network.reaction(name='Hydrogen oxidation',stoich='2.0 H2(aq) + 1.0 O2(aq) -> 2.0 H2O', monod_terms=[decomp_network.monod(species='H2(aq)',k=conc_scales['H2(aq)'],threshold=1.1e-15), decomp_network.monod(species='O2(aq)',k=conc_scales['O2(aq)'],threshold=0.0)], rate_constant=rate_scale*200,reactiontype='MICROBIAL'), # Cation exchange decomp_network.ion_exchange(name='Cation exchange',cations={'Fe++':0.1,'Fe+++':0.3,'Mg++':1.1,'Ca++':4.1,'Na+':1.0,'K+':0.9,'H+':1.1},CEC=2000.0,mineral=None) ] return reactions