1 Introduction

With increasing concerns about climate change and ocean acidification (Caldeira and Wickett 2003; Royal Society 2005; IPCC 2007; Gazeau et al. 2007; Guinotte and Fabry 2008; Doney et al. 2009), there is a strong demand for computational tools that enable a quantitative description of the acid–base chemistry of natural waters. These tools are needed from both a modelling point of view as well as from an experimental perspective. Due to increasing complexity in model descriptions of aquatic ecosystems, biogeochemical models now often require the capability of pH prediction and full acid–base speciation (Luff et al. 2001; Caldeira and Wickett 2005; Jourabchi et al. 2005; Vanderborght et al. 2007; Doney et al. 2007; Blackford and Gilbert 2007; Zeebe et al. 2008; Aloisi 2008; Hofmann et al. 2008, 2009a). However, computational tools that describe acid–base speciation are also of interest to observational and experimental scientists: current methods to calculate total alkalinity (and total inorganic carbon) from measured titration curves, are based on fitting numerical models of the acid–base chemistry of the given water sample (Dickson 1981; DOE 1994; Anderson et al. 1999; Dickson et al. 2007).

Currently, there are two computational tools available that describe the acid–base chemistry of natural waters and the ocean carbon system in particular: the CO 2 SYS program (Lewis and Wallace 1998; Pierrot et al. 2006; van Heuven et al. 2009) and the extension package seacarb (Lavigne et al. 2008) for the open-source programming language R (R Development Core Team 2005). Both programs perform two basic tasks:

  1. 1.

    The calculation of various physical parameters (dissociation constants, solubility constants of calcite and aragonite, Henry’s constant of CO2, etc.) as a function of temperature, salinity, and pressure

  2. 2.

    The calculation of pH, the associated acid–base speciation (including the calculation of all parameters of the CO2 system), and the saturation state with respect to calcite and aragonite.

CO 2 SYS is the oldest program, but has a limited scope and is mainly focused on the ocean carbonate system. Although the phosphate and silicate systems are additionally incorporated as acid–base equilibria, only the carbonate speciation is provided in the output. Originally, the CO 2 SYS program was distributed either as a compiled Microsoft DOS program (Lewis and Wallace 1998) or as a Microsoft Excel spreadsheet (Pierrot et al. 2006), which makes the program static and inflexible. This way, CO 2 SYS was difficult to link to an external biogeochemical model code. Recently, a MATLAB version of CO 2 SYS has been released (van Heuven et al. 2009). Although that allows for some flexibility, the core function is still very rigid and tailored to the needs of an ocean researcher measuring properties of samples in the laboratory or in the field: it is a tool for the experimental scientist rather than a modelling tool. Next to the non-intuitive interface of the CO 2 SYS MATLAB function which uses variable types indicated by numbers instead of variable names, the MATLAB routine shares a shortcoming with the other CO 2 SYS versions: it does not provide the dissociation constants as output, they are only calculated and used internally. Furthermore, the user is restricted to MATLAB which is a commercial, proprietary program and might not be at the disposal of every scientist. The package seacarb , however, is implemented in the open-source programming language R . The R framework provides vast capabilities of preprocessing, statistical postprocessing, and visualization of data. Recently, R has also evolved into a suitable platform for biogeochemical and reactive-transport model development (Soetaert and Herman 2009), as powerful packages for numerical integration of differential equations (e.g. deSolve Soetaert et al. 2008), rootfinding (e.g. rootSolve Soetaert 2008), and reactive-transport modelling (Soetaert and Meysman 2009, e.g. ReacTran ) have been developed. The R platform is excellently suited for rapid prototyping of biogeochemical models, since it combines an interpreted programming language with the possibility to embed legacy FORTRAN code that enables fast numerical calculations.

Here, we report on the new R package AquaEnv that substantially extends the capabilities of both CO 2 SYS and seacarb . Compared to the seacarb package, AquaEnv can be applied to hyposaline systems (see Sect. 2), and it calculates a number of additional quantities, such as the buffer factor, various partial derivatives of total alkalinity, and ionization fractions that are useful for studying and modelling the effect of biogeochemical processes on pH (Hofmann et al. 2008, 2009a,b). Compared to CO 2 SYS , AquaEnv additionally includes the \(\left[\sum \hbox{NH}_4^+\right]\), \(\left[\sum \hbox{H}_2{\rm S}\right]\), \(\left[\sum \hbox{H}_3\hbox{PO}_4\right]\), \(\left[\sum \hbox{Si(OH)}_4\right]\), \(\left[\sum \hbox{HNO}_3\right]\), and \(\left[\sum \hbox{HNO}_2\right]\) acid–base systems, which makes it applicable to sediment pore water and anoxic systems. In addition, a number of more advanced applications are included in AquaEnv . These enable the improved interfacing with numerical biogeochemical models, the generation of “in silico” titrations, and the determination of total alkalinity (and total carbonate) values from measured titration curves by non-linear optimization (inverse modelling).

The AquaEnv package can be obtained from the Comprehensive R Archive Network (CRAN): http://cran.r-project.org/package=AquaEnv or from the R -forge website: http://r-forge.r-project.org/projects/aquaenv/. General information and tutorials about R can be found on the R project homepage: http://www.r-project.org/.

Please note that, at appropriate places throughout the paper, we supply boxes with R code fragments illustrating the usage of AquaEnv . These code fragments should serve as starting points for the inclined reader to explore AquaEnv whilst reading this publication. More detailed R scripts using AquaEnv are provided in the electronic appendix.

2 AquaEnv in Mesohaline and Oligohaline Environements

As mentioned above, the main novel features of AquaEnv are the implementation of quantities for the pH modelling approach given by Hofmann et al. (2008, 2009a,b), the titration simulation, and the alkalinity determination routines. Another important advantage of AquaEnv is that it can also be applied to mesohaline and oligohaline environments.

In AquaEnv , salinity (S) and temperature (t) relationships for dissociation constants as given in Table 1 are implemented. If there are multiple relations per dissociation constant implemented, the first one in the list is the default choice in AquaEnv .

Table 1 S, t relationships with associated S and t ranges as implemented in AquaEnv

