Calculate sensitivities with the derivnum add-on for CO2SYS-Matlab


James Orr - 27 February 2018

<img align="left" width="60%" src="http://www.lsce.ipsl.fr/Css/img/banniere_LSCE_75.png" >

LSCE/IPSL, CEA-CNRS-UVSQ, Gif-sur-Yvette, France


Abstract: This notebook shows how to use the new derivnum add-on of CO2SYS-Matlab to calculate sensitivities, i.e. partial derivatives that express rates changes of computed CO2 system variables (e.g., H+, $p$CO$_2$, $\Omega_A$) per change in the selected input variable (e.g., $A_\text{T}$, $C_\text{T}$, T, S, $K_1$, $K_2$). It uses CO2SYS-Matlab in octave, GNU's clone of Matlab. One can simply inspect the HTML version of this file or take advantage of being able to execute its commands interactively in your browser. The latter requires jupyter notebook and its oct2py add-on that includes the octavemagic interface for octave (see below).

Table of Contents:

1. Basics (install & load octave)
2. Compute sensitivities with `derivnum` add-on for CO2SYS (ALK-DIC)
3. Compute sentitivities as before, but for a different input pair (pH-ALK)
4. Compute sentitivities as before, but for a different input pair (pCO2-DIC)

1. Basics

Run interactively

If you are visualizing this after clicking on the link to this file on github, you are visualizing the HTML version of a jupyter notebook. Alternatively, you may run cells interactively and modify them if you have jupyter notebook installed on your machine. To install that software, just download and the anaconda open software installer for your computing platform (Windows, OS X, or Linux) from https://www.continuum.io/downloads and then follow the easy install instructions at

https://docs.continuum.io/anaconda/install#

Then just download this jupyter notebook file as well as the 3 routines in the src directory (CO2SYS.m, errors.m, and derivnum.m). Afterwards, you'll only need to install octavemagic, available in the oct2py package with the 1-line command in the following section.

Install octavemagic

To install the octavemagic funtionality, we must install oct2py, with the following command at the Unix prompt:

conda install -c conda-forge oct2py=3.6.5

Then launch the notebook as usual with the following command:

jupyter notebook

A new window or tab should appear in your browser, showing the files in the directory from where you launched the above command. Then just click on one of the .ipynb files, such as this one.

One the notebook file appears in your browser, move to any of its cells with your mouse. Run a cell by clicking on it and hitting Ctrl-Return. Alternatively, type Shift-Return to run a cell and then move to the next one. More information on all the interactive commankds is available in the Jupyter Notebook Quick Start Guide: http://jupyter-notebook-beginner-guide.readthedocs.io/en/latest/execute.html

At the top of the notebook, you'll see 8 Tabs (File, Edit, View, Insert, ...). Those tabls provide commands that will allow you to do whatever you like. Under the Help tab you'll find keyboard shortcuts for commands. Alternatively, a cheat sheet for short cuts to commands within jupyter notebook is available at https://zenodo.org/record/44973/files/ipynb-cheat-sheet.pdf . Or use the command palette after typing Ctrl-Shift-P.

Documentation for octavemagic

Load octave magic function

Because octavemagic is now in conda's oct2py module, it is loaded with a slight modification to what is given on the above web page, i.e., now with the command below


In [1]:
%load_ext oct2py.ipython

Specify directory where you have put the Matlab routines CO2SYS.m, errors.m, and derivnum.m.


In [2]:
%%octave
addpath ("~/Software/MATLAB/CO2SYS-MATLAB/src")

2. Compute sentitivities with derivnum add-on for CO2SYS-Matlab ($A_\text{T}$-$C_\text{T}$ pair)

2.1 Specify input variables and choices


In [3]:
%%octave

# Standard input for CO2SYS:
# --------------------------
    # Input Variables:
    PAR1 = 2300;        % ALK
    PAR2 = 2000;        % DIC
    PAR1TYPE = 1;       % 1=ALK, 2=DIC, 3=pH, 4=pCO2, 5=fCO2
    PAR2TYPE = 2;       % Same 5 choices as PAR1TYPE
    SAL = 35;           % Salinity
    TEMPIN = 18;        % Temperature (input)
    TEMPOUT = 25;       % Temperature (output)
    PRESIN = 0;         % Pressure (input)
    PRESOUT = PRESIN;   % Pressure (output)
