示例#1
0
文件: misc.py 项目: MMaus/mutils
def get_minmax(data, deg=2):
    """
    returns the interpolated extremum and position (in fractions of frames)

    :args:
        data (iterable): data to be fitted with a <deg> degree polynomial
        deg (int): degree of polynomial to fit

    :returns:
        val, pos: a tuple of floats indicating the position
    """

    x = arange(len(data))
    p = polyfit(x, data, deg)
    d = (arange(len(p))[::-1] * p)[:-1]
    r = roots(d)
    cnt = 0
    idx = None
    for nr, rx in enumerate(r):
        if isreal(r):
            idx = nr
            cnt +=1
            if cnt > 1:
                raise ValueError("Too many real roots found." + 
                        "Reduce order of polynomial!")
    x0 = r[nr].real
    return x0, polyval(p, x0)
示例#2
0
文件: misc.py 项目: MMaus/mutils
def get_minmax(data, deg=2):
    """
    returns the interpolated extremum and position (in fractions of frames)

    :args:
        data (iterable): data to be fitted with a <deg> degree polynomial
        deg (int): degree of polynomial to fit

    :returns:
        val, pos: a tuple of floats indicating the position
    """

    x = arange(len(data))
    p = polyfit(x, data, deg)
    d = (arange(len(p))[::-1] * p)[:-1]
    r = roots(d)
    cnt = 0
    idx = None
    for nr, rx in enumerate(r):
        if isreal(r):
            idx = nr
            cnt += 1
            if cnt > 1:
                raise ValueError("Too many real roots found." +
                                 "Reduce order of polynomial!")
    x0 = r[nr].real
    return x0, polyval(p, x0)
示例#3
0
def find_solid_p(rho):
    sigma=1.
    p=pl.arange(10,20,0.01 )

    v0=sigma**3/pl.sqrt(2)
    v=1./rho

    y=(p*sigma**3)**-1


    coeffs=pl.zeros(7)

    coeffs[0]=19328.09
    coeffs[1]=-2609.26
    coeffs[2]=141.6000
    coeffs[3]=11.56350
    coeffs[4]=-1.807846
    coeffs[5]=3
    coeffs[6]=-v+v0

    def find_real_positive(roots):
        for root in roots:
            if root.imag==0 and root.real>0:
                return root.real
    # print coeffs
    roots=1./pl.roots(coeffs)
    # f=3-1.807846*y+11.56350*y**2+141.6000*y**3-2609.260*y**4+19328.09*y**5-(v-v0)/y
    # # print pl.polyval(coeffs,1./p)

    # polynomial= pl.poly1d(coeffs)


    P=find_real_positive(roots)
    return P
def Cretaceous_cc(
    y, t0, cl_sens, deep_grad, PG, change_out, F_outgass, W_plus_1, F_carbw,
    CWF, CO2_dep, Te, n, coef_for_diss, beta, Ebas
):  #inputs include DIC and ALK for ocean and pore space, time, and key parameters

    global pK1, pK2, H_CO2, Pore_mod, k_d, k_w, k_c, k_o, Mp, ppCO2_o, Ea, Mo, ko1, ko2

    # Perscribed evolution of ocean and pore-space calcium molality (Fig. S6):
    Ca = 7.00658e-27 * abs(t0)**3 - 1.9847e-18 * (t0)**2 + 2.4016e-10 * (
        t0) + 0.0100278

    #ocean variables
    s = 1.8e20 / Mo  #Constant for ensuring mass conversation
    [c, d] = pylab.roots([
        y[1] / (10**-pK2 * 10**-pK1) * (1 + s / H_CO2),
        (y[1] - y[0]) / (10**-pK2), (y[1] - 2 * y[0])
    ])
    EM_H_o = numpy.max([c, d])  ## Evolving model ocean hydrogen molality
    EM_pH_o = -pylab.log10(EM_H_o)  ## Evolving model ocean pH
    EM_co3_o = y[1] / (2 + EM_H_o /
                       (10**-pK2))  ## Evolving model ocean carbonate molality
    EM_hco3_o = y[
        1] - 2 * EM_co3_o  ## Evolving model ocean bicarbonate molality
    EM_co2aq_o = (EM_hco3_o * EM_H_o / (10**-pK1)
                  )  ## Evolving model ocean aqueous CO2 molality
    EM_ppCO2_o = EM_co2aq_o / H_CO2  ## Evolving model atmospheric pCO2
    EM_Ca_o = Ca  #Perscribed ocean Ca molality

    #pore space variables
    [c, d] = pylab.roots([
        y[3] / (10**-pK2 * 10**-pK1), (y[3] - y[2]) / (10**-pK2),
        (y[3] - 2 * y[2])
    ])
    EM_H_p = numpy.max([c, d])  ## Evolving model pore space hydrogen molality
    EM_pH_p = -pylab.log10(EM_H_p)  ## Evolving model pore space pH
    EM_co3_p = y[3] / (2 + EM_H_p / (10**-pK2)
                       )  ## Evolving model pore space carbonate molality
    EM_hco3_p = y[
        3] - 2 * EM_co3_p  ## Evolving model pore space bicarbonate molality
    EM_co2aq_p = (EM_hco3_p * EM_H_p / (10**-pK1)
                  )  ## Evolving model pore space aqueous CO2 molality
    EM_ppCO2_p = EM_co2aq_p / H_CO2  ## Evolving model pore space pCO2 (unused)
    EM_Ca_p = Ca  #Percribed pore space Ca molality

    # Perscribed evolution of continental shelf area (Fig. S5):
    area = (.540e-23 * abs(t0)**3 - 3.072e-15 * abs(t0)**2 +
            2.9997e-07 * abs(t0) + 16.089) / 16.089

    # Apply climate model to calculate surface temperature (equation 5):
    T_surface_diff = (cl_sens / numpy.log(2)) * numpy.log(
        EM_ppCO2_o / ppCO2_o) - cl_sens * abs(t0) / (0.181e9 *
                                                     1.26) + PG * abs(t0) / 1e8
    T_surface = T_surface_diff + 285
    # Calculate pore space temperature (equation 11):
    interc = 274.037 - deep_grad * 285
    buffer_T = deep_grad * T_surface + interc

    F_outg = F_outgass + change_out * F_outgass * (
        abs(t0) / 1e8)  #Outgassing as a function of time, equation 9
    Relative_outgassing = F_outg / F_outgass  #Relative outgassing
    weatherability = weatherability_func(
        abs(t0), W_plus_1)  #Weatherability as a functino of time

    #Calculate saturation state of ocean and pore space (equation 19):
    EM_omega_o = EM_Ca_o * EM_co3_o / (Sol_prod(T_surface))
    EM_omega_p = EM_Ca_p * EM_co3_p / (Sol_prod(buffer_T + Pore_mod))

    # Carbonate weathering flux (equartion 7)
    carb_weath = F_carbw * (1 + CWF * abs(t0) / 1e8) * (
        EM_ppCO2_o / ppCO2_o)**(CO2_dep) * numpy.exp(
            (T_surface_diff) / Te) * weatherability
    # Ocean carbonate precipitation flux (equation 17)
    Precip_ocean = ko1 * area * (EM_omega_o - 1)**n + ko2 * (
        EM_omega_o**2.84)  #shelf + pelagic
    # Pore space carbonate precipitation flux (equation 18)
    Precip_pore = k_c * (EM_omega_p - 1)**n
    #seafloor dissolution flux (equation 12)
    F_diss = k_d * 2.88 * 10**-14 * 10**(
        -coef_for_diss * EM_pH_p) * Relative_outgassing**beta * numpy.exp(
            -Ebas / (8.314 * (buffer_T + Pore_mod)))
    #continental silicate weathering flux (equation 2)
    F_silic = k_w * weatherability * (EM_ppCO2_o /
                                      ppCO2_o)**CO2_dep * numpy.exp(
                                          (T_surface_diff) / Te)

    return [
        Ca, EM_H_o, EM_pH_o, EM_co3_o, EM_hco3_o, EM_co2aq_o, EM_ppCO2_o,
        EM_Ca_o, EM_H_p, EM_pH_p, EM_co3_p, EM_hco3_p, EM_co2aq_p, EM_ppCO2_p,
        EM_Ca_p, area, T_surface, T_surface_diff, buffer_T, EM_omega_o,
        EM_omega_p, Relative_outgassing, weatherability, F_outg, carb_weath,
        Precip_ocean, Precip_pore, F_diss, F_silic
    ]
