New URL for NEMO forge!   http://forge.nemo-ocean.eu

Since March 2022 along with NEMO 4.2 release, the code development moved to a self-hosted GitLab.
This present forge is now archived and remained online for history.
mocsy_mainmod.F90 in branches/UKMO/dev_r5518_GO6_under_ice_relax_dr_hook/NEMOGCM/NEMO/TOP_SRC/MEDUSA – NEMO

source: branches/UKMO/dev_r5518_GO6_under_ice_relax_dr_hook/NEMOGCM/NEMO/TOP_SRC/MEDUSA/mocsy_mainmod.F90 @ 11738

Last change on this file since 11738 was 11738, checked in by marc, 5 years ago

The Dr Hook changes from my perl code.

File size: 90.1 KB
Line 
1MODULE mocsy_mainmod
2
3      USE in_out_manager  ! I/O manager
4
5CONTAINS
6
7! ----------------------------------------------------------------------
8!  SW_ADTG
9! ----------------------------------------------------------------------
10!
11!> \file sw_adtg.f90
12!! \BRIEF
13!> Module with sw_adtg function - compute adiabatic temp. gradient from S,T,P
14!>  Function to calculate adiabatic temperature gradient as per UNESCO 1983 routines.
15FUNCTION sw_adtg  (s,t,p)
16
17  !     ==================================================================
18  !     Calculates adiabatic temperature gradient as per UNESCO 1983 routines.
19  !     Armin Koehl akoehl@ucsd.edu
20  !     ==================================================================
21  USE mocsy_singledouble
22  USE yomhook, ONLY: lhook, dr_hook
23  USE parkind1, ONLY: jprb, jpim
24
25  IMPLICIT NONE
26  !> salinity [psu (PSU-78)]
27  REAL(kind=wp) :: s
28  !> temperature [degree C (IPTS-68)]
29  REAL(kind=wp) :: t
30  !> pressure [db]
31  REAL(kind=wp) :: p
32
33  REAL(kind=wp) :: a0,a1,a2,a3,b0,b1,c0,c1,c2,c3,d0,d1,e0,e1,e2
34  REAL(kind=wp) :: sref
35
36  REAL(kind=wp) :: sw_adtg
37  INTEGER(KIND=jpim), PARAMETER :: zhook_in = 0
38  INTEGER(KIND=jpim), PARAMETER :: zhook_out = 1
39  REAL(KIND=jprb)               :: zhook_handle
40
41  CHARACTER(LEN=*), PARAMETER :: RoutineName='SW_ADTG'
42
43  IF (lhook) CALL dr_hook(RoutineName,zhook_in,zhook_handle)
44
45
46  sref = 35.d0
47  a0 =  3.5803d-5
48  a1 = +8.5258d-6
49  a2 = -6.836d-8
50  a3 =  6.6228d-10
51
52  b0 = +1.8932d-6
53  b1 = -4.2393d-8
54
55  c0 = +1.8741d-8
56  c1 = -6.7795d-10
57  c2 = +8.733d-12
58  c3 = -5.4481d-14
59
60  d0 = -1.1351d-10
61  d1 =  2.7759d-12
62
63  e0 = -4.6206d-13
64  e1 = +1.8676d-14
65  e2 = -2.1687d-16
66
67  sw_adtg =  a0 + (a1 + (a2 + a3*T)*T)*T &
68       + (b0 + b1*T)*(S-sref) &
69       + ( (c0 + (c1 + (c2 + c3*T)*T)*T) + (d0 + d1*T)*(S-sref) )*P &
70       + (  e0 + (e1 + e2*T)*T )*P*P
71
72  IF (lhook) CALL dr_hook(RoutineName,zhook_out,zhook_handle)
73END FUNCTION sw_adtg
74
75! ----------------------------------------------------------------------
76!  SW_ADTG
77! ----------------------------------------------------------------------
78!
79!> \file sw_ptmp.f90
80!! \BRIEF
81!> Module with sw_ptmp function - compute potential T from in-situ T
82!> Function to calculate potential temperature [C] from in-situ temperature
83FUNCTION sw_ptmp  (s,t,p,pr)
84
85  !     ==================================================================
86  !     Calculates potential temperature [C] from in-situ Temperature [C]
87  !     From UNESCO 1983 report.
88  !     Armin Koehl akoehl@ucsd.edu
89  !     ==================================================================
90
91  !     Input arguments:
92  !     -------------------------------------
93  !     s  = salinity            [psu      (PSS-78) ]
94  !     t  = temperature         [degree C (IPTS-68)]
95  !     p  = pressure            [db]
96  !     pr = reference pressure  [db]
97
98  USE mocsy_singledouble
99  USE yomhook, ONLY: lhook, dr_hook
100  USE parkind1, ONLY: jprb, jpim
101
102  IMPLICIT NONE
103
104! Input arguments
105  !> salinity [psu (PSS-78)]
106  REAL(kind=wp) :: s
107  !> temperature [degree C (IPTS-68)]
108  REAL(kind=wp) :: t
109  !> pressure [db]
110  REAL(kind=wp) :: p
111  !> reference pressure  [db] 
112  REAL(kind=wp) :: pr
113
114! local arguments
115  REAL(kind=wp) :: del_P ,del_th, th, q
116  REAL(kind=wp) :: onehalf, two, three
117  PARAMETER (onehalf = 0.5d0, two = 2.d0, three = 3.d0 )
118
119! REAL(kind=wp) :: sw_adtg
120! EXTERNAL sw_adtg
121
122! Output
123  REAL(kind=wp) :: sw_ptmp
124  INTEGER(KIND=jpim), PARAMETER :: zhook_in = 0
125  INTEGER(KIND=jpim), PARAMETER :: zhook_out = 1
126  REAL(KIND=jprb)               :: zhook_handle
127
128  CHARACTER(LEN=*), PARAMETER :: RoutineName='SW_PTMP'
129
130  IF (lhook) CALL dr_hook(RoutineName,zhook_in,zhook_handle)
131
132
133  ! theta1
134  del_P  = PR - P
135  del_th = del_P*sw_adtg(S,T,P)
136  th     = T + onehalf*del_th
137  q      = del_th
138
139  ! theta2
140  del_th = del_P*sw_adtg(S,th,P+onehalf*del_P)
141  th     = th + (1.d0 - 1.d0/SQRT(two))*(del_th - q)
142  q      = (two-SQRT(two))*del_th + (-two+three/SQRT(two))*q
143
144  ! theta3
145  del_th = del_P*sw_adtg(S,th,P+onehalf*del_P)
146  th     = th + (1.d0 + 1.d0/SQRT(two))*(del_th - q)
147  q      = (two + SQRT(two))*del_th + (-two-three/SQRT(two))*q
148
149  ! theta4
150  del_th = del_P*sw_adtg(S,th,P+del_P)
151  sw_ptmp     = th + (del_th - two*q)/(two*three)
152
153  IF (lhook) CALL dr_hook(RoutineName,zhook_out ,zhook_handle)
154  RETURN
155  IF (lhook) CALL dr_hook(RoutineName,zhook_out,zhook_handle)
156END FUNCTION sw_ptmp
157
158
159! ----------------------------------------------------------------------
160!  SW_TEMP
161! ----------------------------------------------------------------------
162!
163!> \file sw_temp.f90
164!! \BRIEF
165!> Module with sw_temp function - compute in-situ T from potential T
166!> Function to compute in-situ temperature [C] from potential temperature [C]
167FUNCTION sw_temp( s, t, p, pr )
168  !     =============================================================
169  !     SW_TEMP
170  !     Computes in-situ temperature [C] from potential temperature [C]
171  !     Routine available in seawater.f (used for MIT GCM)
172  !     Downloaded seawater.f (on 17 April 2009) from
173  !     http://ecco2.jpl.nasa.gov/data1/beaufort/MITgcm/bin/
174  !     =============================================================
175
176  !     REFERENCES:
177  !     Fofonoff, P. and Millard, R.C. Jr
178  !     Unesco 1983. Algorithms for computation of fundamental properties of
179  !     seawater, 1983. _Unesco Tech. Pap. in Mar. Sci._, No. 44, 53 pp.
180  !     Eqn.(31) p.39
181
182  !     Bryden, H. 1973.
183  !     "New Polynomials for thermal expansion, adiabatic temperature gradient
184  !     and potential temperature of sea water."
185  !     DEEP-SEA RES., 1973, Vol20,401-408.
186  !     =============================================================
187
188  !     Simple modifications: J. C. Orr, 16 April 2009
189  !     - combined fortran code from MITgcm site & simplification in
190  !       CSIRO code (matlab equivalent) from Phil Morgan
191
192  USE mocsy_singledouble
193  USE yomhook, ONLY: lhook, dr_hook
194  USE parkind1, ONLY: jprb, jpim
195
196  IMPLICIT NONE
197
198  !     Input arguments:
199  !     -----------------------------------------------
200  !     s  = salinity              [psu      (PSS-78) ]
201  !     t  = potential temperature [degree C (IPTS-68)]
202  !     p  = pressure              [db]
203  !     pr = reference pressure    [db]
204
205  !> salinity [psu (PSS-78)]
206  REAL(kind=wp) ::   s
207  !> potential temperature [degree C (IPTS-68)]
208  REAL(kind=wp) ::   t
209  !> pressure [db]
210  REAL(kind=wp) ::   p
211  !> reference pressure [db]
212  REAL(kind=wp) ::   pr
213
214  REAL(kind=wp) ::  ds, dt, dp, dpr
215  REAL(kind=wp) :: dsw_temp
216
217  REAL(kind=wp) ::   sw_temp
218  INTEGER(KIND=jpim), PARAMETER :: zhook_in = 0
219  INTEGER(KIND=jpim), PARAMETER :: zhook_out = 1
220  REAL(KIND=jprb)               :: zhook_handle
221
222  CHARACTER(LEN=*), PARAMETER :: RoutineName='SW_TEMP'
223
224  IF (lhook) CALL dr_hook(RoutineName,zhook_in,zhook_handle)
225
226! EXTERNAL sw_ptmp
227! REAL(kind=wp) ::   sw_ptmp
228
229  ds = DBLE(s)
230  dt = DBLE(t)
231  dp = DBLE(p)
232  dpr = DBLE(pr)
233
234  !    Simple solution
235  !    (see https://svn.mpl.ird.fr/us191/oceano/tags/V0/lib/matlab/seawater/sw_temp.m)
236  !    Carry out inverse calculation by swapping P_ref (pr) and Pressure (p)
237  !    in routine that is normally used to compute potential temp from temp
238  dsw_temp = sw_ptmp(ds, dt, dpr, dp)
239  sw_temp = REAL(dsw_temp)
240
241  !    The above simplification works extremely well (compared to Table in 1983 report)
242  !    whereas the sw_temp routine from MIT GCM site does not seem to work right
243
244  IF (lhook) CALL dr_hook(RoutineName,zhook_out ,zhook_handle)
245  RETURN
246  IF (lhook) CALL dr_hook(RoutineName,zhook_out,zhook_handle)
247END FUNCTION sw_temp
248
249! ----------------------------------------------------------------------
250!  TPOT
251! ----------------------------------------------------------------------
252!
253!> \file tpot.f90
254!! \BRIEF
255!>    Module with tpot subroutine - compute potential T from in situ T,S,P
256!>    Compute potential temperature from arrays of in situ temp, salinity, and pressure.
257!!    This subroutine is needed because sw_ptmp is a function (using scalars not arrays)
258SUBROUTINE tpot(salt, tempis, press, pressref, N, tempot)
259  !    Purpose:
260  !    Compute potential temperature from arrays of in situ temp, salinity, and pressure.
261  !    Needed because sw_ptmp is a function
262
263  USE mocsy_singledouble
264  USE yomhook, ONLY: lhook, dr_hook
265  USE parkind1, ONLY: jprb, jpim
266
267  IMPLICIT NONE
268
269  !> number of records
270  INTEGER, intent(in) :: N
271
272! INPUT variables
273  !> salinity [psu]
274  REAL(kind=wp), INTENT(in), DIMENSION(N) :: salt
275  !> in situ temperature [C]
276  REAL(kind=wp), INTENT(in), DIMENSION(N) :: tempis
277  !> pressure [db]
278  REAL(kind=wp), INTENT(in), DIMENSION(N) :: press
279!f2py optional , depend(salt) :: n=len(salt)
280  !> pressure reference level [db]
281  REAL(kind=wp), INTENT(in) :: pressref
282
283! OUTPUT variables:
284  !> potential temperature [C] for pressref
285  REAL(kind=wp), INTENT(out), DIMENSION(N) :: tempot
286
287  REAL(kind=wp) :: dsalt, dtempis, dpress, dpressref
288  REAL(kind=wp) :: dtempot
289
290  INTEGER :: i
291  INTEGER(KIND=jpim), PARAMETER :: zhook_in = 0
292  INTEGER(KIND=jpim), PARAMETER :: zhook_out = 1
293  REAL(KIND=jprb)               :: zhook_handle
294
295  CHARACTER(LEN=*), PARAMETER :: RoutineName='TPOT'
296
297  IF (lhook) CALL dr_hook(RoutineName,zhook_in,zhook_handle)
298
299
300! REAL(kind=wp) :: sw_ptmp
301! EXTERNAL sw_ptmp
302
303  DO i = 1,N
304     dsalt     = DBLE(salt(i))
305     dtempis   = DBLE(tempis(i))
306     dpress    = DBLE(press(i))
307     dpressref = DBLE(pressref)
308
309     dtempot   = sw_ptmp(dsalt, dtempis, dpress, dpressref)
310
311     tempot(i) = REAL(dtempot)
312  END DO
313
314  IF (lhook) CALL dr_hook(RoutineName,zhook_out ,zhook_handle)
315  RETURN
316  IF (lhook) CALL dr_hook(RoutineName,zhook_out,zhook_handle)
317END SUBROUTINE tpot
318
319! ----------------------------------------------------------------------
320!  TIS
321! ----------------------------------------------------------------------
322!
323!> \file tis.f90
324!! \BRIEF
325!>    Module with tis subroutine - compute in situ T from S,T,P
326!>    Compute in situ temperature from arrays of potential temp, salinity, and pressure.
327!!    This subroutine is needed because sw_temp is a function (using scalars not arrays)
328SUBROUTINE tis(salt, tempot, press, pressref, N, tempis)
329  !    Purpose:
330  !    Compute in situ temperature from arrays of in situ temp, salinity, and pressure.
331  !    Needed because sw_temp is a function
332
333  USE mocsy_singledouble
334  USE yomhook, ONLY: lhook, dr_hook
335  USE parkind1, ONLY: jprb, jpim
336
337  IMPLICIT NONE
338
339  !> number of records
340  INTEGER, intent(in) :: N
341
342! INPUT variables
343  !> salinity [psu]
344  REAL(kind=wp), INTENT(in), DIMENSION(N) :: salt
345  !> potential temperature [C]
346  REAL(kind=wp), INTENT(in), DIMENSION(N) :: tempot
347  !> pressure [db]
348  REAL(kind=wp), INTENT(in), DIMENSION(N) :: press
349!f2py optional , depend(salt) :: n=len(salt)
350  !> pressure reference level [db]
351  REAL(kind=wp), INTENT(in) :: pressref
352
353! OUTPUT variables:
354  !> in situ temperature [C]
355  REAL(kind=wp), INTENT(out), DIMENSION(N) :: tempis
356
357! REAL(kind=wp) :: dsalt, dtempis, dpress, dpressref
358! REAL(kind=wp) :: dtempot
359
360  INTEGER :: i
361  INTEGER(KIND=jpim), PARAMETER :: zhook_in = 0
362  INTEGER(KIND=jpim), PARAMETER :: zhook_out = 1
363  REAL(KIND=jprb)               :: zhook_handle
364
365  CHARACTER(LEN=*), PARAMETER :: RoutineName='TIS'
366
367  IF (lhook) CALL dr_hook(RoutineName,zhook_in,zhook_handle)
368
369
370! REAL(kind=wp) :: sw_temp
371! REAL(kind=wp) :: sw_temp
372! EXTERNAL sw_temp
373
374  DO i = 1,N
375    !dsalt     = DBLE(salt(i))
376    !dtempot   = DBLE(tempot(i))
377    !dpress    = DBLE(press(i))
378    !dpressref = DBLE(pressref)
379    !dtempis   = sw_temp(dsalt, dtempot, dpress, dpressref)
380    !tempis(i) = REAL(dtempis)
381
382     tempis   = sw_temp(salt(i), tempot(i), press(i), pressref)
383  END DO
384
385  IF (lhook) CALL dr_hook(RoutineName,zhook_out ,zhook_handle)
386  RETURN
387  IF (lhook) CALL dr_hook(RoutineName,zhook_out,zhook_handle)
388END SUBROUTINE tis
389
390! ----------------------------------------------------------------------
391!  P80
392! ----------------------------------------------------------------------
393!
394!> \file p80.f90
395!! \BRIEF
396!> Module with p80 function - compute pressure from depth
397!>     Function to compute pressure from depth using Saunder's (1981) formula with eos80.
398FUNCTION p80(dpth,xlat)
399
400  !     Compute Pressure from depth using Saunder's (1981) formula with eos80.
401
402  !     Reference:
403  !     Saunders, Peter M. (1981) Practical conversion of pressure
404  !     to depth, J. Phys. Ooceanogr., 11, 573-574, (1981)
405
406  !     Coded by:
407  !     R. Millard
408  !     March 9, 1983
409  !     check value: p80=7500.004 dbars at lat=30 deg., depth=7321.45 meters
410
411  !     Modified (slight format changes + added ref. details):
412  !     J. Orr, 16 April 2009
413
414  USE mocsy_singledouble
415  USE yomhook, ONLY: lhook, dr_hook
416  USE parkind1, ONLY: jprb, jpim
417
418  IMPLICIT NONE
419
420! Input variables:
421  !> depth [m]
422  REAL(kind=wp), INTENT(in) :: dpth
423  !> latitude [degrees]
424  REAL(kind=wp), INTENT(in) :: xlat
425
426! Output variable:
427  !> pressure [db]
428  REAL(kind=wp) :: p80
429
430! Local variables:
431  REAL(kind=wp) :: pi
432  REAL(kind=wp) :: plat, d, c1
433  INTEGER(KIND=jpim), PARAMETER :: zhook_in = 0
434  INTEGER(KIND=jpim), PARAMETER :: zhook_out = 1
435  REAL(KIND=jprb)               :: zhook_handle
436
437  CHARACTER(LEN=*), PARAMETER :: RoutineName='P80'
438
439  IF (lhook) CALL dr_hook(RoutineName,zhook_in,zhook_handle)
440
441
442  pi=3.141592654
443
444  plat = ABS(xlat*pi/180.)
445  d  = SIN(plat)
446  c1 = 5.92e-3+d**2 * 5.25e-3
447
448  p80 = ((1-c1)-SQRT(((1-c1)**2)-(8.84e-6*dpth))) / 4.42e-6
449
450  IF (lhook) CALL dr_hook(RoutineName,zhook_out ,zhook_handle)
451  RETURN
452  IF (lhook) CALL dr_hook(RoutineName,zhook_out,zhook_handle)
453END FUNCTION p80
454
455! ----------------------------------------------------------------------
456!  RHO
457! ----------------------------------------------------------------------
458!
459!> \file rho.f90
460!! \BRIEF
461!> Module with rho function - computes in situ density from S, T, P
462!> Function to compute in situ density from salinity (psu), in situ temperature (C), & pressure (bar)
463FUNCTION rho(salt, temp, pbar)
464
465  ! Compute in situ density from salinity (psu), in situ temperature (C), & pressure (bar)
466
467  USE mocsy_singledouble
468  USE yomhook, ONLY: lhook, dr_hook
469  USE parkind1, ONLY: jprb, jpim
470
471  IMPLICIT NONE
472
473  !> salinity [psu]
474  REAL(kind=wp) :: salt
475  !> in situ temperature (C)
476  REAL(kind=wp) :: temp
477  !> pressure (bar) [Note units: this is NOT in decibars]
478  REAL(kind=wp) :: pbar
479
480  REAL(kind=wp) :: s, t, p
481! REAL(kind=wp) :: t68
482  REAL(kind=wp) :: X
483  REAL(kind=wp) :: rhow, rho0
484  REAL(kind=wp) :: a, b, c
485  REAL(kind=wp) :: Ksbmw, Ksbm0, Ksbm
486  REAL(kind=wp) :: drho
487
488  REAL(kind=wp) :: rho
489  INTEGER(KIND=jpim), PARAMETER :: zhook_in = 0
490  INTEGER(KIND=jpim), PARAMETER :: zhook_out = 1
491  REAL(KIND=jprb)               :: zhook_handle
492
493  CHARACTER(LEN=*), PARAMETER :: RoutineName='RHO'
494
495  IF (lhook) CALL dr_hook(RoutineName,zhook_in,zhook_handle)
496
497
498  !     Input arguments:
499  !     -------------------------------------
500  !     s  = salinity            [psu      (PSS-78) ]
501  !     t  = in situ temperature [degree C (IPTS-68)]
502  !     p  = pressure            [bar] !!!!  (not in [db]
503
504  s = DBLE(salt)
505  t = DBLE(temp)
506  p = DBLE(pbar)
507
508! Convert the temperature on today's "ITS 90" scale to older IPTS 68 scale
509! (see Dickson et al., Best Practices Guide, 2007, Chap. 5, p. 7, including footnote)
510! According to Best-Practices guide, line above should be commented & 2 lines below should be uncommented
511! Guide's answer of rho (s=35, t=25, p=0) = 1023.343 is for temperature given on ITPS-68 scale
512! t68 = (T - 0.0002) / 0.99975
513! X = t68
514! Finally, don't do the ITS-90 to IPTS-68 conversion (T input var now already on IPTS-68 scale)
515  X = T
516
517! Density of pure water
518  rhow = 999.842594d0 + 6.793952e-2_wp*X          &
519       -9.095290e-3_wp*X*X + 1.001685e-4_wp*X**3  &
520       -1.120083e-6_wp*X**4 + 6.536332e-9_wp*X**5
521
522! Density of seawater at 1 atm, P=0
523  A = 8.24493e-1_wp - 4.0899e-3_wp*X                         &
524       + 7.6438e-5_wp*X*X - 8.2467e-7_wp*X**3 + 5.3875e-9_wp*X**4
525  B = -5.72466e-3_wp + 1.0227e-4_wp*X - 1.6546e-6_wp*X*X
526  C = 4.8314e-4_wp
527
528  rho0 = rhow + A*S + B*S*SQRT(S) + C*S**2.0d0
529
530! Secant bulk modulus of pure water
531! The secant bulk modulus is the average change in pressure
532! divided by the total change in volume per unit of initial volume.
533  Ksbmw = 19652.21d0 + 148.4206d0*X - 2.327105d0*X*X &
534       + 1.360477e-2_wp*X**3 - 5.155288e-5_wp*X**4
535
536! Secant bulk modulus of seawater at 1 atm
537  Ksbm0 = Ksbmw + S*( 54.6746d0 - 0.603459d0*X + 1.09987e-2_wp*X**2 &
538       - 6.1670e-5_wp*X**3) &
539       + S*SQRT(S)*( 7.944e-2_wp + 1.6483e-2_wp*X - 5.3009e-4_wp*X**2)
540
541! Secant bulk modulus of seawater at S,T,P
542  Ksbm = Ksbm0 &
543       + P*(3.239908d0 + 1.43713e-3_wp*X + 1.16092e-4_wp*X**2 - 5.77905e-7_wp*X**3) &
544       + P*S*(2.2838e-3_wp - 1.0981e-5_wp*X - 1.6078e-6_wp*X**2) &
545       + P*S*SQRT(S)*1.91075e-4_wp &
546       + P*P*(8.50935e-5_wp - 6.12293e-6_wp*X + 5.2787e-8_wp*X**2) &
547       + P*P*S*(-9.9348e-7_wp + 2.0816e-8_wp*X + 9.1697e-10_wp*X**2)
548
549! Density of seawater at S,T,P
550  drho = rho0/(1.0d0 - P/Ksbm)
551  rho = REAL(drho)
552
553  IF (lhook) CALL dr_hook(RoutineName,zhook_out ,zhook_handle)
554  RETURN
555  IF (lhook) CALL dr_hook(RoutineName,zhook_out,zhook_handle)
556END FUNCTION rho
557
558! ----------------------------------------------------------------------
559!  RHOINSITU
560! ----------------------------------------------------------------------
561!
562!> \file rhoinsitu.f90
563!! \BRIEF
564!> Module with rhoinsitu subroutine - compute in situ density from S, Tis, P
565!>     Compute in situ density from salinity (psu), in situ temperature (C), & pressure (db).
566!!     This subroutine is needed because rho is a function (using scalars not arrays)
567SUBROUTINE rhoinsitu(salt, tempis, pdbar, N, rhois)
568
569  !     Purpose:
570  !     Compute in situ density from salinity (psu), in situ temperature (C), & pressure (db)
571  !     Needed because rho is a function
572
573  USE mocsy_singledouble
574  USE yomhook, ONLY: lhook, dr_hook
575  USE parkind1, ONLY: jprb, jpim
576
577  IMPLICIT NONE
578
579  INTEGER :: N
580
581! INPUT variables
582  ! salt   = salinity [psu]
583  ! tempis = in situ temperature [C]
584  ! pdbar  = pressure [db]
585
586  !> salinity [psu]
587  REAL(kind=wp), INTENT(in), DIMENSION(N) :: salt
588  !> in situ temperature [C]
589  REAL(kind=wp), INTENT(in), DIMENSION(N) :: tempis
590  !> pressure [db]
591  REAL(kind=wp), INTENT(in), DIMENSION(N) :: pdbar
592!f2py optional , depend(salt) :: n=len(salt)
593
594! OUTPUT variables:
595  ! rhois  = in situ density
596
597  !> in situ density [kg/m3]
598  REAL(kind=wp), INTENT(out), DIMENSION(N) :: rhois
599
600! Local variables
601  INTEGER :: i
602  INTEGER(KIND=jpim), PARAMETER :: zhook_in = 0
603  INTEGER(KIND=jpim), PARAMETER :: zhook_out = 1
604  REAL(KIND=jprb)               :: zhook_handle
605
606  CHARACTER(LEN=*), PARAMETER :: RoutineName='RHOINSITU'
607
608  IF (lhook) CALL dr_hook(RoutineName,zhook_in,zhook_handle)
609
610
611! REAL(kind=wp) ::  rho
612! EXTERNAL rho
613
614  DO i = 1,N
615     rhois(i) = rho(salt(i), tempis(i), pdbar(i)/10.)
616  END DO
617
618  IF (lhook) CALL dr_hook(RoutineName,zhook_out ,zhook_handle)
619  RETURN
620  IF (lhook) CALL dr_hook(RoutineName,zhook_out,zhook_handle)
621END SUBROUTINE rhoinsitu
622
623! ----------------------------------------------------------------------
624!  DEPTH2PRESS
625! ----------------------------------------------------------------------
626!
627!> \file depth2press.f90
628!! \BRIEF
629!> Module with depth2press subroutine - converts depth to pressure
630!! with Saunders (1981) formula
631!>     Compute pressure [db] from depth [m] & latitude [degrees north].
632!!     This subroutine is needed because p80 is a function (using scalars not arrays)
633SUBROUTINE depth2press(depth, lat, pdbar, N)
634
635  !     Purpose:
636  !     Compute pressure [db] from depth [m] & latitude [degrees north].
637  !     Needed because p80 is a function
638
639  USE mocsy_singledouble
640  USE yomhook, ONLY: lhook, dr_hook
641  USE parkind1, ONLY: jprb, jpim
642
643  IMPLICIT NONE
644
645  !> number of records
646  INTEGER, intent(in) :: N
647
648! INPUT variables
649  !> depth [m]
650  REAL(kind=wp), INTENT(in), DIMENSION(N) :: depth
651  !> latitude [degrees]
652  REAL(kind=wp), INTENT(in), DIMENSION(N) :: lat
653!f2py optional , depend(depth) :: n=len(depth)
654
655! OUTPUT variables:
656  !> pressure [db]
657  REAL(kind=wp), INTENT(out), DIMENSION(N) :: pdbar
658
659  !     Local variables
660  INTEGER :: i
661  INTEGER(KIND=jpim), PARAMETER :: zhook_in = 0
662  INTEGER(KIND=jpim), PARAMETER :: zhook_out = 1
663  REAL(KIND=jprb)               :: zhook_handle
664
665  CHARACTER(LEN=*), PARAMETER :: RoutineName='DEPTH2PRESS'
666
667  IF (lhook) CALL dr_hook(RoutineName,zhook_in,zhook_handle)
668
669
670! REAL(kind=wp) ::  p80
671! EXTERNAL p80
672
673  DO i = 1,N
674     pdbar(i) = p80(depth(i), lat(i))
675  END DO
676
677  IF (lhook) CALL dr_hook(RoutineName,zhook_out ,zhook_handle)
678  RETURN
679  IF (lhook) CALL dr_hook(RoutineName,zhook_out,zhook_handle)
680END SUBROUTINE depth2press
681
682! ----------------------------------------------------------------------
683!  CONSTANTS
684! ----------------------------------------------------------------------
685!
686!> \file constants.f90
687!! \BRIEF
688!> Module with contants subroutine - computes carbonate system constants
689!! from S,T,P
690!> Compute thermodynamic constants
691!! FROM temperature, salinity, and pressure (1D arrays)
692SUBROUTINE constants(K0, K1, K2, Kb, Kw, Ks, Kf, Kspc, Kspa,  &
693                     K1p, K2p, K3p, Ksi,                      &
694                     St, Ft, Bt,                              &
695                     temp, sal, Patm,                         &
696                     depth, lat, N,                           &
697                     optT, optP, optB, optK1K2, optKf, optGAS)
698
699  !   Purpose:
700  !     Compute thermodynamic constants
701  !     FROM: temperature, salinity, and pressure (1D arrays)
702
703  !     INPUT variables:
704  !     ================
705  !     Patm    = atmospheric pressure [atm]
706  !     depth   = depth [m]     (with optP='m', i.e., for a z-coordinate model vertical grid is depth, not pressure)
707  !             = pressure [db] (with optP='db')
708  !     lat     = latitude [degrees] (needed to convert depth to pressure, i.e., when optP='m')
709  !             = dummy array (unused when optP='db')
710  !     temp    = potential temperature [degrees C] (with optT='Tpot', i.e., models carry tempot, not temp)
711  !             = in situ   temperature [degrees C] (with optT='Tinsitu', e.g., for data)
712  !     sal     = salinity in [psu]
713  !     ---------
714  !     optT: choose in situ vs. potential temperature as input
715  !     ---------
716  !     NOTE: Carbonate chem calculations require IN-SITU temperature (not potential Temperature)
717  !       -> 'Tpot' means input is pot. Temperature (in situ Temp "tempis" is computed)
718  !       -> 'Tinsitu' means input is already in-situ Temperature, not pot. Temp ("tempis" not computed)
719  !     ---------
720  !     optP: choose depth (m) vs pressure (db) as input
721  !     ---------
722  !       -> 'm'  means "depth" input is in "m" (thus in situ Pressure "p" [db] is computed)
723  !       -> 'db' means "depth" input is already in situ pressure [db], not m (p = depth)
724  !     ---------
725  !     optB:
726  !     ---------
727  !       -> 'u74' means use classic formulation of Uppström (1974) for total Boron
728  !       -> 'l10' means use newer   formulation of Lee et al. (2010) for total Boron
729  !     ---------
730  !     optK1K2:
731  !     ---------
732  !       -> 'l'   means use Lueker et al. (2000) formulations for K1 & K2 (recommended by Dickson et al. 2007)
733  !                **** BUT this should only be used when 2 < T < 35 and 19 < S < 43
734  !       -> 'm10' means use Millero (2010) formulation for K1 & K2 (see Dickson et al., 2007)
735  !                **** Valid for 0 < T < 50°C and 1 < S < 50 psu
736  !       -> 'w14' means use Waters (2014) formulation for K1 & K2 (see Dickson et al., 2007)
737  !                **** Valid for 0 < T < 50°C and 1 < S < 50 psu
738  !     -----------
739  !     optKf:
740  !     ----------
741  !       -> 'pf' means use Perez & Fraga (1987) formulation for Kf (recommended by Dickson et al., 2007)
742  !               **** BUT Valid for  9 < T < 33°C and 10 < S < 40.
743  !       -> 'dg' means use Dickson & Riley (1979) formulation for Kf (recommended by Dickson & Goyet, 1994)
744  !     -----------
745  !     optGAS: choose in situ vs. potential fCO2 and pCO2
746  !     ---------
747  !       PRESSURE corrections for K0 and the fugacity coefficient (Cf)
748  !       -> 'Pzero'   = 'zero order' fCO2 and pCO2 (typical approach, which is flawed)
749  !                      considers in situ T & only atm pressure (hydrostatic=0)
750  !       -> 'Ppot'    = 'potential' fCO2 and pCO2 (water parcel brought adiabatically to the surface)
751  !                      considers potential T & only atm pressure (hydrostatic press = 0)
752  !       -> 'Pinsitu' = 'in situ' fCO2 and pCO2 (accounts for huge effects of pressure)
753  !                      considers in situ T & total pressure (atm + hydrostatic)
754  !     ---------
755
756  !     OUTPUT variables:
757  !     =================
758  !     K0, K1, K2, Kb, Kw, Ks, Kf, Kspc, Kspa, K1p, K2p, K3p, Ksi
759  !     St, Ft, Bt
760
761  USE mocsy_singledouble
762  USE yomhook, ONLY: lhook, dr_hook
763  USE parkind1, ONLY: jprb, jpim
764
765  IMPLICIT NONE
766
767! Input variables
768  !>     number of records
769  INTEGER, INTENT(in) :: N
770  !> in <b>situ temperature</b> (when optT='Tinsitu', typical data)
771  !! OR <b>potential temperature</b> (when optT='Tpot', typical models) [degree C]
772  REAL(kind=wp), INTENT(in),    DIMENSION(N) :: temp
773  !> depth in <b>meters</b> (when optP='m') or <b>decibars</b> (when optP='db')
774  REAL(kind=wp), INTENT(in),    DIMENSION(N) :: depth
775  !> latitude <b>[degrees north]</b>
776  REAL(kind=wp), INTENT(in),    DIMENSION(N) :: lat
777  !> salinity <b>[psu]</b>
778  REAL(kind=wp), INTENT(in), DIMENSION(N) :: sal
779!f2py optional , depend(sal) :: n=len(sal)
780
781  !> atmospheric pressure <b>[atm]</b>
782  REAL(kind=wp), INTENT(in), DIMENSION(N) :: Patm
783
784  !> for temp input, choose \b 'Tinsitu' for in situ Temp or
785  !! \b 'Tpot' for potential temperature (in situ Temp is computed, needed for models)
786  CHARACTER(7), INTENT(in) :: optT
787  !> for depth input, choose \b "db" for decibars (in situ pressure) or \b "m" for meters (pressure is computed, needed for models)
788  CHARACTER(2), INTENT(in) :: optP
789  !> for total boron, choose either \b 'u74' (Uppstrom, 1974) or \b 'l10' (Lee et al., 2010).
790  !! The 'l10' formulation is based on 139 measurements (instead of 20),
791  !! uses a more accurate method, and
792  !! generally increases total boron in seawater by 4%
793!f2py character*3 optional, intent(in) :: optB='l10'
794  CHARACTER(3), OPTIONAL, INTENT(in) :: optB
795  !> for Kf, choose either \b 'pf' (Perez & Fraga, 1987) or \b 'dg' (Dickson & Riley, 1979)
796!f2py character*2 optional, intent(in) :: optKf='pf'
797  CHARACTER(2), OPTIONAL, INTENT(in) :: optKf
798  !> for K1,K2 choose either \b 'l' (Lueker et al., 2000) or \b 'm10' (Millero, 2010) or \b 'w14' (Waters et al., 2014)
799!f2py character*3 optional, intent(in) :: optK1K2='l'
800  CHARACTER(3), OPTIONAL, INTENT(in) :: optK1K2
801  !> for K0,fugacity coefficient choose either \b 'Ppot' (no pressure correction) or \b 'Pinsitu' (with pressure correction)
802  !! 'Ppot'    - for 'potential' fCO2 and pCO2 (water parcel brought adiabatically to the surface)
803  !! 'Pinsitu' - for 'in situ' values of fCO2 and pCO2, accounting for pressure on K0 and Cf
804  !! with 'Pinsitu' the fCO2 and pCO2 will be many times higher in the deep ocean
805!f2py character*7 optional, intent(in) :: optGAS='Pinsitu'
806  CHARACTER(7), OPTIONAL, INTENT(in) :: optGAS
807
808! Ouput variables
809  !> solubility of CO2 in seawater (Weiss, 1974), also known as K0
810  REAL(kind=wp), INTENT(out), DIMENSION(N) :: K0
811  !> K1 for the dissociation of carbonic acid from Lueker et al. (2000) or Millero (2010), depending on optK1K2
812  REAL(kind=wp), INTENT(out), DIMENSION(N) :: K1
813  !> K2 for the dissociation of carbonic acid from Lueker et al. (2000) or Millero (2010), depending on optK1K2
814  REAL(kind=wp), INTENT(out), DIMENSION(N) :: K2
815  !> equilibrium constant for dissociation of boric acid
816  REAL(kind=wp), INTENT(out), DIMENSION(N) :: Kb
817  !> equilibrium constant for the dissociation of water (Millero, 1995)
818  REAL(kind=wp), INTENT(out), DIMENSION(N) :: Kw
819  !> equilibrium constant for the dissociation of bisulfate (Dickson, 1990)
820  REAL(kind=wp), INTENT(out), DIMENSION(N) :: Ks
821  !> equilibrium constant for the dissociation of hydrogen fluoride
822  !! either from Dickson and Riley (1979) or from Perez and Fraga (1987), depending on optKf
823  REAL(kind=wp), INTENT(out), DIMENSION(N) :: Kf
824  !> solubility product for calcite (Mucci, 1983)
825  REAL(kind=wp), INTENT(out), DIMENSION(N) :: Kspc
826  !> solubility product for aragonite (Mucci, 1983)
827  REAL(kind=wp), INTENT(out), DIMENSION(N) :: Kspa
828  !> 1st dissociation constant for phosphoric acid (Millero, 1995)
829  REAL(kind=wp), INTENT(out), DIMENSION(N) :: K1p
830  !> 2nd dissociation constant for phosphoric acid (Millero, 1995)
831  REAL(kind=wp), INTENT(out), DIMENSION(N) :: K2p
832  !> 3rd dissociation constant for phosphoric acid (Millero, 1995)
833  REAL(kind=wp), INTENT(out), DIMENSION(N) :: K3p
834  !> equilibrium constant for the dissociation of silicic acid (Millero, 1995)
835  REAL(kind=wp), INTENT(out), DIMENSION(N) :: Ksi
836  !> total sulfate (Morris & Riley, 1966)
837  REAL(kind=wp), INTENT(out), DIMENSION(N) :: St
838  !> total fluoride  (Riley, 1965)
839  REAL(kind=wp), INTENT(out), DIMENSION(N) :: Ft
840  !> total boron
841  !! from either Uppstrom (1974) or Lee et al. (2010), depending on optB
842  REAL(kind=wp), INTENT(out), DIMENSION(N) :: Bt
843
844! Local variables
845  REAL(kind=wp) :: ssal
846  REAL(kind=wp) :: p
847  REAL(kind=wp) :: tempot, tempis68, tempot68
848  REAL(kind=wp) :: tempis
849  REAL(kind=wp) :: is, invtk, dlogtk, is2, s2, sqrtis
850  REAL(kind=wp) :: Ks_0p, Kf_0p
851  REAL(kind=wp) :: total2free, free2SWS, total2SWS, SWS2total
852  REAL(kind=wp) :: total2free_0p, free2SWS_0p, total2SWS_0p
853! REAL(kind=wp) :: free2SWS, free2SWS_0p
854
855  REAL(kind=wp) :: dtempot, dtempot68
856  REAL(kind=wp) :: R
857
858  REAL(kind=wp) :: pK1o, ma1, mb1, mc1, pK1
859  REAL(kind=wp) :: pK2o, ma2, mb2, mc2, pK2
860
861  REAL(kind=wp), DIMENSION(12) :: a0, a1, a2, b0, b1, b2
862  REAL(kind=wp), DIMENSION(12) :: deltav, deltak, lnkpok0
863  REAL(kind=wp) :: tmp, nK0we74
864
865  INTEGER :: i, icount, ipc
866
867  REAL(kind=wp) :: t, tk, tk0, prb
868  REAL(kind=wp) :: s, sqrts, s15, scl
869
870  REAL(kind=wp) :: Phydro_atm, Patmd, Ptot, Rgas_atm, vbarCO2
871
872! Arrays to pass optional arguments into or use defaults (Dickson et al., 2007)
873  CHARACTER(3) :: opB
874  CHARACTER(2) :: opKf
875  CHARACTER(3) :: opK1K2
876  CHARACTER(7) :: opGAS
877
878  ! CONSTANTS
879  ! =========
880  ! Constants in formulation for Pressure effect on K's (Millero, 95)
881  ! with corrected coefficients for Kb, Kw, Ksi, etc.
882
883  ! index: 1) K1 , 2) K2, 3) Kb, 4) Kw, 5) Ks, 6) Kf, 7) Kspc, 8) Kspa,
884  !            9) K1P, 10) K2P, 11) K3P, 12) Ksi
885
886  DATA a0 /-25.5_wp, -15.82_wp, -29.48_wp, -20.02_wp, &
887          -18.03_wp,  -9.78_wp, -48.76_wp, -45.96_wp, &
888          -14.51_wp, -23.12_wp, -26.57_wp, -29.48_wp/
889  DATA a1 /0.1271_wp, -0.0219_wp, 0.1622_wp, 0.1119_wp, &
890           0.0466_wp, -0.0090_wp, 0.5304_wp, 0.5304_wp, &
891           0.1211_wp, 0.1758_wp, 0.2020_wp, 0.1622_wp/
892  DATA a2 /     0.0_wp,       0.0_wp, -2.608e-3_wp, -1.409e-3_wp, &
893           0.316e-3_wp, -0.942e-3_wp,  0.0_wp,       0.0_wp, &
894          -0.321e-3_wp, -2.647e-3_wp, -3.042e-3_wp, -2.6080e-3_wp/
895  DATA b0 /-3.08e-3_wp, 1.13e-3_wp,  -2.84e-3_wp,   -5.13e-3_wp, &
896           -4.53e-3_wp, -3.91e-3_wp, -11.76e-3_wp, -11.76e-3_wp, &
897           -2.67e-3_wp, -5.15e-3_wp,  -4.08e-3_wp,  -2.84e-3_wp/
898  DATA b1 /0.0877e-3_wp, -0.1475e-3_wp, 0.0_wp,       0.0794e-3_wp, &
899           0.09e-3_wp,    0.054e-3_wp,  0.3692e-3_wp, 0.3692e-3_wp, &
900           0.0427e-3_wp,  0.09e-3_wp,   0.0714e-3_wp, 0.0_wp/
901  DATA b2 /12*0.0_wp/
902  INTEGER(KIND=jpim), PARAMETER :: zhook_in = 0
903  INTEGER(KIND=jpim), PARAMETER :: zhook_out = 1
904  REAL(KIND=jprb)               :: zhook_handle
905
906  CHARACTER(LEN=*), PARAMETER :: RoutineName='CONSTANTS'
907
908  IF (lhook) CALL dr_hook(RoutineName,zhook_in,zhook_handle)
909
910
911! Set defaults for optional arguments (in Fortran 90)
912! Note:  Optional arguments with f2py (python) are set above with
913!        the !f2py statements that precede each type declaraion
914  IF (PRESENT(optB)) THEN
915    opB = optB
916  ELSE
917    opB = 'l10'
918  ENDIF
919  IF (PRESENT(optKf)) THEN
920    opKf = optKf
921  ELSE
922    opKf = 'pf'
923  ENDIF
924  IF (PRESENT(optK1K2)) THEN
925    opK1K2 = optK1K2
926  ELSE
927    opK1K2 = 'l'
928  ENDIF
929  IF (PRESENT(optGAS)) THEN
930    opGAS = optGAS
931  ELSE
932    opGAS = 'Pinsitu'
933  ENDIF
934
935  R = 83.14472_wp
936
937  icount = 0
938  DO i = 1, N
939     icount = icount + 1
940!    ===============================================================
941!    Convert model depth -> press; convert model Theta -> T in situ
942!    ===============================================================
943!    * Model temperature tracer is usually "potential temperature"
944!    * Model vertical grid is usually in meters
945!    BUT carbonate chem routines require pressure & in-situ T
946!    Thus before computing chemistry, if appropriate,
947!    convert these 2 model vars (input to this routine)
948!     - depth [m] => convert to pressure [db]
949!     - potential temperature (C) => convert to in-situ T (C)
950!    -------------------------------------------------------
951!    1)  Compute pressure [db] from depth [m] and latitude [degrees] (if input is m, for models)
952     IF (trim(optP) == 'm' ) THEN
953!       Compute pressure [db] from depth [m] and latitude [degrees]
954        p = p80(depth(i), lat(i))
955     ELSEIF (trim(optP) == 'db' ) THEN
956!       In this case (where optP = 'db'), p is input & output (no depth->pressure conversion needed)
957        p = depth(i)
958     ELSE
959        PRINT *,"optP must be 'm' or 'db'"
960        STOP
961     ENDIF
962
963!    2) Convert potential T to in-situ T (if input is Tpot, i.e. case for models):
964     IF (trim(optT) == 'Tpot' .OR. trim(optT) == 'tpot') THEN
965        tempot = temp(i)
966!       This is the case for most models and some data
967!       a) Convert the pot. temp on today's "ITS 90" scale to older IPTS 68 scale
968!          (see Dickson et al., Best Practices Guide, 2007, Chap. 5, p. 7, including footnote)
969        tempot68 = (tempot - 0.0002) / 0.99975
970!       b) Compute "in-situ Temperature" from "Potential Temperature" (both on IPTS 68)
971        tempis68 = sw_temp(sal(i), tempot68, p, 0.0_wp )
972!       c) Convert the in-situ temp on older IPTS 68 scale to modern scale (ITS 90)
973        tempis = 0.99975*tempis68 + 0.0002
974!       Note: parts (a) and (c) above are tiny corrections;
975!             part  (b) is a big correction for deep waters (but zero at surface)
976     ELSEIF (trim(optT) == 'Tinsitu' .OR. trim(optT) == 'tinsitu') THEN
977!       When optT = 'Tinsitu', tempis is input & output (no tempot needed)
978        tempis    = temp(i)
979        tempis68  = (temp(i) - 0.0002) / 0.99975
980!       dtempot68 = sw_ptmp(DBLE(sal(i)), DBLE(tempis68), DBLE(p), 0.0_wp)
981        dtempot68 = sw_ptmp(sal(i), tempis68, p, 0.0_wp)
982        dtempot   = 0.99975*dtempot68 + 0.0002
983     ELSE
984        PRINT *,"optT must be either 'Tpot' or 'Tinsitu'"
985        PRINT *,"you specified optT =", trim(optT) 
986        STOP
987     ENDIF
988
989!    Compute constants:
990     IF (temp(i) >= -5. .AND. temp(i) < 1.0e+2) THEN
991!       Test to indicate if any of input variables are unreasonable
992        IF (      sal(i) < 0.  .OR.  sal(i) > 1e+3) THEN
993           PRINT *, 'i, icount, temp, sal =', i, icount, temp(i), sal(i)
994        ENDIF
995!       Zero out negative salinity (prev case for OCMIP2 model w/ slightly negative S in some coastal cells)
996        IF (sal(i) < 0.0) THEN
997           ssal = 0.0
998        ELSE
999           ssal = sal(i)
1000        ENDIF
1001
1002!       Absolute temperature (Kelvin) and related values
1003        t = DBLE(tempis)
1004        tk = 273.15d0 + t
1005        invtk=1.0d0/tk
1006        dlogtk=LOG(tk)
1007
1008!       Atmospheric pressure
1009        Patmd = DBLE(Patm(i))
1010
1011!       Hydrostatic pressure (prb is in bars)
1012        prb = DBLE(p) / 10.0d0
1013
1014!       Salinity and simply related values
1015        s = DBLE(ssal)
1016        s2=s*s
1017        sqrts=SQRT(s)
1018        s15=s**1.5d0
1019        scl=s/1.80655d0
1020
1021!       Ionic strength:
1022        is = 19.924d0*s/(1000.0d0 - 1.005d0*s)
1023        is2 = is*is
1024        sqrtis = SQRT(is)
1025
1026!       Total concentrations for sulfate, fluoride, and boron
1027
1028!       Sulfate: Morris & Riley (1966)
1029        St(i) = 0.14d0 * scl/96.062d0
1030
1031!       Fluoride:  Riley (1965)
1032        Ft(i) = 0.000067d0 * scl/18.9984d0
1033
1034!       Boron:
1035        IF (trim(opB) == 'l10') THEN
1036!          New formulation from Lee et al (2010)
1037           Bt(i) = 0.0002414d0 * scl/10.811d0
1038        ELSEIF (trim(opB) == 'u74') THEN
1039!          Classic formulation from Uppström (1974)
1040           Bt(i) = 0.000232d0  * scl/10.811d0
1041        ELSE
1042           PRINT *,"optB must be 'l10' or 'u74'"
1043           STOP
1044        ENDIF
1045
1046!       K0 (K Henry)
1047!       CO2(g) <-> CO2(aq.)
1048!       K0  = [CO2]/ fCO2
1049!       Weiss (1974)   [mol/kg/atm]
1050        IF     (trim(opGAS) == 'Pzero'   .OR. trim(opGAS) == 'pzero') THEN
1051           tk0 = tk                   !in situ temperature (K) for K0 calculation
1052           Ptot = Patmd               !total pressure (in atm) = atmospheric pressure ONLY
1053        ELSEIF (trim(opGAS) == 'Ppot'    .OR. trim(opGAS) == 'ppot') THEN
1054           tk0 = dtempot + 273.15d0   !potential temperature (K) for K0 calculation as needed for potential fCO2 & pCO2
1055           Ptot = Patmd               !total pressure (in atm) = atmospheric pressure ONLY
1056        ELSEIF (trim(opGAS) == 'Pinsitu' .OR. trim(opGAS) == 'pinsitu') THEN
1057           tk0 = tk                     !in situ temperature (K) for K0 calculation
1058           Phydro_atm = prb / 1.01325d0 !convert hydrostatic pressure from bar to atm (1.01325 bar / atm)
1059           Ptot = Patmd + Phydro_atm    !total pressure (in atm) = atmospheric pressure + hydrostatic pressure
1060        ELSE
1061           PRINT *, "optGAS must be 'Pzero', 'Ppot', or 'Pinsitu'"
1062           STOP
1063        ENDIF
1064        tmp = 9345.17d0/tk0 - 60.2409d0 + 23.3585d0 * LOG(tk0/100.0d0)
1065        nK0we74 = tmp + s*(0.023517d0 - 0.00023656d0*tk0 + 0.0047036e-4_wp*tk0*tk0)
1066        K0(i) = EXP(nK0we74)
1067
1068!       K1 = [H][HCO3]/[H2CO3]
1069!       K2 = [H][CO3]/[HCO3]
1070        IF (trim(opK1K2) == 'l') THEN
1071!         Mehrbach et al. (1973) refit, by Lueker et al. (2000) (total pH scale)
1072          K1(i) = 10.0d0**(-1.0d0*(3633.86d0*invtk - 61.2172d0 + 9.6777d0*dlogtk  &
1073                  - 0.011555d0*s + 0.0001152d0*s2))
1074          K2(i) = 10.0d0**(-1*(471.78d0*invtk + 25.9290d0 - 3.16967d0*dlogtk      &
1075                  - 0.01781d0*s + 0.0001122d0*s2))
1076        ELSEIF (trim(opK1K2) == 'm10') THEN
1077!         Millero (2010, Mar. Fresh Wat. Res.) (seawater pH scale)
1078          pK1o = 6320.813d0*invtk + 19.568224d0*dlogtk -126.34048d0
1079          ma1 = 13.4038d0*sqrts + 0.03206d0*s - (5.242e-5)*s2
1080          mb1 = -530.659d0*sqrts - 5.8210d0*s
1081          mc1 = -2.0664d0*sqrts
1082          pK1 = pK1o + ma1 + mb1*invtk + mc1*dlogtk
1083          K1(i) = 10.0d0**(-pK1) 
1084
1085          pK2o = 5143.692d0*invtk + 14.613358d0*dlogtk -90.18333d0
1086          ma2 = 21.3728d0*sqrts + 0.1218d0*s - (3.688e-4)*s2
1087          mb2 = -788.289d0*sqrts - 19.189d0*s
1088          mc2 = -3.374d0*sqrts
1089          pK2 = pK2o + ma2 + mb2*invtk + mc2*dlogtk
1090          K2(i) = 10.0d0**(-pK2)
1091        ELSEIF (trim(opK1K2) == 'w14') THEN
1092!         Waters, Millero, Woosley (Mar. Chem., 165, 66-67, 2014) (seawater scale)
1093          pK1o = 6320.813d0*invtk + 19.568224d0*dlogtk -126.34048d0
1094          ma1 = 13.409160d0*sqrts + 0.031646d0*s - (5.1895e-5)*s2
1095          mb1 = -531.3642d0*sqrts - 5.713d0*s
1096          mc1 = -2.0669166d0*sqrts
1097          pK1 = pK1o + ma1 + mb1*invtk + mc1*dlogtk
1098          K1(i) = 10.0d0**(-pK1) 
1099
1100          pK2o = 5143.692d0*invtk + 14.613358d0*dlogtk -90.18333d0
1101          ma2 = 21.225890d0*sqrts + 0.12450870d0*s - (3.7243e-4_r8)*s2
1102          mb2 = -779.3444d0*sqrts - 19.91739d0*s
1103          mc2 = -3.3534679d0*sqrts
1104          pK2 = pK2o + ma2 + mb2*invtk + mc2*dlogtk
1105          K2(i) = 10.0d0**(-pK2)
1106        ELSE
1107           PRINT *, "optK1K2 must be either 'l' or 'm10', or 'w14'"
1108           STOP
1109        ENDIF
1110
1111!       Kb = [H][BO2]/[HBO2]
1112!       (total scale)
1113!       Millero p.669 (1995) using data from Dickson (1990)
1114        Kb(i) = EXP((-8966.90d0 - 2890.53d0*sqrts - 77.942d0*s +  &
1115                1.728d0*s15 - 0.0996d0*s2)*invtk +              &
1116                (148.0248d0 + 137.1942d0*sqrts + 1.62142d0*s) +   &
1117                (-24.4344d0 - 25.085d0*sqrts - 0.2474d0*s) *      &
1118                dlogtk + 0.053105d0*sqrts*tk)
1119
1120!       K1p = [H][H2PO4]/[H3PO4]
1121!       (seawater scale)
1122!       DOE(1994) eq 7.2.20 with footnote using data from Millero (1974)
1123!       Millero (1995), p.670, eq. 65
1124!       Use Millero equation's 115.540 constant instead of 115.525 (Dickson et al., 2007).
1125!       The latter is only an crude approximation to convert to Total scale (by subtracting 0.015)
1126!       And we want to stay on the SWS scale anyway for the pressure correction later.
1127        K1p(i) = EXP(-4576.752d0*invtk + 115.540d0 - 18.453d0*dlogtk +  &
1128                 (-106.736d0*invtk + 0.69171d0) * sqrts +             &
1129                 (-0.65643d0*invtk - 0.01844d0) * s)
1130
1131!       K2p = [H][HPO4]/[H2PO4]
1132!       (seawater scale)
1133!       DOE(1994) eq 7.2.23 with footnote using data from Millero (1974))
1134!       Millero (1995), p.670, eq. 66
1135!       Use Millero equation's 172.1033 constant instead of 172.0833 (Dickson et al., 2007).
1136!       The latter is only an crude approximation to convert to Total scale (by subtracting 0.015)
1137!       And we want to stay on the SWS scale anyway for the pressure correction later.
1138        K2p(i) = EXP(-8814.715d0*invtk + 172.1033d0 - 27.927d0*dlogtk +  &
1139                 (-160.340d0*invtk + 1.3566d0)*sqrts +                 &
1140                 (0.37335d0*invtk - 0.05778d0)*s)
1141
1142!       K3p = [H][PO4]/[HPO4]
1143!       (seawater scale)
1144!       DOE(1994) eq 7.2.26 with footnote using data from Millero (1974)
1145!       Millero (1995), p.670, eq. 67
1146!       Use Millero equation's 18.126 constant instead of 18.141 (Dickson et al., 2007).
1147!       The latter is only an crude approximation to convert to Total scale (by subtracting 0.015)
1148!       And we want to stay on the SWS scale anyway for the pressure correction later.
1149        K3p(i) = EXP(-3070.75d0*invtk - 18.126d0 +            &
1150                 (17.27039d0*invtk + 2.81197d0) *             &
1151                 sqrts + (-44.99486d0*invtk - 0.09984d0) * s)
1152
1153!       Ksi = [H][SiO(OH)3]/[Si(OH)4]
1154!       (seawater scale)
1155!       Millero (1995), p.671, eq. 72
1156!       Use Millero equation's 117.400 constant instead of 117.385 (Dickson et al., 2007).
1157!       The latter is only an crude approximation to convert to Total scale (by subtracting 0.015)
1158!       And we want to stay on the SWS scale anyway for the pressure correction later.
1159        Ksi(i) = EXP(-8904.2d0*invtk  + 117.400d0 - 19.334d0*dlogtk +  &
1160                 (-458.79d0*invtk + 3.5913d0) * sqrtis +             &
1161                 (188.74d0*invtk - 1.5998d0) * is +                  &
1162                 (-12.1652d0*invtk + 0.07871d0) * is2 +              &
1163                 LOG(1.0 - 0.001005d0*s))
1164
1165!       Kw = [H][OH]
1166!       (seawater scale)
1167!       Millero (1995) p.670, eq. 63 from composite data
1168!       Use Millero equation's 148.9802 constant instead of 148.9652 (Dickson et al., 2007).
1169!       The latter is only an crude approximation to convert to Total scale (by subtracting 0.015)
1170!       And we want to stay on the SWS scale anyway for the pressure correction later.
1171        Kw(i) = EXP(-13847.26d0*invtk + 148.9802d0 - 23.6521d0*dlogtk +  &
1172               (118.67d0*invtk - 5.977d0 + 1.0495d0 * dlogtk) *          &
1173               sqrts - 0.01615d0 * s)
1174
1175!       Ks = [H][SO4]/[HSO4]
1176!       (free scale)
1177!       Dickson (1990, J. chem. Thermodynamics 22, 113)
1178        Ks_0p = EXP(-4276.1d0*invtk + 141.328d0 - 23.093d0*dlogtk          &
1179                + (-13856.d0*invtk + 324.57d0 - 47.986d0*dlogtk) * sqrtis  &
1180                + (35474.d0*invtk - 771.54 + 114.723d0*dlogtk) * is      &
1181                - 2698.d0*invtk*is**1.5 + 1776.d0*invtk*is2              &
1182                + LOG(1.0d0 - 0.001005d0*s))
1183
1184!       Kf = [H][F]/[HF]
1185!       (total scale)
1186        IF (trim(opKf) == 'dg') THEN
1187!          Dickson and Riley (1979) -- change pH scale to total (following Dickson & Goyet, 1994)
1188           Kf_0p = EXP(1590.2d0*invtk - 12.641d0 + 1.525d0*sqrtis +  &
1189                   LOG(1.0d0 - 0.001005d0*s) +                     &
1190                   LOG(1.0d0 + St(i)/Ks_0p))
1191        ELSEIF (trim(opKf) == 'pf') THEN
1192!          Perez and Fraga (1987) - Already on Total scale (no need for last line above)
1193!          Formulation as given in Dickson et al. (2007)
1194           Kf_0p = EXP(874.d0*invtk - 9.68d0 + 0.111d0*sqrts)
1195        ELSE
1196           PRINT *, "optKf must be either 'dg' or 'pf'"
1197           STOP
1198        ENDIF
1199
1200!       Kspc (calcite) - apparent solubility product of calcite
1201!       (no scale)
1202!       Kspc = [Ca2+] [CO32-] when soln is in equilibrium w/ calcite
1203!       Mucci 1983 mol/kg-soln
1204        Kspc(i) = 10d0**(-171.9065d0 - 0.077993d0*tk + 2839.319d0/tk    &
1205                 + 71.595d0*LOG10(tk)                             &
1206                 + (-0.77712d0 + 0.0028426d0*tk + 178.34d0/tk)*sqrts  &
1207                 -0.07711d0*s + 0.0041249d0*s15 )
1208
1209
1210!       Kspa (aragonite) - apparent solubility product of aragonite
1211!       (no scale)
1212!       Kspa = [Ca2+] [CO32-] when soln is in equilibrium w/ aragonite
1213!       Mucci 1983 mol/kg-soln
1214        Kspa(i) = 10.d0**(-171.945d0 - 0.077993d0*tk + 2903.293d0/tk &
1215             +71.595d0*LOG10(tk) &
1216             +(-0.068393d0 + 0.0017276d0*tk + 88.135d0/tk)*sqrts &
1217             -0.10018d0*s + 0.0059415d0*s15 )
1218
1219!       Pressure effect on K0 based on Weiss (1974, equation 5)
1220        Rgas_atm = 82.05736_wp      ! (cm3 * atm) / (mol * K)  CODATA (2006)
1221        vbarCO2 = 32.3_wp           ! partial molal volume (cm3 / mol) from Weiss (1974, Appendix, paragraph 3)
1222        K0(i) = K0(i) * exp( ((1-Ptot)*vbarCO2)/(Rgas_atm*tk0) )   ! Weiss (1974, equation 5)
1223
1224!       Pressure effect on all other K's (based on Millero, (1995)
1225!           index: K1(1), K2(2), Kb(3), Kw(4), Ks(5), Kf(6), Kspc(7), Kspa(8),
1226!                  K1p(9), K2p(10), K3p(11), Ksi(12)
1227        DO ipc = 1, 12
1228           deltav(ipc)  =  a0(ipc) + a1(ipc) *t + a2(ipc) *t*t
1229           deltak(ipc)   = (b0(ipc)  + b1(ipc) *t + b2(ipc) *t*t)
1230           lnkpok0(ipc)  = (-(deltav(ipc)) &
1231                +(0.5d0*deltak(ipc) * prb) &
1232                )                         * prb/(R*tk)
1233        END DO
1234
1235!       Pressure correction on Ks (Free scale)
1236        Ks(i) = Ks_0p*EXP(lnkpok0(5))
1237!       Conversion factor total -> free scale
1238        total2free     = 1.d0/(1.d0 + St(i)/Ks(i))   ! Kfree = Ktotal*total2free
1239!       Conversion factor total -> free scale at pressure zero
1240        total2free_0p  = 1.d0/(1.d0 + St(i)/Ks_0p)   ! Kfree = Ktotal*total2free
1241
1242!       Pressure correction on Kf
1243!       Kf must be on FREE scale before correction
1244        Kf_0p = Kf_0p * total2free_0p   !Convert from Total to Free scale (pressure 0)
1245        Kf(i) = Kf_0p * EXP(lnkpok0(6)) !Pressure correction (on Free scale)
1246        Kf(i) = Kf(i)/total2free        !Convert back from Free to Total scale
1247
1248!       Convert between seawater and total hydrogen (pH) scales
1249        free2SWS  = 1.d0 + St(i)/Ks(i) + Ft(i)/(Kf(i)*total2free)  ! using Kf on free scale
1250        total2SWS = total2free * free2SWS                          ! KSWS = Ktotal*total2SWS
1251        SWS2total = 1.d0 / total2SWS
1252!       Conversion at pressure zero
1253        free2SWS_0p  = 1.d0 + St(i)/Ks_0p + Ft(i)/(Kf_0p)  ! using Kf on free scale
1254        total2SWS_0p = total2free_0p * free2SWS_0p         ! KSWS = Ktotal*total2SWS
1255
1256!       Convert from Total to Seawater scale before pressure correction
1257!       Must change to SEAWATER scale: K1, K2, Kb
1258        IF (trim(optK1K2) == 'l') THEN
1259          K1(i)  = K1(i)*total2SWS_0p
1260          K2(i)  = K2(i)*total2SWS_0p
1261          !This conversion is unnecessary for the K1,K2 from Millero (2010),
1262          !since we use here the formulation already on the seawater scale
1263        ENDIF
1264        Kb(i)  = Kb(i)*total2SWS_0p
1265
1266!       Already on SEAWATER scale: K1p, K2p, K3p, Kb, Ksi, Kw
1267
1268!       Other contants (keep on another scale):
1269!          - K0         (independent of pH scale, already pressure corrected)
1270!          - Ks         (already on Free scale;   already pressure corrected)
1271!          - Kf         (already on Total scale;  already pressure corrected)
1272!          - Kspc, Kspa (independent of pH scale; pressure-corrected below)
1273
1274!       Perform actual pressure correction (on seawater scale)
1275        K1(i)   = K1(i)*EXP(lnkpok0(1))
1276        K2(i)   = K2(i)*EXP(lnkpok0(2))
1277        Kb(i)   = Kb(i)*EXP(lnkpok0(3))
1278        Kw(i)   = Kw(i)*EXP(lnkpok0(4))
1279        Kspc(i) = Kspc(i)*EXP(lnkpok0(7))
1280        Kspa(i) = Kspa(i)*EXP(lnkpok0(8))
1281        K1p(i)  = K1p(i)*EXP(lnkpok0(9))
1282        K2p(i)  = K2p(i)*EXP(lnkpok0(10))
1283        K3p(i)  = K3p(i)*EXP(lnkpok0(11))
1284        Ksi(i)  = Ksi(i)*EXP(lnkpok0(12))
1285
1286!       Convert back to original total scale:
1287        K1(i)  = K1(i) *SWS2total
1288        K2(i)  = K2(i) *SWS2total
1289        K1p(i) = K1p(i)*SWS2total
1290        K2p(i) = K2p(i)*SWS2total
1291        K3p(i) = K3p(i)*SWS2total
1292        Kb(i)  = Kb(i) *SWS2total
1293        Ksi(i) = Ksi(i)*SWS2total
1294        Kw(i)  = Kw(i) *SWS2total
1295
1296     ELSE
1297
1298        K0(i)   = 1.e20_wp
1299        K1(i)   = 1.e20_wp
1300        K2(i)   = 1.e20_wp
1301        Kb(i)   = 1.e20_wp
1302        Kw(i)   = 1.e20_wp
1303        Ks(i)   = 1.e20_wp
1304        Kf(i)   = 1.e20_wp
1305        Kspc(i) = 1.e20_wp
1306        Kspa(i) = 1.e20_wp
1307        K1p(i)  = 1.e20_wp
1308        K2p(i)  = 1.e20_wp
1309        K3p(i)  = 1.e20_wp
1310        Ksi(i)  = 1.e20_wp
1311        Bt(i)   = 1.e20_wp
1312        Ft(i)   = 1.e20_wp
1313        St(i)   = 1.e20_wp
1314
1315     ENDIF
1316
1317  END DO
1318
1319  IF (lhook) CALL dr_hook(RoutineName,zhook_out ,zhook_handle)
1320  RETURN
1321  IF (lhook) CALL dr_hook(RoutineName,zhook_out,zhook_handle)
1322END SUBROUTINE constants
1323
1324! ----------------------------------------------------------------------
1325!  VARSOLVER
1326! ----------------------------------------------------------------------
1327!
1328!> \file varsolver.f90
1329!! \BRIEF
1330!> Module with varsolver subroutine - solve for pH and other carbonate system variables
1331!>    Solve for pH and other carbonate system variables (with input from vars routine)
1332SUBROUTINE varsolver(ph, pco2, fco2, co2, hco3, co3, OmegaA, OmegaC,             &
1333                    temp, salt, ta, tc, pt, sit,                                 &
1334                    Bt, St, Ft,                                                  &
1335                    K0, K1, K2, Kb, Kw, Ks, Kf, Kspc, Kspa, K1p, K2p, K3p, Ksi,  & 
1336                    Patm, Phydro_bar, rhodum, optGAS                             )
1337
1338  !   Purpose: Solve for pH and other carbonate system variables (with input from vars routine)
1339
1340  !     INPUT variables:
1341  !     ================
1342  !     temp    = in situ temperature [degrees C]
1343  !     ta      = total alkalinity                     in [eq/m^3] or [eq/kg]   based on optCON in calling routine (vars)
1344  !     tc      = dissolved inorganic carbon           in [mol/m^3] or [mol/kg] based on optCON in calling routine (vars)
1345  !     pt      = total dissolved inorganic phosphorus in [mol/m^3] or [mol/kg] based on optCON in calling routine (vars)
1346  !     sit     = total dissolved inorganic silicon    in [mol/m^3] or [mol/kg] based on optCON in calling routine (vars)
1347  !     Bt      = total dissolved inorganic boron      computed in calling routine (vars)
1348  !     St      = total dissolved inorganic sulfur     computed in calling routine (vars)
1349  !     Ft      = total dissolved inorganic fluorine   computed in calling routine (vars)
1350  !     K's     = K0, K1, K2, Kb, Kw, Ks, Kf, Kspc, Kspa, K1p, K2p, K3p, Ksi
1351  !     Patm    = atmospheric pressure [atm]
1352  !     Phydro_bar = hydrostatic pressure [bar]
1353  !     rhodum  = density factor as computed in calling routine  (vars)
1354  !     -----------
1355  !     optGAS: choose in situ vs. potential fCO2 and pCO2 (default optGAS = 'Pinsitu')
1356  !     ---------
1357  !       PRESSURE & T corrections for K0 and the fugacity coefficient (Cf)
1358  !       -> 'Pzero'   = 'zero order' fCO2 and pCO2 (typical approach, which is flawed)
1359  !                      considers in situ T & only atm pressure (hydrostatic=0)
1360  !       -> 'Ppot'    = 'potential' fCO2 and pCO2 (water parcel brought adiabatically to the surface)
1361  !                      considers potential T & only atm pressure (hydrostatic press = 0)
1362  !       -> 'Pinsitu' = 'in situ' fCO2 and pCO2 (accounts for huge effects of pressure)
1363  !                      considers in situ T & total pressure (atm + hydrostatic)
1364  !     ---------
1365
1366  !     OUTPUT variables:
1367  !     =================
1368  !     ph   = pH on total scale
1369  !     pco2 = CO2 partial pressure (uatm)
1370  !     fco2 = CO2 fugacity (uatm)
1371  !     co2  = aqueous CO2 concentration in [mol/kg] or [mol/m^3] determined by rhodum (depends on optCON in calling routine)
1372  !     hco3 = bicarbonate (HCO3-) concentration in [mol/kg] or [mol/m^3] determined by rhodum
1373  !     co3  = carbonate (CO3--) concentration in [mol/kg] or [mol/m^3] determined by rhodum
1374  !     OmegaA = Omega for aragonite, i.e., the aragonite saturation state
1375  !     OmegaC = Omega for calcite, i.e., the   calcite saturation state
1376
1377  USE mocsy_singledouble
1378  USE mocsy_phsolvers
1379
1380  USE yomhook, ONLY: lhook, dr_hook
1381  USE parkind1, ONLY: jprb, jpim
1382
1383  IMPLICIT NONE
1384
1385! Input variables
1386  !> <b>in situ temperature</b> [degrees C]
1387  REAL(kind=wp), INTENT(in) :: temp
1388  !> <b>salinity</b> [on the practical salinity scale, dimensionless]
1389  REAL(kind=wp), INTENT(in) :: salt
1390  !> total alkalinity in <b>[eq/m^3]</b> OR in <b>[eq/kg]</b>, depending on optCON in calling routine
1391  REAL(kind=wp), INTENT(in) :: ta
1392  !> dissolved inorganic carbon in <b>[mol/m^3]</b> OR in <b>[mol/kg]</b>, depending on optCON in calling routine
1393  REAL(kind=wp), INTENT(in) :: tc
1394  !> phosphate concentration in <b>[mol/m^3]</b> OR in <b>[mol/kg]</b>, depending on optCON in calling routine
1395  REAL(kind=wp), INTENT(in) :: pt
1396  !> total dissolved inorganic silicon concentration in <b>[mol/m^3]</b> OR in <b>[mol/kg]</b>, depending on optCON in calling routine
1397  REAL(kind=wp), INTENT(in) :: sit
1398  !> total boron from either Uppstrom (1974) or Lee et al. (2010), depending on optB in calling routine
1399  REAL(kind=wp), INTENT(in) :: Bt
1400  !> total sulfate (Morris & Riley, 1966)
1401  REAL(kind=wp), INTENT(in) :: St
1402  !> total fluoride  (Riley, 1965)
1403  REAL(kind=wp), INTENT(in) :: Ft
1404  !> solubility of CO2 in seawater (Weiss, 1974), also known as K0
1405  REAL(kind=wp), INTENT(in) :: K0
1406  !> K1 for the dissociation of carbonic acid from Lueker et al. (2000) or Millero (2010), depending on optK1K2
1407  REAL(kind=wp), INTENT(in) :: K1
1408  !> K2 for the dissociation of carbonic acid from Lueker et al. (2000) or Millero (2010), depending on optK1K2
1409  REAL(kind=wp), INTENT(in) :: K2
1410  !> equilibrium constant for dissociation of boric acid
1411  REAL(kind=wp), INTENT(in) :: Kb
1412  !> equilibrium constant for the dissociation of water (Millero, 1995)
1413  REAL(kind=wp), INTENT(in) :: Kw
1414  !> equilibrium constant for the dissociation of bisulfate (Dickson, 1990)
1415  REAL(kind=wp), INTENT(in) :: Ks
1416  !> equilibrium constant for the dissociation of hydrogen fluoride
1417  !! from Dickson and Riley (1979) or Perez and Fraga (1987), depending on optKf
1418  REAL(kind=wp), INTENT(in) :: Kf
1419  !> solubility product for calcite (Mucci, 1983)
1420  REAL(kind=wp), INTENT(in) :: Kspc
1421  !> solubility product for aragonite (Mucci, 1983)
1422  REAL(kind=wp), INTENT(in) :: Kspa
1423  !> 1st dissociation constant for phosphoric acid (Millero, 1995)
1424  REAL(kind=wp), INTENT(in) :: K1p
1425  !> 2nd dissociation constant for phosphoric acid (Millero, 1995)
1426  REAL(kind=wp), INTENT(in) :: K2p
1427  !> 3rd dissociation constant for phosphoric acid (Millero, 1995)
1428  REAL(kind=wp), INTENT(in) :: K3p
1429  !> equilibrium constant for the dissociation of silicic acid (Millero, 1995)
1430  REAL(kind=wp), INTENT(in) :: Ksi
1431  !> total atmospheric pressure <b>[atm]</b>
1432  REAL(kind=wp), INTENT(in) :: Patm
1433  !> total hydrostatic pressure <b>[bar]</b>
1434  REAL(kind=wp), INTENT(in) :: Phydro_bar
1435  !> density factor as computed incalling routine  (vars)
1436  REAL(kind=wp), INTENT(in) :: rhodum
1437  !> for K0,fugacity coefficient choose either \b 'Ppot' (no pressure correction) or \b 'Pinsitu' (with pressure correction)
1438  !! 'Ppot'    - for 'potential' fCO2 and pCO2 (water parcel brought adiabatically to the surface)
1439  !! 'Pinsitu' - for 'in situ' values of fCO2 and pCO2, accounting for pressure on K0 and Cf
1440  !! with 'Pinsitu' the fCO2 and pCO2 will be many times higher in the deep ocean
1441!f2py character*7 optional, intent(in) :: optGAS='Pinsitu'
1442  CHARACTER(7), OPTIONAL, INTENT(in) :: optGAS
1443
1444! Output variables:
1445  !> pH on the <b>total scale</b>
1446  REAL(kind=wp), INTENT(out) :: ph
1447  !> CO2 partial pressure <b>[uatm]</b>
1448  REAL(kind=wp), INTENT(out) :: pco2
1449  !> CO2 fugacity <b>[uatm]</b>
1450  REAL(kind=wp), INTENT(out) :: fco2
1451  !> aqueous CO2* concentration, either in <b>[mol/m^3]</b> or <b>[mol/kg</b>] depending on choice for optCON
1452  REAL(kind=wp), INTENT(out) :: co2
1453  !> bicarbonate ion (HCO3-) concentration, either in <b>[mol/m^3]</b> or <b>[mol/kg]</b> depending on choice for optCON
1454  REAL(kind=wp), INTENT(out) :: hco3
1455  !> carbonate ion (CO3--) concentration, either in <b>[mol/m^3]</b> or <b>[mol/kg]</b> depending on choice for optCON
1456  REAL(kind=wp), INTENT(out) :: co3
1457  !> Omega for aragonite, i.e., the aragonite saturation state
1458  REAL(kind=wp), INTENT(out) :: OmegaA
1459  !> Omega for calcite, i.e., the calcite saturation state
1460  REAL(kind=wp), INTENT(out) :: OmegaC
1461
1462! Local variables
1463  REAL(kind=wp) :: Phydro_atm, Ptot
1464  REAL(kind=wp) :: Rgas_atm, B, Del, xCO2approx, xc2, fugcoeff
1465  REAL(kind=wp) :: tk, tk0
1466  real(kind=wp) :: temp68, tempot, tempot68
1467  REAL(kind=wp) :: Hinit, H
1468  REAL(kind=wp) :: HSO4, HF, HSI, HPO4
1469  REAL(kind=wp) :: ab, aw, ac
1470  REAL(kind=wp) :: cu, cb, cc
1471  REAL(kind=wp) :: Ca
1472! Array to pass optional arguments
1473  CHARACTER(7) :: opGAS
1474  INTEGER(KIND=jpim), PARAMETER :: zhook_in = 0
1475  INTEGER(KIND=jpim), PARAMETER :: zhook_out = 1
1476  REAL(KIND=jprb)               :: zhook_handle
1477
1478  CHARACTER(LEN=*), PARAMETER :: RoutineName='VARSOLVER'
1479
1480  IF (lhook) CALL dr_hook(RoutineName,zhook_in,zhook_handle)
1481
1482
1483  IF (PRESENT(optGAS)) THEN
1484    opGAS = optGAS
1485  ELSE
1486    opGAS = 'Pinsitu'
1487  ENDIF
1488
1489! Compute pH from constants and total concentrations
1490! - use SolveSAPHE v1.0.1 routines from Munhoven (2013, GMD) modified to use mocsy's Ks instead of its own
1491! 1) Compute best starting point for H+ calculation
1492  call ahini_for_at(ta, tc, Bt, K1, K2, Kb, Hinit)
1493! 2) Solve for H+ using above result as the initial H+ value
1494  H = solve_at_general(ta, tc, Bt,                                         & 
1495                       pt,     sit,                                        &
1496                       St, Ft,                                             &
1497                       K0, K1, K2, Kb, Kw, Ks, Kf, K1p, K2p, K3p, Ksi,     &
1498                       Hinit)
1499! 3) Calculate pH from from H+ concentration (mol/kg)
1500  IF (H > 0.d0) THEN
1501     pH = -1.*LOG10(H)
1502  ELSE
1503     pH = 1.e20_wp
1504  ENDIF
1505
1506! Compute carbonate Alk (Ac) by difference: from total Alk and other Alk components
1507  HSO4 = St/(1.0d0 + Ks/(H/(1.0d0 + St/Ks)))
1508  HF = 1.0d0/(1.0d0 + Kf/H)
1509  HSI = 1.0d0/(1.0d0 + H/Ksi)
1510  HPO4 = (K1p*K2p*(H + 2.*K3p) - H**3) /                &
1511  (H**3 + K1p*H**2 + K1p*K2p*H + K1p*K2p*K3p)
1512  ab = Bt/(1.0d0 + H/Kb)
1513  aw = Kw/H - H/(1.0d0 + St/Ks)
1514  ac = ta + hso4 - sit*hsi - ab - aw + Ft*hf - pt*hpo4
1515
1516! Calculate CO2*, HCO3-, & CO32- (in mol/kg soln) from Ct, Ac, H+, K1, & K2
1517  cu = (2.0d0 * tc - ac) / (2.0d0 + K1 / H)
1518  cb = K1 * cu / H
1519  cc = K2 * cb / H
1520
1521! When optCON = 'mol/m3' in calling routine (vars), then:
1522! convert output var concentrations from mol/kg to mol/m^3
1523! e.g., for case when drho = 1028, multiply by [1.028 kg/L  x  1000 L/m^3])
1524  co2  = cu * rhodum
1525  hco3 = cb * rhodum
1526  co3  = cc * rhodum
1527
1528! Determine CO2 fugacity [uatm]
1529! NOTE: equation just below requires CO2* in mol/kg
1530  fCO2 = cu * 1.e6_wp/K0
1531
1532! Determine CO2 partial pressure from CO2 fugacity [uatm]
1533  tk = 273.15d0 + temp
1534  !Compute EITHER "potential pCO2" OR "in situ pCO2" (T and P used for calculations will differ)
1535  IF     (trim(opGAS) == 'Pzero'   .OR. trim(opGAS) == 'pzero') THEN
1536     tk0 = tk                 !in situ temperature (K) for K0 calculation
1537     Ptot = Patm              !total pressure (in atm) = atmospheric pressure ONLY
1538  ELSEIF (trim(opGAS) == 'Ppot' .OR. trim(opGAS) == 'ppot') THEN
1539     !Use potential temperature and atmospheric pressure (water parcel adiabatically brought back to surface)
1540     !temp68 = (temp - 0.0002d0) / 0.99975d0          !temp = in situ T; temp68 is same converted to ITPS-68 scale
1541     !tempot68 = sw_ptmp(salt, temp68, Phydro_bar*10d0, 0.0d0) !potential temperature (C)
1542     !tempot   = 0.99975*tempot68 + 0.0002
1543     !tk0 = tempot + 273.15d0  !potential temperature (K) for fugacity coeff. calc as needed for potential fCO2 & pCO2
1544     tempot = sw_ptmp(salt, temp, Phydro_bar*10._wp, 0.0_wp) !potential temperature (C)
1545     tk0 = tempot + 273.15d0  !potential temperature (K) for fugacity coeff. calc as needed for potential fCO2 & pCO2
1546     Ptot = Patm              !total pressure (in atm) = atmospheric pressure ONLY
1547  ELSEIF (trim(opGAS) == 'Pinsitu' .OR. trim(opGAS) == 'pinsitu') THEN
1548     !Use in situ temperature and total pressure
1549     tk0 = tk                             !in situ temperature (K) for fugacity coefficient calculation
1550     Phydro_atm = Phydro_bar / 1.01325d0  !convert hydrostatic pressure from bar to atm (1.01325 bar / atm)
1551     Ptot = Patm + Phydro_atm            !total pressure (in atm) = atmospheric pressure + hydrostatic pressure
1552  ELSE
1553     PRINT *, "optGAS must be 'Pzero', 'Ppot', or 'Pinsitu'"
1554     STOP
1555  ENDIF
1556
1557! Now that we have T and P in the right form, continue with calculation of fugacity coefficient (and pCO2)
1558  Rgas_atm = 82.05736_wp      ! (cm3 * atm) / (mol * K)  CODATA (2006)
1559! To compute fugcoeff, we need 3 other terms (B, Del, xc2) in addition to 3 others above (tk, Ptot, Rgas_atm)
1560  B = -1636.75d0 + 12.0408d0*tk0 - 0.0327957d0*(tk0*tk0) + 0.0000316528d0*(tk0*tk0*tk0)
1561  Del = 57.7d0 - 0.118d0*tk0
1562! "x2" term often neglected (assumed = 1) in applications of Weiss's (1974) equation 9
1563! x2 = 1 - x1 = 1 - xCO2 (it is very close to 1, but not quite)
1564! Let's assume that xCO2 = fCO2. Resulting fugcoeff is identical to 8th digit after the decimal.
1565  xCO2approx = fCO2 * 1.e-6_wp
1566  IF (trim(opGAS) == 'Pinsitu' .OR. trim(opGAS) == 'pinsitu') THEN
1567!    xCO2approx = 400.0e-6_wp      !a simple test (gives about same result as seacarb for pCO2insitu)
1568!    approximate surface xCO2 ~ surface fCO2 (i.e., in situ fCO2 d by exponential pressure correction)
1569     xCO2approx = xCO2approx * exp( ((1-Ptot)*32.3_wp)/(82.05736_wp*tk0) )   ! of K0 press. correction, see Weiss (1974, equation 5)
1570  ENDIF
1571  xc2 = (1.0d0 - xCO2approx)**2 
1572  fugcoeff = exp( Ptot*(B + 2.0d0*xc2*Del)/(Rgas_atm*tk0) )
1573  pCO2 = fCO2 / fugcoeff
1574
1575! Determine Omega Calcite et Aragonite
1576! OmegaA = ((0.01028d0*salt/35.0d0)*cc) / Kspa
1577! OmegaC = ((0.01028d0*salt/35.0d0)*cc) / Kspc
1578! - see comments from Munhoven on the best value "0.02128" which differs slightly from the best practices guide (0.02127)
1579  Ca = (0.02128d0/40.078d0) * salt/1.80655d0
1580  OmegaA = (Ca*cc) / Kspa
1581  OmegaC = (Ca*cc) / Kspc
1582
1583  IF (lhook) CALL dr_hook(RoutineName,zhook_out ,zhook_handle)
1584  RETURN
1585  IF (lhook) CALL dr_hook(RoutineName,zhook_out,zhook_handle)
1586END SUBROUTINE varsolver
1587
1588! ----------------------------------------------------------------------
1589!  VARS
1590! ----------------------------------------------------------------------
1591!
1592!> \file vars.f90
1593!! \BRIEF
1594!> Module with vars subroutine - compute carbonate system vars from DIC,Alk,T,S,P,nuts
1595!>    Computes standard carbonate system variables (pH, CO2*, HCO3- and CO32-, OmegaA, OmegaC, R)
1596!!    as 1D arrays FROM
1597!!    temperature, salinity, pressure,
1598!!    total alkalinity (ALK), dissolved inorganic carbon (DIC),
1599!!    silica and phosphate concentrations (all 1-D arrays)
1600SUBROUTINE vars(ph, pco2, fco2, co2, hco3, co3, OmegaA, OmegaC, BetaD, rhoSW, p, tempis,  &
1601                temp, sal, alk, dic, sil, phos, Patm, depth, lat, N,                      &
1602                optCON, optT, optP, optB, optK1K2, optKf, optGAS                          )
1603
1604  !   Purpose:
1605  !     Computes other standard carbonate system variables (pH, CO2*, HCO3- and CO32-, OmegaA, OmegaC, R)
1606  !     as 1D arrays
1607  !     FROM:
1608  !     temperature, salinity, pressure,
1609  !     total alkalinity (ALK), dissolved inorganic carbon (DIC),
1610  !     silica and phosphate concentrations (all 1-D arrays)
1611
1612  !     INPUT variables:
1613  !     ================
1614  !     Patm    = atmospheric pressure [atm]
1615  !     depth   = depth [m]     (with optP='m', i.e., for a z-coordinate model vertical grid is depth, not pressure)
1616  !             = pressure [db] (with optP='db')
1617  !     lat     = latitude [degrees] (needed to convert depth to pressure, i.e., when optP='m')
1618  !             = dummy array (unused when optP='db')
1619  !     temp    = potential temperature [degrees C] (with optT='Tpot', i.e., models carry tempot, not in situ temp)
1620  !             = in situ   temperature [degrees C] (with optT='Tinsitu', e.g., for data)
1621  !     sal     = salinity in [psu]
1622  !     alk     = total alkalinity in [eq/m^3] with optCON = 'mol/m3'
1623  !             =               [eq/kg]  with optCON = 'mol/kg'
1624  !     dic     = dissolved inorganic carbon [mol/m^3] with optCON = 'mol/m3'
1625  !             =                            [mol/kg]  with optCON = 'mol/kg'
1626  !     sil     = silica    [mol/m^3] with optCON = 'mol/m3'
1627  !             =           [mol/kg]  with optCON = 'mol/kg'
1628  !     phos    = phosphate [mol/m^3] with optCON = 'mol/m3'
1629  !             =           [mol/kg]  with optCON = 'mol/kg'
1630  !     INPUT options:
1631  !     ==============
1632  !     -----------
1633  !     optCON: choose input & output concentration units - mol/kg (data) vs. mol/m^3 (models)
1634  !     -----------
1635  !       -> 'mol/kg' for DIC, ALK, sil, & phos given on mokal scale, i.e., in mol/kg  (std DATA units)
1636  !       -> 'mol/m3' for DIC, ALK, sil, & phos given in mol/m^3 (std MODEL units)
1637  !     -----------
1638  !     optT: choose in situ vs. potential temperature as input
1639  !     ---------
1640  !     NOTE: Carbonate chem calculations require IN-SITU temperature (not potential Temperature)
1641  !       -> 'Tpot' means input is pot. Temperature (in situ Temp "tempis" is computed)
1642  !       -> 'Tinsitu' means input is already in-situ Temperature, not pot. Temp ("tempis" not computed)
1643  !     ---------
1644  !     optP: choose depth (m) vs pressure (db) as input
1645  !     ---------
1646  !       -> 'm'  means "depth" input is in "m" (thus in situ Pressure "p" [db] is computed)
1647  !       -> 'db' means "depth" input is already in situ pressure [db], not m (thus p = depth)
1648  !     ---------
1649  !     optB: choose total boron formulation - Uppström (1974) vs. Lee et al. (2010)
1650  !     ---------
1651  !       -> 'u74' means use classic formulation of Uppström (1974) for total Boron
1652  !       -> 'l10' means use newer   formulation of Lee et al. (2010) for total Boron
1653  !     ---------
1654  !     optK1K2:
1655  !     ---------
1656  !       -> 'l'   means use Lueker et al. (2000) formulations for K1 & K2 (recommended by Dickson et al. 2007)
1657  !                **** BUT this should only be used when 2 < T < 35 and 19 < S < 43
1658  !       -> 'm10' means use Millero (2010) formulation for K1 & K2 (see Dickson et al., 2007)
1659  !                **** Valid for 0 < T < 50°C and 1 < S < 50 psu
1660  !     ----------
1661  !     optKf:
1662  !     ----------
1663  !       -> 'pf' means use Perez & Fraga (1987) formulation for Kf (recommended by Dickson et al., 2007)
1664  !               **** BUT Valid for  9 < T < 33°C and 10 < S < 40.
1665  !       -> 'dg' means use Dickson & Riley (1979) formulation for Kf (recommended by Dickson & Goyet, 1994)
1666  !     -----------
1667  !     optGAS: choose in situ vs. potential fCO2 and pCO2
1668  !     ---------
1669  !       PRESSURE corrections for K0 and the fugacity coefficient (Cf)
1670  !       -> 'Pzero'   = 'zero order' fCO2 and pCO2 (typical approach, which is flawed)
1671  !                      considers in situ T & only atm pressure (hydrostatic=0)
1672  !       -> 'Ppot'    = 'potential' fCO2 and pCO2 (water parcel brought adiabatically to the surface)
1673  !                      considers potential T & only atm pressure (hydrostatic press = 0)
1674  !       -> 'Pinsitu' = 'in situ' fCO2 and pCO2 (accounts for huge effects of pressure)
1675  !                      considers in situ T & total pressure (atm + hydrostatic)
1676  !     ---------
1677
1678  !     OUTPUT variables:
1679  !     =================
1680  !     ph   = pH on total scale
1681  !     pco2 = CO2 partial pressure (uatm)
1682  !     fco2 = CO2 fugacity (uatm)
1683  !     co2  = aqueous CO2 concentration in [mol/kg] or [mol/m^3] depending on optCON
1684  !     hco3 = bicarbonate (HCO3-) concentration in [mol/kg] or [mol/m^3] depending on optCON
1685  !     co3  = carbonate (CO3--) concentration in [mol/kg] or [mol/m^3] depending on optCON
1686  !     OmegaA = Omega for aragonite, i.e., the aragonite saturation state
1687  !     OmegaC = Omega for calcite, i.e., the   calcite saturation state
1688  !     BetaD = Revelle factor   dpCO2/pCO2 / dDIC/DIC
1689  !     rhoSW  = in-situ density of seawater; rhoSW = f(s, t, p)
1690  !     p = pressure [decibars]; p = f(depth, latitude) if computed from depth [m] OR p = depth if [db]
1691  !     tempis  = in-situ temperature [degrees C]
1692
1693  USE mocsy_singledouble
1694
1695  USE yomhook, ONLY: lhook, dr_hook
1696  USE parkind1, ONLY: jprb, jpim
1697
1698  IMPLICIT NONE
1699
1700! Input variables
1701  !>     number of records
1702  INTEGER, INTENT(in) :: N
1703  !> either <b>in situ temperature</b> (when optT='Tinsitu', typical data)
1704  !! OR <b>potential temperature</b> (when optT='Tpot', typical models) <b>[degree C]</b>
1705  REAL(kind=wp), INTENT(in),    DIMENSION(N) :: temp
1706  !> salinity <b>[psu]</b>
1707  REAL(kind=wp), INTENT(in), DIMENSION(N) :: sal
1708  !> total alkalinity in <b>[eq/m^3]</b> (when optCON = 'mol/m3') OR in <b>[eq/kg]</b>  (when optCON = 'mol/kg')
1709  REAL(kind=wp), INTENT(in), DIMENSION(N) :: alk
1710  !> dissolved inorganic carbon in <b>[mol/m^3]</b> (when optCON = 'mol/m3') OR in <b>[mol/kg]</b> (when optCON = 'mol/kg')
1711  REAL(kind=wp), INTENT(in), DIMENSION(N) :: dic
1712  !> SiO2 concentration in <b>[mol/m^3]</b> (when optCON = 'mol/m3') OR in <b>[mol/kg]</b> (when optCON = 'mol/kg')
1713  REAL(kind=wp), INTENT(in), DIMENSION(N) :: sil
1714  !> phosphate concentration in <b>[mol/m^3]</b> (when optCON = 'mol/m3') OR in <b>[mol/kg]</b> (when optCON = 'mol/kg')
1715  REAL(kind=wp), INTENT(in), DIMENSION(N) :: phos
1716!f2py optional , depend(sal) :: n=len(sal)
1717  !> atmospheric pressure <b>[atm]</b>
1718  REAL(kind=wp), INTENT(in), DIMENSION(N) :: Patm
1719  !> depth in \b meters (when optP='m') or \b decibars (when optP='db')
1720  REAL(kind=wp), INTENT(in),    DIMENSION(N) :: depth
1721  !> latitude <b>[degrees north]</b>
1722  REAL(kind=wp), INTENT(in),    DIMENSION(N) :: lat
1723
1724  !> choose either \b 'mol/kg' (std DATA units) or \b 'mol/m3' (std MODEL units) to select
1725  !! concentration units for input (for alk, dic, sil, phos) & output (co2, hco3, co3)
1726  CHARACTER(6), INTENT(in) :: optCON
1727  !> choose \b 'Tinsitu' for in situ temperature or \b 'Tpot' for potential temperature (in situ Temp is computed, needed for models)
1728  CHARACTER(7), INTENT(in) :: optT
1729  !> for depth input, choose \b "db" for decibars (in situ pressure) or \b "m" for meters (pressure is computed, needed for models)
1730  CHARACTER(2), INTENT(in) :: optP
1731  !> for total boron, choose either \b 'u74' (Uppstrom, 1974) or \b 'l10' (Lee et al., 2010).
1732  !! The 'l10' formulation is based on 139 measurements (instead of 20),
1733  !! uses a more accurate method, and
1734  !! generally increases total boron in seawater by 4%
1735!f2py character*3 optional, intent(in) :: optB='l10'
1736  CHARACTER(3), OPTIONAL, INTENT(in) :: optB
1737  !> for Kf, choose either \b 'pf' (Perez & Fraga, 1987) or \b 'dg' (Dickson & Riley, 1979)
1738!f2py character*2 optional, intent(in) :: optKf='pf'
1739  CHARACTER(2), OPTIONAL, INTENT(in) :: optKf
1740  !> for K1,K2 choose either \b 'l' (Lueker et al., 2000) or \b 'm10' (Millero, 2010)
1741!f2py character*3 optional, intent(in) :: optK1K2='l'
1742  CHARACTER(3), OPTIONAL, INTENT(in) :: optK1K2
1743  !> for K0,fugacity coefficient choose either \b 'Ppot' (no pressure correction) or \b 'Pinsitu' (with pressure correction)
1744  !! 'Ppot'    - for 'potential' fCO2 and pCO2 (water parcel brought adiabatically to the surface)
1745  !! 'Pinsitu' - for 'in situ' values of fCO2 and pCO2, accounting for pressure on K0 and Cf
1746  !! with 'Pinsitu' the fCO2 and pCO2 will be many times higher in the deep ocean
1747!f2py character*7 optional, intent(in) :: optGAS='Pinsitu'
1748  CHARACTER(7), OPTIONAL, INTENT(in) :: optGAS
1749
1750! Output variables:
1751  !> pH on the <b>total scale</b>
1752  REAL(kind=wp), INTENT(out), DIMENSION(N) :: ph
1753  !> CO2 partial pressure <b>[uatm]</b>
1754  REAL(kind=wp), INTENT(out), DIMENSION(N) :: pco2
1755  !> CO2 fugacity <b>[uatm]</b>
1756  REAL(kind=wp), INTENT(out), DIMENSION(N) :: fco2
1757  !> aqueous CO2* concentration, either in <b>[mol/m^3]</b> or <b>[mol/kg</b>] depending on choice for optCON
1758  REAL(kind=wp), INTENT(out), DIMENSION(N) :: co2
1759  !> bicarbonate ion (HCO3-) concentration, either in <b>[mol/m^3]</b> or <b>[mol/kg]</b> depending on choice for optCON
1760  REAL(kind=wp), INTENT(out), DIMENSION(N) :: hco3
1761  !> carbonate ion (CO3--) concentration, either in <b>[mol/m^3]</b> or <b>[mol/kg]</b> depending on choice for optCON
1762  REAL(kind=wp), INTENT(out), DIMENSION(N) :: co3
1763  !> Omega for aragonite, i.e., the aragonite saturation state
1764  REAL(kind=wp), INTENT(out), DIMENSION(N) :: OmegaA
1765  !> Omega for calcite, i.e., the calcite saturation state
1766  REAL(kind=wp), INTENT(out), DIMENSION(N) :: OmegaC
1767  !> Revelle factor, i.e., dpCO2/pCO2 / dDIC/DIC
1768  REAL(kind=wp), INTENT(out), DIMENSION(N) :: BetaD
1769  !> in-situ density of seawater; rhoSW = f(s, t, p) in <b>[kg/m3]</b>
1770  REAL(kind=wp), INTENT(out), DIMENSION(N) :: rhoSW
1771  !> pressure <b>[decibars]</b>; p = f(depth, latitude) if computed from depth [m] (when optP='m') OR p = depth [db] (when optP='db')
1772  REAL(kind=wp), INTENT(out), DIMENSION(N) :: p
1773  !> in-situ temperature \b <b>[degrees C]</b>
1774  REAL(kind=wp), INTENT(out), DIMENSION(N) :: tempis
1775
1776! Local variables
1777  REAL(kind=wp) :: ssal, salk, sdic, ssil, sphos
1778  REAL(kind=wp) :: tempot, tempis68, tempot68
1779  REAL(kind=wp) :: drho
1780
1781  REAL(kind=wp) :: K0, K1, K2, Kb, Kw, Ks, Kf, Kspc
1782  REAL(kind=wp) :: Kspa, K1p, K2p, K3p, Ksi
1783  REAL(kind=wp) :: St, Ft, Bt
1784
1785  REAL(kind=wp), DIMENSION(1) :: aK0, aK1, aK2, aKb, aKw, aKs, aKf, aKspc
1786  REAL(kind=wp), DIMENSION(1) :: aKspa, aK1p, aK2p, aK3p, aKsi
1787  REAL(kind=wp), DIMENSION(1) :: aSt, aFt, aBt
1788
1789  REAL(kind=wp) :: Patmd, Ptot, Rgas_atm, B, Del, xCO2approx, xc2, fugcoeff
1790  REAL(kind=wp) :: Phydro_atm
1791
1792  INTEGER :: i, icount
1793
1794  REAL(kind=wp) :: t, tk, prb
1795  REAL(kind=wp) :: s
1796  REAL(kind=wp) :: tc, ta
1797  REAL(kind=wp) :: sit, pt
1798  REAL(kind=wp) :: Hinit
1799  REAL(kind=wp) :: ah1
1800
1801  REAL(kind=wp) :: HSO4, HF, HSI, HPO4
1802  REAL(kind=wp) :: ab, aw, ac, ah2, erel
1803
1804  REAL(kind=wp) :: cu, cb, cc
1805
1806  REAL(kind=wp), DIMENSION(2) :: dicdel, pco2del
1807  REAL(kind=wp) :: dx, Rf
1808  REAL(kind=wp) :: dph, dpco2, dfco2, dco2, dhco3, dco3, dOmegaA, dOmegaC
1809
1810  INTEGER :: kcomp
1811  INTEGER :: j, minusplus
1812
1813! Arrays to pass optional arguments into or use defaults (Dickson et al., 2007)
1814  CHARACTER(3) :: opB
1815  CHARACTER(2) :: opKf
1816  CHARACTER(3) :: opK1K2
1817  CHARACTER(7) :: opGAS
1818  INTEGER(KIND=jpim), PARAMETER :: zhook_in = 0
1819  INTEGER(KIND=jpim), PARAMETER :: zhook_out = 1
1820  REAL(KIND=jprb)               :: zhook_handle
1821
1822  CHARACTER(LEN=*), PARAMETER :: RoutineName='VARS'
1823
1824  IF (lhook) CALL dr_hook(RoutineName,zhook_in,zhook_handle)
1825
1826
1827! Set defaults for optional arguments (in Fortran 90)
1828! Note:  Optional arguments with f2py (python) are set above with
1829!        the !f2py statements that precede each type declaraion
1830  IF (PRESENT(optB)) THEN
1831!   print *,"optB present:"
1832!   print *,"optB = ", optB
1833    opB = optB
1834  ELSE
1835!   Default is Lee et al (2010) for total boron
1836!   print *,"optB NOT present:"
1837    opB = 'l10'
1838!   print *,"opB = ", opB
1839  ENDIF
1840  IF (PRESENT(optKf)) THEN
1841!   print *,"optKf = ", optKf
1842    opKf = optKf
1843  ELSE
1844!   print *,"optKf NOT present:"
1845!   Default is Perez & Fraga (1987) for Kf
1846    opKf = 'pf'
1847!   print *,"opKf = ", opKf
1848  ENDIF
1849  IF (PRESENT(optK1K2)) THEN
1850!   print *,"optK1K2 = ", optK1K2
1851    opK1K2 = optK1K2
1852  ELSE
1853!   print *,"optK1K2 NOT present:"
1854!   Default is Lueker et al. 2000) for K1 & K2
1855    opK1K2 = 'l'
1856!   print *,"opK1K2 = ", opK1K2
1857  ENDIF
1858  IF (PRESENT(optGAS)) THEN
1859    opGAS = optGAS
1860  ELSE
1861    opGAS = 'Pinsitu'
1862  ENDIF
1863
1864  icount = 0
1865  DO i = 1, N
1866     icount = icount + 1
1867!    ===============================================================
1868!    Convert model depth -> press; convert model Theta -> T in situ
1869!    ===============================================================
1870!    * Model temperature tracer is usually "potential temperature"
1871!    * Model vertical grid is usually in meters
1872!    BUT carbonate chem routines require pressure & in-situ T
1873!    Thus before computing chemistry, if appropriate,
1874!    convert these 2 model vars (input to this routine)
1875!    - depth [m] => convert to pressure [db]
1876!    - potential temperature (C) => convert to in-situ T (C)
1877!    -------------------------------------------------------
1878!    1)  Compute pressure [db] from depth [m] and latitude [degrees] (if input is m, for models)
1879     !print *,"optP =", optP, "end"
1880     IF (trim(optP) == 'm' ) THEN
1881!       Compute pressure [db] from depth [m] and latitude [degrees]
1882        p(i) = p80(depth(i), lat(i))
1883     ELSEIF (trim(optP) == 'db') THEN
1884!       In this case (where optP = 'db'), p is input & output (no depth->pressure conversion needed)
1885        p(i) = depth(i)
1886     ELSE
1887        !print *,"optP =", optP, "end"
1888        PRINT *,"optP must be either 'm' or 'db'"
1889        STOP
1890     ENDIF
1891
1892!    2) Convert potential T to in-situ T (if input is Tpot, i.e. case for models):
1893     IF (trim(optT) == 'Tpot' .OR. trim(optT) == 'tpot') THEN
1894        tempot = temp(i)
1895!       This is the case for most models and some data
1896!       a) Convert the pot. temp on today's "ITS 90" scale to older IPTS 68 scale
1897!          (see Dickson et al., Best Practices Guide, 2007, Chap. 5, p. 7, including footnote)
1898        tempot68 = (tempot - 0.0002) / 0.99975
1899!       b) Compute "in-situ Temperature" from "Potential Temperature" (both on IPTS 68)
1900        tempis68 = sw_temp(sal(i), tempot68, p(i), 0.0_wp )
1901!       c) Convert the in-situ temp on older IPTS 68 scale to modern scale (ITS 90)
1902        tempis(i) = 0.99975*tempis68 + 0.0002
1903!       Note: parts (a) and (c) above are tiny corrections;
1904!             part  (b) is a big correction for deep waters (but zero at surface)
1905     ELSEIF (trim(optT) == 'Tinsitu' .OR. trim(optT) == 'tinsitu') THEN
1906!       When optT = 'Tinsitu', tempis is input & output (no tempot needed)
1907        tempis(i) = temp(i)
1908        tempis68  = (temp(i) - 0.0002) / 0.99975
1909!       dtempot68 = sw_ptmp(DBLE(sal(i)), DBLE(tempis68), DBLE(p), 0.0d0)
1910!       dtempot   = 0.99975*dtempot68 + 0.0002
1911     ELSE
1912        PRINT *,"optT must be either 'Tpot' or 'Tinsitu'"
1913        PRINT *,"you specified optT =", trim(optT) 
1914        STOP
1915     ENDIF
1916
1917!    ================================================================
1918!    Carbonate chemistry computations
1919!    ================================================================
1920     IF (dic(i) > 0. .AND. dic(i) < 1.0e+4) THEN
1921!       Test to indicate if any of input variables are unreasonable
1922        IF (       sal(i) < 0.   &
1923             .OR.  alk(i) < 0.   &
1924             .OR.  dic(i) < 0.   &
1925             .OR.  sil(i) < 0.   &
1926             .OR. phos(i) < 0.   &
1927             .OR.  sal(i) > 1e+3 &
1928             .OR.  alk(i) > 1e+3 &
1929             .OR.  dic(i) > 1e+3 &
1930             .OR.  sil(i) > 1e+3 &
1931             .OR. phos(i) > 1e+3) THEN
1932           PRINT *, 'i, icount, tempot, sal,    alk,    dic,    sil,    phos =', &
1933                     i, icount, tempot, sal(i), alk(i), dic(i), sil(i), phos(i)
1934        ENDIF
1935!       Zero out any negative salinity, phosphate, silica, dic, and alk
1936        IF (sal(i) < 0.0) THEN
1937           ssal = 0.0
1938        ELSE
1939           ssal = sal(i)
1940        ENDIF
1941        IF (phos(i) < 0.0) THEN
1942           sphos = 0.0
1943        ELSE
1944           sphos = phos(i)
1945        ENDIF
1946        IF (sil(i) < 0.0) THEN
1947           ssil = 0.0
1948        ELSE
1949           ssil = sil(i)
1950        ENDIF
1951        IF (dic(i) < 0.0) THEN
1952          sdic = 0.0
1953        ELSE
1954          sdic = dic(i)
1955        ENDIF
1956        IF (alk(i) < 0.0) THEN
1957          salk = 0.0
1958        ELSE
1959          salk = alk(i)
1960        ENDIF
1961
1962!       Absolute temperature (Kelvin) & related variables
1963        t  = DBLE(tempis(i))
1964        tk = 273.15d0 + t
1965
1966!       Atmospheric pressure
1967        Patmd = DBLE(Patm(i))
1968!       Hydrostatic pressure (prb is in bars)
1969        prb = DBLE(p(i)) / 10.0d0
1970        Phydro_atm = prb / 1.01325d0  ! convert hydrostatic pressure from bar to atm (1.01325 bar / atm)
1971!       Total pressure [atm]
1972        IF     (trim(opGAS) == 'Pzero'     .OR. trim(opGAS) == 'pzero') THEN
1973           Ptot = Patmd               ! total pressure (in atm) = atmospheric pressure ONLY
1974        ELSEIF (trim(opGAS) == 'Ppot'    .OR. trim(opGAS) == 'ppot') THEN
1975           Ptot = Patmd               ! total pressure (in atm) = atmospheric pressure ONLY
1976        ELSEIF (trim(opGAS) == 'Pinsitu' .OR. trim(opGAS) == 'pinsitu') THEN
1977           Ptot = Patmd + Phydro_atm   ! total pressure (in atm) = atmospheric pressure + hydrostatic pressure
1978        ELSE
1979           PRINT *, "optGAS must be 'Pzero', 'Ppot', or 'Pinsitu'"
1980           STOP
1981        ENDIF
1982
1983!       Salinity (equivalent array in double precision)
1984        s = DBLE(ssal)
1985
1986!       Get all equilibrium constants and total concentrations of SO4, F, B
1987        CALL constants(aK0, aK1, aK2, aKb, aKw, aKs, aKf, aKspc, aKspa,  &
1988                       aK1p, aK2p, aK3p, aKsi,                           &
1989                       aSt, aFt, aBt,                                    &
1990                       temp(i), sal(i), Patm(i),                         &
1991                       depth(i), lat(i), 1,                              &
1992                       optT, optP, opB, opK1K2, opKf, opGAS              )
1993
1994!       Unlike f77, in F90 we can't assign an array (dimen=1) to a scalar in a routine argument
1995!       Thus, set scalar constants equal to array (dimension=1) values required as arguments
1996        K0 = aK0(1) ; K1 = aK1(1) ; K2 = aK2(1) ; Kb = aKb(1) ; Kw = aKw(1) 
1997        Ks = aKs(1) ; Kf = aKs(1) ; Kspc = aKspc(1) ; Kspa = aKspa(1) 
1998        K1p = aK1p(1) ; K2p = aK2p(1) ; K3p = aK3p(1) ; Ksi = aKsi(1)
1999        St = aSt(1) ; Ft = aFt(1) ; Bt = aBt(1)
2000
2001!       Compute in-situ density [kg/m^3]
2002        rhoSW(i) =  rho(ssal, tempis68, prb)
2003
2004!       Either convert units of DIC and ALK (MODEL case) or not (DATA case)
2005        IF     (trim(optCON) == 'mol/kg') THEN
2006!          No conversion:
2007!          print *,'DIC and ALK already given in mol/kg (std DATA units)'
2008           drho = 1.
2009        ELSEIF (trim(optCON) == 'mol/m3') THEN
2010!          Do conversion:
2011!          print *,"DIC and ALK given in mol/m^3 (std MODEL units)"
2012           drho = DBLE(rhoSW(i))
2013        ELSE
2014           PRINT *,"optCON must be either 'mol/kg' or 'mol/m3'"
2015           STOP
2016        ENDIF
2017
2018        tc  = DBLE(sdic)/drho
2019        ta  = DBLE(salk)/drho
2020        sit = DBLE(ssil)/drho
2021        pt  = DBLE(sphos)/drho
2022
2023!       Solve for pH and all other variables
2024!       ------------------------------------
2025        CALL varsolver(dph, dpco2, dfco2, dco2, dhco3, dco3, dOmegaA, dOmegaC,     &
2026                      t, s, ta, tc, pt, sit,                                       &
2027                      Bt, St, Ft,                                                  &
2028                      K0, K1, K2, Kb, Kw, Ks, Kf, Kspc, Kspa, K1p, K2p, K3p, Ksi,  & 
2029                      Patmd, prb, drho, opGAS                                     )
2030
2031!       Convert all output variables from double to single precision
2032        pH(i)     = REAL(dph)
2033        co2(i)    = REAL(dco2)
2034        hco3(i)   = REAL(dhco3)
2035        co3(i)    = REAL(dco3)
2036        fCO2(i)   = REAL(dfCO2)
2037        pCO2(i)   = REAL(dpCO2)
2038        OmegaA(i) = REAL(dOmegaA)
2039        OmegaC(i) = REAL(dOmegaC)
2040
2041!       Compute Revelle factor numerically (derivative using centered-difference scheme)
2042        DO j=1,2
2043           minusplus = (-1)**j
2044           dx = 0.1 * 1e-6         ! Numerical tests found for DIC that optimal dx = 0.1 umol/kg (0.1e-6 mol/kg)
2045           dicdel(j) = tc + DBLE(minusplus)*dx/2.0d0
2046            CALL varsolver(dph, dpco2, dfco2, dco2, dhco3, dco3, dOmegaA, dOmegaC, &
2047               t, s, ta, dicdel(j), pt, sit,                                       &
2048               Bt, St, Ft,                                                         &
2049               K0, K1, K2, Kb, Kw, Ks, Kf, Kspc, Kspa, K1p, K2p, K3p, Ksi,         & 
2050               Patmd, prb, drho, optGAS                                            )
2051            pco2del(j) = dpco2
2052        END DO
2053       !Classic finite centered difference formula for derivative (2nd order accurate)
2054        Rf = (pco2del(2) - pco2del(1)) / (dicdel(2) - dicdel(1))       ! dpCO2/dDIC
2055       !Rf = (pco2del(2) - pco2del(1)) / (dx)                          ! dpCO2/dDIC (same as just above)
2056        Rf = Rf * tc / dpco2                                           ! R = (dpCO2/dDIC) * (DIC/pCO2)
2057
2058        BetaD(i) = REAL(Rf)
2059
2060     ELSE
2061
2062        ph(i)     = 1.e20_wp
2063        pco2(i)   = 1.e20_wp
2064        fco2(i)   = 1.e20_wp
2065        co2(i)    = 1.e20_wp
2066        hco3(i)   = 1.e20_wp
2067        co3(i)    = 1.e20_wp
2068        OmegaA(i) = 1.e20_wp
2069        OmegaC(i) = 1.e20_wp
2070        BetaD(i)  = 1.e20_wp
2071        rhoSW(i)  = 1.e20_wp
2072        p(i)      = 1.e20_wp
2073        tempis(i) = 1.e20_wp
2074
2075     ENDIF
2076
2077  END DO
2078
2079  IF (lhook) CALL dr_hook(RoutineName,zhook_out ,zhook_handle)
2080  RETURN
2081  IF (lhook) CALL dr_hook(RoutineName,zhook_out,zhook_handle)
2082END SUBROUTINE vars
2083
2084! ----------------------------------------------------------------------
2085!  P2FCO2
2086! ----------------------------------------------------------------------
2087!
2088!> \file p2fCO2.f90
2089!! \BRIEF
2090!>    Module with p2fCO2 subroutine - compute fCO2 from pCO2, in situ T, atm pressure, hydrostatic pressure
2091!>    Compute fCO2 from arrays of pCO2, in situ temp, atm pressure, & hydrostatic pressure
2092SUBROUTINE p2fCO2(pCO2, temp, Patm, p, N, fCO2)
2093  !    Purpose:
2094  !    Compute fCO2 from arrays of pCO2, in situ temp, atm pressure, & hydrostatic pressure
2095
2096  USE mocsy_singledouble
2097  USE yomhook, ONLY: lhook, dr_hook
2098  USE parkind1, ONLY: jprb, jpim
2099
2100  IMPLICIT NONE
2101
2102  !> number of records
2103  INTEGER, INTENT(in) :: N
2104
2105! INPUT variables
2106  !> oceanic partial pressure of CO2 [uatm]
2107  REAL(kind=wp), INTENT(in), DIMENSION(N) :: pCO2
2108  !> in situ temperature [C]
2109  REAL(kind=wp), INTENT(in), DIMENSION(N) :: temp
2110  !> atmospheric pressure [atm]
2111  REAL(kind=wp), INTENT(in), DIMENSION(N) :: Patm
2112  !> hydrostatic pressure [db]
2113  REAL(kind=wp), INTENT(in), DIMENSION(N) :: p
2114
2115! OUTPUT variables:
2116  !> fugacity of CO2 [uatm]
2117  REAL(kind=wp), INTENT(out), DIMENSION(N) :: fCO2
2118
2119! LOCAL variables:
2120  REAL(kind=wp) :: dpCO2, dtemp, tk, dPatm, prb
2121  REAL(kind=wp) :: Ptot, Rgas_atm, B, Del, xCO2approx, xc2, fugcoeff
2122  REAL(kind=wp) :: dfCO2
2123
2124  INTEGER :: i
2125  INTEGER(KIND=jpim), PARAMETER :: zhook_in = 0
2126  INTEGER(KIND=jpim), PARAMETER :: zhook_out = 1
2127  REAL(KIND=jprb)               :: zhook_handle
2128
2129  CHARACTER(LEN=*), PARAMETER :: RoutineName='P2FCO2'
2130
2131  IF (lhook) CALL dr_hook(RoutineName,zhook_in,zhook_handle)
2132
2133
2134! REAL(kind=wp) :: sw_ptmp
2135! EXTERNAL sw_ptmp
2136
2137  DO i = 1,N
2138     dpCO2     = DBLE(pCO2(i))
2139     dtemp     = DBLE(temp(i))
2140     dPatm     = DBLE(Patm(i))
2141     tk = 273.15d0 + DBLE(temp(i))     !Absolute temperature (Kelvin)
2142     prb = DBLE(p(i)) / 10.0d0         !Pressure effect (prb is in bars)
2143     Ptot = dPatm + prb/1.01325d0      !Total pressure (atmospheric + hydrostatic) [atm]
2144     Rgas_atm = 82.05736_wp            !R in (cm3 * atm) / (mol * K)  from CODATA (2006)
2145!    To compute fugcoeff, we need 3 other terms (B, Del, xc2) as well as 3 others above (tk, Ptot, Rgas_atm)
2146     B = -1636.75d0 + 12.0408d0*tk - 0.0327957d0*(tk*tk) + 0.0000316528d0*(tk*tk*tk)
2147     Del = 57.7d0 - 0.118d0*tk
2148!    "x2" term often neglected (assumed = 1) in applications of Weiss's (1974) equation 9
2149!    x2 = 1 - x1 = 1 - xCO2 (it is very close to 1, but not quite)
2150!    Let's assume that xCO2 = pCO2. Resulting fugcoeff is identical to 8th digit after the decimal.
2151     xCO2approx = dpCO2 * 1.e-6_wp
2152     xc2 = (1.0d0 - xCO2approx)**2 
2153     fugcoeff = EXP( Ptot*(B + 2.0d0*xc2*Del)/(Rgas_atm*tk) )
2154     dfCO2 = dpCO2 * fugcoeff
2155     fCO2(i) = REAL(dfCO2)
2156  END DO
2157
2158  IF (lhook) CALL dr_hook(RoutineName,zhook_out ,zhook_handle)
2159  RETURN
2160  IF (lhook) CALL dr_hook(RoutineName,zhook_out,zhook_handle)
2161END SUBROUTINE p2fCO2
2162
2163! ----------------------------------------------------------------------
2164!  P2FCO2
2165! ----------------------------------------------------------------------
2166!
2167!> \file f2pCO2.f90
2168!! \BRIEF
2169!>    Module with f2pCO2 subroutine - compute pCO2 from fCO2, in situ T, atm pressure, hydrostatic pressure
2170!>    Compute pCO2 from arrays of fCO2, in situ temp, atm pressure, & hydrostatic pressure
2171SUBROUTINE f2pCO2(fCO2, temp, Patm, p, N, pCO2)
2172  !    Purpose:
2173  !    Compute pCO2 from arrays of fCO2, in situ temp, atm pressure, & hydrostatic pressure
2174
2175  USE mocsy_singledouble
2176  USE yomhook, ONLY: lhook, dr_hook
2177  USE parkind1, ONLY: jprb, jpim
2178
2179  IMPLICIT NONE
2180
2181  !> number of records
2182  INTEGER, intent(in) :: N
2183
2184! INPUT variables
2185  !> oceanic fugacity of CO2 [uatm]
2186  REAL(kind=wp), INTENT(in), DIMENSION(N) :: fCO2
2187  !> in situ temperature [C]
2188  REAL(kind=wp), INTENT(in), DIMENSION(N) :: temp
2189  !> atmospheric pressure [atm]
2190  REAL(kind=wp), INTENT(in), DIMENSION(N) :: Patm
2191  !> hydrostatic pressure [db]
2192  REAL(kind=wp), INTENT(in), DIMENSION(N) :: p
2193
2194! OUTPUT variables:
2195  !> oceanic partial pressure of CO2 [uatm]
2196  REAL(kind=wp), INTENT(out), DIMENSION(N) :: pCO2
2197
2198! LOCAL variables:
2199  REAL(kind=wp) :: dfCO2, dtemp, tk, dPatm, prb
2200  REAL(kind=wp) :: Ptot, Rgas_atm, B, Del, xCO2approx, xc2, fugcoeff
2201  REAL(kind=wp) :: dpCO2
2202
2203  INTEGER :: i
2204  INTEGER(KIND=jpim), PARAMETER :: zhook_in = 0
2205  INTEGER(KIND=jpim), PARAMETER :: zhook_out = 1
2206  REAL(KIND=jprb)               :: zhook_handle
2207
2208  CHARACTER(LEN=*), PARAMETER :: RoutineName='F2PCO2'
2209
2210  IF (lhook) CALL dr_hook(RoutineName,zhook_in,zhook_handle)
2211
2212
2213! REAL(kind=wp) :: sw_ptmp
2214! EXTERNAL sw_ptmp
2215
2216  DO i = 1,N
2217     dfCO2     = DBLE(fCO2(i))
2218     dtemp     = DBLE(temp(i))
2219     dPatm     = DBLE(Patm(i))
2220     tk = 273.15d0 + DBLE(temp(i))     !Absolute temperature (Kelvin)
2221     prb = DBLE(p(i)) / 10.0d0         !Pressure effect (prb is in bars)
2222     Ptot = dPatm + prb/1.01325d0      !Total pressure (atmospheric + hydrostatic) [atm]
2223     Rgas_atm = 82.05736_wp            !R in (cm3 * atm) / (mol * K)  from CODATA (2006)
2224!    To compute fugcoeff, we need 3 other terms (B, Del, xc2) as well as 3 others above (tk, Ptot, Rgas_atm)
2225     B = -1636.75d0 + 12.0408d0*tk - 0.0327957d0*(tk*tk) + 0.0000316528d0*(tk*tk*tk)
2226     Del = 57.7d0 - 0.118d0*tk
2227!    "x2" term often neglected (assumed = 1) in applications of Weiss's (1974) equation 9
2228!    x2 = 1 - x1 = 1 - xCO2 (it is very close to 1, but not quite)
2229!    Let's assume that xCO2 = fCO2. Resulting fugcoeff is identical to 8th digit after the decimal.
2230     xCO2approx = dfCO2 * 1.e-6_wp
2231     xc2 = (1.0d0 - xCO2approx)**2 
2232     fugcoeff = exp( Ptot*(B + 2.0d0*xc2*Del)/(Rgas_atm*tk) )
2233     dpCO2 = dfCO2 / fugcoeff
2234     pCO2(i) = REAL(dpCO2)
2235  END DO
2236
2237  IF (lhook) CALL dr_hook(RoutineName,zhook_out ,zhook_handle)
2238  RETURN
2239  IF (lhook) CALL dr_hook(RoutineName,zhook_out,zhook_handle)
2240END SUBROUTINE f2pCO2
2241
2242END MODULE mocsy_mainmod
Note: See TracBrowser for help on using the repository browser.