#   SI = 60;            % Total dissolved inorganic silicon (Sit)
#   PO4 = 2;            % Total dissoloved inorganic Phosphorus (Pt)
    SI =  0;            % Total dissolved inorganic silicon (Sit)
    PO4 = 0;            % Total dissoloved inorganic Phosphorus (Pt)

    # Input Parameters:
    pHSCALEIN = 1;      % pH scale (1=total, 2=seawater, 3=NBS, 4=Free)
    K1K2CONSTANTS = 10; % set for K1 & K2: 10=Lueker et al. (2000); 14=Millero (2010); 15= Waters et al. (2014)
    KSO4CONSTANTS = 1;  % KSO4 of Dickson (1990a) & Total dissolved boron (Bt) from Uppström (1974)


warning: load: can not read multi-byte encoded UTF8 characters; replacing unreadable characters with '?'

In [4]:
%%octave 
help derivnum


'derivnum' is a function from the file /homel/orr/Software/MATLAB/CO2SYS-MATLAB/src/derivnum.m

 derivnum()
 This subroutine computes partial derivatives of output carbonate variables 
 with respect to input variables (two), plus nutrients (two), temperature and salinity,
 dissociation constants, and total boron.

 It uses central differences, introducing a small perturbation 
 (plus and minus of a delta) in one input variable and computes the
 resulting induced change in each output variable

 After numerical tests, the small PERTURBATION (delta) is chosen
 as a fraction of a reference value as follows:
 * 1.e-3 (0.1%) for the equilibrium constants and total boron 
 * 1.e-6        for the pair of CO2 system input variables (PAR1, PAR2)
 * 1.e-4        for temperature and salinity
 * 1.e-3        for total dissolved inorganic P and Si (PO4, SI)

**************************************************************************

  **** SYNTAX:
  [deriv, headers_der, units_der, headers_err, units_err]=...
                  derivnum(VARID,PAR1,PAR2,PAR1TYPE,PAR2TYPE,...
                          SAL,TEMPIN,TEMPOUT,PRESIN,PRESOUT,...
                          SI,PO4,pHSCALEIN,K1K2CONSTANTS,KSO4CONSTANTS)
 
  **** SYNTAX EXAMPLES:
  [der, headers, units] = derivnum('par1',2400,2200,1,2,35,0,25,4200,0,15,1,1,4,1)
  [der, headers, units] = derivnum('sit', 2400,   8,1,3,35,0,25,4200,0,15,1,1,4,1)
  [deriv, headers]      = derivnum(  'T',  500,   8,5,3,35,0,25,4200,0,15,1,1,4,1)
  [deriv]               = derivnum('S',2400,2000:10:2400,1,2,35,0,25,4200,0,15,1,1,4,1)
  [deriv]               = derivnum('K0',2400,2200,1,2,0:1:35,0,25,4200,0,15,1,1,4,1)
  [deriv]               = derivnum('K1',2400,2200,1,2,35,0,25,0:100:4200,0,15,1,1,4,1)
  
**************************************************************************

 INPUT:

   - VARID     :   character string to select the input variable for which
                   derivatives will be taken with respect to. 
                   This variable appears in denominator of each resulting derivative.
                   = variable length, case insensitive, character code
                     case 'par1'  :  Parameter 1 of the input pair (This is TAlk if PAR1TYPE is 1)
                     case 'par2'  :  Parameter 2 of the input pair (This is TAlk if PAR2TYPE is 1)
                     case 'sil', 'silt', 'tsil', 'silicate', or 'sit'     : Silicate concentration
                     case 'phos', 'phost', 'tphos', 'phosphate', or 'pt'  : Phosphate concentration
                     case 't', 'temp' or 'temperature'           : temperature
                     case 's', 'sal', or 'salinity'              : salinity
                     case 'K0','K1','K2','Kb','Kw','Kspa', 'Kspc': dissociation constants 
                     case 'bor': total boron

   - all others :  same list of input parameters as in CO2SYS() subroutine (scalar or vectors)

