MOM6
MOM_EOS_NEMO.F90
Go to the documentation of this file.
2 !***********************************************************************
3 !* GNU General Public License *
4 !* This file is a part of MOM. *
5 !* *
6 !* MOM is free software; you can redistribute it and/or modify it and *
7 !* are expected to follow the terms of the GNU General Public License *
8 !* as published by the Free Software Foundation; either version 2 of *
9 !* the License, or (at your option) any later version. *
10 !* *
11 !* MOM is distributed in the hope that it will be useful, but WITHOUT *
12 !* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
13 !* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public *
14 !* License for more details. *
15 !* *
16 !* For the full text of the GNU General Public License, *
17 !* write to: Free Software Foundation, Inc., *
18 !* 675 Mass Ave, Cambridge, MA 02139, USA. *
19 !* or see: http://www.gnu.org/licenses/gpl.html *
20 !***********************************************************************
21 
22 !***********************************************************************
23 !* The subroutines in this file implement the equation of state for *
24 !* sea water using the formulae provided by NEMO developer Roquet *
25 !* in a private communication , Roquet et al, Ocean Modelling (2015) *
26 !* Roquet, F., Madec, G., McDougall, T. J., and Barker, P. M., 2015. *
27 !* Accurate polynomial expressions for the density and specific volume*
28 !* of seawater using the TEOS-10 standard. Ocean Modelling, 90:29-43. *
29 !* These algorithms are NOT from NEMO package!! *
30 !***********************************************************************
31 
32 !use gsw_mod_toolbox, only : gsw_sr_from_sp, gsw_ct_from_pt
33 use gsw_mod_toolbox, only : gsw_rho_first_derivatives
34 
35 implicit none ; private
36 
40 
43 end interface calculate_density_nemo
44 
45  real, parameter :: pa2db = 1.e-4
46  real, parameter :: rdeltas = 32.
47  real, parameter :: r1_s0 = 0.875/35.16504
48  real, parameter :: r1_t0 = 1./40.
49  real, parameter :: r1_p0 = 1.e-4
50  real, parameter :: r00 = 4.6494977072e+01
51  real, parameter :: r01 = -5.2099962525
52  real, parameter :: r02 = 2.2601900708e-01
53  real, parameter :: r03 = 6.4326772569e-02
54  real, parameter :: r04 = 1.5616995503e-02
55  real, parameter :: r05 = -1.7243708991e-03
56  real, parameter :: eos000 = 8.0189615746e+02
57  real, parameter :: eos100 = 8.6672408165e+02
58  real, parameter :: eos200 = -1.7864682637e+03
59  real, parameter :: eos300 = 2.0375295546e+03
60  real, parameter :: eos400 = -1.2849161071e+03
61  real, parameter :: eos500 = 4.3227585684e+02
62  real, parameter :: eos600 = -6.0579916612e+01
63  real, parameter :: eos010 = 2.6010145068e+01
64  real, parameter :: eos110 = -6.5281885265e+01
65  real, parameter :: eos210 = 8.1770425108e+01
66  real, parameter :: eos310 = -5.6888046321e+01
67  real, parameter :: eos410 = 1.7681814114e+01
68  real, parameter :: eos510 = -1.9193502195
69  real, parameter :: eos020 = -3.7074170417e+01
70  real, parameter :: eos120 = 6.1548258127e+01
71  real, parameter :: eos220 = -6.0362551501e+01
72  real, parameter :: eos320 = 2.9130021253e+01
73  real, parameter :: eos420 = -5.4723692739
74  real, parameter :: eos030 = 2.1661789529e+01
75  real, parameter :: eos130 = -3.3449108469e+01
76  real, parameter :: eos230 = 1.9717078466e+01
77  real, parameter :: eos330 = -3.1742946532
78  real, parameter :: eos040 = -8.3627885467
79  real, parameter :: eos140 = 1.1311538584e+01
80  real, parameter :: eos240 = -5.3563304045
81  real, parameter :: eos050 = 5.4048723791e-01
82  real, parameter :: eos150 = 4.8169980163e-01
83  real, parameter :: eos060 = -1.9083568888e-01
84  real, parameter :: eos001 = 1.9681925209e+01
85  real, parameter :: eos101 = -4.2549998214e+01
86  real, parameter :: eos201 = 5.0774768218e+01
87  real, parameter :: eos301 = -3.0938076334e+01
88  real, parameter :: eos401 = 6.6051753097
89  real, parameter :: eos011 = -1.3336301113e+01
90  real, parameter :: eos111 = -4.4870114575
91  real, parameter :: eos211 = 5.0042598061
92  real, parameter :: eos311 = -6.5399043664e-01
93  real, parameter :: eos021 = 6.7080479603
94  real, parameter :: eos121 = 3.5063081279
95  real, parameter :: eos221 = -1.8795372996
96  real, parameter :: eos031 = -2.4649669534
97  real, parameter :: eos131 = -5.5077101279e-01
98  real, parameter :: eos041 = 5.5927935970e-01
99  real, parameter :: eos002 = 2.0660924175
100  real, parameter :: eos102 = -4.9527603989
101  real, parameter :: eos202 = 2.5019633244
102  real, parameter :: eos012 = 2.0564311499
103  real, parameter :: eos112 = -2.1311365518e-01
104  real, parameter :: eos022 = -1.2419983026
105  real, parameter :: eos003 = -2.3342758797e-02
106  real, parameter :: eos103 = -1.8507636718e-02
107  real, parameter :: eos013 = 3.7969820455e-01
108  real, parameter :: alp000 = -6.5025362670e-01
109  real, parameter :: alp100 = 1.6320471316
110  real, parameter :: alp200 = -2.0442606277
111  real, parameter :: alp300 = 1.4222011580
112  real, parameter :: alp400 = -4.4204535284e-01
113  real, parameter :: alp500 = 4.7983755487e-02
114  real, parameter :: alp010 = 1.8537085209
115  real, parameter :: alp110 = -3.0774129064
116  real, parameter :: alp210 = 3.0181275751
117  real, parameter :: alp310 = -1.4565010626
118  real, parameter :: alp410 = 2.7361846370e-01
119  real, parameter :: alp020 = -1.6246342147
120  real, parameter :: alp120 = 2.5086831352
121  real, parameter :: alp220 = -1.4787808849
122  real, parameter :: alp320 = 2.3807209899e-01
123  real, parameter :: alp030 = 8.3627885467e-01
124  real, parameter :: alp130 = -1.1311538584
125  real, parameter :: alp230 = 5.3563304045e-01
126  real, parameter :: alp040 = -6.7560904739e-02
127  real, parameter :: alp140 = -6.0212475204e-02
128  real, parameter :: alp050 = 2.8625353333e-02
129  real, parameter :: alp001 = 3.3340752782e-01
130  real, parameter :: alp101 = 1.1217528644e-01
131  real, parameter :: alp201 = -1.2510649515e-01
132  real, parameter :: alp301 = 1.6349760916e-02
133  real, parameter :: alp011 = -3.3540239802e-01
134  real, parameter :: alp111 = -1.7531540640e-01
135  real, parameter :: alp211 = 9.3976864981e-02
136  real, parameter :: alp021 = 1.8487252150e-01
137  real, parameter :: alp121 = 4.1307825959e-02
138  real, parameter :: alp031 = -5.5927935970e-02
139  real, parameter :: alp002 = -5.1410778748e-02
140  real, parameter :: alp102 = 5.3278413794e-03
141  real, parameter :: alp012 = 6.2099915132e-02
142  real, parameter :: alp003 = -9.4924551138e-03
143  real, parameter :: bet000 = 1.0783203594e+01
144  real, parameter :: bet100 = -4.4452095908e+01
145  real, parameter :: bet200 = 7.6048755820e+01
146  real, parameter :: bet300 = -6.3944280668e+01
147  real, parameter :: bet400 = 2.6890441098e+01
148  real, parameter :: bet500 = -4.5221697773
149  real, parameter :: bet010 = -8.1219372432e-01
150  real, parameter :: bet110 = 2.0346663041
151  real, parameter :: bet210 = -2.1232895170
152  real, parameter :: bet310 = 8.7994140485e-01
153  real, parameter :: bet410 = -1.1939638360e-01
154  real, parameter :: bet020 = 7.6574242289e-01
155  real, parameter :: bet120 = -1.5019813020
156  real, parameter :: bet220 = 1.0872489522
157  real, parameter :: bet320 = -2.7233429080e-01
158  real, parameter :: bet030 = -4.1615152308e-01
159  real, parameter :: bet130 = 4.9061350869e-01
160  real, parameter :: bet230 = -1.1847737788e-01
161  real, parameter :: bet040 = 1.4073062708e-01
162  real, parameter :: bet140 = -1.3327978879e-01
163  real, parameter :: bet050 = 5.9929880134e-03
164  real, parameter :: bet001 = -5.2937873009e-01
165  real, parameter :: bet101 = 1.2634116779
166  real, parameter :: bet201 = -1.1547328025
167  real, parameter :: bet301 = 3.2870876279e-01
168  real, parameter :: bet011 = -5.5824407214e-02
169  real, parameter :: bet111 = 1.2451933313e-01
170  real, parameter :: bet211 = -2.4409539932e-02
171  real, parameter :: bet021 = 4.3623149752e-02
172  real, parameter :: bet121 = -4.6767901790e-02
173  real, parameter :: bet031 = -6.8523260060e-03
174  real, parameter :: bet002 = -6.1618945251e-02
175  real, parameter :: bet102 = 6.2255521644e-02
176  real, parameter :: bet012 = -2.6514181169e-03
177  real, parameter :: bet003 = -2.3025968587e-04
178 
179 
180 
181 contains
182 
183 subroutine calculate_density_scalar_nemo(T, S, pressure, rho)
184 real, intent(in) :: T, S, pressure
185 real, intent(out) :: rho
186 ! * Arguments: T - conservative temperature in C. *
187 ! * (in) S - absoulte salinity in g/Kg. *
188 ! * (in) pressure - pressure in Pa. *
189 ! * (out) rho - in situ density in kg m-3. *
190 
191 ! *====================================================================*
192 ! * This subroutine computes the in situ density of sea water (rho in *
193 ! * units of kg/m^3) from absolute salinity (S in g/Kg), conservative *
194 ! * temperature (T in deg C), and pressure in Pa. *
195 ! *====================================================================*
196 
197  real :: al0, p0, lambda
198  integer :: j
199  real, dimension(1) :: T0, S0, pressure0
200  real, dimension(1) :: rho0
201 
202  t0(1) = t
203  s0(1) = s
204  pressure0(1) = pressure
205 
206  call calculate_density_array_nemo(t0, s0, pressure0, rho0, 1, 1)
207  rho = rho0(1)
208 end subroutine calculate_density_scalar_nemo
209 !> This subroutine computes the in situ density of sea water (rho in
210 !! units of kg/m^3) from absolute salinity (S in g/Kg),
211 !! conservative temperature (T in deg C), and pressure in Pa.
212 subroutine calculate_density_array_nemo(T, S, pressure, rho, start, npts)
213  real, intent(in), dimension(:) :: T !< Conservative temperature in C.
214  real, intent(in), dimension(:) :: S !< Absoulte salinity in g/Kg.
215  real, intent(in), dimension(:) :: pressure !< Pressure in Pa.
216  real, intent(out), dimension(:) :: rho !< In situ density in kg m-3.
217  integer, intent(in) :: start !< The starting point in the arrays.
218  integer, intent(in) :: npts !< The number of values to calculate.
219 
220 ! * Arguments: T - conservative temperature in C. *
221 ! * (in) S - absoulte salinity in g/Kg. *
222 ! * (in) pressure - pressure in Pa. *
223 ! * (out) rho - in situ density in kg m-3. *
224 ! * (in) start - the starting point in the arrays. *
225 ! * (in) npts - the number of values to calculate. *
226 
227 ! *====================================================================*
228 ! * This subroutine computes the in situ density of sea water (rho in *
229 ! * units of kg/m^3) from absolute salinity (S in g/Kg), *
230 ! * conservative temperature (T in deg C), and pressure in Pa. *
231 ! *====================================================================*
232  real :: zp,zt , zh , zs , zr0, zn , zn0, zn1, zn2, zn3
233  integer :: j
234 
235  do j=start,start+npts-1
236  !Conversions
237  zs = s(j) !gsw_sr_from_sp(S(j)) !Convert practical salinity to absolute salinity
238  zt = t(j) !gsw_ct_from_pt(S(j),T(j)) !Convert potantial temp to conservative temp
239  zp = pressure(j)* pa2db !Convert pressure from Pascal to decibar
240 
241  !The following algorithm was provided by Roquet in a private communication.
242  !It is not necessarily the algorithm used in NEMO ocean!
243  zp = zp * r1_p0 !pressure
244  zt = zt * r1_t0 !temperature
245  zs = sqrt( abs( zs + rdeltas ) * r1_s0 ) ! square root salinity
246  !
247  zn3 = eos013*zt &
248  & + eos103*zs+eos003
249  !
250  zn2 = (eos022*zt &
251  & + eos112*zs+eos012)*zt &
252  & + (eos202*zs+eos102)*zs+eos002
253  !
254  zn1 = (((eos041*zt &
255  & + eos131*zs+eos031)*zt &
256  & + (eos221*zs+eos121)*zs+eos021)*zt &
257  & + ((eos311*zs+eos211)*zs+eos111)*zs+eos011)*zt &
258  & + (((eos401*zs+eos301)*zs+eos201)*zs+eos101)*zs+eos001
259  !
260  zn0 = (((((eos060*zt &
261  & + eos150*zs+eos050)*zt &
262  & + (eos240*zs+eos140)*zs+eos040)*zt &
263  & + ((eos330*zs+eos230)*zs+eos130)*zs+eos030)*zt &
264  & + (((eos420*zs+eos320)*zs+eos220)*zs+eos120)*zs+eos020)*zt &
265  & + ((((eos510*zs+eos410)*zs+eos310)*zs+eos210)*zs+eos110)*zs+eos010)*zt &
266  & + (((((eos600*zs+eos500)*zs+eos400)*zs+eos300)*zs+eos200)*zs+eos100)*zs+eos000
267  !
268  zn = ( ( zn3 * zp + zn2 ) * zp + zn1 ) * zp + zn0
269  !
270  zr0 = (((((r05 * zp+r04) * zp+r03 ) * zp+r02 ) * zp+r01) * zp+r00) * zp
271  !
272  rho(j) = ( zn + zr0 ) ! density
273 
274  enddo
275 end subroutine calculate_density_array_nemo
276 
277 subroutine calculate_density_derivs_nemo(T, S, pressure, drho_dT, drho_dS, start, npts)
278  real, intent(in), dimension(:) :: T !< Conservative temperature in C.
279  real, intent(in), dimension(:) :: S !< Absolute salinity in g/kg.
280  real, intent(in), dimension(:) :: pressure !< Pressure in Pa.
281  real, intent(out), dimension(:) :: drho_dT !< The partial derivative of density with potential
282  !! temperature, in kg m-3 K-1.
283  real, intent(out), dimension(:) :: drho_dS !< The partial derivative of density with salinity,
284  !! in kg m-3 psu-1.
285  integer, intent(in) :: start !< The starting point in the arrays.
286  integer, intent(in) :: npts !< The number of values to calculate.
287 ! * Arguments: T - conservative temperature in C. *
288 ! * (in) S - absolute salinity in g/kg. *
289 ! * (in) pressure - pressure in Pa. *
290 ! * (out) drho_dT - the partial derivative of density with *
291 ! * potential temperature, in kg m-3 K-1. *
292 ! * (out) drho_dS - the partial derivative of density with *
293 ! * salinity, in kg m-3 psu-1. *
294 ! * (in) start - the starting point in the arrays. *
295 ! * (in) npts - the number of values to calculate. *
296  real :: zp,zt , zh , zs , zr0, zn , zn0, zn1, zn2, zn3
297  integer :: j
298 
299  do j=start,start+npts-1
300  !Conversions
301  zs = s(j) !gsw_sr_from_sp(S(j)) !Convert practical salinity to absolute salinity
302  zt = t(j) !gsw_ct_from_pt(S(j),T(j)) !Convert potantial temp to conservative temp
303  zp = pressure(j)* pa2db !Convert pressure from Pascal to decibar
304 
305  !The following algorithm was provided by Roquet in a private communication.
306  !It is not necessarily the algorithm used in NEMO ocean!
307  zp = zp * r1_p0 ! pressure (first converted to decibar)
308  zt = zt * r1_t0 ! temperature
309  zs = sqrt( abs( zs + rdeltas ) * r1_s0 ) ! square root salinity
310  !
311  ! alpha
312  zn3 = alp003
313  !
314  zn2 = alp012*zt + alp102*zs+alp002
315  !
316  zn1 = ((alp031*zt &
317  & + alp121*zs+alp021)*zt &
318  & + (alp211*zs+alp111)*zs+alp011)*zt &
319  & + ((alp301*zs+alp201)*zs+alp101)*zs+alp001
320  !
321  zn0 = ((((alp050*zt &
322  & + alp140*zs+alp040)*zt &
323  & + (alp230*zs+alp130)*zs+alp030)*zt &
324  & + ((alp320*zs+alp220)*zs+alp120)*zs+alp020)*zt &
325  & + (((alp410*zs+alp310)*zs+alp210)*zs+alp110)*zs+alp010)*zt &
326  & + ((((alp500*zs+alp400)*zs+alp300)*zs+alp200)*zs+alp100)*zs+alp000
327  !
328  zn = ( ( zn3 * zp + zn2 ) * zp + zn1 ) * zp + zn0
329  !
330  drho_dt(j) = -zn
331  !
332  ! beta
333  !
334  zn3 = bet003
335  !
336  zn2 = bet012*zt + bet102*zs+bet002
337  !
338  zn1 = ((bet031*zt &
339  & + bet121*zs+bet021)*zt &
340  & + (bet211*zs+bet111)*zs+bet011)*zt &
341  & + ((bet301*zs+bet201)*zs+bet101)*zs+bet001
342  !
343  zn0 = ((((bet050*zt &
344  & + bet140*zs+bet040)*zt &
345  & + (bet230*zs+bet130)*zs+bet030)*zt &
346  & + ((bet320*zs+bet220)*zs+bet120)*zs+bet020)*zt &
347  & + (((bet410*zs+bet310)*zs+bet210)*zs+bet110)*zs+bet010)*zt &
348  & + ((((bet500*zs+bet400)*zs+bet300)*zs+bet200)*zs+bet100)*zs+bet000
349  !
350  zn = ( ( zn3 * zp + zn2 ) * zp + zn1 ) * zp + zn0
351  !
352  drho_ds(j) = zn / zs
353  enddo
354 
355 end subroutine calculate_density_derivs_nemo
356 
357 subroutine calculate_compress_nemo(T, S, pressure, rho, drho_dp, start, npts)
358  real, intent(in), dimension(:) :: T !< Conservative temperature in C.
359  real, intent(in), dimension(:) :: S !< Absolute salinity in g/kg.
360  real, intent(in), dimension(:) :: pressure !< Pressure in Pa.
361  real, intent(out), dimension(:) :: rho !< In situ density in kg m-3.
362  real, intent(out), dimension(:) :: drho_dp !< The partial derivative of density with pressure
363  !! (also the inverse of the square of sound speed)
364  !! in s2 m-2.
365  integer, intent(in) :: start !< The starting point in the arrays.
366  integer, intent(in) :: npts !< The number of values to calculate.
367 ! * Arguments: T - conservative temperature in C. *
368 ! * (in) S - absolute salinity in g/kg. *
369 ! * (in) pressure - pressure in Pa. *
370 ! * (out) rho - in situ density in kg m-3. *
371 ! * (out) drho_dp - the partial derivative of density with *
372 ! * pressure (also the inverse of the square of *
373 ! * sound speed) in s2 m-2. *
374 ! * (in) start - the starting point in the arrays. *
375 ! * (in) npts - the number of values to calculate. *
376 ! *====================================================================*
377  real :: zs,zt,zp
378  integer :: j
379 
380  call calculate_density_array_nemo(t, s, pressure, rho, start, npts)
381  !
382  !NOTE: The following calculates the TEOS10 approximation to compressibility
383  ! since the corresponding NEMO approximation is not available yet.
384  !
385  do j=start,start+npts-1
386  !Conversions
387  zs = s(j) !gsw_sr_from_sp(S(j)) !Convert practical salinity to absolute salinity
388  zt = t(j) !gsw_ct_from_pt(S(j),T(j)) !Convert potantial temp to conservative temp
389  zp = pressure(j)* pa2db !Convert pressure from Pascal to decibar
390  call gsw_rho_first_derivatives(zs,zt,zp, drho_dp=drho_dp(j))
391  enddo
392 end subroutine calculate_compress_nemo
393 
394 end module mom_eos_nemo
real, parameter bet012
real, parameter alp010
real, parameter alp021
real, parameter bet031
real, parameter alp003
real, parameter alp012
real, parameter alp050
real, parameter eos022
real, parameter bet230
real, parameter eos102
real, parameter bet002
real, parameter eos060
real, parameter eos112
real, parameter bet111
real, parameter eos031
real, parameter eos130
real, parameter eos013
real, parameter eos003
real, parameter alp301
real, parameter eos500
real, parameter bet410
real, parameter eos300
real, parameter eos050
real, parameter eos211
real, parameter eos330
real, parameter bet011
real, parameter alp002
real, parameter bet010
real, parameter eos210
real, parameter bet500
real, parameter bet021
real, parameter alp030
real, parameter alp101
real, parameter bet210
real, parameter bet100
real, parameter eos103
real, parameter eos200
real, parameter alp001
real, parameter bet121
real, parameter alp100
real, parameter eos600
real, parameter eos510
real, parameter eos012
real, parameter alp110
real, parameter r1_s0
real, parameter r04
subroutine, public calculate_density_array_nemo(T, S, pressure, rho, start, npts)
This subroutine computes the in situ density of sea water (rho in units of kg/m^3) from absolute sali...
real, parameter alp040
real, parameter r01
real, parameter alp102
real, parameter eos011
real, parameter alp130
real, parameter eos120
real, parameter alp230
real, parameter bet001
real, parameter alp031
subroutine, public calculate_density_derivs_nemo(T, S, pressure, drho_dT, drho_dS, start, npts)
real, parameter bet211
real, parameter r03
real, parameter r00
real, parameter bet301
real, parameter bet400
real, parameter alp220
real, parameter eos320
real, parameter eos150
real, parameter r02
real, parameter bet000
real, parameter pa2db
real, parameter eos410
real, parameter bet140
real, parameter bet110
real, parameter eos221
real, parameter bet220
real, parameter eos020
real, parameter eos111
subroutine, public calculate_compress_nemo(T, S, pressure, rho, drho_dp, start, npts)
real, parameter eos100
real, parameter rdeltas
real, parameter eos101
real, parameter r1_p0
real, parameter r1_t0
real, parameter alp120
real, parameter eos010
real, parameter bet201
subroutine, public calculate_density_scalar_nemo(T, S, pressure, rho)
real, parameter bet101
real, parameter alp111
real, parameter bet030
real, parameter eos230
real, parameter eos401
real, parameter eos301
real, parameter alp121
real, parameter alp210
real, parameter alp011
real, parameter eos030
real, parameter alp200
real, parameter r05
real, parameter alp140
real, parameter eos311
real, parameter bet200
real, parameter alp310
real, parameter eos220
real, parameter alp000
real, parameter alp400
real, parameter eos240
real, parameter eos420
real, parameter eos201
real, parameter bet320
real, parameter bet130
real, parameter eos131
real, parameter eos400
real, parameter bet102
real, parameter alp320
real, parameter bet300
real, parameter alp500
real, parameter eos110
real, parameter bet020
real, parameter alp300
real, parameter bet040
real, parameter eos021
real, parameter bet120
real, parameter bet003
real, parameter eos202
real, parameter eos002
real, parameter alp211
real, parameter eos000
real, parameter eos140
real, parameter alp410
real, parameter bet310
real, parameter eos001
real, parameter eos310
real, parameter alp201
real, parameter alp020
real, parameter eos121
real, parameter eos040
real, parameter bet050
real, parameter eos041