def forward_model(W, F_outgass, n, CO2_dep, Te, mod_sea, alt_frac, Mp_frac,
                  W_plus_1, cl_sens, change_out, F_carbw, frac_pel, CWF,
                  deep_grad, coef_for_diss, beta, Ebas, PG):
    #import pdb
    #pdb.set_trace()
    # Make carbon chemistry constants and other parameters global variables:
    global pK1, pK2, H_CO2, Pore_mod, k_d, k_w, k_c, k_o, Mp, ppCO2_o, Ea, Mo, ko1, ko2

    # Constants for carbon chemisty
    T = 18 + 273  #Temperature held constant for the purposes of calculating equilibrium constants (see manuscript)
    pK1 = 17.788 - .073104 * T - .0051087 * 35 + 1.1463 * 10**-4 * T**2
    pK2 = 20.919 - .064209 * T - .011887 * 35 + 8.7313 * 10**-5 * T**2
    H_CO2 = pylab.exp(
        9345.17 / T - 167.8108 + 23.3585 * pylab.log(T) +
        (.023517 - 2.3656 * 10**-4 * T + 4.7036 * 10**-7 * T**2) * 35)

    Mo = 1.35e21  #Mass of ocean (kg)
    W = Mo / W  #convert timescale of circulation (yr) to water flux through pore space (kg/yr)

    Mp = Mp_frac * Mo  #Calculate mass of ocean in pore space
    partition = mod_sea / F_outgass  #seafloor precipitation as a fraction of total carbon sink (used to initialize)

    ############################################################################
    ## Compute initial conditions (i.e. fluxes and ocean chemistry for modern carbon cycle):

    F_diss0 = alt_frac * partition * F_outgass  # Modern seafloor dissolution flux in pore space
    F_silic0 = (1 - partition) * F_outgass + (
        1 - alt_frac
    ) * partition * F_outgass  #Modern continental silicaet weathering
    Precip_pore0 = partition * F_outgass  # Modern carbonate precipitation in pore-space

    ### Initial conditions for modern atmosphere and ocean
    pH_o = 8.2  #pH of modern ocean
    ppCO2_o = .000280  #preindustrial pCO2 (ppm)
    CO2_aq_o = H_CO2 * ppCO2_o  #modern ocean aqueous pCO2 molality
    hco3_o = (10**-pK1) * CO2_aq_o / (10**-pH_o
                                      )  #modern ocean bicarbonate molality
    co3_o = (10**-pK2) * hco3_o / (10**-pH_o
                                   )  # modern ocean carbonate molality
    DIC_o = co3_o + hco3_o + CO2_aq_o  #modern ocean dissolved inorganic carbon
    ALK_o = 2 * co3_o + hco3_o  # modern ocean alkalinity
    Ca_o = 0.0100278  # modern oceanic calcium molality (mol/kg)
    salt = ALK_o - 2 * Ca_o  ## set salt to ensure ALK is consistent with Ca

    T_surface_diff = 0
    T_surface = T_surface_diff + 285  # Modern average surface temperature (K)
    interc = 274.037 - deep_grad * 285  # Calculate intercept for surface vs. deep ocean temperature relationship
    buffer_T = deep_grad * T_surface + interc  # Calculate modern deep ocean temperature (K)
    Pore_mod = 9.0  # Constant difference between deep ocean temperature and pore space temperature (K)

    ## Use these constants and steady state assumption to calculate remaining initial conditions:
    b1 = 2 * F_diss0 + W * ALK_o - 2 * W * DIC_o
    b2 = 2 * F_silic0 - W * ALK_o - 2 * F_outgass + 2 * W * DIC_o
    a1 = W
    a2 = -2 * W
    a3 = -W
    a4 = 2 * W

    # Solving system of equations for pore space properties
    DIC_p = DIC_o - Precip_pore0 / W  #Modern dissolved inorganic carbon in pore space
    ALK_p = (b1 - a2 * DIC_p) / a1  #Modern alkalinity in pore space
    Precip_ocean0 = (F_outgass + F_carbw
                     ) - (DIC_o - DIC_p) * W  #Carbonate precipitation in ocean

    if DIC_p < 0:
        print("WARNING: NO PHYSIAL STEADY STATE EXISTS! DIC is negative")

    #Solve quadratic ignoring H in ALK but including CO2aq
    [vv, xx] = pylab.roots([
        ALK_p / (10**-pK1 * 10**-pK2), (ALK_p - DIC_p) / (10**-pK2),
        ALK_p - 2 * DIC_p
    ])
    H_p = numpy.max([vv, xx])  # Modern hydrogen molality in pore space
    pH_p = -pylab.log10(H_p)  # Modern pH of pore space

    #Find remaining carbon chemistry from equilibrium conditions:
    CO2aq_p = DIC_p / ((10**-pK1) * (10**-pK2) / H_p**2 + 10**-pK1 / H_p + 1
                       )  # Modern aqueous CO2 in pore space
    co3_p = ALK_p - DIC_p - H_p + CO2aq_p  # Modern carbonate alkalinity in pore space
    hco3_p = co3_p * 10**-pH_p / (
        10**-pK2)  #Modern bicarbonate alkalinity in pore space (not used)

    Ca_p = 0.5 * (ALK_p - salt)  #Modern calcium molality in pore space
    omega_p = Ca_p * co3_p / Sol_prod(
        buffer_T + Pore_mod)  #Modern saturation state pore space
    omega_o = Ca_o * co3_o / Sol_prod(
        T_surface)  #Modern saturatino state of ocean

    ## All initital conditions have been calculated
    ############################################################################

    ############ Calculate proportionality constants ###########################
    # Given modern precipitation fluxes and saturation states, calculate proportionality constants
    k_c = Precip_pore0 / (omega_p - 1)**n
    k_o = Precip_ocean0 / (omega_o - 1)**n

    ## Partition ocean carbonate sink into shelf precipitation and carbonate precipitation
    ko1 = (1 - frac_pel) * Precip_ocean0 / (omega_o -
                                            1)**n  #Modern shelf precipitation
    ko2 = frac_pel * Precip_ocean0 / (omega_o**2.84
                                      )  #Modern pelagic precipitation

    # Calculate remaining proportionality constants
    k_d = F_diss0 / (2.88 * 10**-14 * 10**(-coef_for_diss * pH_p) *
                     numpy.exp(-Ebas / (8.314 * (buffer_T + Pore_mod))))
    k_w = F_silic0
    ##### all proportionality constants have been calculated ###################

    time = numpy.linspace(
        0, 1e8,
        100)  # Time array for outputs, 100 timesteps between 0 and 100 Ma
    #print ('IC new',DIC_o+1.8e20/Mo*ppCO2_o,ALK_o,DIC_p,ALK_p)
    # Given initial conditions, unknown parameters, and system of ODEs (below), solve for time evolution of DIC and ALK of ocean and pore space:
    [out, mes] = scipy.integrate.odeint(
        system_of_equations,
        [DIC_o + 1.8e20 / Mo * ppCO2_o, ALK_o, DIC_p, ALK_p],
        time,
        args=(W, F_outgass, n, CO2_dep, Te, mod_sea, alt_frac, Mp_frac,
              W_plus_1, cl_sens, change_out, F_carbw, CWF, deep_grad,
              coef_for_diss, beta, Ebas, PG),
        full_output=1)

    # Create empty arrays for storing model outputs
    pH_array_o = 0 * time  # pH of ocean
    CO2_array_o = 0 * time  # pCO2 of ocean
    pH_array_p = 0 * time  # pH of pore space
    CO2_array_p = 0 * time  # pCO2 pore space
    Ca_array_o = 0 * time  # Ca molality ocean
    Ca_array_p = 0 * time  # Ca molality pore space
    CO3_array_o = 0 * time  # Carbonate molality ocean
    CO3_array_p = 0 * time  # Carbonate molality pore space
    HCO3_array_o = 0 * time  # Bicarbonate molaity ocean
    HCO3_array_p = 0 * time  # Bicarbonate molality pore space
    omega_o = 0 * time  # Saturation state ocean
    omega_p = 0 * time  # Saturation state pore space
    Tsurf_array = 0 * time  # Surface temperature
    Tdeep_array = 0 * time  # Pore space temperature
    Fd_array = 0 * time  # Seafloor dissolution flux
    Fs_array = 0 * time  # Continental silicate weathering flux
    Precip_ocean_array = 0 * time  # Carbonate precipitaion ocean flux
    Precip_pore_array = 0 * time  # Carbonate precipitation pore space flux
    volc_array = 0 * time  # Volcanic outgassing flux
    carbw_ar = 0 * time  # Carbonate weathering flux
    co2_aq_o = 0 * time  # aqueous CO2 ocean molality
    co2_aq_p = 0 * time  # aqueous CO2 pore space molality

    ### Step through time, and fill output arrays with solution calculated above
    for i in range(0, len(time)):

        # Given time evolution of DIC and ALK for ocean and pore space, calculate time evolution for other carbon cycle variables (fluxes and equilibrium chemistry):
        [
            Ca, EM_H_o, EM_pH_o, EM_co3_o, EM_hco3_o, EM_co2aq_o, EM_ppCO2_o,
            EM_Ca_o, EM_H_p, EM_pH_p, EM_co3_p, EM_hco3_p, EM_co2aq_p,
            EM_ppCO2_p, EM_Ca_p, area, T_surface, T_surface_diff, buffer_T,
            EM_omega_o, EM_omega_p, Relative_outgassing, weatherability,
            F_outg, carb_weath, Precip_ocean, Precip_pore, F_diss, F_silic
        ] = Cretaceous_cc([out[i, 0], out[i, 1], out[i, 2], out[i, 3]],
                          time[i], cl_sens, deep_grad, PG, change_out,
                          F_outgass, W_plus_1, F_carbw, CWF, CO2_dep, Te, n,
                          coef_for_diss, beta, Ebas)
        array_of_outputs = [
            EM_pH_o, EM_co3_o, EM_hco3_o, EM_co2aq_o, EM_ppCO2_o, EM_Ca_o,
            EM_omega_o, T_surface, buffer_T, F_diss, F_silic, Precip_ocean,
            Precip_pore, EM_omega_p, carb_weath, EM_co3_p, EM_hco3_p,
            EM_co2aq_p, EM_pH_p, EM_Ca_p, EM_co2aq_p
        ]

        # Fill output array with appropriate model outputs:
        co2_aq_o[i] = array_of_outputs[3]
        pH_array_o[i] = array_of_outputs[0]
        CO2_array_o[i] = array_of_outputs[4]
        co2_aq_p[i] = array_of_outputs[17]
        pH_array_p[i] = array_of_outputs[18]
        CO2_array_p[i] = array_of_outputs[20]
        Ca_array_o[i] = array_of_outputs[5]
        Ca_array_p[i] = array_of_outputs[19]
        CO3_array_o[i] = array_of_outputs[1]
        CO3_array_p[i] = array_of_outputs[15]
        HCO3_array_o[i] = array_of_outputs[2]
        HCO3_array_p[i] = array_of_outputs[16]
        omega_o[i] = array_of_outputs[6]
        omega_p[i] = array_of_outputs[13]
        carbw_ar[i] = array_of_outputs[14]
        Tsurf_array[i] = array_of_outputs[7]
        Tdeep_array[i] = array_of_outputs[8]
        Fd_array[i] = array_of_outputs[9]
        Fs_array[i] = array_of_outputs[10]
        Precip_ocean_array[i] = array_of_outputs[11]
        Precip_pore_array[i] = array_of_outputs[12]
        volc_array[i] = F_outgass + change_out * F_outgass * (time[i] / 1e8)

    ############################################################################
    #### Checking for mass balance
    ############################################################################
    #max_el=numpy.size(time)-1
    #tstep=numpy.max(time)/max_el #duration of timestep
    #sources=numpy.sum(volc_array[2:]+carbw_ar[2:])*tstep
    #sinks=numpy.sum(Precip_ocean_array[2:]+Precip_pore_array[2:])*tstep
    #flux_bal=sources-sinks
    #res_change=1.8e20*(CO2_array_o[max_el]-CO2_array_o[2])+Mo*(HCO3_array_o[max_el]+CO3_array_o[max_el]+co2_aq_o[max_el]-co2_aq_o[2]-CO3_array_o[2]-HCO3_array_o[2])+Mp*(HCO3_array_p[max_el]+CO3_array_p[max_el]+co2_aq_p[max_el]-co2_aq_p[2]-CO3_array_p[2]-HCO3_array_p[2])
    #res_change2=(out[max_el,0]-out[2,0])*Mo+(out[max_el,2]-out[2,2])*Mp
    #print flux_bal,res_change,res_change2,Mo*(HCO3_array_o[max_el]+CO3_array_o[max_el]+co2_aq_o[max_el]-co2_aq_o[2]-CO3_array_o[2]-HCO3_array_o[2])+Mp*(HCO3_array_p[max_el]+CO3_array_p[max_el]+co2_aq_p[max_el]-co2_aq_p[2]-CO3_array_p[2]-HCO3_array_p[2])
    #imbalance=(flux_bal-res_change)/(out[max_el,0]*Mo)
    #print imbalance
    imbalance = 0  ## Comment out if wish to calculate mass imbalance
    ############################################################################

    # Return selected outputs to Main_code.py for plotting
    return [
        out[:, 0], out[:, 1], out[:, 2], out[:,
                                             3], time, pH_array_o, CO2_array_o,
        pH_array_p, CO2_array_p, Ca_array_o, Ca_array_p, CO3_array_o,
        CO3_array_p, HCO3_array_o, HCO3_array_p, omega_o, omega_p, Tsurf_array,
        Tdeep_array, Fd_array, Fs_array, Precip_ocean_array, Precip_pore_array
    ], imbalance
