Compute coefficients for anthropogenic CO$_2$ perturbation approach


James Orr

LSCE/IPSL

26 March 2018

Introduction and set up to use R

The perturbation approach developped in Sarmiento et al.,(1992) identifies a linear relation between the Ocean anthropogenic change in $p$CO$_2$ and its ratio with the corresponding ocean change in total carbon :

\begin{eqnarray} \frac{\delta p CO_{2_o}}{\delta C_T} = z_0 + z_1 \delta p CO_{2_o} \hbox{.} \end{eqnarray}

where $z_0$ and $z_1$ are quadratic functions of temperature, i.e : \begin{eqnarray} z_0 = a_0 + a_1 T + a_2 T^2 \hbox{,} \end{eqnarray} and \begin{eqnarray} z_1 = b_0 + b_1 T + b_2 T^2 \hbox{.} \end{eqnarray}

Below we demonstrate how the coefficients needed to calculate $z_0$ and $z_1$ (i.e : $a_i$ and $b_i$) have been calculated considering two different reference states (1765 and 1870), with one set of coefficients for each.

The seacarb package is used to make these calculations (using the Rmagic environment in a Jupyter notebook).

0. Set up to use R

Start by loading Rmagic, which is part of Rpy2 for iPython.

In [1]:
%reload_ext rpy2.ipython

Then launch R and install the needed R libraries (packages), if they are not already installed. After installing, comment out corresponding line as below.

In [2]:
%%R
#  remove.packages('seacarb')
#  install.packages('seacarb')
#  install.packages('abind')
NULL

Continue in the same R session.

1. Initialise the basic information needed to compute the ocean carbonate chemistry.