This means, in AquaEnv , the default choice of S, t relations for dissociation constants is valid for a salinity range of 0–45, except for the relation for \({\tt K\_HSO4}\). However since DOE (1994), Zeebe and Wolf-Gladrow (2001), and Dickson et al. (2007) all recommend the Dickson (1990b) formulation for \({\tt K\_HSO4}\), we chose to make that our default choice. Applying AquaEnv to salinities below 5 using this default setting is still acceptable, since \({\tt K\_HSO4}\) is mainly needed for pH scale conversions from and to the total and seawater scale. However, in brackish and freshwater (model) applications, the NBS scale and the free scale are normally used, where \({\tt K\_HSO4}\) is less important as it plays no role for conversions between the NBS scale and the free scale. The influence of \({\tt K\_HSO4}\) via association or dissociation of the \(\hbox{HSO}_4^-\rightleftharpoons \hbox{H}^+ + \hbox{SO}_4^{2-}\) system on total alkalinity and pH is minute (free scale pH values differ in the sixth digit if different \({\tt K\_HSO4}\) formulations are used). Nevertheless, the user can choose to use the Khoo et al. (1977) formulation for \({\tt K\_HSO4}\) which is, as can be inferred from Millero (1995), valid down to S = 0.

Most important for the pH chemistry of aquatic systems with a high dissolved inorganic carbon concentration, like many estuaries, is the choice of the S, t relations for the first and the second dissociation constant of the carbonate system. We implement the relation by Roy et al. (1993b), adapted to low salinities as described by Millero (1995) (see caption of Table 1) and the relation by Millero et al. (2006), which are both explicitly valid down to S = 0. seacarb only implements the original version of Roy et al. (1993b), not adapted to low salinities, and the relation of Lueker et al. (2000), which are not valid below S = 5 and S = 19, respectively. Figure 1 plots all four relations against salinity in the oligohaline and mesohaline region.

Fig. 1
figure 1

Salinity dependence of four different S, t relationships of the first (left panel) and second (right panel) dissociation constant of the carbonate system. Magenta line Roy et al. (1993b), not adapted to low salinities (as implemented in seacarb ); red line Lueker et al. (2000), not valid below S = 19 (implemented in seacarb and AquaEnv ); black line Roy et al. (1993b), adapted to low salinities (as implemented in AquaEnv ); blue line Millero et al. (2006), valid down to S = 0 (implemented in AquaEnv )

It becomes clear that in the oligohaline realm (S < 5), there are big differences between the relations that are explicitly defined for low salinities and the ones that are not, this can also be seen in Fig. 2. AquaEnv implements two S, t relations for the first and second dissociation constant of the carbonate system (\({\tt K\_CO2}\) and \({\tt K\_HCO3}\)) that are valid down to S = 0, whilst seacarb implements none.

Fig. 2
figure 2

Using AquaEnv to visualize the sensitivity of the carbonate speciation towards changes in salinity S . Black line using a salinity dependence for the first and second dissociation constants of the carbonate system as given in Roy et al. (1993b) with a freshwater formulation for salinities below 5, as recommended by Millero (1995) (these functions are used by default in AquaEnv ). Blue line using a salinity dependence for the first and second dissociation constants of the carbonate system as given in Lueker et al. (2000), as recommended by Dickson et al. (2007) (these functions can be used in AquaEnv by setting the flag \({\tt k1k2}\) to the value “\({\tt lueker}\)”). Red line using a salinity dependence for the first and second dissociation constants of the carbonate system as given in Millero et al. (2006) (these functions can be used in AquaEnv by setting the flag \({\tt k1k2}\) to the value “\({\tt millero}\)”). Note that [TA] and \(\left[\sum\hbox{CO}_{2}\right]\) have been kept constant at 0.003 mol/kg-solution. Note further that \(\left[\sum \hbox{B(OH)}_3\right]\), \(\left[\sum \hbox{H}_2\hbox{SO}_4\right]\), and \(\left[\sum \hbox{HF}\right]\) are calculated from salinity. The plotted effect of changes in S on the carbonate speciation is thus twofold: via the salinity dependence of the dissociation constants and via the salinity dependence of \(\left[\sum \hbox{B(OH)}_3\right]\), \(\left[\sum \hbox{H}_2\hbox{SO}_4\right]\), and \(\left[\sum \hbox{HF}\right]\)

This means, AquaEnv provides an advantage over seacarb for oligohaline and mesohaline systems, since (1) it implements S, t relations for \({\tt K\_CO2}\) and \({\tt K\_HCO3}\) that are valid down to S = 0 and (2) it implements the conversion from and to the NBS scale for brackish and freshwater, which is not implemented in seacarb . In general, one can choose more S, t relationships in AquaEnv than one can in seacarb . CO 2 SYS can handle low salinities, but, as mentioned above, is restricted to a narrow choice of acid–base systems that are considered in the calculations, making it unsuitable for pore water and anoxic systems. However, CO 2 SYS does provide more choices of S, t relations for the CO2 system, since this is its main focus. It offers the same choice of S, t relations for \({\tt K\_HSO4}\) as does AquaEnv , but less choices for \({\tt K\_HF}\).

3 Structure of the AquaEnv Package and an aquaenv Object

The functionality in the seacarb package is established by calls to separate R functions. Rather than implementing separate functions for each feature, AquaEnv adopts a more integrated approach. Almost all functionality is contained within one generic function, termed aquaenv , which creates structured objects of the aquaenv class (encoded as an R list with multiple components), termed “aquaenv objects” in what follows. Components within an aquaenv object contain all information (physical parameters, acid–base dissociation constants, chemical speciation, partial derivatives, etc.) that can be calculated from the given input parameters. Whilst an underdeterminated system (too few input parameters) prompts an error message, an overdetermined system (too many input parameters) prompts AquaEnv to display a message that informs the user how calculated and suplied values differ. Information is obtained by selecting the appropriate element from the aquaenv object. At the same time, AquaEnv also includes individual functions that calculate quantities like acid–base dissociation constants separately.