**************************************************************************%

 OUTPUT: * an array containing the derivative of the following parameter (one row per sample):
         *  a cell-array containing crudely formatted headers

    POS  PARAMETER        UNIT

    01 - TAlk                 (umol/kgSW)
    02 - TCO2                 (umol/kgSW)
    03 - [H+] input           (umol/kgSW)
    04 - pCO2 input           (uatm)
    05 - fCO2 input           (uatm)
    06 - HCO3 input           (umol/kgSW)
    07 - CO3 input            (umol/kgSW)
    08 - CO2 input            (umol/kgSW)
    09 - OmegaCa input        ()
    10 - OmegaAr input        ()
    11 - xCO2 input           (ppm)
    12 - [H+] output          ()
    13 - pCO2 output          (uatm)
    14 - fCO2 output          (uatm)
    15 - HCO3 output          (umol/kgSW)
    16 - CO3 output           (umol/kgSW)
    17 - CO2 output           (umol/kgSW)
    18 - OmegaCa output       ()
    19 - OmegaAr output       ()
    20 - xCO2 output          (ppm)

 Remark : if all input pairs are of the same type, derivatives of input pairs are omitted



Additional help for built-in functions and operators is
available in the online version of the manual.  Use the command
'doc <topic>' to search the manual index.

Help and information about Octave is also available on the WWW
at http://www.octave.org and via the help@octave.org
mailing list.

2.2 Partial derivatives with respect to par1 (specified above as ALK)


In [5]:
%%octave
    [b, bhead, bunits] = derivnum ('par1', PAR1, PAR2, PAR1TYPE, PAR2TYPE, SAL, TEMPIN, TEMPOUT, PRESIN, PRESOUT,... 
                                   SI, PO4,...
                                   pHSCALEIN, K1K2CONSTANTS, KSO4CONSTANTS);
# Print (nicely formatted):
  printf("%s %s %s %s %s %s %s %s %s \n", bhead{1:9});
  printf("%s %s %s %s %s %s %s %s %s \n", bunits{1:9});
  printf("%f  %f   %f    %f    %f    %f   %f         %f       %f \n", b(1:9));


dHin/dALK dpCO2in/dALK dfCO2in/dALK dHCO3in/dALK dCO3in/dALK dCO2in/dALK dOmegaCAin/dALK dOmegaARin/dALK dxCO2in/dALK 
(nmol/umol) (uatm kg/umol) (uatm kg/umol) (umol/umol) (umol/umol) (umol/umol) (kg/umol) (kg/umol) (ppm kg/umol) 
-0.025272  -1.177568   -1.173474    -0.640003    0.680239    -0.040236   0.016242         0.010503       -1.201560 

2.3 Partial derivatives with respect to par1 (specified above as DIC)


In [6]:
%%octave
    [b, bhead, bunits] = derivnum ('par2', PAR1, PAR2, PAR1TYPE, PAR2TYPE, SAL, TEMPIN, TEMPOUT, PRESIN, PRESOUT,... 
                                   SI, PO4,...
                                   pHSCALEIN, K1K2CONSTANTS, KSO4CONSTANTS);
# Print (nicely formatted):
  printf("%s %s %s %s %s %s %s %s %s \n", bhead{1:9});
  printf("%s %s %s %s %s %s %s %s %s \n", bunits{1:9});
  printf("%f  %f   %f    %f    %f    %f   %f         %f       %f \n", b(1:9));


dHin/dDIC dpCO2in/dDIC dfCO2in/dDIC dHCO3in/dDIC dCO3in/dDIC dCO2in/dDIC dOmegaCAin/dDIC dOmegaARin/dDIC dxCO2in/dDIC 
(nmol/umol) (uatm kg/umol) (uatm kg/umol) (umol/umol) (umol/umol) (umol/umol) (kg/umol) (kg/umol) (ppm kg/umol) 
0.027804  1.444617   1.439594    1.593748    -0.643108    0.049360   -0.015355         -0.009929       1.474049 

2.3 Partial derivatives with respect to Temperature


In [7]:
%%octave
    [b, bhead, bunits] = derivnum ('T', PAR1, PAR2, PAR1TYPE, PAR2TYPE, SAL, TEMPIN, TEMPOUT, PRESIN, PRESOUT,... 
                                   SI, PO4,...
                                   pHSCALEIN, K1K2CONSTANTS, KSO4CONSTANTS);