In the next cell, chose between the Global conditions (compute the GLO approach coefficients) and Mediterranean Sea conditions (compute the MED coefficients). That is, uncomment the preferred choice, and comment out the other (precede lines by #).

In [3]:
%%R
# Load library to compute carbonate chemistry
  library(seacarb)

# REFERENCE atm xCO2: Mole fraction (ppm) measured in dry air
# xCO2o = 280.0     #(Sarmiento et al., 1992)
  xCO2o = 277.860   #(xCO2atm at time 1765.0 in record from Meinshausen et al. (2017, GMD, Supplement)
# xCO2o = 287.290   #(xCO2atm at time 1870.0 in combined record from M17 & J. Simeon's forcing for ORCA05)

## Global ocean:
  Temp <- seq( -1.5, 30, by=0.5)
  Salt = 35
  TA = 2300e-6
  # Maximum perturbation
  delpco2MAX = 280. 


## Mediterranean Sea:
#  Temp <- seq(13, 30, by=1)
#  Salt = 38
#  TA = 2600e-6
#  delpco2MAX = 280.
/homel/orr/anaconda2/lib/python2.7/site-packages/rpy2/rinterface/__init__.py:186: RRuntimeWarning: Loading required package: oce

  warnings.warn(x, RRuntimeWarning)
/homel/orr/anaconda2/lib/python2.7/site-packages/rpy2/rinterface/__init__.py:186: RRuntimeWarning: Loading required package: gsw

  warnings.warn(x, RRuntimeWarning)

2. Correct for atmospheric humidity (100%) at equilibrium, see Sarmiento et al. (1992 - Eq. 9)

Compute initial field pCO$_{2,o}$, which varies with temperature (due to humidity correction)

In [4]:
%%R
tk     <- Temp + 273.15   #Absolute temperature (K)
LNespa <- 20.1050 - 0.0097982*tk - 6163.10/tk
espa   <- exp(LNespa)
pCO2o  <- xCO2o * (1 - espa)   #Convert from mole fraction (ppm) to partial pressure (uatm), assumes Patm = 1 atm
In [5]:
%%R
help(carb)
R Help on ‘carb’carb                  package:seacarb                  R Documentation

_P_a_r_a_m_e_t_e_r_s _o_f _t_h_e _s_e_a_w_a_t_e_r _c_a_r_b_o_n_a_t_e _s_y_s_t_e_m

_D_e_s_c_r_i_p_t_i_o_n:

     Returns parameters of the seawater carbonate system.

_U_s_a_g_e:

     carb(flag, var1, var2, S=35, T=25, Patm=1, P=0, Pt=0, Sit=0,
             k1k2="x", kf="x", ks="d", pHscale="T", b="u74", gas="potential", 
             warn="y", eos="eos80", long=1.e20, lat=1.e20)
     
_A_r_g_u_m_e_n_t_s:

    flag: select the couple of variables available. The flags which can
          be used are:

          flag = 1 pH and CO2 given

          flag = 2 CO2 and HCO3 given

          flag = 3 CO2 and CO3 given

          flag = 4 CO2 and ALK given

          flag = 5 CO2 and DIC given

          flag = 6 pH and HCO3 given

          flag = 7 pH and CO3 given

          flag = 8 pH and ALK given

          flag = 9 pH and DIC given

          flag = 10 HCO3 and CO3 given

          flag = 11 HCO3 and ALK given

          flag = 12 HCO3 and DIC given

          flag = 13 CO3 and ALK given

          flag = 14 CO3 and DIC given

          flag = 15 ALK and DIC given

          flag = 21 pCO2 and pH given

          flag = 22 pCO2 and HCO3 given

          flag = 23 pCO2 and CO3 given

          flag = 24 pCO2 and ALK given

          flag = 25 pCO2 and DIC given

    var1: Value of the first variable in mol/kg, except for pH and for
          pCO2 in muatm

    var2: Value of the second variable in mol/kg, except for pH

       S: Salinity

       T: Temperature in degrees Celsius

    Patm: Surface atmospheric pressure in atm, default is 1 atm

       P: Hydrostatic pressure in bar (surface = 0)

      Pt: Concentration of total phosphate in mol/kg; set to 0 if NA

     Sit: Concentration of total silicate in mol/kg; set to 0 if NA

    k1k2: "l" for using K1 and K2 from Lueker et al. (2000), "m06" from
          Millero et al. (2006), "m10" from Millero (2010), "w14" from
          Waters et al. (2014), and "r" from Roy et al. (1993). "x" is
          the default flag; the default value is then "l", except if T
          is outside the range 2 to 35oC and/or S is outside the range
          19 to 43. In these cases, the default value is "w14".

      kf: "pf" for using Kf from Perez and Fraga (1987) and "dg" for
          using Kf from Dickson and Riley (1979 in Dickson and Goyet,
          1994). "x" is the default flag; the default value is then
          "pf", except if T is outside the range 9 to 33oC and/or S is
          outside the range 10 to 40. In these cases, the default is
          "dg".

      ks: "d" for using Ks from Dickson (1990) and "k" for using Ks
          from Khoo et al. (1977), default is "d"

 pHscale: "T" for the total scale, "F" for the free scale and "SWS" for
          using the seawater scale, default is "T" (total scale)

       b: Concentration of total boron. "l10" for the Lee et al. (2010)
          formulation or "u74" for the Uppstrom (1974) formulation,
          default is "u74"

     gas: used to indicate the convention for INPUT pCO2, i.e., when it
          is an input variable (flags 21 to 25): "insitu" indicates it
          is referenced to in situ pressure and in situ temperature;
          "potential" indicates it is referenced to 1 atm pressure and
          potential temperature; and "standard" indicates it is
          referenced to 1 atm pressure and in situ temperature. All
          three options should give identical results at surface
          pressure. This option is not used when pCO2 is not an input
          variable (flags 1 to 15). The default is "potential".

    warn: "y" to show warnings when T or S go beyond the valid range
          for constants; "n" to supress warnings. The default is "y".

     eos: "teos10" to specify T and S according to Thermodynamic
          Equation Of Seawater - 2010 (TEOS-10); "eos80" to specify T
          and S according to EOS-80.

    long: longitude of data point, used when eos parameter is "teos10"
          as a conversion parameter from absolute to practical
          salinity.

     lat: latitude of data point, used when eos parameter is "teos10".

_D_e_t_a_i_l_s:

     The Lueker et al. (2000) constants for K1 and K2, the Perez and
     Fraga (1987) constant for Kf and the Dickson (1990) constant for
     Ks are recommended by Dickson et al. (2007). It is, however,
     critical to consider that each formulation is only valid for
     specific ranges of temperature and salinity:

     _For K1 and K2:_

        • Roy et al. (1993): S ranging between 5 and 45 and T ranging
          between 0 and 45oC.

        • Lueker et al. (2000): S ranging between 19 and 43 and T
          ranging between 2 and 35oC.

        • Millero et al. (2006): S ranging between 0.1 and 50 and T
          ranging between 1 and 50oC.

        • Millero (2010): S ranging between 1 and 50 and T ranging
          between 0 and 50oC. Millero (2010) provides a K1 and K2
          formulation for the seawater, total and free pH scales.
          Therefore, when this method is used and if P=0, K1 and K2 are
          computed with the formulation corresponding to the pH scale
          given in the flag "pHscale".

     _For Kf:_

        • Perez and Fraga (1987): S ranging between 10 and 40 and T
          ranging between 9 and 33oC.

        • Dickson and Riley (1979 in Dickson and Goyet, 1994): S
          ranging between 0 and 45 and T ranging between 0 and 45oC.

     _For Ks:_

        • Dickson (1990): S ranging between 5 and 45 and T ranging
          between 0 and 45oC.

        • Khoo et al. (1977): S ranging between 20 and 45 and T ranging
          between 5 and 40oC.

     The arguments can be given as a unique number or as vectors. If
     the lengths of the vectors are different, the longer vector is
     retained and only the first value of the other vectors is used. It
     is recommended to use either vectors with the same dimension or
     one vector for one argument and numbers for the other arguments.

     _Pressure corrections and pH scale:_

        • For K0, the pressure correction term of Weiss (1974) is used.

        • For K1, K2, pK1, pK2, pK3, Kw, Kb, Khs and Ksi, the pressure
          correction was applied on the seawater scale. Hence, if
          needed, values were first transformed from the total scale to
          the seawater scale, the pressure correction applied as
          described by Millero (1995), and the value was transformed
          back to the required scale (T, F or SWS).

        • For Kf, the pressure correction was applied on the free
          scale. The formulation of Dickson and Riley (1979 in Dickson
          and Goyet, 1994) provides Kf on the free scale but that of
          Perez and Fraga (1987) provides it on the total scale. Hence,
          in that case, Kf was first transformed from the total scale
          to the free scale. With both formulations, the pressure
          correction was applied as described by Millero (1995), and
          the value was transformed back to the required scale (T, F or
          SWS).

        • For Ks, the pressure correction was applied on the free
          scale. The pressure correction was applied as described by
          Millero (1995), and the value was transformed back to the
          required scale (T, F or SWS).

        • For Kn, The pressure correction was applied on the seawater
          scale. The pressure correction was applied as described by
          Millero (1995), and the value was transformed back to the
          required scale (T, F or SWS).

     long and lat are used as conversion parameters from absolute to
     practical salinity: when seawater is not of standard composition,
     practical salinity alone is not sufficient to compute absolute
     salinity and vice-versa. One needs to know the density. When long
     and lat are given, density is inferred from WOA silicate
     concentration at given location. When they are not, an arbitrary
     geographic point is chosen: mid equatorial Atlantic. Note that
     this implies an error on computed salinity up to 0.02 g/kg.

_V_a_l_u_e:

     The function returns a data frame containing the following
     columns:

       S: Salinity

       T: Temperature in degrees Celsius

    Patm: Surface atmospheric pressure in atm

       P: Hydrostatic pressure in bar

      pH: pH

     CO2: CO2 concentration (mol/kg)

    pCO2: "standard" pCO2, CO2 partial pressure computed at in situ
          temperature and atmospheric pressure (muatm)

    fCO2: "standard" fCO2, CO2 fugacity computed at in situ temperature
          and atmospheric pressure (muatm)

 pCO2pot: "potential" pCO2, CO2 partial pressure computed at potential
          temperature and atmospheric pressure (muatm)

 fCO2pot: "potential" fCO2, CO2 fugacity computed at potential
          temperature and atmospheric pressure (muatm)

pCO2insitu: "in situ" pCO2, CO2 partial pressure computed at in situ
          temperature and total pressure (atm + hydrostatic) (muatm)

fCO2insitu: "in situ" fCO2, CO2 fugacity computed at in situ
          temperature and total pressure (atm + hydrostatic) (muatm)

    HCO3: HCO3 concentration (mol/kg)

     CO3: CO3 concentration (mol/kg)

     DIC: DIC concentration (mol/kg)

     ALK: ALK, total alkalinity (mol/kg)

OmegaAragonite: Omega aragonite, aragonite saturation state

OmegaCalcite: Omega calcite, calcite saturation state

_N_o_t_e:

     *Warning:* pCO2 estimates below 100 m are subject to considerable
     uncertainty. See Weiss (1974) and Orr et al. (2015)

_A_u_t_h_o_r(_s):

     Heloise Lavigne, James Orr and Jean-Pierre Gattuso <email:
     gattuso@obs-vlfr.fr>

_R_e_f_e_r_e_n_c_e_s:

     Dickson A. G. and Riley J. P., 1979 The estimation of acid
     dissociation constants in seawater media from potentiometric
     titrations with strong base. I. The ionic product of water.
     _Marine Chemistry_ *7*, 89-99.

     Dickson A. G., 1990 Standard potential of the reaction: AgCI(s) +
     1/2H2(g) = Ag(s) + HCI(aq), and the standard acidity constant of
     the ion HSO4 in synthetic sea water from 273.15 to 318.15 K.
     _Journal of Chemical Thermodynamics_ *22*, 113-127.

     Dickson A. G., Sabine C. L. and Christian J. R., 2007 Guide to
     best practices for ocean CO2 measurements. _PICES Special
     Publication_ *3*, 1-191.

     Khoo H. K., Ramette R. W., Culberson C. H. and Bates R. G., 1977
     Determination of Hydrogen ion concentration in seawater from 5 to
     40oC: standard potentials at salinities from 20 to 45. _Analytical
     Chemistry_ *49*, 29-34.

     Lee K., Tae-Wook K., Byrne R.H., Millero F.J., Feely R.A. and Liu
     Y-M, 2010 The universal ratio of the boron to chlorinity for the
     North Pacific and North Atlantoc oceans. _Geochimica et
     Cosmochimica Acta_ *74* 1801-1811.

     Lueker T. J., Dickson A. G. and Keeling C. D., 2000 Ocean pCO2
     calculated from dissolved inorganic carbon, alkalinity, and
     equations for K1 and K2: validation based on laboratory
     measurements of CO2 in gas and seawater at equilibrium. _Marine
     Chemistry_ *70* 105-119.

     Millero F. J., 1995. Thermodynamics of the carbon dioxide system
     in the oceans. _Geochimica Cosmochimica Acta_ *59*: 661-677.

     Millero F. J., 2010. Carbonate constant for estuarine waters.
     _Marine and Freshwater Research_ *61*: 139-142.

     Millero F. J., Graham T. B., Huang F., Bustos-Serrano H. and
     Pierrot D., 2006. Dissociation constants of carbonic acid in
     seawater as a function of salinity and temperature.  _Marine
     Chemistry_ *100*, 80-84.

     Orr J. C., Epitalon J.-M. and Gattuso J.-P., 2015. Comparison of
     seven packages that compute ocean carbonate chemistry.
     _Biogeosciences_ *12*, 1483-1510.

     Perez F. F. and Fraga F., 1987 Association constant of fluoride
     and hydrogen ions in seawater. _Marine Chemistry_ *21*, 161-168.

     Roy R. N., Roy L. N., Vogel K. M., Porter-Moore C., Pearson T.,
     Good C. E., Millero F. J. and Campbell D. M., 1993. The
     dissociation constants of carbonic acid in seawater at salinities
     5 to 45 and temperatures 0 to 45oC. _Marine Chemistry_ *44*,
     249-267.

     Uppstrom L.R., 1974 The boron/chlorinity ratio of the deep-sea
     water from the Pacific Ocean. _Deep-Sea Research I_ *21*, 161-162.

     Waters, J., Millero, F. J., and Woosley, R. J., 2014. Corrigendum
     to ``The free proton concentration scale for seawater pH'',
     [MARCHE: 149 (2013) 8-22], Marine Chemistry *165*, 66-67.

     Weiss, R. F., 1974. Carbon dioxide in water and seawater: the
     solubility of a non-ideal gas, _Mar.  Chem._, *2*, 203-215.

     Weiss, R. F. and Price, B. A., 1980. Nitrous oxide solubility in
     water and seawater, _Marine Chemistry_, *8*, 347-359.

     Zeebe R. E. and Wolf-Gladrow D. A., 2001 _CO2 in seawater:
     equilibrium, kinetics, isotopes_. Amsterdam: Elsevier, 346 pp.

_E_x_a_m_p_l_e_s:

     ## With a couple of variables
     carb(flag=8, var1=8.2, var2=0.00234, S=35, T=25, P=0, Patm=1.0, Pt=0, Sit=0,
             pHscale="T", kf="pf", k1k2="l", ks="d", b="u74")
     
     ## Using vectors as arguments
     flag <- c(8, 2, 8)
     var1 <- c(8.2, 7.477544e-06, 8.2)
     var2 <- c(0.002343955, 0.001649802, 2400e-6)
     S <- c(35, 35, 30)
     T <- c(25, 25, 30)
     P <- c(0, 0, 0)
     Pt <- c(0, 0, 0)
     Sit <- c(0, 0, 0)
     kf <- c("pf", "pf", "pf")
     k1k2 <- c("l", "l", "l")
     pHscale <- c("T", "T", "T")
     b <- c("l10", "l10", "l10")
     carb(flag=flag, var1=var1, var2=var2, S=S, T=T, P=P,
       Pt=Pt, Sit=Sit, kf=kf, k1k2=k1k2, pHscale=pHscale, b=b)
     
     ## Test with all flags 
     flag <- c((1:15), (21:25))
     var1 <- c(8.200000, 7.308171e-06, 7.308171e-06, 7.308171e-06, 7.308171e-06, 
             8.2, 8.2, 8.2, 8.2, 0.001646857, 0.001646857, 0.001646857, 0.0002822957, 
             0.0002822957, 0.00234, 258.2164, 258.2164, 258.2164, 258.2164, 258.2164 )
     var2 <- c(7.308171e-06, 0.001646857, 0.0002822957, 0.00234, 0.001936461, 
             0.001646857, 0.0002822957, 0.00234, 0.001936461, 0.0002822957, 
             0.00234, 0.001936461,  0.00234, 0.001936461, 0.001936461, 8.2, 
             0.001646857, 0.0002822957, 0.00234, 0.001936461)
     carb(flag=flag, var1=var1, var2=var2)
     
     ## Test using a data frame 
     data(seacarb_test_P0)   #test data set for P=0 (surface)
     tab <- seacarb_test_P0[14:19,]
     
     ## method 1 using the column numbers
     carb(flag=tab[[1]], var1=tab[[2]], var2=tab[[3]], S=tab[[4]], T=tab[[5]], 
     P=tab[[6]], Sit=tab[[8]], Pt=tab[[7]])
     
     ## method 2 using the column names
     carb(flag=tab$flag, var1=tab$var1, var2=tab$var2, S=tab$S, T=tab$T, 
     P=tab$P, Sit=tab$Sit, Pt=tab$Pt)
     

3. Compute corresponding (pre-industrial) DIC field with DIC0 = f(T)

In [6]:
%%R
carb0 <- carb(flag=24, var1=pCO2o, var2=TA, S=Salt, T=Temp, P=0, Patm=1, Pt=0, Sit=0, 
              k1k2="l", kf="dr", ks="d", pHscale="T", b="u74", gas="standard")
dic0 <- carb0$DIC

4. Increase ocean pCO$_2$ incrementally & compute corresponding surface DIC each time for all $T$'s

That is, do so by specifying $\delta$pCO$_2$ from 0 to 280 ppm and computing the corresponding change in surface DIC.

In [7]:
%%R
DIC  <- numeric(0) ; pCO2 <- numeric(0)
delDIC  <- numeric(0) ; delpCO2 <- numeric(0)
In [8]:
%%R
DIC  <- numeric(0) ; pCO2 <- numeric(0)
delDIC  <- numeric(0) ; delpCO2 <- numeric(0)

  for (i in seq(1,delpco2MAX,1)) {
    #print(c("delpCO2 =", i))
    carbdel <- carb(flag=24, var1=pCO2o+i, var2=TA, S=Salt, T=Temp, P=0, Patm=1, Pt=0, Sit=0, 
                    k1k2="l", kf="dr", ks="d", pHscale="T", b="u74", gas="standard")
    dic <- carbdel$DIC
    pco2 <- carbdel$pCO2
    DIC  <- rbind(DIC, dic)
    pCO2 <- rbind(pCO2, pco2)
    delDIC  <- rbind(delDIC, dic - dic0)
    delpCO2 <- rbind(delpCO2, pco2 - pCO2o)
   }

5. Compute linear regression coefficients (slope and intercept) as a function of temperature

Compute $z_0$ and $z_1$, i.e., the intercept and slope relating the ratio $\frac{\delta pCO_2}{\delta C_T}$ and $\delta C_T$. Do so by a linear regression.

In [9]:
%%R
  delDIC <- delDIC * 1e+6   #Convert from mol/kg to umol/kg
  ratio <- delpCO2 / delDIC

 Z0  <- numeric(0) ; Z1  <- numeric(0) 
  for (i in 1:length(Temp)) {
    z0 <- lm(ratio[,i] ~ delpCO2[,i])$coeff[[1]]  #Intercept
    z1 <- lm(ratio[,i] ~ delpCO2[,i])$coeff[[2]]  #Slope
    Z0 <- append(Z0, z0)
    Z1 <- append(Z1, z1)
  }

6. Fit each linear regression coefficient to a quadratic equation in Temperature

Fit each linear regression coefficient to a quadratic equation in Temperature to deduce the $a_i$ and $b_i$ coefficients.

In [10]:
%%R
    t <- Temp
    t2 <- t^2
    s0 <- summary(lm(Z0 ~ t + t2))
    s1 <- summary(lm(Z1 ~ t + t2))
    print(s0)
    print(s1)
Call:
lm(formula = Z0 ~ t + t2)

Residuals:
       Min         1Q     Median         3Q        Max 
-0.0076381 -0.0026519  0.0000724  0.0026905  0.0067048 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept)  1.748e+00  9.490e-04 1842.15   <2e-16 ***
t           -3.281e-02  1.538e-04 -213.39   <2e-16 ***
t2           4.186e-04  5.182e-06   80.77   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.003162 on 61 degrees of freedom
Multiple R-squared:  0.9998,	Adjusted R-squared:  0.9997 
F-statistic: 1.223e+05 on 2 and 61 DF,  p-value: < 2.2e-16