Once created, aquaenv objects can be used in generic plotting and data processing commands, that have been specifically created for the aquaenv class. aquaenv objects can be converted to an R data.frame , which can be further postprocessed with standard R routines. Similarly, an R data.frame can be converted to an aquaenv object, for the use of aquaenv object specific plotting facilities provided in AquaEnv . Furthermore, the aquaenv objects can be used as input argument supplying initial conditions in the titration and TAfit functions, which respectively simulate an in silico titration and perform the inverse modelling of titration data to obtain total alkalinity values.

Appendix 7.1 details the complete structure of an aquaenv object. For each component, the name, physical units and a short explanation are listed. Appendix 7.2 gives all relevant mathematical formulae as well as physical and chemical constants, with respective literature references, used for calculation of components of an aquaenv object.

4 Basic Applications

4.1 Physical and Chemical Parameters

AquaEnv provides routines that calculate the key physical and chemical parameters involved in the acid–base chemistry of natural waters. These include the stoichiometric equilibrium constants (K*) for the major acid–base systems (carbonate, ammonia, sulphide, nitrate, nitrite, phosphate, silicate, borate, sulphate, and fluoride), the ion product of water, the Henry’s constants (K0) that govern the solubility of CO2 and O2, as well as the solubility products (Ksp) for calcite and aragonite. These parameters are all calculated according to a standard (S, t, p) format, i.e., as a function of salinity (S), temperature in °C (t), and the gauge pressure or applied pressure (p) which represents the total pressure (P) minus the atmospheric pressure (P a ) (Millero et al. 2008; Feistel 2008). Instead of the gauge pressure p, the total pressure P or the water depth d can also be given as input parameters. All required mathematical expressions were compiled from various sources in literature as discussed in Appendix 7.2.

Note that in AquaEnv , three different S, t dependencies for the first and the second dissociation constant of the carbonate system are implemented: the relation by Roy et al. (1993a) adapted to be also applicable to low salinities as described by Millero (1995); the relation by Lueker et al. (2000) which is recommended by Dickson et al. (2007) but which is not applicable to low salinities; and the relation introduced by Millero et al. (2006) which covers a salinity range from 0 to 40 and which is, amongst other relations, also used in CO 2 SYS . The relation by Roy et al. (1993a) is used by default in AquaEnv , and the other two relations can be employed by setting the flag k1k2 to “ lueker ” or “ millero ”. In the same way, two different relations for the dissociation constant of hydrogen fluoride can be used: the relation by Dickson and Riley (1979a) (default in AquaEnv ) and the relation by Perez and Fraga (1987) (as advised by Dickson et al. (2007); flag khf set to “ perez ” in AquaEnv ). Similarly, two different relations for the dissociation constant of hydrogen sulphate can be used: the relation by Dickson (1990b), as recommended by DOE (1994); Zeebe and Wolf-Gladrow (2001); Dickson et al. (2007) (default in AquaEnv ), and the relation by Khoo et al. (1977) as used in, e.g., Roy et al. (1993b); Millero (1995); Lewis and Wallace (1998) (flag khso4 set to “ khoo ” in AquaEnv ).

Our goal was to arrive at an internally consistent parameter set, where all quantities are expressed using the same concentration units and the same pH scale (molinity and free pH scale: see discussion below). To achieve this, appropriate conversions were applied, using auxiliary variables like seawater density calculated as a function of salinity and temperature, and ionic strength calculated as a function of salinity (see Appendix 7.2). These auxiliary variables are also stored as components in aquaenv objects and can thus be accessed by the user (As mentioned, a full list of names of components contained in aquaenv objects is given in Appendix 7.1).

4.2 Seawater Composition

For some biogeochemical applications, the detailed ionic composition of seawater is required. AquaEnv calculates this composition from salinity (according to DOE 1994; Dickson et al. 2007), determining the total borate concentration (\(\left[\sum \hbox{B(OH)}_3\right]\)), the total sulphate concentration (\(\left[\sum \hbox{H}_2\hbox{SO}_4\right]\)), the total fluoride concentration (\(\left[\sum \hbox{HF}\right]\)), and the ion concentrations of \(\hbox{Cl}^-\), Br, Na+, Mg2+, Ca2+, K+, and Sr2+. Note that the values for \(\left[\sum \hbox{B(OH)}_3\right]\), \(\left[\sum \hbox{H}_2\hbox{SO}_4\right]\), \(\left[\sum \hbox{HF}\right]\) can also be given as input (in mol/kg-solution) upon construction of an aquaenv object, and in that case, they override the default values calculated from salinity.

4.3 pH Scales and Unit Conversions

Acid–base calculations are always characterized by a specific choice of the concentration unit (molarity = mol/l, molality = mol/kg-H2O, or molinity = mol/kg-solution) and the pH scale (free scale, total scale, seawater scale, and NBS scale, all based on a specific concentration unit: see discussion on pH scales in Dickson (1984), Lewis and Wallace (1998), and Zeebe and Wolf-Gladrow (2001)). To ensure the accuracy and consistency of the calculations, it is vital to consider the issue of concentration units and pH scales. Often, it is only specified that calculations are performed in gravimetric units (i.e., mol/kg). However, with increasing salinity, the difference between the two gravimetric units, molality and molinity, becomes significant, and so, the choice of concentration units must be made explicit. Similarly, the differences between pH scales are significant, especially at higher salinities (Zeebe and Wolf-Gladrow 2001). Each pH scale is linked to its own specific set of values for the stoichiometric equilibrium constants. Using a mixture of pH scales for equilibrium constants (K *) and pH values thus will lead to erroneous speciation calculations.

In AquaEnv , the input, output, and internal calculations are all stated in SI units (except for the pressure unit, which is bar instead of Pascal for the gauge pressure and atm instead of Pascal for the fugacities.), molinity, and on the free pH scale. To be consistent with Lewis and Wallace (1998), the NBS pH scale in AquaEnv is based on the proton concentration in mol/kg-H2O, while all other pH scales are based on mol/kg-soln. Both the input parameters and the components of an aquaenv object can be converted between different concentration units and pH scales using the generic AquaEnv function convert . Furthermore, the factors for conversion between molality and molinity ( molal2molin ) and between the free, total and seawater pH scale ( free2tot , free2sws , etc.) are components of an aquaenv object. The mathematical relations underlying these conversion functions are also detailed in Appendix 7.2.

