FV3 Bundle
gsw_ct_from_rho.f90
Go to the documentation of this file.
1 !==========================================================================
2 elemental subroutine gsw_ct_from_rho (rho, sa, p, ct, ct_multiple)
3 ! =========================================================================
4 !
5 ! Calculates the Conservative Temperature of a seawater sample, for given
6 ! values of its density, Absolute Salinity and sea pressure (in dbar).
7 !
8 ! rho = density of a seawater sample (e.g. 1026 kg/m^3) [ kg/m^3 ]
9 ! Note. This input has not had 1000 kg/m^3 subtracted from it.
10 ! That is, it is 'density', not 'density anomaly'.
11 ! SA = Absolute Salinity [ g/kg ]
12 ! p = sea pressure [ dbar ]
13 ! ( i.e. absolute pressure - 10.1325 dbar )
14 !
15 ! CT = Conservative Temperature (ITS-90) [ deg C ]
16 ! CT_multiple = Conservative Temperature (ITS-90) [ deg C ]
17 ! Note that at low salinities, in brackish water, there are two possible
18 ! Conservative Temperatures for a single density. This programme will
19 ! output both valid solutions. To see this second solution the user
20 ! must call the programme with two outputs (i.e. [CT,CT_multiple]), if
21 ! there is only one possible solution and the programme has been
22 ! called with two outputs the second variable will be set to NaN.
23 !--------------------------------------------------------------------------
24 
27 
29 
30 use gsw_mod_kinds
31 
32 implicit none
33 
34 real (r8), intent(in) :: rho, sa, p
35 real (r8), intent(out) :: ct
36 real (r8), intent(out), optional :: ct_multiple
37 
38 integer :: number_of_iterations
39 real (r8) :: a, alpha_freezing, alpha_mean, b, c, ct_a, ct_b, ct_diff
40 real (r8) :: ct_freezing, ct_max_rho, ct_mean, ct_old
41 real (r8) :: delta_ct, delta_v, factor, factorqa, factorqb
42 real (r8) :: rho_40, rho_extreme, rho_freezing, rho_max, rho_mean
43 real (r8) :: rho_old, sqrt_disc, top, v_ct, v_lab
44 
45 character (*), parameter :: func_name = "gsw_ct_from_rho"
46 
47 ! alpha_limit is the positive value of the thermal expansion coefficient
48 ! which is used at the freezing temperature to distinguish between
49 ! salty and fresh water.
50 real (r8), parameter :: alpha_limit = 1e-5_r8
51 
52 ! rec_half_rho_TT is a constant representing the reciprocal of half the
53 ! second derivative of density with respect to temperature near the
54 ! temperature of maximum density.
55 real (r8), parameter :: rec_half_rho_tt = -110.0_r8
56 
57 rho_40 = gsw_rho(sa,40.0_r8,p)
58 if (rho .lt. rho_40) then
59  ct = gsw_error_code(1,func_name)
60  if (present(ct_multiple)) ct_multiple = ct
61  return
62 end if
63 
64 ct_max_rho = gsw_ct_maxdensity(sa,p)
65 rho_max = gsw_rho(sa,ct_max_rho,p)
66 rho_extreme = rho_max
67 
68 ! Assumes that the seawater is always unsaturated with air
69 ct_freezing = gsw_ct_freezing_poly(sa,p,0.0_r8)
70 
71 call gsw_rho_alpha_beta(sa,ct_freezing,p,rho=rho_freezing,alpha=alpha_freezing)
72 
73 ! reset the extreme values
74 if (ct_freezing .gt. ct_max_rho) rho_extreme = rho_freezing
75 
76 if (rho .gt. rho_extreme) then
77  ct = gsw_error_code(2,func_name)
78  if (present(ct_multiple)) ct_multiple = ct
79  return
80 end if
81 
82 if (alpha_freezing .gt. alpha_limit) then
83 
84  ct_diff = 40.0_r8 - ct_freezing
85  top = rho_40 - rho_freezing + rho_freezing*alpha_freezing*ct_diff
86  a = top/(ct_diff*ct_diff)
87  b = -rho_freezing*alpha_freezing
88  c = rho_freezing - rho
89  sqrt_disc = sqrt(b*b - 4*a*c)
90  ct = ct_freezing + 0.5_r8*(-b - sqrt_disc)/a
91 
92 else
93 
94  ct_diff = 40.0_r8 - ct_max_rho
95  factor = (rho_max - rho)/(rho_max - rho_40)
96  delta_ct = ct_diff*sqrt(factor)
97 
98  if (delta_ct .gt. 5.0_r8) then
99 
100  ct = ct_max_rho + delta_ct
101 
102  else
103 
104  ! Set the initial value of the quadratic solution roots.
105  ct_a = ct_max_rho + sqrt(rec_half_rho_tt*(rho - rho_max))
106  do number_of_iterations = 1, 7
107  ct_old = ct_a
108  rho_old = gsw_rho(sa,ct_old,p)
109  factorqa = (rho_max - rho)/(rho_max - rho_old)
110  ct_a = ct_max_rho + (ct_old - ct_max_rho)*sqrt(factorqa)
111  end do
112 
113  if (ct_freezing - ct_a .lt. 0.0_r8) then
114  ct = gsw_error_code(3,func_name)
115  if (present(ct_multiple)) ct_multiple = ct
116  return
117  end if
118 
119  ct = ct_a
120  if (.not. present(ct_multiple)) return
121 
122  ! Set the initial value of the quadratic solution roots.
123  ct_b = ct_max_rho - sqrt(rec_half_rho_tt*(rho - rho_max))
124  do number_of_iterations = 1, 7
125  ct_old = ct_b
126  rho_old = gsw_rho(sa,ct_old,p)
127  factorqb = (rho_max - rho)/(rho_max - rho_old)
128  ct_b = ct_max_rho + (ct_old - ct_max_rho)*sqrt(factorqb)
129  end do
130 
131  ! After seven iterations of this quadratic iterative procedure,
132  ! the error in rho is no larger than 4.6x10^-13 kg/m^3.
133 
134  if (ct_freezing - ct_b .lt. 0.0_r8) then
135  ct = gsw_error_code(4,func_name)
136  if (present(ct_multiple)) ct_multiple = ct
137  return
138  end if
139 
140  ct_multiple = ct_b
141  return
142 
143  end if
144 
145 end if
146 
147 ! Begin the modified Newton-Raphson iterative method
148 
149 v_lab = 1.0_r8/rho
150 call gsw_rho_alpha_beta(sa,ct,p,rho=rho_mean,alpha=alpha_mean)
151 v_ct = alpha_mean/rho_mean
152 
153 do number_of_iterations = 1, 3
154  ct_old = ct
155  delta_v = gsw_specvol(sa,ct_old,p) - v_lab
156  ct = ct_old - delta_v/v_ct
157  ct_mean = 0.5_r8*(ct + ct_old)
158  call gsw_rho_alpha_beta(sa,ct_mean,p,rho=rho_mean,alpha=alpha_mean)
159  v_ct = alpha_mean/rho_mean
160  ct = ct_old - delta_v/v_ct
161 end do
162 
163 ! After three iterations of this modified Newton-Raphson iteration,
164 ! the error in rho is no larger than 1.6x10^-12 kg/m^3.
165 
166 if (present(ct_multiple)) ct_multiple = gsw_error_code(5,func_name)
167 
168 return
169 end subroutine
170 
171 !--------------------------------------------------------------------------
real(r8), parameter, public gsw_error_limit
elemental subroutine gsw_ct_from_rho(rho, sa, p, ct, ct_multiple)
elemental real(r8) function, public gsw_error_code(err_num, func_name, error_code)