Call:
lm(formula = Z1 ~ t + t2)

Residuals:
       Min         1Q     Median         3Q        Max 
-3.431e-05 -7.236e-06 -5.000e-07  8.493e-06  1.408e-05 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept)  3.961e-03  3.063e-06 1293.12   <2e-16 ***
t           -7.373e-05  4.964e-07 -148.53   <2e-16 ***
t2           5.476e-07  1.673e-08   32.73   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1.021e-05 on 61 degrees of freedom
Multiple R-squared:  0.9997,	Adjusted R-squared:  0.9996 
F-statistic: 8.904e+04 on 2 and 61 DF,  p-value: < 2.2e-16

7. Retrieve coefficients from quadratic fits, and write them to output file

In [11]:
%%R
# 7) Retrieve coefficients from quadratic fits, and write them to output file

#   Coefficients, associated errors, and R^2 for Z0 = a0 + a1*t + a2*t^2
    a0 <- (lm(Z0 ~ t + t2))$coeff[[1]]
    a1 <- (lm(Z0 ~ t + t2))$coeff[[2]]
    a2 <- (lm(Z0 ~ t + t2))$coeff[[3]]
    ae0 <- s0$coefficients[[1,2]]      #Std. Error of a0
    ae1 <- s0$coefficients[[2,2]]      #Std. Error of a1
    ae2 <- s0$coefficients[[3,2]]      #Std. Error of a2
    aR2 <- s0$adj.r.squared            #Adjusted R^2