The conversion from and to the NBS pH scale requires the activity coefficient for protons in solution (Durst 1975; Dickson 1981; Zeebe and Wolf-Gladrow 2001). In AquaEnv , we opted for a simple and direct approach: we implemented the Davies equation (as stated in Zeebe and Wolf-Gladrow 2001) to calculate the proton activity coefficient. Since the NBS scale is mainly used for fresh and brackish waters and not for open ocean waters, we choose not to invest time in the implementation of a detailed and intricate ion-interaction model (Pitzer model) as given by Millero and Pierrot (1998). The Davies equation is valid up to an ionic strength of I = 0.5 mol/kg-H2O (Zeebe and Wolf-Gladrow 2001) and hence, up to a salinity S of ∼25. Above this salinity, the conversion from and to the NBS pH scale as implemented in AquaEnv should be regarded as approximate.

4.4 Acid–Base Speciation Calculations

Given suitable input parameters, AquaEnv calculates the full speciation of all acid–base systems in the solution at hand. As output, one obtains an aquaenv object containing the concentrations of all dissociated species in the system, the related ionization fractions (i.e., the ratios of dissociated concentrations over total concentrations), the fugacity of CO2, as well as the saturation state Ω = [Ca2+][CO 2−3 ]/K sp for calcite and aragonite.

The speciation calculation consists essentially of two steps: the pH is first computed numerically, followed by the analytical calculations that describe the speciation. Numerically, the pH calculation comes down to the solution of a set of non-linear algebraic equations as determined by the mass action equations of the acid–base systems. In AquaEnv , this non-linear system is solved using the iterative approximation approach described by Follows et al. (2006), which is based on the repeated analytical solution of a quadratic equation derived from the mass action equations of the carbonate system only. In cases where this approach does not converge, e.g. in cases with very low or zero total dissolved inorganic carbon concentration \(\left( \left[ \sum \hbox{CO}_{2}\right] \right) \), the R function uniroot is employed which implements an interval based root finding algorithm. If only the pH needs to be calculated without a full speciation, one can set the flag speciation to FALSE .

A full speciation (i.e., all concentrations of the CO2 system as well as of all other acid–base systems) is calculated from salinity, temperature, and pressure (determining the stoichiometric equilibrium constants), the total concentrations associated with acid–base systems present (\(\left[\sum \hbox{CO}_2\right]\), \(\left[\sum \hbox{NH}_4^+\right]\), \(\left[\sum \hbox{H}_2{\rm S}\right]\), \(\left[\sum \hbox{HNO}_3\right]\), \(\left[\sum \hbox{HNO}_2\right]\), \(\left[\sum \hbox{H}_3{\rm PO}_4\right]\), \(\left[\sum \hbox{Si(OH)}_4\right]\), \(\left[\sum \hbox{B(OH)}_3\right]\), \(\left[\sum \hbox{H}_2\hbox{SO}_4\right]\), \(\left[\sum \hbox{HF}\right]\)), as well as total alkalinity ([TA]), or pH, or the carbon dioxide fugacity (fCO2), or the carbon dioxide concentration ([CO2]). Some of the quantities above have default values and do not need to be supplied. That means, for example, the parameter pairs ([TA], \(\left[\sum \hbox{CO}_2\right]\)), ([TA], pH), (pH, \(\left[\sum \hbox{CO}_2\right]\)) (fCO2, \(\left[\sum \hbox{CO}_2\right]\)), ([CO2], [TA]), etc. allow for the calculation of a full speciation. If too much information is provided (i.e. an overdetermined system is created), a message is displayed, stating how calculated and provided numbers differ.

Furthermore, it is possible to calculate \([\sum \hbox{CO}_2]\) and a full speciation from a suitable set of input parameters. To that end, the input value NULL needs to be assigned to the argument SumCO2 and one of the pairs pH and [CO2], pH and fCO2, pH and [TA], [TA] and [CO2], or [TA] and fCO2 needs to be supplied.

4.5 Buffer Factor, Partial Derivatives of Total Alkalinity, and Revelle Factor

Theory states that total alkalinity can be specified as a function of the proton concentration and both the total concentrations and the dissociation constants (K i *) of the various acid–base systems.

$$ \left[{\rm TA}\right] = f([\hbox{H}^+], \left[\sum \hbox{CO}_2\right], \left[\sum \hbox{NH}_4^+\right], \left[\sum \hbox{H}_2\hbox{S}\right],\; \ldots, \;K^*_i) $$
(1)

Recently, it has been shown that the partial derivativesFootnote 1 of this expression are crucial in the description of pH dynamics and proton cycling in natural waters (a detailed explanation of proton cycling in natural waters is beyond the scope of this publication. The interested reader is referred to our other publications on this subject: Hofmann et al. 2008, 2009a,b). In particular, they play a key role in the construction of pH models. The most important partial derivative is the buffer factor β, which is related to buffer quantities introduced by Morel and Hering (1993), Frankignoulle (1994), and Stumm and Morgan (1996), but which is defined differently

$$ \beta = - \frac{\partial[\hbox{TA}]}{\partial [\hbox{H}^+]} $$
(2)

Similarly, the partial derivatives of alkalinity with respect to the concentrations of the other total quantities are important

$$ \frac{\partial [\hbox{TA}]}{\partial[\sum \hbox{CO}_2]}, \; \frac{\partial [\hbox{TA}]}{\partial [\sum \hbox{NH}_4^+]}, \;\frac{\partial [\hbox{TA}]}{\partial[\sum \hbox{H}_2\hbox{S}]}, \; \ldots $$
(3)

In AquaEnv , all these partial derivatives are calculated via analytical expressions and are accessible to the user as components of an aquaenv object.

Furthermore, [TA] is a function of the dissociation constants (K i *) of the various acid–base systems which, in turn, are functions of salinity S, temperature t, and pressure p. If these dissociation constants are calculated on one pH scale and then converted to another pH scale, they become functions of \(\left[\sum \hbox{H}_2\hbox{SO}_4\right]\) and \(\left[\sum \hbox{HF}\right]\) as well (see also Hofmann et al. 2009a). In general,

