LCOV - code coverage report
Current view: top level - columnphysics - icepack_aerosol.F90 (source / functions) Coverage Total Hit
Test: 250115-224328:3d8b76b919:4:base,io,travis,quick Lines: 70.69 % 423 299
Test Date: 2025-01-15 16:24:29 Functions: 100.00 % 2 2

            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              : !=======================================================================
        

Generated by: LCOV version 2.0-1