LCOV - code coverage report
Current view: | top level - physics/cam - gw_diffusion.F90 (source / functions) |  |  | Hit | Total | Coverage
Test: | coverage.info |  | Lines: | 27 | 31 | 87.1 %
Date: | 2025-01-13 21:54:50 |  | Functions: | 2 | 2 | 100.0 %

              Line data    Source code
           1             : module gw_diffusion
           2             :
           3             : !
           4             : ! This module contains code computing the effective diffusion of
           5             : ! constituents and dry static energy due to gravity wave breaking.
           6             : !
           7             :
           8             : use gw_utils, only: r8
           9             : use linear_1d_operators, only: TriDiagDecomp
          10             :
          11             : implicit none
          12             : private
          13             : save
          14             :
          15             : public :: gw_ediff
          16             : public :: gw_diff_tend
          17             :
          18             : contains
          19             :
          20             : !==========================================================================
          21             :
          22     1489176 : subroutine gw_ediff(ncol, pver, ngwv, kbot, ktop, tend_level, &
          23     2978352 :      gwut, ubm, nm, rho, dt, prndl, gravit, p, c, vramp, &
          24           0 :      egwdffi, decomp, ro_adjust)
          25             : !
          26             : ! Calculate effective diffusivity associated with GW forcing.
          27             : !
          28             : ! Author: F. Sassi, Jan 31, 2001
          29             : !
          30             :   use gw_utils, only: midpoint_interp
          31             :   use coords_1d, only: Coords1D
          32             :   use vdiff_lu_solver, only: fin_vol_lu_decomp
          33             :
          34             : !-------------------------------Input Arguments----------------------------
          35             :
          36             :   ! Column, level, and gravity wave spectrum dimensions.
          37             :   integer, intent(in) :: ncol, pver, ngwv
          38             :   ! Bottom and top levels to operate on.
          39             :   integer, intent(in) :: kbot, ktop
          40             :   ! Per-column bottom index where tendencies are applied.
          41             :   integer, intent(in) :: tend_level(ncol)
          42             :   ! GW zonal wind tendencies at midpoint.
          43             :   real(r8), intent(in) :: gwut(ncol,pver,-ngwv:ngwv)
          44             :   ! Projection of wind at midpoints.
          45             :   real(r8), intent(in) :: ubm(ncol,pver)
          46             :   ! Brunt-Vaisalla frequency.
          47             :   real(r8), intent(in) :: nm(ncol,pver)
          48             :
          49             :   ! Density at interfaces.
          50             :   real(r8), intent(in) :: rho(ncol,pver+1)
          51             :   ! Time step.
          52             :   real(r8), intent(in) :: dt
          53             :   ! Inverse Prandtl number.
          54             :   real(r8), intent(in) :: prndl
          55             :   ! Acceleration due to gravity.
          56             :   real(r8), intent(in) :: gravit
          57             :   ! Pressure coordinates.
          58             :   type(Coords1D), intent(in) :: p
          59             :   ! Wave phase speeds for each column.
          60             :   real(r8), intent(in) :: c(ncol,-ngwv:ngwv)
          61             :
          62             :   ! Coefficient to ramp down diffusion coeff.
          63             :   real(r8), pointer, intent(in) :: vramp(:)
          64             :
          65             :   ! Adjustment parameter for IGWs.
          66             :   real(r8), intent(in), optional :: &
          67             :        ro_adjust(ncol,-ngwv:ngwv,pver+1)
          68             :
          69             : !-----------------------------Output Arguments-----------------------------
          70             :   ! Effective gw diffusivity at interfaces.
          71             :   real(r8), intent(out) :: egwdffi(ncol,pver+1)
          72             :   ! LU decomposition.
          73             :   type(TriDiagDecomp), intent(out) :: decomp
          74             :
          75             : !-----------------------------Local Workspace------------------------------
          76             :
          77             :   ! Effective gw diffusivity at midpoints.
          78     2978352 :   real(r8) :: egwdffm(ncol,pver)
          79             :   ! Temporary used to hold gw_diffusivity for one level and wavenumber.
          80     2978352 :   real(r8) :: egwdff_lev(ncol)
          81             :   ! (dp/dz)^2 == (gravit*rho)^2
          82     1489176 :   real(r8) :: dpidz_sq(ncol,pver+1)
          83             :   ! Level and wave indices.
          84             :   integer :: k, l
          85             :
          86             :   ! Density scale height.
          87             :   real(r8), parameter :: dscale=7000._r8
          88             :
          89             : !--------------------------------------------------------------------------
          90             :
          91   672865128 :   egwdffi = 0._r8
          92   647999352 :   egwdffm = 0._r8
          93             :
          94             :   ! Calculate effective diffusivity at midpoints.
          95     2978352 :   do l = -ngwv, ngwv
          96    41696928 :      do k = ktop, kbot
          97             :
          98             :         egwdff_lev = &
          99   646510176 :              prndl * 0.5_r8 * gwut(:,k,l) * (c(:,l)-ubm(:,k)) / nm(:,k)**2
         100             :
         101             :         ! IGWs need ro_adjust factor.
         102    38718576 :         if (present(ro_adjust)) then
         103           0 :            egwdff_lev = egwdff_lev * ro_adjust(:,l,k)**2
         104             :         end if
         105             :
         106   647999352 :         egwdffm(:,k) = egwdffm(:,k) + egwdff_lev
         107             :
         108             :      end do
         109             :   end do
         110             :
         111     1489176 :   if (associated(vramp)) then
         112           0 :      do k = ktop,kbot
         113           0 :         egwdffm(:,k) = egwdffm(:,k) * vramp(k)
         114             :      end do
         115             :   endif
         116             :
         117             :   ! Interpolate effective diffusivity to interfaces.
         118             :   ! Assume zero at top and bottom interfaces.
         119     1489176 :   egwdffi(:,ktop+1:kbot) = midpoint_interp(egwdffm(:,ktop:kbot))
         120             :
         121             :   ! Do not calculate diffusivities below level where tendencies are
         122             :   ! actually allowed.
         123    38718576 :   do k = ktop+1, kbot
         124   623133576 :      where (k > tend_level) egwdffi(:,k) = 0.0_r8
         125             :   enddo
         126             :
         127             :   ! Calculate (dp/dz)^2.
         128   672865128 :   dpidz_sq = rho*gravit
         129   672865128 :   dpidz_sq = dpidz_sq*dpidz_sq
         130             :
         131             :   ! Decompose the diffusion matrix.
         132             :   decomp = fin_vol_lu_decomp(dt, p%section([1,ncol],[ktop,kbot]), &
         133   678821832 :        coef_q_diff=egwdffi(:,ktop:kbot+1)*dpidz_sq(:,ktop:kbot+1))
         134             :
         135     1489176 : end subroutine gw_ediff
         136             :
         137             : !==========================================================================
         138             :
         139     5956704 : subroutine gw_diff_tend(ncol, pver, kbot, ktop, q, dt, decomp, dq)
         140             :
         141             : !
         142             : ! Calculates tendencies from effective diffusion due to gravity wave
         143             : ! breaking.
         144             : !
         145             : ! Method:
         146             : ! A constituent flux on interfaces is given by:
         147             : !
         148             : !              rho * (w'q') = rho * Deff qz
         149             : !
         150             : ! where (all evaluated on interfaces):
         151             : !
         152             : !        rho   = density
         153             : !        qz    = constituent vertical gradient
         154             : !        Deff  = effective diffusivity
         155             : !
         156             : ! An effective diffusivity is calculated by adding up the diffusivities
         157             : ! from all waves (see gw_ediff). The tendency is calculated by invoking LU
         158             : ! decomposition and solving as for a regular diffusion equation.
         159             : !
         160             : ! Author: Sassi - Jan 2001
         161             : !--------------------------------------------------------------------------
         162             :
         163             : !---------------------------Input Arguments--------------------------------
         164             :
         165             :   ! Column and level dimensions.
         166             :   integer, intent(in) :: ncol, pver
         167             :   ! Bottom and top levels to operate on.
         168             :   integer, intent(in) :: kbot, ktop
         169             :
         170             :   ! Constituent to diffuse.
         171             :   real(r8), intent(in) :: q(ncol,pver)
         172             :   ! Time step.
         173             :   real(r8), intent(in) :: dt
         174             :
         175             :   ! LU decomposition.
         176             :   type(TriDiagDecomp), intent(in) :: decomp
         177             :
         178             : !--------------------------Output Arguments--------------------------------
         179             :
         180             :   ! Constituent tendencies.
         181             :   real(r8), intent(out) :: dq(ncol,pver)
         182             :
         183             : !--------------------------Local Workspace---------------------------------
         184             :
         185             :   ! Temporary storage for constituent.
         186     5956704 :   real(r8) :: qnew(ncol,pver)
         187             :
         188             : !--------------------------------------------------------------------------
         189             :
         190  2591997408 :   dq   = 0.0_r8
         191  2591997408 :   qnew = q
         192             :
         193     5956704 :   call decomp%left_div(qnew(:,ktop:kbot))
         194             :
         195             :   ! Evaluate tendency to be reported back.
         196  2591997408 :   dq = (qnew-q) / dt
         197             :
         198     5956704 : end subroutine gw_diff_tend
         199             :
         200             : end module gw_diffusion

Generated by: LCOV version 1.14