$$ {K}^*_{i} = f\left({S},\; {t}, \;{p}, \;\left[\sum \hbox{H}_2\hbox{SO}_4\right], \;\left[\sum \hbox{HF}\right]\right) $$
(4)

Hofmann et al. (2009a) show that the products of the partial derivatives of [TA] with respect to the dissociation constants K i * and the partial derivative of the dissociation constants K i * with respect to one of their variables are needed for their explicit pH modelling approach. Therefore, AquaEnv numerically calculates

$$ \sum_{i} \frac{\partial [\hbox{TA}]} {\partial {K}^*_{i}} \frac{\partial {K}^*_{i}} {\partial {S}},\; \sum_{i} \frac{\partial [\hbox{TA}]}{\partial {K}^*_i} \frac{\partial {K}^*_{i}} {\partial {t}},\; \sum_{i} \frac{\partial [\hbox{TA}]} {\partial {K}^*_{i}} \frac{\partial {K}^*_{i}} {\partial {p}},\; \sum_{i} \frac{\partial [\hbox{TA}]}{\partial {K}^*_i} \frac{\partial {K}^*_i} {\partial [\sum \hbox{H}_2\hbox{SO}_4]},\; \sum_{i} \frac{\partial [\hbox{TA}]}{\partial {K}^*_i} \frac{\partial {K}^*_i}{\partial [\sum \hbox{HF}]} $$
(5)

and provides these quantities as components of an aquaenv object.

Furthermore, as a related quantity, the well-known Revelle factor (e.g. Zeebe and WolfGladrow 2001) which is defined as

$$ \hbox{RF}_0 = \left(\frac{{\hbox{d}}[\hbox{CO}_2]} {[\hbox{CO}_2]}\Bigg / \frac{{\hbox{d}} [\sum \hbox{CO}_2]}{[\sum \hbox{CO}_2]}\right)_{[\hbox{TA}] = {const.}} $$
(6)

is numerically calculated in AquaEnv (see Appendix 7.2.12 for details) and provided as component of an aquaenv object.

Details of how to use the partial derivatives of total alkalinity in reactive-transport models are given in (Hofmann et al. 2008, 2009a,b). Furthermore, Sect. 5.1 provides simple example models employing some of these quantities.

4.6 Sensitivity Analysis

One of the input variables for the function aquaenv may be a vector. All other input variables are then assumed to be constant. As a result, an aquaenv object is created which contains vectors of the respective components as functions of the input vector. Together with the plotting functionality specific for aquaenv objects, this enables a simple form of sensitivity analysis and its visualization. Figure 2 shows how AquaEnv can be used to visualize how salinity variations in estuaries change the carbonate speciation (and pH; not shown). The code fragment below produces the three panels of Fig. 2 in separate plot windows.

4.7 Data Visualization

The plot.aquaenv function is the generic plotting method for aquaenv objects (within the R object-oriented programming environment, this function can be called as plot without the .aquaenv suffix). This plotting method visualizes the information contained in an aquaenv object in a multifunctional way. (1) It can be used to visualize the sensitivity of a system with respect to changes in one input parameter (Fig. 2). (2) The plot.aquaenv function can be used to create Bjerrum plots which are the classical textbook way of displaying the speciation of acid–base systems as a function of pH (e.g. Zeebe and Wolf-Gladrow 2001). (3) plot.aquaenv can generate “cumulative” plots that can be used to, e.g., visualize the partitioning of dissolved inorganic carbon into carbon dioxide, bicarbonate, and carbonate, or to partition the total rate of change of protons into contributions by different processes. The usage and syntax of the plot.aquaenv function is detailed in its R help file as well as in the package vignette of AquaEnv . The following code fragment gives an impression of the capability of the plot.aquaenv function. The last two plot calls produce graphs as shown in Fig. 3. Furthermore, Sect. 5.2 provides examples of how Bjerrum plots can be created using the titration function in combination with the plot.aquaenv function, and Sect. 5.1 provides another example for the cumulative plotting functionality.

Fig. 3
figure 3

Examples for the Bjerrum-plot and cumulative-plot functionality of AquaEnv

5 Advanced Applications

5.1 AquaEnv in Reactive-Transport Models

When simulating the biogeochemistry of natural waters, one often needs to explicitly deal with pH dynamics. As a result, the corresponding reactive transport models need to include an acid–base speciation routine as a subcomponent. The function aquaenv fits this purpose. At each timestep of a dynamic model, aquaenv can calculate the desired information related to the “acid–base state” of the system (physical parameters, speciation, buffer capacity, partial derivatives etc.). We will show the use of aquaenv by means of a simple example model of a hypothetical aquatic system. Note that the example is an artificial model which is deliberately kept very simple for didactical reasons. Accordingly, it is not fitted to a particular natural system and it does not produce results relevant in reality. That means the used specific numerical values, selection of processes, and kinetic formulations for processes only serve illustrative purposes here and will not be discussed in detail.

Over a time scale of days, the pH chemistry of a hypothetical water reservoir is known to be influenced by two processes: CaCO3 precipitation and CO2 exchange across the air–water interface. These two dominant processes can be represented by the reaction equations

$$ \hbox{Ca}^{2+} + \hbox{CO}_3^{2-} \rightarrow \hbox{CaCO}_3 $$
(7)
$$ \hbox{CO}_{2}(\hbox{atm}) \rightleftharpoons \hbox{CO}_{2} $$
(8)

Note that the second reaction represents CO2 air–sea exchange. It is deliberately written in the style of a chemical reaction here to show that chemical and physical processes can be treated similarly concerning pH modelling according to Hofmann et al. (2008). The associated kinetic rate laws are (Morse 1983; Mucci 1986; Morse et al. 2003; Thomann and Mueller 1987):

$$ {\bf R}_P =k_P \left(1-\Upomega\right)^n $$
(9)
$$ {\bf R}_C = k_C \left([\hbox{CO}_2]_{\rm sat} - [\hbox{CO}_2]\right) $$
(10)

