Line data Source code
1 : module icepack_mushy_physics
2 :
3 : use icepack_kinds
4 : use icepack_parameters, only: c0, c1, c2, c4, c1000
5 : use icepack_parameters, only: puny
6 : use icepack_parameters, only: rhow, rhoi, rhos, cp_ocn, cp_ice, Lfresh
7 : use icepack_parameters, only: ksno
8 : use icepack_warnings, only: warnstr, icepack_warnings_add
9 : use icepack_warnings, only: icepack_warnings_setabort, icepack_warnings_aborted
10 :
11 : implicit none
12 :
13 : private
14 : public :: &
15 : conductivity_mush_array, &
16 : conductivity_snow_array, &
17 : enthalpy_snow, &
18 : enthalpy_brine, &
19 : enthalpy_mush, &
20 : enthalpy_mush_liquid_fraction, &
21 : enthalpy_of_melting, &
22 : temperature_snow, &
23 : icepack_mushy_temperature_mush, &
24 : temperature_mush_liquid_fraction, &
25 : liquidus_brine_salinity_mush, &
26 : liquidus_temperature_mush, &
27 : icepack_mushy_liquid_fraction, &
28 : icepack_mushy_density_brine
29 :
30 : !-----------------------------------------------------------------
31 : ! Constants for Liquidus relation from Assur (1958)
32 : !-----------------------------------------------------------------
33 :
34 : ! liquidus relation - higher temperature region
35 : real(kind=dbl_kind), parameter :: &
36 : az1_liq = -18.48_dbl_kind, &
37 : bz1_liq = 0.0_dbl_kind
38 :
39 : ! liquidus relation - lower temperature region
40 : real(kind=dbl_kind), parameter :: &
41 : az2_liq = -10.3085_dbl_kind, &
42 : bz2_liq = 62.4_dbl_kind
43 :
44 : ! liquidus break
45 : real(kind=dbl_kind), parameter :: &
46 : Tb_liq = -7.6362968855167352_dbl_kind, & ! temperature of liquidus break
47 : Sb_liq = 123.66702800276086_dbl_kind ! salinity of liquidus break
48 :
49 : ! basic liquidus relation constants
50 : real(kind=dbl_kind), parameter :: &
51 : az1p_liq = az1_liq / c1000, &
52 : bz1p_liq = bz1_liq / c1000, &
53 : az2p_liq = az2_liq / c1000, &
54 : bz2p_liq = bz2_liq / c1000
55 :
56 : !-----------------------------------------------------------------
57 : ! Other parameters
58 : !-----------------------------------------------------------------
59 :
60 : real(kind=dbl_kind), parameter :: &
61 : ki = 2.3_dbl_kind , & ! fresh ice conductivity (W m-1 K-1)
62 : kb = 0.5375_dbl_kind ! brine conductivity (W m-1 K-1)
63 :
64 : !=======================================================================
65 :
66 : contains
67 :
68 : !=======================================================================
69 : ! Physical Quantities
70 : !=======================================================================
71 :
72 3172532 : subroutine conductivity_mush_array(nilyr, zqin, zSin, km)
73 :
74 : ! detemine the conductivity of the mush from enthalpy and salinity
75 :
76 : integer (kind=int_kind), intent(in) :: &
77 : nilyr ! number of ice layers
78 :
79 : real(kind=dbl_kind), dimension(:), intent(in) :: &
80 : zqin, & ! ice layer enthalpy (J m-3)
81 : zSin ! ice layer bulk salinity (ppt)
82 :
83 : real(kind=dbl_kind), dimension(:), intent(out) :: &
84 : km ! ice layer conductivity (W m-1 K-1)
85 :
86 : integer(kind=int_kind) :: &
87 : k ! ice layer index
88 :
89 1064186 : real(kind=dbl_kind) :: Tmush
90 :
91 : character(len=*),parameter :: subname='(conductivity_mush_array)'
92 :
93 25380256 : do k = 1, nilyr
94 :
95 22207724 : Tmush = icepack_mushy_temperature_mush(zqin(k), zSin(k))
96 :
97 25380256 : km(k) = heat_conductivity(Tmush, zSin(k))
98 :
99 : enddo ! k
100 :
101 3172532 : end subroutine conductivity_mush_array
102 :
103 : !=======================================================================
104 :
105 65469212 : function icepack_mushy_density_brine(Sbr) result(rho)
106 :
107 : ! density of brine from brine salinity
108 :
109 : real(kind=dbl_kind), intent(in) :: &
110 : Sbr ! brine salinity (ppt)
111 :
112 : real(kind=dbl_kind) :: &
113 : rho ! brine density (kg m-3)
114 :
115 : real(kind=dbl_kind), parameter :: &
116 : a = 1000.3_dbl_kind , & ! zeroth empirical coefficient
117 : b = 0.78237_dbl_kind , & ! linear empirical coefficient
118 : c = 2.8008e-4_dbl_kind ! quadratic empirical coefficient
119 :
120 : character(len=*),parameter :: subname='(icepack_mushy_density_brine)'
121 :
122 65469212 : rho = a + b * Sbr + c * Sbr**2
123 :
124 65469212 : end function icepack_mushy_density_brine
125 :
126 : !=======================================================================
127 : ! Snow
128 : !=======================================================================
129 :
130 2550448 : subroutine conductivity_snow_array(ks)
131 :
132 : ! heat conductivity of the snow
133 :
134 : real(kind=dbl_kind), dimension(:), intent(out) :: &
135 : ks ! snow layer conductivity (W m-1 K-1)
136 :
137 : character(len=*),parameter :: subname='(conductivity_snow_array)'
138 :
139 5100896 : ks = ksno
140 :
141 2550448 : end subroutine conductivity_snow_array
142 :
143 : !=======================================================================
144 :
145 5271794 : function enthalpy_snow(zTsn) result(zqsn)
146 :
147 : ! enthalpy of snow from snow temperature
148 :
149 : real(kind=dbl_kind), intent(in) :: &
150 : zTsn ! snow layer temperature (C)
151 :
152 : real(kind=dbl_kind) :: &
153 : zqsn ! snow layer enthalpy (J m-3)
154 :
155 : character(len=*),parameter :: subname='(enthalpy_snow)'
156 :
157 5271794 : zqsn = -rhos * (-cp_ice * zTsn + Lfresh)
158 :
159 5271794 : end function enthalpy_snow
160 :
161 : !=======================================================================
162 :
163 6780877 : function temperature_snow(zqsn) result(zTsn)
164 :
165 : ! temperature of snow from the snow enthalpy
166 :
167 : real(kind=dbl_kind), intent(in) :: &
168 : zqsn ! snow layer enthalpy (J m-3)
169 :
170 : real(kind=dbl_kind) :: &
171 : zTsn, & ! snow layer temperature (C)
172 1648965 : A, B
173 :
174 : character(len=*),parameter :: subname='(temperature_snow)'
175 :
176 5131912 : A = c1 / (rhos * cp_ice)
177 5131912 : B = Lfresh / cp_ice
178 5131912 : zTsn = A * zqsn + B
179 :
180 5131912 : end function temperature_snow
181 :
182 : !=======================================================================
183 : ! Mushy Layer Formulation - Assur (1958) liquidus
184 : !=======================================================================
185 :
186 275917167 : function liquidus_brine_salinity_mush(zTin) result(Sbr)
187 :
188 : ! liquidus relation: equilibrium brine salinity as function of temperature
189 : ! based on empirical data from Assur (1958)
190 :
191 : real(kind=dbl_kind), intent(in) :: &
192 : zTin ! ice layer temperature (C)
193 :
194 : real(kind=dbl_kind) :: &
195 : Sbr ! ice brine salinity (ppt)
196 :
197 : real(kind=dbl_kind) :: &
198 69349195 : t_high , & ! mask for high temperature liquidus region
199 69349195 : lsubzero ! mask for sub-zero temperatures
200 :
201 : real(kind=dbl_kind) :: &
202 208047585 : J1_liq, K1_liq, L1_liq, & ! temperature to brine salinity
203 208047585 : J2_liq, K2_liq, L2_liq
204 :
205 : character(len=*),parameter :: subname='(liquidus_brine_salinty_mush)'
206 :
207 : ! temperature to brine salinity
208 206567972 : J1_liq = bz1_liq / az1_liq
209 206567972 : K1_liq = c1 / c1000
210 206567972 : L1_liq = (c1 + bz1p_liq) / az1_liq
211 206567972 : J2_liq = bz2_liq / az2_liq
212 206567972 : K2_liq = c1 / c1000
213 206567972 : L2_liq = (c1 + bz2p_liq) / az2_liq
214 :
215 206567972 : t_high = merge(c1, c0, (zTin > Tb_liq))
216 206567972 : lsubzero = merge(c1, c0, (zTin <= c0))
217 :
218 : Sbr = ((zTin + J1_liq) / (K1_liq * zTin + L1_liq)) * t_high + &
219 206567972 : ((zTin + J2_liq) / (K2_liq * zTin + L2_liq)) * (c1 - t_high)
220 :
221 206567972 : Sbr = Sbr * lsubzero
222 :
223 206567972 : end function liquidus_brine_salinity_mush
224 :
225 : !=======================================================================
226 :
227 66769555 : function liquidus_temperature_mush(Sbr) result(zTin)
228 :
229 : ! liquidus relation: equilibrium temperature as function of brine salinity
230 : ! based on empirical data from Assur (1958)
231 :
232 : real(kind=dbl_kind), intent(in) :: &
233 : Sbr ! ice brine salinity (ppt)
234 :
235 : real(kind=dbl_kind) :: &
236 : zTin ! ice layer temperature (C)
237 :
238 : real(kind=dbl_kind) :: &
239 16815711 : t_high ! mask for high temperature liquidus region
240 :
241 : real(kind=dbl_kind) :: &
242 16815711 : M1_liq, &! brine salinity to temperature
243 16815711 : N1_liq, &
244 16815711 : O1_liq, &
245 16815711 : M2_liq, &
246 16815711 : N2_liq, &
247 16815711 : O2_liq
248 :
249 : character(len=*),parameter :: subname='(liquidus_temperature_mush)'
250 :
251 : ! brine salinity to temperature
252 49953844 : M1_liq = az1_liq
253 49953844 : N1_liq = -az1p_liq
254 49953844 : O1_liq = -bz1_liq / az1_liq
255 49953844 : M2_liq = az2_liq
256 49953844 : N2_liq = -az2p_liq
257 49953844 : O2_liq = -bz2_liq / az2_liq
258 :
259 49953844 : t_high = merge(c1, c0, (Sbr <= Sb_liq))
260 :
261 : zTin = ((Sbr / (M1_liq + N1_liq * Sbr)) + O1_liq) * t_high + &
262 49953844 : ((Sbr / (M2_liq + N2_liq * Sbr)) + O2_liq) * (c1 - t_high)
263 :
264 49953844 : end function liquidus_temperature_mush
265 :
266 : !=======================================================================
267 :
268 5185123 : function enthalpy_mush(zTin, zSin) result(zqin)
269 :
270 : ! enthalpy of mush from mush temperature and bulk salinity
271 :
272 : real(kind=dbl_kind), intent(in) :: &
273 : zTin, & ! ice layer temperature (C)
274 : zSin ! ice layer bulk salinity (ppt)
275 :
276 : real(kind=dbl_kind) :: &
277 : zqin ! ice layer enthalpy (J m-3)
278 :
279 : real(kind=dbl_kind) :: &
280 1310944 : phi ! ice liquid fraction
281 :
282 : character(len=*),parameter :: subname='(enthalpy_mush)'
283 :
284 3874179 : phi = icepack_mushy_liquid_fraction(zTin, zSin)
285 :
286 : zqin = phi * (cp_ocn * rhow - cp_ice * rhoi) * zTin + &
287 3874179 : rhoi * cp_ice * zTin - (c1 - phi) * rhoi * Lfresh
288 :
289 3874179 : end function enthalpy_mush
290 :
291 : !=======================================================================
292 :
293 48732761 : function enthalpy_mush_liquid_fraction(zTin, phi) result(zqin)
294 :
295 : ! enthalpy of mush from mush temperature and bulk salinity
296 :
297 : real(kind=dbl_kind), intent(in) :: &
298 : zTin, & ! ice layer temperature (C)
299 : phi ! liquid fraction
300 :
301 : real(kind=dbl_kind) :: &
302 : zqin ! ice layer enthalpy (J m-3)
303 :
304 : character(len=*),parameter :: subname='(enthalpy_mush_liquid_fraction)'
305 :
306 : zqin = phi * (cp_ocn * rhow - cp_ice * rhoi) * zTin + &
307 48732761 : rhoi * cp_ice * zTin - (c1 - phi) * rhoi * Lfresh
308 :
309 48732761 : end function enthalpy_mush_liquid_fraction
310 :
311 : !=======================================================================
312 :
313 25380256 : function enthalpy_of_melting(zSin) result(qm)
314 :
315 : ! enthalpy of melting of mush
316 : ! energy needed to fully melt mush (T < 0)
317 :
318 : real(kind=dbl_kind), intent(in) :: &
319 : zSin ! ice layer bulk salinity (ppt)
320 :
321 : real(kind=dbl_kind) :: &
322 : qm ! melting ice enthalpy (J m-3)
323 :
324 : character(len=*),parameter :: subname='(enthalpy_of_melting)'
325 :
326 25380256 : qm = cp_ocn * rhow * liquidus_temperature_mush(zSin)
327 :
328 25380256 : end function enthalpy_of_melting
329 :
330 : !=======================================================================
331 :
332 123014673 : function enthalpy_brine(zTin) result(qbr)
333 :
334 : ! enthalpy of brine (fully liquid)
335 :
336 : real(kind=dbl_kind), intent(in) :: &
337 : zTin ! ice layer temperature (C)
338 :
339 : real(kind=dbl_kind) :: &
340 : qbr ! brine enthalpy (J m-3)
341 :
342 : character(len=*),parameter :: subname='(enthalpy_brine)'
343 :
344 123014673 : qbr = cp_ocn * rhow * zTin
345 :
346 123014673 : end function enthalpy_brine
347 :
348 : !=======================================================================
349 :
350 122213520 : function icepack_mushy_temperature_mush(zqin, zSin) result(zTin)
351 :
352 : ! temperature of mush from mush enthalpy
353 :
354 : real(kind=dbl_kind), intent(in) :: &
355 : zqin , & ! ice enthalpy (J m-3)
356 : zSin ! ice layer bulk salinity (ppt)
357 :
358 : real(kind=dbl_kind) :: &
359 : zTin ! ice layer temperature (C)
360 :
361 : real(kind=dbl_kind) :: &
362 30663347 : qb , & ! liquidus break enthalpy
363 30663347 : q0 , & ! fully melted enthalpy
364 30663347 : A , & ! quadratic equation A parameter
365 30663347 : B , & ! quadratic equation B parameter
366 30663347 : C , & ! quadratic equation C parameter
367 30663347 : S_low , & ! mask for salinity less than the liquidus break salinity
368 30663347 : t_high , & ! mask for high temperature liquidus region
369 30663347 : t_low , & ! mask for low temperature liquidus region
370 30663347 : q_melt ! mask for all mush melted
371 :
372 : ! quadratic constants - higher temperature region
373 : real(kind=dbl_kind) :: &
374 61326694 : AS1_liq, AC1_liq, & ! quadratic constants - higher temperature region
375 91990041 : BS1_liq, BC1_liq, BQ1_liq, & ! "
376 91990041 : CS1_liq, CC1_liq, CQ1_liq, & ! "
377 61326694 : AS2_liq, AC2_liq, & ! quadratic constants - lower temperature region
378 91990041 : BS2_liq, BC2_liq, BQ2_liq, & ! "
379 91990041 : CS2_liq, CC2_liq, CQ2_liq, & ! "
380 30663347 : D_liq, E_liq, & ! break enthalpy constants
381 91990041 : F1_liq, G1_liq, H1_liq, & ! just fully melted enthapy constants
382 91990041 : F2_liq, G2_liq, H2_liq, & ! "
383 30663347 : I_liq ! warmer than fully melted constants
384 :
385 : character(len=*),parameter :: subname='(icepack_mushy_temperature_mush)'
386 :
387 : !--------------------------------------------------------
388 :
389 : ! quadratic constants - higher temperature region
390 91550173 : AS1_liq = az1p_liq * (rhow * cp_ocn - rhoi * cp_ice)
391 91550173 : AC1_liq = rhoi * cp_ice * az1_liq
392 : BS1_liq = (c1 + bz1p_liq) * (rhow * cp_ocn - rhoi * cp_ice) &
393 91550173 : + rhoi * Lfresh * az1p_liq
394 91550173 : BQ1_liq = -az1_liq
395 91550173 : BC1_liq = rhoi * cp_ice * bz1_liq - rhoi * Lfresh * az1_liq
396 91550173 : CS1_liq = rhoi * Lfresh * (c1 + bz1p_liq)
397 91550173 : CQ1_liq = -bz1_liq
398 91550173 : CC1_liq = -rhoi * Lfresh * bz1_liq
399 :
400 : ! quadratic constants - lower temperature region
401 91550173 : AS2_liq = az2p_liq * (rhow * cp_ocn - rhoi * cp_ice)
402 91550173 : AC2_liq = rhoi * cp_ice * az2_liq
403 : BS2_liq = (c1 + bz2p_liq) * (rhow * cp_ocn - rhoi * cp_ice) &
404 91550173 : + rhoi * Lfresh * az2p_liq
405 91550173 : BQ2_liq = -az2_liq
406 91550173 : BC2_liq = rhoi * cp_ice * bz2_liq - rhoi * Lfresh * az2_liq
407 91550173 : CS2_liq = rhoi * Lfresh * (c1 + bz2p_liq)
408 91550173 : CQ2_liq = -bz2_liq
409 91550173 : CC2_liq = -rhoi * Lfresh * bz2_liq
410 :
411 : ! break enthalpy constants
412 : D_liq = ((c1 + az1p_liq*Tb_liq + bz1p_liq) &
413 : / ( az1_liq*Tb_liq + bz1_liq)) &
414 91550173 : * ((cp_ocn*rhow - cp_ice*rhoi)*Tb_liq + Lfresh*rhoi)
415 91550173 : E_liq = cp_ice*rhoi*Tb_liq - Lfresh*rhoi
416 :
417 : ! just fully melted enthapy constants
418 91550173 : F1_liq = ( -c1000 * cp_ocn * rhow) / az1_liq
419 91550173 : G1_liq = -c1000
420 91550173 : H1_liq = (-bz1_liq * cp_ocn * rhow) / az1_liq
421 91550173 : F2_liq = ( -c1000 * cp_ocn * rhow) / az2_liq
422 91550173 : G2_liq = -c1000
423 91550173 : H2_liq = (-bz2_liq * cp_ocn * rhow) / az2_liq
424 :
425 : ! warmer than fully melted constants
426 91550173 : I_liq = c1 / (cp_ocn * rhow)
427 :
428 : ! just melted enthalpy
429 91550173 : S_low = merge(c1, c0, (zSin < Sb_liq))
430 : q0 = ((F1_liq * zSin) / (G1_liq + zSin) + H1_liq) * S_low + &
431 91550173 : ((F2_liq * zSin) / (G2_liq + zSin) + H2_liq) * (c1 - S_low)
432 91550173 : q_melt = merge(c1, c0, (zqin > q0))
433 :
434 : ! break enthalpy
435 91550173 : qb = D_liq * zSin + E_liq
436 91550173 : t_high = merge(c1, c0, (zqin > qb))
437 91550173 : t_low = c1 - t_high
438 :
439 : ! quadratic values
440 : A = (AS1_liq * zSin + AC1_liq) * t_high + &
441 91550173 : (AS2_liq * zSin + AC2_liq) * t_low
442 :
443 : B = (BS1_liq * zSin + BQ1_liq * zqin + BC1_liq) * t_high + &
444 91550173 : (BS2_liq * zSin + BQ2_liq * zqin + BC2_liq) * t_low
445 :
446 : C = (CS1_liq * zSin + CQ1_liq * zqin + CC1_liq) * t_high + &
447 91550173 : (CS2_liq * zSin + CQ2_liq * zqin + CC2_liq) * t_low
448 :
449 91550173 : zTin = (-B + sqrt(max(B**2 - c4 * A * C,puny))) / (c2 * A)
450 :
451 : ! change T if all melted
452 91550173 : zTin = q_melt * zqin * I_liq + (c1 - q_melt) * zTin
453 :
454 91550173 : end function icepack_mushy_temperature_mush
455 :
456 : !=======================================================================
457 :
458 22207724 : function temperature_mush_liquid_fraction(zqin, phi) result(zTin)
459 :
460 : ! temperature of mush from mush enthalpy
461 :
462 : real(kind=dbl_kind), intent(in) :: &
463 : zqin , & ! ice enthalpy (J m-3)
464 : phi ! liquid fraction
465 :
466 : real(kind=dbl_kind) :: &
467 : zTin ! ice layer temperature (C)
468 :
469 : character(len=*),parameter :: subname='(temperature_mush_liquid_fraction)'
470 :
471 : zTin = (zqin + (c1 - phi) * rhoi * Lfresh) / &
472 22207724 : (phi * (cp_ocn * rhow - cp_ice * rhoi) + rhoi * cp_ice)
473 :
474 22207724 : end function temperature_mush_liquid_fraction
475 :
476 : !=======================================================================
477 :
478 29657026 : function heat_conductivity(zTin, zSin) result(km)
479 :
480 : ! msuh heat conductivity from mush temperature and bulk salinity
481 :
482 : real(kind=dbl_kind), intent(in) :: &
483 : zTin , & ! ice layer temperature (C)
484 : zSin ! ice layer bulk salinity (ppt)
485 :
486 : real(kind=dbl_kind) :: &
487 : km ! ice layer conductivity (W m-1 K-1)
488 :
489 : real(kind=dbl_kind) :: &
490 7449302 : phi ! liquid fraction
491 :
492 : character(len=*),parameter :: subname='(heat_conductivity)'
493 :
494 22207724 : phi = icepack_mushy_liquid_fraction(zTin, zSin)
495 :
496 22207724 : km = phi * (kb - ki) + ki
497 :
498 22207724 : end function heat_conductivity
499 :
500 : !=======================================================================
501 :
502 127398643 : function icepack_mushy_liquid_fraction(zTin, zSin) result(phi)
503 :
504 : ! liquid fraction of mush from mush temperature and bulk salinity
505 :
506 : real(kind=dbl_kind), intent(in) :: &
507 : zTin, & ! ice layer temperature (C)
508 : zSin ! ice layer bulk salinity (ppt)
509 :
510 : real(kind=dbl_kind) :: &
511 : phi , & ! liquid fraction
512 31974291 : Sbr ! brine salinity (ppt)
513 :
514 : character(len=*),parameter :: subname='(icepack_mushy_liquid_fraction)'
515 :
516 95424352 : Sbr = max(liquidus_brine_salinity_mush(zTin),puny)
517 95424352 : phi = zSin / max(Sbr, zSin)
518 :
519 95424352 : end function icepack_mushy_liquid_fraction
520 :
521 : !=======================================================================
522 :
523 : end module icepack_mushy_physics
524 :
525 :
|