Learn R Programming

seacarb (version 3.4.0)

buffderiv: Analytic partial derivatives of the Bolin sensitivity Be

Description

Computes, in closed form, the four partial derivatives of the Bolin sensitivity \(B_e = \partial DIC / \partial [CO_2^*]\) (at constant total alkalinity, temperature and salinity) with respect to temperature, salinity, DIC and total alkalinity.

Usage

buffderiv(flag, var1, var2, S = 35, T = 25, Patm = 1, Pt = 0, Sit = 0,
          NH4t = 0, HSt = 0, k1k2 = "l", kf = "dg", ks = "d",
          pHscale = "T", b = "u74", warn = "y", npolish = 3)

Value

A data frame containing:

Be

Bolin sensitivity, dimensionless

dBe_dT

derivative of Be with respect to temperature, per degree Celsius

dBe_dS

derivative of Be with respect to salinity, per practical salinity unit

dBe_dCT

derivative of Be with respect to DIC, per (mol/kg)

dBe_dAT

derivative of Be with respect to total alkalinity, per (mol/kg)

dh_dT

derivative of [H+] with respect to temperature, (mol/kg) per degree Celsius

dh_dS

derivative of [H+] with respect to salinity, (mol/kg) per psu

dh_dCT

derivative of [H+] with respect to DIC, dimensionless

dh_dAT

derivative of [H+] with respect to total alkalinity, dimensionless

alk_residual

Ac(h) + Anc(h) - ALK (mol/kg). A diagnostic. It must vanish to machine precision; if it does not, the alkalinity being differentiated is not the one seacarb solved, and every derivative above is suspect.

Arguments

flag

select the pair of variables available, as in carb

var1

value of the first variable in mol/kg, except for pH, and for pCO2 in \(\mu\)atm

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

Pt

concentration of total dissolved inorganic phosphorus (mol/kg)

Sit

concentration of total dissolved inorganic silicon (mol/kg)

NH4t

concentration of total dissolved inorganic ammonia (mol/kg)

HSt

concentration of total dissolved inorganic hydrogen sulfide (mol/kg)

k1k2

formulation of K1 and K2. Must be "l" (Lueker et al., 2000). See Details.

kf

formulation of Kf. Must be "dg" (Dickson and Riley, 1979). See Details.

ks

formulation of Ks. Must be "d" (Dickson, 1990).

pHscale

choice of pH scale. Must be "T" (total scale).

b

formulation of total boron. Must be "u74" (Uppstrom, 1974).

warn

"y" to show warnings when T or S go beyond the valid range

npolish

number of Newton refinement steps applied to [H+] (default 3). See Details.

Author

James Orr james.orr@lsce.ipsl.fr

Details

Surface only (P = 0).

Method. The proton concentration \(h\) is fixed implicitly by the total alkalinity constraint $$F(h; T,S,C_T,A_T) = A_c(h,C_T) + A_{nc}(h) - A_T = 0$$ and \(B_e\) is then an explicit algebraic function \(G(h,C_T,T,S)\), the same one evaluated by buffsun. For any \(Y\) in \(\{T,S,C_T,A_T\}\), the implicit function theorem gives $$\frac{dB_e}{dY} = G_Y + G_h \left(-\frac{F_Y}{F_h}\right)$$ Every term is closed form. The only nonlinear solve is the single call to carb (or carbfull) that supplies \(h\). This makes the routine roughly two orders of magnitude cheaper than differencing carb() numerically, and free of step-size error.

Acid-base systems. Carbonate, borate, water, phosphate, silicate, fluoride, and (on the carbfull path) ammonia and sulfide. Sulfate and the free proton are carried exactly as in SolveSAPHE. The alkalinity is precisely the one that seacarb itself inverts; alk_residual is returned so this can be checked at every point.

Silicate follows the solver. When NH4t = HSt = 0 the routine calls carb, whose alkalinity treats silicate as monoprotic (K1si only). Otherwise it calls carbfull, which is diprotic. K2si is set to zero on the first path, which reduces the diprotic expressions to the monoprotic ones exactly.

Constants are not optional. The analytic dK/dT and dK/dS (in dlnK.R) are the exact derivatives of specific formulations, so buffderiv stops rather than silently returning derivatives of the wrong function. Two of the guards matter in practice: k1k2 = "x" silently switches to Waters et al. (2014) when T < 2 or T > 35 or S < 19 or S > 43, which is exactly where polar surface waters lie; and kf = "x" silently switches between Perez and Fraga and Dickson and Riley by T and S range, changing the SWS-to-total conversion and hence Kw, Ksi, K1p, K2p and K3p by 0.5 to 0.9 percent. Neither switch warns.

Newton refinement. carb() returns \(h\) converged to roughly 1e-10 relative. \(B_e\) is steep in \(h\) and its derivatives steeper still, so buffderiv applies npolish Newton steps to \(F(h) = 0\) using \(F_h\), which it needs anyway. Speciation, \(B_e\) and all four derivatives then follow from the same \(h\) to machine precision. Set npolish = 0 to use carb()'s \(h\) untouched.

References

Bolin, B. and Eriksson, E., 1959 Changes in the carbon dioxide content of the atmosphere and sea due to fossil fuel combustion. The Atmosphere and the Sea in Motion, Rossby Memorial Volume, Rockefeller Institute Press, 130-142.

Munhoven, G., 2013 Mathematics of the total alkalinity-pH equation - pathway to robust and universal solution algorithms: the SolveSAPHE package v1.0.1. Geoscientific Model Development 6, 1367-1388.

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

See Also

buffsun, buffer, buffesm, buffzwg, carb, carbfull, derivnum.

Examples

Run this code
##  Bolin sensitivity and its four partial derivatives,
##  from total alkalinity (2300 umol/kg) and DIC (2000 umol/kg)
buffderiv(flag = 15, var1 = 2300e-6, var2 = 2000e-6, S = 35, T = 20,
          Pt = 0.2e-6, Sit = 3e-6,
          k1k2 = "l", kf = "dg", ks = "d", pHscale = "T", b = "u74")

##  Vectorised over a field. The single carb() call is the only nonlinear solve.
n   <- 1000
S   <- runif(n, 30, 37)
T   <- runif(n, -1.8, 30)
AT  <- runif(n, 2100, 2400) * 1e-6
CT  <- AT * runif(n, 0.85, 0.97)
d   <- buffderiv(15, AT, CT, S = S, T = T, k1k2 = "l", kf = "dg", ks = "d",
                 pHscale = "T", b = "u74", warn = "n")
summary(d[, c("Be", "dBe_dT", "dBe_dS", "dBe_dCT", "dBe_dAT")])

##  The alkalinity residual must be at machine precision
max(abs(d$alk_residual) / AT)

Run the code above in your browser using DataLab