LCOV - code coverage report
Current view: top level - icepack/columnphysics - icepack_atmo.F90 (source / functions) Hit Total Coverage
Test: 231018-211459:8916b9ff2c:1:quick Lines: 132 262 50.38 %
Date: 2023-10-18 15:30:36 Functions: 7 9 77.78 %

          Line data    Source code
       1             : !=======================================================================
       2             : 
       3             : ! Atmospheric boundary interface (stability based flux calculations)
       4             : 
       5             : ! author: Elizabeth C. Hunke, LANL
       6             : !
       7             : ! 2003: Vectorized by Clifford Chen (Fujitsu) and William Lipscomb
       8             : ! 2004: Block structure added by William Lipscomb
       9             : ! 2006: Converted to free source form (F90) by Elizabeth Hunke
      10             : ! 2013: Form drag routine added (neutral_drag_coeffs) by David Schroeder
      11             : ! 2014: Adjusted form drag and added high frequency coupling by Andrew Roberts
      12             : 
      13             :       module icepack_atmo
      14             : 
      15             :       use icepack_kinds
      16             :       use icepack_parameters, only: c0, c1, c2, c4, c5, c8, c10
      17             :       use icepack_parameters, only: c16, c20, p001, p01, p2, p4, p5, p75, puny
      18             :       use icepack_parameters, only: senscoef, latncoef
      19             :       use icepack_parameters, only: cp_wv, cp_air, iceruf, zref, qqqice, TTTice, qqqocn, TTTocn
      20             :       use icepack_parameters, only: Lsub, Lvap, vonkar, Tffresh, zvir, gravit
      21             :       use icepack_parameters, only: pih, dragio, rhoi, rhos, rhow
      22             :       use icepack_parameters, only: atmbndy, calc_strair, formdrag
      23             :       use icepack_parameters, only: icepack_chkoptargflag
      24             :       use icepack_tracers, only: n_iso
      25             :       use icepack_tracers, only: tr_iso
      26             :       use icepack_warnings, only: warnstr, icepack_warnings_add
      27             :       use icepack_warnings, only: icepack_warnings_setabort, icepack_warnings_aborted
      28             : 
      29             :       implicit none
      30             : 
      31             :       private
      32             :       public :: neutral_drag_coeffs, &
      33             :                 icepack_atm_boundary
      34             : 
      35             : !=======================================================================
      36             : 
      37             :       contains
      38             : 
      39             : !=======================================================================
      40             : 
      41             : ! Compute coefficients for atm/ice fluxes, stress, and reference
      42             : ! temperature and humidity. NOTE:
      43             : ! (1) All fluxes are positive downward,
      44             : ! (2) Here, tstar = (WT)/U*, and qstar = (WQ)/U*,
      45             : ! (3a) wind speeds should all be above a minimum speed (eg. 1.0 m/s).
      46             : !
      47             : ! ASSUME:
      48             : !  The saturation humidity of air at T(K): qsat(T)  (kg/m**3)
      49             : !
      50             : ! Code originally based on CSM1
      51             : 
      52    46176939 :       subroutine atmo_boundary_layer (sfctype,            &
      53             :                                       calc_strair, formdrag, &   ! LCOV_EXCL_LINE
      54             :                                       Tsf,      potT,     &   ! LCOV_EXCL_LINE
      55             :                                       uatm,     vatm,     &   ! LCOV_EXCL_LINE
      56             :                                       wind,     zlvl,     &   ! LCOV_EXCL_LINE
      57             :                                       Qa,       rhoa,     &   ! LCOV_EXCL_LINE
      58             :                                       strx,     stry,     &   ! LCOV_EXCL_LINE
      59             :                                       Tref,     Qref,     &   ! LCOV_EXCL_LINE
      60             :                                       delt,     delq,     &   ! LCOV_EXCL_LINE
      61             :                                       lhcoef,   shcoef,   &   ! LCOV_EXCL_LINE
      62             :                                       Cdn_atm,            &   ! LCOV_EXCL_LINE
      63             :                                       Cdn_atm_ratio_n,    &   ! LCOV_EXCL_LINE
      64             :                                       Qa_iso,   Qref_iso, &   ! LCOV_EXCL_LINE
      65             :                                       uvel,     vvel,     &   ! LCOV_EXCL_LINE
      66             :                                       Uref,     zlvs      )
      67             : 
      68             :       use icepack_parameters, only: highfreq, natmiter, atmiter_conv
      69             : 
      70             :       character (len=3), intent(in) :: &
      71             :          sfctype      ! ice or ocean
      72             : 
      73             :       logical (kind=log_kind), intent(in) :: &
      74             :          calc_strair, &  ! if true, calculate wind stress components   ! LCOV_EXCL_LINE
      75             :          formdrag        ! if true, calculate form drag
      76             : 
      77             :       real (kind=dbl_kind), intent(in) :: &
      78             :          Tsf      , & ! surface temperature of ice or ocean   ! LCOV_EXCL_LINE
      79             :          potT     , & ! air potential temperature  (K)   ! LCOV_EXCL_LINE
      80             :          uatm     , & ! x-direction wind speed (m/s)   ! LCOV_EXCL_LINE
      81             :          vatm     , & ! y-direction wind speed (m/s)   ! LCOV_EXCL_LINE
      82             :          wind     , & ! wind speed (m/s)   ! LCOV_EXCL_LINE
      83             :          zlvl     , & ! atm level height (m)   ! LCOV_EXCL_LINE
      84             :          Qa       , & ! specific humidity (kg/kg)   ! LCOV_EXCL_LINE
      85             :          rhoa         ! air density (kg/m^3)
      86             : 
      87             :       real (kind=dbl_kind), intent(inout) :: &
      88             :          Cdn_atm      ! neutral drag coefficient
      89             : 
      90             :       real (kind=dbl_kind), intent(inout) :: &
      91             :          Cdn_atm_ratio_n ! ratio drag coeff / neutral drag coeff
      92             : 
      93             :       real (kind=dbl_kind), intent(inout) :: &
      94             :          strx     , & ! x surface stress (N)   ! LCOV_EXCL_LINE
      95             :          stry         ! y surface stress (N)
      96             : 
      97             :       real (kind=dbl_kind), intent(inout) :: &
      98             :          Tref     , & ! reference height temperature  (K)   ! LCOV_EXCL_LINE
      99             :          Qref     , & ! reference height specific humidity (kg/kg)   ! LCOV_EXCL_LINE
     100             :          delt     , & ! potential T difference   (K)   ! LCOV_EXCL_LINE
     101             :          delq     , & ! humidity difference      (kg/kg)   ! LCOV_EXCL_LINE
     102             :          shcoef   , & ! transfer coefficient for sensible heat   ! LCOV_EXCL_LINE
     103             :          lhcoef       ! transfer coefficient for latent heat
     104             : 
     105             :       real (kind=dbl_kind), intent(in), dimension(:), optional :: &
     106             :          Qa_iso       ! specific isotopic humidity (kg/kg)
     107             : 
     108             :       real (kind=dbl_kind), intent(inout), dimension(:), optional :: &
     109             :          Qref_iso     ! reference specific isotopic humidity (kg/kg)
     110             : 
     111             :       real (kind=dbl_kind), intent(in) :: &
     112             :          uvel     , & ! x-direction ice speed (m/s)   ! LCOV_EXCL_LINE
     113             :          vvel         ! y-direction ice speed (m/s)
     114             : 
     115             :       real (kind=dbl_kind), intent(out) :: &
     116             :          Uref         ! reference height wind speed (m/s)
     117             : 
     118             :       real (kind=dbl_kind), intent(in), optional :: &
     119             :          zlvs        ! atm level height (scalar quantities) (m)
     120             : 
     121             :       ! local variables
     122             : 
     123             :       integer (kind=int_kind) :: &
     124             :          k,n         ! iteration index
     125             : 
     126             :       real (kind=dbl_kind) :: &
     127             :          TsfK  , & ! surface temperature in Kelvin (K)   ! LCOV_EXCL_LINE
     128             :          psimh , & ! stability function at zlvl   (momentum)   ! LCOV_EXCL_LINE
     129             :          tau   , & ! stress at zlvl   ! LCOV_EXCL_LINE
     130             :          fac   , & ! interpolation factor   ! LCOV_EXCL_LINE
     131             :          al2   , & ! ln(z10   /zTrf)   ! LCOV_EXCL_LINE
     132             :          psix2 , & ! stability function at zTrf   (heat and water)   ! LCOV_EXCL_LINE
     133             :          ssq   , & ! sat surface humidity     (kg/kg)   ! LCOV_EXCL_LINE
     134             :          qqq   , & ! for qsat, dqsfcdt   ! LCOV_EXCL_LINE
     135             :          TTT   , & ! for qsat, dqsfcdt   ! LCOV_EXCL_LINE
     136             :          qsat  , & ! the saturation humidity of air (kg/m^3)   ! LCOV_EXCL_LINE
     137             :          Lheat , & ! Lvap or Lsub, depending on surface type   ! LCOV_EXCL_LINE
     138     6371954 :          umin      ! minimum wind speed (m/s)
     139             : 
     140             :       real (kind=dbl_kind) :: &
     141             :          ustar , & ! ustar (m/s)   ! LCOV_EXCL_LINE
     142             :          ustar_prev , & ! ustar_prev (m/s)   ! LCOV_EXCL_LINE
     143             :          tstar , & ! tstar   ! LCOV_EXCL_LINE
     144             :          qstar , & ! qstar   ! LCOV_EXCL_LINE
     145             :          ratio , & ! ratio   ! LCOV_EXCL_LINE
     146             :          rdn   , & ! sqrt of neutral exchange coefficient (momentum)   ! LCOV_EXCL_LINE
     147             :          rhn   , & ! sqrt of neutral exchange coefficient (heat)   ! LCOV_EXCL_LINE
     148             :          ren   , & ! sqrt of neutral exchange coefficient (water)   ! LCOV_EXCL_LINE
     149             :          rd    , & ! sqrt of exchange coefficient (momentum)   ! LCOV_EXCL_LINE
     150             :          re    , & ! sqrt of exchange coefficient (water)   ! LCOV_EXCL_LINE
     151             :          rh    , & ! sqrt of exchange coefficient (heat)   ! LCOV_EXCL_LINE
     152             :          vmag  , & ! surface wind magnitude   (m/s)   ! LCOV_EXCL_LINE
     153             :          alzm  , & ! ln(zlvl  /z10)   ! LCOV_EXCL_LINE
     154             :          alzs  , & ! ln(zlvs  /z10) (if zlvs present)   ! LCOV_EXCL_LINE
     155             :          thva  , & ! virtual temperature      (K)   ! LCOV_EXCL_LINE
     156             :          cp    , & ! specific heat of moist air   ! LCOV_EXCL_LINE
     157             :          holm  , & ! H (at zlvl  ) over L   ! LCOV_EXCL_LINE
     158             :          hols  , & ! H (at zlvs  ) over L (if zlvs present)   ! LCOV_EXCL_LINE
     159             :          stable, & ! stability factor   ! LCOV_EXCL_LINE
     160             :          cpvir , & ! defined as cp_wv/cp_air - 1.   ! LCOV_EXCL_LINE
     161     6371954 :          psixh     ! stability function at zlvl (at zlvs if present) (heat and water)
     162             : 
     163             :       real (kind=dbl_kind), parameter :: &
     164             :          zTrf  = c2     ! reference height for air temp (m)
     165             : 
     166             :       character(len=*),parameter :: subname='(atmo_boundary_layer)'
     167             : 
     168    46176939 :       al2 = log(zref/zTrf)
     169             : 
     170             :       !------------------------------------------------------------
     171             :       ! Initialize
     172             :       !------------------------------------------------------------
     173             : 
     174    46176939 :       cpvir = cp_wv/cp_air-c1   ! defined as cp_wv/cp_air - 1.
     175             : 
     176    46176939 :       if (highfreq) then
     177           0 :        umin  = p5 ! minumum allowable wind-ice speed difference of 0.5 m/s
     178             :       else
     179    46176939 :        umin  = c1 ! minumum allowable wind speed of 1m/s
     180             :       endif
     181             : 
     182    46176939 :       Tref = c0
     183    46176939 :       Qref = c0
     184    46176939 :       Uref = c0
     185    46176939 :       delt = c0
     186    46176939 :       delq = c0
     187    46176939 :       shcoef = c0
     188    46176939 :       lhcoef = c0
     189             : 
     190             :       !------------------------------------------------------------
     191             :       ! Compute turbulent flux coefficients, wind stress, and
     192             :       ! reference temperature and humidity.
     193             :       !------------------------------------------------------------
     194             : 
     195             :       !------------------------------------------------------------
     196             :       ! define variables that depend on surface type
     197             :       !------------------------------------------------------------
     198             : 
     199    46176939 :       if (sfctype(1:3)=='ice') then
     200             : 
     201    33852099 :          qqq   = qqqice          ! for qsat
     202    33852099 :          TTT   = TTTice          ! for qsat
     203    33852099 :          Lheat = Lsub            ! ice to vapor
     204             : 
     205    33852099 :             if (highfreq) then
     206             :                vmag = max(umin, sqrt( (uatm-uvel)**2 + &
     207           0 :                                       (vatm-vvel)**2) )
     208             :             else
     209    33852099 :                vmag = max(umin, wind)
     210             :             endif
     211             : 
     212    33852099 :             if (formdrag .and. Cdn_atm > puny) then
     213           0 :                rdn = sqrt(Cdn_atm)
     214             :             else
     215    33852099 :                rdn  = vonkar/log(zref/iceruf) ! neutral coefficient
     216    33852099 :                Cdn_atm = rdn * rdn
     217             :             endif
     218             : 
     219    12324840 :       elseif (sfctype(1:3)=='ocn') then
     220             : 
     221    12324840 :          qqq   = qqqocn
     222    12324840 :          TTT   = TTTocn
     223    12324840 :          Lheat = Lvap           ! liquid to vapor
     224    12324840 :          vmag = max(umin, wind)
     225             :          rdn  = sqrt(0.0027_dbl_kind/vmag &
     226    12324840 :               + .000142_dbl_kind + .0000764_dbl_kind*vmag)
     227             : 
     228             :       endif   ! sfctype
     229             : 
     230             :       !------------------------------------------------------------
     231             :       ! define some more needed variables
     232             :       !------------------------------------------------------------
     233             : 
     234    46176939 :       TsfK = Tsf + Tffresh     ! surface temp (K)
     235    46176939 :       delt = potT - TsfK       ! pot temp diff (K)
     236    46176939 :       qsat = qqq * exp(-TTT/TsfK)   ! saturation humidity (kg/m^3)
     237    46176939 :       ssq  = qsat / rhoa       ! sat surf hum (kg/kg)
     238             : 
     239    46176939 :       thva = potT * (c1 + zvir * Qa) ! virtual pot temp (K)
     240    46176939 :       delq = Qa - ssq          ! spec hum dif (kg/kg)
     241    46176939 :       alzm = log(zlvl/zref)
     242    46176939 :       if (present(zlvs)) then
     243    33852099 :          alzs = log(zlvs/zref)
     244             :       else
     245    12324840 :          alzs = alzm
     246             :       endif
     247    46176939 :       cp   = cp_air*(c1 + cpvir*ssq)
     248             : 
     249             :       !------------------------------------------------------------
     250             :       ! first estimate of Z/L and ustar, tstar and qstar
     251             :       !------------------------------------------------------------
     252             : 
     253             :       ! neutral coefficients, z/L = 0.0
     254    46176939 :       rhn = rdn
     255    46176939 :       ren = rdn
     256             : 
     257             :       ! ustar,tstar,qstar
     258    46176939 :       ustar = rdn * vmag
     259    46176939 :       tstar = rhn * delt
     260    46176939 :       qstar = ren * delq
     261             : 
     262             :       !------------------------------------------------------------
     263             :       ! iterate to converge on Z/L, ustar, tstar and qstar
     264             :       !------------------------------------------------------------
     265             : 
     266    46176939 :       ustar_prev = c2 * ustar
     267             : 
     268    46176939 :       k = 1
     269   276153750 :       do while (abs(ustar - ustar_prev)/ustar > atmiter_conv .and. k <= natmiter)
     270   229976811 :          k = k + 1
     271   229976811 :          ustar_prev = ustar
     272             : 
     273             :          ! compute stability & evaluate all stability functions
     274             :          holm = compute_stability_parameter(zlvl , thva , &   ! LCOV_EXCL_LINE
     275             :                                            ustar, tstar, &   ! LCOV_EXCL_LINE
     276   229976811 :                                            qstar, Qa)
     277   229976811 :          if (present(zlvs)) then
     278             :             hols = compute_stability_parameter(zlvs , thva , &
     279             :                                                ustar, tstar, &   ! LCOV_EXCL_LINE
     280   168580187 :                                                qstar, Qa)
     281             :          else
     282    61396624 :             hols = holm
     283             :          endif
     284             : 
     285   229976811 :          call compute_stability_function('momentum', holm, stable, psimh)
     286   229976811 :          call compute_stability_function('scalar'  , hols, stable, psixh)
     287             : 
     288             :          ! shift all coeffs to measurement height and stability
     289   229976811 :          rd = rdn / (c1+rdn/vonkar*(alzm-psimh))
     290   229976811 :          rh = rhn / (c1+rhn/vonkar*(alzs-psixh))
     291   229976811 :          re = ren / (c1+ren/vonkar*(alzs-psixh))
     292             : 
     293             :          ! update ustar, tstar, qstar using updated, shifted coeffs
     294   229976811 :          ustar = rd * vmag
     295   229976811 :          tstar = rh * delt
     296   229976811 :          qstar = re * delq
     297             : 
     298             :       enddo                     ! end iteration
     299             : 
     300    46176939 :       if (calc_strair) then
     301             : 
     302             :          ! initialize
     303    46176939 :          strx = c0
     304    46176939 :          stry = c0
     305             : 
     306    46176939 :          if (highfreq .and. sfctype(1:3)=='ice') then
     307             : 
     308             :             !------------------------------------------------------------
     309             :             ! momentum flux for high frequency coupling (RASM/CESM)
     310             :             !------------------------------------------------------------
     311             :             ! tau = rhoa * rd * rd
     312             :             ! strx = tau * |Uatm-U| * (uatm-u)
     313             :             ! stry = tau * |Uatm-U| * (vatm-v)
     314             :             !------------------------------------------------------------
     315             : 
     316           0 :             tau = rhoa * rd * rd ! not the stress at zlvl
     317             : 
     318             :             ! high frequency momentum coupling following Roberts et al. (2014)
     319           0 :             strx = tau * sqrt((uatm-uvel)**2 + (vatm-vvel)**2) * (uatm-uvel)
     320           0 :             stry = tau * sqrt((uatm-uvel)**2 + (vatm-vvel)**2) * (vatm-vvel)
     321             : 
     322             :          else
     323             : 
     324             :             !------------------------------------------------------------
     325             :             ! momentum flux
     326             :             !------------------------------------------------------------
     327             :             ! tau = rhoa * ustar * ustar
     328             :             ! strx = tau * uatm / vmag
     329             :             ! stry = tau * vatm / vmag
     330             :             !------------------------------------------------------------
     331             : 
     332    46176939 :             tau = rhoa * ustar * rd ! not the stress at zlvl
     333    46176939 :             strx = tau * uatm
     334    46176939 :             stry = tau * vatm
     335             : 
     336             :          endif
     337             : 
     338    46176939 :          Cdn_atm_ratio_n = rd * rd / rdn / rdn
     339             : 
     340             :       endif                     ! calc_strair
     341             : 
     342             :       !------------------------------------------------------------
     343             :       ! coefficients for turbulent flux calculation
     344             :       !------------------------------------------------------------
     345             :       ! add windless coefficient for sensible heat flux
     346             :       ! as in Jordan et al (JGR, 1999)
     347             :       !------------------------------------------------------------
     348             : 
     349    46176939 :       if (trim(atmbndy) == 'mixed') then
     350             :          !- Use constant coefficients for sensible and latent heat fluxes
     351             :          !    similar to atmo_boundary_const but using vmag instead of wind
     352           0 :          shcoef = senscoef*cp_air*rhoa*vmag
     353           0 :          lhcoef = latncoef*Lheat *rhoa*vmag
     354             :       else ! 'similarity'
     355             :          !- Monin-Obukhov similarity theory for boundary layer
     356    46176939 :          shcoef = rhoa * ustar * cp * rh + c1
     357    46176939 :          lhcoef = rhoa * ustar * Lheat  * re
     358             :       endif
     359             : 
     360             :       !------------------------------------------------------------
     361             :       ! Compute diagnostics: 2m ref T, Q, U
     362             :       !------------------------------------------------------------
     363             : 
     364    46176939 :       hols  = hols*zTrf/zlvl
     365    46176939 :       psix2 = -c5*hols*stable + (c1-stable)*psi_scalar_unstable(hols)
     366             :       fac   = (rh/vonkar) &
     367    46176939 :             * (alzs + al2 - psixh + psix2)
     368    46176939 :       Tref  = potT - delt*fac
     369    46176939 :       Tref  = Tref - p01*zTrf ! pot temp to temp correction
     370             :       fac   = (re/vonkar) &
     371    46176939 :             * (alzs + al2 - psixh + psix2)
     372    46176939 :       Qref  = Qa - delq*fac
     373             : 
     374    46176939 :       if (highfreq .and. sfctype(1:3)=='ice') then
     375           0 :          Uref = sqrt((uatm-uvel)**2 + (vatm-vvel)**2) * rd / rdn
     376             :       else
     377    46176939 :          Uref = vmag * rd / rdn
     378             :       endif
     379             : 
     380    46176939 :       if (tr_iso .and. sfctype(1:3)=='ice') then
     381           0 :          Qref_iso(:) = c0
     382           0 :          do n = 1, n_iso
     383           0 :             ratio = c0
     384           0 :             if (Qa_iso(2) > puny) ratio = Qa_iso(n)/Qa_iso(2)
     385           0 :             Qref_iso(n) = Qa_iso(n) - ratio*delq*fac
     386             :          enddo
     387             :       endif
     388             : 
     389    46176939 :       end subroutine atmo_boundary_layer
     390             : 
     391             : !=======================================================================
     392             : 
     393             : ! Compute coefficients for atm/ice fluxes, stress
     394             : ! NOTE: \\
     395             : ! (1) all fluxes are positive downward,  \\
     396             : ! (2) reference temperature and humidity are NOT computed
     397             : 
     398           0 :       subroutine atmo_boundary_const (sfctype,  calc_strair, &
     399             :                                       uatm,     vatm,     &   ! LCOV_EXCL_LINE
     400             :                                       wind,     rhoa,     &   ! LCOV_EXCL_LINE
     401             :                                       strx,     stry,     &   ! LCOV_EXCL_LINE
     402             :                                       Tsf,      potT,     &   ! LCOV_EXCL_LINE
     403             :                                       Qa,                 &   ! LCOV_EXCL_LINE
     404             :                                       delt,     delq,     &   ! LCOV_EXCL_LINE
     405             :                                       lhcoef,   shcoef    )
     406             : 
     407             :       character (len=3), intent(in) :: &
     408             :          sfctype      ! ice or ocean
     409             : 
     410             :       logical (kind=log_kind), intent(in) :: &
     411             :          calc_strair  ! if true, calculate wind stress components
     412             : 
     413             :       real (kind=dbl_kind), intent(in) :: &
     414             :          Tsf      , & ! surface temperature of ice or ocean   ! LCOV_EXCL_LINE
     415             :          potT     , & ! air potential temperature  (K)   ! LCOV_EXCL_LINE
     416             :          Qa       , & ! specific humidity (kg/kg)   ! LCOV_EXCL_LINE
     417             :          uatm     , & ! x-direction wind speed (m/s)   ! LCOV_EXCL_LINE
     418             :          vatm     , & ! y-direction wind speed (m/s)   ! LCOV_EXCL_LINE
     419             :          wind     , & ! wind speed (m/s)   ! LCOV_EXCL_LINE
     420             :          rhoa         ! air density (kg/m^3)
     421             : 
     422             :       real (kind=dbl_kind), intent(inout):: &
     423             :          strx     , & ! x surface stress (N)   ! LCOV_EXCL_LINE
     424             :          stry         ! y surface stress (N)
     425             : 
     426             :       real (kind=dbl_kind), intent(out):: &
     427             :          delt     , & ! potential T difference   (K)   ! LCOV_EXCL_LINE
     428             :          delq     , & ! humidity difference      (kg/kg)   ! LCOV_EXCL_LINE
     429             :          shcoef   , & ! transfer coefficient for sensible heat   ! LCOV_EXCL_LINE
     430             :          lhcoef       ! transfer coefficient for latent heat
     431             : 
     432             :        ! local variables
     433             : 
     434             :       real (kind=dbl_kind) :: &
     435             :          TsfK, & ! surface temperature in Kelvin (K)   ! LCOV_EXCL_LINE
     436             :          qsat, & ! the saturation humidity of air (kg/m^3)   ! LCOV_EXCL_LINE
     437             :          ssq , & ! sat surface humidity     (kg/kg)   ! LCOV_EXCL_LINE
     438             :          tau, &  ! stress at zlvl   ! LCOV_EXCL_LINE
     439           0 :          Lheat   ! Lvap or Lsub, depending on surface type
     440             : 
     441             :       character(len=*),parameter :: subname='(atmo_boundary_const)'
     442             : 
     443             :       !------------------------------------------------------------
     444             :       ! Initialize
     445             :       !------------------------------------------------------------
     446             : 
     447           0 :       delt = c0
     448           0 :       delq = c0
     449           0 :       shcoef = c0
     450           0 :       lhcoef = c0
     451             : 
     452           0 :       if (calc_strair) then
     453             : 
     454           0 :          strx = c0
     455           0 :          stry = c0
     456             : 
     457             :       !------------------------------------------------------------
     458             :       ! momentum flux
     459             :       !------------------------------------------------------------
     460           0 :          tau = rhoa * 0.0012_dbl_kind * wind
     461             : !AOMIP         tau = rhoa * (1.10_dbl_kind + c4*p01*wind) &
     462             : !AOMIP                         * wind * p001
     463           0 :          strx = tau * uatm
     464           0 :          stry = tau * vatm
     465             : 
     466             :       endif                     ! calc_strair
     467             : 
     468             :       !------------------------------------------------------------
     469             :       ! define variables that depend on surface type
     470             :       !------------------------------------------------------------
     471             : 
     472           0 :       if (sfctype(1:3)=='ice') then
     473           0 :          Lheat = Lsub           ! ice to vapor
     474           0 :       elseif (sfctype(1:3)=='ocn') then
     475           0 :          Lheat = Lvap           ! liquid to vapor
     476             :       endif   ! sfctype
     477             : 
     478             :       !------------------------------------------------------------
     479             :       ! potential temperature and specific humidity differences
     480             :       !------------------------------------------------------------
     481             : 
     482           0 :       TsfK     = Tsf + Tffresh    ! surface temp (K)
     483           0 :       qsat     = qqqocn * exp(-TTTocn/TsfK) ! sat humidity (kg/m^3)
     484           0 :       ssq      = qsat / rhoa      ! sat surf hum (kg/kg)
     485             : 
     486           0 :       delt= potT - TsfK      ! pot temp diff (K)
     487           0 :       delq= Qa - ssq         ! spec hum dif (kg/kg)
     488             : 
     489             :       !------------------------------------------------------------
     490             :       ! coefficients for turbulent flux calculation
     491             :       !------------------------------------------------------------
     492             : 
     493           0 :       shcoef = senscoef*cp_air*rhoa*wind
     494           0 :       lhcoef = latncoef*Lheat *rhoa*wind
     495             : 
     496           0 :       end subroutine atmo_boundary_const
     497             : 
     498             : !=======================================================================
     499             : 
     500             : ! Neutral drag coefficients for ocean and atmosphere also compute the
     501             : ! intermediate necessary variables ridge height, distance, floe size
     502             : ! based upon Tsamados et al. (2014), JPO, DOI: 10.1175/JPO-D-13-0215.1.
     503             : ! Places where the code varies from the paper are commented.
     504             : !
     505             : ! authors: Michel Tsamados, CPOM
     506             : !          David Schroeder, CPOM
     507             : !
     508             : ! changes: Andrew Roberts, NPS (RASM/CESM coupling and documentation)
     509             : 
     510           0 :       subroutine neutral_drag_coeffs (apnd,     hpnd,     &
     511             :                                       ipnd,               &   ! LCOV_EXCL_LINE
     512             :                                       alvl,     vlvl,     &   ! LCOV_EXCL_LINE
     513             :                                       aice,     vice,     &   ! LCOV_EXCL_LINE
     514             :                                       vsno,     aicen,    &   ! LCOV_EXCL_LINE
     515             :                                       vicen, &   ! LCOV_EXCL_LINE
     516             :                                       Cdn_ocn,  Cdn_ocn_skin,    &   ! LCOV_EXCL_LINE
     517             :                                       Cdn_ocn_floe, Cdn_ocn_keel,&   ! LCOV_EXCL_LINE
     518             :                                       Cdn_atm,  Cdn_atm_skin,    &   ! LCOV_EXCL_LINE
     519             :                                       Cdn_atm_floe, Cdn_atm_pond,&   ! LCOV_EXCL_LINE
     520             :                                       Cdn_atm_rdg, hfreebd,      &   ! LCOV_EXCL_LINE
     521             :                                       hdraft,   hridge,          &   ! LCOV_EXCL_LINE
     522             :                                       distrdg,  hkeel,           &   ! LCOV_EXCL_LINE
     523             :                                       dkeel,    lfloe,           &   ! LCOV_EXCL_LINE
     524             :                                       dfloe,    ncat)
     525             : 
     526             :       use icepack_tracers, only: tr_pond
     527             : 
     528             :       integer (kind=int_kind), intent(in) :: &
     529             :          ncat
     530             : 
     531             :       real (kind=dbl_kind), dimension (:), intent(in) :: &
     532             :          apnd     ,& ! melt pond fraction of sea ice   ! LCOV_EXCL_LINE
     533             :          hpnd     ,& ! mean melt pond depth over sea ice   ! LCOV_EXCL_LINE
     534             :          ipnd     ,& ! mean ice pond depth over sea ice in cat n   ! LCOV_EXCL_LINE
     535             :          alvl     ,& ! level ice area fraction (of grid cell ?)   ! LCOV_EXCL_LINE
     536             :          vlvl        ! level ice mean thickness
     537             : 
     538             :       real (kind=dbl_kind), intent(in) :: &
     539             :          aice     , & ! concentration of ice   ! LCOV_EXCL_LINE
     540             :          vice     , & ! volume per unit area of ice   ! LCOV_EXCL_LINE
     541             :          vsno         ! volume per unit area of snow
     542             : 
     543             :       real (kind=dbl_kind), dimension (:), intent(in) :: &
     544             :          aicen    , & ! concentration of ice   ! LCOV_EXCL_LINE
     545             :          vicen        ! volume per unit area of ice (m)
     546             : 
     547             :       real (kind=dbl_kind), intent(out) :: &
     548             :          hfreebd      , & ! freeboard (m)   ! LCOV_EXCL_LINE
     549             :          hdraft       , & ! draught of ice + snow column (Stoessel1993)   ! LCOV_EXCL_LINE
     550             :          hridge       , & ! ridge height   ! LCOV_EXCL_LINE
     551             :          distrdg      , & ! distance between ridges   ! LCOV_EXCL_LINE
     552             :          hkeel        , & ! keel depth   ! LCOV_EXCL_LINE
     553             :          dkeel        , & ! distance between keels   ! LCOV_EXCL_LINE
     554             :          lfloe        , & ! floe length (m)   ! LCOV_EXCL_LINE
     555             :          dfloe        , & ! distance between floes   ! LCOV_EXCL_LINE
     556             :          Cdn_ocn      , & ! ocean-ice neutral drag coefficient   ! LCOV_EXCL_LINE
     557             :          Cdn_ocn_skin , & ! drag coefficient due to skin drag   ! LCOV_EXCL_LINE
     558             :          Cdn_ocn_floe , & ! drag coefficient due to floe edges   ! LCOV_EXCL_LINE
     559             :          Cdn_ocn_keel , & ! drag coefficient due to keels   ! LCOV_EXCL_LINE
     560             :          Cdn_atm      , & ! ice-atmosphere drag coefficient   ! LCOV_EXCL_LINE
     561             :          Cdn_atm_skin , & ! drag coefficient due to skin drag   ! LCOV_EXCL_LINE
     562             :          Cdn_atm_floe , & ! drag coefficient due to floe edges   ! LCOV_EXCL_LINE
     563             :          Cdn_atm_pond , & ! drag coefficient due to ponds   ! LCOV_EXCL_LINE
     564             :          Cdn_atm_rdg      ! drag coefficient due to ridges
     565             : 
     566             :       real (kind=dbl_kind), parameter :: &
     567             :                                       ! [,] = range of values that can be tested
     568             :          csw       = 0.002_dbl_kind ,&! ice-ocn drag coefficient [0.0005,0.005]
     569             :          csa       = 0.0005_dbl_kind,&! ice-air drag coefficient [0.0001,0.001]   ! LCOV_EXCL_LINE
     570             :          mrdg      = c20            ,&! screening effect see Lu2011 [5,50]   ! LCOV_EXCL_LINE
     571             :          mrdgo     = c10            ,&! screening effect see Lu2011 [5,50]   ! LCOV_EXCL_LINE
     572             :          beta      = p5             ,&! power exponent appearing in astar and   ! LCOV_EXCL_LINE
     573             :                                       ! L=Lmin(A*/(A*-A))**beta [0,1]
     574             :          Lmin      = c8             ,&! min length of floe (m) [5,100]
     575             :          Lmax      = 300._dbl_kind  ,&! max length of floe (m) [30,3000]   ! LCOV_EXCL_LINE
     576             :          cfa       = p2             ,&! Eq. 12 ratio of local from drag over   ! LCOV_EXCL_LINE
     577             :                                       ! geometrical parameter [0,1]
     578             :          cfw       = p2             ,&! Eq. 15 ratio of local from drag over
     579             :                                       ! geometrical parameter [0,1]
     580             :          cpa       = p2             ,&! Eq. 16 ratio of local form drag over
     581             :                                       ! geometrical parameter [0,1]
     582             :          cra       = p2             ,&! Eq. 10 local form drag coefficient [0,1]
     583             :          crw       = p2             ,&! Eq. 11 local form drag coefficient [0,1]   ! LCOV_EXCL_LINE
     584             :          sl        = 22._dbl_kind   ,&! Sheltering parameter Lupkes2012 [10,30]   ! LCOV_EXCL_LINE
     585             :          lpmin     = 2.26_dbl_kind  ,&! min pond length (m) see Eq. 17 [1,10]   ! LCOV_EXCL_LINE
     586             :          lpmax     = 24.63_dbl_kind ,&! max pond length (m) see Eq. 17 [10,100]   ! LCOV_EXCL_LINE
     587             :          tanar     = p4             ,&! 0.25 sail slope = 14 deg [0.4,1]   ! LCOV_EXCL_LINE
     588             :          tanak     = p4             ,&! 0.58 keel slope = 30 deg [0.4,1]   ! LCOV_EXCL_LINE
     589             :          phir      = 0.8_dbl_kind   ,&! porosity of ridges [0.4,1]   ! LCOV_EXCL_LINE
     590             :          phik      = 0.8_dbl_kind   ,&! porosity of keels  [0.4,1]   ! LCOV_EXCL_LINE
     591             :          hkoverhr  = c4             ,&! hkeel/hridge ratio [4,8]   ! LCOV_EXCL_LINE
     592             :          dkoverdr  = c1             ,&! dkeel/distrdg ratio [1,5]   ! LCOV_EXCL_LINE
     593             :          sHGB      = 0.18_dbl_kind  ,&! Lupkes2012 Eq. 28, Hanssen1988,   ! LCOV_EXCL_LINE
     594             :                                       ! Steele1989 suggest instead 0.18
     595             :          alpha2    = c0             ,&! weight functions for area of
     596             :          beta2     = p75              ! ridged ice [0,1]
     597             : 
     598             :        integer (kind=int_kind) :: &
     599             :          n            ! category index
     600             : 
     601             :       real (kind=dbl_kind) :: &
     602             :          astar,     & ! new constant for form drag   ! LCOV_EXCL_LINE
     603             :          ctecaf,    & ! constante   ! LCOV_EXCL_LINE
     604             :          ctecwf,    & ! constante   ! LCOV_EXCL_LINE
     605             :          sca,       & ! wind attenuation function   ! LCOV_EXCL_LINE
     606             :          scw,       & ! ocean attenuation function   ! LCOV_EXCL_LINE
     607             :          lp,        & ! pond length (m)   ! LCOV_EXCL_LINE
     608             :          ctecar,    &   ! LCOV_EXCL_LINE
     609             :          ctecwk,    &   ! LCOV_EXCL_LINE
     610             :          ai, aii,   & ! ice area and its inverse   ! LCOV_EXCL_LINE
     611             :          ocnrufi,   & ! inverse ocean roughness   ! LCOV_EXCL_LINE
     612             :          icerufi,   & ! inverse ice roughness   ! LCOV_EXCL_LINE
     613           0 :          tmp1         ! temporary
     614             : 
     615             :       real (kind=dbl_kind) :: &
     616             :          apond    , & ! melt pond fraction of grid cell   ! LCOV_EXCL_LINE
     617             :          ardg     , & ! ridged ice area fraction of grid cell   ! LCOV_EXCL_LINE
     618           0 :          vrdg         ! ridged ice mean thickness
     619             : 
     620             :       real (kind=dbl_kind), parameter :: &
     621             :          ocnruf   = 0.000327_dbl_kind ! ocean surface roughness (m)
     622             : 
     623             :       real (kind=dbl_kind), parameter :: &
     624             :          camax    = 0.02_dbl_kind , & ! Maximum for atmospheric drag   ! LCOV_EXCL_LINE
     625             :          cwmax    = 0.06_dbl_kind     ! Maximum for ocean drag
     626             : 
     627             :       character(len=*),parameter :: subname='(neutral_drag_coeffs)'
     628             : 
     629           0 :       astar = c1/(c1-(Lmin/Lmax)**(c1/beta))
     630             : 
     631             :       !-----------------------------------------------------------------
     632             :       ! Initialize across entire grid
     633             :       !-----------------------------------------------------------------
     634             : 
     635           0 :       ocnrufi  = c1/ocnruf    ! inverse ocean roughness
     636           0 :       icerufi  = c1/iceruf    ! inverse ice roughness
     637           0 :       hfreebd=c0
     638           0 :       hdraft =c0
     639           0 :       hridge =c0
     640           0 :       distrdg=c0
     641           0 :       hkeel  =c0
     642           0 :       dkeel  =c0
     643           0 :       lfloe  =c0
     644           0 :       dfloe  =c0
     645           0 :       Cdn_ocn=dragio
     646           0 :       Cdn_ocn_skin=c0
     647           0 :       Cdn_ocn_floe=c0
     648           0 :       Cdn_ocn_keel=c0
     649           0 :       Cdn_atm = (vonkar/log(zref/iceruf)) * (vonkar/log(zref/iceruf))
     650           0 :       Cdn_atm_skin=c0
     651           0 :       Cdn_atm_floe=c0
     652           0 :       Cdn_atm_pond=c0
     653           0 :       Cdn_atm_rdg =c0
     654             : 
     655           0 :       if (aice > p001) then
     656             : 
     657           0 :          Cdn_atm_skin = csa
     658           0 :          Cdn_ocn_skin = csw
     659             : 
     660           0 :          ai  = aice
     661           0 :          aii = c1/ai
     662             : 
     663             :       !------------------------------------------------------------
     664             :       ! Compute average quantities
     665             :       !------------------------------------------------------------
     666             : 
     667             :          ! ponds
     668           0 :          apond = c0
     669           0 :          if (tr_pond) then
     670           0 :             do n = 1,ncat
     671             :                ! area of pond per unit area of grid cell
     672           0 :                apond = apond+apnd(n)*aicen(n)
     673             :             enddo
     674             :          endif
     675             : 
     676             :          ! draft and freeboard (see Eq. 27)
     677           0 :          hdraft = (rhoi*vice+rhos*vsno)*aii/rhow ! without ponds
     678           0 :          hfreebd = (vice+vsno)*aii-hdraft
     679             : 
     680             :          ! Do not allow draft larger than ice thickness (see Eq. 28)
     681           0 :          if (hdraft >= vice*aii) then
     682             :             ! replace excess snow with ice so hi~=hdraft
     683             :             hfreebd = (hdraft*ai*(c1-rhoi/rhow) + &
     684             :                       (vsno-(vice-hdraft*ai)*rhoi/rhos) * &   ! LCOV_EXCL_LINE
     685           0 :                       (c1-rhos/rhow))*aii ! Stoessel1993
     686             :          endif
     687             : 
     688             :          ! floe size parameterization see Eq. 13
     689           0 :          lfloe = Lmin * (astar / (astar - ai))**beta
     690             : 
     691             :          ! distance between floes parameterization see Eq. 14
     692           0 :          dfloe = lfloe * (c1/sqrt(ai) - c1)
     693             : 
     694             :          ! Relate ridge height and distance between ridges to
     695             :          ! ridged ice area fraction and ridged ice mean thickness
     696             :          ! Assumes total volume of ridged ice is split into ridges and keels.
     697             :          ! Then assume total ridges volume over total area of ridges =
     698             :          ! volume of one average ridge / area of one average ridge
     699             :          ! Same for keels.
     700             : 
     701           0 :          ardg=c0
     702           0 :          vrdg=c0
     703           0 :          do n=1,ncat
     704             :             ! ridged ice area fraction over grid cell
     705           0 :             ardg=ardg+(c1-alvl(n))*aicen(n)
     706             :             ! total ridged ice volume per unit grid cell area
     707           0 :             vrdg=vrdg+(c1-vlvl(n))*vicen(n)
     708             :          enddo
     709             : 
     710             :          ! hridge, hkeel, distrdg and dkeel estimates from CICE for
     711             :          ! simple triangular geometry
     712           0 :          if (ardg > p001) then
     713             :             ! see Eq. 25 and Eq. 26
     714             :             hridge = vrdg/ardg*c2 &
     715             :                    * (alpha2+beta2*hkoverhr/dkoverdr*tanar/tanak) &   ! LCOV_EXCL_LINE
     716           0 :                    / (phir*c1+phik*tanar/tanak*hkoverhr**c2/dkoverdr)
     717             :             distrdg = c2*hridge*ai/ardg &
     718           0 :                     * (alpha2/tanar+beta2/tanak*hkoverhr/dkoverdr)
     719           0 :             hkeel = hkoverhr * hridge
     720           0 :             dkeel = dkoverdr * distrdg
     721             : 
     722             :           ! Use the height of ridges relative to the mean freeboard of
     723             :           ! the pack.  Therefore skin drag and ridge drag differ in
     724             :           ! this code as compared to  Tsamados et al. (2014) equations
     725             :           ! 10 and 18, which reference both to sea level.
     726           0 :           tmp1 = max(c0,hridge - hfreebd)
     727             : 
     728             :       !------------------------------------------------------------
     729             :       ! Skin drag (atmo)
     730             :       !------------------------------------------------------------
     731             : 
     732           0 :           Cdn_atm_skin = csa*(c1 - mrdg*tmp1/distrdg)
     733           0 :           Cdn_atm_skin = max(min(Cdn_atm_skin,camax),c0)
     734             : 
     735             :       !------------------------------------------------------------
     736             :       ! Ridge effect (atmo)
     737             :       !------------------------------------------------------------
     738             : 
     739           0 :           if (tmp1 > puny) then
     740           0 :             sca = c1 - exp(-sHGB*distrdg/tmp1) ! see Eq. 9
     741           0 :             ctecar = cra*p5
     742             :             Cdn_atm_rdg = ctecar*tmp1/distrdg*sca* &
     743           0 :                        (log(tmp1*icerufi)/log(zref*icerufi))**c2
     744           0 :             Cdn_atm_rdg = min(Cdn_atm_rdg,camax)
     745             :           endif
     746             : 
     747             :           ! Use the depth of keels relative to the mean draft of
     748             :           ! the pack.  Therefore skin drag and keel drag differ in
     749             :           ! this code as compared to  Tsamados et al. (2014) equations
     750             :           ! 11 and 19, which reference both to  sea level. In some
     751             :           ! circumstances, hkeel can be less than hdraft because hkoverhr
     752             :           ! is constant, and max(c0,...) temporarily addresses this.
     753           0 :           tmp1 = max(c0,hkeel - hdraft)
     754             : 
     755             :       !------------------------------------------------------------
     756             :       ! Skin drag bottom ice (ocean)
     757             :       !------------------------------------------------------------
     758             : 
     759           0 :           Cdn_ocn_skin = csw * (c1 - mrdgo*tmp1/dkeel)
     760           0 :           Cdn_ocn_skin = max(min(Cdn_ocn_skin,cwmax), c0)
     761             : 
     762             :       !------------------------------------------------------------
     763             :       ! Keel effect (ocean)
     764             :       !------------------------------------------------------------
     765             : 
     766           0 :           if (tmp1 > puny) then
     767           0 :             scw = c1 - exp(-sHGB*dkeel/tmp1)
     768           0 :             ctecwk = crw*p5
     769             :             Cdn_ocn_keel = ctecwk*tmp1/dkeel*scw* &
     770           0 :                         (log(tmp1*icerufi)/log(zref*icerufi))**c2
     771           0 :             Cdn_ocn_keel = max(min(Cdn_ocn_keel,cwmax),c0)
     772             :           endif
     773             : 
     774             :          endif ! ardg > 0.001
     775             : 
     776             :       !------------------------------------------------------------
     777             :       ! Floe edge drag effect (atmo)
     778             :       !------------------------------------------------------------
     779             : 
     780           0 :         if (hfreebd > puny) then
     781           0 :           sca = c1 - exp(-sl*beta*(c1-ai))
     782           0 :           ctecaf = cfa*p5*(log(hfreebd*ocnrufi)/log(zref*ocnrufi))**c2*sca
     783           0 :           Cdn_atm_floe = ctecaf * hfreebd / lfloe
     784           0 :           Cdn_atm_floe = max(min(Cdn_atm_floe,camax),c0)
     785             :         endif
     786             : 
     787             :       !------------------------------------------------------------
     788             :       ! Pond edge effect (atmo)
     789             :       !------------------------------------------------------------
     790             : 
     791           0 :         if (hfreebd > puny) then
     792           0 :           sca = (apond)**(c1/(zref*beta))
     793           0 :           lp  = lpmin*(1-apond)+lpmax*apond
     794             :           Cdn_atm_pond = cpa*p5*sca*apond*hfreebd/lp &
     795           0 :                    * (log(hfreebd*ocnrufi)/log(zref*ocnrufi))**c2
     796           0 :           Cdn_atm_pond = min(Cdn_atm_pond,camax)
     797             :         endif
     798             : 
     799             :       !------------------------------------------------------------
     800             :       ! Floe edge drag effect (ocean)
     801             :       !------------------------------------------------------------
     802             : 
     803           0 :         if (hdraft > puny) then
     804           0 :           scw = c1 - exp(-sl*beta*(c1-ai))
     805           0 :           ctecwf = cfw*p5*(log(hdraft*ocnrufi)/log(zref*ocnrufi))**c2*scw
     806           0 :           Cdn_ocn_floe = ctecwf * hdraft / lfloe
     807           0 :           Cdn_ocn_floe = max(min(Cdn_ocn_floe,cwmax),c0)
     808             :         endif
     809             : 
     810             :       !------------------------------------------------------------
     811             :       ! Total drag coefficient (atmo)
     812             :       !------------------------------------------------------------
     813             : 
     814           0 :          Cdn_atm = Cdn_atm_skin + Cdn_atm_floe + Cdn_atm_pond + Cdn_atm_rdg
     815           0 :          Cdn_atm = min(Cdn_atm,camax)
     816             : 
     817             :       !------------------------------------------------------------
     818             :       ! Total drag coefficient (ocean)
     819             :       !------------------------------------------------------------
     820             : 
     821           0 :          Cdn_ocn = Cdn_ocn_skin + Cdn_ocn_floe + Cdn_ocn_keel
     822           0 :          Cdn_ocn = min(Cdn_ocn,cwmax)
     823             : 
     824             :       endif
     825             : 
     826           0 :       end subroutine neutral_drag_coeffs
     827             : 
     828             : !=======================================================================
     829             : !autodocument_start icepack_atm_boundary
     830             : !
     831             : 
     832    46176939 :       subroutine icepack_atm_boundary(sfctype,                   &
     833             :                                      Tsf,         potT,          &   ! LCOV_EXCL_LINE
     834             :                                      uatm,        vatm,          &   ! LCOV_EXCL_LINE
     835             :                                      wind,        zlvl,          &   ! LCOV_EXCL_LINE
     836             :                                      Qa,          rhoa,          &   ! LCOV_EXCL_LINE
     837             :                                      strx,        stry,          &   ! LCOV_EXCL_LINE
     838             :                                      Tref,        Qref,          &   ! LCOV_EXCL_LINE
     839             :                                      delt,        delq,          &   ! LCOV_EXCL_LINE
     840             :                                      lhcoef,      shcoef,        &   ! LCOV_EXCL_LINE
     841             :                                      Cdn_atm,                    &   ! LCOV_EXCL_LINE
     842             :                                      Cdn_atm_ratio_n,            &   ! LCOV_EXCL_LINE
     843             :                                      Qa_iso,      Qref_iso,      &   ! LCOV_EXCL_LINE
     844             :                                      uvel,        vvel,          &   ! LCOV_EXCL_LINE
     845             :                                      Uref,        zlvs)
     846             : 
     847             :       character (len=3), intent(in) :: &
     848             :          sfctype      ! ice or ocean
     849             : 
     850             :       real (kind=dbl_kind), intent(in) :: &
     851             :          Tsf      , & ! surface temperature of ice or ocean   ! LCOV_EXCL_LINE
     852             :          potT     , & ! air potential temperature  (K)   ! LCOV_EXCL_LINE
     853             :          uatm     , & ! x-direction wind speed (m/s)   ! LCOV_EXCL_LINE
     854             :          vatm     , & ! y-direction wind speed (m/s)   ! LCOV_EXCL_LINE
     855             :          wind     , & ! wind speed (m/s)   ! LCOV_EXCL_LINE
     856             :          zlvl     , & ! atm level height for momentum (and scalars if zlvs is not present) (m)   ! LCOV_EXCL_LINE
     857             :          Qa       , & ! specific humidity (kg/kg)   ! LCOV_EXCL_LINE
     858             :          rhoa         ! air density (kg/m^3)
     859             : 
     860             :       real (kind=dbl_kind), intent(inout) :: &
     861             :          Cdn_atm  , &    ! neutral drag coefficient   ! LCOV_EXCL_LINE
     862             :          Cdn_atm_ratio_n ! ratio drag coeff / neutral drag coeff
     863             : 
     864             :       real (kind=dbl_kind), intent(inout) :: &
     865             :          strx     , & ! x surface stress (N)   ! LCOV_EXCL_LINE
     866             :          stry         ! y surface stress (N)
     867             : 
     868             :       real (kind=dbl_kind), intent(inout) :: &
     869             :          Tref     , & ! reference height temperature  (K)   ! LCOV_EXCL_LINE
     870             :          Qref     , & ! reference height specific humidity (kg/kg)   ! LCOV_EXCL_LINE
     871             :          delt     , & ! potential T difference   (K)   ! LCOV_EXCL_LINE
     872             :          delq     , & ! humidity difference      (kg/kg)   ! LCOV_EXCL_LINE
     873             :          shcoef   , & ! transfer coefficient for sensible heat   ! LCOV_EXCL_LINE
     874             :          lhcoef       ! transfer coefficient for latent heat
     875             : 
     876             :       real (kind=dbl_kind), intent(in), dimension(:), optional :: &
     877             :          Qa_iso       ! specific isotopic humidity (kg/kg)
     878             : 
     879             :       real (kind=dbl_kind), intent(inout), dimension(:), optional :: &
     880             :          Qref_iso     ! reference specific isotopic humidity (kg/kg)
     881             : 
     882             :       real (kind=dbl_kind), intent(in), optional :: &
     883             :          uvel     , & ! x-direction ice speed (m/s)   ! LCOV_EXCL_LINE
     884             :          vvel     , & ! y-direction ice speed (m/s)   ! LCOV_EXCL_LINE
     885             :          zlvs         ! atm level height for scalars (if different than zlvl) (m)
     886             : 
     887             :       real (kind=dbl_kind), intent(out), optional :: &
     888             :          Uref         ! reference height wind speed (m/s)
     889             : 
     890             : !autodocument_end
     891             : 
     892             :       ! local variables
     893             : 
     894             :       real (kind=dbl_kind) :: &
     895     6371954 :          l_uvel, l_vvel, l_Uref
     896             : 
     897             :       logical (kind=log_kind), save :: &
     898             :          first_call_ice = .true.   ! first call flag
     899             : 
     900             :       character(len=*),parameter :: subname='(icepack_atm_boundary)'
     901             : 
     902             :       !------------------------------------------------------------
     903             :       ! Check optional arguments
     904             :       ! Need separate first_call flags for 'ice' and 'ocn' sfctype
     905             :       !------------------------------------------------------------
     906             : 
     907    46176939 :       if (sfctype == 'ice') then
     908    33852099 :       if (icepack_chkoptargflag(first_call_ice)) then
     909          44 :          if (tr_iso) then
     910           0 :             if (.not.(present(Qa_iso).and.present(Qref_iso))) then
     911           0 :               call icepack_warnings_add(subname//' error in fiso_ocn argument, tr_iso=T')
     912           0 :               call icepack_warnings_setabort(.true.,__FILE__,__LINE__)
     913           0 :               return
     914             :             endif
     915             :          endif
     916             :       endif
     917             :       endif
     918             : 
     919    46176939 :       l_uvel = c0
     920    46176939 :       l_vvel = c0
     921    46176939 :       l_Uref = c0
     922    46176939 :       if (present(uvel)) then
     923    33852099 :          l_uvel = uvel
     924             :       endif
     925    46176939 :       if (present(vvel)) then
     926    33852099 :          l_vvel = vvel
     927             :       endif
     928             : 
     929    46176939 :       Cdn_atm_ratio_n = c1
     930             : 
     931    46176939 :       if (trim(atmbndy) == 'constant') then
     932             :          call atmo_boundary_const (sfctype,  calc_strair, &
     933             :                                    uatm,     vatm,     &   ! LCOV_EXCL_LINE
     934             :                                    wind,     rhoa,     &   ! LCOV_EXCL_LINE
     935             :                                    strx,     stry,     &   ! LCOV_EXCL_LINE
     936             :                                    Tsf,      potT,     &   ! LCOV_EXCL_LINE
     937             :                                    Qa,                 &   ! LCOV_EXCL_LINE
     938             :                                    delt,     delq,     &   ! LCOV_EXCL_LINE
     939           0 :                                    lhcoef,   shcoef    )
     940           0 :          if (icepack_warnings_aborted(subname)) return
     941             :       else
     942             :          call atmo_boundary_layer (sfctype,                 &
     943             :                                    calc_strair, formdrag,   &   ! LCOV_EXCL_LINE
     944             :                                    Tsf,      potT,          &   ! LCOV_EXCL_LINE
     945             :                                    uatm,     vatm,          &   ! LCOV_EXCL_LINE
     946             :                                    wind,     zlvl,          &   ! LCOV_EXCL_LINE
     947             :                                    Qa,       rhoa,          &   ! LCOV_EXCL_LINE
     948             :                                    strx,     stry,          &   ! LCOV_EXCL_LINE
     949             :                                    Tref,     Qref,          &   ! LCOV_EXCL_LINE
     950             :                                    delt,     delq,          &   ! LCOV_EXCL_LINE
     951             :                                    lhcoef,   shcoef,        &   ! LCOV_EXCL_LINE
     952             :                                    Cdn_atm,                 &   ! LCOV_EXCL_LINE
     953             :                                    Cdn_atm_ratio_n,         &   ! LCOV_EXCL_LINE
     954             :                                    Qa_iso=Qa_iso,           &   ! LCOV_EXCL_LINE
     955             :                                    Qref_iso=Qref_iso,       &   ! LCOV_EXCL_LINE
     956             :                                    uvel=l_uvel, vvel=l_vvel,&   ! LCOV_EXCL_LINE
     957    46176939 :                                    Uref=l_Uref, zlvs=zlvs   )
     958    46176939 :          if (icepack_warnings_aborted(subname)) return
     959             :       endif ! atmbndy
     960             : 
     961    46176939 :       if (present(Uref)) then
     962    33852099 :          Uref = l_Uref
     963             :       endif
     964             : 
     965    46176939 :       if (sfctype == 'ice') then
     966    33852099 :          first_call_ice = .false.
     967             :       endif
     968             : 
     969             :       end subroutine icepack_atm_boundary
     970             : 
     971             : !=======================================================================
     972             : 
     973   398556998 :       function compute_stability_parameter(zlvl , thva , &
     974             :                                            ustar, tstar, &   ! LCOV_EXCL_LINE
     975             :                                            qstar, Qa)    &   ! LCOV_EXCL_LINE
     976    46413088 :                                            result(hol)
     977             : 
     978             :       real (kind=dbl_kind), intent(in) :: &
     979             :          zlvl     , & ! atm level height (m)   ! LCOV_EXCL_LINE
     980             :          thva     , & ! virtual temperature      (K)   ! LCOV_EXCL_LINE
     981             :          ustar    , & ! turbulent scale for momentum   ! LCOV_EXCL_LINE
     982             :          tstar    , & ! turbulent scale for temperature   ! LCOV_EXCL_LINE
     983             :          qstar    , & ! turbulent scale for humidity   ! LCOV_EXCL_LINE
     984             :          Qa           ! specific humidity (kg/kg)
     985             : 
     986             :       real (kind=dbl_kind) :: &
     987             :          hol          ! H (at zlvl) over L
     988             : 
     989             :       character(len=*),parameter :: subname='(compute_stability_parameter)'
     990             : 
     991             :       hol = vonkar * gravit * zlvl &
     992             :                * (tstar/thva &   ! LCOV_EXCL_LINE
     993             :                + qstar/(c1/zvir+Qa)) &   ! LCOV_EXCL_LINE
     994   398556998 :                / ustar**2
     995   398556998 :       hol    = sign( min(abs(hol),c10), hol)
     996             : 
     997   398556998 :       end function compute_stability_parameter
     998             : 
     999             : !=======================================================================
    1000             : 
    1001   459953622 :       subroutine compute_stability_function(qty, hol, stable, psi)
    1002             : 
    1003             :       character (len=*), intent(in) :: &
    1004             :          qty          ! 'momentum' or 'scalar'
    1005             : 
    1006             :       real (kind=dbl_kind), intent(in) :: &
    1007             :          hol          ! H over L
    1008             : 
    1009             :       real (kind=dbl_kind), intent(out) :: &
    1010             :          psi          , & ! stability function at hol   ! LCOV_EXCL_LINE
    1011             :          stable           ! unit step function at hol
    1012             : 
    1013             :       ! local variables
    1014             : 
    1015             :       real (kind=dbl_kind) :: &
    1016             :          psi_stable   , & ! stable stability funcion at hol   ! LCOV_EXCL_LINE
    1017    62709046 :          psi_unstable     ! unstable stability funcion at hol
    1018             : 
    1019             :       character(len=*),parameter :: subname='(compute_stability_function)'
    1020             : 
    1021   459953622 :       stable = p5 + sign(p5 , hol)
    1022             : 
    1023             :       psi_stable = -(0.7_dbl_kind*hol &
    1024             :                  + 0.75_dbl_kind*(hol-14.3_dbl_kind) &   ! LCOV_EXCL_LINE
    1025   459953622 :                  * exp(-0.35_dbl_kind*hol) + 10.7_dbl_kind)
    1026             : 
    1027   459953622 :       if(trim(qty) == 'momentum') then
    1028   229976811 :          psi_unstable = psi_momentum_unstable(hol)
    1029   229976811 :       elseif(trim(qty) == 'scalar') then
    1030   229976811 :          psi_unstable = psi_scalar_unstable(hol)
    1031             :       else
    1032           0 :          call icepack_warnings_add(subname//' incorrect qty: ' // qty)
    1033           0 :          call icepack_warnings_setabort(.true.,__FILE__,__LINE__)
    1034             :       endif
    1035             : 
    1036   459953622 :       psi = psi_stable*stable + (c1 - stable)*psi_unstable
    1037             : 
    1038   459953622 :    end subroutine compute_stability_function
    1039             : 
    1040             : !------------------------------------------------------------
    1041             : ! Define functions
    1042             : !------------------------------------------------------------
    1043             : 
    1044             : !=======================================================================
    1045             : 
    1046   229976811 :       real(kind=dbl_kind) function psi_momentum_unstable(hol)
    1047             : 
    1048             :       real(kind=dbl_kind), intent(in) :: hol
    1049             : 
    1050    31354523 :       real(kind=dbl_kind) :: xd
    1051             : 
    1052   229976811 :       xd = capital_X(hol)
    1053             : 
    1054             :       psi_momentum_unstable = log((c1+xd*(c2+xd))*(c1+xd*xd)/c8) &
    1055   229976811 :                               - c2*atan(xd) + pih
    1056             : 
    1057   229976811 :       end function psi_momentum_unstable
    1058             : 
    1059             : !=======================================================================
    1060             : 
    1061   276153750 :       real(kind=dbl_kind) function psi_scalar_unstable(hol)
    1062             : 
    1063             :       real(kind=dbl_kind), intent(in) :: hol
    1064             : 
    1065    37726477 :       real(kind=dbl_kind) :: xd
    1066             : 
    1067   276153750 :       xd = capital_X(hol)
    1068             : 
    1069   276153750 :       psi_scalar_unstable =  c2 * log((c1 + xd*xd)/c2)
    1070             : 
    1071   276153750 :       end function psi_scalar_unstable
    1072             : 
    1073             : !=======================================================================
    1074             : 
    1075   506130561 :       real(kind=dbl_kind) function capital_X(hol)
    1076             : 
    1077             :       real(kind=dbl_kind), intent(in) :: hol
    1078             : 
    1079   506130561 :       capital_X =  sqrt(max(sqrt(abs(c1 - c16*hol)) , c1))
    1080             : 
    1081   506130561 :       end function capital_X
    1082             : 
    1083             : !=======================================================================
    1084             : 
    1085             :       end module icepack_atmo
    1086             : 
    1087             : !=======================================================================

Generated by: LCOV version 1.14-6-g40580cd