示例#6
0
def soln(mchirp):
	return pylab.roots([1., 0., -mchirp**(5./3), -1])[0]**3	
def carbon_cycle(y, t0, Bio_f, ppCO2_00, n, climp, tdep_weath, F_meta_mod,
                 F_out_mantle_mod, pH_00, lfrac, R_carb_00, del_carb0, F_carbw,
                 R_mantle_00, F_sub_mod, coef_for_diss, beta, n_out, mm,
                 growth_timing, new_add_Ca, Ebas, e1, protero_O2, del_org0, e2,
                 j1, j2, j3, org_weath_mod0, thermo_weath, multplic,
                 Mantle_temp_mod):

    Ca_cofactor = new_add_Ca / 5000.0 * (
        (1 - abs(t0) / (4.5e9))**-0.5 - 1)  #Redundant

    global pK1, pK2, H_CO2, salt, Pore_mod, T_surface0, ALK_o, ALK_p, Ca_p, Ca_o, Rcrust0, Rorg0, k_meta0_carb, k_meta0_org, k_sub0_carb, k_sub0_org, F_orgB0, imply_forg0, org_weath0, carb_minus_org, carb_minus_AO
    global landf_vary, lum_vary, salt0, k_w, k_c, k_o, k_r, Mp, ppCO2_o, Mo, ko1, ko2, k_meta0, k_sub0, k_mantle0, k_sub_arc0
    global mantle_mod, Rcrust_mod, Rorg_mod, F_meta_mod_carb, F_meta_mod_org
    global F_sub_mod_carb, F_sub_mod_org, ppCO2_mod, deep_grad

    s = 1.8e20 / Mo
    [c, d] = pylab.roots([
        y[1] / (10**-pK2 * 10**-pK1) * (1 + s / H_CO2),
        (y[1] - y[0]) / (10**-pK2), (y[1] - 2 * y[0])
    ])
    EE_H_o = numpy.max([c, d])
    EE_pH_o = -pylab.log10(EE_H_o)
    EE_co3_o = y[1] / (2 + EE_H_o / (10**-pK2))
    EE_hco3_o = y[1] - 2 * EE_co3_o
    EE_co2aq_o = (EE_hco3_o * EE_H_o / (10**-pK1))
    EE_ppCO2_o = EE_co2aq_o / H_CO2
    EE_Ca_o = Ca_o + 0.5 * (y[1] - ALK_o) + Ca_cofactor

    #pore space
    EE_H_p = EE_H_o
    EE_pH_p = EE_pH_o
    EE_co3_p = EE_co3_o
    EE_hco3_p = EE_hco3_o
    EE_co2aq_p = EE_co2aq_o
    EE_ppCO2_p = EE_ppCO2_o
    EE_Ca_p = EE_Ca_o

    bio_now = 1 - 1 / (1 / (1 - Bio_f) + numpy.exp(-5 * (abs(t0) - 1e9) / 1e9))
    bio_Archean = 1 - 1 / (1 /
                           (1 - Bio_f) + numpy.exp(-5 *
                                                   (abs(4.1e9) - 1e9) / 1e9))
    biology_modern = 1 - 1 / (1 /
                              (1 - Bio_f) + numpy.exp(-5 *
                                                      (abs(0.0) - 1e9) / 1e9))
    biology = bio_now / bio_Archean
    biology_mod = biology_modern / bio_Archean

    Q0 = (1 - abs(4.1e9) / (4.5e9))**-n_out
    Q = (1 - abs(t0) / (4.5e9))**-n_out
    spread = Q**beta

    Mantle_temp = Mantle_temp_mod * (Q)**0.1
    Ccrit = (3.125e-3 * 80.0 + 835.5 - 285.0) / (Mantle_temp - 285.0)
    carb_eff_modifier = numpy.min([1.0, (Ccrit - 0.3) / (0.6 - 0.3)])
    if carb_eff_modifier < 0.0:
        carb_eff_modifier = 0.0

    F_out_mantle = F_out_mantle_mod * (Q**mm) * (y[5] / mantle_mod)
    F_meta_carb = F_meta_mod_carb * (Q**mm) * (y[4] / Rcrust_mod)
    F_meta_org = F_meta_mod_org * (Q**mm) * (y[6] / Rorg_mod)
    F_meta = F_meta_carb + F_meta_org
    F_sub_carb = F_sub_mod_carb * (Q**beta) * (y[4] / Rcrust_mod)
    F_sub_org = F_sub_mod_org * (Q**beta) * (y[6] / Rorg_mod)

    F_sub = F_sub_carb + F_sub_org
    F_sub_arc = F_sub_carb * (1 - carb_eff_modifier) + F_sub_org * e1
    F_outg = F_out_mantle + F_meta + F_sub_arc

    #isotopes
    del_sub = (F_sub_carb * y[8] + F_sub_org * y[7]) / F_sub_arc
    del_arc_volc = (F_sub_carb * (1 - carb_eff_modifier) * y[8] +
                    e1 * F_sub_org * y[7]) / F_sub_arc
    del_meta_volc = (F_meta_carb * y[8] + F_meta_org * y[7]) / F_meta
    del_crust = (y[4] * y[8] + y[6] * y[7]) / (y[4] + y[6])
    del_out = (F_out_mantle * y[9] + F_meta_carb * y[8] + F_meta_org * y[7] +
               F_sub_carb * (1 - carb_eff_modifier) * y[8] +
               (e1) * F_sub_org * y[7]) / F_outg
    carb_minus_org = 0
    carb_minus_AO = 0
    if abs(t0) < 4.0e9:
        carb_minus_org = 28.0
        carb_minus_AO = 2
    del_carb_precip = y[10] + carb_minus_AO
    del_org_buried = del_carb_precip - carb_minus_org

    if landf_vary == "y":
        land = lf(t0, lfrac, growth_timing)
        land_mod = lf(0, lfrac, growth_timing)
    else:
        land = 1
        land_mod = 1

    if lum_vary == "y":
        L_over_Lo = 1 / (1 + 0.4 * (abs(t0) / 4.6e9))
        T_surface = clim_fun(EE_ppCO2_o, L_over_Lo)
    else:
        L_over_Lo = 1 / (1 + 0.4 * (abs(4.1e9) / 4.6e9))
        T_surface = clim_fun(EE_ppCO2_o, L_over_Lo)

    T_surface_mod = clim_fun(ppCO2_mod, 1 / (1 + 0.4 * (abs(0) / 4.6e9)))
    T_surface_diff_mod = T_surface - T_surface_mod
    T_surface_diff = T_surface - T_surface0
    interc = 274.037 - deep_grad * 285.44411576277344
    buffer_T = deep_grad * T_surface + interc
    buffer_Ti = numpy.max([deep_grad * T_surface + interc, 271.15])
    buffer_T = numpy.min([buffer_Ti, T_surface])

    EE_omega_o = EE_Ca_o * EE_co3_o / (Sol_prod(T_surface))
    EE_omega_p = EE_Ca_p * EE_co3_p / (Sol_prod(buffer_T + Pore_mod))

    #ocean carbonate sink
    Carb_sink = ko1 * (land / land_mod) * (EE_omega_o)**n + ko2 * (EE_omega_o**
                                                                   2.84)
    Precip_ocean = Carb_sink
    Precip_pore = k_c * (EE_omega_p)**n

    # Carbonate weathering flux
    carb_weath = (y[4] / Rcrust_mod) * F_carbw * (biology / biology_mod) * (
        EE_ppCO2_o / ppCO2_mod)**(climp) * numpy.exp(
            (T_surface_diff_mod) / tdep_weath) * (land / land_mod)
    F_diss = k_r * (2.88 * 10**-14 * 10**(-coef_for_diss * EE_pH_p) *
                    numpy.exp(-Ebas / (8.314 *
                                       (buffer_T + Pore_mod)))) * spread
    F_silic = k_w * (biology / biology_mod) * (land / land_mod) * (
        EE_ppCO2_o / ppCO2_mod)**climp * numpy.exp(
            (T_surface_diff_mod) / tdep_weath)

    aa = -0.5 * numpy.log10(protero_O2)
    bb = 4.5 + 0.5 * numpy.log10(protero_O2)
    cc = -4.5
    pO2 = 10**(aa * numpy.tanh(-20 * (abs(t0) - 0.55e9) / 1e9) +
               bb * numpy.tanh(-20 * (abs(t0) - 2.45e9) / 1e9) + cc)

    org_weath = org_weath_mod0 * (y[6] / Rorg_mod) * (land / land_mod) * (
        pO2)**0.30809 + thermo_weath * (y[6] / Rorg_mod
                                        )  ## This is running in retrieval

    total_carb_inputs = (carb_weath + org_weath + F_outg)
    if (abs(t0) > 4.0e9):
        F_orgB = 0 * total_carb_inputs
    if (abs(t0) < 4.0e9) and (abs(t0) > 3.9e9):
        F_orgB = j1 * total_carb_inputs * (-abs(t0) + 4.0e9) / 0.1e9
    if (abs(t0) < 3.9e9) and (abs(t0) > 2.5e9):
        F_orgB = j1 * total_carb_inputs
    if (abs(t0) < 2.5e9) and (abs(t0) > 2.4e9):
        inbetween = (abs(t0) - 2.4e9) / 0.1e9
        F_orgB = j1 * total_carb_inputs * inbetween + (
            1 - inbetween) * j2 * j1 * total_carb_inputs
    if (abs(t0) < 2.4e9) and (abs(t0) > 0.6e9):
        F_orgB = j2 * j1 * total_carb_inputs
    if (abs(t0) > 0.5e9) and (abs(t0) < 0.6e9):
        inbetween = (abs(t0) - 0.5e9) / 0.1e9
        F_orgB = j1 * j2 * total_carb_inputs * inbetween + (
            1 - inbetween) * j3 * j2 * j1 * total_carb_inputs
    if (abs(t0) < 0.5e9):
        F_orgB = j3 * j2 * j1 * total_carb_inputs

    if (abs(t0) > 4.0e9):
        tempforg = 0
    if (abs(t0) < 4.0e9) and (abs(t0) > 3.9e9):
        tempforg = j1 * (-abs(t0) + 4.0e9) / 0.1e9
    if (abs(t0) < 3.9e9) and (abs(t0) > 2.5e9):
        tempforg = j1
    if (abs(t0) < 2.5e9) and (abs(t0) > 2.4e9):
        inbetween = (abs(t0) - 2.4e9) / 0.1e9
        tempforg = j1 * inbetween + (1 - inbetween) * j2 * j1
    if (abs(t0) < 2.4e9) and (abs(t0) > 0.6e9):
        tempforg = j2 * j1
    if (abs(t0) > 0.5e9) and (abs(t0) < 0.6e9):
        inbetween = (abs(t0) - 0.5e9) / 0.1e9
        tempforg = j1 * j2 * inbetween + (1 - inbetween) * j3 * j2 * j1
    if (abs(t0) < 0.5e9):
        tempforg = j3 * j2 * j1

    current_volc = F_out_mantle_mod + F_meta_mod + F_sub_mod
    multiplicative = 1 + multplic * abs(t0) / 4.1e9
    O2_fast_sink = multiplicative * 2.4e12 * F_outg / current_volc
    model_modern_forg = j1 * j2 * j3

    reduced_early = (F_orgB + 5.15e12 * tempforg / model_modern_forg -
                     org_weath - O2_fast_sink)
    del_inputs = (F_outg * del_out + org_weath * y[7] +
                  carb_weath * y[8]) / (F_outg + org_weath + carb_weath)
    O2_source = F_orgB + 5.15e12 * (tempforg / model_modern_forg)
    Kox = O2_source / O2_fast_sink

    return [
        EE_pH_o, EE_co3_o, EE_hco3_o, EE_co2aq_o, EE_ppCO2_o, EE_Ca_o,
        EE_omega_o, T_surface, buffer_T, F_diss, F_silic, Precip_ocean,
        Precip_pore, EE_omega_p, F_outg, carb_weath, EE_co3_p, EE_hco3_p,
        EE_co2aq_p, EE_pH_p, EE_ppCO2_p, EE_Ca_p, EE_H_o, EE_H_p,
        T_surface_diff, F_outg, F_meta, F_sub, F_out_mantle, F_meta_carb,
        F_sub_carb, F_meta_org, F_sub_org, org_weath, F_orgB, del_org_buried,
        del_carb_precip, del_crust, del_out, del_inputs, pO2, reduced_early,
        F_sub_arc, del_arc_volc, del_meta_volc, del_sub, 1 - carb_eff_modifier,
        Kox
    ]