# Print (nicely formatted):
  printf("%s %s %s %s %s %s %s %s %s \n", bhead{1:9});
  printf("%s %s %s %s %s %s %s %s %s \n", bunits{1:9});
  printf("%f  %f   %f    %f    %f    %f   %f         %f       %f \n", b(1:9));


dHin/dT dpCO2in/dT dfCO2in/dT dHCO3in/dT dCO3in/dT dCO2in/dT dOmegaCAin/dT dOmegaARin/dT dxCO2in/dT 
(nmol/kg/C) (uatm/C) (uatm/C) (umol/kg/C) (umol/kg/C) (umol/kg/C) ( /C) ( /C) (ppm/C) 
0.249816  12.420949   12.390731    -0.569214    0.436810    0.132404   0.014165         0.017063       13.063959 

2.3 Partial derivatives with respect to Salinity


In [8]:
%%octave
    [b, bhead, bunits] = derivnum ('S', PAR1, PAR2, PAR1TYPE, PAR2TYPE, SAL, TEMPIN, TEMPOUT, PRESIN, PRESOUT,... 
                                   SI, PO4,...
                                   pHSCALEIN, K1K2CONSTANTS, KSO4CONSTANTS);
# Print (nicely formatted):
  printf("%s %s %s %s %s %s %s %s %s \n", bhead{1:9});
  printf("%s %s %s %s %s %s %s %s %s \n", bunits{1:9});
  printf("%f  %f   %f    %f    %f    %f   %f         %f       %f \n", b(1:9));


dHin/dS dpCO2in/dS dfCO2in/dS dHCO3in/dS dCO3in/dS dCO2in/dS dOmegaCAin/dS dOmegaARin/dS dxCO2in/dS 
(nmol/kg/psu) (uatm/psu) (uatm/psu) (umol/kg/psu) (umol/kg/psu) (umol/kg/psu) ( /psu) ( /psu) (ppm/psu) 
0.205749  8.118520   8.090290    0.988837    -1.210351    0.221515   -0.065058         -0.037038       8.280555 

2.4 Partial derivatives with respect to $K_1$


In [9]:
%%octave
    [b, bhead, bunits] = derivnum ('K1', PAR1, PAR2, PAR1TYPE, PAR2TYPE, SAL, TEMPIN, TEMPOUT, PRESIN, PRESOUT,... 
                                   SI, PO4,...
                                   pHSCALEIN, K1K2CONSTANTS, KSO4CONSTANTS);
# Print (nicely formatted):
  printf("%s %s %s %s %s %s %s %s %s \n", bhead{1:9});
  printf("%s %s %s %s %s %s %s %s %s \n", bunits{1:9});
  printf("%f  %f   %f    %f    %f    %f   %f         %f       %f \n", b(1:9));


dHin/dK1 dpCO2in/dK1 dfCO2in/dK1 dHCO3in/dK1 dCO3in/dK1 dCO2in/dK1 dOmegaCAin/dK1 dOmegaARin/dK1 dxCO2in/dK1 
(nmol/kg/) (uatm/) (uatm/) (umol/kg/) (umol/kg/) (umol/kg/) ( /) ( /) (ppm/) 
230359.391927  -230506161.311936   -229704650.944598    13204152.567520    -5328129.469279    -7876023.098139   -127215.501345         -82264.826480       -235202479.519809 

2.5 Partial derivatives with respect to $K_A$ (solubility product for aragonite)


In [10]:
%%octave
    [b, bhead, bunits] = derivnum ('Kspa', PAR1, PAR2, PAR1TYPE, PAR2TYPE, SAL, TEMPIN, TEMPOUT, PRESIN, PRESOUT,... 
                                   SI, PO4,...
                                   pHSCALEIN, K1K2CONSTANTS, KSO4CONSTANTS);
# Print (nicely formatted):
  printf("%s %s %s %s %s %s %s %s %s \n", bhead{1:9});
  printf("%s %s %s %s %s %s %s %s %s \n", bunits{1:9});
  printf("%f  %f   %f    %f    %f    %f   %f         %f       %f \n", b(1:9));


