FV3 Bundle
gsw_frazil_properties.f90
Go to the documentation of this file.
1 !==========================================================================
2 elemental subroutine gsw_frazil_properties (sa_bulk, h_bulk, p, &
3  sa_final, ct_final, w_ih_final)
4 !==========================================================================
5 !
6 ! Calculates the mass fraction of ice (mass of ice divided by mass of ice
7 ! plus seawater), w_Ih_final, which results from given values of the bulk
8 ! Absolute Salinity, SA_bulk, bulk enthalpy, h_bulk, occuring at pressure
9 ! p. The final values of Absolute Salinity, SA_final, and Conservative
10 ! Temperature, CT_final, of the interstitial seawater phase are also
11 ! returned. This code assumes that there is no dissolved air in the
12 ! seawater (that is, saturation_fraction is assumed to be zero
13 ! throughout the code).
14 !
15 ! When the mass fraction w_Ih_final is calculated as being a positive
16 ! value, the seawater-ice mixture is at thermodynamic equlibrium.
17 !
18 ! This code returns w_Ih_final = 0 when the input bulk enthalpy, h_bulk,
19 ! is sufficiently large (i.e. sufficiently "warm") so that there is no ice
20 ! present in the final state. In this case the final state consists of
21 ! only seawater rather than being an equlibrium mixture of seawater and
22 ! ice which occurs when w_Ih_final is positive. Note that when
23 ! w_Ih_final = 0, the final seawater is not at the freezing temperature.
24 !
25 ! SA_bulk = bulk Absolute Salinity of the seawater and ice mixture
26 ! [ g/kg ]
27 ! h_bulk = bulk enthalpy of the seawater and ice mixture [ J/kg ]
28 ! p = sea pressure [ dbar ]
29 ! ( i.e. absolute pressure - 10.1325 dbar )
30 !
31 ! SA_final = Absolute Salinity of the seawater in the final state,
32 ! whether or not any ice is present. [ g/kg ]
33 ! CT_final = Conservative Temperature of the seawater in the the final
34 ! state, whether or not any ice is present. [ deg C ]
35 ! w_Ih_final = mass fraction of ice in the final seawater-ice mixture.
36 ! If this ice mass fraction is positive, the system is at
37 ! thermodynamic equilibrium. If this ice mass fraction is
38 ! zero there is no ice in the final state which consists
39 ! only of seawater which is warmer than the freezing
40 ! temperature. [unitless]
41 !--------------------------------------------------------------------------
42 
49 
51 
52 use gsw_mod_kinds
53 
54 implicit none
55 
56 real (r8), intent(in) :: sa_bulk, h_bulk, p
57 real (r8), intent(out) :: sa_final, ct_final, w_ih_final
58 
59 integer :: number_of_iterations
60 real (r8) :: cp_ih, ctf_sa, ctf, dfunc_dw_ih, dfunc_dw_ih_mean_poly
61 real (r8) :: func, func0, hf, h_hat_ct, h_hat_sa
62 real (r8) :: h_ihf, sa, tf_sa, tf, w_ih_mean, w_ih_old, w_ih
63 
64 ! Throughout this code seawater is taken to contain no dissolved air.
65 real (r8), parameter :: saturation_fraction = 0.0_r8
66 
67 real (r8), parameter :: num_f = 5.0e-2_r8
68 real (r8), parameter :: num_f2 = 6.9e-7_r8
69 real (r8), parameter :: num_p = 2.21_r8
70 
71 character (*), parameter :: func_name = "gsw_frazil_properties"
72 
73 !--------------------------------------------------------------------------
74 ! Finding func0
75 !--------------------------------------------------------------------------
76 ctf = gsw_ct_freezing_exact(sa_bulk,p,saturation_fraction)
77 func0 = h_bulk - gsw_enthalpy_ct_exact(sa_bulk,ctf,p)
78 
79 !--------------------------------------------------------------------------
80 ! When func0 is zero or positive we can immediately calculate the three
81 ! outputs, as the bulk enthalpy, h_bulk, is too large to allow any ice
82 ! at thermodynamic equilibrium. The result will be (warm) seawater with no
83 ! frazil ice being present. The three outputs can be set and the rest of
84 ! this code does not need to be performed.
85 !--------------------------------------------------------------------------
86 if (func0 .ge. 0.0_r8) then
87  sa_final = sa_bulk
88  ct_final = gsw_ct_from_enthalpy_exact(sa_bulk,h_bulk,p)
89  w_ih_final = 0.0_r8
90  return
91 endif
92 
93 !--------------------------------------------------------------------------
94 ! Begin to find the solution for those data points that have func0 < 0,
95 ! implying that the output will be a positive ice mass fraction w_Ih_final.
96 !
97 ! Do a quasi-Newton step with a separate polynomial estimate of the
98 ! derivative of func with respect to the ice mass fraction. This section
99 ! of the code delivers initial values of both w_Ih and SA to the rest
100 ! of the more formal modified Newtons Method approach of McDougall and
101 ! Wotherspoon (2014).
102 !--------------------------------------------------------------------------
103 dfunc_dw_ih_mean_poly = 3.347814e+05_r8 &
104  - num_f*func0*(1.0_r8 + num_f2*func0) - num_p*p
105 w_ih = min(-func0/dfunc_dw_ih_mean_poly, 0.95_r8)
106 sa = sa_bulk/(1.0_r8 - w_ih)
107 if (sa .lt. 0.0_r8 .or. sa .gt. 120.0_r8) then
108  sa_final = gsw_error_code(1,func_name)
109  ct_final = sa_final
110  w_ih_final = sa_final
111  return
112 endif
113 
114 !--------------------------------------------------------------------------
115 ! Calculating the estimate of the derivative of func, dfunc_dw_Ih, to be
116 ! fed into the iterative Newton's Method.
117 !--------------------------------------------------------------------------
118 ctf = gsw_ct_freezing_exact(sa,p,saturation_fraction)
119 hf = gsw_enthalpy_ct_exact(sa,ctf,p)
120 tf = gsw_t_freezing_exact(sa,p,saturation_fraction)
121 h_ihf = gsw_enthalpy_ice(tf,p)
122 cp_ih = gsw_cp_ice(tf,p)
123 call gsw_enthalpy_first_derivatives_ct_exact(sa,ctf,p,h_hat_sa,h_hat_ct)
124 call gsw_ct_freezing_first_derivatives(sa,p,saturation_fraction,ctf_sa)
125 call gsw_t_freezing_first_derivatives(sa,p,saturation_fraction,tf_sa)
126 
127 dfunc_dw_ih = hf - h_ihf &
128  - sa*(h_hat_sa + h_hat_ct*ctf_sa + w_ih*cp_ih*tf_sa/(1.0_r8 - w_ih))
129 
130 !--------------------------------------------------------------------------
131 ! Enter the main McDougall-Wotherspoon (2014) modified Newton-Raphson loop
132 !--------------------------------------------------------------------------
133 do number_of_iterations = 1, 3
134 
135  if (number_of_iterations .gt. 1) then
136  ! on the first iteration these values are already known
137  ctf = gsw_ct_freezing_exact(sa,p,saturation_fraction)
138  hf = gsw_enthalpy_ct_exact(sa,ctf,p)
139  tf = gsw_t_freezing_exact(sa,p,saturation_fraction)
140  h_ihf = gsw_enthalpy_ice(tf,p)
141  end if
142 
143  func = h_bulk - (1.0_r8 - w_ih)*hf - w_ih*h_ihf
144 
145  w_ih_old = w_ih
146  w_ih = w_ih_old - func/dfunc_dw_ih
147  w_ih_mean = 0.5_r8*(w_ih + w_ih_old)
148 
149  if (w_ih_mean .gt. 0.9_r8) then
150  ! This ensures that the mass fraction of ice never exceeds 0.9
151  sa_final = gsw_error_code(1+number_of_iterations,func_name)
152  ct_final = sa_final
153  w_ih_final = sa_final
154  return
155  endif
156 
157  sa = sa_bulk/(1.0_r8 - w_ih_mean)
158  ctf = gsw_ct_freezing_exact(sa,p,saturation_fraction)
159  hf = gsw_enthalpy_ct_exact(sa,ctf,p)
160  tf = gsw_t_freezing_exact(sa,p,saturation_fraction)
161  h_ihf = gsw_enthalpy_ice(tf,p)
162  cp_ih = gsw_cp_ice(tf,p)
163  call gsw_enthalpy_first_derivatives_ct_exact(sa,ctf,p,h_hat_sa,h_hat_ct)
164  call gsw_ct_freezing_first_derivatives(sa,p,saturation_fraction,ctf_sa)
165  call gsw_t_freezing_first_derivatives(sa,p,saturation_fraction,tf_sa)
166 
167  dfunc_dw_ih = hf - h_ihf - sa*(h_hat_sa + h_hat_ct*ctf_sa &
168  + w_ih_mean*cp_ih*tf_sa/(1.0_r8 - w_ih_mean))
169 
170  w_ih = w_ih_old - func/dfunc_dw_ih
171 
172  if (w_ih .gt. 0.9_r8) then
173  ! This ensures that the mass fraction of ice never exceeds 0.9
174  sa_final = gsw_error_code(4+number_of_iterations,func_name)
175  ct_final = sa_final
176  w_ih_final = sa_final
177  return
178  endif
179 
180  sa = sa_bulk/(1.0_r8 - w_ih)
181 end do
182 
183 sa_final = sa
184 ct_final = gsw_ct_freezing_exact(sa,p,saturation_fraction)
185 w_ih_final = w_ih
186 
187 if (w_ih_final .lt. 0.0_r8) then
188  ! This will only trap cases that are smaller than zero by just
189  ! machine precision
190  sa_final = sa_bulk
191  ct_final = gsw_ct_from_enthalpy_exact(sa_final,h_bulk,p)
192  w_ih_final = 0.0_r8
193 end if
194 
195 return
196 end subroutine
197 
198 !--------------------------------------------------------------------------
elemental subroutine gsw_frazil_properties(sa_bulk, h_bulk, p, sa_final, ct_final, w_ih_final)
real(r8), parameter, public gsw_error_limit
#define min(a, b)
Definition: mosaic_util.h:32
elemental real(r8) function, public gsw_error_code(err_num, func_name, error_code)