LCOV - code coverage report
Current view: top level - icepack/columnphysics - icepack_aerosol.F90 (source / functions) Hit Total Coverage
Test: 200629-175621:c6c20bf86f:7:first,base,travis,decomp,reprosum,io,quick Lines: 335 443 75.62 %
Date: 2020-06-29 18:01:52 Functions: 2 2 100.00 %

          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, puny, rhoi, rhos, hs_min
      12             :       use icepack_parameters, only: hi_ssl, hs_ssl
      13             :       use icepack_tracers, only: max_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             : !  Increase aerosol in ice or snow surface due to deposition
      31             : !  and vertical cycling
      32             : 
      33    52109425 :       subroutine update_aerosol(dt,                   &
      34             :                                 nilyr,    nslyr,      &
      35             :                                 n_aero,     &
      36             :                                 meltt,    melts,      &
      37             :                                 meltb,    congel,     &
      38             :                                 snoice,               &
      39             :                                 fsnow,                &
      40    52109425 :                                 aerosno,  aeroice,    &
      41             :                                 aice_old,             &
      42             :                                 vice_old, vsno_old,   &
      43             :                                 vicen, vsnon, aicen,  &
      44   104218850 :                                 faero_atm, faero_ocn)
      45             : 
      46             :       integer (kind=int_kind), intent(in) :: &
      47             :          nilyr, nslyr, n_aero
      48             : 
      49             :       real (kind=dbl_kind), intent(in) :: &
      50             :          dt,       & ! time step
      51             :          meltt,    & ! thermodynamic melt/growth rates
      52             :          melts,    &
      53             :          meltb,    &
      54             :          congel,   &
      55             :          snoice,   &
      56             :          fsnow,    &
      57             :          vicen,    & ! ice volume (m)
      58             :          vsnon,    & ! snow volume (m)
      59             :          aicen,    & ! ice area fraction
      60             :          aice_old, & ! values prior to thermodynamic changes
      61             :          vice_old, &
      62             :          vsno_old 
      63             : 
      64             :       real (kind=dbl_kind), dimension(:), &
      65             :          intent(in) :: &
      66             :          faero_atm   ! aerosol deposition rate (W/m^2 s)
      67             : 
      68             :       real (kind=dbl_kind), dimension(:), &
      69             :          intent(inout) :: &
      70             :          faero_ocn   ! aerosol flux to ocean (W/m^2 s)
      71             : 
      72             :       real (kind=dbl_kind), dimension(:,:), intent(inout) :: &
      73             :          aerosno,  aeroice    ! kg/m^2
      74             : 
      75             :       !  local variables
      76             :       integer (kind=int_kind) :: k
      77             : 
      78             :       real (kind=dbl_kind) :: &
      79     3952149 :          dzssl,  dzssl_new,      & ! snow ssl thickness
      80     3952149 :          dzint,                  & ! snow interior thickness
      81     3952149 :          dzssli, dzssli_new,     & ! ice ssl thickness
      82     3952149 :          dzinti,                 & ! ice interior thickness
      83     3952149 :          dznew,                  & ! tracks thickness changes
      84     7904298 :          hs, hi,                 & ! snow/ice thickness (m)
      85     7904298 :          dhs_evap, dhi_evap,     & ! snow/ice thickness change due to evap
      86     7904298 :          dhs_melts, dhi_meltt,   & ! ... due to surface melt
      87     7904298 :          dhs_snoice, dhi_snoice, & ! ... due to snow-ice formation
      88     7904298 :          dhi_congel, dhi_meltb,  & ! ... due to bottom growth, melt
      89     7904298 :          hslyr, hilyr,           & ! snow, ice layer thickness (m)
      90     7904298 :          hslyr_old, hilyr_old,   & ! old snow, ice layer thickness (m)
      91     7904298 :          hs_old, hi_old,         & ! old snow, ice thickness (m)
      92     3952149 :          sloss1, sloss2,         & ! aerosol mass loss (kg/m^2)
      93     3952149 :          ar                        ! 1/aicen(i,j)
      94             : 
      95             :       real (kind=dbl_kind), dimension(max_aero) :: &
      96             :          kscav, kscavsi       ! scavenging by melt water
      97             : 
      98             :       real (kind=dbl_kind), dimension(n_aero) :: &
      99   108170999 :          aerotot, aerotot0, & ! for conservation check
     100   104218850 :          focn_old             ! for conservation check
     101             : 
     102             :       ! echmod:  this assumes max_aero=6
     103             :       data kscav   / .03_dbl_kind, .20_dbl_kind, .02_dbl_kind, &
     104             :                      .02_dbl_kind, .01_dbl_kind, .01_dbl_kind / 
     105             :       data kscavsi / .03_dbl_kind, .20_dbl_kind, .02_dbl_kind, &
     106             :                      .02_dbl_kind, .01_dbl_kind, .01_dbl_kind / 
     107             : 
     108             :      character(len=*),parameter :: subname='(update_aerosol)'
     109             : 
     110             :     !-------------------------------------------------------------------
     111             :     ! initialize
     112             :     !-------------------------------------------------------------------
     113   104218850 :       focn_old(:) = faero_ocn(:)
     114             :       
     115    52109425 :       hs_old    = vsno_old/aice_old
     116    52109425 :       hi_old    = vice_old/aice_old
     117    52109425 :       hslyr_old = hs_old/real(nslyr,kind=dbl_kind)
     118    52109425 :       hilyr_old = hi_old/real(nilyr,kind=dbl_kind)
     119             :       
     120    52109425 :       dzssl  = min(hslyr_old/c2, hs_ssl)
     121    52109425 :       dzssli = min(hilyr_old/c2, hi_ssl)
     122    52109425 :       dzint  = hs_old - dzssl
     123    52109425 :       dzinti = hi_old - dzssli
     124             :       
     125    52109425 :       if (aicen > c0) then
     126    52109425 :          ar = c1/aicen
     127    52109425 :          hs = vsnon*ar
     128    52109425 :          hi = vicen*ar
     129    52109425 :          dhs_melts  = -melts*ar
     130    52109425 :          dhi_snoice = snoice*ar
     131    52109425 :          dhs_snoice = dhi_snoice*rhoi/rhos
     132    52109425 :          dhi_meltt  = -meltt*ar
     133    52109425 :          dhi_meltb  = -meltb*ar
     134    52109425 :          dhi_congel = congel*ar
     135             :       else ! ice disappeared during time step
     136           0 :          hs = vsnon/aice_old
     137           0 :          hi = vicen/aice_old
     138           0 :          dhs_melts  = -melts/aice_old
     139           0 :          dhi_snoice = snoice/aice_old
     140           0 :          dhs_snoice = dhi_snoice*rhoi/rhos
     141           0 :          dhi_meltt  = -meltt/aice_old
     142           0 :          dhi_meltb  = -meltb/aice_old
     143           0 :          dhi_congel = congel/aice_old
     144             :       endif
     145             :       
     146             :       dhs_evap = hs - (hs_old + dhs_melts - dhs_snoice &
     147    52109425 :                               + fsnow/rhos*dt)
     148             :       dhi_evap = hi - (hi_old + dhi_meltt + dhi_meltb &
     149    52109425 :                               + dhi_congel + dhi_snoice)
     150             : 
     151   104218850 :       do k = 1, n_aero
     152     3952149 :          aerotot0(k) = aerosno(k,2) + aerosno(k,1) &
     153   104218850 :                      + aeroice(k,2) + aeroice(k,1)
     154             :       enddo
     155             :       
     156             :     !-------------------------------------------------------------------
     157             :     ! evaporation
     158             :     !-------------------------------------------------------------------
     159    52109425 :       dzint  = dzint  + min(dzssl  + dhs_evap, c0)
     160    52109425 :       dzinti = dzinti + min(dzssli + dhi_evap, c0)
     161    52109425 :       dzssl  = max(dzssl  + dhs_evap, c0)
     162    52109425 :       dzssli = max(dzssli + dhi_evap, c0)
     163             : 
     164             :     !-------------------------------------------------------------------
     165             :     ! basal ice growth
     166             :     !-------------------------------------------------------------------
     167    52109425 :       dzinti = dzinti + dhi_congel
     168             : 
     169             :     !-------------------------------------------------------------------
     170             :     ! surface snow melt
     171             :     !-------------------------------------------------------------------
     172    52109425 :       if (-dhs_melts > puny) then
     173     7316724 :          do k = 1, n_aero
     174     3658362 :             sloss1 = c0
     175     3658362 :             sloss2 = c0
     176     3658362 :             if (dzssl > puny)  &
     177       14836 :                  sloss1 = kscav(k)*aerosno(k,1)  &
     178     3657867 :                                   *min(-dhs_melts,dzssl)/dzssl
     179     3658362 :             aerosno(k,1) = aerosno(k,1) - sloss1
     180     3658362 :             if (dzint > puny)  &
     181       14838 :                  sloss2 = kscav(k)*aerosno(k,2) &
     182     3658058 :                                   *max(-dhs_melts-dzssl,c0)/dzint
     183     3658362 :             aerosno(k,2) = aerosno(k,2) - sloss2
     184     7316724 :             faero_ocn(k) = faero_ocn(k) + (sloss1+sloss2)/dt
     185             :          enddo  ! n_aero
     186             : 
     187             :          ! update snow thickness
     188     3658362 :          dzint=dzint+min(dzssl+dhs_melts, c0)
     189     3658362 :          dzssl=max(dzssl+dhs_melts, c0)
     190             : 
     191     3658362 :          if ( dzssl <= puny ) then ! ssl melts away
     192     1100956 :             aerosno(:,2) = aerosno(:,1) + aerosno(:,2)
     193     1100956 :             aerosno(:,1) = c0
     194      550478 :             dzssl = max(dzssl, c0)
     195             :          endif
     196     3658362 :          if (dzint <= puny ) then  ! all snow melts away
     197           0 :             aeroice(:,1) = aeroice(:,1) &
     198     1017598 :                          + aerosno(:,1) + aerosno(:,2)
     199     2543995 :             aerosno(:,:) = c0
     200      508799 :             dzint = max(dzint, c0)
     201             :          endif
     202             :       endif
     203             : 
     204             :     !-------------------------------------------------------------------
     205             :     ! surface ice melt
     206             :     !-------------------------------------------------------------------
     207    52109425 :       if (-dhi_meltt > puny) then
     208     3424344 :          do k = 1, n_aero
     209     1712172 :             sloss1 = c0
     210     1712172 :             sloss2 = c0
     211     1712172 :             if (dzssli > puny)  &
     212         359 :                  sloss1 = kscav(k)*aeroice(k,1)  &
     213     1711803 :                                   *min(-dhi_meltt,dzssli)/dzssli
     214     1712172 :             aeroice(k,1) = aeroice(k,1) - sloss1
     215     1712172 :             if (dzinti > puny)  &
     216         378 :                  sloss2 = kscav(k)*aeroice(k,2)  &
     217     1712172 :                                   *max(-dhi_meltt-dzssli,c0)/dzinti
     218     1712172 :             aeroice(k,2) = aeroice(k,2) - sloss2
     219     3424344 :             faero_ocn(k) = faero_ocn(k) + (sloss1+sloss2)/dt
     220             :          enddo
     221             :          
     222     1712172 :          dzinti = dzinti + min(dzssli+dhi_meltt, c0)
     223     1712172 :          dzssli = max(dzssli+dhi_meltt, c0)
     224     1712172 :          if (dzssli <= puny) then   ! ssl ice melts away
     225        1962 :             do k = 1, n_aero
     226         981 :                aeroice(k,2) = aeroice(k,1) + aeroice(k,2)
     227        1962 :                aeroice(k,1) = c0
     228             :             enddo
     229         981 :             dzssli = max(dzssli, c0)
     230             :          endif
     231     1712172 :          if (dzinti <= puny) then   ! all ice melts away
     232           0 :             do k = 1, n_aero
     233           0 :                faero_ocn(k) = faero_ocn(k)  &
     234           0 :                             + (aeroice(k,1)+aeroice(k,2))/dt
     235           0 :                aeroice(k,:)=c0
     236             :             enddo
     237           0 :             dzinti = max(dzinti, c0)
     238             :          endif
     239             :       endif
     240             : 
     241             :     !-------------------------------------------------------------------
     242             :     ! basal ice melt.  Assume all aero lost in basal melt
     243             :     !-------------------------------------------------------------------
     244    52109425 :       if (-dhi_meltb > puny) then
     245    28633562 :          do k=1,n_aero
     246    14316781 :             sloss1=c0
     247    14316781 :             sloss2=c0
     248    14316781 :             if (dzssli > puny)  &
     249             :                  sloss1 = max(-dhi_meltb-dzinti, c0)  &
     250    14315664 :                         *aeroice(k,1)/dzssli
     251    14316781 :             aeroice(k,1) = aeroice(k,1) - sloss1
     252    14316781 :             if (dzinti > puny)  &
     253             :                  sloss2 = min(-dhi_meltb, dzinti)  &
     254    14315918 :                         *aeroice(k,2)/dzinti
     255    14316781 :             aeroice(k,2) = aeroice(k,2) - sloss2
     256    28633562 :             faero_ocn(k) = faero_ocn(k) + (sloss1+sloss2)/dt
     257             :          enddo
     258             : 
     259    14316781 :          dzssli = dzssli + min(dzinti+dhi_meltb, c0)
     260    14316781 :          dzinti = max(dzinti+dhi_meltb, c0)           
     261             :       endif
     262             : 
     263             :     !-------------------------------------------------------------------
     264             :     ! snowfall
     265             :     !-------------------------------------------------------------------
     266    52109425 :       if (fsnow > c0) dzssl = dzssl + fsnow/rhos*dt
     267             : 
     268             :     !-------------------------------------------------------------------
     269             :     ! snow-ice formation
     270             :     !-------------------------------------------------------------------
     271    52109425 :       if (dhs_snoice > puny) then
     272     2862578 :          do k = 1, n_aero
     273     1431289 :             sloss1 = c0
     274     1431289 :             sloss2 = c0
     275     1431289 :             if (dzint > puny)  &
     276             :                  sloss2 = min(dhs_snoice, dzint)  &
     277     1431289 :                         *aerosno(k,2)/dzint
     278     1431289 :             aerosno(k,2) = aerosno(k,2) - sloss2
     279     1431289 :             if (dzssl > puny)  &
     280             :                  sloss1 = max(dhs_snoice-dzint, c0)  &
     281     1431289 :                         *aerosno(k,1)/dzssl
     282     1431289 :             aerosno(k,1) = aerosno(k,1) - sloss1
     283      178248 :             aeroice(k,1) = aeroice(k,1) &
     284     1431289 :                          + (c1-kscavsi(k))*(sloss2+sloss1)
     285      178248 :             faero_ocn(k) = faero_ocn(k) &
     286     2862578 :                          + kscavsi(k)*(sloss2+sloss1)/dt
     287             :          enddo
     288     1431289 :          dzssl  = dzssl - max(dhs_snoice-dzint, c0)
     289     1431289 :          dzint  = max(dzint-dhs_snoice, c0)
     290     1431289 :          dzssli = dzssli + dhi_snoice
     291             :       endif
     292             : 
     293             :     !-------------------------------------------------------------------
     294             :     ! aerosol deposition
     295             :     !-------------------------------------------------------------------
     296    52109425 :       if (aicen > c0) then
     297    52109425 :          hs = vsnon * ar
     298             :       else
     299           0 :          hs = c0
     300             :       endif
     301    52109425 :       if (hs > hs_min) then    ! should this really be hs_min or 0? 
     302             :          ! should use same hs_min value as in radiation
     303   100464474 :          do k=1,n_aero
     304     3938636 :             aerosno(k,1) = aerosno(k,1) &
     305   100464474 :                          + faero_atm(k)*dt*aicen
     306             :          enddo
     307             :       else
     308     3754376 :          do k=1,n_aero
     309       13513 :             aeroice(k,1) = aeroice(k,1) &
     310     3754376 :                          + faero_atm(k)*dt*aicen
     311             :          enddo
     312             :       endif
     313             : 
     314             :     !-------------------------------------------------------------------
     315             :     ! redistribute aerosol within vertical layers
     316             :     !-------------------------------------------------------------------
     317    52109425 :       if (aicen > c0) then
     318    52109425 :          hs = vsnon  * ar     ! new snow thickness
     319    52109425 :          hi = vicen  * ar     ! new ice thickness
     320             :       else
     321           0 :          hs = c0
     322           0 :          hi = c0
     323             :       endif
     324    52109425 :       if (dzssl <= puny) then   ! nothing in SSL
     325     3624234 :          do k=1,n_aero
     326     1812117 :             aerosno(k,2) = aerosno(k,2) + aerosno(k,1)
     327     3624234 :             aerosno(k,1) = c0
     328             :          enddo
     329             :       endif
     330    52109425 :       if (dzint <= puny) then   ! nothing in Snow Int
     331     5825724 :          do k = 1, n_aero
     332     2912862 :             aeroice(k,1) = aeroice(k,1) + aerosno(k,2)
     333     5825724 :             aerosno(k,2) = c0
     334             :          enddo
     335             :       endif
     336    52109425 :       if (dzssli <= puny) then  ! nothing in Ice SSL
     337    14225800 :          do k = 1, n_aero
     338     7112900 :             aeroice(k,2) = aeroice(k,2) + aeroice(k,1)
     339    14225800 :             aeroice(k,1) = c0
     340             :          enddo
     341             :       endif
     342             :       
     343    52109425 :       if (dzinti <= puny) then  ! nothing in Ice INT
     344    12314730 :          do k = 1, n_aero
     345      466902 :             faero_ocn(k) = faero_ocn(k) &
     346     6157365 :                          + (aeroice(k,1)+aeroice(k,2))/dt
     347    24629460 :             aeroice(k,:)=c0
     348             :          enddo
     349             :       endif
     350             :       
     351    52109425 :       hslyr      = hs/real(nslyr,kind=dbl_kind)
     352    52109425 :       hilyr      = hi/real(nilyr,kind=dbl_kind)
     353    52109425 :       dzssl_new  = min(hslyr/c2, hs_ssl)
     354    52109425 :       dzssli_new = min(hilyr/c2, hi_ssl)
     355             : 
     356    52109425 :       if (hs > hs_min) then
     357   100464474 :          do k = 1, n_aero
     358    50232237 :             dznew = min(dzssl_new-dzssl, c0)
     359    50232237 :             sloss1 = c0
     360    50232237 :             if (dzssl > puny) &
     361    50201138 :                  sloss1 = dznew*aerosno(k,1)/dzssl ! not neccesarily a loss
     362    50232237 :             dznew = max(dzssl_new-dzssl, c0)
     363    50232237 :             if (dzint > puny) &
     364    49110445 :                  sloss1 = sloss1 + aerosno(k,2)*dznew/dzint
     365    50232237 :             aerosno(k,1) = aerosno(k,1) + sloss1 
     366   100464474 :             aerosno(k,2) = aerosno(k,2) - sloss1
     367             :          enddo
     368             :       else
     369           0 :          aeroice(:,1) = aeroice(:,1)  &
     370     3754376 :                       + aerosno(:,1) + aerosno(:,2)
     371     9385940 :          aerosno(:,:) = c0
     372             :       endif
     373             :       
     374    52109425 :       if (vicen > puny) then ! may want a limit on hi instead?
     375   104167618 :          do k = 1, n_aero
     376    52083809 :             sloss2 = c0
     377    52083809 :             dznew = min(dzssli_new-dzssli, c0)
     378    52083809 :             if (dzssli > puny) & 
     379    44978425 :                  sloss2 = dznew*aeroice(k,1)/dzssli
     380    52083809 :             dznew = max(dzssli_new-dzssli, c0)
     381    52083809 :             if (dzinti > puny) & 
     382    45944544 :                  sloss2 = sloss2 + aeroice(k,2)*dznew/dzinti
     383    52083809 :             aeroice(k,1) = aeroice(k,1) + sloss2 
     384   104167618 :             aeroice(k,2) = aeroice(k,2) - sloss2
     385             :          enddo
     386             :       else
     387       51232 :          faero_ocn(:) = faero_ocn(:) + (aeroice(:,1)+aeroice(:,2))/dt
     388      128080 :          aeroice(:,:) = c0
     389             :       endif
     390             :       
     391             :     !-------------------------------------------------------------------
     392             :     ! check conservation
     393             :     !-------------------------------------------------------------------
     394   104218850 :       do k = 1, n_aero
     395     3952149 :          aerotot(k) = aerosno(k,2) + aerosno(k,1) &
     396    52109425 :                     + aeroice(k,2) + aeroice(k,1)
     397    56061574 :          if ((aerotot(k)-aerotot0(k)) &
     398     3952149 :               - (   faero_atm(k)*aicen &
     399    56061574 :               - (faero_ocn(k)-focn_old(k)) )*dt  > puny) then
     400             : 
     401           0 :             write(warnstr,*) subname, 'aerosol tracer:  ',k
     402           0 :             call icepack_warnings_add(warnstr)
     403           0 :             write(warnstr,*) subname, 'aerotot-aerotot0 ',aerotot(k)-aerotot0(k)
     404           0 :             call icepack_warnings_add(warnstr)
     405           0 :             write(warnstr,*) subname, 'faero_atm-faero_ocn      ', &
     406           0 :                  (faero_atm(k)*aicen-(faero_ocn(k)-focn_old(k)))*dt
     407           0 :             call icepack_warnings_add(warnstr)
     408             :          endif
     409             :       enddo
     410             : 
     411             :     !-------------------------------------------------------------------
     412             :     ! check for negative values
     413             :     !-------------------------------------------------------------------
     414             : 
     415             : !echmod:  note that this does not test or fix all aero tracers         
     416     3952149 :       if (aeroice(1,1) < -puny .or. &
     417     3952149 :           aeroice(1,2) < -puny .or. &
     418    52109425 :           aerosno(1,1) < -puny .or. &
     419             :           aerosno(1,2) < -puny) then
     420             : 
     421           0 :          write(warnstr,*) subname, 'aerosol negative in aerosol code'
     422           0 :          call icepack_warnings_add(warnstr)
     423             : 
     424           0 :          aeroice(1,1) = max(aeroice(1,1), c0)
     425           0 :          aeroice(1,2) = max(aeroice(1,2), c0)
     426           0 :          aerosno(1,1) = max(aerosno(1,1), c0)
     427           0 :          aerosno(1,2) = max(aerosno(1,2), c0)
     428             : 
     429             :       endif
     430             : 
     431    52109425 :       end subroutine update_aerosol
     432             : 
     433             : !=======================================================================
     434             : 
     435             : !  Increase aerosol in snow surface due to deposition
     436             : !  and vertical cycling : after update_aerosol
     437             : 
     438    29415679 :       subroutine update_snow_bgc (dt,     nblyr,       &
     439             :                                 nslyr,                 &
     440             :                                 meltt,    melts,       &
     441             :                                 meltb,    congel,      &
     442             :                                 snoice,   nbtrcr,      &
     443             :                                 fsnow,    ntrcr,       &
     444    29415679 :                                 trcrn,    bio_index,   &
     445    29415679 :                                 aice_old, zbgc_snow,   &
     446             :                                 vice_old, vsno_old,    &
     447             :                                 vicen,    vsnon,       &
     448    29415679 :                                 aicen,    flux_bio_atm,&
     449    29415679 :                                 zbgc_atm, flux_bio)
     450             : 
     451             :       integer (kind=int_kind), intent(in) :: &
     452             :          nbtrcr,             & ! number of distinct snow tracers
     453             :          nblyr,              & ! number of bio layers
     454             :          nslyr,              & ! number of snow layers
     455             :          ntrcr                 ! number of tracers
     456             : 
     457             :       integer (kind=int_kind), dimension (nbtrcr), intent(in) :: &
     458             :          bio_index       
     459             : 
     460             :       real (kind=dbl_kind), intent(in) :: &
     461             :          dt                    ! time step
     462             : 
     463             :       real (kind=dbl_kind), intent(in) :: &
     464             :          meltt,    & ! thermodynamic melt/growth rates
     465             :          melts,    &
     466             :          meltb,    &
     467             :          congel,   &
     468             :          snoice,   &
     469             :          fsnow,    &
     470             :          vicen,    & ! ice volume (m)
     471             :          vsnon,    & ! snow volume (m)
     472             :          aicen,    & ! ice area fraction
     473             :          aice_old, & ! values prior to thermodynamic changes
     474             :          vice_old, &
     475             :          vsno_old 
     476             : 
     477             :       real (kind=dbl_kind),dimension(nbtrcr), intent(inout) :: &
     478             :          zbgc_snow, & ! aerosol contribution from snow to ice
     479             :          zbgc_atm,  & ! and atm to ice concentration * volume (kg or mmol/m^3*m)
     480             :          flux_bio     ! total ocean tracer flux (mmol/m^2/s)
     481             : 
     482             :       real (kind=dbl_kind), dimension(nbtrcr), &
     483             :          intent(in) :: &
     484             :          flux_bio_atm   ! aerosol deposition rate (kg or mmol/m^2 s)
     485             : 
     486             :       real (kind=dbl_kind), dimension(ntrcr), &
     487             :          intent(inout) :: &
     488             :          trcrn       ! ice/snow tracer array
     489             : 
     490             :       !  local variables
     491             : 
     492             :       integer (kind=int_kind) ::  k, n
     493             : 
     494             :       real (kind=dbl_kind) :: &
     495       80291 :          dzssl,  dzssl_new,      & ! snow ssl thickness
     496       80291 :          dzint,  dzint_new,      & ! snow interior thickness
     497       80291 :          hs,                     & ! snow thickness (m)
     498       80291 :          dhs_evap,               & ! snow thickness change due to evap
     499       80291 :          dhs_melts,              & ! ... due to surface melt
     500       80291 :          dhs_snoice,             & ! ... due to snow-ice formation
     501       80291 :          hslyr,                  & ! snow layer thickness (m)
     502       80291 :          hslyr_old,              & ! old snow layer thickness (m)
     503       80291 :          hs_old,                 & ! old snow thickness (m)
     504       80291 :          dznew,                  & ! change in the snow sl (m)
     505       80291 :          sloss1, sloss2,         & ! aerosol mass loss (kg/m^2)
     506       80291 :          ar                        ! 1/aicen(i,j)
     507             : 
     508             :       real (kind=dbl_kind), dimension(nbtrcr) :: &
     509    61802125 :          aerotot, aerotot0, & ! for conservation check (mmol/m^3)
     510    60276596 :          aero_cons        , & ! for conservation check (mmol/m^2)
     511    60276596 :          flux_bio_o           ! initial ocean tracer flux (mmol/m^2/s)
     512             : 
     513             :       real (kind=dbl_kind), dimension(nbtrcr,2) :: &
     514    61962707 :          aerosno,  & ! kg/m^2
     515    62042998 :          aerosno0    ! for diagnostic prints
     516             : 
     517             :       character(len=*),parameter :: subname='(update_snow_bgc)'
     518             : 
     519             :     !-------------------------------------------------------------------
     520             :     ! initialize
     521             :     !-------------------------------------------------------------------
     522  1206042839 :          aerosno (:,:) = c0
     523  1206042839 :          aerosno0(:,:) = c0
     524   588313580 :          aero_cons(:) = c0
     525   588313580 :          zbgc_snow(:) = c0
     526   588313580 :          zbgc_atm(:) = c0
     527             : 
     528    29415679 :          hs_old    = vsno_old/aice_old
     529    29415679 :          hslyr_old = hs_old/real(nslyr,kind=dbl_kind)
     530             : 
     531    29415679 :          dzssl  = min(hslyr_old/c2, hs_ssl)
     532    29415679 :          dzint  = hs_old - dzssl
     533             : 
     534    29415679 :          if (aicen > c0) then
     535    29415679 :             ar = c1/aicen
     536    29415679 :             hs = vsnon*ar
     537    29415679 :             dhs_melts  = -melts
     538    29415679 :             dhs_snoice = snoice*rhoi/rhos
     539             :          else ! ice disappeared during time step
     540           0 :             ar = c1
     541           0 :             hs = vsnon/aice_old
     542           0 :             dhs_melts  = -melts
     543           0 :             dhs_snoice = snoice*rhoi/rhos
     544             :          endif
     545             : 
     546             :          dhs_evap = hs - (hs_old + dhs_melts - dhs_snoice &
     547    29415679 :                                  + fsnow/rhos*dt)
     548             : 
     549             :          ! trcrn() has units kg/m^3
     550             : 
     551    29415679 :       if ((vsno_old .le. puny) .or. (vsnon .le. puny)) then
     552             : 
     553    24968601 :          do k=1,nbtrcr
     554      152817 :             flux_bio(k) = flux_bio(k) +  &
     555      305634 :                          (trcrn(bio_index(k)+ nblyr+1)*dzssl+ &
     556    22743456 :                           trcrn(bio_index(k)+ nblyr+2)*dzint)/dt  
     557    22590639 :             trcrn(bio_index(k) + nblyr+1) = c0
     558    22590639 :             trcrn(bio_index(k) + nblyr+2) = c0
     559      152817 :             zbgc_atm(k) = zbgc_atm(k) &
     560    23779620 :                                 + flux_bio_atm(k)*dt 
     561             :          enddo
     562             : 
     563             :       else 
     564             :          
     565   564533960 :          do k=1,nbtrcr
     566   536307262 :             flux_bio_o(k) = flux_bio(k)
     567   536307262 :             aerosno (k,1) = trcrn(bio_index(k)+ nblyr+1) * dzssl
     568   536307262 :             aerosno (k,2) = trcrn(bio_index(k)+ nblyr+2) * dzint
     569  1608921786 :             aerosno0(k,:) = aerosno(k,:)
     570   564533960 :             aerotot0(k)   = aerosno(k,2) + aerosno(k,1) 
     571             :          enddo
     572             : 
     573             :     !-------------------------------------------------------------------
     574             :     ! evaporation
     575             :     !-------------------------------------------------------------------
     576    28226698 :          dzint  = dzint  + min(dzssl  + dhs_evap, c0)
     577    28226698 :          dzssl  = max(dzssl  + dhs_evap, c0)
     578             : 
     579             :     !-------------------------------------------------------------------
     580             :     ! surface snow melt
     581             :     !-------------------------------------------------------------------
     582    28226698 :          if (-dhs_melts > puny) then
     583    15376560 :             do k = 1, nbtrcr
     584    14607732 :                sloss1 = c0
     585    14607732 :                sloss2 = c0
     586    14607732 :                if (dzssl > puny)  &
     587        2299 :                   sloss1 = kscavz(k)*aerosno(k,1)  &
     588    14607428 :                                    *min(-dhs_melts,dzssl)/dzssl
     589    14607732 :                aerosno(k,1) = aerosno(k,1) - sloss1
     590    14607732 :                if (dzint > puny)  &
     591        2318 :                    sloss2 = kscavz(k)*aerosno(k,2) &
     592    14607732 :                                     *max(-dhs_melts-dzssl,c0)/dzint
     593    14607732 :                aerosno(k,2) = aerosno(k,2) - sloss2
     594    15376560 :                zbgc_snow(k) = zbgc_snow(k) + (sloss1+sloss2)
     595             :             enddo  ! 
     596             : 
     597             :             ! update snow thickness
     598      768828 :             dzint=dzint+min(dzssl+dhs_melts, c0)
     599      768828 :             dzssl=max(dzssl+dhs_melts, c0)
     600             : 
     601      768828 :             if ( dzssl <= puny ) then ! ssl melts away
     602      306120 :                aerosno(:,2) = aerosno(:,1) + aerosno(:,2)
     603      306120 :                aerosno(:,1) = c0
     604       15306 :                dzssl = max(dzssl, c0)
     605             :             endif
     606      768828 :             if (dzint <= puny ) then  ! all snow melts away
     607           0 :                zbgc_snow(:) = zbgc_snow(:) &
     608         460 :                                 + max(c0,aerosno(:,1) + aerosno(:,2))
     609         943 :                aerosno(:,:) = c0
     610          23 :                dzint = max(dzint, c0)
     611             :             endif
     612             :          endif
     613             : 
     614             :     !-------------------------------------------------------------------
     615             :     ! snowfall
     616             :     !-------------------------------------------------------------------
     617    28226698 :          if (fsnow > c0) dzssl = dzssl + fsnow/rhos*dt 
     618             : 
     619             :     !-------------------------------------------------------------------
     620             :     ! snow-ice formation
     621             :     !-------------------------------------------------------------------
     622    28226698 :          if (dhs_snoice > puny) then
     623    20403880 :             do k = 1, nbtrcr
     624    19383686 :                sloss1 = c0
     625    19383686 :                sloss2 = c0
     626    19383686 :                if (dzint > puny)  &
     627             :                   sloss2 = min(dhs_snoice, dzint)  &
     628    19383686 :                            *aerosno(k,2)/dzint
     629    19383686 :                aerosno(k,2) = aerosno(k,2) - sloss2
     630    19383686 :                if (dzssl > puny)  &
     631             :                   sloss1 = max(dhs_snoice-dzint, c0)  &
     632    19377663 :                            *aerosno(k,1)/dzssl
     633    19383686 :                aerosno(k,1) = aerosno(k,1) - sloss1
     634        4351 :                zbgc_snow(k) = zbgc_snow(k) &
     635    20403880 :                                + (sloss2+sloss1)
     636             :             enddo
     637     1020194 :             dzssl  = dzssl - max(dhs_snoice-dzint, c0)
     638     1020194 :             dzint  = max(dzint-dhs_snoice, c0)
     639             :          endif
     640             : 
     641             :     !-------------------------------------------------------------------
     642             :     ! aerosol deposition
     643             :     !-------------------------------------------------------------------
     644    28226698 :          if (aicen > c0) then
     645    28226698 :             hs = vsnon * ar
     646             :          else
     647           0 :             hs = c0
     648             :          endif
     649    28226698 :          if (hs >= hs_min)  then !should this really be hs_min or 0? 
     650             :                                   ! should use same hs_min value as in radiation
     651   550551700 :             do k=1,nbtrcr
     652     1173421 :                aerosno(k,1) = aerosno(k,1) &
     653   550551700 :                                 + flux_bio_atm(k)*dt
     654             :             enddo
     655             :          else  
     656    13982260 :             do k=1,nbtrcr
     657      199291 :                zbgc_atm(k) = zbgc_atm(k) &
     658    13982260 :                                 + flux_bio_atm(k)*dt
     659             :             enddo
     660             :          endif
     661             : 
     662             :     !-------------------------------------------------------------------
     663             :     ! redistribute aerosol within vertical layers
     664             :     !-------------------------------------------------------------------
     665    28226698 :          if (aicen > c0) then
     666    28226698 :             hs = vsnon  * ar     ! new snow thickness
     667             :          else
     668           0 :             hs = c0
     669             :          endif
     670    28226698 :          if (dzssl <= puny) then   ! nothing in SSL
     671      356860 :             do k=1,nbtrcr
     672      339017 :                aerosno(k,2) = aerosno(k,2) + aerosno(k,1)
     673      356860 :                aerosno(k,1) = c0
     674             :             enddo
     675             :          endif
     676    28226698 :          if (dzint <= puny) then   ! nothing in Snow Int
     677    14944340 :             do k = 1, nbtrcr
     678    14197123 :                zbgc_snow(k) = zbgc_snow(k) + max(c0,aerosno(k,2))
     679    14944340 :                aerosno(k,2) = c0
     680             :             enddo
     681             :          endif
     682             : 
     683    28226698 :          hslyr      = hs/real(nslyr,kind=dbl_kind)
     684    28226698 :          dzssl_new  = min(hslyr/c2, hs_ssl)
     685    28226698 :          dzint_new  = hs - dzssl_new
     686             : 
     687    28226698 :          if (hs > hs_min) then !should this really be hs_min or 0? 
     688   550551700 :             do k = 1, nbtrcr
     689   523024115 :                dznew = min(dzssl_new-dzssl, c0)
     690   523024115 :                sloss1 = c0
     691   523024115 :                if (dzssl > puny) &
     692   522763074 :                   sloss1 = dznew*aerosno(k,1)/dzssl ! not neccesarily a loss
     693   523024115 :                   dznew = max(dzssl_new-dzssl, c0)
     694   523024115 :                if (dzint > puny) &
     695   518820004 :                   sloss1 = sloss1 + aerosno(k,2)*dznew/dzint
     696   523024115 :                aerosno(k,1) = aerosno(k,1) + sloss1 
     697   550551700 :                aerosno(k,2) = aerosno(k,2) - sloss1
     698             :             enddo
     699             :          else
     700           0 :             zbgc_snow(:) = zbgc_snow(:)  &
     701    13982260 :                              + max(c0,aerosno(:,1) + aerosno(:,2))
     702    28663633 :             aerosno(:,:) = c0
     703             :          endif
     704             : 
     705             :     !-------------------------------------------------------------------
     706             :     ! check conservation
     707             :     !-------------------------------------------------------------------
     708   564533960 :          do k = 1, nbtrcr
     709     1372712 :             aerotot(k) = aerosno(k,2) + aerosno(k,1) &
     710   536307262 :                        + zbgc_snow(k) + zbgc_atm(k) 
     711     1372712 :             aero_cons(k) = aerotot(k)-aerotot0(k) &
     712     1372712 :                           - (    flux_bio_atm(k) & 
     713   536307262 :                           - (flux_bio(k)-flux_bio_o(k))) * dt
     714   564533960 :             if (aero_cons(k)  > puny .or. zbgc_snow(k) + zbgc_atm(k) < c0) then             
     715           0 :                write(warnstr,*) subname, 'Conservation failure: aerosols in snow'
     716           0 :                call icepack_warnings_add(warnstr)
     717           0 :                write(warnstr,*) subname, 'test aerosol 1'
     718           0 :                call icepack_warnings_add(warnstr)
     719           0 :                write(warnstr,*) subname, 'aerosol tracer:  ',k
     720           0 :                call icepack_warnings_add(warnstr)
     721           0 :                write(warnstr,*) subname, 'aero_cons(k),puny:', aero_cons(k),puny
     722           0 :                call icepack_warnings_add(warnstr)
     723           0 :                write(warnstr,*) subname, 'aerotot,aerotot0 ',aerotot(k),aerotot0(k)
     724           0 :                call icepack_warnings_add(warnstr)
     725           0 :                write(warnstr,*) subname, ' aerosno(k,2),aerosno(k,1) ', aerosno(k,2),aerosno(k,1)
     726           0 :                call icepack_warnings_add(warnstr)
     727           0 :                write(warnstr,*) subname, 'flux_bio_atm(k)*aicen*dt', &
     728           0 :                     flux_bio_atm(k)*aicen*dt
     729           0 :                call icepack_warnings_add(warnstr)
     730           0 :                write(warnstr,*) subname, 'zbgc_snow(k)', &
     731           0 :                     zbgc_snow(k)
     732           0 :                call icepack_warnings_add(warnstr)
     733           0 :                write(warnstr,*) subname, 'zbgc_atm(k)', &
     734           0 :                     zbgc_atm(k)
     735           0 :                call icepack_warnings_add(warnstr)
     736             :             endif
     737             :          enddo
     738             : 
     739             :     !-------------------------------------------------------------------
     740             :     ! reload tracers
     741             :     !-------------------------------------------------------------------
     742    28226698 :          if (vsnon > puny) then
     743   564533960 :          do k = 1,nbtrcr
     744   536307262 :              trcrn(bio_index(k)+nblyr+1)=aerosno(k,1)/dzssl_new 
     745   564533960 :              trcrn(bio_index(k)+nblyr+2)=aerosno(k,2)/dzint_new
     746             :          enddo
     747             :          else
     748           0 :          do k = 1,nbtrcr
     749           0 :             zbgc_snow(k) = (zbgc_snow(k) + aerosno(k,1) + aerosno(k,2))
     750           0 :             trcrn(bio_index(k)+nblyr+1)= c0
     751           0 :             trcrn(bio_index(k)+nblyr+2)= c0
     752             :          enddo
     753             :          endif
     754             :     !-------------------------------------------------------------------
     755             :     ! check for negative values
     756             :     !-------------------------------------------------------------------
     757  1100913470 :          if (minval(aerosno(:,1)) < -puny  .or. &
     758       72248 :             minval(aerosno(:,2)) < -puny) then
     759             : 
     760           0 :             write(warnstr,*) subname, 'Snow aerosol negative in update_snow_bgc'
     761           0 :             call icepack_warnings_add(warnstr)
     762           0 :             write(warnstr,*) subname, 'aicen= '      ,aicen
     763           0 :             call icepack_warnings_add(warnstr)
     764           0 :             write(warnstr,*) subname, 'vicen= '      ,vicen
     765           0 :             call icepack_warnings_add(warnstr)
     766           0 :             write(warnstr,*) subname, 'vsnon= '      ,vsnon
     767           0 :             call icepack_warnings_add(warnstr)
     768           0 :             write(warnstr,*) subname, 'viceold= '    ,vice_old
     769           0 :             call icepack_warnings_add(warnstr)
     770           0 :             write(warnstr,*) subname, 'vsnoold= '    ,vsno_old
     771           0 :             call icepack_warnings_add(warnstr)
     772           0 :             write(warnstr,*) subname, 'melts= '      ,melts
     773           0 :             call icepack_warnings_add(warnstr)
     774           0 :             write(warnstr,*) subname, 'meltt= '      ,meltt
     775           0 :             call icepack_warnings_add(warnstr)
     776           0 :             write(warnstr,*) subname, 'meltb= '      ,meltb
     777           0 :             call icepack_warnings_add(warnstr)
     778           0 :             write(warnstr,*) subname, 'congel= '     ,congel
     779           0 :             call icepack_warnings_add(warnstr)
     780           0 :             write(warnstr,*) subname, 'snoice= '     ,snoice
     781           0 :             call icepack_warnings_add(warnstr)
     782           0 :             write(warnstr,*) subname, 'aero evap snow= '  ,dhs_evap
     783           0 :             call icepack_warnings_add(warnstr)
     784           0 :             write(warnstr,*) subname, 'fsnow= '      ,fsnow
     785           0 :             call icepack_warnings_add(warnstr)
     786           0 :             do k = 1, nbtrcr
     787           0 :               write(warnstr,*) subname, 'NBTRCR value k = ', k
     788           0 :               call icepack_warnings_add(warnstr)
     789           0 :               write(warnstr,*) subname, 'aero snowssl (k)= '    ,aerosno0(k,1)
     790           0 :               call icepack_warnings_add(warnstr)
     791           0 :               write(warnstr,*) subname, 'aero new snowssl (k)= ',aerosno(k,1)
     792           0 :               call icepack_warnings_add(warnstr)
     793           0 :               write(warnstr,*) subname, 'aero snowint (k)= '    ,aerosno0(k,2)
     794           0 :               call icepack_warnings_add(warnstr)
     795           0 :               write(warnstr,*) subname, 'aero new snowint(k)= ',aerosno(k,2)
     796           0 :               call icepack_warnings_add(warnstr)
     797           0 :               write(warnstr,*) subname, 'flux_bio_atm(k)= ' , flux_bio_atm(k)
     798           0 :               call icepack_warnings_add(warnstr)
     799           0 :               write(warnstr,*) subname, 'zbgc_snow(k)= '  ,zbgc_snow(k)
     800           0 :               call icepack_warnings_add(warnstr)
     801           0 :               write(warnstr,*) subname, 'zbgc_atm(k)= '  ,zbgc_atm(k)
     802           0 :               call icepack_warnings_add(warnstr)
     803             : 
     804    28226698 :               do n = 1,2
     805           0 :                 trcrn(bio_index(k)+nblyr+n)=max(trcrn(bio_index(k)+nblyr+n), c0)
     806             :               enddo
     807             :             enddo
     808             :          endif
     809             :         endif
     810             : 
     811    29415679 :       end subroutine update_snow_bgc
     812             : 
     813             : !=======================================================================
     814             : 
     815             :       end module icepack_aerosol
     816             : 
     817             : !=======================================================================

Generated by: LCOV version 1.14-6-g40580cd