In addition, the pH chemistry will also depend on a number of “fast” acid–base dissociation reactions, with characteristic time scales of less than a minute (Zeebe and Wolf-Gladrow 2001). To keep the model suitably simple, only the carbonate system is accounted for

$$ \hbox{CO}_{2} + \hbox{H}_{2}\hbox{O} \rightleftharpoons \hbox{HCO}_{3}^{-} + \hbox{H}^{+} $$
(11)
$$ \hbox{HCO}_{3}^{-} \rightleftharpoons \hbox{CO}_{3}^{2-} + \hbox{H}^{+} $$
(12)

The equilibrium mass action equations for these two acid–base reactions are, respectively:

$$ {K}_{{\rm CO}_2}^{\ast} = \frac{[\hbox{H}^+]\;[\hbox{HCO}_3^{-}]}{[\hbox{CO}_2]} $$
(13)
$$ {K}_{{\rm HCO}_3^{-}}^{*} =\frac{[\rm H^+][\hbox{CO}_3^{2-}]}{[\hbox{HCO}_3^{-}]} $$
(14)

As detailed by Hofmann et al. (2009b), there are two main model approaches to arrive at the pH evolution of the water reservoir. In the “alkalinity centred” or “implicit pH modelling approach”, one focuses on the effect of the kinetic processes on alkalinity ([TA]) and the total carbonate concentration (\(\left[\sum \hbox{CO}_2\right]\)) in the system. As a result, one obtains two differential equations describing the evolution of [TA] and \(\left[\sum \hbox{CO}_2\right]\)

$$ \frac{\hbox{d}[\hbox{TA}]}{\hbox{d} t} =-2{\bf R}_P\\ $$
(15)
$$ \frac{\hbox{d} [\sum \hbox{CO}_2]}{\hbox{d} t} ={\bf R}_C - {\bf R}_P $$
(16)

Since the kinetic rate laws (Eqs. 9 and 10) feature concentrations of dissociated species, the integration of Eqs. 15 and 16 requires a two-step approach (e.g. Luff et al. 2001; Follows et al. 2006). Starting with initial values for [TA] and \(\left[\sum \hbox{CO}_2\right]\), one performs an “equilibration step” that calculates the concentrations of all dissociated species as a function of [TA] and \(\left[\sum \hbox{CO}_2\right]\). Subsequently, an “integration step” is performed: the kinetic rate terms, which feature the concentrations of the dissociated species [CO2] and [CO 2−3 ] are calculated, and the resulting rates of change of [TA] and \(\left[\sum \hbox{CO}_2\right]\) are passed on to the integrator which returns new values for [TA] and \(\left[\sum \hbox{CO}_2\right]\). Those new values, in turn, can be used for another “equilibration step”. By repeating this two-step procedure for a suitable sequence of time steps, one eventually obtains the evolution of [TA], \(\left[\sum \hbox{CO}_2\right]\), pH and all dissociated species over the desired time interval. The function aquaenv can be invoked to conveniently perform the “equilibration step”: with one function call, the pH and a full speciation is calculated. The following code fragment represents part of a simple model function that describes pH implicitly via the rates of changes of [TA] and \(\left[\sum \hbox{CO}_2\right]\). The file “AquaEnv-pHModelling.R” in the electronic appendix contains a model script that employs the respective model function.

An alternative approach to pH modelling was recently proposed (Hofmann et al. 2008, 2009b). The method was termed the “proton-centred” or “explicit” pH modelling approach, as it is based on an explicit evolution equation for the proton concentration. (Note that we are very brief in explaining this method here, since a detailed explanation is given by Hofmann et al. (2008) and (2009b) and is beyond the scope of this publication. However, AquaEnv does implement quantities necessary for this method, so we need to briefly repeat the main ideas.) Rather than using an evolution equation for alkalinity, one integrates following differential equation for the proton concentration

$$ \frac{\hbox{d} [\hbox{H}^+]}{\hbox{d} t} = S_P {\bf R}_P + S_C {\bf R}_C $$
(17)

The quantities S P and S C are respectively termed the sensitivities of pH with respect to CaCO3 precipitation and CO2 exchange. They are defined as

$$ S_P = \frac{1}{\left(\frac{\partial[\hbox{TA}]}{\partial [\hbox{H}^+]}\right)} \left( -2 + \frac{\partial [\hbox{TA}]}{\partial[\sum \hbox{CO}_2]} \right) $$
(18)
$$ S_C = \frac{1}{\left(\frac{\partial [\hbox{TA}]}{\partial[\hbox{H}^+]}\right)} \left(-\frac{\partial [\hbox{TA}]}{\partial[\sum \hbox{CO}_2]}\right) $$
(19)

These sensitivities thus feature partial derivatives of total alkalinity [TA], which are calculated in a closed analytical form by the function aquaenv . The following code fragment represents part of a simple model function that describes pH explicitly using partial derivatives of [TA]. The file “AquaEnv-pHModelling.R” in the electronic appendix contains a model script that employs the respective model function.

Hofmann et al. (2009b) show that the sensitivities of pH with respect to biogeochemical processes can also be expressed using ionization fractions (Skoog and West 1982; Stumm and Morgan 1996), here of the carbonate system (\(c_1 = [\hbox{CO}_2]/\left[\sum \hbox{CO}_2\right]\), \(c_2 = [\hbox{HCO}_3^-]/\left[\sum \hbox{CO}_2\right]\), \(c_3 = [\hbox{CO}_3^{2-}]/[\sum \hbox{CO}_2]\))

$$ S_P = \frac{1}{\left(-\frac{\partial[\hbox{TA}]}{\partial\left[\sum \hbox{CO}_2\right]}\right)} \left(2 c_1 + c_2 \right) $$
(20)
$$ S_C = \frac{1}{\left(-\frac{\partial [\hbox{TA}]}{\partial\left[\sum \hbox{CO}_2\right]}\right)} \left(c_2 + 2 c_3 \right) $$
(21)