示例#8
0
def carbon_cycle(y, t0, W, F_outgass, n, climp, tdep_weath, mod_sea, alt_frac,
                 Mp_frac, lfrac, carb_exp, sed_thick, F_carbw, CWF, deep_grad,
                 coef_for_diss, beta, n_out, mm, growth_timing, new_add_Ca,
                 Ebas):

    ## Ca_cofactor is only important for the sensitivity tests where a wide range of Archean Ca abundances are imposed
    Ca_cofactor = new_add_Ca / 1000.0 * numpy.exp(
        t0 / 1e9 - 4)  # perscribed ocean Ca molality evolution

    global pK1, pK2, H_CO2, salt, Pore_mod, T_surface0, ALK_o, ALK_p, Ca_p, Ca_o, options_array
    global landf_vary, lum_vary, salt0, k_w, k_c, k_o, k_r, Mp, ppCO2_o, Mo, ko1, ko2  #,Mg_fun,Ca_Tfun,coef_for_diss

    #ocean variables
    s = 1.8e20 / Mo  #correction factor for mass balance (see manuscript)

    #### Temperature loop ####
    # This loop is necessary because the carbon chemistry equilibrium constants are temperatue dependent,
    # but surface temperature is controlled by atmospheric pCO2, which is in turn modulated by
    # the carbon chemistry of the ocean. Therefore, several iterations are required to ensure the temperature
    # used to calculate equilibrium constants is the same as the surface climate. Sensitivity tests reveal
    # that three iterations are sufficient for accurate (within 1 degree) convergence.
    # Note that if Carbon_chem is set to 0 then the only a single iteration is executed and
    # the carbon chemistry constants are assumed to be fixed. This is faster and only slightly less
    # accurate than the full calculation.

    ## initial guesses for surface temperature and pore space, to be used to determine equilibrium carbon chemistry constants:
    T_upd = 273 + 18  # initial guess for surface temperature
    T_upd2 = 273 + 18  # initial guess for pore-space temperature

    T_surface = 100.0  # Filler value (T_surface will be calcauled within the loop)

    # Check to see if Carbon_chem is 0 or 1
    if options_array[1] == 0:
        max_temp_iter = 1  # run single iteration
    else:
        max_temp_iter = 3  # run 3 iterations

    jk = 0
    for jk in range(0, max_temp_iter):
        ## Calculate temperature-dependent carbon chemistry constants for the ocean:
        [pK1, pK2, H_CO2] = equil_cont(T_upd)

        # Calculate equilibrium carbon chemistry for the ocean:
        [c, d] = pylab.roots([
            y[1] / (10**-pK2 * 10**-pK1) * (1 + s / H_CO2),
            (y[1] - y[0]) / (10**-pK2), (y[1] - 2 * y[0])
        ])  #equation S15
        EE_H_o = numpy.max([c, d])  ## make sure get right root!
        EE_pH_o = -pylab.log10(EE_H_o)  # equation S16
        EE_co3_o = y[1] / (2 + EE_H_o / (10**-pK2))
        EE_hco3_o = y[1] - 2 * EE_co3_o
        EE_co2aq_o = (EE_hco3_o * EE_H_o / (10**-pK1))  # equation S13
        EE_ppCO2_o = EE_co2aq_o / H_CO2  # equation S12
        EE_Ca_o = Ca_o + 0.5 * (y[1] - ALK_o) + Ca_cofactor  #equation S17

        ## Calculate temperature-dependent carbon chemistry constants for the pore space:
        [pK1, pK2, H_CO2] = equil_cont(T_upd2)

        # Calculate equilibrium carbon chemistry for the pore space:
        [c, d] = pylab.roots([
            y[3] / (10**-pK2 * 10**-pK1), (y[3] - y[2]) / (10**-pK2),
            (y[3] - 2 * y[2])
        ])  # equation S15
        EE_H_p = numpy.max([c, d])  ## make sure get right root!
        EE_pH_p = -pylab.log10(EE_H_p)  # equation S16
        EE_co3_p = y[3] / (2 + EE_H_p / (10**-pK2))
        EE_hco3_p = y[3] - 2 * EE_co3_p
        EE_co2aq_p = (EE_hco3_p * EE_H_p / (10**-pK1))  #equation S14
        EE_ppCO2_p = EE_co2aq_p / H_CO2  #equation S12
        EE_Ca_p = Ca_p + 0.5 * (y[3] - ALK_p) + Ca_cofactor  # equation S17

        # Calculate biological modification of continental weathering using equation S7:
        fb_EE = 1 / (1 - CWF)
        biology_modifier = 1 - 1 / (fb_EE + numpy.exp(-10 *
                                                      (t0 - 0.6e9) / 1e9))
        #biology_modifier=1.0

        # Calculate internal heatflow, outgassing, and spreading rate using equations S8-10:
        Q = (1 - t0 / (4.5e9))**-n_out
        #Q=1.0
        #Q=1-(1-n_out)*(t0/4e9)**2.0 # alternative for lowering outgassing
        F_outg = F_outgass * Q**mm
        #F_outg=F_outgass*Q # alternative for lowering outgassing
        spread = Q

        if landf_vary == "y":
            land = lf(t0, lfrac, growth_timing)
        else:
            land = 1.0

        if lum_vary == "y":
            L_over_Lo = 1 / (
                1 + 0.4 *
                (t0 / 4.6e9))  # Evolution of solar luminosity from Gough 1981.
            if options_array[
                    2] == 1:  # Check to see if methane option is on. If yes, use methane climate models:
                ### Weighting functions for Phanerozoic, Proterozoic, and Archean methane climates (only used high methane tests)
                ### Smooth weighting functions are required because sudden temperature jumps break the model.
                w0 = 1 - 1 / (1 + numpy.exp(-15 * (t0 / 1e9 - 0.541))
                              )  # 1 in the Phanerozoic, 0 elsewhere
                w1 = 1 / (1 + numpy.exp(-15 * (t0 / 1e9 - 0.541))) - 1 / (
                    1 + numpy.exp(-15 * (t0 / 1e9 - 2.5))
                )  # 1 in the Proterozoic, 0 elsewhere
                w2 = 1 / (1 + numpy.exp(-15 * (t0 / 1e9 - 2.5))
                          )  # 1 in the Archean, 0 elsewhere
                arch_temp = clim_fun_highCH4(
                    EE_ppCO2_o,
                    L_over_Lo)  ## Archean temperature with high methane
                Protero_temp = clim_fun_lowCH4(
                    EE_ppCO2_o,
                    L_over_Lo)  ## Proterozoic temperature with high methane

                ### Climate model for eleveated Proterozoic and Archean methane abundances:
                T_surface = (w0 * clim_fun_CO2_only(EE_ppCO2_o, L_over_Lo) +
                             w1 * Protero_temp + w2 * arch_temp) / (w0 + w1 +
                                                                    w2)

            else:  # methane option off -> use CO2 only climate model (nominal model)
                T_surface = clim_fun_CO2_only(EE_ppCO2_o, L_over_Lo)
                ###T_surface=clim_fun_CO2_only(EE_ppCO2_o,L_over_Lo)+30.0 * (1/(1+numpy.exp(-15*(t0/1e9-2.5)))) ## for +30 K sensitivity test
        else:
            T_surface = clim_fun_CO2_only(
                EE_ppCO2_o,
                1.0)  # For CO2-only, no evolution in solar luminosity

        ## Calculate deep ocean temperature
        T_surface_diff = T_surface - T_surface0
        interc = 274.037 - deep_grad * T_surface0  # intercept chosen to reproduce initial (modern) temperature
        buffer_T = deep_grad * T_surface + interc
        buffer_Ti = numpy.max([deep_grad * T_surface + interc,
                               271.15])  # ensures deep ocean is not frozen
        buffer_T = numpy.min(
            [buffer_Ti, T_surface]
        )  # This is deep ocean temperature (cannot be warmer than the surface)

        ## Calculate pore space temperature,
        ## accounting for effect of sediment thickness and heatflow
        Pore_mod_dynamic = Pore_mod
        sed_depth = 700 - 700 * (1 - sed_thick) * t0 / 4e9  # equation S5
        Pore_mod_dynamic = Q * sed_depth / 77.7777777  ## Difference is 9 K for Q=1
        T_pore_space = buffer_T + Pore_mod_dynamic
        #T_pore_space=buffer_T+9.0 # sensitivity test constant temperature difference between pore space and deep ocean

        T_upd = T_surface  #update surface temperature for next iteration
        T_upd2 = T_pore_space  #update pore space temperature for next iteration

    # Calculate saturation state of ocean and pore space (equation S18):
    # combined activity coefficients for Ca and CO3. Assumed to be 1 except for Ca sensitiviy test where complexing is important
    act_o = 1.0  #-7.89*EE_Ca_o**3+10.847*EE_Ca_o**2-5.2246*EE_Ca_o+1.0551 #from Aspen polynomial fit Fig. S20, or 1.0 for nominal case
    act_p = 1.0  #-7.89*EE_Ca_p**3+10.847*EE_Ca_p**2-5.2246*EE_Ca_p+1.0551 #from Aspen polynomial fit Fig. S20, or 1.0 for nominal case
    EE_omega_o = act_o * EE_Ca_o * EE_co3_o / (Sol_prod(T_surface)
                                               )  # saturation state ocean
    EE_omega_p = act_p * EE_Ca_p * EE_co3_p / (Sol_prod(T_pore_space)
                                               )  # saturation state pore space

    #Calculate carbonate sinks
    Carb_sink = ko1 * land * (EE_omega_o - 1)**n + ko2 * (
        EE_omega_o**2.84
    )  # ocean carbonate from equation S19, noting that ko2 is 0 in this version of the model
    Precip_ocean = Carb_sink  ## Precipitaion of carbonate in ocean
    Precip_pore = k_c * (EE_omega_p -
                         1)**n  ## Precipitation of carbonate in pore space

    # Carbonate weathering flux
    carb_weath = F_carbw * biology_modifier * (EE_ppCO2_o / ppCO2_o)**(
        carb_exp) * numpy.exp(
            (T_surface_diff) / tdep_weath) * land  # equation S2

    ### Dissolution of seafloor flux:
    F_diss = k_r * 2.88 * 10**-14 * 10**(-coef_for_diss *
                                         EE_pH_p) * spread**beta * numpy.exp(
                                             -Ebas /
                                             (8.314 *
                                              (T_pore_space)))  # equation S3
    #F_diss=k_r*2.88*10**-14*10**(-coef_for_diss*8.57)*numpy.exp(-Ebas/(8.314*(283))) # sensitivity test holding dissolution artifically constant

    #Continetnal silicate weathering flux
    F_silic = k_w * biology_modifier * land * (
        EE_ppCO2_o / ppCO2_o)**climp * numpy.exp(
            (T_surface_diff) / tdep_weath)  # equation 1

    #return selected carbon cycle variables and fluxes
    return [
        EE_pH_o, EE_co3_o, EE_hco3_o, EE_co2aq_o, EE_ppCO2_o, EE_Ca_o,
        EE_omega_o, T_surface, buffer_T, F_diss, F_silic, Precip_ocean,
        Precip_pore, EE_omega_p, F_outg, carb_weath, EE_co3_p, EE_hco3_p,
        EE_co2aq_p, EE_pH_p, EE_ppCO2_p, EE_Ca_p, EE_H_o, EE_H_p,
        T_surface_diff, F_outg, spread, T_pore_space
    ]  #T_pore_space