dHin/dKSPA dpCO2in/dKSPA dfCO2in/dKSPA dHCO3in/dKSPA dCO3in/dKSPA dCO2in/dKSPA dOmegaCAin/dKSPA dOmegaARin/dKSPA dxCO2in/dKSPA 
(nmol/kg/) (uatm/) (uatm/) (umol/kg/) (umol/kg/) (umol/kg/) ( /) ( /) (ppm/) 
0.000000  0.000000   0.000000    0.000000    0.000000    0.000000   0.000000         -4880821.760913       0.000000 

3. Compute sentitivities with derivnum for a different input pair (pH-$A_\text{T}$)

3.1 Specify input variables and choices


In [11]:
%%octave

# Standard input for CO2SYS:
# --------------------------
    # Input Variables:
    PAR1 = 8.1;         % pH
    PAR2 = 2300;        % ALK
    PAR1TYPE = 3;       % 1=ALK, 2=DIC, 3=pH, 4=pCO2, 5=fCO2
    PAR2TYPE = 1;       % Same 5 choices as PAR1TYPE
    SAL = 35;           % Salinity
    TEMPIN = 18;        % Temperature (input)
    TEMPOUT = 25;       % Temperature (output)
    PRESIN = 0;         % Pressure (input)
    PRESOUT = PRESIN;   % Pressure (output)
    SI = 60;            % Total dissolved inorganic silicon (Sit)
    PO4 = 2;            % Total dissoloved inorganic Phosphorus (Pt)

    # Input Parameters:
    pHSCALEIN = 1;      % pH scale (1=total, 2=seawater, 3=NBS, 4=Free)
    K1K2CONSTANTS = 15; % set for K1 & K2: 10=Lueker et al. (2000); 14=Millero (2010); 15=Waters et al. (2014)
    KSO4CONSTANTS = 1;  % KSO4 of Dickson (1990a) & Total dissolved boron (Bt) from Uppstrom (1974)

3.2 Partial derivatives with respect to H+ (since par1 is pH)


In [12]:
%%octave
    [b, bhead, bunits] = derivnum ('par1', PAR1, PAR2, PAR1TYPE, PAR2TYPE, SAL, TEMPIN, TEMPOUT, PRESIN, PRESOUT,... 
                                   SI, PO4,...
                                   pHSCALEIN, K1K2CONSTANTS, KSO4CONSTANTS);
# Print (nicely formatted):
  printf("%s %s %s %s %s %s %s %s %s \n", bhead{1:9});
  printf("%s %s %s %s %s %s %s %s %s \n", bunits{1:9});
  printf("%f  %f   %f    %f    %f    %f   %f         %f       %f \n", b(1:9));


dTCO2/dH dpCO2in/dH dfCO2in/dH dHCO3in/dH dCO3in/dH dCO2in/dH dOmegaCAin/dH dOmegaARin/dH dxCO2in/dH 
(umol/nmol) (uatm kg/nmol) (uatm kg/nmol) (umol/nmol) (umol/nmol) (umol/nmol) (kg/nmol) (kg/nmol) (ppm kg/nmol) 
30.127283  53.010721   52.826393    47.198812    -18.882819    1.811291   -0.450850         -0.291545       54.090758 

3.3 Partial derivatives with respect to par2 (specified above as ALK)


In [13]:
%%octave
    [b, bhead, bunits] = derivnum ('par2', PAR1, PAR2, PAR1TYPE, PAR2TYPE, SAL, TEMPIN, TEMPOUT, PRESIN, PRESOUT,... 
                                   SI, PO4,...
                                   pHSCALEIN, K1K2CONSTANTS, KSO4CONSTANTS);
# Print (nicely formatted):
  printf("%s %s %s %s %s %s %s %s %s \n", bhead{1:9});
  printf("%s %s %s %s %s %s %s %s %s \n", bunits{1:9});
  printf("%f  %f   %f    %f    %f    %f   %f         %f       %f \n", b(1:9));


dTCO2/dALK dpCO2in/dALK dfCO2in/dALK dHCO3in/dALK dCO3in/dALK dCO2in/dALK dOmegaCAin/dALK dOmegaARin/dALK dxCO2in/dALK 
(umol/umol) (uatm kg/umol) (uatm kg/umol) (umol/umol) (umol/umol) (umol/umol) (kg/umol) (kg/umol) (ppm kg/umol) 
0.919834  0.158460   0.157909    0.828840    0.085580    0.005414   0.002043         0.001321       0.161689 