Ionization fractions are calculated by the function aquaenv as well. The following code fragment represents part of a simple model function that describes pH explicitly using ionization fractions. The file “AquaEnv-pHModelling.R” in the electronic appendix contains a model script that employs the respective model function.

As mentioned above, the full implementation of the implicit and explicit pH modelling approaches into R code using the aquaenv function is detailed in the file “AquaEnv-pHModelling.R” in the electronic appendix. The implicit and explicit pH modelling approaches provide exactly the same evolution of pH, alkalinity, the total carbonate concentration, and all other quantities as a function of time (Fig. 4). However, the explicit modelling approach has the important conceptual advantage that it allows a systematic investigation of the sensitivity of pH to the associated biogeochemical processes. Equation 17 specifies that the influence of a given process on pH can always be decomposed as a modulating factor, which is the sensitivity of pH with respect to that process, times the process rate. This way, one can attribute the observed pH changes in a given system to a particular processes. Using the plot.aquaenv function, this can be illustrated in a cumulative plot (Fig. 5). If the result of a model run is stored in the variable output (as done in the respective script provided in the file “AquaEnv-pHModelling.R” in the electronic appendix), the following code fragment creates Fig. 5 and saves it to the file “cumulative.eps”.

Fig. 4
figure 4

Comparison of the results of the implicit and explicit pH modelling approaches using the function aquaenv . Black line implicit approach, Blue circles explicit approach expressing sensitivities of pH with partial derivatives (Eqs. 18 and 19), Red circles explicit approach expressing sensitivities of pH using ionization fractions (Eqs. 20 and 21). Initial values and model parameters are given in the R code in the file “AquaEnv-pHModelling.R” in the electronic appendix

Fig. 5
figure 5

Cumulative plot of the influences of kinetically modelled processes on the pH using the function plot.aquaenv . The grey line represents the net rate of change of the proton concentration over time and the coloured areas signify gross proton production or consumption rates due to the two processes calcium carbonate precipitation and CO2 air–sea exchange. These gross rates adding up to the net rate represent the contribution of the two processes to the rate of change of protons and thus their influence on pH changes and proton cycling. The method of quantifying influences of processes on the pH and proton cycling is introduced and discussed by Hofmann et al. (2008), Hofmann et al. (2009a), and Hofmann et al. (2009b). AquaEnv implements tools to visualize those influences in a cumulative way as shown in this figure. However, a full explanation of the underlying theoretical quantification method is beyond the scope of the present publication

5.2 Titration Simulation

In aquatic chemistry, one important experimental procedure is titration. The function titration within AquaEnv provides a tool to simulate titrations, i.e., to perform “in silico” titrations. The archetypal titration procedure involves an initial water sample to which concentrated monoprotic acid or base is added in a stepwise fashion. The titration function in AquaEnv describes how the composition of a water sample changes due to the addition of titrant solution which can be either a strong acid (typically HCl) or a strong base (typically NaOH). Titration with multiprotic acids is not accounted for.

To simulate a titration using AquaEnv , one proceeds in two steps. First, the composition of the initial water sample has to be specified. This is done via creating an aquaenv object by specifying salinity, temperature, and pressure, as well as the initial pH (or equivalently [TA]), and the concentrations of all total quantities. This aquaenv object describing the initial conditions will be the first argument of the function titration . As further arguments, one has to specify the mass of the initial sample solution ( mass_sample ), the concentration of the titrant ( conc_titrant ), the salinity of the titrant solution ( S_titrant ), the total mass of titrant solution added ( mass_titrant ), the number of titration steps ( steps ), and the type of the titrant (either a strong acid indicated by “HCl”, or a strong base indicated by “NaOH” as values for the argument type with the default value “HCl”). Note that the titration simulation accounts for changes in the salinity of the titrated solution due to dilution of the original sample by the titrant (which may influence acid–base equilibria), as well as for volume changes and thus also the dilution of concentrations (\(\left[\sum \hbox{CO}_2\right]\), etc.) due to the addition of titrant. This feature is particularly important for the treatment of pore water samples where typically small volumes and low concentration titrants are used. The logical flag seawater_titrant decides whether the titrant contains borate, sulphate, and fluoride (titration with natural seawater), or not (titration with artificial seawater). Note that, in AquaEnv , only the calculation of [TA] changes due to changes in the total quantities \(\left[\sum \hbox{B(OH)}_3\right]\), \(\left[\sum \hbox{H}_2\hbox{SO}_4\right]\), and \(\left[\sum \hbox{HF}\right]\) when non-seawater concentrations of borate, sulphate, and fluoride are assumed. The S, t, relations of the dissociation constants remain the ones derived for seawater. The usage and syntax of the titration function is detailed in its R help file as well as in the package vignette of AquaEnv . Example titrations expressed in R code are given in the following code fragment and in the file “AquaEnv-TitrationSimulation.R” in the electronic appendix.

Results can be visualized by plotting pH and speciation against the amount of titrant added or any other variable in the aquaenv object (Fig. 6). However, an aquaenv object containing an in silico titration can also be visualized via Bjerrum plots (Fig. 7). The respective calls to the function plot.aquaenv can be found in the file “AquaEnv-TitrationSimulation.R” in the electronic appendix and in the following code fragment: the first block produces the plots in Fig. 6, the second block produces the plots in Fig. 7.

Fig. 6
figure 6

Visualizing the results of an in silico titration. Note that the CO2 concentration declines towards the right of the plot. This is due to the fact that the titration function takes into account the dilution of the dissolved inorganic carbonate concentration due to the addition of titrant

Fig. 7
figure 7

Left panel Bjerrum plot of a selection of concentrations of dissociated species in the example in silico titration, concentrations are plotted on logarithmic scale. Right panel Bjerrum-like plot, concentrations are plotted on non-logarithmic scale

