LCOV - code coverage report
Current view: top level - physics/cam - gw_drag.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 318 1126 28.2 %
Date: 2025-01-13 21:54:50 Functions: 3 13 23.1 %

          Line data    Source code
       1             : module gw_drag
       2             : 
       3             : !--------------------------------------------------------------------------
       4             : ! CAM and WACCM gravity wave parameterizations were merged by Sean Patrick
       5             : ! Santos in Summer 2013, and at the same time, gw_drag was split into
       6             : ! various modules. This is the CAM interface and driver module. The below
       7             : ! notes are for the old CAM and WACCM versions of gw_drag.
       8             : !--------------------------------------------------------------------------
       9             : ! This file came from wa17 and was modified by Fabrizio: 07-02-2004
      10             : ! Standard gw_drag with modification (6) of latitude profile of gw spectrum
      11             : !--------------------------------------------------------------------------
      12             : ! Purpose:
      13             : !
      14             : ! Module to compute the forcing due to parameterized gravity waves. Both an
      15             : ! orographic and an internal source spectrum are considered.
      16             : !
      17             : ! Author: Byron Boville
      18             : !
      19             : !--------------------------------------------------------------------------
      20             :   use shr_kind_mod,   only: r8=>shr_kind_r8, cl=>shr_kind_cl
      21             :   use shr_log_mod,    only: errMsg => shr_log_errMsg
      22             :   use shr_assert_mod, only: shr_assert
      23             : 
      24             :   use ppgrid,         only: pcols, pver, begchunk, endchunk
      25             :   use constituents,   only: pcnst
      26             :   use physics_types,  only: physics_state, physics_ptend, physics_ptend_init
      27             :   use spmd_utils,     only: masterproc
      28             :   use cam_history,    only: outfld
      29             :   use cam_logfile,    only: iulog
      30             :   use cam_abortutils, only: endrun
      31             :   use error_messages, only: alloc_err
      32             : 
      33             : 
      34             :   use ref_pres,       only: do_molec_diff, nbot_molec, press_lim_idx
      35             :   use physconst,      only: cpair
      36             : 
      37             :   ! These are the actual switches for different gravity wave sources.
      38             :   use phys_control,   only: use_gw_oro, use_gw_front, use_gw_front_igw, &
      39             :                             use_gw_convect_dp, use_gw_convect_sh,       &
      40             :                             use_simple_phys, use_gw_movmtn_pbl
      41             : 
      42             :   use gw_common,      only: GWBand
      43             :   use gw_convect,     only: BeresSourceDesc
      44             :   use gw_movmtn,      only: MovMtnSourceDesc
      45             :   use gw_front,       only: CMSourceDesc
      46             : 
      47             : ! Typical module header
      48             :   implicit none
      49             :   private
      50             :   save
      51             : 
      52             : !
      53             : ! PUBLIC: interfaces
      54             : !
      55             :   public :: gw_drag_readnl           ! Read namelist
      56             :   public :: gw_init                  ! Initialization
      57             :   public :: gw_tend                  ! interface to actual parameterization
      58             : 
      59             : !
      60             : ! PRIVATE: Rest of the data and interfaces are private to this module
      61             : !
      62             :   real(r8), parameter :: unset_r8 = huge(1._r8)
      63             : 
      64             :   ! A mid-scale "band" with only stationary waves (l = 0).
      65             :   type(GWBand) :: band_oro
      66             :   ! Medium scale waves.
      67             :   type(GWBand) :: band_mid
      68             :   ! Long scale waves for IGWs.
      69             :   type(GWBand) :: band_long
      70             :   ! Medium scale waves for moving mountain
      71             :   type(GWBand) :: band_movmtn
      72             : 
      73             :   ! Top level for gravity waves.
      74             :   integer, parameter :: ktop = 1
      75             :   ! Bottom level for frontal waves.
      76             :   integer :: kbot_front
      77             : 
      78             :   ! Factor for SH orographic waves.
      79             :   real(r8) :: gw_oro_south_fac = 1._r8
      80             : 
      81             :   ! Frontogenesis function critical threshold.
      82             :   real(r8) :: frontgfc = unset_r8
      83             : 
      84             :   ! Tendency efficiencies.
      85             : 
      86             :   ! Ridge scheme.
      87             :   logical  :: use_gw_rdg_beta      = .false.
      88             :   integer  :: n_rdg_beta           = 1
      89             :   real(r8) :: effgw_rdg_beta       = unset_r8
      90             :   real(r8) :: effgw_rdg_beta_max   = unset_r8
      91             :   real(r8) :: rdg_beta_cd_llb      = unset_r8  ! Low-level obstacle drag coefficient Ridge scheme.
      92             :   logical  :: trpd_leewv_rdg_beta  = .false.
      93             : 
      94             :   logical  :: use_gw_rdg_gamma     = .false.
      95             :   integer  :: n_rdg_gamma          = -1
      96             :   real(r8) :: effgw_rdg_gamma      = unset_r8
      97             :   real(r8) :: effgw_rdg_gamma_max  = unset_r8
      98             :   real(r8) :: rdg_gamma_cd_llb     = unset_r8
      99             :   logical  :: trpd_leewv_rdg_gamma = .false.
     100             :   character(len=cl) :: bnd_rdggm   = 'bnd_rdggm' ! full pathname for meso-Gamma ridge dataset
     101             : 
     102             :   ! Orography.
     103             :   real(r8) :: effgw_oro = unset_r8
     104             :   ! C&M scheme.
     105             :   real(r8) :: effgw_cm = unset_r8
     106             :   ! C&M scheme (inertial waves).
     107             :   real(r8) :: effgw_cm_igw = unset_r8
     108             :   ! Beres (deep convection).
     109             :   real(r8) :: effgw_beres_dp = unset_r8
     110             :   ! Beres (shallow convection).
     111             :   real(r8) :: effgw_beres_sh = unset_r8
     112             : 
     113             :   ! Horzontal wavelengths [m].
     114             :   real(r8), parameter :: wavelength_mid = 1.e5_r8
     115             :   real(r8), parameter :: wavelength_long = 3.e5_r8
     116             : 
     117             :   ! Background stress source strengths.
     118             :   real(r8) :: taubgnd = unset_r8
     119             :   real(r8) :: taubgnd_igw = unset_r8
     120             : 
     121             :   ! Whether or not to use a polar taper for frontally generated waves.
     122             :   logical :: gw_polar_taper = .false.
     123             : 
     124             :   ! Whether or not to enforce an upper boundary condition of tau = 0.
     125             :   ! (Like many variables, this is only here to hold the value between
     126             :   ! the readnl phase and the init phase of the CAM physics; only gw_common
     127             :   ! should actually use it.)
     128             :   logical :: tau_0_ubc = .false.
     129             : 
     130             :   ! Whether or not to limit tau *before* applying any efficiency factors.
     131             :   logical :: gw_limit_tau_without_eff = .false.
     132             : 
     133             :   ! Whether or not to apply tendency max
     134             :   logical :: gw_apply_tndmax = .true.
     135             : 
     136             :   ! Files to read Beres source spectra from.
     137             :   character(len=cl) :: gw_drag_file = ""
     138             :   character(len=cl) :: gw_drag_file_sh = ""
     139             :   character(len=cl) :: gw_drag_file_mm = ""
     140             : 
     141             :   ! Beres settings and table.
     142             :   type(BeresSourceDesc) :: beres_dp_desc
     143             :   type(BeresSourceDesc) :: beres_sh_desc
     144             : 
     145             :   ! Moving mountain settings and table.
     146             :   type(MovMtnSourceDesc) :: movmtn_desc
     147             : 
     148             :   ! Frontogenesis wave settings.
     149             :   type(CMSourceDesc) :: cm_desc
     150             :   type(CMSourceDesc) :: cm_igw_desc
     151             : 
     152             :   ! Indices into pbuf
     153             :   integer :: kvt_idx      = -1
     154             :   integer :: ttend_dp_idx = -1
     155             :   integer :: ttend_sh_idx = -1
     156             :   integer :: frontgf_idx  = -1
     157             :   integer :: frontga_idx  = -1
     158             :   integer :: sgh_idx      = -1
     159             : 
     160             :   ! From CLUBB
     161             :   integer :: ttend_clubb_idx  = -1
     162             :   integer :: upwp_clubb_gw_idx   = -1
     163             :   integer :: vpwp_clubb_gw_idx   = -1
     164             :   integer :: thlp2_clubb_gw_idx  = -1
     165             :   integer :: wpthlp_clubb_gw_idx  = -1
     166             : 
     167             :   ! anisotropic ridge fields
     168             :   integer, parameter :: prdg = 16
     169             : 
     170             :   real(r8), allocatable, dimension(:,:), target :: &
     171             :      rdg_gbxar
     172             : 
     173             :      ! Meso Beta
     174             :   real(r8), allocatable, dimension(:,:,:), target :: &
     175             :      rdg_hwdth,  &
     176             :      rdg_clngt,  &
     177             :      rdg_mxdis,  &
     178             :      rdg_anixy,  &
     179             :      rdg_angll
     180             : 
     181             :      ! Meso Gamma
     182             :   real(r8), allocatable, dimension(:,:,:), target :: &
     183             :      rdg_hwdthg, &
     184             :      rdg_clngtg, &
     185             :      rdg_mxdisg, &
     186             :      rdg_anixyg, &
     187             :      rdg_angllg
     188             : 
     189             :   ! Water constituent indices for budget
     190             :   integer :: ixcldliq = -1
     191             :   integer :: ixcldice = -1
     192             : 
     193             :   ! Prefixes for history field names
     194             :   character(len=1), parameter :: cm_pf = " "
     195             :   character(len=1), parameter :: cm_igw_pf = "I"
     196             :   character(len=1), parameter :: beres_dp_pf = "B"
     197             :   character(len=1), parameter :: beres_sh_pf = "S"
     198             : 
     199             :   ! namelist
     200             :   logical          :: history_amwg                   ! output the variables used by the AMWG diag package
     201             :   logical  :: gw_lndscl_sgh = .true. ! scale SGH by land frac
     202             :   real(r8) :: gw_prndl = 0.25_r8
     203             :   real(r8) :: gw_qbo_hdepth_scaling = 1._r8 ! heating depth scaling factor
     204             : 
     205             :   ! Width of gaussian used to create frontogenesis tau profile [m s-1].
     206             :   real(r8) :: front_gaussian_width = -huge(1._r8)
     207             : 
     208             :   real(r8) :: alpha_gw_movmtn
     209             : 
     210             :   logical :: gw_top_taper=.false.
     211             :   real(r8), pointer :: vramp(:)=>null()
     212             : 
     213             : !==========================================================================
     214             : contains
     215             : !==========================================================================
     216             : 
     217        1536 : subroutine gw_drag_readnl(nlfile)
     218             : 
     219             :   use namelist_utils,  only: find_group_name
     220             :   use units,           only: getunit, freeunit
     221             :   use spmd_utils,      only: mpicom, mstrid=>masterprocid, mpi_real8, &
     222             :                              mpi_character, mpi_logical, mpi_integer
     223             :   use gw_rdg,          only: gw_rdg_readnl
     224             : 
     225             :   ! File containing namelist input.
     226             :   character(len=*), intent(in) :: nlfile
     227             : 
     228             :   ! Local variables
     229             :   integer :: unitn, ierr
     230             :   character(len=*), parameter :: sub = 'gw_drag_readnl'
     231             : 
     232             :   ! Maximum wave number and width of spectrum bins.
     233             :   integer :: pgwv = -1
     234             :   real(r8) :: gw_dc = unset_r8
     235             :   integer :: pgwv_long = -1
     236             :   real(r8) :: gw_dc_long = unset_r8
     237             : 
     238             :   namelist /gw_drag_nl/ pgwv, gw_dc, pgwv_long, gw_dc_long, tau_0_ubc, &
     239             :        effgw_beres_dp, effgw_beres_sh, effgw_cm, effgw_cm_igw, effgw_oro, &
     240             :        frontgfc, gw_drag_file, gw_drag_file_sh, gw_drag_file_mm, taubgnd, &
     241             :        taubgnd_igw, gw_polar_taper, &
     242             :        use_gw_rdg_beta, n_rdg_beta, effgw_rdg_beta, effgw_rdg_beta_max, &
     243             :        rdg_beta_cd_llb, trpd_leewv_rdg_beta, &
     244             :        use_gw_rdg_gamma, n_rdg_gamma, effgw_rdg_gamma, effgw_rdg_gamma_max, &
     245             :        rdg_gamma_cd_llb, trpd_leewv_rdg_gamma, bnd_rdggm, &
     246             :        gw_oro_south_fac, gw_limit_tau_without_eff, &
     247             :        gw_lndscl_sgh, gw_prndl, gw_apply_tndmax, gw_qbo_hdepth_scaling, &
     248             :        gw_top_taper, front_gaussian_width, alpha_gw_movmtn
     249             :   !----------------------------------------------------------------------
     250             : 
     251        1536 :   if (use_simple_phys) return
     252             : 
     253        1536 :   if (masterproc) then
     254           2 :      unitn = getunit()
     255           2 :      open( unitn, file=trim(nlfile), status='old' )
     256           2 :      call find_group_name(unitn, 'gw_drag_nl', status=ierr)
     257           2 :      if (ierr == 0) then
     258           2 :         read(unitn, gw_drag_nl, iostat=ierr)
     259           2 :         if (ierr /= 0) then
     260           0 :            call endrun(sub // ':: ERROR reading namelist')
     261             :         end if
     262             :      end if
     263           2 :      close(unitn)
     264           2 :      call freeunit(unitn)
     265             :   end if
     266             : 
     267        1536 :   call mpi_bcast(pgwv, 1, mpi_integer, mstrid, mpicom, ierr)
     268        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: pgwv")
     269        1536 :   call mpi_bcast(gw_dc, 1, mpi_real8, mstrid, mpicom, ierr)
     270        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: gw_dc")
     271        1536 :   call mpi_bcast(pgwv_long, 1, mpi_integer, mstrid, mpicom, ierr)
     272        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: pgwv_long")
     273        1536 :   call mpi_bcast(gw_dc_long, 1, mpi_real8, mstrid, mpicom, ierr)
     274        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: gw_dc_long")
     275        1536 :   call mpi_bcast(tau_0_ubc, 1, mpi_logical, mstrid, mpicom, ierr)
     276        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: tau_0_ubc")
     277        1536 :   call mpi_bcast(effgw_beres_dp, 1, mpi_real8, mstrid, mpicom, ierr)
     278        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: effgw_beres_dp")
     279        1536 :   call mpi_bcast(effgw_beres_sh, 1, mpi_real8, mstrid, mpicom, ierr)
     280        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: effgw_beres_sh")
     281        1536 :   call mpi_bcast(effgw_cm, 1, mpi_real8, mstrid, mpicom, ierr)
     282        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: effgw_cm")
     283        1536 :   call mpi_bcast(effgw_cm_igw, 1, mpi_real8, mstrid, mpicom, ierr)
     284        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: effgw_cm_igw")
     285        1536 :   call mpi_bcast(effgw_oro, 1, mpi_real8, mstrid, mpicom, ierr)
     286        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: effgw_oro")
     287             : 
     288        1536 :   call mpi_bcast(use_gw_rdg_beta, 1, mpi_logical, mstrid, mpicom, ierr)
     289        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: use_gw_rdg_beta")
     290        1536 :   call mpi_bcast(n_rdg_beta, 1, mpi_integer, mstrid, mpicom, ierr)
     291        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: n_rdg_beta")
     292        1536 :   call mpi_bcast(effgw_rdg_beta, 1, mpi_real8, mstrid, mpicom, ierr)
     293        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: effgw_rdg_beta")
     294        1536 :   call mpi_bcast(effgw_rdg_beta_max, 1, mpi_real8, mstrid, mpicom, ierr)
     295        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: effgw_rdg_beta_max")
     296        1536 :   call mpi_bcast(rdg_beta_cd_llb, 1, mpi_real8, mstrid, mpicom, ierr)
     297        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: rdg_beta_cd_llb")
     298        1536 :   call mpi_bcast(trpd_leewv_rdg_beta, 1, mpi_logical, mstrid, mpicom, ierr)
     299        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: trpd_leewv_rdg_beta")
     300             : 
     301        1536 :   call mpi_bcast(use_gw_rdg_gamma, 1, mpi_logical, mstrid, mpicom, ierr)
     302        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: use_gw_rdg_gamma")
     303        1536 :   call mpi_bcast(n_rdg_gamma, 1, mpi_integer, mstrid, mpicom, ierr)
     304        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: n_rdg_gamma")
     305        1536 :   call mpi_bcast(effgw_rdg_gamma, 1, mpi_real8, mstrid, mpicom, ierr)
     306        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: effgw_rdg_gamma")
     307        1536 :   call mpi_bcast(effgw_rdg_gamma_max, 1, mpi_real8, mstrid, mpicom, ierr)
     308        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: effgw_rdg_gamma_max")
     309        1536 :   call mpi_bcast(rdg_gamma_cd_llb, 1, mpi_real8, mstrid, mpicom, ierr)
     310        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: rdg_gamma_cd_llb")
     311        1536 :   call mpi_bcast(trpd_leewv_rdg_gamma, 1, mpi_logical, mstrid, mpicom, ierr)
     312        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: trpd_leewv_rdg_gamma")
     313        1536 :   call mpi_bcast(bnd_rdggm, len(bnd_rdggm), mpi_character, mstrid, mpicom, ierr)
     314        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: bnd_rdggm")
     315             : 
     316        1536 :   call mpi_bcast(gw_oro_south_fac, 1, mpi_real8, mstrid, mpicom, ierr)
     317        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: gw_oro_south_fac")
     318        1536 :   call mpi_bcast(frontgfc, 1, mpi_real8, mstrid, mpicom, ierr)
     319        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: frontgfc")
     320        1536 :   call mpi_bcast(taubgnd, 1, mpi_real8, mstrid, mpicom, ierr)
     321        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: taubgnd")
     322        1536 :   call mpi_bcast(taubgnd_igw, 1, mpi_real8, mstrid, mpicom, ierr)
     323        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: taubgnd_igw")
     324             : 
     325        1536 :   call mpi_bcast(gw_polar_taper, 1, mpi_logical, mstrid, mpicom, ierr)
     326        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: gw_polar_taper")
     327        1536 :   call mpi_bcast(gw_limit_tau_without_eff, 1, mpi_logical, mstrid, mpicom, ierr)
     328        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: gw_limit_tau_without_eff")
     329        1536 :   call mpi_bcast(gw_apply_tndmax, 1, mpi_logical, mstrid, mpicom, ierr)
     330        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: gw_apply_tndmax")
     331             : 
     332        1536 :   call mpi_bcast(gw_top_taper, 1, mpi_logical, mstrid, mpicom, ierr)
     333        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: gw_top_taper")
     334             : 
     335        1536 :   call mpi_bcast(gw_lndscl_sgh, 1, mpi_logical, mstrid, mpicom, ierr)
     336        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: gw_lndscl_sgh")
     337        1536 :   call mpi_bcast(gw_prndl, 1, mpi_real8, mstrid, mpicom, ierr)
     338        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: gw_prndl")
     339        1536 :   call mpi_bcast(gw_qbo_hdepth_scaling, 1, mpi_real8, mstrid, mpicom, ierr)
     340        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: gw_qbo_hdepth_scaling")
     341             : 
     342        1536 :   call mpi_bcast(gw_drag_file, len(gw_drag_file), mpi_character, mstrid, mpicom, ierr)
     343        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: gw_drag_file")
     344        1536 :   call mpi_bcast(gw_drag_file_sh, len(gw_drag_file_sh), mpi_character, mstrid, mpicom, ierr)
     345        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: gw_drag_file_sh")
     346        1536 :   call mpi_bcast(gw_drag_file_mm, len(gw_drag_file_mm), mpi_character, mstrid, mpicom, ierr)
     347        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: gw_drag_file_mm")
     348             : 
     349        1536 :   call mpi_bcast(front_gaussian_width, 1, mpi_real8, mstrid, mpicom, ierr)
     350        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: front_gaussian_width")
     351             : 
     352        1536 :   call mpi_bcast(alpha_gw_movmtn, 1, mpi_real8, mstrid, mpicom, ierr)
     353        1536 :   if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: alpha_gw_movmtn")
     354             : 
     355             :   ! Check if pgwv was set.
     356             :   call shr_assert(pgwv >= 0, &
     357             :        "gw_drag_readnl: pgwv must be set via the namelist and &
     358             :        &non-negative."// &
     359        1536 :        errMsg(__FILE__, __LINE__))
     360             : 
     361             :   ! Check if gw_dc was set.
     362             :   call shr_assert(gw_dc /= unset_r8, &
     363             :        "gw_drag_readnl: gw_dc must be set via the namelist."// &
     364        1536 :        errMsg(__FILE__, __LINE__))
     365             : 
     366        1536 :   band_oro = GWBand(0, gw_dc, 1.0_r8, wavelength_mid)
     367        1536 :   band_mid = GWBand(pgwv, gw_dc, 1.0_r8, wavelength_mid)
     368        1536 :   band_long = GWBand(pgwv_long, gw_dc_long, 1.0_r8, wavelength_long)
     369        1536 :   band_movmtn = GWBand(0, gw_dc, 1.0_r8, wavelength_mid)
     370             : 
     371        1536 :   if (use_gw_rdg_gamma .or. use_gw_rdg_beta) then
     372           0 :      call gw_rdg_readnl(nlfile)
     373             :   end if
     374             : 
     375             : end subroutine gw_drag_readnl
     376             : 
     377             : !==========================================================================
     378             : 
     379        1536 : subroutine gw_init()
     380             :   !-----------------------------------------------------------------------
     381             :   ! Time independent initialization for multiple gravity wave
     382             :   ! parameterization.
     383             :   !-----------------------------------------------------------------------
     384             : 
     385             :   use cam_history,      only: addfld, add_default, horiz_only
     386             :   use cam_history,      only: register_vector_field
     387             :   use interpolate_data, only: lininterp
     388             :   use phys_control,     only: phys_getopts
     389             :   use physics_buffer,   only: pbuf_get_index
     390             :   use constituents,     only: cnst_get_ind
     391             : 
     392             :   use cam_initfiles,    only: topo_file_get_id
     393             : 
     394             :   ! temporary for restart with ridge scheme
     395             :   use cam_initfiles,    only: bnd_topo
     396             : 
     397             :   use cam_pio_utils,    only: cam_pio_openfile
     398             :   use cam_grid_support, only: cam_grid_check, cam_grid_id
     399             :   use cam_grid_support, only: cam_grid_get_dim_names
     400             :   use pio,              only: file_desc_t, pio_nowrite, pio_closefile
     401             :   use ncdio_atm,        only: infld
     402             :   use ioFileMod,        only: getfil
     403             : 
     404             :   use ref_pres,   only: pref_edge, pref_mid
     405             :   use physconst,  only: gravit, rair, rearth
     406             : 
     407             :   use gw_common,  only: gw_common_init
     408             :   use gw_front,   only: gaussian_cm_desc
     409             : 
     410             :   !---------------------------Local storage-------------------------------
     411             : 
     412             :   integer          :: i, l, k
     413             :   character(len=1) :: cn
     414             : 
     415             :   ! Index for levels at specific pressures.
     416             :   integer :: kfront
     417             : 
     418             :   ! output tendencies and state variables for CAM4 temperature,
     419             :   ! water vapor, cloud ice and cloud liquid budgets.
     420             :   logical :: history_budget
     421             :   ! output history file number for budget fields
     422             :   integer :: history_budget_histfile_num
     423             :   ! output variables of interest in WACCM runs
     424             :   logical :: history_waccm
     425             : 
     426             :   ! Interpolated Newtonian cooling coefficients.
     427             :   real(r8) :: alpha(pver+1)
     428             : 
     429             :   ! Levels of pre-calculated Newtonian cooling (1/day).
     430             :   ! The following profile is digitized from:
     431             :   ! Wehrbein and Leovy (JAS, 39, 1532-1544, 1982) figure 5
     432             : 
     433             :   integer, parameter :: nalph = 71
     434             :   real(r8) :: alpha0(nalph) = [ &
     435             :        0.1_r8,         0.1_r8,         0.1_r8,         0.1_r8,         &
     436             :        0.1_r8,         0.1_r8,         0.1_r8,         0.1_r8,         &
     437             :        0.1_r8,         0.1_r8,         0.10133333_r8,  0.104_r8,       &
     438             :        0.108_r8,       0.112_r8,       0.116_r8,       0.12066667_r8,  &
     439             :        0.126_r8,       0.132_r8,       0.138_r8,       0.144_r8,       &
     440             :        0.15133333_r8,  0.16_r8,        0.17_r8,        0.18_r8,        &
     441             :        0.19_r8,        0.19933333_r8,  0.208_r8,       0.216_r8,       &
     442             :        0.224_r8,       0.232_r8,       0.23466667_r8,  0.232_r8,       &
     443             :        0.224_r8,       0.216_r8,       0.208_r8,       0.20133333_r8,  &
     444             :        0.196_r8,       0.192_r8,       0.188_r8,       0.184_r8,       &
     445             :        0.18266667_r8,  0.184_r8,       0.188_r8,       0.192_r8,       &
     446             :        0.196_r8,       0.19333333_r8,  0.184_r8,       0.168_r8,       &
     447             :        0.152_r8,       0.136_r8,       0.12133333_r8,  0.108_r8,       &
     448             :        0.096_r8,       0.084_r8,       0.072_r8,       0.061_r8,       &
     449             :        0.051_r8,       0.042_r8,       0.033_r8,       0.024_r8,       &
     450             :        0.017666667_r8, 0.014_r8,       0.013_r8,       0.012_r8,       &
     451             :        0.011_r8,       0.010333333_r8, 0.01_r8,        0.01_r8,        &
     452             :        0.01_r8,        0.01_r8,        0.01_r8                         &
     453             :        ]
     454             : 
     455             :   ! Pressure levels that were used to calculate alpha0 (hPa).
     456             :   real(r8) :: palph(nalph) = [ &
     457             :        2.06115E-06_r8, 2.74280E-06_r8, 3.64988E-06_r8, 4.85694E-06_r8, &
     458             :        6.46319E-06_r8, 8.60065E-06_r8, 1.14450E-05_r8, 1.52300E-05_r8, &
     459             :        2.02667E-05_r8, 2.69692E-05_r8, 3.58882E-05_r8, 4.77568E-05_r8, &
     460             :        6.35507E-05_r8, 8.45676E-05_r8, 0.000112535_r8, 0.000149752_r8, &
     461             :        0.000199277_r8, 0.000265180_r8, 0.000352878_r8, 0.000469579_r8, &
     462             :        0.000624875_r8, 0.000831529_r8, 0.00110653_r8,  0.00147247_r8,  &
     463             :        0.00195943_r8,  0.00260744_r8,  0.00346975_r8,  0.00461724_r8,  &
     464             :        0.00614421_r8,  0.00817618_r8,  0.0108801_r8,   0.0144783_r8,   &
     465             :        0.0192665_r8,   0.0256382_r8,   0.0341170_r8,   0.0453999_r8,   &
     466             :        0.0604142_r8,   0.0803939_r8,   0.106981_r8,    0.142361_r8,    &
     467             :        0.189442_r8,    0.252093_r8,    0.335463_r8,    0.446404_r8,    &
     468             :        0.594036_r8,    0.790490_r8,    1.05192_r8,     1.39980_r8,     &
     469             :        1.86273_r8,     2.47875_r8,     3.29851_r8,     4.38936_r8,     &
     470             :        5.84098_r8,     7.77266_r8,     10.3432_r8,     13.7638_r8,     &
     471             :        18.3156_r8,     24.3728_r8,     32.4332_r8,     43.1593_r8,     &
     472             :        57.4326_r8,     76.4263_r8,     101.701_r8,     135.335_r8,     &
     473             :        180.092_r8,     239.651_r8,     318.907_r8,     424.373_r8,     &
     474             :        564.718_r8,     751.477_r8,     1000._r8                        &
     475             :        ]
     476             : 
     477             :   ! Read data from file
     478             :   type(file_desc_t), pointer :: fh_topo
     479             :   type(file_desc_t)  :: fh_rdggm
     480             :   integer            :: grid_id
     481             :   character(len=8)   :: dim1name, dim2name
     482             :   logical            :: found
     483             :   character(len=cl) :: bnd_rdggm_loc   ! filepath of topo file on local disk
     484             : 
     485             :   ! Allow reporting of error messages.
     486             :   character(len=128) :: errstring
     487             :   character(len=*), parameter :: sub = 'gw_init'
     488             : 
     489             :   ! temporary workaround for restart w/ ridge scheme
     490             :   character(len=cl) :: bnd_topo_loc   ! filepath of topo file on local disk
     491             : 
     492             :   integer :: botndx,topndx
     493             : 
     494             :   !-----------------------------------------------------------------------
     495             : 
     496        1536 :   if (do_molec_diff) then
     497           0 :      kvt_idx     = pbuf_get_index('kvt')
     498             :   end if
     499             : 
     500        1536 :   if (masterproc) then
     501           2 :      write(iulog,*) ' '
     502           2 :      write(iulog,*) "GW_DRAG: band_mid%ngwv = ", band_mid%ngwv
     503           4 :      do l = -band_mid%ngwv, band_mid%ngwv
     504             :         write (iulog,'(A,I0,A,F7.2)') &
     505           4 :              "GW_DRAG: band_mid%cref(",l,") = ",band_mid%cref(l)
     506             :      enddo
     507           2 :      write(iulog,*) 'GW_DRAG: band_mid%kwv = ', band_mid%kwv
     508           2 :      write(iulog,*) 'GW_DRAG: band_mid%fcrit2 = ', band_mid%fcrit2
     509           2 :      write(iulog,*) ' '
     510           2 :      write(iulog,*) "GW_DRAG: band_long%ngwv = ", band_long%ngwv
     511           4 :      do l = -band_long%ngwv, band_long%ngwv
     512             :         write (iulog,'(A,I2,A,F7.2)') &
     513           4 :              "GW_DRAG: band_long%cref(",l,") = ",band_long%cref(l)
     514             :      enddo
     515           2 :      write(iulog,*) 'GW_DRAG: band_long%kwv = ', band_long%kwv
     516           2 :      write(iulog,*) 'GW_DRAG: band_long%fcrit2 = ', band_long%fcrit2
     517           2 :      write(iulog,*) ' '
     518             :   end if
     519             : 
     520             :   ! pre-calculated newtonian damping:
     521             :   !     * convert to s-1
     522             :   !     * ensure it is not smaller than 1e-6
     523             :   !     * convert palph from hpa to pa
     524             : 
     525      110592 :   do k=1,nalph
     526      109056 :      alpha0(k) = alpha0(k) / 86400._r8
     527      109056 :      alpha0(k) = max(alpha0(k), 1.e-6_r8)
     528      110592 :      palph(k) = palph(k)*1.e2_r8
     529             :   end do
     530             : 
     531             :   ! interpolate to current vertical grid and obtain alpha
     532             : 
     533        1536 :   call lininterp (alpha0  ,palph, nalph , alpha  , pref_edge , pver+1)
     534        1536 :   if (masterproc) then
     535           2 :      write (iulog,*) 'gw_init: newtonian damping (1/day):'
     536           2 :      write (iulog,fmt='(a4,a12,a10)') ' k  ','  pref_edge      ', &
     537           4 :           '  alpha   '
     538          56 :      do k = 1, pver+1
     539          54 :         write (iulog,fmt='(i4,1e12.5,1f10.2)') k,pref_edge(k), &
     540         110 :              alpha(k)*86400._r8
     541             :      end do
     542             :   end if
     543             : 
     544        1536 :   if (masterproc) then
     545           2 :      write(iulog,*) 'KTOP        =',ktop
     546             :   end if
     547             : 
     548             :   ! Used to decide whether temperature tendencies should be output.
     549             :   call phys_getopts( history_budget_out = history_budget, &
     550             :        history_budget_histfile_num_out = history_budget_histfile_num, &
     551             :        history_waccm_out = history_waccm, &
     552        1536 :        history_amwg_out   = history_amwg  )
     553             : 
     554             :   ! Initialize subordinate modules.
     555             :   call gw_common_init(pver,&
     556             :        tau_0_ubc, ktop, gravit, rair, alpha, gw_prndl, &
     557        1536 :        gw_qbo_hdepth_scaling, errstring )
     558             :   call shr_assert(trim(errstring) == "", "gw_common_init: "//errstring// &
     559        1536 :        errMsg(__FILE__, __LINE__))
     560             : 
     561        1536 :   if ( use_gw_oro ) then
     562             : 
     563        1536 :      if (effgw_oro == unset_r8) then
     564             :         call endrun("gw_init: Orographic gravity waves enabled, &
     565           0 :              &but effgw_oro was not set.")
     566             :      end if
     567             :   end if
     568             : 
     569        1536 :   if (use_gw_oro .or. use_gw_rdg_beta .or. use_gw_rdg_gamma) then
     570             : 
     571        1536 :      sgh_idx = pbuf_get_index('SGH')
     572             : 
     573             :      ! Declare history variables for orographic term
     574             :      call addfld ('TAUAORO',    (/ 'ilev' /), 'I','N m-2',  &
     575        3072 :           'Total stress from original OGW scheme')
     576             :      call addfld ('TTGWORO',    (/ 'lev' /), 'A','K s-1',  &
     577        3072 :           'T tendency - orographic gravity wave drag')
     578             :      call addfld ('TTGWSDFORO', (/ 'lev' /), 'A','K s-1',  &
     579        3072 :           'T tendency - orographic gravity wave, diffusion.')
     580             :      call addfld ('TTGWSKEORO', (/ 'lev' /), 'A','K s-1',  &
     581        3072 :           'T tendency - orographic gravity wave, breaking KE.')
     582             :      call addfld ('UTGWORO',    (/ 'lev' /), 'A','m s-2', &
     583        3072 :           'U tendency - orographic gravity wave drag')
     584             :      call addfld ('VTGWORO',    (/ 'lev' /), 'A','m s-2', &
     585        3072 :           'V tendency - orographic gravity wave drag')
     586        1536 :      call register_vector_field('UTGWORO', 'VTGWORO')
     587             :      call addfld ('TAUGWX',     horiz_only,  'A','N m-2', &
     588        1536 :           'Zonal gravity wave surface stress')
     589             :      call addfld ('TAUGWY',     horiz_only,  'A','N m-2', &
     590        1536 :           'Meridional gravity wave surface stress')
     591        1536 :      call register_vector_field('TAUGWX', 'TAUGWY')
     592             : 
     593        1536 :      if (history_amwg) then
     594        1536 :         call add_default('TAUGWX  ', 1, ' ')
     595        1536 :         call add_default('TAUGWY  ', 1, ' ')
     596             :      end if
     597             : 
     598        1536 :      if (history_waccm) then
     599           0 :         call add_default('UTGWORO ', 1, ' ')
     600           0 :         call add_default('VTGWORO ', 1, ' ')
     601           0 :         call add_default('TAUGWX  ', 1, ' ')
     602           0 :         call add_default('TAUGWY  ', 1, ' ')
     603             :      end if
     604             : 
     605             :   end if
     606             : 
     607        1536 :   if (use_gw_rdg_beta .or. use_gw_rdg_gamma) then
     608           0 :      grid_id = cam_grid_id('physgrid')
     609           0 :      if (.not. cam_grid_check(grid_id)) then
     610           0 :         call endrun(sub//': ERROR: no "physgrid" grid')
     611             :      end if
     612           0 :      call cam_grid_get_dim_names(grid_id, dim1name, dim2name)
     613             :   end if
     614             : 
     615        1536 :   if (use_gw_rdg_beta) then
     616             : 
     617           0 :      if (effgw_rdg_beta == unset_r8) then
     618             :         call endrun(sub//": ERROR: Anisotropic OGW enabled, &
     619           0 :                      &but effgw_rdg_beta was not set.")
     620             :      end if
     621             : 
     622           0 :      fh_topo => topo_file_get_id()
     623           0 :      bnd_topo_loc = ' '
     624           0 :      if (.not. associated(fh_topo)) then
     625             : 
     626             :         ! Try to open topo file here.  This workaround will not be needed
     627             :         ! once the refactored initialization sequence is on trunk.
     628             : 
     629           0 :         allocate(fh_topo)
     630             :         ! Error exit is from getfil if file not found.
     631           0 :         call getfil(bnd_topo, bnd_topo_loc)
     632           0 :         call cam_pio_openfile(fh_topo, bnd_topo_loc, PIO_NOWRITE)
     633             : 
     634             :      end if
     635             : 
     636             :      ! Get beta ridge data
     637             :      allocate( &
     638           0 :         rdg_gbxar(pcols,begchunk:endchunk),      &
     639           0 :         rdg_hwdth(pcols,prdg,begchunk:endchunk), &
     640           0 :         rdg_clngt(pcols,prdg,begchunk:endchunk), &
     641           0 :         rdg_mxdis(pcols,prdg,begchunk:endchunk), &
     642           0 :         rdg_anixy(pcols,prdg,begchunk:endchunk), &
     643           0 :         rdg_angll(pcols,prdg,begchunk:endchunk)  )
     644             : 
     645             :      call infld('GBXAR', fh_topo, dim1name, dim2name, 1, pcols, &
     646           0 :                          begchunk, endchunk, rdg_gbxar, found, gridname='physgrid')
     647           0 :      if (.not. found) call endrun(sub//': ERROR: GBXAR not found on topo file')
     648           0 :      rdg_gbxar = rdg_gbxar * (rearth/1000._r8)*(rearth/1000._r8) ! transform to km^2
     649             : 
     650             :      call infld('HWDTH', fh_topo, dim1name, 'nrdg', dim2name, 1, pcols, &
     651           0 :                 1, prdg, begchunk, endchunk, rdg_hwdth, found, gridname='physgrid')
     652           0 :      if (.not. found) call endrun(sub//': ERROR: HWDTH not found on topo file')
     653             : 
     654             :      call infld('CLNGT', fh_topo, dim1name, 'nrdg', dim2name, 1, pcols, &
     655           0 :                 1, prdg, begchunk, endchunk, rdg_clngt, found, gridname='physgrid')
     656           0 :      if (.not. found) call endrun(sub//': ERROR: CLNGT not found on topo file')
     657             : 
     658             :      call infld('MXDIS', fh_topo, dim1name, 'nrdg', dim2name, 1, pcols, &
     659           0 :                 1, prdg, begchunk, endchunk, rdg_mxdis, found, gridname='physgrid')
     660           0 :      if (.not. found) call endrun(sub//': ERROR: MXDIS not found on topo file')
     661             : 
     662             :      call infld('ANIXY', fh_topo, dim1name, 'nrdg', dim2name, 1, pcols, &
     663           0 :                 1, prdg, begchunk, endchunk, rdg_anixy, found, gridname='physgrid')
     664           0 :      if (.not. found) call endrun(sub//': ERROR: ANIXY not found on topo file')
     665             : 
     666             :      call infld('ANGLL', fh_topo, dim1name, 'nrdg', dim2name, 1, pcols, &
     667           0 :                 1, prdg, begchunk, endchunk, rdg_angll, found, gridname='physgrid')
     668           0 :      if (.not. found) call endrun(sub//': ERROR: ANGLL not found on topo file')
     669             : 
     670             :      ! close topo file only if it was opened here
     671           0 :      if (len_trim(bnd_topo_loc) > 0) then
     672           0 :         call pio_closefile(fh_topo)
     673             :      end if
     674             : 
     675             :      call addfld ('WBR_HT1',     horiz_only,  'I','m', &
     676           0 :           'Wave breaking height for DSW')
     677             :      call addfld ('TLB_HT1',     horiz_only,  'I','m', &
     678           0 :           'Form drag layer height')
     679             :      call addfld ('BWV_HT1',     horiz_only,  'I','m', &
     680           0 :           'Bottom of freely-propagating OGW regime')
     681             :      call addfld ('TAUDSW1',     horiz_only,  'I','Nm-2', &
     682           0 :           'DSW enhanced drag')
     683             :      call addfld ('TAUORO1',     horiz_only,  'I','Nm-2', &
     684           0 :           'lower BC on propagating wave stress')
     685             :      call addfld ('UBMSRC1',     horiz_only,  'I','ms-1', &
     686           0 :           'below-peak-level on-ridge wind')
     687             :      call addfld ('USRC1',     horiz_only,  'I','ms-1', &
     688           0 :           'below-peak-level Zonal wind')
     689             :      call addfld ('VSRC1',     horiz_only,  'I','ms-1', &
     690           0 :           'below-peak-level Meridional wind')
     691             :      call addfld ('NSRC1',     horiz_only,  'I','s-1', &
     692           0 :           'below-peak-level stratification')
     693             :      call addfld ('MXDIS1',     horiz_only,  'I','m', &
     694           0 :           'Ridge/obstacle height')
     695             :      call addfld ('ANGLL1',     horiz_only,  'I','degrees', &
     696           0 :           'orientation clockwise w/resp north-south')
     697             :      call addfld ('ANIXY1',     horiz_only,  'I','1', &
     698           0 :           'Ridge quality')
     699             :      call addfld ('HWDTH1',     horiz_only,  'I','km', &
     700           0 :           'Ridge width')
     701             :      call addfld ('CLNGT1',     horiz_only,  'I','km', &
     702           0 :           'Ridge length')
     703             :      call addfld ('GBXAR1',     horiz_only,  'I','km+2', &
     704           0 :           'grid box area')
     705             : 
     706             :      call addfld ('Fr1_DIAG',     horiz_only,  'I','1', &
     707           0 :           'Critical Froude number for linear waves')
     708             :      call addfld ('Fr2_DIAG',     horiz_only,  'I','1', &
     709           0 :           'Critical Froude number for blocked flow')
     710             :      call addfld ('Frx_DIAG',     horiz_only,  'I','1', &
     711           0 :           'Obstacle Froude Number')
     712             : 
     713             :      call addfld('UEGW',  (/ 'lev' /) , 'A'  ,'s-1' ,  &
     714           0 :           'Zonal wind profile-entry to GW ' )
     715             :      call addfld('VEGW',  (/ 'lev' /) , 'A'  ,'s-1' ,  &
     716           0 :           'Merdional wind profile-entry to GW ' )
     717           0 :      call register_vector_field('UEGW','VEGW')
     718             :      call addfld('TEGW',  (/ 'lev' /) , 'A'  ,'K' ,  &
     719           0 :           'Temperature profile-entry to GW ' )
     720             :      call addfld('ZEGW',  (/ 'ilev' /) , 'A'  ,'m' ,  &
     721           0 :           'interface geopotential heights in GW code ' )
     722             :      call addfld('ZMGW',  (/ 'lev' /) , 'A'  ,'m' ,  &
     723           0 :           'midlayer geopotential heights in GW code ' )
     724             : 
     725             :      call addfld('TAUM1_DIAG' , (/ 'ilev' /) , 'I'  ,'N m-2' , &
     726           0 :           'Ridge based momentum flux profile')
     727             :      call addfld('TAU1RDGBETAM' , (/ 'ilev' /) , 'I'  ,'N m-2' , &
     728           0 :           'Ridge based momentum flux profile')
     729             :      call addfld('UBM1BETA',  (/ 'lev' /) , 'A'  ,'s-1' ,  &
     730           0 :           'On-ridge wind profile           ' )
     731             :      call addfld('UBT1RDGBETA' , (/ 'lev' /) , 'I'  ,'m s-1' , &
     732           0 :           'On-ridge wind tendency from ridge 1     ')
     733             : 
     734           0 :      do i = 1, 6
     735           0 :         write(cn, '(i1)') i
     736             :         call addfld('TAU'//cn//'RDGBETAY' , (/ 'ilev' /), 'I', 'N m-2', &
     737           0 :           'Ridge based momentum flux profile')
     738             :         call addfld('TAU'//cn//'RDGBETAX' , (/ 'ilev' /), 'I', 'N m-2', &
     739           0 :           'Ridge based momentum flux profile')
     740           0 :         call register_vector_field('TAU'//cn//'RDGBETAX','TAU'//cn//'RDGBETAY')
     741             :         call addfld('UT'//cn//'RDGBETA',    (/ 'lev' /),  'I', 'm s-1', &
     742           0 :           'U wind tendency from ridge '//cn)
     743             :         call addfld('VT'//cn//'RDGBETA',    (/ 'lev' /),  'I', 'm s-1', &
     744           0 :           'V wind tendency from ridge '//cn)
     745           0 :         call register_vector_field('UT'//cn//'RDGBETA','VT'//cn//'RDGBETA')
     746             :      end do
     747             : 
     748             :      call addfld('TAUARDGBETAY' , (/ 'ilev' /) , 'I'  ,'N m-2' , &
     749           0 :           'Ridge based momentum flux profile')
     750             :      call addfld('TAUARDGBETAX' , (/ 'ilev' /) , 'I'  ,'N m-2' , &
     751           0 :           'Ridge based momentum flux profile')
     752           0 :      call register_vector_field('TAUARDGBETAX','TAUARDGBETAY')
     753             : 
     754           0 :      if (history_waccm) then
     755           0 :         call add_default('TAUARDGBETAX', 1, ' ')
     756           0 :         call add_default('TAUARDGBETAY  ', 1, ' ')
     757             :      end if
     758             : 
     759             :   end if
     760             : 
     761        1536 :   if (use_gw_rdg_gamma) then
     762             : 
     763           0 :      if (effgw_rdg_gamma == unset_r8) then
     764           0 :         call endrun(sub//": ERROR: Anisotropic OGW enabled, but effgw_rdg_gamma was not set.")
     765             :      end if
     766             : 
     767           0 :      call getfil(bnd_rdggm, bnd_rdggm_loc, iflag=1, lexist=found)
     768           0 :      if (found) then
     769           0 :         call cam_pio_openfile(fh_rdggm, bnd_rdggm_loc, PIO_NOWRITE)
     770             :      else
     771             :         call endrun(sub//': ERROR: file for gamma ridges not found: bnd_rdggm='// &
     772           0 :                    trim(bnd_rdggm))
     773             :      end if
     774             : 
     775           0 :      if (.not. allocated(rdg_gbxar)) then
     776           0 :         allocate(rdg_gbxar(pcols,begchunk:endchunk))
     777             :         call infld('GBXAR', fh_rdggm, dim1name, dim2name, 1, pcols, &
     778           0 :                             begchunk, endchunk, rdg_gbxar, found, gridname='physgrid')
     779           0 :         if (.not. found) call endrun(sub//': ERROR: GBXAR not found on bnd_rdggm')
     780           0 :         rdg_gbxar = rdg_gbxar * (rearth/1000._r8)*(rearth/1000._r8) ! transform to km^2
     781             :      end if
     782             : 
     783             :      ! Get meso-gamma ridge data
     784             :      allocate( &
     785           0 :         rdg_hwdthg(pcols,prdg,begchunk:endchunk), &
     786           0 :         rdg_clngtg(pcols,prdg,begchunk:endchunk), &
     787           0 :         rdg_mxdisg(pcols,prdg,begchunk:endchunk), &
     788           0 :         rdg_anixyg(pcols,prdg,begchunk:endchunk), &
     789           0 :         rdg_angllg(pcols,prdg,begchunk:endchunk)  )
     790             : 
     791             :      call infld('HWDTH', fh_rdggm, dim1name, 'nrdg', dim2name, 1, pcols, &
     792           0 :                 1, prdg, begchunk, endchunk, rdg_hwdthg, found, gridname='physgrid')
     793           0 :      if (.not. found) call endrun(sub//': ERROR: HWDTH not found on bnd_rdggm')
     794             : 
     795             :      call infld('CLNGT', fh_rdggm, dim1name, 'nrdg', dim2name, 1, pcols, &
     796           0 :                 1, prdg, begchunk, endchunk, rdg_clngtg, found, gridname='physgrid')
     797           0 :      if (.not. found) call endrun(sub//': ERROR: CLNGT not found on bnd_rdggm')
     798             : 
     799             :      call infld('MXDIS', fh_rdggm, dim1name, 'nrdg', dim2name, 1, pcols, &
     800           0 :                 1, prdg, begchunk, endchunk, rdg_mxdisg, found, gridname='physgrid')
     801           0 :      if (.not. found) call endrun(sub//': ERROR: MXDIS not found on bnd_rdggm')
     802             : 
     803             :      call infld('ANIXY', fh_rdggm, dim1name, 'nrdg', dim2name, 1, pcols, &
     804           0 :                 1, prdg, begchunk, endchunk, rdg_anixyg, found, gridname='physgrid')
     805           0 :      if (.not. found) call endrun(sub//': ERROR: ANIXY not found on bnd_rdggm')
     806             : 
     807             :      call infld('ANGLL', fh_rdggm, dim1name, 'nrdg', dim2name, 1, pcols, &
     808           0 :                 1, prdg, begchunk, endchunk, rdg_angllg, found, gridname='physgrid')
     809           0 :      if (.not. found) call endrun(sub//': ERROR: ANGLL not found on bnd_rdggm')
     810             : 
     811           0 :      call pio_closefile(fh_rdggm)
     812             : 
     813             :      call addfld ('TAU1RDGGAMMAM' , (/ 'ilev' /) , 'I'  ,'N m-2' , &
     814           0 :           'Ridge based momentum flux profile')
     815             :      call addfld ('UBM1GAMMA',  (/ 'lev' /) , 'A'  ,'s-1' ,  &
     816           0 :           'On-ridge wind profile           ' )
     817             :      call addfld ('UBT1RDGGAMMA' , (/ 'lev' /) , 'I'  ,'m s-1' , &
     818           0 :           'On-ridge wind tendency from ridge 1     ')
     819             : 
     820           0 :      do i = 1, 6
     821           0 :         write(cn, '(i1)') i
     822             :         call addfld('TAU'//cn//'RDGGAMMAY', (/ 'ilev' /), 'I', 'N m-2', &
     823           0 :           'Ridge based momentum flux profile')
     824             :         call addfld('TAU'//cn//'RDGGAMMAX', (/ 'ilev' /), 'I', 'N m-2', &
     825           0 :           'Ridge based momentum flux profile')
     826             :         call addfld('UT'//cn//'RDGGAMMA' , (/ 'lev' /),  'I', 'm s-1', &
     827           0 :           'U wind tendency from ridge '//cn)
     828             :         call addfld('VT'//cn//'RDGGAMMA' , (/ 'lev' /),  'I', 'm s-1', &
     829           0 :           'V wind tendency from ridge '//cn)
     830           0 :         call register_vector_field('UT'//cn//'RDGGAMMA','VT'//cn//'RDGGAMMA')
     831             :      end do
     832             : 
     833             :      call addfld ('TAUARDGGAMMAY' , (/ 'ilev' /) , 'I'  ,'N m-2' , &
     834           0 :           'Ridge based momentum flux profile')
     835             :      call addfld ('TAUARDGGAMMAX' , (/ 'ilev' /) , 'I'  ,'N m-2' , &
     836           0 :           'Ridge based momentum flux profile')
     837           0 :      call register_vector_field('TAUARDGGAMMAX','TAUARDGGAMMAY')
     838             :      call addfld ('TAURDGGMX',     horiz_only,  'A','N m-2', &
     839           0 :           'Zonal gravity wave surface stress')
     840             :      call addfld ('TAURDGGMY',     horiz_only,  'A','N m-2', &
     841           0 :           'Meridional gravity wave surface stress')
     842           0 :      call register_vector_field('TAURDGGMX','TAURDGGMY')
     843             :      call addfld ('UTRDGGM' , (/ 'lev' /) , 'I'  ,'m s-1' , &
     844           0 :           'U wind tendency from ridge 6     ')
     845             :      call addfld ('VTRDGGM' , (/ 'lev' /) , 'I'  ,'m s-1' , &
     846           0 :           'V wind tendency from ridge 6     ')
     847           0 :      call register_vector_field('UTRDGGM','VTRDGGM')
     848             :   end if
     849             : 
     850        1536 :   if (use_gw_front .or. use_gw_front_igw) then
     851             : 
     852           0 :      frontgf_idx = pbuf_get_index('FRONTGF')
     853           0 :      frontga_idx = pbuf_get_index('FRONTGA')
     854             : 
     855             :      call shr_assert(unset_r8 /= frontgfc, &
     856             :           "gw_init: Frontogenesis enabled, but frontgfc was &
     857             :           & not set!"// &
     858           0 :           errMsg(__FILE__, __LINE__))
     859             : 
     860           0 :      do k = 0, pver
     861             :         ! Check frontogenesis at 600 hPa.
     862           0 :         if (pref_edge(k+1) < 60000._r8) kfront = k+1
     863             :      end do
     864             : 
     865             :      ! Source waves from 500 hPa.
     866           0 :      kbot_front = maxloc(pref_edge, 1, (pref_edge < 50000._r8)) - 1
     867             : 
     868           0 :      if (masterproc) then
     869           0 :         write (iulog,*) 'KFRONT      =',kfront
     870           0 :         write (iulog,*) 'KBOT_FRONT  =',kbot_front
     871           0 :         write(iulog,*) ' '
     872             :      end if
     873             : 
     874             :      call addfld ('FRONTGF', (/ 'lev' /), 'A', 'K^2/M^2/S', &
     875           0 :           'Frontogenesis function at gws src level')
     876             :      call addfld ('FRONTGFA', (/ 'lev' /), 'A', 'K^2/M^2/S', &
     877           0 :           'Frontogenesis function at gws src level')
     878             : 
     879           0 :      if (history_waccm) then
     880           0 :         call add_default('FRONTGF', 1, ' ')
     881           0 :         call add_default('FRONTGFA', 1, ' ')
     882             :      end if
     883             : 
     884             :   end if
     885             : 
     886        1536 :   if (use_gw_front) then
     887             : 
     888             :      call shr_assert(all(unset_r8 /= [ effgw_cm, taubgnd ]), &
     889             :           "gw_init: Frontogenesis mid-scale waves enabled, but not &
     890             :           &all required namelist variables were set!"// &
     891           0 :           errMsg(__FILE__, __LINE__))
     892             : 
     893           0 :      if (masterproc) then
     894           0 :         write(iulog,*) 'gw_init: gw spectrum taubgnd, ', &
     895           0 :              'effgw_cm = ',taubgnd, effgw_cm
     896           0 :         write(iulog,*) ' '
     897             :      end if
     898             : 
     899             :      cm_desc = gaussian_cm_desc(band_mid, kbot_front, kfront, frontgfc, &
     900           0 :           taubgnd, front_gaussian_width)
     901             : 
     902             :      ! Output for gravity waves from frontogenesis.
     903             :      call gw_spec_addflds(prefix=cm_pf, scheme="C&M", band=band_mid, &
     904           0 :           history_defaults=history_waccm)
     905             : 
     906             :   end if
     907             : 
     908        1536 :   if (use_gw_front_igw) then
     909             : 
     910             :      call shr_assert(all(unset_r8 /= [ effgw_cm_igw, taubgnd_igw ]), &
     911             :           "gw_init: Frontogenesis inertial waves enabled, but not &
     912             :           &all required namelist variables were set!"// &
     913           0 :           errMsg(__FILE__, __LINE__))
     914             : 
     915           0 :      if (masterproc) then
     916           0 :         write(iulog,*) 'gw_init: gw spectrum taubgnd_igw, ', &
     917           0 :              'effgw_cm_igw = ',taubgnd_igw, effgw_cm_igw
     918           0 :         write(iulog,*) ' '
     919             :      end if
     920             : 
     921             :      cm_igw_desc = gaussian_cm_desc(band_long, kbot_front, kfront, frontgfc, &
     922           0 :           taubgnd_igw, front_gaussian_width)
     923             : 
     924             :      ! Output for gravity waves from frontogenesis.
     925             :      call gw_spec_addflds(prefix=cm_igw_pf, scheme="C&M IGW", &
     926           0 :           band=band_long, history_defaults=history_waccm)
     927             : 
     928             :   end if
     929             : 
     930             :   ! ========= Moving Mountain initialization! ==========================
     931        1536 :   if (use_gw_movmtn_pbl) then
     932             : 
     933             :      ! get pbuf indices for CLUBB couplings
     934           0 :      ttend_clubb_idx     = pbuf_get_index('TTEND_CLUBB')
     935           0 :      thlp2_clubb_gw_idx  = pbuf_get_index('THLP2_CLUBB_GW')
     936           0 :      upwp_clubb_gw_idx   = pbuf_get_index('UPWP_CLUBB_GW')
     937           0 :      vpwp_clubb_gw_idx   = pbuf_get_index('VPWP_CLUBB_GW')
     938           0 :      wpthlp_clubb_gw_idx  = pbuf_get_index('WPTHLP_CLUBB_GW')
     939             : 
     940           0 :      if (masterproc) then
     941           0 :         write (iulog,*) 'Moving Mountain development code call init_movmtn'
     942             :      end if
     943             : 
     944             : 
     945             :      ! Confirm moving mountain file is enabled
     946             :      call shr_assert(trim(gw_drag_file_mm) /= "", &
     947             :           "gw_init: No gw_drag_file provided for DP GW moving mountain lookup &
     948             :           &table. Set this via namelist."// &
     949           0 :           errMsg(__FILE__, __LINE__))
     950             : 
     951           0 :      call gw_init_movmtn(gw_drag_file_mm, band_movmtn, movmtn_desc)
     952             : 
     953           0 :      do k = 0, pver
     954             :         ! 950 hPa index
     955           0 :         if (pref_edge(k+1) < 95000._r8) movmtn_desc%k = k+1
     956             :      end do
     957             : 
     958             :     ! Don't use deep convection heating depths below this limit.
     959           0 :      movmtn_desc%min_hdepth = 1._r8
     960           0 :      if (masterproc) then
     961           0 :         write (iulog,*) 'Moving mountain deep level =',movmtn_desc%k
     962             :      end if
     963             : 
     964             :      call addfld ('GWUT_MOVMTN',(/ 'lev' /), 'I','m s-2', &
     965           0 :           'Mov Mtn dragforce - ubm component')
     966             :      call addfld ('UTGW_MOVMTN',(/ 'lev' /), 'I','m s-2', &
     967           0 :           'Mov Mtn dragforce - u component')
     968             :      call addfld ('VTGW_MOVMTN',(/ 'lev' /), 'I','m s-2', &
     969           0 :           'Mov Mtn dragforce - v component')
     970             :      call addfld('TAU_MOVMTN', (/ 'ilev' /), 'I', 'N m-2', &
     971           0 :           'Moving Mountain momentum flux profile')
     972             :      call addfld('U_MOVMTN_IN', (/ 'lev' /), 'I', 'm s-1', &
     973           0 :           'Moving Mountain - midpoint zonal input wind')
     974             :      call addfld('V_MOVMTN_IN', (/ 'lev' /), 'I', 'm s-1', &
     975           0 :           'Moving Mountain - midpoint meridional input wind')
     976             :      call addfld('UBI_MOVMTN', (/ 'ilev' /), 'I', 'm s-1', &
     977           0 :           'Moving Mountain - interface wind in direction of wave')
     978             :      call addfld('UBM_MOVMTN', (/ 'lev' /), 'I', 'm s-1', &
     979           0 :           'Moving Mountain - midpoint wind in direction of wave')
     980             :      call addfld ('HDEPTH_MOVMTN',horiz_only,'I','km', &
     981           0 :           'Heating Depth')
     982             :      call addfld ('UCELL_MOVMTN',horiz_only,'I','m s-1', &
     983           0 :           'Gravity Wave Moving Mountain - Source-level X-wind')
     984             :      call addfld ('VCELL_MOVMTN',horiz_only,'I','m s-1', &
     985           0 :           'Gravity Wave Moving Mountain - Source-level Y-wind')
     986             :      call addfld ('CS_MOVMTN',horiz_only,'I','m s-1', &
     987           0 :           'Gravity Wave Moving Mountain - phase speed in direction of wave')
     988             :      call addfld ('STEER_LEVEL_MOVMTN',horiz_only,'I','1', &
     989           0 :           'Gravity Wave Moving Mountain - steering level for movmtn GW')
     990             :      call addfld ('SRC_LEVEL_MOVMTN',horiz_only,'I','1', &
     991           0 :           'Gravity Wave Moving Mountain - launch level for movmtn GW')
     992             :      call addfld ('TND_LEVEL_MOVMTN',horiz_only,'I','1', &
     993           0 :           'Gravity Wave Moving Mountain - tendency lowest level for movmtn GW')
     994             :      call addfld ('NETDT_MOVMTN',(/ 'lev' /),'I','K s-1', &
     995           0 :           'Gravity Wave Moving Mountain - Net heating rate')
     996             :      call addfld ('TTEND_CLUBB',(/ 'lev' /),'A','K s-1', &
     997           0 :           'Gravity Wave Moving Mountain - CLUBB Net heating rate')
     998             :      call addfld ('THLP2_CLUBB_GW',(/ 'ilev' /),'A','K+2', &
     999           0 :           'Gravity Wave Moving Mountain - THLP variance from CLUBB to GW')
    1000             :      call addfld ('WPTHLP_CLUBB_GW',(/ 'ilev' /),'A','Km s-2', &
    1001           0 :           'Gravity Wave Moving Mountain - WPTHLP from CLUBB to GW')
    1002             :      call addfld ('UPWP_CLUBB_GW',(/ 'ilev' /),'A','m+2 s-2', &
    1003           0 :           'Gravity Wave Moving Mountain - X-momflux from CLUBB to GW')
    1004             :      call addfld ('VPWP_CLUBB_GW',(/ 'ilev' /),'A','m+2 s-2', &
    1005           0 :           'Gravity Wave Moving Mountain - Y-momflux from CLUBB to GW')
    1006             :      call addfld ('XPWP_SRC_MOVMTN',horiz_only,'I','m+2 s-2', &
    1007           0 :           'Gravity Wave Moving Mountain - flux source for moving mtn')
    1008             : 
    1009             :   end if
    1010             : 
    1011        1536 :   if (use_gw_convect_dp) then
    1012             : 
    1013           0 :      ttend_dp_idx    = pbuf_get_index('TTEND_DP')
    1014             : 
    1015             :      ! Set the deep scheme specification components.
    1016           0 :      beres_dp_desc%storm_shift = .true.
    1017             : 
    1018           0 :      do k = 0, pver
    1019             :         ! 700 hPa index
    1020           0 :         if (pref_edge(k+1) < 70000._r8) beres_dp_desc%k = k+1
    1021             :      end do
    1022             : 
    1023           0 :      if (masterproc) then
    1024           0 :         write (iulog,*) 'Beres deep level =',beres_dp_desc%k
    1025             :      end if
    1026             : 
    1027             :      ! Don't use deep convection heating depths below this limit.
    1028             :      ! This is important for QBO. Bad result if left at 2.5 km.
    1029           0 :      beres_dp_desc%min_hdepth = 1000._r8
    1030             : 
    1031             :      ! Read Beres file.
    1032             : 
    1033             :      call shr_assert(trim(gw_drag_file) /= "", &
    1034             :           "gw_init: No gw_drag_file provided for Beres deep &
    1035             :           &scheme. Set this via namelist."// &
    1036           0 :           errMsg(__FILE__, __LINE__))
    1037             : 
    1038           0 :      call gw_init_beres(gw_drag_file, band_mid, beres_dp_desc)
    1039             : 
    1040             :      ! Output for gravity waves from the Beres scheme (deep).
    1041             :      call gw_spec_addflds(prefix=beres_dp_pf, scheme="Beres (deep)", &
    1042           0 :           band=band_mid, history_defaults=history_waccm)
    1043             : 
    1044             :      call addfld ('NETDT',(/ 'lev' /), 'A','K s-1', &
    1045           0 :           'Net heating rate')
    1046             :      call addfld ('MAXQ0',horiz_only  ,  'A','K day-1', &
    1047           0 :           'Max column heating rate')
    1048             :      call addfld ('HDEPTH',horiz_only,    'A','km', &
    1049           0 :           'Heating Depth')
    1050             : 
    1051           0 :      if (history_waccm) then
    1052           0 :         call add_default('NETDT    ', 1, ' ')
    1053           0 :         call add_default('HDEPTH   ', 1, ' ')
    1054           0 :         call add_default('MAXQ0    ', 1, ' ')
    1055             :      end if
    1056             : 
    1057             :   end if
    1058             : 
    1059        1536 :   if (use_gw_convect_sh) then
    1060             : 
    1061           0 :      ttend_sh_idx    = pbuf_get_index('TTEND_SH')
    1062             : 
    1063             :      ! Set the shallow scheme specification components.
    1064           0 :      beres_sh_desc%storm_shift = .false.
    1065             : 
    1066           0 :      do k = 0, pver
    1067             :         ! 900 hPa index
    1068           0 :         if (pref_edge(k+1) < 90000._r8) beres_sh_desc%k = k+1
    1069             :      end do
    1070             : 
    1071           0 :      if (masterproc) then
    1072           0 :         write (iulog,*) 'Beres shallow level =',beres_sh_desc%k
    1073             :      end if
    1074             : 
    1075             :      ! Use all heating depths for shallow convection.
    1076           0 :      beres_sh_desc%min_hdepth = 0._r8
    1077             : 
    1078             :      ! Read Beres file.
    1079             : 
    1080             :      call shr_assert(trim(gw_drag_file_sh) /= "", &
    1081             :           "gw_init: No gw_drag_file_sh provided for Beres shallow &
    1082             :           &scheme. Set this via namelist."// &
    1083           0 :           errMsg(__FILE__, __LINE__))
    1084             : 
    1085           0 :      call gw_init_beres(gw_drag_file_sh, band_mid, beres_sh_desc)
    1086             : 
    1087             :      ! Output for gravity waves from the Beres scheme (shallow).
    1088             :      call gw_spec_addflds(prefix=beres_sh_pf, scheme="Beres (shallow)", &
    1089           0 :           band=band_mid, history_defaults=history_waccm)
    1090             : 
    1091             :      call addfld ('SNETDT',(/ 'lev' /), 'A','K s-1', &
    1092           0 :           'Net heating rate')
    1093             :      call addfld ('SMAXQ0',horiz_only  ,  'A','K day-1', &
    1094           0 :           'Max column heating rate')
    1095             :      call addfld ('SHDEPTH',horiz_only,    'A','km', &
    1096           0 :           'Heating Depth')
    1097             : 
    1098           0 :      if (history_waccm) then
    1099           0 :         call add_default('SNETDT   ', 1, ' ')
    1100           0 :         call add_default('SHDEPTH  ', 1, ' ')
    1101           0 :         call add_default('SMAXQ0   ', 1, ' ')
    1102             :      end if
    1103             : 
    1104             :   end if
    1105             : 
    1106             :   call addfld ('EKGW' ,(/ 'ilev' /), 'A','M2/S', &
    1107        3072 :        'Effective Kzz due to diffusion by gravity waves')
    1108             : 
    1109        1536 :   if (history_waccm) then
    1110           0 :      call add_default('EKGW', 1, ' ')
    1111             :   end if
    1112             : 
    1113             :   call addfld ('UTGW_TOTAL',    (/ 'lev' /), 'A','m s-2', &
    1114        3072 :        'Total U tendency due to gravity wave drag')
    1115             :   call addfld ('VTGW_TOTAL',    (/ 'lev' /), 'A','m s-2', &
    1116        3072 :        'Total V tendency due to gravity wave drag')
    1117        1536 :   call register_vector_field('UTGW_TOTAL', 'VTGW_TOTAL')
    1118             : 
    1119             :   ! Total temperature tendency output.
    1120             :   call addfld ('TTGW', (/ 'lev' /), 'A', 'K s-1',  &
    1121        3072 :        'T tendency - gravity wave drag')
    1122             : 
    1123             :   ! Water budget terms.
    1124             :   call addfld('QTGW',(/ 'lev' /), 'A','kg/kg/s', &
    1125        3072 :        'Q tendency - gravity wave drag')
    1126             :   call addfld('CLDLIQTGW',(/ 'lev' /), 'A','kg/kg/s', &
    1127        3072 :        'CLDLIQ tendency - gravity wave drag')
    1128             :   call addfld('CLDICETGW',(/ 'lev' /), 'A','kg/kg/s', &
    1129        3072 :        'CLDICE tendency - gravity wave drag')
    1130             : 
    1131        1536 :   if ( history_budget ) then
    1132           0 :      call add_default('TTGW', history_budget_histfile_num, ' ')
    1133           0 :      call add_default('QTGW', history_budget_histfile_num, ' ')
    1134           0 :      call add_default('CLDLIQTGW', history_budget_histfile_num, ' ')
    1135           0 :      call add_default('CLDICETGW', history_budget_histfile_num, ' ')
    1136             :   end if
    1137             : 
    1138             :   ! Get indices to actually output the above.
    1139        1536 :   call cnst_get_ind("CLDLIQ", ixcldliq)
    1140        1536 :   call cnst_get_ind("CLDICE", ixcldice)
    1141             : 
    1142        1536 :   if (gw_top_taper) then
    1143           0 :      allocate(vramp(pver))
    1144           0 :      vramp(:) = 1._r8
    1145           0 :      topndx = 1
    1146           0 :      botndx = press_lim_idx( 0.6E-02_r8, top=.true. )
    1147           0 :      if (botndx>1) then
    1148           0 :         do k=botndx,topndx,-1
    1149           0 :            vramp(k) = vramp(k+1)/(pref_edge(k+1)/pref_edge(k))
    1150             :         end do
    1151           0 :         if (masterproc) then
    1152           0 :            write(iulog,'(A)') 'GW taper coef (vramp):'
    1153           0 :            do k=1,pver
    1154           0 :               write(iulog,"('k: ',I4,' taper coef,press(Pa): ',F12.8,E12.4)") k, vramp(k), pref_mid(k)
    1155             :            enddo
    1156             :         endif
    1157             :      endif
    1158             :   end if
    1159             : 
    1160        3072 : end subroutine gw_init
    1161             : 
    1162             : !==========================================================================
    1163             : 
    1164           0 : subroutine gw_init_beres(file_name, band, desc)
    1165             : 
    1166        1536 :   use ioFileMod, only: getfil
    1167             :   use pio, only: file_desc_t, pio_nowrite, pio_inq_varid, pio_get_var, &
    1168             :        pio_closefile
    1169             :   use cam_pio_utils, only: cam_pio_openfile
    1170             : 
    1171             :   character(len=*), intent(in) :: file_name
    1172             :   type(GWBand), intent(in) :: band
    1173             : 
    1174             :   type(BeresSourceDesc), intent(inout) :: desc
    1175             : 
    1176             :   type(file_desc_t) :: gw_file_desc
    1177             : 
    1178             :   ! PIO variable ids and error code.
    1179             :   integer :: mfccid, hdid, stat
    1180             : 
    1181             :   ! Number of wavenumbers in the input file.
    1182             :   integer :: ngwv_file
    1183             : 
    1184             :   ! Full path to gw_drag_file.
    1185             :   character(len=cl) :: file_path
    1186             : 
    1187             :   character(len=cl) :: msg
    1188             : 
    1189             :   !----------------------------------------------------------------------
    1190             :   ! read in look-up table for source spectra
    1191             :   !-----------------------------------------------------------------------
    1192             : 
    1193           0 :   call getfil(file_name, file_path)
    1194           0 :   call cam_pio_openfile(gw_file_desc, file_path, pio_nowrite)
    1195             : 
    1196             :   ! Get HD (heating depth) dimension.
    1197             : 
    1198           0 :   desc%maxh = get_pio_dimlen(gw_file_desc, "HD", file_path)
    1199             : 
    1200             :   ! Get MW (mean wind) dimension.
    1201             : 
    1202           0 :   desc%maxuh = get_pio_dimlen(gw_file_desc, "MW", file_path)
    1203             : 
    1204             :   ! Get PS (phase speed) dimension.
    1205             : 
    1206           0 :   ngwv_file = get_pio_dimlen(gw_file_desc, "PS", file_path)
    1207             : 
    1208             :   ! Number in each direction is half of total (and minus phase speed of 0).
    1209           0 :   desc%maxuh = (desc%maxuh-1)/2
    1210           0 :   ngwv_file = (ngwv_file-1)/2
    1211             : 
    1212             :   call shr_assert(ngwv_file >= band%ngwv, &
    1213             :        "gw_init_beres: PhaseSpeed in lookup table file does not cover the whole &
    1214           0 :        &spectrum implied by the model's ngwv. ")
    1215             : 
    1216             :   ! Allocate hd and get data.
    1217             : 
    1218           0 :   allocate(desc%hd(desc%maxh), stat=stat, errmsg=msg)
    1219             : 
    1220             :   call shr_assert(stat == 0, &
    1221             :        "gw_init_beres: Allocation error (hd): "//msg// &
    1222           0 :        errMsg(__FILE__, __LINE__))
    1223             : 
    1224           0 :   stat = pio_inq_varid(gw_file_desc,'HD',hdid)
    1225             : 
    1226             :   call handle_pio_error(stat, &
    1227           0 :        'Error finding HD in: '//trim(file_path))
    1228             : 
    1229             :   stat = pio_get_var(gw_file_desc, hdid, start=[1], count=[desc%maxh], &
    1230           0 :        ival=desc%hd)
    1231             : 
    1232             :   call handle_pio_error(stat, &
    1233           0 :        'Error reading HD from: '//trim(file_path))
    1234             : 
    1235             :   ! While not currently documented in the file, it uses kilometers. Convert
    1236             :   ! to meters.
    1237           0 :   desc%hd = desc%hd*1000._r8
    1238             : 
    1239             :   ! Allocate mfcc. "desc%maxh" and "desc%maxuh" are from the file, but the
    1240             :   ! model determines wavenumber dimension.
    1241             : 
    1242             :   allocate(desc%mfcc(desc%maxh,-desc%maxuh:desc%maxuh,&
    1243           0 :        -band%ngwv:band%ngwv), stat=stat, errmsg=msg)
    1244             : 
    1245             :   call shr_assert(stat == 0, &
    1246             :        "gw_init_beres: Allocation error (mfcc): "//msg// &
    1247           0 :        errMsg(__FILE__, __LINE__))
    1248             : 
    1249             :   ! Get mfcc data.
    1250             : 
    1251           0 :   stat = pio_inq_varid(gw_file_desc,'mfcc',mfccid)
    1252             : 
    1253             :   call handle_pio_error(stat, &
    1254           0 :        'Error finding mfcc in: '//trim(file_path))
    1255             : 
    1256             :   stat = pio_get_var(gw_file_desc, mfccid, &
    1257           0 :        start=[1,1,ngwv_file-band%ngwv+1], count=shape(desc%mfcc), &
    1258           0 :        ival=desc%mfcc)
    1259             : 
    1260             :   call handle_pio_error(stat, &
    1261           0 :        'Error reading mfcc from: '//trim(file_path))
    1262             : 
    1263           0 :   call pio_closefile(gw_file_desc)
    1264             : 
    1265           0 :   if (masterproc) then
    1266             : 
    1267           0 :      write(iulog,*) "Read in source spectra from file."
    1268           0 :      write(iulog,*) "mfcc max, min = ", &
    1269           0 :           maxval(desc%mfcc),", ",minval(desc%mfcc)
    1270             : 
    1271             :   endif
    1272             : 
    1273           0 : end subroutine gw_init_beres
    1274             : 
    1275             : !==============================================================
    1276           0 : subroutine gw_init_movmtn(file_name, band, desc)
    1277             : 
    1278           0 :   use ioFileMod, only: getfil
    1279             :   use pio, only: file_desc_t, pio_nowrite, pio_inq_varid, pio_get_var, &
    1280             :        pio_closefile
    1281             :   use cam_pio_utils, only: cam_pio_openfile
    1282             : 
    1283             :   character(len=*), intent(in) :: file_name
    1284             :   type(GWBand), intent(in) :: band
    1285             : 
    1286             :   type(MovMtnSourceDesc), intent(inout) :: desc
    1287             : 
    1288             :   type(file_desc_t) :: gw_file_desc
    1289             : 
    1290             :   ! PIO variable ids and error code.
    1291             :   integer :: mfccid, uhid, hdid, stat
    1292             : 
    1293             :   ! Number of wavenumbers in the input file.
    1294             :   integer :: ngwv_file
    1295             : 
    1296             :   ! Full path to gw_drag_file.
    1297             :   character(len=cl) :: file_path
    1298             : 
    1299             :   character(len=cl) :: msg
    1300             : 
    1301             :   !----------------------------------------------------------------------
    1302             :   ! read in look-up table for source spectra
    1303             :   !-----------------------------------------------------------------------
    1304             : 
    1305           0 :   call getfil(file_name, file_path)
    1306             : 
    1307           0 :   call cam_pio_openfile(gw_file_desc, file_path, pio_nowrite)
    1308             : 
    1309             :   ! Get HD (heating depth) dimension.
    1310             : 
    1311           0 :   desc%maxh = 15 !get_pio_dimlen(gw_file_desc, "HD", file_path)
    1312             : 
    1313             :   ! Get MW (mean wind) dimension.
    1314             : 
    1315           0 :  desc%maxuh = 241 ! get_pio_dimlen(gw_file_desc, "MW", file_path)
    1316             : 
    1317             :   ! Get PS (phase speed) dimension.
    1318             : 
    1319           0 :   ngwv_file = 0 !get_pio_dimlen(gw_file_desc, "PS", file_path)
    1320             : 
    1321             :   ! Number in each direction is half of total (and minus phase speed of 0).
    1322           0 :   desc%maxuh = (desc%maxuh-1)/2
    1323           0 :   ngwv_file = (ngwv_file-1)/2
    1324             : 
    1325             :   call shr_assert(ngwv_file >= band%ngwv, &
    1326           0 :        "gw_movmtn_init: PhaseSpeed in lookup table inconsistent with moving mountain")
    1327             : 
    1328             :   ! Allocate hd and get data.
    1329             : 
    1330           0 :   allocate(desc%hd(desc%maxh), stat=stat, errmsg=msg)
    1331             : 
    1332             :   call shr_assert(stat == 0, &
    1333             :        "gw_init_movmtn: Allocation error (hd): "//msg// &
    1334           0 :        errMsg(__FILE__, __LINE__))
    1335             : 
    1336           0 :   stat = pio_inq_varid(gw_file_desc,'HDEPTH',hdid)
    1337             : 
    1338             :   call handle_pio_error(stat, &
    1339           0 :        'Error finding HD in: '//trim(file_path))
    1340             : 
    1341             :   stat = pio_get_var(gw_file_desc, hdid, start=[1], count=[desc%maxh], &
    1342           0 :        ival=desc%hd)
    1343             : 
    1344             :   call handle_pio_error(stat, &
    1345           0 :        'Error reading HD from: '//trim(file_path))
    1346             : 
    1347             :   ! While not currently documented in the file, it uses kilometers. Convert
    1348             :   ! to meters.
    1349           0 :   desc%hd = desc%hd*1000._r8
    1350             : 
    1351             :  ! Allocate wind and get data.
    1352             : 
    1353           0 :   allocate(desc%uh(desc%maxuh), stat=stat, errmsg=msg)
    1354             : 
    1355             :   call shr_assert(stat == 0, &
    1356             :        "gw_init_movmtn: Allocation error (uh): "//msg// &
    1357           0 :        errMsg(__FILE__, __LINE__))
    1358             : 
    1359           0 :   stat = pio_inq_varid(gw_file_desc,'UARR',uhid)
    1360             : 
    1361             :   call handle_pio_error(stat, &
    1362           0 :        'Error finding UH in: '//trim(file_path))
    1363             : 
    1364             :   stat = pio_get_var(gw_file_desc, uhid, start=[1], count=[desc%maxuh], &
    1365           0 :        ival=desc%uh)
    1366             : 
    1367             :   call handle_pio_error(stat, &
    1368           0 :        'Error reading UH from: '//trim(file_path))
    1369             : 
    1370             :   ! Allocate mfcc. "desc%maxh" and "desc%maxuh" are from the file, but the
    1371             :   ! model determines wavenumber dimension.
    1372             : 
    1373             :   allocate(desc%mfcc(desc%maxh,-desc%maxuh:desc%maxuh,&
    1374           0 :        -band%ngwv:band%ngwv), stat=stat, errmsg=msg)
    1375             : 
    1376             :   call shr_assert(stat == 0, &
    1377             :        "gw_init_movmtn: Allocation error (mfcc): "//msg// &
    1378           0 :        errMsg(__FILE__, __LINE__))
    1379             : 
    1380             :   ! Get mfcc data.
    1381             : 
    1382           0 :   stat = pio_inq_varid(gw_file_desc,'NEWMF',mfccid)
    1383             : 
    1384             :   call handle_pio_error(stat, &
    1385           0 :        'Error finding mfcc in: '//trim(file_path))
    1386             : 
    1387             :   stat = pio_get_var(gw_file_desc, mfccid, &
    1388           0 :        start=[1,1], count=shape(desc%mfcc), &
    1389           0 :        ival=desc%mfcc)
    1390             : 
    1391             :   call handle_pio_error(stat, &
    1392           0 :        'Error reading mfcc from: '//trim(file_path))
    1393             : 
    1394           0 :   call pio_closefile(gw_file_desc)
    1395             : 
    1396           0 :   if (masterproc) then
    1397             : 
    1398           0 :      write(iulog,*) "Read in Mov Mountain source file."
    1399             : 
    1400             :   endif
    1401             : 
    1402           0 : end subroutine gw_init_movmtn
    1403             : !==========================================================================
    1404             : 
    1405             : ! Utility to reduce the repetitiveness of reads during initialization.
    1406           0 : function get_pio_dimlen(file_desc, dim_name, file_path) result(dimlen)
    1407             : 
    1408           0 :   use pio, only: file_desc_t, pio_inq_dimid, pio_inq_dimlen
    1409             : 
    1410             :   type(file_desc_t), intent(in) :: file_desc
    1411             :   character(len=*), intent(in) :: dim_name
    1412             : 
    1413             :   ! File path, for use in error messages only.
    1414             :   character(len=*), intent(in) :: file_path
    1415             : 
    1416             :   integer :: dimlen
    1417             : 
    1418             :   integer :: dimid, stat
    1419             : 
    1420           0 :   stat = pio_inq_dimid(file_desc, dim_name, dimid)
    1421             : 
    1422             :   call handle_pio_error(stat, &
    1423           0 :        "Error finding dimension "//dim_name//" in: "//file_path)
    1424             : 
    1425           0 :   stat = pio_inq_dimlen(file_desc, dimid, dimlen)
    1426             : 
    1427             :   call handle_pio_error(stat, &
    1428           0 :        "Error reading dimension "//dim_name//" from: "//file_path)
    1429             : 
    1430           0 : end function get_pio_dimlen
    1431             : 
    1432             : !==========================================================================
    1433             : 
    1434             : ! In fact, we'd usually expect PIO errors to abort the run before you can
    1435             : ! even check the error code. But just in case, use this little assert.
    1436           0 : subroutine handle_pio_error(stat, message)
    1437             :   use pio, only: pio_noerr
    1438             :   integer, intent(in) :: stat
    1439             :   character(len=*) :: message
    1440             : 
    1441             :   call shr_assert(stat == pio_noerr, &
    1442             :        "PIO error in gw_init_beres: "//trim(message)// &
    1443           0 :        errMsg(__FILE__, __LINE__))
    1444             : 
    1445           0 : end subroutine handle_pio_error
    1446             : 
    1447             : !==========================================================================
    1448             : 
    1449     5956704 : subroutine gw_tend(state, pbuf, dt, ptend, cam_in, flx_heat)
    1450             :   !-----------------------------------------------------------------------
    1451             :   ! Interface for multiple gravity wave drag parameterization.
    1452             :   !-----------------------------------------------------------------------
    1453             : 
    1454             :   use physics_types,   only: physics_state_copy, set_dry_to_wet
    1455             :   use constituents,    only: cnst_type
    1456             :   use physics_buffer,  only: physics_buffer_desc, pbuf_get_field
    1457             :   use camsrfexch,      only: cam_in_t
    1458             :   ! Location-dependent cpair
    1459             :   use air_composition, only: cpairv
    1460             :   use physconst,       only: pi
    1461             :   use coords_1d,       only: Coords1D
    1462             :   use gw_common,       only: gw_prof, gw_drag_prof, calc_taucd
    1463             :   use gw_common,       only: momentum_flux, momentum_fixer, energy_change
    1464             :   use gw_common,       only: energy_fixer, coriolis_speed, adjust_inertial
    1465             :   use gw_oro,          only: gw_oro_src
    1466             :   use gw_front,        only: gw_cm_src
    1467             :   use gw_convect,      only: gw_beres_src
    1468             :   use gw_movmtn,       only: gw_movmtn_src
    1469             : 
    1470             :   !------------------------------Arguments--------------------------------
    1471             :   type(physics_state), intent(in) :: state   ! physics state structure
    1472             :   type(physics_buffer_desc), pointer :: pbuf(:) ! Physics buffer
    1473             :   real(r8), intent(in) :: dt                    ! time step
    1474             :   ! Parameterization net tendencies.
    1475             :   type(physics_ptend), intent(out):: ptend
    1476             :   type(cam_in_t), intent(in) :: cam_in
    1477             :   real(r8), intent(out) :: flx_heat(pcols)
    1478             : 
    1479             :   !---------------------------Local storage-------------------------------
    1480             : 
    1481     1489176 :   type(physics_state) :: state1     ! Local copy of state variable
    1482             : 
    1483             :   integer :: lchnk                  ! chunk identifier
    1484             :   integer :: ncol                   ! number of atmospheric columns
    1485             :   integer :: istat
    1486             : 
    1487             :   integer :: i, k                   ! loop indices
    1488             : 
    1489     1489176 :   type(Coords1D) :: p               ! Pressure coordinates
    1490             : 
    1491     2978352 :   real(r8) :: ttgw(state%ncol,pver) ! temperature tendency
    1492     2978352 :   real(r8) :: utgw(state%ncol,pver) ! zonal wind tendency
    1493     2978352 :   real(r8) :: vtgw(state%ncol,pver) ! meridional wind tendency
    1494             : 
    1495     2978352 :   real(r8) :: ni(state%ncol,pver+1) ! interface Brunt-Vaisalla frequency
    1496     2978352 :   real(r8) :: nm(state%ncol,pver)   ! midpoint Brunt-Vaisalla frequency
    1497     2978352 :   real(r8) :: rhoi(state%ncol,pver+1)     ! interface density
    1498     1489176 :   real(r8), allocatable :: tau(:,:,:)  ! wave Reynolds stress
    1499     2978352 :   real(r8) :: tau0x(state%ncol)     ! c=0 sfc. stress (zonal)
    1500     2978352 :   real(r8) :: tau0y(state%ncol)     ! c=0 sfc. stress (meridional)
    1501     2978352 :   real(r8) :: ubi(state%ncol,pver+1)! projection of wind at interfaces
    1502     2978352 :   real(r8) :: ubm(state%ncol,pver)  ! projection of wind at midpoints
    1503     2978352 :   real(r8) :: xv(state%ncol)        ! unit vector of source wind (x)
    1504     2978352 :   real(r8) :: yv(state%ncol)        ! unit vector of source wind (y)
    1505             : 
    1506             :   integer :: m                      ! dummy integers
    1507     2978352 :   real(r8) :: qtgw(state%ncol,pver,pcnst) ! constituents tendencies
    1508             : 
    1509             :   ! Reynolds stress for waves propagating in each cardinal direction.
    1510     2978352 :   real(r8) :: taucd(state%ncol,pver+1,4)
    1511             : 
    1512             :   ! gravity wave wind tendency for each wave
    1513     1489176 :   real(r8), allocatable :: gwut(:,:,:)
    1514             : 
    1515             :   ! Temperature tendencies from diffusion and kinetic energy.
    1516     2978352 :   real(r8) :: dttdf(state%ncol,pver)
    1517     2978352 :   real(r8) :: dttke(state%ncol,pver)
    1518             : 
    1519             :   ! Wave phase speeds for each column
    1520     1489176 :   real(r8), allocatable :: phase_speeds(:,:)
    1521             : 
    1522             :   ! Efficiency for a gravity wave source.
    1523     2978352 :   real(r8) :: effgw(state%ncol)
    1524             : 
    1525             :   ! Coriolis characteristic speed.
    1526     2978352 :   real(r8) :: u_coriolis(state%ncol)
    1527             : 
    1528             :   ! Adjustment for inertial gravity waves.
    1529     1489176 :   real(r8), allocatable :: ro_adjust(:,:,:)
    1530             : 
    1531             :   ! pbuf fields
    1532             :   ! Molecular diffusivity
    1533     1489176 :   real(r8), pointer :: kvt_in(:,:)
    1534     2978352 :   real(r8) :: kvtt(state%ncol,pver+1)
    1535             : 
    1536             :   ! Frontogenesis
    1537     1489176 :   real(r8), pointer :: frontgf(:,:)
    1538     1489176 :   real(r8), pointer :: frontga(:,:)
    1539             : 
    1540             :   ! Temperature change due to deep convection.
    1541     1489176 :   real(r8), pointer :: ttend_dp(:,:)
    1542             :   ! Temperature change due to shallow convection.
    1543     1489176 :   real(r8), pointer :: ttend_sh(:,:)
    1544             : 
    1545             :   !  New couplings from CLUBB
    1546     1489176 :   real(r8), pointer :: ttend_clubb(:,:)
    1547     1489176 :   real(r8), pointer :: thlp2_clubb_gw(:,:)
    1548     1489176 :   real(r8), pointer :: wpthlp_clubb_gw(:,:)
    1549     1489176 :   real(r8), pointer :: upwp_clubb_gw(:,:)
    1550     1489176 :   real(r8), pointer :: vpwp_clubb_gw(:,:)
    1551     2978352 :   real(r8) :: xpwp_clubb(state%ncol,pver+1)
    1552             : 
    1553             : 
    1554             :   ! Standard deviation of orography.
    1555     1489176 :   real(r8), pointer :: sgh(:)
    1556             : 
    1557             :   ! gridbox area
    1558     1489176 :   real(r8), pointer :: gbxar(:)
    1559             : 
    1560             :      ! Beta ridges
    1561             :   ! width of ridges.
    1562     1489176 :   real(r8), pointer :: hwdth(:,:)
    1563             :   ! length of ridges.
    1564     1489176 :   real(r8), pointer :: clngt(:,:)
    1565             :   ! Maximum deviations of ridges.
    1566     1489176 :   real(r8), pointer :: mxdis(:,:)
    1567             :   ! orientation of ridges.
    1568     1489176 :   real(r8), pointer :: angll(:,:)
    1569             :   ! anisotropy of ridges.
    1570     1489176 :   real(r8), pointer :: anixy(:,:)
    1571             : 
    1572             :      ! Gamma ridges
    1573             :   ! width of ridges.
    1574     1489176 :   real(r8), pointer :: hwdthg(:,:)
    1575             :   ! length of ridges.
    1576     1489176 :   real(r8), pointer :: clngtg(:,:)
    1577             :   ! Maximum deviations of ridges.
    1578     1489176 :   real(r8), pointer :: mxdisg(:,:)
    1579             :   ! orientation of ridges.
    1580     1489176 :   real(r8), pointer :: angllg(:,:)
    1581             :   ! anisotropy of ridges.
    1582     1489176 :   real(r8), pointer :: anixyg(:,:)
    1583             : 
    1584             :   ! Indices of gravity wave source and lowest level where wind tendencies
    1585             :   ! are allowed.
    1586     2978352 :   integer :: src_level(state%ncol)
    1587     2978352 :   integer :: tend_level(state%ncol)
    1588             : 
    1589             :   ! Convective source heating depth.
    1590             :   ! heating depth
    1591     2978352 :   real(r8) :: hdepth(state%ncol)
    1592             :   ! maximum heating rate
    1593     2978352 :   real(r8) :: maxq0(state%ncol)
    1594             : 
    1595             :   ! Scale sgh to account for landfrac.
    1596     2978352 :   real(r8) :: sgh_scaled(state%ncol)
    1597             : 
    1598             :   ! Parameters for the IGW polar taper.
    1599             :   real(r8), parameter :: degree2radian = pi/180._r8
    1600             :   real(r8), parameter :: al0 = 82.5_r8 * degree2radian
    1601             :   real(r8), parameter :: dlat0 = 5.0_r8 * degree2radian
    1602             : 
    1603             :   ! effective gw diffusivity at interfaces needed for output
    1604     2978352 :   real(r8) :: egwdffi(state%ncol,pver+1)
    1605             :   ! sum from the two types of spectral GW
    1606     2978352 :   real(r8) :: egwdffi_tot(state%ncol,pver+1)
    1607             : 
    1608             :   ! Momentum fluxes used by fixer.
    1609     2978352 :   real(r8) :: um_flux(state%ncol), vm_flux(state%ncol)
    1610             :   ! Energy change used by fixer.
    1611     2978352 :   real(r8) :: de(state%ncol)
    1612             : 
    1613             :   ! Which constituents are being affected by diffusion.
    1614             :   logical  :: lq(pcnst)
    1615             : 
    1616             :   ! Contiguous copies of state arrays.
    1617     2978352 :   real(r8) :: dse(state%ncol,pver)
    1618     2978352 :   real(r8) :: t(state%ncol,pver)
    1619     2978352 :   real(r8) :: u(state%ncol,pver)
    1620     2978352 :   real(r8) :: v(state%ncol,pver)
    1621     2978352 :   real(r8) :: q(state%ncol,pver,pcnst)
    1622     2978352 :   real(r8) :: piln(state%ncol,pver+1)
    1623     2978352 :   real(r8) :: zm(state%ncol,pver)
    1624     2978352 :   real(r8) :: zi(state%ncol,pver+1)
    1625             : 
    1626             :   !------------------------------------------------------------------------
    1627             : 
    1628             :   ! Make local copy of input state.
    1629     1489176 :   call physics_state_copy(state, state1)
    1630             : 
    1631             :   ! constituents are all treated as wet mmr
    1632     1489176 :   call set_dry_to_wet(state1, convert_cnst_type='dry')
    1633             : 
    1634     1489176 :   lchnk = state1%lchnk
    1635     1489176 :   ncol  = state1%ncol
    1636             : 
    1637     1489176 :   p = Coords1D(state1%pint(:ncol,:))
    1638             : 
    1639   647999352 :   dse = state1%s(:ncol,:)
    1640   647999352 :   t = state1%t(:ncol,:)
    1641   647999352 :   u = state1%u(:ncol,:)
    1642   647999352 :   v = state1%v(:ncol,:)
    1643  1945487232 :   q = state1%q(:ncol,:,:)
    1644   672865128 :   piln = state1%lnpint(:ncol,:)
    1645   647999352 :   zm = state1%zm(:ncol,:)
    1646   672865128 :   zi = state1%zi(:ncol,:)
    1647             : 
    1648     5956704 :   lq = .true.
    1649             :   call physics_ptend_init(ptend, state1%psetcols, "Gravity wave drag", &
    1650     1489176 :        ls=.true., lu=.true., lv=.true., lq=lq)
    1651             : 
    1652             :   ! Profiles of background state variables
    1653     1489176 :   call gw_prof(ncol, p, cpair, t, rhoi, nm, ni)
    1654             : 
    1655     1489176 :   if (do_molec_diff) then
    1656             :      !--------------------------------------------------------
    1657             :      ! Initialize and calculate local molecular diffusivity
    1658             :      !--------------------------------------------------------
    1659             : 
    1660           0 :      call pbuf_get_field(pbuf, kvt_idx, kvt_in)  ! kvt_in(1:pcols,1:pver+1)
    1661             : 
    1662             :      ! Set kvtt from pbuf field; kvtt still needs a factor of 1/cpairv.
    1663           0 :      kvtt = kvt_in(:ncol,:)
    1664             : 
    1665             :      ! Use linear extrapolation of cpairv to top interface.
    1666             :      kvtt(:,1) = kvtt(:,1) / &
    1667           0 :           (1.5_r8*cpairv(:ncol,1,lchnk) - &
    1668           0 :           0.5_r8*cpairv(:ncol,2,lchnk))
    1669             : 
    1670             :      ! Interpolate cpairv to other interfaces.
    1671           0 :      do k = 2, nbot_molec
    1672           0 :         kvtt(:,k) = kvtt(:,k) / &
    1673           0 :              (cpairv(:ncol,k+1,lchnk)+cpairv(:ncol,k,lchnk)) * 2._r8
    1674             :      enddo
    1675             : 
    1676             :   else
    1677             : 
    1678   672865128 :      kvtt = 0._r8
    1679             : 
    1680             :   end if
    1681             : 
    1682     1489176 :   if (use_gw_front_igw) then
    1683           0 :      u_coriolis = coriolis_speed(band_long, state1%lat(:ncol))
    1684             :   end if
    1685             : 
    1686             :   ! Totals that accumulate over different sources.
    1687   672865128 :   egwdffi_tot = 0._r8
    1688     1489176 :   flx_heat = 0._r8
    1689             : 
    1690     1489176 :   if (use_gw_movmtn_pbl) then
    1691             :      !------------------------------------------------------------------
    1692             :      !Convective moving mountain gravity waves (Beres scheme).
    1693             :      !------------------------------------------------------------------
    1694             : 
    1695           0 :      call outfld('U_MOVMTN_IN', u, ncol, lchnk)
    1696           0 :      call outfld('V_MOVMTN_IN', v, ncol, lchnk)
    1697             : 
    1698             :      ! Allocate wavenumber fields.
    1699           0 :      allocate(tau(ncol,-band_movmtn%ngwv:band_movmtn%ngwv,pver+1),stat=istat)
    1700           0 :      call alloc_err(istat,'gw_tend','tau',ncol*(band_movmtn%ngwv**2+1)*(pver+1))
    1701           0 :      allocate(gwut(ncol,pver,-band_movmtn%ngwv:band_movmtn%ngwv),stat=istat)
    1702           0 :      call alloc_err(istat,'gw_tend','gwut',ncol*pver*band_movmtn%ngwv**2+1)
    1703           0 :      allocate(phase_speeds(ncol,-band_movmtn%ngwv:band_movmtn%ngwv),stat=istat)
    1704           0 :      call alloc_err(istat,'gw_tend','phase_speeds',ncol*band_movmtn%ngwv**2+1)
    1705             : 
    1706             :      ! Set up heating
    1707           0 :      if (ttend_dp_idx > 0) then
    1708           0 :         call pbuf_get_field(pbuf, ttend_dp_idx, ttend_dp)
    1709             :      else
    1710           0 :         allocate(ttend_dp(pcols,pver), stat=istat)
    1711           0 :         call alloc_err(istat, 'gw_tend', 'ttend_dp', pcols*pver)
    1712           0 :         ttend_dp = 0.0_r8
    1713             :      end if
    1714             : 
    1715             :      !   New couplings from CLUBB
    1716           0 :      call pbuf_get_field(pbuf, ttend_clubb_idx, ttend_clubb)
    1717           0 :      call pbuf_get_field(pbuf, thlp2_clubb_gw_idx, thlp2_clubb_gw)
    1718           0 :      call pbuf_get_field(pbuf, wpthlp_clubb_gw_idx, wpthlp_clubb_gw)
    1719           0 :      call pbuf_get_field(pbuf, upwp_clubb_gw_idx, upwp_clubb_gw)
    1720           0 :      call pbuf_get_field(pbuf, vpwp_clubb_gw_idx, vpwp_clubb_gw)
    1721             : 
    1722           0 :      xpwp_clubb(:ncol,:) = sqrt( upwp_clubb_gw(:ncol,:)**2 + vpwp_clubb_gw(:ncol,:)**2 )
    1723             : 
    1724           0 :      effgw = 1._r8
    1725             :      call gw_movmtn_src(ncol, lchnk, band_movmtn , movmtn_desc, &
    1726           0 :           u, v, ttend_dp(:ncol,:), ttend_clubb(:ncol,:), xpwp_clubb(:ncol,:)  , &
    1727             :           zm, alpha_gw_movmtn, src_level, tend_level, &
    1728             :           tau, ubm, ubi, xv, yv, &
    1729           0 :           phase_speeds, hdepth)
    1730             :      !-------------------------------------------------------------
    1731             :      ! gw_movmtn_src returns wave-relative wind profiles ubm,ubi
    1732             :      ! and unit vector components describing direction of wavevector
    1733             :      ! and application of wave-drag force. I believe correct setting
    1734             :      ! for c is c=0, since it is incorporated in ubm and (xv,yv)
    1735             :      !--------------------------------------------------------------
    1736             : 
    1737           0 :      call outfld('SRC_LEVEL_MOVMTN', real(src_level,r8), ncol, lchnk)
    1738           0 :      call outfld('TND_LEVEL_MOVMTN', real(tend_level,r8), ncol, lchnk)
    1739           0 :      call outfld('UBI_MOVMTN', ubi, ncol, lchnk)
    1740           0 :      call outfld('UBM_MOVMTN', ubm, ncol, lchnk)
    1741             : 
    1742             :      call gw_drag_prof(ncol, band_movmtn, p, src_level, tend_level, dt, &
    1743             :           t, vramp,    &
    1744             :           piln, rhoi,       nm,   ni, ubm,  ubi,  xv,    yv,   &
    1745             :           effgw,   phase_speeds,       kvtt, q,  dse,  tau,  utgw,  vtgw, &
    1746             :           ttgw, qtgw, egwdffi,  gwut, dttdf, dttke,            &
    1747           0 :           lapply_effgw_in=gw_apply_tndmax )
    1748             : 
    1749             :      ! Project stress into directional components.
    1750           0 :      taucd = calc_taucd(ncol, band_movmtn%ngwv, tend_level, tau, phase_speeds, xv, yv, ubi)
    1751             : 
    1752             :      !  add the diffusion coefficients
    1753           0 :      do k = 1, pver+1
    1754           0 :         egwdffi_tot(:,k) = egwdffi_tot(:,k) + egwdffi(:,k)
    1755             :      end do
    1756             : 
    1757             :      ! Store constituents tendencies
    1758           0 :      do m=1, pcnst
    1759           0 :         do k = 1, pver
    1760           0 :            ptend%q(:ncol,k,m) = ptend%q(:ncol,k,m) + qtgw(:,k,m)
    1761             :         end do
    1762             :      end do
    1763             : 
    1764             :       ! Add the momentum tendencies to the output tendency arrays.
    1765           0 :      do k = 1, pver
    1766           0 :         ptend%u(:ncol,k) = ptend%u(:ncol,k) + utgw(:,k)
    1767           0 :         ptend%v(:ncol,k) = ptend%v(:ncol,k) + vtgw(:,k)
    1768             :      end do
    1769             : 
    1770           0 :      do k = 1, pver
    1771           0 :         ptend%s(:ncol,k) = ptend%s(:ncol,k) + ttgw(:,k)
    1772             :      end do
    1773             : 
    1774           0 :      call outfld('TAU_MOVMTN', tau(:,0,:), ncol, lchnk)
    1775           0 :      call outfld('GWUT_MOVMTN', gwut(:,:,0), ncol, lchnk)
    1776           0 :      call outfld('VTGW_MOVMTN', vtgw, ncol, lchnk)
    1777           0 :      call outfld('UTGW_MOVMTN', utgw, ncol, lchnk)
    1778           0 :      call outfld('HDEPTH_MOVMTN', hdepth/1000._r8, ncol, lchnk)
    1779           0 :      call outfld('NETDT_MOVMTN', ttend_dp, pcols, lchnk)
    1780           0 :      call outfld('TTEND_CLUBB', ttend_clubb, pcols, lchnk)
    1781           0 :      call outfld('THLP2_CLUBB_GW', thlp2_clubb_gw, pcols, lchnk)
    1782           0 :      call outfld('WPTHLP_CLUBB_GW', wpthlp_clubb_gw, pcols, lchnk)
    1783           0 :      call outfld('UPWP_CLUBB_GW', upwp_clubb_gw, pcols, lchnk)
    1784           0 :      call outfld('VPWP_CLUBB_GW', vpwp_clubb_gw, pcols, lchnk)
    1785             : 
    1786             :      !Deallocate variables that are no longer used:
    1787           0 :      deallocate(tau, gwut, phase_speeds)
    1788             : 
    1789             :      !Deallocate/nullify ttend_dp if not a pbuf variable:
    1790           0 :      if (ttend_dp_idx <= 0) then
    1791           0 :        deallocate(ttend_dp)
    1792             :        nullify(ttend_dp)
    1793             :      end if
    1794             : 
    1795             :   end if
    1796             : 
    1797     1489176 :   if (use_gw_convect_dp) then
    1798             :      !------------------------------------------------------------------
    1799             :      ! Convective gravity waves (Beres scheme, deep).
    1800             :      !------------------------------------------------------------------
    1801             : 
    1802             :      ! Allocate wavenumber fields.
    1803           0 :      allocate(tau(ncol,-band_mid%ngwv:band_mid%ngwv,pver+1),stat=istat)
    1804           0 :      call alloc_err(istat,'gw_tend','tau',ncol*(band_mid%ngwv**2+1)*(pver+1))
    1805           0 :      allocate(gwut(ncol,pver,-band_mid%ngwv:band_mid%ngwv),stat=istat)
    1806           0 :      call alloc_err(istat,'gw_tend','gwut',ncol*pver*(band_mid%ngwv**2+1))
    1807           0 :      allocate(phase_speeds(ncol,-band_mid%ngwv:band_mid%ngwv),stat=istat)
    1808           0 :      call alloc_err(istat,'gw_tend','tau',ncol*(band_mid%ngwv**2+1))
    1809             : 
    1810             :      ! Set up heating
    1811           0 :      call pbuf_get_field(pbuf, ttend_dp_idx, ttend_dp)
    1812             : 
    1813             :      ! Efficiency of gravity wave momentum transfer.
    1814             :      ! This is really only to remove the pole points.
    1815           0 :      where (pi/2._r8 - abs(state1%lat(:ncol)) >= 4*epsilon(1._r8))
    1816             :         effgw = effgw_beres_dp
    1817             :      elsewhere
    1818             :         effgw = 0._r8
    1819             :      end where
    1820             : 
    1821             :      ! Determine wave sources for Beres deep scheme
    1822             :      call gw_beres_src(ncol, band_mid, beres_dp_desc, &
    1823           0 :           u, v, ttend_dp(:ncol,:), zm, src_level, tend_level, tau, &
    1824           0 :           ubm, ubi, xv, yv, phase_speeds, hdepth, maxq0)
    1825             : 
    1826             :      ! Solve for the drag profile with Beres source spectrum.
    1827             :      call gw_drag_prof(ncol, band_mid, p, src_level, tend_level, dt, &
    1828             :           t, vramp,    &
    1829             :           piln, rhoi,       nm,   ni, ubm,  ubi,  xv,    yv,   &
    1830             :           effgw,   phase_speeds,       kvtt, q,  dse,  tau,  utgw,  vtgw, &
    1831             :           ttgw, qtgw, egwdffi,  gwut, dttdf, dttke,            &
    1832           0 :           lapply_effgw_in=gw_apply_tndmax)
    1833             : 
    1834             :      ! Project stress into directional components.
    1835           0 :      taucd = calc_taucd(ncol, band_mid%ngwv, tend_level, tau, phase_speeds, xv, yv, ubi)
    1836             : 
    1837             :      !  add the diffusion coefficients
    1838           0 :      do k = 1, pver+1
    1839           0 :         egwdffi_tot(:,k) = egwdffi_tot(:,k) + egwdffi(:,k)
    1840             :      end do
    1841             : 
    1842             :      ! Store constituents tendencies
    1843           0 :      do m=1, pcnst
    1844           0 :         do k = 1, pver
    1845           0 :            ptend%q(:ncol,k,m) = ptend%q(:ncol,k,m) + qtgw(:,k,m)
    1846             :         end do
    1847             :      end do
    1848             : 
    1849             :      ! Find momentum flux, and use it to fix the wind tendencies below
    1850             :      ! the gravity wave region.
    1851           0 :      call momentum_flux(tend_level, taucd, um_flux, vm_flux)
    1852           0 :      call momentum_fixer(tend_level, p, um_flux, vm_flux, utgw, vtgw)
    1853             : 
    1854             :      ! Add the momentum tendencies to the output tendency arrays.
    1855           0 :      do k = 1, pver
    1856           0 :         ptend%u(:ncol,k) = ptend%u(:ncol,k) + utgw(:,k)
    1857           0 :         ptend%v(:ncol,k) = ptend%v(:ncol,k) + vtgw(:,k)
    1858             :      end do
    1859             : 
    1860             :      ! Find energy change in the current state, and use fixer to apply
    1861             :      ! the difference in lower levels.
    1862           0 :      call energy_change(dt, p, u, v, ptend%u(:ncol,:), &
    1863           0 :           ptend%v(:ncol,:), ptend%s(:ncol,:)+ttgw, de)
    1864           0 :      call energy_fixer(tend_level, p, de-flx_heat(:ncol), ttgw)
    1865             : 
    1866           0 :      do k = 1, pver
    1867           0 :         ptend%s(:ncol,k) = ptend%s(:ncol,k) + ttgw(:,k)
    1868             :      end do
    1869             : 
    1870             :      ! Change ttgw to a temperature tendency before outputing it.
    1871           0 :      ttgw = ttgw / cpair
    1872             :      call gw_spec_outflds(beres_dp_pf, lchnk, ncol, band_mid, phase_speeds, u, v, &
    1873           0 :           xv, yv, gwut, dttdf, dttke, tau(:,:,2:), utgw, vtgw, ttgw, &
    1874           0 :           taucd)
    1875             : 
    1876             :      ! Diagnostic outputs (convert hdepth to km).
    1877           0 :      call outfld('NETDT', ttend_dp, pcols, lchnk)
    1878           0 :      call outfld('HDEPTH', hdepth/1000._r8, ncol, lchnk)
    1879           0 :      call outfld('MAXQ0', maxq0, ncol, lchnk)
    1880             : 
    1881           0 :      deallocate(tau, gwut, phase_speeds)
    1882             : 
    1883             :   end if
    1884             : 
    1885     1489176 :   if (use_gw_convect_sh) then
    1886             :      !------------------------------------------------------------------
    1887             :      ! Convective gravity waves (Beres scheme, shallow).
    1888             :      !------------------------------------------------------------------
    1889             : 
    1890             :      ! Allocate wavenumber fields.
    1891           0 :      allocate(tau(ncol,-band_mid%ngwv:band_mid%ngwv,pver+1),stat=istat)
    1892           0 :      call alloc_err(istat,'gw_tend','tau',ncol*(band_mid%ngwv**2+1)*(pver+1))
    1893           0 :      allocate(gwut(ncol,pver,-band_mid%ngwv:band_mid%ngwv),stat=istat)
    1894           0 :      call alloc_err(istat,'gw_tend','gwut',ncol*pver*(band_mid%ngwv**2+1))
    1895           0 :      allocate(phase_speeds(ncol,-band_mid%ngwv:band_mid%ngwv),stat=istat)
    1896           0 :      call alloc_err(istat,'gw_tend','phase_speeds',ncol*(band_mid%ngwv**2+1))
    1897             : 
    1898             :      ! Set up heating
    1899           0 :      call pbuf_get_field(pbuf, ttend_sh_idx, ttend_sh)
    1900             : 
    1901             :      ! Efficiency of gravity wave momentum transfer.
    1902             :      ! This is really only to remove the pole points.
    1903           0 :      where (pi/2._r8 - abs(state1%lat(:ncol)) >= 4*epsilon(1._r8))
    1904             :         effgw = effgw_beres_sh
    1905             :      elsewhere
    1906             :         effgw = 0._r8
    1907             :      end where
    1908             : 
    1909             :      ! Determine wave sources for Beres shallow scheme
    1910             :      call gw_beres_src(ncol, band_mid, beres_sh_desc, &
    1911           0 :           u, v, ttend_sh(:ncol,:), zm, src_level, tend_level, tau, &
    1912           0 :           ubm, ubi, xv, yv, phase_speeds, hdepth, maxq0)
    1913             : 
    1914             :      ! Solve for the drag profile with Beres source spectrum.
    1915             :      call gw_drag_prof(ncol, band_mid, p, src_level, tend_level,  dt, &
    1916             :           t, vramp,    &
    1917             :           piln, rhoi,       nm,   ni, ubm,  ubi,  xv,    yv,   &
    1918             :           effgw,   phase_speeds,       kvtt, q,  dse,  tau,  utgw,  vtgw, &
    1919             :           ttgw, qtgw, egwdffi,  gwut, dttdf, dttke,            &
    1920           0 :           lapply_effgw_in=gw_apply_tndmax)
    1921             : 
    1922             :      ! Project stress into directional components.
    1923           0 :      taucd = calc_taucd(ncol, band_mid%ngwv, tend_level, tau, phase_speeds, xv, yv, ubi)
    1924             : 
    1925             :      !  add the diffusion coefficients
    1926           0 :      do k = 1, pver+1
    1927           0 :         egwdffi_tot(:,k) = egwdffi_tot(:,k) + egwdffi(:,k)
    1928             :      end do
    1929             : 
    1930             :      ! Store constituents tendencies
    1931           0 :      do m=1, pcnst
    1932           0 :         do k = 1, pver
    1933           0 :            ptend%q(:ncol,k,m) = ptend%q(:ncol,k,m) + qtgw(:,k,m)
    1934             :         end do
    1935             :      end do
    1936             : 
    1937             :      ! Add the momentum tendencies to the output tendency arrays.
    1938             :      ! Don't calculate fixers, since we are too close to the ground to
    1939             :      ! spread momentum/energy differences across low layers.
    1940           0 :      do k = 1, pver
    1941           0 :         ptend%u(:ncol,k) = ptend%u(:ncol,k) + utgw(:,k)
    1942           0 :         ptend%v(:ncol,k) = ptend%v(:ncol,k) + vtgw(:,k)
    1943           0 :         ptend%s(:ncol,k) = ptend%s(:ncol,k) + ttgw(:,k)
    1944             :      end do
    1945             : 
    1946             :      ! Calculate energy change for output to CAM's energy checker.
    1947             :      ! This is sort of cheating; we don't have a good a priori idea of the
    1948             :      ! energy coming from surface stress, so we just integrate what we and
    1949             :      ! actually have so far and overwrite flx_heat with that.
    1950           0 :      call energy_change(dt, p, u, v, ptend%u(:ncol,:), &
    1951           0 :           ptend%v(:ncol,:), ptend%s(:ncol,:), de)
    1952           0 :      flx_heat(:ncol) = de
    1953             : 
    1954             :      ! Change ttgw to a temperature tendency before outputing it.
    1955           0 :      ttgw = ttgw / cpair
    1956             :      call gw_spec_outflds(beres_sh_pf, lchnk, ncol, band_mid, phase_speeds, u, v, &
    1957           0 :           xv, yv, gwut, dttdf, dttke, tau(:,:,2:), utgw, vtgw, ttgw, &
    1958           0 :           taucd)
    1959             : 
    1960             :      ! Diagnostic outputs (convert SHDEPTH to km).
    1961           0 :      call outfld ('SNETDT', ttend_sh, pcols, lchnk)
    1962           0 :      call outfld ('SHDEPTH', hdepth/1000._r8, ncol, lchnk)
    1963           0 :      call outfld ('SMAXQ0', maxq0, ncol, lchnk)
    1964             : 
    1965           0 :      deallocate(tau, gwut, phase_speeds)
    1966             : 
    1967             :   end if
    1968             : 
    1969     1489176 :   if (use_gw_front .or. use_gw_front_igw) then
    1970             :      ! Get frontogenesis physics buffer fields set by dynamics.
    1971           0 :      call pbuf_get_field(pbuf, frontgf_idx, frontgf)
    1972           0 :      call pbuf_get_field(pbuf, frontga_idx, frontga)
    1973             : 
    1974             :      ! Output for diagnostics.
    1975           0 :      call outfld ('FRONTGF', frontgf, pcols, lchnk)
    1976           0 :      call outfld ('FRONTGFA', frontga, pcols, lchnk)
    1977             :   end if
    1978             : 
    1979     1489176 :   if (use_gw_front) then
    1980             :      !------------------------------------------------------------------
    1981             :      ! Frontally generated gravity waves
    1982             :      !------------------------------------------------------------------
    1983             : 
    1984             :      ! Allocate wavenumber fields.
    1985           0 :      allocate(tau(ncol,-band_mid%ngwv:band_mid%ngwv,pver+1),stat=istat)
    1986           0 :      call alloc_err(istat,'gw_tend','tau',ncol*(band_mid%ngwv**2+1)*(pver+1))
    1987           0 :      allocate(gwut(ncol,pver,-band_mid%ngwv:band_mid%ngwv),stat=istat)
    1988           0 :      call alloc_err(istat,'gw_tend','gwut',ncol*pver*(band_mid%ngwv**2+1))
    1989           0 :      allocate(phase_speeds(ncol,-band_mid%ngwv:band_mid%ngwv),stat=istat)
    1990           0 :      call alloc_err(istat,'gw_tend','tau',ncol*(band_mid%ngwv**2+1))
    1991             : 
    1992             :      ! Efficiency of gravity wave momentum transfer.
    1993           0 :      effgw = effgw_cm
    1994             :      ! Frontogenesis is too high at the poles (at least for the FV
    1995             :      ! dycore), so introduce a polar taper.
    1996           0 :      if (gw_polar_taper) effgw = effgw * cos(state1%lat(:ncol))
    1997             : 
    1998             :      ! Determine the wave source for C&M background spectrum
    1999           0 :      call gw_cm_src(ncol, band_mid, cm_desc, u, v, frontgf(:ncol,:), &
    2000           0 :           src_level, tend_level, tau, ubm, ubi, xv, yv, phase_speeds)
    2001             : 
    2002             :      ! Solve for the drag profile with C&M source spectrum.
    2003             :      call gw_drag_prof(ncol, band_mid, p, src_level, tend_level,  dt, &
    2004             :           t, vramp,   &
    2005             :           piln, rhoi,       nm,   ni, ubm,  ubi,  xv,    yv,   &
    2006             :           effgw,   phase_speeds,       kvtt, q,  dse,  tau,  utgw,  vtgw, &
    2007             :           ttgw, qtgw, egwdffi,  gwut, dttdf, dttke,            &
    2008           0 :           lapply_effgw_in=gw_apply_tndmax)
    2009             : 
    2010             :      ! Project stress into directional components.
    2011           0 :      taucd = calc_taucd(ncol, band_mid%ngwv, tend_level, tau, phase_speeds, xv, yv, ubi)
    2012             : 
    2013             :      !  add the diffusion coefficients
    2014           0 :      do k = 1, pver+1
    2015           0 :         egwdffi_tot(:,k) = egwdffi_tot(:,k) + egwdffi(:,k)
    2016             :      end do
    2017             : 
    2018             :      !Add the constituent tendencies
    2019           0 :      do m=1, pcnst
    2020           0 :         do k = 1, pver
    2021           0 :            ptend%q(:ncol,k,m) = ptend%q(:ncol,k,m) + qtgw(:,k,m)
    2022             :         end do
    2023             :      end do
    2024             : 
    2025             :      ! Find momentum flux, and use it to fix the wind tendencies below
    2026             :      ! the gravity wave region.
    2027           0 :      call momentum_flux(tend_level, taucd, um_flux, vm_flux)
    2028           0 :      call momentum_fixer(tend_level, p, um_flux, vm_flux, utgw, vtgw)
    2029             : 
    2030             :      ! add the momentum tendencies to the output tendency arrays
    2031           0 :      do k = 1, pver
    2032           0 :         ptend%u(:ncol,k) = ptend%u(:ncol,k) + utgw(:,k)
    2033           0 :         ptend%v(:ncol,k) = ptend%v(:ncol,k) + vtgw(:,k)
    2034             :      end do
    2035             : 
    2036             :      ! Find energy change in the current state, and use fixer to apply
    2037             :      ! the difference in lower levels.
    2038           0 :      call energy_change(dt, p, u, v, ptend%u(:ncol,:), &
    2039           0 :           ptend%v(:ncol,:), ptend%s(:ncol,:)+ttgw, de)
    2040           0 :      call energy_fixer(tend_level, p, de-flx_heat(:ncol), ttgw)
    2041             : 
    2042           0 :      do k = 1, pver
    2043           0 :         ptend%s(:ncol,k) = ptend%s(:ncol,k) + ttgw(:,k)
    2044             :      end do
    2045             : 
    2046             :      ! Change ttgw to a temperature tendency before outputing it.
    2047           0 :      ttgw = ttgw / cpair
    2048             :      call gw_spec_outflds(cm_pf, lchnk, ncol, band_mid, phase_speeds, u, v, &
    2049           0 :           xv, yv, gwut, dttdf, dttke, tau(:,:,2:), utgw, vtgw, ttgw, &
    2050           0 :           taucd)
    2051             : 
    2052           0 :      deallocate(tau, gwut, phase_speeds)
    2053             : 
    2054             :   end if
    2055             : 
    2056     1489176 :   if (use_gw_front_igw) then
    2057             :      !------------------------------------------------------------------
    2058             :      ! Frontally generated inertial gravity waves
    2059             :      !------------------------------------------------------------------
    2060             : 
    2061             :      ! Allocate wavenumber fields.
    2062           0 :      allocate(tau(ncol,-band_long%ngwv:band_long%ngwv,pver+1),stat=istat)
    2063           0 :      call alloc_err(istat,'gw_tend','tau',ncol*(band_long%ngwv**2+1)*(pver+1))
    2064           0 :      allocate(gwut(ncol,pver,-band_long%ngwv:band_long%ngwv),stat=istat)
    2065           0 :      call alloc_err(istat,'gw_tend','gwut',ncol*pver*(band_long%ngwv**2+1))
    2066           0 :      allocate(phase_speeds(ncol,-band_long%ngwv:band_long%ngwv),stat=istat)
    2067           0 :      call alloc_err(istat,'gw_tend','phase_speeds',ncol*(band_long%ngwv**2+1))
    2068           0 :      allocate(ro_adjust(ncol,-band_long%ngwv:band_long%ngwv,pver+1),stat=istat)
    2069           0 :      call alloc_err(istat,'gw_tend','ro_adjust',ncol*(band_long%ngwv**2+1)*(pver+1))
    2070             : 
    2071             :      ! Efficiency of gravity wave momentum transfer.
    2072           0 :      effgw = effgw_cm_igw
    2073             : 
    2074             :      ! Frontogenesis is too high at the poles (at least for the FV
    2075             :      ! dycore), so introduce a polar taper.
    2076           0 :      if (gw_polar_taper) then
    2077           0 :         where (abs(state1%lat(:ncol)) <= 89._r8*degree2radian)
    2078             :            effgw = effgw * 0.25_r8 * &
    2079           0 :                  (1._r8+tanh((state1%lat(:ncol)+al0)/dlat0)) * &
    2080             :                  (1._r8-tanh((state1%lat(:ncol)-al0)/dlat0))
    2081             :         elsewhere
    2082             :            effgw = 0._r8
    2083             :         end where
    2084             :      end if
    2085             : 
    2086             :      ! Determine the wave source for C&M background spectrum
    2087           0 :      call gw_cm_src(ncol, band_long, cm_igw_desc, u, v, frontgf(:ncol,:), &
    2088           0 :           src_level, tend_level, tau, ubm, ubi, xv, yv, phase_speeds)
    2089             : 
    2090             :      call adjust_inertial(band_long, tend_level, u_coriolis, phase_speeds, ubi, &
    2091           0 :           tau, ro_adjust)
    2092             : 
    2093             :      ! Solve for the drag profile with C&M source spectrum.
    2094             :      call gw_drag_prof(ncol, band_long, p, src_level, tend_level,  dt, &
    2095             :           t, vramp,    &
    2096             :           piln, rhoi,       nm,   ni, ubm,  ubi,  xv,    yv,   &
    2097             :           effgw,   phase_speeds,       kvtt, q,  dse,  tau,  utgw,  vtgw, &
    2098             :           ttgw, qtgw, egwdffi,  gwut, dttdf, dttke, ro_adjust=ro_adjust, &
    2099           0 :           lapply_effgw_in=gw_apply_tndmax)
    2100             : 
    2101             :      ! Project stress into directional components.
    2102           0 :      taucd = calc_taucd(ncol, band_long%ngwv, tend_level, tau, phase_speeds, xv, yv, ubi)
    2103             : 
    2104             :      !  add the diffusion coefficients
    2105           0 :      do k = 1, pver+1
    2106           0 :         egwdffi_tot(:,k) = egwdffi_tot(:,k) + egwdffi(:,k)
    2107             :      end do
    2108             : 
    2109             :      !Add the constituent tendencies
    2110           0 :      do m=1, pcnst
    2111           0 :         do k = 1, pver
    2112           0 :            ptend%q(:ncol,k,m) = ptend%q(:ncol,k,m) + qtgw(:,k,m)
    2113             :         end do
    2114             :      end do
    2115             : 
    2116             :      ! Find momentum flux, and use it to fix the wind tendencies below
    2117             :      ! the gravity wave region.
    2118           0 :      call momentum_flux(tend_level, taucd, um_flux, vm_flux)
    2119           0 :      call momentum_fixer(tend_level, p, um_flux, vm_flux, utgw, vtgw)
    2120             : 
    2121             :      ! add the momentum tendencies to the output tendency arrays
    2122           0 :      do k = 1, pver
    2123           0 :         ptend%u(:ncol,k) = ptend%u(:ncol,k) + utgw(:,k)
    2124           0 :         ptend%v(:ncol,k) = ptend%v(:ncol,k) + vtgw(:,k)
    2125             :      end do
    2126             : 
    2127             :      ! Find energy change in the current state, and use fixer to apply
    2128             :      ! the difference in lower levels.
    2129           0 :      call energy_change(dt, p, u, v, ptend%u(:ncol,:), &
    2130           0 :           ptend%v(:ncol,:), ptend%s(:ncol,:)+ttgw, de)
    2131           0 :      call energy_fixer(tend_level, p, de-flx_heat(:ncol), ttgw)
    2132             : 
    2133           0 :      do k = 1, pver
    2134           0 :         ptend%s(:ncol,k) = ptend%s(:ncol,k) + ttgw(:,k)
    2135             :      end do
    2136             : 
    2137             :      ! Change ttgw to a temperature tendency before outputing it.
    2138           0 :      ttgw = ttgw / cpair
    2139             :      call gw_spec_outflds(cm_igw_pf, lchnk, ncol, band_long, phase_speeds, u, v, &
    2140           0 :           xv, yv, gwut, dttdf, dttke, tau(:,:,2:), utgw, vtgw, ttgw, &
    2141           0 :           taucd)
    2142             : 
    2143           0 :      deallocate(tau, gwut, phase_speeds, ro_adjust)
    2144             : 
    2145             :   end if
    2146             : 
    2147     1489176 :   if (use_gw_oro) then
    2148             :      !---------------------------------------------------------------------
    2149             :      ! Orographic stationary gravity waves
    2150             :      !---------------------------------------------------------------------
    2151             : 
    2152             :      ! Allocate wavenumber fields.
    2153     5956704 :      allocate(tau(ncol,band_oro%ngwv:band_oro%ngwv,pver+1),stat=istat)
    2154     1489176 :      call alloc_err(istat,'gw_tend','tau',ncol*(band_oro%ngwv**2+1)*(pver+1))
    2155     4467528 :      allocate(gwut(ncol,pver,band_oro%ngwv:band_oro%ngwv),stat=istat)
    2156     1489176 :      call alloc_err(istat,'gw_tend','gwut',ncol*pver*(band_oro%ngwv**2+1))
    2157     4467528 :      allocate(phase_speeds(ncol,band_oro%ngwv:band_oro%ngwv),stat=istat)
    2158     1489176 :      call alloc_err(istat,'gw_tend','phase_speeds',ncol*(band_oro%ngwv**2+1))
    2159             : 
    2160             :      ! Efficiency of gravity wave momentum transfer.
    2161             :      ! Take into account that wave sources are only over land.
    2162     1489176 :      call pbuf_get_field(pbuf, sgh_idx, sgh)
    2163             : 
    2164     1489176 :      if (gw_lndscl_sgh) then
    2165   121350528 :         where (cam_in%landfrac(:ncol) >= epsilon(1._r8))
    2166     1489176 :            effgw = effgw_oro * cam_in%landfrac(:ncol)
    2167     1489176 :            sgh_scaled = sgh(:ncol) / sqrt(cam_in%landfrac(:ncol))
    2168             :         elsewhere
    2169             :            effgw = 0._r8
    2170             :            sgh_scaled = 0._r8
    2171             :         end where
    2172             : 
    2173             :         ! Determine the orographic wave source
    2174             :         call gw_oro_src(ncol, band_oro, p, &
    2175             :            u, v, t, sgh_scaled, zm, nm, &
    2176     1489176 :            src_level, tend_level, tau, ubm, ubi, xv, yv, phase_speeds)
    2177             :      else
    2178           0 :         effgw = effgw_oro
    2179             : 
    2180             :         ! Determine the orographic wave source
    2181             :         call gw_oro_src(ncol, band_oro, p, &
    2182           0 :              u, v, t, sgh(:ncol), zm, nm, &
    2183           0 :              src_level, tend_level, tau, ubm, ubi, xv, yv, phase_speeds)
    2184             :      endif
    2185    24865776 :      do i = 1, ncol
    2186    24865776 :         if (state1%lat(i) < 0._r8) then
    2187   642856500 :            tau(i,:,:) = tau(i,:,:) * gw_oro_south_fac
    2188             :         end if
    2189             :      end do
    2190             : 
    2191             :      ! Solve for the drag profile with orographic sources.
    2192             :      call gw_drag_prof(ncol, band_oro, p, src_level, tend_level,   dt,   &
    2193             :           t, vramp,   &
    2194             :           piln, rhoi,       nm,   ni, ubm,  ubi,  xv,    yv,   &
    2195             :           effgw, phase_speeds, kvtt, q,  dse,  tau,  utgw,  vtgw, &
    2196             :           ttgw, qtgw, egwdffi,  gwut, dttdf, dttke,            &
    2197     1489176 :           lapply_effgw_in=gw_apply_tndmax)
    2198             : 
    2199             :      ! For orographic waves, don't bother with taucd, since there are no
    2200             :      ! momentum conservation routines or directional diagnostics.
    2201             : 
    2202             :      !  add the diffusion coefficients
    2203    41696928 :      do k = 1, pver+1
    2204   672865128 :         egwdffi_tot(:,k) = egwdffi_tot(:,k) + egwdffi(:,k)
    2205             :      end do
    2206             : 
    2207             :      ! Add the orographic tendencies to the spectrum tendencies.
    2208             :      ! Don't calculate fixers, since we are too close to the ground to
    2209             :      ! spread momentum/energy differences across low layers.
    2210    40207752 :      do k = 1, pver
    2211   646510176 :         ptend%u(:ncol,k) = ptend%u(:ncol,k) + utgw(:,k)
    2212   646510176 :         ptend%v(:ncol,k) = ptend%v(:ncol,k) + vtgw(:,k)
    2213   646510176 :         ptend%s(:ncol,k) = ptend%s(:ncol,k) + ttgw(:,k)
    2214             :         ! Convert to temperature tendency for output.
    2215   647999352 :         ttgw(:,k) = ttgw(:,k) / cpairv(:ncol, k, lchnk)
    2216             :      end do
    2217             : 
    2218             :      ! Calculate energy change for output to CAM's energy checker.
    2219             :      ! This is sort of cheating; we don't have a good a priori idea of the
    2220             :      ! energy coming from surface stress, so we just integrate what we and
    2221             :      ! actually have so far and overwrite flx_heat with that.
    2222           0 :      call energy_change(dt, p, u, v, ptend%u(:ncol,:), &
    2223     1489176 :           ptend%v(:ncol,:), ptend%s(:ncol,:), de)
    2224    24865776 :      flx_heat(:ncol) = de
    2225             : 
    2226     5956704 :      do m = 1, pcnst
    2227   122112432 :         do k = 1, pver
    2228  1943998056 :            ptend%q(:ncol,k,m) = ptend%q(:ncol,k,m) + qtgw(:,k,m)
    2229             :         end do
    2230             :      end do
    2231             : 
    2232             :      ! Write output fields to history file
    2233     1489176 :      call outfld('TAUAORO', tau(:,0,:),  ncol, lchnk)
    2234     1489176 :      call outfld('UTGWORO', utgw,  ncol, lchnk)
    2235     1489176 :      call outfld('VTGWORO', vtgw,  ncol, lchnk)
    2236     1489176 :      call outfld('TTGWORO', ttgw,  ncol, lchnk)
    2237   647999352 :      call outfld('TTGWSDFORO', dttdf / cpair,  ncol, lchnk)
    2238   647999352 :      call outfld('TTGWSKEORO', dttke / cpair,  ncol, lchnk)
    2239    24865776 :      tau0x = tau(:,0,pver+1) * xv
    2240    24865776 :      tau0y = tau(:,0,pver+1) * yv
    2241     1489176 :      call outfld('TAUGWX', tau0x, ncol, lchnk)
    2242     1489176 :      call outfld('TAUGWY', tau0y, ncol, lchnk)
    2243             : 
    2244     1489176 :      deallocate(tau, gwut, phase_speeds)
    2245             : 
    2246             :   end if
    2247             : 
    2248     1489176 :   if (use_gw_rdg_beta) then
    2249             :      !---------------------------------------------------------------------
    2250             :      ! Orographic stationary gravity waves
    2251             :      !---------------------------------------------------------------------
    2252             : 
    2253             :      ! Efficiency of gravity wave momentum transfer.
    2254             :      ! Take into account that wave sources are only over land.
    2255             : 
    2256           0 :      hwdth => rdg_hwdth(:ncol,:,lchnk)
    2257           0 :      clngt => rdg_clngt(:ncol,:,lchnk)
    2258           0 :      gbxar => rdg_gbxar(:ncol,lchnk)
    2259           0 :      mxdis => rdg_mxdis(:ncol,:,lchnk)
    2260           0 :      angll => rdg_angll(:ncol,:,lchnk)
    2261           0 :      anixy => rdg_anixy(:ncol,:,lchnk)
    2262             : 
    2263           0 :      where(mxdis < 0._r8)
    2264             :         mxdis = 0._r8
    2265             :      end where
    2266             : 
    2267             :      ! Save state at top of routine
    2268             :      ! Useful for unit testing checks
    2269           0 :      call outfld('UEGW', u ,  ncol, lchnk)
    2270           0 :      call outfld('VEGW', v ,  ncol, lchnk)
    2271           0 :      call outfld('TEGW', t ,  ncol, lchnk)
    2272           0 :      call outfld('ZEGW', zi , ncol, lchnk)
    2273           0 :      call outfld('ZMGW', zm , ncol, lchnk)
    2274             : 
    2275             :      call gw_rdg_calc(&
    2276             :         'BETA ', ncol, lchnk, n_rdg_beta, dt,     &
    2277             :         u, v, t, p, piln, zm, zi,                 &
    2278             :         nm, ni, rhoi, kvtt, q, dse,               &
    2279             :         effgw_rdg_beta, effgw_rdg_beta_max,       &
    2280             :         hwdth, clngt, gbxar, mxdis, angll, anixy, &
    2281             :         rdg_beta_cd_llb, trpd_leewv_rdg_beta,     &
    2282           0 :         ptend, flx_heat)
    2283             : 
    2284             :   end if
    2285             : 
    2286     1489176 :   if (use_gw_rdg_gamma) then
    2287             :      !---------------------------------------------------------------------
    2288             :      ! Orographic stationary gravity waves
    2289             :      !---------------------------------------------------------------------
    2290             : 
    2291             :      ! Efficiency of gravity wave momentum transfer.
    2292             :      ! Take into account that wave sources are only over land.
    2293             : 
    2294           0 :      hwdthg => rdg_hwdthg(:ncol,:,lchnk)
    2295           0 :      clngtg => rdg_clngtg(:ncol,:,lchnk)
    2296           0 :      gbxar  => rdg_gbxar(:ncol,lchnk)
    2297           0 :      mxdisg => rdg_mxdisg(:ncol,:,lchnk)
    2298           0 :      angllg => rdg_angllg(:ncol,:,lchnk)
    2299           0 :      anixyg => rdg_anixyg(:ncol,:,lchnk)
    2300             : 
    2301           0 :      where(mxdisg < 0._r8)
    2302             :         mxdisg = 0._r8
    2303             :      end where
    2304             : 
    2305             :      call gw_rdg_calc(&
    2306             :         'GAMMA', ncol, lchnk, n_rdg_gamma, dt,         &
    2307             :         u, v, t, p, piln, zm, zi,                      &
    2308             :         nm, ni, rhoi, kvtt, q, dse,                    &
    2309             :         effgw_rdg_gamma, effgw_rdg_gamma_max,          &
    2310             :         hwdthg, clngtg, gbxar, mxdisg, angllg, anixyg, &
    2311             :         rdg_gamma_cd_llb, trpd_leewv_rdg_gamma,        &
    2312           0 :         ptend, flx_heat)
    2313             : 
    2314             :   endif
    2315             : 
    2316             :   ! Convert the tendencies for the dry constituents to dry air basis.
    2317     5956704 :   do m = 1, pcnst
    2318     5956704 :      if (cnst_type(m).eq.'dry') then
    2319           0 :         do k = 1, pver
    2320           0 :            do i = 1, ncol
    2321           0 :               ptend%q(i,k,m) = ptend%q(i,k,m)*state1%pdel(i,k)/state1%pdeldry(i,k)
    2322             :            end do
    2323             :         end do
    2324             :      end if
    2325             :   end do
    2326             : 
    2327             :   ! Write totals to history file.
    2328     1489176 :   call outfld('EKGW', egwdffi_tot , ncol, lchnk)
    2329   659704968 :   call outfld('TTGW', ptend%s/cpairv(:,:,lchnk),  pcols, lchnk)
    2330             : 
    2331     1489176 :   call outfld('UTGW_TOTAL', ptend%u, pcols, lchnk)
    2332     1489176 :   call outfld('VTGW_TOTAL', ptend%v, pcols, lchnk)
    2333             : 
    2334     1489176 :   call outfld('QTGW', ptend%q(:,:,1), pcols, lchnk)
    2335     1489176 :   call outfld('CLDLIQTGW', ptend%q(:,:,ixcldliq), pcols, lchnk)
    2336     1489176 :   call outfld('CLDICETGW', ptend%q(:,:,ixcldice), pcols, lchnk)
    2337             : 
    2338             :   ! Destroy objects.
    2339     1489176 :   call p%finalize()
    2340             : 
    2341     2978352 : end subroutine gw_tend
    2342             : 
    2343             : !==========================================================================
    2344             : 
    2345           0 : subroutine gw_rdg_calc( &
    2346           0 :    type, ncol, lchnk, n_rdg, dt, &
    2347           0 :    u, v, t, p, piln, zm, zi, &
    2348           0 :    nm, ni, rhoi, kvtt, q, dse, &
    2349             :    effgw_rdg, effgw_rdg_max, &
    2350           0 :    hwdth, clngt, gbxar, &
    2351           0 :    mxdis, angll, anixy, &
    2352             :    rdg_cd_llb, trpd_leewv, &
    2353             :    ptend, flx_heat)
    2354             : 
    2355     1489176 :    use coords_1d,  only: Coords1D
    2356             :    use gw_rdg,     only: gw_rdg_src, gw_rdg_belowpeak, gw_rdg_break_trap, gw_rdg_do_vdiff
    2357             :    use gw_common,  only: gw_drag_prof, energy_change
    2358             : 
    2359             :    character(len=5), intent(in) :: type         ! BETA or GAMMA
    2360             :    integer,          intent(in) :: ncol         ! number of atmospheric columns
    2361             :    integer,          intent(in) :: lchnk        ! chunk identifier
    2362             :    integer,          intent(in) :: n_rdg
    2363             :    real(r8),         intent(in) :: dt           ! Time step.
    2364             : 
    2365             :    real(r8),         intent(in) :: u(ncol,pver)    ! Midpoint zonal winds. ( m s-1)
    2366             :    real(r8),         intent(in) :: v(ncol,pver)    ! Midpoint meridional winds. ( m s-1)
    2367             :    real(r8),         intent(in) :: t(ncol,pver)    ! Midpoint temperatures. (K)
    2368             :    type(Coords1D),   intent(in) :: p               ! Pressure coordinates.
    2369             :    real(r8),         intent(in) :: piln(ncol,pver+1)  ! Log of interface pressures.
    2370             :    real(r8),         intent(in) :: zm(ncol,pver)   ! Midpoint altitudes above ground (m).
    2371             :    real(r8),         intent(in) :: zi(ncol,pver+1) ! Interface altitudes above ground (m).
    2372             :    real(r8),         intent(in) :: nm(ncol,pver)   ! Midpoint Brunt-Vaisalla frequencies (s-1).
    2373             :    real(r8),         intent(in) :: ni(ncol,pver+1) ! Interface Brunt-Vaisalla frequencies (s-1).
    2374             :    real(r8),         intent(in) :: rhoi(ncol,pver+1) ! Interface density (kg m-3).
    2375             :    real(r8),         intent(in) :: kvtt(ncol,pver+1) ! Molecular thermal diffusivity.
    2376             :    real(r8),         intent(in) :: q(:,:,:)        ! Constituent array.
    2377             :    real(r8),         intent(in) :: dse(ncol,pver)  ! Dry static energy.
    2378             : 
    2379             : 
    2380             :    real(r8),         intent(in) :: effgw_rdg       ! Tendency efficiency.
    2381             :    real(r8),         intent(in) :: effgw_rdg_max
    2382             :    real(r8),         intent(in) :: hwdth(ncol,prdg) ! width of ridges.
    2383             :    real(r8),         intent(in) :: clngt(ncol,prdg) ! length of ridges.
    2384             :    real(r8),         intent(in) :: gbxar(ncol)      ! gridbox area
    2385             : 
    2386             :    real(r8),         intent(in) :: mxdis(ncol,prdg) ! Height estimate for ridge (m).
    2387             :    real(r8),         intent(in) :: angll(ncol,prdg) ! orientation of ridges.
    2388             :    real(r8),         intent(in) :: anixy(ncol,prdg) ! Anisotropy parameter.
    2389             : 
    2390             :    real(r8),         intent(in) :: rdg_cd_llb      ! Drag coefficient for low-level flow
    2391             :    logical,          intent(in) :: trpd_leewv
    2392             : 
    2393             :    type(physics_ptend), intent(inout):: ptend   ! Parameterization net tendencies.
    2394             : 
    2395             :    real(r8),        intent(out) :: flx_heat(pcols)
    2396             : 
    2397             :    !---------------------------Local storage-------------------------------
    2398             : 
    2399             :    integer :: k, m, nn, istat
    2400             : 
    2401           0 :    real(r8), allocatable :: tau(:,:,:)  ! wave Reynolds stress
    2402             :    ! gravity wave wind tendency for each wave
    2403           0 :    real(r8), allocatable :: gwut(:,:,:)
    2404             :    ! Wave phase speeds for each column
    2405           0 :    real(r8), allocatable :: phase_speeds(:,:)
    2406             : 
    2407             :    ! Isotropic source flag [anisotropic orography].
    2408           0 :    integer  :: isoflag(ncol)
    2409             : 
    2410             :    ! horiz wavenumber [anisotropic orography].
    2411           0 :    real(r8) :: kwvrdg(ncol)
    2412             : 
    2413             :    ! Efficiency for a gravity wave source.
    2414           0 :    real(r8) :: effgw(ncol)
    2415             : 
    2416             :    ! Indices of top gravity wave source level and lowest level where wind
    2417             :    ! tendencies are allowed.
    2418           0 :    integer :: src_level(ncol)
    2419           0 :    integer :: tend_level(ncol)
    2420           0 :    integer :: bwv_level(ncol)
    2421           0 :    integer :: tlb_level(ncol)
    2422             : 
    2423             :    ! Projection of wind at midpoints and interfaces.
    2424           0 :    real(r8) :: ubm(ncol,pver)
    2425           0 :    real(r8) :: ubi(ncol,pver+1)
    2426             : 
    2427             :    ! Unit vectors of source wind (zonal and meridional components).
    2428           0 :    real(r8) :: xv(ncol)
    2429           0 :    real(r8) :: yv(ncol)
    2430             : 
    2431             :    ! Averages over source region.
    2432           0 :    real(r8) :: ubmsrc(ncol) ! On-ridge wind.
    2433           0 :    real(r8) :: usrc(ncol)   ! Zonal wind.
    2434           0 :    real(r8) :: vsrc(ncol)   ! Meridional wind.
    2435           0 :    real(r8) :: nsrc(ncol)   ! B-V frequency.
    2436           0 :    real(r8) :: rsrc(ncol)   ! Density.
    2437             : 
    2438             :    ! normalized wavenumber
    2439           0 :    real(r8) :: m2src(ncol)
    2440             : 
    2441             :    ! Top of low-level flow layer.
    2442           0 :    real(r8) :: tlb(ncol)
    2443             : 
    2444             :    ! Bottom of linear wave region.
    2445           0 :    real(r8) :: bwv(ncol)
    2446             : 
    2447             :    ! Froude numbers for flow/drag regimes
    2448           0 :    real(r8) :: Fr1(ncol)
    2449           0 :    real(r8) :: Fr2(ncol)
    2450           0 :    real(r8) :: Frx(ncol)
    2451             : 
    2452             :    ! Wave Reynolds stresses at source level
    2453           0 :    real(r8) :: tauoro(ncol)
    2454           0 :    real(r8) :: taudsw(ncol)
    2455             : 
    2456             :    ! Surface streamline displacement height for linear waves.
    2457           0 :    real(r8) :: hdspwv(ncol)
    2458             : 
    2459             :    ! Surface streamline displacement height for downslope wind regime.
    2460           0 :    real(r8) :: hdspdw(ncol)
    2461             : 
    2462             :    ! Wave breaking level
    2463           0 :    real(r8) :: wbr(ncol)
    2464             : 
    2465           0 :    real(r8) :: utgw(ncol,pver)       ! zonal wind tendency
    2466           0 :    real(r8) :: vtgw(ncol,pver)       ! meridional wind tendency
    2467           0 :    real(r8) :: ttgw(ncol,pver)       ! temperature tendency
    2468           0 :    real(r8) :: qtgw(ncol,pver,pcnst) ! constituents tendencies
    2469             : 
    2470             :    ! Effective gravity wave diffusivity at interfaces.
    2471           0 :    real(r8) :: egwdffi(ncol,pver+1)
    2472             : 
    2473             :    ! Temperature tendencies from diffusion and kinetic energy.
    2474           0 :    real(r8) :: dttdf(ncol,pver)
    2475           0 :    real(r8) :: dttke(ncol,pver)
    2476             : 
    2477             :    ! Wave stress in zonal/meridional direction
    2478           0 :    real(r8) :: taurx(ncol,pver+1)
    2479           0 :    real(r8) :: taurx0(ncol,pver+1)
    2480           0 :    real(r8) :: taury(ncol,pver+1)
    2481           0 :    real(r8) :: taury0(ncol,pver+1)
    2482             :    ! Provisional absolute wave stress from gw_drag_prof
    2483           0 :    real(r8) :: tau_diag(ncol,pver+1)
    2484             : 
    2485             :    ! U,V tendency accumulators
    2486           0 :    real(r8) :: utrdg(ncol,pver)
    2487           0 :    real(r8) :: vtrdg(ncol,pver)
    2488           0 :    real(r8) :: ttrdg(ncol,pver)
    2489             : 
    2490             :    ! Energy change used by fixer.
    2491           0 :    real(r8) :: de(ncol)
    2492             : 
    2493             :    character(len=1) :: cn
    2494             :    character(len=9) :: fname(4)
    2495             :    !----------------------------------------------------------------------------
    2496             : 
    2497             :    ! Allocate wavenumber fields.
    2498           0 :    allocate(tau(ncol,band_oro%ngwv:band_oro%ngwv,pver+1),stat=istat)
    2499           0 :    call alloc_err(istat,'gw_rdg_calc','tau',ncol*(band_oro%ngwv**2+1)*(pver+1))
    2500           0 :    allocate(gwut(ncol,pver,band_oro%ngwv:band_oro%ngwv),stat=istat)
    2501           0 :    call alloc_err(istat,'rdg_calc','gwut',ncol*pver*(band_oro%ngwv**2+1))
    2502           0 :    allocate(phase_speeds(ncol,band_oro%ngwv:band_oro%ngwv),stat=istat)
    2503           0 :    call alloc_err(istat,'rdg_calc','phase_speeds',ncol*(band_oro%ngwv**2+1))
    2504             : 
    2505             :    ! initialize accumulated momentum fluxes and tendencies
    2506           0 :    taurx = 0._r8
    2507           0 :    taury = 0._r8
    2508           0 :    ttrdg = 0._r8
    2509           0 :    utrdg = 0._r8
    2510           0 :    vtrdg = 0._r8
    2511           0 :    tau_diag = -9999._r8
    2512             : 
    2513           0 :    do nn = 1, n_rdg
    2514           0 :       kwvrdg  = 0.001_r8 / ( hwdth(:,nn) + 0.001_r8 ) ! this cant be done every time step !!!
    2515           0 :       isoflag = 0
    2516           0 :       effgw   = effgw_rdg * ( hwdth(1:ncol,nn)* clngt(1:ncol,nn) ) / gbxar(1:ncol)
    2517           0 :       effgw   = min( effgw_rdg_max , effgw )
    2518             : 
    2519             :       call gw_rdg_src(ncol, band_oro, p, &
    2520             :          u, v, t, mxdis(:,nn), angll(:,nn), anixy(:,nn), kwvrdg, isoflag, zi, nm, &
    2521             :          src_level, tend_level, bwv_level, tlb_level, tau, ubm, ubi, xv, yv,  &
    2522           0 :          ubmsrc, usrc, vsrc, nsrc, rsrc, m2src, tlb, bwv, Fr1, Fr2, Frx, phase_speeds)
    2523             : 
    2524             :       call gw_rdg_belowpeak(ncol, band_oro, rdg_cd_llb, &
    2525             :          t, mxdis(:,nn), anixy(:,nn), kwvrdg, &
    2526             :          zi, nm, ni, rhoi, &
    2527             :          src_level, tau, &
    2528             :          ubmsrc, nsrc, rsrc, m2src, tlb, bwv, Fr1, Fr2, Frx, &
    2529           0 :          tauoro, taudsw, hdspwv, hdspdw)
    2530             : 
    2531             : 
    2532             :       call gw_rdg_break_trap(ncol, band_oro, &
    2533             :          zi, nm, ni, ubm, ubi, rhoi, kwvrdg , bwv, tlb, wbr, &
    2534             :          src_level, tlb_level, hdspwv, hdspdw,  mxdis(:,nn), &
    2535             :          tauoro, taudsw, tau, &
    2536           0 :          ldo_trapped_waves=trpd_leewv)
    2537             : 
    2538             : 
    2539             :       call gw_drag_prof(ncol, band_oro, p, src_level, tend_level, dt, &
    2540             :          t, vramp,    &
    2541             :          piln, rhoi, nm, ni, ubm, ubi, xv, yv,   &
    2542             :          effgw, phase_speeds, kvtt, q, dse, tau, utgw, vtgw, &
    2543             :          ttgw, qtgw, egwdffi,   gwut, dttdf, dttke, &
    2544             :          kwvrdg=kwvrdg, &
    2545           0 :          satfac_in = 1._r8, lapply_vdiff=gw_rdg_do_vdiff , tau_diag=tau_diag )
    2546             : 
    2547             :       ! Add the tendencies from each ridge to the totals.
    2548           0 :       do k = 1, pver
    2549             :          ! diagnostics
    2550           0 :          utrdg(:,k) = utrdg(:,k) + utgw(:,k)
    2551           0 :          vtrdg(:,k) = vtrdg(:,k) + vtgw(:,k)
    2552           0 :          ttrdg(:,k) = ttrdg(:,k) + ttgw(:,k)
    2553             :          ! physics tendencies
    2554           0 :          ptend%u(:ncol,k) = ptend%u(:ncol,k) + utgw(:,k)
    2555           0 :          ptend%v(:ncol,k) = ptend%v(:ncol,k) + vtgw(:,k)
    2556           0 :          ptend%s(:ncol,k) = ptend%s(:ncol,k) + ttgw(:,k)
    2557             :       end do
    2558             : 
    2559           0 :       do m = 1, pcnst
    2560           0 :          do k = 1, pver
    2561           0 :             ptend%q(:ncol,k,m) = ptend%q(:ncol,k,m) + qtgw(:,k,m)
    2562             :          end do
    2563             :       end do
    2564             : 
    2565           0 :       do k = 1, pver+1
    2566           0 :          taurx0(:,k) =  tau(:,0,k)*xv
    2567           0 :          taury0(:,k) =  tau(:,0,k)*yv
    2568           0 :          taurx(:,k)  =  taurx(:,k) + taurx0(:,k)
    2569           0 :          taury(:,k)  =  taury(:,k) + taury0(:,k)
    2570             :       end do
    2571             : 
    2572           0 :       if (nn == 1) then
    2573           0 :          call outfld('BWV_HT1', bwv,     ncol, lchnk)
    2574           0 :          call outfld('TLB_HT1', tlb,     ncol, lchnk)
    2575           0 :          call outfld('WBR_HT1', wbr,     ncol, lchnk)
    2576           0 :          call outfld('TAUDSW1', taudsw,  ncol, lchnk)
    2577           0 :          call outfld('TAUORO1', tauoro,  ncol, lchnk)
    2578           0 :          call outfld('UBMSRC1', ubmsrc,  ncol, lchnk)
    2579           0 :          call outfld('USRC1',   usrc,    ncol, lchnk)
    2580           0 :          call outfld('VSRC1',   vsrc,    ncol, lchnk)
    2581           0 :          call outfld('NSRC1'  , nsrc,    ncol, lchnk)
    2582             :          ! Froude numbers
    2583           0 :          call outfld('Fr1_DIAG' , Fr1,    ncol, lchnk)
    2584           0 :          call outfld('Fr2_DIAG' , Fr2,    ncol, lchnk)
    2585           0 :          call outfld('Frx_DIAG' , Frx,    ncol, lchnk)
    2586             :          ! Ridge quantities - don't change.  Written for convenience
    2587           0 :          call outfld('MXDIS1' , mxdis(:,nn) ,  ncol, lchnk)
    2588           0 :          call outfld('ANGLL1' , angll(:,nn) ,  ncol, lchnk)
    2589           0 :          call outfld('ANIXY1' , anixy(:,nn) ,  ncol, lchnk)
    2590           0 :          call outfld('HWDTH1' , hwdth(:,nn) ,  ncol, lchnk)
    2591           0 :          call outfld('CLNGT1' , clngt(:,nn) ,  ncol, lchnk)
    2592           0 :          call outfld('GBXAR1' , gbxar ,        ncol, lchnk)
    2593           0 :          call outfld('TAUM1_DIAG' , tau_diag ,  ncol, lchnk)
    2594           0 :          call outfld('TAU1RDG'//trim(type)//'M', tau(:,0,:),  ncol, lchnk)
    2595           0 :          call outfld('UBM1'//trim(type),         ubm,         ncol, lchnk)
    2596           0 :          call outfld('UBT1RDG'//trim(type),      gwut,        ncol, lchnk)
    2597             :       end if
    2598             : 
    2599           0 :       if (nn <= 6) then
    2600           0 :          write(cn, '(i1)') nn
    2601           0 :          call outfld('TAU'//cn//'RDG'//trim(type)//'X', taurx0,  ncol, lchnk)
    2602           0 :          call outfld('TAU'//cn//'RDG'//trim(type)//'Y', taury0,  ncol, lchnk)
    2603           0 :          call outfld('UT'//cn//'RDG'//trim(type),       utgw,    ncol, lchnk)
    2604           0 :          call outfld('VT'//cn//'RDG'//trim(type),       vtgw,    ncol, lchnk)
    2605             :       end if
    2606             : 
    2607             :    end do ! end of loop over multiple ridges
    2608             : 
    2609             :    ! Calculate energy change for output to CAM's energy checker.
    2610           0 :    call energy_change(dt, p, u, v, ptend%u(:ncol,:), &
    2611           0 :           ptend%v(:ncol,:), ptend%s(:ncol,:), de)
    2612           0 :    flx_heat(:ncol) = de
    2613             : 
    2614           0 :    call outfld('TAUARDG'//trim(type)//'X', taurx,  ncol, lchnk)
    2615           0 :    call outfld('TAUARDG'//trim(type)//'Y', taury,  ncol, lchnk)
    2616             : 
    2617           0 :    if (trim(type) == 'BETA') then
    2618           0 :       fname(1) = 'TAUGWX'
    2619           0 :       fname(2) = 'TAUGWY'
    2620           0 :       fname(3) = 'UTGWORO'
    2621           0 :       fname(4) = 'VTGWORO'
    2622           0 :    else if (trim(type) == 'GAMMA') then
    2623           0 :       fname(1) = 'TAURDGGMX'
    2624           0 :       fname(2) = 'TAURDGGMY'
    2625           0 :       fname(3) = 'UTRDGGM'
    2626           0 :       fname(4) = 'VTRDGGM'
    2627             :    else
    2628             :       call endrun('gw_rdg_calc: FATAL: type must be either BETA or GAMMA'&
    2629           0 :                   //' type= '//type)
    2630             :    end if
    2631             : 
    2632           0 :    call outfld(fname(1), taurx(:,pver+1), ncol, lchnk)
    2633           0 :    call outfld(fname(2), taury(:,pver+1), ncol, lchnk)
    2634           0 :    call outfld(fname(3), utrdg,  ncol, lchnk)
    2635           0 :    call outfld(fname(4), vtrdg,  ncol, lchnk)
    2636           0 :    call outfld('TTGWORO', ttrdg / cpair,  ncol, lchnk)
    2637             : 
    2638           0 :    deallocate(tau, gwut, phase_speeds)
    2639             : 
    2640           0 : end subroutine gw_rdg_calc
    2641             : 
    2642             : !==========================================================================
    2643             : 
    2644             : ! Add all history fields for a gravity wave spectrum source.
    2645           0 : subroutine gw_spec_addflds(prefix, scheme, band, history_defaults)
    2646             :   use cam_history, only: addfld, add_default, register_vector_field
    2647             : 
    2648             :   !------------------------------Arguments--------------------------------
    2649             : 
    2650             :   ! One character prefix prepended to output fields.
    2651             :   character(len=1), intent(in) :: prefix
    2652             :   ! Gravity wave scheme name prepended to output field descriptions.
    2653             :   character(len=*), intent(in) :: scheme
    2654             :   ! Wave speeds.
    2655             :   type(GWBand), intent(in) :: band
    2656             :   ! Whether or not to call add_default for fields output by WACCM.
    2657             :   logical, intent(in) :: history_defaults
    2658             : 
    2659             :   !---------------------------Local storage-------------------------------
    2660             : 
    2661             :   integer :: l
    2662             :   ! 7 chars is enough for "-100.00"
    2663             :   character(len=7)  :: fnum
    2664             :   ! 10 chars is enough for "BTAUXSn32"
    2665             :   character(len=10) :: dumc1x, dumc1y
    2666             :   ! Allow 80 chars for description
    2667             :   character(len=80) dumc2
    2668             : 
    2669             :   !-----------------------------------------------------------------------
    2670             : 
    2671             :   ! Overall wind tendencies.
    2672             :   call addfld (trim(prefix)//'UTGWSPEC',(/ 'lev' /), 'A','m s-2', &
    2673           0 :        trim(scheme)//' U tendency - gravity wave spectrum')
    2674             :   call addfld (trim(prefix)//'VTGWSPEC',(/ 'lev' /), 'A','m s-2', &
    2675           0 :        trim(scheme)//' V tendency - gravity wave spectrum')
    2676           0 :   call register_vector_field(trim(prefix)//'UTGWSPEC',trim(prefix)//'VTGWSPEC')
    2677             : 
    2678             :   call addfld (trim(prefix)//'TTGWSPEC',(/ 'lev' /), 'A','K s-1', &
    2679           0 :        trim(scheme)//' T tendency - gravity wave spectrum')
    2680             : 
    2681             :   ! Wind tendencies broken across five spectral bins.
    2682             :   call addfld (trim(prefix)//'UTEND1',  (/ 'lev' /), 'A','m s-2', &
    2683           0 :        trim(scheme)//' U tendency   c < -40')
    2684             :   call addfld (trim(prefix)//'UTEND2',  (/ 'lev' /), 'A','m s-2', &
    2685           0 :        trim(scheme)//' U tendency  -40 < c < -15')
    2686             :   call addfld (trim(prefix)//'UTEND3',  (/ 'lev' /), 'A','m s-2', &
    2687           0 :        trim(scheme)//' U tendency  -15 < c <  15')
    2688             :   call addfld (trim(prefix)//'UTEND4',  (/ 'lev' /), 'A','m s-2', &
    2689           0 :        trim(scheme)//' U tendency   15 < c <  40')
    2690             :   call addfld (trim(prefix)//'UTEND5',  (/ 'lev' /), 'A','m s-2', &
    2691           0 :        trim(scheme)//' U tendency   40 < c ')
    2692             : 
    2693             :   ! Reynold's stress toward each cardinal direction, and net zonal stress.
    2694             :   call addfld (trim(prefix)//'TAUE' ,   (/ 'ilev' /), 'A','Pa', &
    2695           0 :        trim(scheme)//' Eastward Reynolds stress')
    2696             :   call addfld (trim(prefix)//'TAUW' ,   (/ 'ilev' /), 'A','Pa', &
    2697           0 :        trim(scheme)//' Westward Reynolds stress')
    2698             :   call addfld (trim(prefix)//'TAUNET' , (/ 'ilev' /), 'A','Pa', &
    2699           0 :        trim(scheme)//' E+W Reynolds stress')
    2700             :   call addfld (trim(prefix)//'TAUN' ,   (/ 'ilev' /), 'A','Pa', &
    2701           0 :        trim(scheme)//' Northward Reynolds stress')
    2702             :   call addfld (trim(prefix)//'TAUS' ,   (/ 'ilev' /), 'A','Pa', &
    2703           0 :        trim(scheme)//' Southward Reynolds stress')
    2704             : 
    2705             :   ! Momentum flux in each direction.
    2706             :   call addfld (trim(prefix)//'EMF',       (/ 'lev' /), 'A','Pa', &
    2707           0 :        trim(scheme)//' Eastward MF')
    2708             :   call addfld (trim(prefix)//'WMF',       (/ 'lev' /), 'A','Pa', &
    2709           0 :        trim(scheme)//' Westward MF')
    2710             :   call addfld (trim(prefix)//'NMF',       (/ 'lev' /), 'A','Pa', &
    2711           0 :        trim(scheme)//' Northward MF')
    2712             :   call addfld (trim(prefix)//'SMF',       (/ 'lev' /), 'A','Pa', &
    2713           0 :        trim(scheme)//' Southward MF')
    2714             : 
    2715             :   ! Temperature tendency terms.
    2716             :   call addfld (trim(prefix)//'TTGWSDF' , (/ 'lev' /), 'A','K s-1', &
    2717           0 :        trim(scheme)//' t tendency - diffusion term')
    2718             :   call addfld (trim(prefix)//'TTGWSKE' , (/ 'lev' /), 'A','K s-1', &
    2719           0 :        trim(scheme)//' t tendency - kinetic energy conversion term')
    2720             : 
    2721             :   ! Gravity wave source spectra by wave number.
    2722           0 :   do l=-band%ngwv,band%ngwv
    2723             :      ! String containing reference speed.
    2724           0 :      write (fnum,fmt='(f7.2)') band%cref(l)
    2725             : 
    2726           0 :      dumc1x = tau_fld_name(l, prefix, x_not_y=.true.)
    2727           0 :      dumc1y = tau_fld_name(l, prefix, x_not_y=.false.)
    2728           0 :      dumc2 = trim(scheme)//" tau at c= "//trim(fnum)//" m s-1"
    2729           0 :      call addfld (trim(dumc1x),(/ 'lev' /), 'A','Pa',dumc2)
    2730           0 :      call addfld (trim(dumc1y),(/ 'lev' /), 'A','Pa',dumc2)
    2731             : 
    2732             :   end do
    2733             : 
    2734           0 :   if (history_defaults) then
    2735           0 :      call add_default(trim(prefix)//'UTGWSPEC', 1, ' ')
    2736           0 :      call add_default(trim(prefix)//'VTGWSPEC', 1, ' ')
    2737           0 :      call add_default(trim(prefix)//'TTGWSPEC', 1, ' ')
    2738           0 :      call add_default(trim(prefix)//'TAUE', 1, ' ')
    2739           0 :      call add_default(trim(prefix)//'TAUW', 1, ' ')
    2740           0 :      call add_default(trim(prefix)//'TAUNET', 1, ' ')
    2741           0 :      call add_default(trim(prefix)//'TAUN', 1, ' ')
    2742           0 :      call add_default(trim(prefix)//'TAUS', 1, ' ')
    2743             :   end if
    2744             : 
    2745           0 : end subroutine gw_spec_addflds
    2746             : 
    2747             : !==========================================================================
    2748             : 
    2749             : ! Outputs for spectral waves.
    2750           0 : subroutine gw_spec_outflds(prefix, lchnk, ncol, band, phase_speeds, u, v, xv, yv, &
    2751           0 :      gwut, dttdf, dttke, tau, utgw, vtgw, ttgw, taucd)
    2752             : 
    2753           0 :   use gw_common, only: west, east, south, north
    2754             : 
    2755             :   ! One-character prefix prepended to output fields.
    2756             :   character(len=1), intent(in) :: prefix
    2757             :   ! Chunk and number of columns in the chunk.
    2758             :   integer, intent(in) :: lchnk
    2759             :   integer, intent(in) :: ncol
    2760             :   ! Wave speeds.
    2761             :   type(GWBand), intent(in) :: band
    2762             :   ! Wave phase speeds for each column.
    2763             :   real(r8), intent(in) :: phase_speeds(ncol,-band%ngwv:band%ngwv)
    2764             :   ! Winds at cell midpoints.
    2765             :   real(r8), intent(in) :: u(ncol,pver)
    2766             :   real(r8), intent(in) :: v(ncol,pver)
    2767             :   ! Unit vector in the direction of wind at source level.
    2768             :   real(r8), intent(in) :: xv(ncol)
    2769             :   real(r8), intent(in) :: yv(ncol)
    2770             :   ! Wind tendency for each wave.
    2771             :   real(r8), intent(in) :: gwut(ncol,pver,-band%ngwv:band%ngwv)
    2772             :   ! Temperature tendencies from diffusion and kinetic energy.
    2773             :   real(r8) :: dttdf(ncol,pver)
    2774             :   real(r8) :: dttke(ncol,pver)
    2775             :   ! Wave Reynolds stress.
    2776             :   real(r8), intent(in) :: tau(ncol,-band%ngwv:band%ngwv,pver)
    2777             :   ! Zonal and meridional total wind tendencies.
    2778             :   real(r8), intent(in) :: utgw(ncol,pver)
    2779             :   real(r8), intent(in) :: vtgw(ncol,pver)
    2780             :   ! Temperature tendencies.
    2781             :   real(r8), intent(in) :: ttgw(ncol,pver)
    2782             :   ! Reynolds stress for waves propagating in each cardinal direction.
    2783             :   real(r8), intent(in) :: taucd(ncol,pver+1,4)
    2784             : 
    2785             :   ! Indices
    2786             :   integer :: i, k, l
    2787           0 :   integer :: ix(ncol, -band%ngwv:band%ngwv), iy(ncol, -band%ngwv:band%ngwv)
    2788           0 :   integer :: iu(ncol), iv(ncol)
    2789             : 
    2790             :   ! Zonal wind tendency, broken up into five bins.
    2791           0 :   real(r8) :: utb(ncol, pver, 5)
    2792             :   ! Definition of the bin boundaries.
    2793             :   real(r8), parameter :: bounds(4) = (/ -40._r8, -15._r8, &
    2794             :        15._r8, 40._r8 /)
    2795             : 
    2796             :   ! Momentum flux in the four cardinal directions.
    2797           0 :   real(r8) :: mf(ncol, pver, 4)
    2798             : 
    2799             :   ! Wave stress in zonal/meridional direction
    2800           0 :   real(r8) :: taux(ncol,-band%ngwv:band%ngwv,pver)
    2801           0 :   real(r8) :: tauy(ncol,-band%ngwv:band%ngwv,pver)
    2802             : 
    2803             :   ! Temporaries for output
    2804           0 :   real(r8) :: dummyx(ncol,pver)
    2805           0 :   real(r8) :: dummyy(ncol,pver)
    2806             :   ! Variable names
    2807             :   character(len=10) :: dumc1x, dumc1y
    2808             : 
    2809             : 
    2810             :   ! Accumulate wind tendencies binned according to phase speed.
    2811             : 
    2812           0 :   utb = 0._r8
    2813             : 
    2814             :   ! Find which output bin the phase speed corresponds to.
    2815           0 :   ix = find_bin(phase_speeds)
    2816             : 
    2817             :   ! Put the wind tendency in that bin.
    2818           0 :   do l = -band%ngwv, band%ngwv
    2819           0 :      do k = 1, pver
    2820           0 :         do i = 1, ncol
    2821           0 :            utb(i,k,ix(i,l)) = utb(i,k,ix(i,l)) + gwut(i,k,l)
    2822             :         end do
    2823             :      end do
    2824             :   end do
    2825             : 
    2826             :   ! Find just the zonal part.
    2827           0 :   do l = 1, 5
    2828           0 :      do k = 1, pver
    2829           0 :         utb(:, k, l) = utb(:, k, l) * xv
    2830             :      end do
    2831             :   end do
    2832             : 
    2833           0 :   call outfld(trim(prefix)//'UTEND1', utb(:,:,1), ncol, lchnk)
    2834           0 :   call outfld(trim(prefix)//'UTEND2', utb(:,:,2), ncol, lchnk)
    2835           0 :   call outfld(trim(prefix)//'UTEND3', utb(:,:,3), ncol, lchnk)
    2836           0 :   call outfld(trim(prefix)//'UTEND4', utb(:,:,4), ncol, lchnk)
    2837           0 :   call outfld(trim(prefix)//'UTEND5', utb(:,:,5), ncol, lchnk)
    2838             : 
    2839             :   ! Output temperature tendencies due to diffusion and from kinetic energy.
    2840           0 :   call outfld(trim(prefix)//'TTGWSDF', dttdf / cpair, ncol, lchnk)
    2841           0 :   call outfld(trim(prefix)//'TTGWSKE', dttke / cpair, ncol, lchnk)
    2842             : 
    2843             : 
    2844             :   ! Output tau broken down into zonal and meridional components.
    2845             : 
    2846           0 :   taux = 0._r8
    2847           0 :   tauy = 0._r8
    2848             : 
    2849             :   ! Project phase_speeds, and convert each component to a wavenumber index.
    2850             :   ! These are mappings from the wavenumber index of tau to those of taux
    2851             :   ! and tauy, respectively.
    2852           0 :   do l=-band%ngwv,band%ngwv
    2853           0 :      ix(:,l) = c_to_l(phase_speeds(:,l)*xv)
    2854           0 :      iy(:,l) = c_to_l(phase_speeds(:,l)*yv)
    2855             :   end do
    2856             : 
    2857             :   ! Find projection of tau.
    2858           0 :   do k = 1, pver
    2859           0 :      do l = -band%ngwv,band%ngwv
    2860           0 :         do i = 1, ncol
    2861           0 :            taux(i,ix(i,l),k) = taux(i,ix(i,l),k) &
    2862           0 :                 + abs(tau(i,l,k)*xv(i))
    2863           0 :            tauy(i,iy(i,l),k) = tauy(i,iy(i,l),k) &
    2864           0 :                 + abs(tau(i,l,k)*yv(i))
    2865             :         end do
    2866             :      end do
    2867             :   end do
    2868             : 
    2869           0 :   do l=-band%ngwv,band%ngwv
    2870             : 
    2871           0 :      dummyx = taux(:,l,:)
    2872           0 :      dummyy = tauy(:,l,:)
    2873             : 
    2874           0 :      dumc1x = tau_fld_name(l, prefix, x_not_y=.true.)
    2875           0 :      dumc1y = tau_fld_name(l, prefix, x_not_y=.false.)
    2876             : 
    2877           0 :      call outfld(dumc1x,dummyx,ncol,lchnk)
    2878           0 :      call outfld(dumc1y,dummyy,ncol,lchnk)
    2879             : 
    2880             :   enddo
    2881             : 
    2882             : 
    2883             :   ! Output momentum flux in each cardinal direction.
    2884           0 :   mf = 0._r8
    2885             : 
    2886           0 :   do k = 1, pver
    2887             : 
    2888             :      ! Convert wind speed components to wavenumber indices.
    2889           0 :      iu = c_to_l(u(:,k))
    2890           0 :      iv = c_to_l(v(:,k))
    2891             : 
    2892             :      ! Sum tau components in each cardinal direction.
    2893             :      ! Split west/east and north/south based on whether wave speed exceeds
    2894             :      ! wind speed.
    2895           0 :      do l = -band%ngwv, band%ngwv
    2896             : 
    2897           0 :         where (iu > l)
    2898           0 :            mf(:,k,west) = mf(:,k,west) + taux(:,l,k)
    2899             :         elsewhere
    2900           0 :            mf(:,k,east) = mf(:,k,east) + taux(:,l,k)
    2901             :         end where
    2902             : 
    2903           0 :         where (iv > l)
    2904           0 :            mf(:,k,south) = mf(:,k,south) + tauy(:,l,k)
    2905             :         elsewhere
    2906           0 :            mf(:,k,north) = mf(:,k,north) + tauy(:,l,k)
    2907             :         end where
    2908             : 
    2909             :      end do
    2910             : 
    2911             :   end do
    2912             : 
    2913           0 :   call outfld(trim(prefix)//'WMF',mf(:,:,west),ncol,lchnk)
    2914           0 :   call outfld(trim(prefix)//'EMF',mf(:,:,east),ncol,lchnk)
    2915           0 :   call outfld(trim(prefix)//'SMF',mf(:,:,south),ncol,lchnk)
    2916           0 :   call outfld(trim(prefix)//'NMF',mf(:,:,north),ncol,lchnk)
    2917             : 
    2918             :   ! Simple output fields written to history file.
    2919             :   ! Total wind tendencies.
    2920           0 :   call outfld (trim(prefix)//'UTGWSPEC', utgw , ncol, lchnk)
    2921           0 :   call outfld (trim(prefix)//'VTGWSPEC', vtgw , ncol, lchnk)
    2922           0 :   call outfld (trim(prefix)//'TTGWSPEC', ttgw , ncol, lchnk)
    2923             : 
    2924             :   ! Tau in each direction.
    2925           0 :   call outfld (trim(prefix)//'TAUE', taucd(:,:,east), ncol, lchnk)
    2926           0 :   call outfld (trim(prefix)//'TAUW', taucd(:,:,west), ncol, lchnk)
    2927           0 :   call outfld (trim(prefix)//'TAUN', taucd(:,:,north), ncol, lchnk)
    2928           0 :   call outfld (trim(prefix)//'TAUS', taucd(:,:,south), ncol, lchnk)
    2929             : 
    2930             :   call outfld (trim(prefix)//'TAUNET', taucd(:,:,east)+taucd(:,:,west), &
    2931           0 :        ncol, lchnk)
    2932             : 
    2933             : contains
    2934             : 
    2935             :   ! Given a value, finds which bin marked by "bounds" the value falls
    2936             :   ! into.
    2937           0 :   elemental function find_bin(val) result(idx)
    2938             :     real(r8), intent(in) :: val
    2939             : 
    2940             :     integer :: idx
    2941             : 
    2942             :     ! We just have to count how many bounds are exceeded.
    2943           0 :     if (val >= 0._r8) then
    2944           0 :        idx = count(val > bounds) + 1
    2945             :     else
    2946           0 :        idx = count(val >= bounds) + 1
    2947             :     end if
    2948             : 
    2949           0 :   end function find_bin
    2950             : 
    2951             :   ! Convert a speed to a wavenumber between -ngwv and ngwv.
    2952           0 :   elemental function c_to_l(c) result(l)
    2953             :     real(r8), intent(in) :: c
    2954             : 
    2955             :     integer :: l
    2956             : 
    2957           0 :     l = min( max(int(c/band%dc),-band%ngwv), band%ngwv )
    2958             : 
    2959           0 :   end function c_to_l
    2960             : 
    2961             : end subroutine gw_spec_outflds
    2962             : 
    2963             : !==========================================================================
    2964             : 
    2965             : ! Generates names for tau output across the wave spectrum (e.g.
    2966             : ! BTAUXSn01 or TAUYSp05).
    2967             : ! Probably this should use a wavenumber dimension on one field rather
    2968             : ! than creating a ton of numbered fields.
    2969           0 : character(len=9) pure function tau_fld_name(l, prefix, x_not_y)
    2970             :   ! Wavenumber
    2971             :   integer, intent(in) :: l
    2972             :   ! Single-character prefix for output
    2973             :   character(len=1), intent(in) :: prefix
    2974             :   ! X or Y?
    2975             :   logical, intent(in) :: x_not_y
    2976             : 
    2977             :   character(len=2) :: num_str
    2978             : 
    2979           0 :   tau_fld_name = trim(prefix)
    2980             : 
    2981           0 :   tau_fld_name = trim(tau_fld_name)//"TAU"
    2982             : 
    2983           0 :   if (x_not_y) then
    2984           0 :      tau_fld_name = trim(tau_fld_name)//"XS"
    2985             :   else
    2986           0 :      tau_fld_name = trim(tau_fld_name)//"YS"
    2987             :   end if
    2988             : 
    2989           0 :   if (l < 0) then
    2990           0 :      tau_fld_name = trim(tau_fld_name)//"n"
    2991             :   else
    2992           0 :      tau_fld_name = trim(tau_fld_name)//"p"
    2993             :   end if
    2994             : 
    2995           0 :   write(num_str,'(I2.2)') abs(l)
    2996             : 
    2997           0 :   tau_fld_name = trim(tau_fld_name)//num_str
    2998             : 
    2999           0 : end function tau_fld_name
    3000             : 
    3001             : !==========================================================================
    3002             : 
    3003             : end module gw_drag

Generated by: LCOV version 1.14