4. Compute sentitivities with derivnum for a different input pair (pCO2-$C_\text{T}$)

4.1 Specify input variables and choices


In [16]:
%%octave

# Standard input for CO2SYS:
# --------------------------
    # Input Variables:
    PAR1 = 400;         % pCO2
    PAR2 = 2300;        % DIC
    PAR1TYPE = 4;       % 1=ALK, 2=DIC, 3=pH, 4=pCO2, 5=fCO2
    PAR2TYPE = 2;       % Same 5 choices as PAR1TYPE
    SAL = 35;           % Salinity
    TEMPIN = 18;        % Temperature (input)
    TEMPOUT = 25;       % Temperature (output)
    PRESIN = 0;         % Pressure (input)
    PRESOUT = PRESIN;   % Pressure (output)
    SI = 60;            % Total dissolved inorganic silicon (Sit)
    PO4 = 2;            % Total dissoloved inorganic Phosphorus (Pt)

    # Input Parameters:
    pHSCALEIN = 1;      % pH scale (1=total, 2=seawater, 3=NBS, 4=Free)
    K1K2CONSTANTS = 15; % set for K1 & K2: 10=Lueker et al. (2000); 14=Millero (2010); 15=Waters et al. (2014)
    KSO4CONSTANTS = 1;  % KSO4 of Dickson (1990a) & Total dissolved boron (Bt) from Uppstrom (1974)

4.2 Partial derivatives with respect to par1 (specified as pCO2 above)


In [17]:
%%octave
    [b, bhead, bunits] = derivnum ('par1', PAR1, PAR2, PAR1TYPE, PAR2TYPE, SAL, TEMPIN, TEMPOUT, ...
                                   PRESIN, PRESOUT, SI, PO4,...
                                   pHSCALEIN, K1K2CONSTANTS, KSO4CONSTANTS);
# Print (nicely formatted):
  printf("%s %s %s %s %s %s %s %s %s \n", bhead{1:9});
  printf("%s %s %s %s %s %s %s %s %s \n", bunits{1:9});
  printf("%f  %f   %f    %f    %f    %f   %f         %f       %f \n", b(1:9));


dTAlk/dpCO2 dHin/dpCO2 dfCO2in/dpCO2 dHCO3in/dpCO2 dCO3in/dpCO2 dCO2in/dpCO2 dOmegaCAin/dpCO2 dOmegaARin/dpCO2 dxCO2in/dpCO2 
(umol/kg/uatm) (nmol/kg/uatm) (uatm/uatm) (umol/kg/uatm) (umol/kg/uatm) (umol/kg/uatm) ( /uatm) ( /uatm) (ppm/uatm) 
-0.652024  0.018440   0.996523    0.412178    -0.446346    0.034168   -0.010657         -0.006891       1.020374 

4.3 Partial derivatives with respect to par2 (specified above as DIC)


In [18]:
%%octave
    [b, bhead, bunits] = derivnum ('par2', PAR1, PAR2, PAR1TYPE, PAR2TYPE, SAL, TEMPIN, TEMPOUT,... 
                                   PRESIN, PRESOUT, SI, PO4,...
                                   pHSCALEIN, K1K2CONSTANTS, KSO4CONSTANTS);
# Print (nicely formatted):
  printf("%s %s %s %s %s %s %s %s %s \n", bhead{1:9});
  printf("%s %s %s %s %s %s %s %s %s \n", bunits{1:9});
  printf("%f  %f   %f    %f    %f    %f   %f         %f       %f \n", b(1:9));


dTAlk/dDIC dHin/dDIC dfCO2in/dDIC dHCO3in/dDIC dCO3in/dDIC dCO2in/dDIC dOmegaCAin/dDIC dOmegaARin/dDIC dxCO2in/dDIC 
(umol/umol) (nmol/umol) (uatm kg/umol) (umol/umol) (umol/umol) (umol/umol) (kg/umol) (kg/umol) (ppm kg/umol) 
1.199753  -0.003207   0.000000    0.830075    0.169925    -0.000000   0.004057         0.002624       0.000000