Line data Source code
1 : !=======================================================================
2 :
3 : ! Aerosol tracer within sea ice
4 : !
5 : ! authors Marika Holland, NCAR
6 : ! David Bailey, NCAR
7 :
8 : module icepack_aerosol
9 :
10 : use icepack_kinds
11 : use icepack_parameters, only: c0, c1, c2, p5, puny, rhoi, rhos, hs_min
12 : use icepack_parameters, only: hi_ssl, hs_ssl, hs_ssl_min
13 : use icepack_tracers, only: max_aero, nilyr, nslyr, nblyr, ntrcr, nbtrcr, n_aero
14 : use icepack_warnings, only: warnstr, icepack_warnings_add
15 : use icepack_warnings, only: icepack_warnings_setabort, icepack_warnings_aborted
16 :
17 : use icepack_zbgc_shared, only: kscavz
18 :
19 : implicit none
20 :
21 : private
22 : public :: update_aerosol, update_snow_bgc
23 :
24 : !=======================================================================
25 :
26 : contains
27 :
28 : !=======================================================================
29 :
30 : ! Deposition and vertical cycling of aerosol in ice or snow
31 : ! Called from icepack_step_therm1 when tr_aero=T (not used for zbgc tracers)
32 :
33 351672 : subroutine update_aerosol(dt, &
34 : meltt, melts, &
35 : meltb, congel, &
36 : snoice, &
37 : fsnow, &
38 351672 : aerosno, aeroice, &
39 : aice_old, &
40 : vice_old, vsno_old, &
41 : vicen, vsnon, aicen, &
42 703344 : faero_atm, faero_ocn)
43 :
44 : real (kind=dbl_kind), intent(in) :: &
45 : dt, & ! time step
46 : meltt, & ! thermodynamic melt/growth rates
47 : melts, &
48 : meltb, &
49 : congel, &
50 : snoice, &
51 : fsnow, &
52 : vicen, & ! ice volume (m)
53 : vsnon, & ! snow volume (m)
54 : aicen, & ! ice area fraction
55 : aice_old, & ! values prior to thermodynamic changes
56 : vice_old, &
57 : vsno_old
58 :
59 : real (kind=dbl_kind), dimension(:), intent(in) :: &
60 : faero_atm ! aerosol deposition rate (W/m^2 s)
61 :
62 : real (kind=dbl_kind), dimension(:), intent(inout) :: &
63 : faero_ocn ! aerosol flux to ocean (W/m^2 s)
64 :
65 : real (kind=dbl_kind), dimension(:,:), intent(inout) :: &
66 : aerosno, aeroice ! kg/m^2
67 :
68 : ! local variables
69 : integer (kind=int_kind) :: k
70 :
71 : real (kind=dbl_kind) :: &
72 : dzssl, dzssl_new, & ! snow ssl thickness
73 : dzint, & ! snow interior thickness
74 : dzssli, dzssli_new, & ! ice ssl thickness
75 : dzinti, & ! ice interior thickness
76 : dznew, & ! tracks thickness changes
77 : hs, hi, & ! snow/ice thickness (m)
78 : dhs_evap, dhi_evap, & ! snow/ice thickness change due to evap
79 : dhs_melts, dhi_meltt, & ! ... due to surface melt
80 : dhs_snoice, dhi_snoice, & ! ... due to snow-ice formation
81 : dhi_congel, dhi_meltb, & ! ... due to bottom growth, melt
82 : hslyr, hilyr, & ! snow, ice layer thickness (m)
83 : hslyr_old, hilyr_old, & ! old snow, ice layer thickness (m)
84 : hs_old, hi_old, & ! old snow, ice thickness (m)
85 : sloss1, sloss2, & ! aerosol mass loss (kg/m^2)
86 : ar ! 1/aicen(i,j)
87 :
88 : real (kind=dbl_kind), dimension(max_aero) :: &
89 : kscav, kscavsi ! scavenging by melt water
90 :
91 : real (kind=dbl_kind), dimension(n_aero) :: &
92 703344 : aerotot, aerotot0, & ! for conservation check
93 703344 : focn_old ! for conservation check
94 :
95 : ! echmod: this assumes max_aero=6
96 : data kscav / .03_dbl_kind, .20_dbl_kind, .02_dbl_kind, &
97 : .02_dbl_kind, .01_dbl_kind, .01_dbl_kind /
98 : data kscavsi / .03_dbl_kind, .20_dbl_kind, .02_dbl_kind, &
99 : .02_dbl_kind, .01_dbl_kind, .01_dbl_kind /
100 :
101 : character(len=*),parameter :: subname='(update_aerosol)'
102 :
103 : !-------------------------------------------------------------------
104 : ! initialize
105 : !-------------------------------------------------------------------
106 703344 : focn_old(:) = faero_ocn(:)
107 :
108 351672 : hs_old = vsno_old/aice_old
109 351672 : hi_old = vice_old/aice_old
110 351672 : hslyr_old = hs_old/real(nslyr,kind=dbl_kind)
111 351672 : hilyr_old = hi_old/real(nilyr,kind=dbl_kind)
112 :
113 351672 : dzssl = min(hslyr_old/c2, hs_ssl)
114 351672 : dzssli = min(hilyr_old/c2, hi_ssl)
115 351672 : dzint = hs_old - dzssl
116 351672 : dzinti = hi_old - dzssli
117 :
118 351672 : if (aicen > c0) then
119 351672 : ar = c1/aicen
120 : else ! ice disappeared during time step
121 0 : ar = c1/aice_old
122 : endif
123 :
124 351672 : hs = vsnon*ar
125 351672 : hi = vicen*ar
126 : ! fluxes were divided by aice for thermo, not yet multiplied by aice
127 351672 : dhs_melts = -melts
128 351672 : dhi_snoice = snoice
129 351672 : dhs_snoice = dhi_snoice*rhoi/rhos
130 351672 : dhi_meltt = -meltt
131 351672 : dhi_meltb = -meltb
132 351672 : dhi_congel = congel
133 :
134 : dhs_evap = hs - (hs_old + dhs_melts - dhs_snoice &
135 351672 : + fsnow/rhos*dt)
136 : dhi_evap = hi - (hi_old + dhi_meltt + dhi_meltb &
137 351672 : + dhi_congel + dhi_snoice)
138 :
139 703344 : do k = 1, n_aero
140 : aerotot0(k) = aerosno(k,2) + aerosno(k,1) &
141 703344 : + aeroice(k,2) + aeroice(k,1)
142 : enddo
143 :
144 : !-------------------------------------------------------------------
145 : ! evaporation
146 : !-------------------------------------------------------------------
147 351672 : dzint = dzint + min(dzssl + dhs_evap, c0)
148 351672 : dzinti = dzinti + min(dzssli + dhi_evap, c0)
149 351672 : dzssl = max(dzssl + dhs_evap, c0)
150 351672 : dzssli = max(dzssli + dhi_evap, c0)
151 :
152 : !-------------------------------------------------------------------
153 : ! basal ice growth
154 : !-------------------------------------------------------------------
155 351672 : dzinti = dzinti + dhi_congel
156 :
157 : !-------------------------------------------------------------------
158 : ! surface snow melt
159 : !-------------------------------------------------------------------
160 351672 : if (-dhs_melts > puny) then
161 12010 : do k = 1, n_aero
162 6005 : sloss1 = c0
163 6005 : sloss2 = c0
164 6005 : if (dzssl > puny) &
165 : sloss1 = kscav(k)*aerosno(k,1) &
166 5608 : *min(-dhs_melts,dzssl)/dzssl
167 6005 : aerosno(k,1) = aerosno(k,1) - sloss1
168 6005 : if (dzint > puny) &
169 : sloss2 = kscav(k)*aerosno(k,2) &
170 6005 : *max(-dhs_melts-dzssl,c0)/dzint
171 6005 : aerosno(k,2) = aerosno(k,2) - sloss2
172 12010 : faero_ocn(k) = faero_ocn(k) + (sloss1+sloss2)/dt
173 : enddo ! n_aero
174 :
175 : ! update snow thickness
176 6005 : dzint=dzint+min(dzssl+dhs_melts, c0)
177 6005 : dzssl=max(dzssl+dhs_melts, c0)
178 :
179 6005 : if ( dzssl <= puny ) then ! ssl melts away
180 846 : aerosno(:,2) = aerosno(:,1) + aerosno(:,2)
181 846 : aerosno(:,1) = c0
182 423 : dzssl = max(dzssl, c0)
183 : endif
184 6005 : if (dzint <= puny ) then ! all snow melts away
185 : aeroice(:,1) = aeroice(:,1) &
186 824 : + aerosno(:,1) + aerosno(:,2)
187 2060 : aerosno(:,:) = c0
188 412 : dzint = max(dzint, c0)
189 : endif
190 : endif
191 :
192 : !-------------------------------------------------------------------
193 : ! surface ice melt
194 : !-------------------------------------------------------------------
195 351672 : if (-dhi_meltt > puny) then
196 54176 : do k = 1, n_aero
197 27088 : sloss1 = c0
198 27088 : sloss2 = c0
199 27088 : if (dzssli > puny) &
200 : sloss1 = kscav(k)*aeroice(k,1) &
201 27088 : *min(-dhi_meltt,dzssli)/dzssli
202 27088 : aeroice(k,1) = aeroice(k,1) - sloss1
203 27088 : if (dzinti > puny) &
204 : sloss2 = kscav(k)*aeroice(k,2) &
205 27088 : *max(-dhi_meltt-dzssli,c0)/dzinti
206 27088 : aeroice(k,2) = aeroice(k,2) - sloss2
207 54176 : faero_ocn(k) = faero_ocn(k) + (sloss1+sloss2)/dt
208 : enddo
209 :
210 27088 : dzinti = dzinti + min(dzssli+dhi_meltt, c0)
211 27088 : dzssli = max(dzssli+dhi_meltt, c0)
212 27088 : if (dzssli <= puny) then ! ssl ice melts away
213 8 : do k = 1, n_aero
214 4 : aeroice(k,2) = aeroice(k,1) + aeroice(k,2)
215 8 : aeroice(k,1) = c0
216 : enddo
217 4 : dzssli = max(dzssli, c0)
218 : endif
219 27088 : if (dzinti <= puny) then ! all ice melts away
220 0 : do k = 1, n_aero
221 : faero_ocn(k) = faero_ocn(k) &
222 0 : + (aeroice(k,1)+aeroice(k,2))/dt
223 0 : aeroice(k,:)=c0
224 : enddo
225 0 : dzinti = max(dzinti, c0)
226 : endif
227 : endif
228 :
229 : !-------------------------------------------------------------------
230 : ! basal ice melt. Assume all aero lost in basal melt
231 : !-------------------------------------------------------------------
232 351672 : if (-dhi_meltb > puny) then
233 331398 : do k=1,n_aero
234 165699 : sloss1=c0
235 165699 : sloss2=c0
236 165699 : if (dzssli > puny) &
237 : sloss1 = max(-dhi_meltb-dzinti, c0) &
238 165695 : *aeroice(k,1)/dzssli
239 165699 : aeroice(k,1) = aeroice(k,1) - sloss1
240 165699 : if (dzinti > puny) &
241 : sloss2 = min(-dhi_meltb, dzinti) &
242 165699 : *aeroice(k,2)/dzinti
243 165699 : aeroice(k,2) = aeroice(k,2) - sloss2
244 331398 : faero_ocn(k) = faero_ocn(k) + (sloss1+sloss2)/dt
245 : enddo
246 :
247 165699 : dzssli = dzssli + min(dzinti+dhi_meltb, c0)
248 165699 : dzinti = max(dzinti+dhi_meltb, c0)
249 : endif
250 :
251 : !-------------------------------------------------------------------
252 : ! snowfall
253 : !-------------------------------------------------------------------
254 351672 : if (fsnow > c0) dzssl = dzssl + fsnow/rhos*dt
255 :
256 : !-------------------------------------------------------------------
257 : ! snow-ice formation
258 : !-------------------------------------------------------------------
259 351672 : if (dhs_snoice > puny) then
260 5220 : do k = 1, n_aero
261 2610 : sloss1 = c0
262 2610 : sloss2 = c0
263 2610 : if (dzint > puny) &
264 : sloss2 = min(dhs_snoice, dzint) &
265 2610 : *aerosno(k,2)/dzint
266 2610 : aerosno(k,2) = aerosno(k,2) - sloss2
267 2610 : if (dzssl > puny) &
268 : sloss1 = max(dhs_snoice-dzint, c0) &
269 2610 : *aerosno(k,1)/dzssl
270 2610 : aerosno(k,1) = aerosno(k,1) - sloss1
271 : aeroice(k,1) = aeroice(k,1) &
272 2610 : + (c1-kscavsi(k))*(sloss2+sloss1)
273 : faero_ocn(k) = faero_ocn(k) &
274 5220 : + kscavsi(k)*(sloss2+sloss1)/dt
275 : enddo
276 2610 : dzssl = dzssl - max(dhs_snoice-dzint, c0)
277 2610 : dzint = max(dzint-dhs_snoice, c0)
278 2610 : dzssli = dzssli + dhi_snoice
279 : endif
280 :
281 : !-------------------------------------------------------------------
282 : ! aerosol deposition
283 : !-------------------------------------------------------------------
284 351672 : if (aicen > c0) then
285 351672 : hs = vsnon * ar
286 : else
287 0 : hs = c0
288 : endif
289 351672 : if (hs > hs_min) then ! should this really be hs_min or 0?
290 : ! should use same hs_min value as in radiation
291 570262 : do k=1,n_aero
292 : aerosno(k,1) = aerosno(k,1) &
293 570262 : + faero_atm(k)*dt*aicen
294 : enddo
295 : else
296 133082 : do k=1,n_aero
297 : aeroice(k,1) = aeroice(k,1) &
298 133082 : + faero_atm(k)*dt*aicen
299 : enddo
300 : endif
301 :
302 : !-------------------------------------------------------------------
303 : ! redistribute aerosol within vertical layers
304 : !-------------------------------------------------------------------
305 351672 : if (aicen > c0) then
306 351672 : hs = vsnon * ar ! new snow thickness
307 351672 : hi = vicen * ar ! new ice thickness
308 : else
309 0 : hs = c0
310 0 : hi = c0
311 : endif
312 351672 : if (dzssl <= puny) then ! nothing in SSL
313 20024 : do k=1,n_aero
314 10012 : aerosno(k,2) = aerosno(k,2) + aerosno(k,1)
315 20024 : aerosno(k,1) = c0
316 : enddo
317 : endif
318 351672 : if (dzint <= puny) then ! nothing in Snow Int
319 127314 : do k = 1, n_aero
320 63657 : aeroice(k,1) = aeroice(k,1) + aerosno(k,2)
321 127314 : aerosno(k,2) = c0
322 : enddo
323 : endif
324 351672 : if (dzssli <= puny) then ! nothing in Ice SSL
325 8 : do k = 1, n_aero
326 4 : aeroice(k,2) = aeroice(k,2) + aeroice(k,1)
327 8 : aeroice(k,1) = c0
328 : enddo
329 : endif
330 :
331 351672 : if (dzinti <= puny) then ! nothing in Ice INT
332 0 : do k = 1, n_aero
333 : faero_ocn(k) = faero_ocn(k) &
334 0 : + (aeroice(k,1)+aeroice(k,2))/dt
335 0 : aeroice(k,:)=c0
336 : enddo
337 : endif
338 :
339 351672 : hslyr = hs/real(nslyr,kind=dbl_kind)
340 351672 : hilyr = hi/real(nilyr,kind=dbl_kind)
341 351672 : dzssl_new = min(hslyr/c2, hs_ssl)
342 351672 : dzssli_new = min(hilyr/c2, hi_ssl)
343 :
344 351672 : if (hs > hs_min) then
345 570262 : do k = 1, n_aero
346 285131 : dznew = min(dzssl_new-dzssl, c0)
347 285131 : sloss1 = c0
348 285131 : if (dzssl > puny) &
349 285123 : sloss1 = dznew*aerosno(k,1)/dzssl ! not neccesarily a loss
350 285131 : dznew = max(dzssl_new-dzssl, c0)
351 285131 : if (dzint > puny) &
352 285131 : sloss1 = sloss1 + aerosno(k,2)*dznew/dzint
353 285131 : aerosno(k,1) = aerosno(k,1) + sloss1
354 570262 : aerosno(k,2) = aerosno(k,2) - sloss1
355 : enddo
356 : else
357 : aeroice(:,1) = aeroice(:,1) &
358 133082 : + aerosno(:,1) + aerosno(:,2)
359 332705 : aerosno(:,:) = c0
360 : endif
361 :
362 351672 : if (vicen > puny) then ! may want a limit on hi instead?
363 703344 : do k = 1, n_aero
364 351672 : sloss2 = c0
365 351672 : dznew = min(dzssli_new-dzssli, c0)
366 351672 : if (dzssli > puny) &
367 351668 : sloss2 = dznew*aeroice(k,1)/dzssli
368 351672 : dznew = max(dzssli_new-dzssli, c0)
369 351672 : if (dzinti > puny) &
370 351672 : sloss2 = sloss2 + aeroice(k,2)*dznew/dzinti
371 351672 : aeroice(k,1) = aeroice(k,1) + sloss2
372 703344 : aeroice(k,2) = aeroice(k,2) - sloss2
373 : enddo
374 : else
375 0 : faero_ocn(:) = faero_ocn(:) + (aeroice(:,1)+aeroice(:,2))/dt
376 0 : aeroice(:,:) = c0
377 : endif
378 :
379 : !-------------------------------------------------------------------
380 : ! check conservation
381 : !-------------------------------------------------------------------
382 703344 : do k = 1, n_aero
383 : aerotot(k) = aerosno(k,2) + aerosno(k,1) &
384 351672 : + aeroice(k,2) + aeroice(k,1)
385 351672 : if ((aerotot(k)-aerotot0(k)) &
386 : - ( faero_atm(k)*aicen &
387 351672 : - (faero_ocn(k)-focn_old(k)) )*dt > puny) then
388 :
389 0 : write(warnstr,*) subname, 'aerosol tracer: ',k
390 0 : call icepack_warnings_add(warnstr)
391 0 : write(warnstr,*) subname, 'aerotot-aerotot0 ',aerotot(k)-aerotot0(k)
392 0 : call icepack_warnings_add(warnstr)
393 0 : write(warnstr,*) subname, 'faero_atm-faero_ocn ', &
394 0 : (faero_atm(k)*aicen-(faero_ocn(k)-focn_old(k)))*dt
395 0 : call icepack_warnings_add(warnstr)
396 : endif
397 : enddo
398 :
399 : !-------------------------------------------------------------------
400 : ! check for negative values
401 : !-------------------------------------------------------------------
402 :
403 : !echmod: note that this does not test or fix all aero tracers
404 : if (aeroice(1,1) < -puny .or. &
405 : aeroice(1,2) < -puny .or. &
406 351672 : aerosno(1,1) < -puny .or. &
407 : aerosno(1,2) < -puny) then
408 :
409 0 : write(warnstr,*) subname, 'aerosol negative in aerosol code'
410 0 : call icepack_warnings_add(warnstr)
411 :
412 0 : aeroice(1,1) = max(aeroice(1,1), c0)
413 0 : aeroice(1,2) = max(aeroice(1,2), c0)
414 0 : aerosno(1,1) = max(aerosno(1,1), c0)
415 0 : aerosno(1,2) = max(aerosno(1,2), c0)
416 :
417 : endif
418 :
419 351672 : end subroutine update_aerosol
420 :
421 : !=======================================================================
422 :
423 : ! Aerosol in snow for vertical biogeochemistry with mushy thermodynamics
424 : ! Called from icepack_algae.F90 when z_tracers=T (replaces update_aerosol)
425 :
426 660884 : subroutine update_snow_bgc(dt, &
427 : meltt, melts, &
428 : meltb, congel, &
429 : snoice, fsnow, &
430 660884 : trcrn, bio_index, &
431 660884 : aice_old, zbgc_snow, &
432 : vice_old, vsno_old, &
433 : vicen, vsnon, &
434 660884 : aicen, flux_bio_atm,&
435 660884 : zbgc_atm, flux_bio, &
436 660884 : bio_index_o)
437 :
438 : integer (kind=int_kind), dimension (nbtrcr), intent(in) :: &
439 : bio_index, &
440 : bio_index_o ! provides index of scavenging (kscavz) data array
441 :
442 : real (kind=dbl_kind), intent(in) :: &
443 : dt ! time step
444 :
445 : real (kind=dbl_kind), intent(in) :: &
446 : meltt, & ! thermodynamic melt/growth rates
447 : melts, &
448 : meltb, &
449 : congel, &
450 : snoice, &
451 : fsnow, &
452 : vicen, & ! ice volume (m)
453 : vsnon, & ! snow volume (m)
454 : aicen, & ! ice area fraction
455 : aice_old, & ! values prior to thermodynamic changes
456 : vice_old, &
457 : vsno_old
458 :
459 : real (kind=dbl_kind), dimension(nbtrcr), intent(out) :: &
460 : zbgc_snow, & ! aerosol contribution from snow to ice
461 : zbgc_atm ! and atm to ice concentration * volume (kg or mmol/m^3*m)
462 :
463 : real (kind=dbl_kind),dimension(nbtrcr), intent(inout) :: &
464 : flux_bio ! total ocean tracer flux (mmol/m^2/s)
465 :
466 : real (kind=dbl_kind), dimension(nbtrcr), intent(in) :: &
467 : flux_bio_atm ! aerosol deposition rate (kg or mmol/m^2 s)
468 :
469 : real (kind=dbl_kind), dimension(ntrcr), intent(inout) :: &
470 : trcrn ! ice/snow tracer array
471 :
472 : ! local variables
473 :
474 : integer (kind=int_kind) :: k, n
475 :
476 : real (kind=dbl_kind) :: &
477 : dzssl, dzssl_new, & ! snow ssl thickness
478 : dzint, dzint_new, & ! snow interior thickness
479 : dz, & !
480 : hi, & ! ice thickness (m)
481 : hilyr, & ! ice layer thickness (m)
482 : hs, & ! snow thickness (m)
483 : dhs_evap, & ! snow thickness change due to evap
484 : dhs_melts, & ! ... due to surface melt
485 : dhs_snoice, & ! ... due to snow-ice formation
486 : hslyr, & ! snow layer thickness (m)
487 : hslyr_old, & ! old snow layer thickness (m)
488 : hs_old, & ! old snow thickness (m)
489 : dznew, & ! change in the snow sl (m)
490 : sloss1, sloss2, & ! aerosol mass loss (kg/m^2)
491 : ar ! 1/aicen(i,j)
492 :
493 : real (kind=dbl_kind), dimension(nbtrcr) :: &
494 1321768 : aerotot, aerotot0, & ! for conservation check (mmol/m^3)
495 1321768 : aero_cons , & ! for conservation check (mmol/m^2)
496 1321768 : flux_bio_o ! initial ocean tracer flux (mmol/m^2/s)
497 :
498 : real (kind=dbl_kind), dimension(nbtrcr,2) :: &
499 1321768 : aerosno, & ! kg/m^2
500 1321768 : aerosno0 ! for diagnostic prints
501 :
502 : character(len=*),parameter :: subname='(update_snow_bgc)'
503 :
504 : !-------------------------------------------------------------------
505 : ! initialize
506 : !-------------------------------------------------------------------
507 17637862 : aerosno (:,:) = c0
508 17637862 : aerosno0(:,:) = c0
509 8488489 : aero_cons(:) = c0
510 8488489 : zbgc_snow(:) = c0
511 8488489 : zbgc_atm(:) = c0
512 :
513 660884 : hs_old = vsno_old/aice_old
514 660884 : if (aice_old .gt. puny) then
515 660884 : hs_old = vsno_old/aice_old
516 : else
517 0 : hs_old = c0
518 : end if
519 660884 : hslyr_old = hs_old/real(nslyr,kind=dbl_kind)
520 :
521 660884 : dzssl = hslyr_old/c2
522 660884 : dzint = hs_old - dzssl
523 :
524 660884 : if (aicen > c0) then
525 660884 : ar = c1/aicen
526 660884 : hs = vsnon*ar
527 660884 : hi = vicen*ar
528 : else ! ice disappeared during time step
529 0 : ar = c1
530 0 : hs = c0
531 0 : hi = c0
532 0 : if (aice_old > c0) hs = vsnon/aice_old
533 : endif
534 660884 : hilyr = hi/real(nblyr,kind=dbl_kind)
535 660884 : hslyr = hs/real(nslyr,kind=dbl_kind)
536 660884 : dzssl_new = hslyr/c2
537 660884 : dhs_melts = -melts
538 660884 : dhs_snoice = snoice*rhoi/rhos
539 : dhs_evap = hs - (hs_old + dhs_melts - dhs_snoice &
540 660884 : + fsnow/rhos*dt)
541 :
542 : ! trcrn() has units kg/m^3
543 :
544 660884 : if (dzssl_new .lt. hs_ssl_min) then ! Put atm BC/dust flux directly into the sea ice
545 4928253 : do k=1,nbtrcr
546 4552664 : flux_bio_o(k) = flux_bio(k)
547 4552664 : if (hilyr .lt. hs_ssl_min) then
548 : flux_bio(k) = flux_bio(k) + &
549 : (trcrn(bio_index(k)+ nblyr+1)*dzssl+ &
550 0 : trcrn(bio_index(k)+ nblyr+2)*dzint)/dt
551 0 : flux_bio(k) = flux_bio(k) + flux_bio_atm(k)
552 : else
553 : zbgc_snow(k) = zbgc_snow(k) + &
554 : (trcrn(bio_index(k)+ nblyr+1)*dzssl+ &
555 4552664 : trcrn(bio_index(k)+ nblyr+2)*dzint)
556 : zbgc_atm(k) = zbgc_atm(k) &
557 4552664 : + flux_bio_atm(k)*dt
558 : end if
559 4552664 : trcrn(bio_index(k) + nblyr+1) = c0
560 4928253 : trcrn(bio_index(k) + nblyr+2) = c0
561 : enddo
562 :
563 : else
564 :
565 3560236 : do k=1,nbtrcr
566 3274941 : flux_bio_o(k) = flux_bio(k)
567 3274941 : aerosno (k,1) = trcrn(bio_index(k)+ nblyr+1) * dzssl
568 3274941 : aerosno (k,2) = trcrn(bio_index(k)+ nblyr+2) * dzint
569 9824823 : aerosno0(k,:) = aerosno(k,:)
570 3560236 : aerotot0(k) = aerosno(k,2) + aerosno(k,1)
571 : enddo
572 :
573 : !-------------------------------------------------------------------
574 : ! evaporation
575 : !-------------------------------------------------------------------
576 285295 : dzint = dzint + min(dzssl + dhs_evap, c0)
577 285295 : dzssl = max(dzssl + dhs_evap, c0)
578 285295 : if (dzssl <= puny) then
579 0 : do k = 1,nbtrcr
580 0 : aerosno(k,2) = aerosno(k,2) + aerosno(k,1)
581 0 : aerosno(k,1) = c0
582 : end do
583 : end if
584 285295 : if (dzint <= puny) then
585 0 : do k = 1,nbtrcr
586 0 : zbgc_snow(k) = zbgc_snow(k) + (aerosno(k,2) + aerosno(k,1))
587 0 : aerosno(k,2) = c0
588 0 : aerosno(k,1) = c0
589 : end do
590 : end if
591 :
592 : !------------------------------------------------------------------
593 : ! snowfall
594 : !-------------------------------------------------------------------
595 285295 : if (fsnow > c0) then
596 267515 : sloss1 = c0
597 267515 : dz = min(fsnow/rhos*dt,dzssl)
598 3344439 : do k = 1, nbtrcr
599 3076924 : if (dzssl > puny) &
600 3076924 : sloss1 = aerosno(k,1)*dz/dzssl
601 3076924 : aerosno(k,1) = max(c0,aerosno(k,1) - sloss1)
602 3344439 : aerosno(k,2) = aerosno(k,2) + sloss1
603 : end do
604 267515 : dzssl = dzssl - dz + fsnow/rhos*dt
605 267515 : dzint = dzint + dz
606 : end if
607 285295 : if (dzssl <= puny) then
608 0 : do k = 1,nbtrcr
609 0 : aerosno(k,2) = aerosno(k,2) + aerosno(k,1)
610 0 : aerosno(k,1) = c0
611 : end do
612 : end if
613 285295 : if (dzint <= puny) then
614 0 : do k = 1,nbtrcr
615 0 : zbgc_snow(k) = zbgc_snow(k) + (aerosno(k,2) + aerosno(k,1))
616 0 : aerosno(k,2) = c0
617 0 : aerosno(k,1) = c0
618 : end do
619 : end if
620 :
621 : !-------------------------------------------------------------------
622 : ! surface snow melt
623 : !-------------------------------------------------------------------
624 285295 : if (-dhs_melts > puny) then
625 180401 : do k = 1, nbtrcr
626 167751 : sloss1 = c0
627 167751 : sloss2 = c0
628 167751 : if (dzssl > puny) &
629 : sloss1 = kscavz(bio_index_o(k))*aerosno(k,1) &
630 167751 : *min(-dhs_melts,dzssl)/dzssl
631 167751 : aerosno(k,1) = max(c0,aerosno(k,1) - sloss1)
632 167751 : if (dzint > puny) &
633 : sloss2 = kscavz(bio_index_o(k))*aerosno(k,2) &
634 167751 : *max(-dhs_melts-dzssl,c0)/dzint
635 167751 : aerosno(k,2) = max(c0,aerosno(k,2) - sloss2)
636 180401 : zbgc_snow(k) = zbgc_snow(k) + (sloss1+sloss2) ! all not scavenged ends in ice
637 : enddo
638 :
639 : ! update snow thickness
640 12650 : dzint=dzint+min(dzssl+dhs_melts, c0)
641 12650 : dzssl=max(dzssl+dhs_melts, c0)
642 :
643 12650 : if ( dzssl .le. puny ) then ! ssl melts away
644 166 : do k = 1,nbtrcr
645 150 : aerosno(k,2) = aerosno(k,1) + aerosno(k,2)
646 166 : aerosno(k,1) = c0
647 : end do
648 16 : dzssl = max(dzssl, c0)
649 : endif
650 12650 : if (dzint .le. puny ) then ! all snow melts away
651 0 : do k = 1,nbtrcr
652 : zbgc_snow(k) = zbgc_snow(k) &
653 0 : + aerosno(k,1) + aerosno(k,2)
654 0 : aerosno(k,:) = c0
655 : enddo
656 0 : dzint = max(dzint, c0)
657 : endif
658 : endif ! -dhs_melts > puny
659 :
660 : !-------------------------------------------------------------------
661 : ! snow-ice formation
662 : !-------------------------------------------------------------------
663 285295 : if (dhs_snoice > puny) then
664 338892 : do k = 1, nbtrcr
665 322304 : sloss1 = c0
666 322304 : sloss2 = c0
667 322304 : if (dzint > puny .and. aerosno(k,2) > c0) &
668 : sloss2 = min(dhs_snoice, dzint) &
669 84882 : *aerosno(k,2)/dzint
670 322304 : aerosno(k,2) = max(c0,aerosno(k,2) - sloss2)
671 322304 : if (dzssl > puny .and. aerosno(k,1) > c0) &
672 : sloss1 = max(dhs_snoice-dzint, c0) &
673 84882 : *aerosno(k,1)/dzssl
674 :
675 322304 : aerosno(k,1) = max(c0,aerosno(k,1) - sloss1)
676 : flux_bio(k) = flux_bio(k) &
677 322304 : + kscavz(bio_index_o(k)) * (sloss2+sloss1)/dt
678 : zbgc_snow(k) = zbgc_snow(k) &
679 338892 : + (c1-kscavz(bio_index_o(k)))*(sloss2+sloss1)
680 : enddo
681 16588 : dzssl = max(c0,dzssl - max(dhs_snoice-dzint, c0))
682 16588 : dzint = max(dzint-dhs_snoice, c0)
683 : endif ! dhs_snowice > puny
684 :
685 : !-------------------------------------------------------------------
686 : ! aerosol deposition
687 : !-------------------------------------------------------------------
688 : ! Spread out the atm dust flux in the snow interior for small snow surface layers
689 285295 : if (dzssl .ge. hs_ssl*p5) then
690 :
691 2013934 : do k=1,nbtrcr
692 : aerosno(k,1) = aerosno(k,1) &
693 2013934 : + flux_bio_atm(k)*dt
694 : enddo
695 : else
696 131485 : dz = (hs_ssl*p5 - dzssl)/(hs_ssl*p5)
697 1546302 : do k=1,nbtrcr
698 : aerosno(k,1) = aerosno(k,1) &
699 1414817 : + flux_bio_atm(k)*dt*(c1-dz)
700 : aerosno(k,2) = aerosno(k,2) &
701 1546302 : + flux_bio_atm(k)*dt*dz
702 : enddo
703 : endif
704 :
705 : !-------------------------------------------------------------------
706 : ! redistribute aerosol within vertical layers
707 : !-------------------------------------------------------------------
708 285295 : if (aicen > c0) then
709 285295 : hs = vsnon * ar ! new snow thickness
710 : else
711 0 : hs = c0
712 : endif
713 285295 : if (dzssl <= puny) then ! nothing in SSL
714 166 : do k=1,nbtrcr
715 150 : aerosno(k,2) = aerosno(k,2) + aerosno(k,1)
716 166 : aerosno(k,1) = c0
717 : enddo
718 : endif
719 285295 : if (dzint <= puny) then ! nothing in Snow Int
720 0 : do k = 1, nbtrcr
721 0 : zbgc_snow(k) = zbgc_snow(k) + max(c0,aerosno(k,2)+aerosno(k,1))
722 0 : aerosno(k,1) = c0
723 0 : aerosno(k,2) = c0
724 : enddo
725 : endif
726 :
727 285295 : hslyr = hs/real(nslyr,kind=dbl_kind)
728 285295 : dzssl_new = hslyr/c2
729 285295 : dzint_new = max(c0,hs - dzssl_new)
730 :
731 285295 : if (hs > hs_min) then
732 3560236 : do k = 1, nbtrcr
733 3274941 : dznew = min(dzssl_new-dzssl, c0)
734 3274941 : sloss1 = c0
735 3274941 : if (dzssl > puny .and. aerosno(k,1) > c0) &
736 1145745 : sloss1 = dznew*aerosno(k,1)/dzssl ! not neccesarily a loss
737 3274941 : dznew = max(dzssl_new-dzssl, c0)
738 3274941 : if (dzint > puny .and. aerosno(k,2) > c0) &
739 1145697 : sloss1 = aerosno(k,2)*dznew/dzint
740 3274941 : aerosno(k,1) = max(c0,aerosno(k,1) + sloss1)
741 3560236 : aerosno(k,2) = max(c0,aerosno(k,2) - sloss1)
742 : enddo
743 : else
744 : zbgc_snow(:) = zbgc_snow(:) &
745 0 : + aerosno(:,1) + aerosno(:,2)
746 0 : aerosno(:,:) = c0
747 : endif
748 :
749 : !-------------------------------------------------------------------
750 : ! check conservation
751 : !-------------------------------------------------------------------
752 3560236 : do k = 1, nbtrcr
753 : aerotot(k) = aerosno(k,2) + aerosno(k,1) &
754 3274941 : + zbgc_snow(k) + zbgc_atm(k)
755 : aero_cons(k) = aerotot(k)-aerotot0(k) &
756 : - ( flux_bio_atm(k) &
757 3274941 : - (flux_bio(k)-flux_bio_o(k))) * dt
758 3274941 : if (aerotot0(k) > aerotot(k) .and. aerotot0(k) > c0) then
759 1592 : aero_cons(k) = aero_cons(k)/aerotot0(k)
760 3273349 : else if (aerotot(k) > c0) then
761 1144201 : aero_cons(k) = aero_cons(k)/aerotot(k)
762 : end if
763 3560236 : if (aero_cons(k) > puny .or. zbgc_snow(k) + zbgc_atm(k) < c0) then
764 0 : write(warnstr,*) subname, 'Conservation failure: aerosols in snow'
765 0 : call icepack_warnings_add(warnstr)
766 0 : write(warnstr,*) subname, 'test aerosol 1'
767 0 : call icepack_warnings_add(warnstr)
768 0 : write(warnstr,*) subname, 'aerosol tracer: ',k
769 0 : call icepack_warnings_add(warnstr)
770 0 : write(warnstr,*) subname, 'aero_cons(k),puny:', aero_cons(k),puny
771 0 : call icepack_warnings_add(warnstr)
772 0 : write(warnstr,*) subname, 'aerotot,aerotot0 ',aerotot(k),aerotot0(k)
773 0 : call icepack_warnings_add(warnstr)
774 0 : write(warnstr,*) subname, ' aerosno(k,2),aerosno(k,1) ', aerosno(k,2),aerosno(k,1)
775 0 : call icepack_warnings_add(warnstr)
776 0 : write(warnstr,*) subname, 'flux_bio_atm(k)*aicen*dt', &
777 0 : flux_bio_atm(k)*aicen*dt
778 0 : call icepack_warnings_add(warnstr)
779 0 : write(warnstr,*) subname, 'zbgc_snow(k)', &
780 0 : zbgc_snow(k)
781 0 : call icepack_warnings_add(warnstr)
782 0 : write(warnstr,*) subname, 'zbgc_atm(k)', &
783 0 : zbgc_atm(k)
784 0 : call icepack_warnings_add(warnstr)
785 : endif
786 : enddo
787 :
788 : !-------------------------------------------------------------------
789 : ! reload tracers
790 : !-------------------------------------------------------------------
791 285295 : if (dzssl_new > puny .and. dzint_new > puny .and. vsnon > puny) then
792 3560208 : do k = 1,nbtrcr
793 3274920 : trcrn(bio_index(k)+nblyr+1)=aerosno(k,1)/dzssl_new
794 3560208 : trcrn(bio_index(k)+nblyr+2)=aerosno(k,2)/dzint_new
795 : enddo
796 : else
797 28 : do k = 1,nbtrcr
798 21 : trcrn(bio_index(k)+nblyr+1)= c0
799 28 : trcrn(bio_index(k)+nblyr+2)= c0
800 : enddo
801 : endif
802 :
803 : !-------------------------------------------------------------------
804 : ! check for negative values
805 : !-------------------------------------------------------------------
806 6835177 : if (minval(aerosno(:,1)) < -puny .or. &
807 : minval(aerosno(:,2)) < -puny) then
808 :
809 0 : write(warnstr,*) subname, 'Snow aerosol negative in update_snow_bgc'
810 0 : call icepack_warnings_add(warnstr)
811 0 : write(warnstr,*) subname, 'aicen= ' ,aicen
812 0 : call icepack_warnings_add(warnstr)
813 0 : write(warnstr,*) subname, 'vicen= ' ,vicen
814 0 : call icepack_warnings_add(warnstr)
815 0 : write(warnstr,*) subname, 'vsnon= ' ,vsnon
816 0 : call icepack_warnings_add(warnstr)
817 0 : write(warnstr,*) subname, 'viceold= ' ,vice_old
818 0 : call icepack_warnings_add(warnstr)
819 0 : write(warnstr,*) subname, 'vsnoold= ' ,vsno_old
820 0 : call icepack_warnings_add(warnstr)
821 0 : write(warnstr,*) subname, 'melts= ' ,melts
822 0 : call icepack_warnings_add(warnstr)
823 0 : write(warnstr,*) subname, 'meltt= ' ,meltt
824 0 : call icepack_warnings_add(warnstr)
825 0 : write(warnstr,*) subname, 'meltb= ' ,meltb
826 0 : call icepack_warnings_add(warnstr)
827 0 : write(warnstr,*) subname, 'congel= ' ,congel
828 0 : call icepack_warnings_add(warnstr)
829 0 : write(warnstr,*) subname, 'snoice= ' ,snoice
830 0 : call icepack_warnings_add(warnstr)
831 0 : write(warnstr,*) subname, 'aero evap snow= ' ,dhs_evap
832 0 : call icepack_warnings_add(warnstr)
833 0 : write(warnstr,*) subname, 'fsnow= ' ,fsnow
834 0 : call icepack_warnings_add(warnstr)
835 0 : do k = 1, nbtrcr
836 0 : write(warnstr,*) subname, 'NBTRCR value k = ', k
837 0 : call icepack_warnings_add(warnstr)
838 0 : write(warnstr,*) subname, 'aero snowssl (k)= ' ,aerosno0(k,1)
839 0 : call icepack_warnings_add(warnstr)
840 0 : write(warnstr,*) subname, 'aero new snowssl (k)= ',aerosno(k,1)
841 0 : call icepack_warnings_add(warnstr)
842 0 : write(warnstr,*) subname, 'aero snowint (k)= ' ,aerosno0(k,2)
843 0 : call icepack_warnings_add(warnstr)
844 0 : write(warnstr,*) subname, 'aero new snowint(k)= ',aerosno(k,2)
845 0 : call icepack_warnings_add(warnstr)
846 0 : write(warnstr,*) subname, 'flux_bio_atm(k)= ' , flux_bio_atm(k)
847 0 : call icepack_warnings_add(warnstr)
848 0 : write(warnstr,*) subname, 'zbgc_snow(k)= ' ,zbgc_snow(k)
849 0 : call icepack_warnings_add(warnstr)
850 0 : write(warnstr,*) subname, 'zbgc_atm(k)= ' ,zbgc_atm(k)
851 0 : call icepack_warnings_add(warnstr)
852 :
853 0 : do n = 1,2
854 0 : trcrn(bio_index(k)+nblyr+n)=max(trcrn(bio_index(k)+nblyr+n), c0)
855 : enddo
856 : enddo
857 : endif
858 : endif
859 :
860 660884 : end subroutine update_snow_bgc
861 :
862 : !=======================================================================
863 :
864 : end module icepack_aerosol
865 :
866 : !=======================================================================
|