#   Coefficients, associated errors, and R^2 for Z1 = a0 + a1*t + a2*t^2
    b0 <- (lm(Z1 ~ t + t2))$coeff[[1]]
    b1 <- (lm(Z1 ~ t + t2))$coeff[[2]]
    b2 <- (lm(Z1 ~ t + t2))$coeff[[3]]
    be0 <- s1$coefficients[[1,2]]      #Std. Error of b0
    be1 <- s1$coefficients[[2,2]]      #Std. Error of b1
    be2 <- s1$coefficients[[3,2]]      #Std. Error of b2
    bR2 <- s1$adj.r.squared            #Adjusted R^2

The calculation is now completed. Below are the $a_i$ and $b_i$ coefficients, and their respective standard error ($ae_i$ and $be_i$):

In [12]:
%%R
## present the coefficients :
## coefficients ai, bi, and ci (i index varies from 0 to 9) used to compute z1, z2 and z3 (equation 13 of the manuscript):
part00 <- data.frame("i", "ai", "bi")
part0  <- data.frame("0", a0, b0)
part1  <- data.frame("1", a1, b1)
part2  <- data.frame("2", a2, b2)

partA0 <- data.frame( a0,'+/-',ae0, a1,'+/-',ae1, a2,'+/-',ae2)
partB0 <- data.frame( b0,'+/-',be0, b1,'+/-',be1, b2,'+/-',be2)
partA0
#cat(partB0)
        a0 X.....         ae0          a1 X......1          ae1          a2