The plots in Fig. 7 differ from the classical textbook Bjerrum graphs (e.g. Zeebe and Wolf-Gladrow 2001) since the effect of dilution due to the addition of titrant is accounted for (this can be seen, for example, in the left panel, in a decrease in [SO 2−4 ] from high to low pH values which is an effect of a decrease in \(\left[\sum \hbox{H}_2\hbox{SO}_4\right]\) due to dilution during the titration which started at a high pH. In the right panel, this can be seen by a decrease in \(\left[\sum \hbox{CO}_2\right]\) (the curves for the three carbonate species added up) from high to low pH values due to dilution). Although one can create a theoretical textbook Bjerrum plot which is not based on a titration experiment by creating an aquaenv object with a vector of [TA] values as input (see Fig. 3 and the corresponding code fragment), creating a textbook Bjerrum plot is also possible based on a virtual titration experiment. When simulating a titration with a rather large volume and a concentrated titrant, the volume and salinity corrections are only minor, and one obtains the classical Bjerrum graphs known from textbooks (see Fig. 8 which is produced by the following code fragment. Note that, within the precision of the plot, the total quantities do not change anymore. Note also, that we changed the list of variables to be displayed from Fig. 7, that we changed the colours for the different variables, and that we zoomed in on an interesting section. We did this to illustrate the plotting capabilities of AquaEnv ).

Fig. 8
figure 8

Classical textbook Bjerrum plot using an in silico titration object

5.3 Titration Data Analysis: Obtaining Total Alkalinity and Total Carbonate From Titration Data

The function TAfit is based on a method described in DOE (1994) and Dickson et al. (2007), makes use of the in silico titration function titration provided in AquaEnv , and allows for determining total alkalinity ([TA]), the total dissolved inorganic carbon concentrationFootnote 2 (\(\left[\sum \hbox{CO}_2\right]\)), as well as the electrode standard potential (E 0) and the first dissociation constant of the carbonate system (\(K_{\rm{CO2}}^{*}\)) from measured titration curves (pH versus the mass of titrant added) using an inverse modelling procedure. The Levenberg-Marquardt least squares optimization algorithm as provided in the R package minpack.lm (Elzhov and Mullen 2008) is employed to match calculated and measured titration curves.

The underlying principle of TAfit is simple: it generates an in silico titration curve (using an initial aquaenv object and the supplied parameters conc_titrant , mass_sample , S_titrant , and seawater_titrant which are passed on to the function titration ) with arbitrary values for [TA], \(\left[\sum \hbox{CO}_2\right]\), and E 0 (if an electrode potential curve is used). This in silico titration curve is then compared to the measured curve. In an iterative least-squares procedure, the arbitrary values for [TA], \(\left[\sum \hbox{CO}_2\right]\), and E 0 are then refined to the “best-fitting” values by matching the calculated and the measured titration curve (by setting the flag verbose to TRUE , the fitting process can be visualized while it is performed). Note that, although TAfit always returns values for [TA] and \(\left[\sum \hbox{CO}_2\right]\), the \(\left[\sum \hbox{CO}_2\right]\) value only reflects the value of the original sample if the titration is conducted in a closed vessel to prevent equilibration with the air. Due to uncertainties in the first dissociation constant of the carbonate system \(K_{\rm{CO2}}^{*}\), it is sometimes advised to fit this constant in the iterative least-squares procedure as well (this can be specified in TAfit via the logical flag K_CO2fit ). All other dissociation constants are calculated from salinity, temperature, and pressure. This curve fitting procedure was introduced by Dickson (1981), restated in DOE (1994) and Dickson et al. (2007), and mentioned by Anderson et al. (1999) and Zeebe and Wolf-Gladrow (2001). Additionally, Dickson et al. (2007) employ an open-cell variant of this method: a [TA] value is obtained by fitting only a part of the total titration curve after the sample has been acidified to expel all carbonate from the solution. The function TAfit is also capable of fitting only a part of a titration curve: with the argument datxbegin the amount of titrant added to acidify the sample before the actual titration can be specified. The usage and syntax of the TAfit function is detailed in its R help file as well as in the package vignette of AquaEnv .

Here, the functioning of TAfit is illustrated with a simple example. Dickson (1981) provided a benchmark test for total alkalinity fitting programs in the form of a synthetic dataset. This dataset is included in AquaEnv as the object sample_dickson1981 . Dickson (1981) uses fixed values for the equilibrium constants instead of calculating them as functions of salinity and temperature. TAfit allows for providing fixed values for the main dissociation constants, so the values given in Dickson (1981) can be used for the fitting procedure. As shown in the script and associated output in the following code fragment, the values for [TA] and \(\left[\sum \hbox{CO}_2\right]\) returned by the function TAfit are exactly the same as given in Dickson (1981), i.e., the fitting procedure yields the correct values.

Note that, for computational reasons, Johansson and Wedborg (1982) and Anderson et al. (1999) suggested to switch the dependent and independent variables, i.e., to calculate a theoretical vector of titrant masses instead of a vector of theoretical pH or E values while calculating the in silico titration curve. This has the advantage that one does not need to solve a non-linear equation system for the pH at every point of every in silico titration. However, due to the fact that in curve fitting algorithms the sum of squares of errors in the dependent variable is minimized, while errors in the independent variable are disregarded, Anderson et al. (1999) concluded that in principle the pH (or E) values would be the best choice as dependent variable, as their associated measurement uncertainty is larger than the measurement uncertainty for the amount of titrant added. Since nowadays computational power is not limiting anymore, we implemented the TAfit function of AquaEnv such that pH or E serve as dependent variables.

6 Summary

The R -package AquaEnv provides an integrated framework for acid–base speciation calculations and pH modelling. AquaEnv extends the functionality and application domain of packages like CO 2 SYS (Lewis and Wallace 1998; Pierrot et al. 2006) and seacarb (Lavigne et al. 2008). The package is not only applicable to seawater, but also to brackish and freshwater environments, and it not only deals with carbonate chemistry, but also includes a large selection of other relevant acid–base systems in natural waters. We adopted an integrated programming style by letting the function aquaenv create objects of a certain class which then can be visualized and processed with the functions plot and convert , but can also be exported to an R data.frame for further processing. AquaEnv cannot only be used as a stand-alone tool for quick calculations or rapid prototyping of models, but it can also be seamlessly integrated with complex biogeochemical models in the R modelling environment. Furthermore, it provides functions that allow to simulate titrations and to calculate alkalinity and total carbonate values from measured titration data.