示例#9
0
def Forward_Model(W, F_outgass, n, climp, tdep_weath, mod_sea, alt_frac,
                  Mp_frac, lfrac, carb_exp, sed_thick, F_carbw, fpel, CWF,
                  deep_grad, coef_for_diss, beta, n_out, mm, growth_timing,
                  new_add_Ca, Ebas):

    # define global variables:
    global pK1, pK2, H_CO2, salt, Pore_mod, T_surface0, Ca_p, Ca_o, options_array
    global landf_vary, lum_vary, salt0, k_w, k_c, k_o, k_r, Mp, ppCO2_o, Mo, ko1, ko2, ALK_o, ALK_p
    # load options defined in main_code_parallel.py:
    options_array = numpy.load('options_array.npy')

    # Initial (modern) ocean pH and atmospheric pCO2 (bar)
    pH_o = 8.2
    ppCO2_o = .000280

    T = clim_fun_CO2_only(ppCO2_o, 1.0)  # find initial (modern) temperature
    # Calculate equilibrium constants for carbon chemistry:
    [pK1, pK2, H_CO2] = equil_cont(T)

    Mo = 1.35e21  # Mass of ocean (kg)
    W = Mo / W  # convert mixing time of ocean (yr) to mass flux (kg/yr)
    Mp = Mp_frac * Mo  # Mass of water in pore space

    ##############################################################
    ############ Compute other initial conditions ################
    # First, we use the assumed values for modern seafloor carbonate precipitation, outgassing, and seafloor dissolution to carbonate precipitation ratio
    # along with the carbon cycle steady state assumption to calculated the modern seafloor dissolution and continental silciate weathering
    partition = mod_sea / F_outgass
    F_diss0 = alt_frac * partition * F_outgass  #initial seafloor dissolution flux i.e. dissolution = alt_frac*precip_seafloor
    F_sil0 = (1 - partition) * F_outgass + (
        1 - alt_frac
    ) * partition * F_outgass  #initial continental silicate weathering flux
    Fprecip_p = partition * F_outgass  #initial pore space carbonate precipation flux (reduntant)

    #vary solar luminosity? y or n (don't modify these options - better to change elsewhere).
    lum_vary = "y"
    landf_vary = "y"

    ### Initial conditions for modern atmosphere and ocean (equations S12 to S14)
    CO2_aq_o = H_CO2 * ppCO2_o  #aqueous dissolved CO2
    hco3_o = (10**-pK1) * CO2_aq_o / (10**-pH_o)  # aqueous bicarbonate
    co3_o = (10**-pK2) * hco3_o / (10**-pH_o)  #aqueous carbonate
    DIC_o = co3_o + hco3_o + CO2_aq_o  #dissolved inorganic carbon
    ALK_o = 2 * co3_o + hco3_o  #carbonate alkalinity
    Ca_o = 0.0100278  # initial (modern) calcium molality
    salt = ALK_o - 2 * Ca_o  ## set salt to ensure ALK is consistent with Ca
    salt0 = salt  # initial (modern) salt

    T_surface0 = clim_fun_CO2_only(ppCO2_o, 1.0)
    interc = 274.037 - deep_grad * T_surface0
    buffer_T = deep_grad * T_surface0 + interc  #initial deep ocean temperature
    Pore_mod = 9.0  #difference between pore space and deep ocean temperature for modern Earth

    ## Use these constants and steady state assumption to calculate remaining initial conditions:
    b1 = 2 * F_diss0 + W * ALK_o - 2 * W * DIC_o
    b2 = 2 * F_sil0 - W * ALK_o - 2 * F_outgass + 2 * W * DIC_o
    a1 = W
    a2 = -2 * W
    a3 = -W
    a4 = 2 * W

    # Solving system of equations for pore space properties
    DIC_p = DIC_o - Fprecip_p / W
    ALK_p = (b1 - a2 * DIC_p) / a1
    Fprecip_o = (F_outgass + F_carbw) - (DIC_o - DIC_p) * W

    if DIC_p == 0:
        print "WARNING: NO PHYSIAL STEADY STATE EXISTS! DIC is negative"

    #Solve quadratic ignoring H in ALK but including CO2aq
    [vv, xx] = pylab.roots([
        ALK_p / (10**-pK1 * 10**-pK2), (ALK_p - DIC_p) / (10**-pK2),
        ALK_p - 2 * DIC_p
    ])  #equation S15
    H_p = numpy.max([vv, xx])  # take positive root
    pH_p = -pylab.log10(H_p)

    #Find remaining carbon chemistry from equilibrium conditions:
    CO2aq_p = DIC_p / ((10**-pK1) * (10**-pK2) / H_p**2 + 10**-pK1 / H_p + 1)
    co3_p = ALK_p - DIC_p - H_p + CO2aq_p  ## only true for high pH, okay for fitting I think (actually should include CO2aq to get exact).
    hco3_p = co3_p * 10**-pH_p / (
        10**-pK2)  #Modern bicarbonate alkalinity in pore space (not used)

    Ca_p = 0.5 * (ALK_p - salt)  #initial calcium molality in pore space
    omega_p = Ca_p * co3_p / Sol_prod(
        buffer_T + Pore_mod)  # saturation state pore space
    omega_o = Ca_o * co3_o / Sol_prod(T_surface0)  # saturation state ocean
    ## All initital conditions have been calculated ############################
    ############################################################################

    ############ Calculate proportionality constants ###########################
    # Given modern precipitation fluxes and saturation states, calculate proportionality constants
    k_c = Fprecip_p / (omega_p - 1)**n
    k_o = Fprecip_o / (omega_o - 1)**n

    ## Partition ocean carbonate sink into shelf precipitation and carbonate precipitation
    frac_pel = fpel  # no pelagic carbonates in this version of the code (i.e. default is fpel=0)
    ko1 = (1 - frac_pel) * Fprecip_o / (omega_o - 1)**n
    ko2 = frac_pel * Fprecip_o / (omega_o**2.84)

    ### remaining proportionality constants
    k_r = F_diss0 / (2.88 * 10**-14 * 10**(-coef_for_diss * pH_p) * numpy.exp(
        -Ebas / (8.314 * (buffer_T + Pore_mod))))  #for seafloor dissolution
    k_w = F_sil0  # for continental silicate weathering

    time = numpy.linspace(
        0, 4e9, 100
    )  #define time array from 0 to 4 Ga in 100 time steps. Number of time steps can be increased for greater precision (takes longer)
    # run ode solver with initial conditions defined above, and inputs from main_code_parallel.py. The ode solver will output the dissolved inorganic carbon and
    # alkalinities of the ocean and pore space through time (all containted in 'out'). The diagnostic 'mes' is also returned
    [out, mes] = scipy.integrate.odeint(
        system_of_equations,
        [DIC_o + 1.8e20 / Mo * ppCO2_o, ALK_o, DIC_p, ALK_p],
        time,
        args=(W, F_outgass, n, climp, tdep_weath, mod_sea, alt_frac, Mp_frac,
              lfrac, carb_exp, sed_thick, F_carbw, CWF, deep_grad,
              coef_for_diss, beta, n_out, mm, growth_timing, new_add_Ca, Ebas),
        full_output=1)

    # Given alkalinities and dissolved inorganic carbon, calculate time-evolution for other carbon cycle variables
    # define empty arrays for variables of interest:

    pH_array_o = 0 * time  #ocean pH
    CO2_array_o = 0 * time  # atmospheric CO2
    pH_array_p = 0 * time  # pore space pH
    CO2_array_p = 0 * time  # pore space CO2
    Ca_array_o = 0 * time  # ocean calcium molality
    Ca_array_p = 0 * time  # pore space calcium molality
    CO3_array_o = 0 * time  # ocean carbonate molality
    CO3_array_p = 0 * time  # pore space carbonate molality
    HCO3_array_o = 0 * time  # ocean bicarbonate molality
    HCO3_array_p = 0 * time  # pore space bicarbonate molality
    omega_o = 0 * time  # saturation state ocean
    omega_p = 0 * time  # saturation state pore space
    Tsurf_array = 0 * time  # Surface temperature
    Tdeep_array = 0 * time  # Deep ocean temperature
    Fd_array = 0 * time  # Seafloor dissolution
    Fs_array = 0 * time  # Continental silciate weathering
    Precip_ocean_array = 0 * time  # ocean carbonate precipitation
    Precip_pore_array = 0 * time  # pore space carbonate precipitation
    volc_array = 0 * time  # volcanic outgassing
    carbw_ar = 0 * time  # Continental carbonate weathering
    co2_aq_o = 0 * time  # ocean aqueous CO2
    co2_aq_p = 0 * time  # pore space aqueous CO2
    spread_ar = 0 * time  # spreading rate relative to modern
    T_pore_space_ar = 0 * time  # pore space temperature

    for i in range(0, len(time)):
        # using ode solution (alkalinities and DIC abundances) and input parameters, fill array pl1 with other carbon cycle evolution variables
        pl1 = carbon_cycle([out[i, 0], out[i, 1], out[i, 2], out[i, 3]],
                           time[i], W, F_outgass, n, climp, tdep_weath,
                           mod_sea, alt_frac, Mp_frac, lfrac, carb_exp,
                           sed_thick, F_carbw, CWF, deep_grad, coef_for_diss,
                           beta, n_out, mm, growth_timing, new_add_Ca,
                           Ebas)  #ocean
        # Fill in arrays define above
        pH_array_o[i] = pl1[0]
        co2_aq_o[i] = pl1[3]
        CO2_array_o[i] = pl1[4]
        pH_array_p[i] = pl1[19]
        CO2_array_p[i] = pl1[20]
        Ca_array_o[i] = pl1[5]
        Ca_array_p[i] = pl1[21]
        CO3_array_o[i] = pl1[1]
        CO3_array_p[i] = pl1[16]
        HCO3_array_o[i] = pl1[2]
        HCO3_array_p[i] = pl1[17]
        co2_aq_p[i] = pl1[18]
        omega_o[i] = pl1[6]
        omega_p[i] = pl1[13]
        Tsurf_array[i] = pl1[7]
        Tdeep_array[i] = pl1[8]
        Fd_array[i] = pl1[9]
        Fs_array[i] = pl1[10]
        Precip_ocean_array[i] = pl1[11]
        Precip_pore_array[i] = pl1[12]
        carbw_ar[i] = pl1[15]
        volc_array[i] = pl1[14]
        spread_ar[i] = pl1[26]
        T_pore_space_ar[i] = pl1[27]

    max_el = numpy.size(time) - 1  #number of elements in time array
    tstep = numpy.max(time) / max_el  #time step (yrs) in time array

    # calculate mass imbalance
    flux_bal = numpy.sum(volc_array[2:] + carbw_ar[2:]) * tstep - numpy.sum(
        Precip_ocean_array[2:] + Precip_pore_array[2:]
    ) * tstep  # integral of carbon inputs minus outpus over all timesteps
    res_change = 1.8e20 * (CO2_array_o[max_el] - CO2_array_o[2]) + Mo * (
        HCO3_array_o[max_el] + CO3_array_o[max_el] + co2_aq_o[max_el] -
        co2_aq_o[2] - CO3_array_o[2] - HCO3_array_o[2]
    ) + Mp * (
        HCO3_array_p[max_el] + CO3_array_p[max_el] + co2_aq_p[max_el] -
        co2_aq_p[2] - CO3_array_p[2] - HCO3_array_p[2]
    )  # final - initial carbon abundances (starting at second element to avoid transients)
    res_change2 = (out[max_el, 0] - out[2, 0]) * Mo + (
        out[max_el, 2] - out[2, 2]
    ) * Mp  # alternative way of calculating final - initial carbon abundances

    imbalance = (flux_bal - res_change) / (
        out[max_el, 0] * Mo
    )  # difference between integrated flux balance and final-initial abundances (should be zero).

    # return selected carbon cycle outputs to main_code_parallel.py
    return [
        out[:, 0], out[:, 1], out[:, 2], out[:, 3], time, pH_array_o,
        CO2_array_o, pH_array_p, CO2_array_p, Ca_array_o, Ca_array_p,
        CO3_array_o, CO3_array_p, HCO3_array_o, HCO3_array_p, omega_o, omega_p,
        Tsurf_array, Tdeep_array, Fd_array, Fs_array, Precip_ocean_array,
        Precip_pore_array, spread_ar, volc_array, T_pore_space_ar
    ], imbalance