1 1.748145    +/- 0.000948968 -0.03281331      +/- 0.0001537704 0.000418554
  X......2          ae2
1      +/- 5.182273e-06
In [13]:
%%R
partB0
           b0 X.....          be0            b1 X......1          be1
1 0.003961463    +/- 3.063504e-06 -7.373295e-05      +/- 4.964089e-07
            b2 X......2          be2
1 5.475942e-07      +/- 1.672966e-08

8. Show results in a nice table (using Pandas in python).

In [14]:
#import numpy as np
#import pandas as pd
In [15]:
from rpy2.robjects import r, pandas2ri
pandas2ri.activate()
In [16]:
r.data('partAO')
ai = r['partA0']
ai
Out[16]:
a0 X..... ae0 a1 X......1 ae1 a2 X......2 ae2
1 1.748145 +/- 0.000949 -0.032813 +/- 0.000154 0.000419 +/- 0.000005
In [17]:
r.data('partBO')
bi = r['partB0']
bi
Out[17]:
b0 X..... be0 b1 X......1 be1 b2 X......2 be2
1 0.003961 +/- 0.000003 -0.000074 +/- 4.964089e-07 5.475942e-07 +/- 1.672966e-08

9. Assess error in the $\delta pCO_{2,o}$ calculated from the perturbation approach relative to "true" values from seacarb package

For a 200-ppm change in atm xCO2 (280 to 480 ppm), compute relative error in perturbation approach.

In [22]:
%%R
# 8) Verify Fitted vs. True results
    x0 <- a0 + a1*t +a2*t2
    x1 <- b0 + b1*t +b2*t2
#   For a 200 ppm change of atmospheric xCO2 (280 to 480 ppm), 
#   corresponding delta DIC will vary (from changes in T)
    dxCO2true = 200
    xCO2true = 280 + dxCO2true
#   Convert xCO2 to pCO2 (and calculate corresponding dpCO2)
    pCO2true <- xCO2true * (1-espa)
    dpCO2true  <- pCO2true - pCO2o
#   Compute "true" reference value from seacarb
    carbd <- carb(flag=24, var1=pCO2true, var2=TA, S=Salt, T=Temp, P=0, Patm=1, Pt=0, Sit=0, 
                  k1k2="l", kf="dr", ks="d", pHscale="T", b="u74", gas="standard")
    ddic <- (carbd$DIC - dic0) * 1e+6
#   Compute delta pCO2 from perturbation approach (using true ddic from seacarb)
    dpCO2fit <- (x0 * ddic) / (1 - x1*ddic)
#   Plot results
    plot(x=Temp, y=100*(dpCO2fit - dpCO2true)/dpCO2true, col="blue")
#   Rough conclusion (from above plot): relative errors always < +/-0.3% when delxCO2 < 200 (i.e., atm xCO2 ~ 560 ppm)

Figure 1: Relative error as a function of temperature for the $\delta$pCO$_2$ computed by the perturbation approach relative to reference values from seacarb.

Conclusion

Relative errors remain less than +/-0.3% across the observed temperature range of the Global Ocean.