LCOV - code coverage report
Current view: | top level - physics/clubb/src/CLUBB_core - sponge_layer_damping.F90 (source / functions) |  |  | Hit | Total | Coverage
Test: | coverage.info |  | Lines: | 0 | 51 | 0.0 %
Date: | 2024-12-17 22:39:59 |  | Functions: | 0 | 8 | 0.0 %

              Line data    Source code
           1             : !---------------------------------------------------------------------------
           2             : ! $Id$
           3             : !===============================================================================
           4             : module sponge_layer_damping
           5             :
           6             :   ! Description:
           7             :   ! This module is used for damping variables in upper altitudes of the grid.
           8             :   !
           9             :   ! References:
          10             :   !   None
          11             :   !-------------------------------------------------------------------------
          12             :
          13             :   use clubb_precision, only: &
          14             :       core_rknd ! Variable(s)
          15             :
          16             :   implicit none
          17             :
          18             :   public :: sponge_damp_xm,             & ! Procedure(s)
          19             :             sponge_damp_xp2,            &
          20             :             sponge_damp_xp3,            &
          21             :             initialize_tau_sponge_damp, &
          22             :             finalize_tau_sponge_damp,   &
          23             :             sponge_damp_settings,       & ! Variable type(s)
          24             :             sponge_damp_profile
          25             :
          26             :
          27             :   type sponge_damp_settings
          28             :
          29             :     real( kind = core_rknd ) :: &
          30             :       tau_sponge_damp_min, & ! Minimum damping time scale (model top)        [s]
          31             :       tau_sponge_damp_max, & ! Maximum damping time scale (damp layer base)  [s]
          32             :       sponge_damp_depth      ! Damping depth as a fraction of domain height  [-]
          33             :
          34             :     logical :: &
          35             :       l_sponge_damping = .false.       ! True if damping is being used, default false
          36             :
          37             :   end type sponge_damp_settings
          38             :
          39             :   type sponge_damp_profile
          40             :
          41             :     real( kind = core_rknd ), allocatable, dimension(:) :: &
          42             :       tau_sponge_damp    ! Damping time scale    [1/s]
          43             :
          44             :     real( kind = core_rknd ) :: &
          45             :       sponge_layer_depth    ! Depth of sponge damping layer  [m]
          46             :
          47             :   end type sponge_damp_profile
          48             :
          49             :
          50             :   type(sponge_damp_settings), public :: &
          51             :     thlm_sponge_damp_settings,    & ! Variable(s)
          52             :     rtm_sponge_damp_settings,     &
          53             :     uv_sponge_damp_settings,      &
          54             :     wp2_sponge_damp_settings,     &
          55             :     wp3_sponge_damp_settings,     &
          56             :     up2_vp2_sponge_damp_settings
          57             :
          58             :   type(sponge_damp_profile), public :: &
          59             :     thlm_sponge_damp_profile,    & ! Variable(s)
          60             :     rtm_sponge_damp_profile,     &
          61             :     uv_sponge_damp_profile,      &
          62             :     wp2_sponge_damp_profile,     &
          63             :     wp3_sponge_damp_profile,     &
          64             :     up2_vp2_sponge_damp_profile
          65             :
          66             :
          67             :   private
          68             :
          69             :   contains
          70             :
          71             :   !=============================================================================
          72           0 :   function sponge_damp_xm( nz, dt, z, zm, &
          73           0 :                            xm_ref, xm, damping_profile ) result( xm_p )
          74             :
          75             :     ! Description:
          76             :     ! Damps specified mean field toward a reference profile.  The module must be
          77             :     ! initialized for this function to work.  Otherwise a stop is issued.
          78             :
          79             :     ! References:
          80             :     ! None
          81             :     !-----------------------------------------------------------------------
          82             :
          83             :     !  "Sponge"-layer damping at the domain top region
          84             :
          85             :     use clubb_precision, only: &
          86             :         core_rknd    ! Variable(s)
          87             :
          88             :     implicit none
          89             :
          90             :     integer, intent(in) :: &
          91             :       nz
          92             :
          93             :     ! External
          94             :     intrinsic :: allocated
          95             :
          96             :     ! Input Variable(s)
          97             :     real( kind = core_rknd ), intent(in) :: &
          98             :       dt    ! Model Timestep  [s]
          99             :
         100             :     real( kind = core_rknd ), dimension(nz), intent(in) :: &
         101             :       z,      & ! Height of model grid levels                [m]
         102             :       xm_ref, & ! Reference profile of x to damp xm towards  [units vary]
         103             :       xm,     & ! Mean field being damped                    [units vary]
         104             :       zm        ! Momentum grid
         105             :
         106             :     type(sponge_damp_profile), intent(in) :: &
         107             :       damping_profile
         108             :
         109             :     ! Output Variable
         110             :     real( kind = core_rknd ), dimension(nz) :: &
         111             :       xm_p   ! Damped value of xm  [units_vary]
         112             :
         113             :     ! Local Variable(s)
         114             :     real( kind = core_rknd ) :: &
         115             :       dt_on_tau    ! Ratio of timestep to damping timescale  [-]
         116             :
         117             :     integer :: k
         118             :
         119             :     ! ---- Begin Code ----
         120             :
         121           0 :     if ( allocated( damping_profile%tau_sponge_damp ) ) then
         122             :
         123           0 :        xm_p = xm
         124             :
         125           0 :        do k = nz, 1, -1
         126             :
         127             :           ! The height of the model top is zm(nz).
         128           0 :           if ( zm(nz) - z(k) < damping_profile%sponge_layer_depth ) then
         129             :
         130             :              ! Vince Larson used implicit discretization in order to
         131             :              ! reduce noise in rtm in cloud_feedback_s12 (CGILS)
         132             :              !xm_p(k) = xm(k) - real( ( ( xm(k) - xm_ref(k) ) / &
         133             :              !                  damping_profile%tau_sponge_damp(k) ) * dt )
         134           0 :              dt_on_tau = dt / damping_profile%tau_sponge_damp(k)
         135             :
         136             :              ! Really, we should be using xm_ref at time n+1 rather than n.
         137             :              ! However, for steady profiles of xm_ref, it won't matter.
         138             :              xm_p(k) = ( xm(k) + dt_on_tau * xm_ref(k) ) / &
         139           0 :                              ( 1.0_core_rknd + dt_on_tau )
         140             :              ! End Vince Larson's change
         141             :
         142             :           else ! zm(nz) - z(k) >= damping_profile%sponge_layer_depth
         143             :
         144             :              ! Below sponge damping layer; exit loop.
         145             :              exit
         146             :
         147             :           endif ! zm(nz) - z(k) < damping_profile%sponge_layer_depth
         148             :
         149             :
         150             :        enddo ! k = nz, 1, -1
         151             :
         152             :     else
         153             :
         154           0 :        error stop "tau_sponge_damp in sponge_damp_xm used before initialization"
         155             :
         156             :     endif
         157             :
         158             :
         159           0 :     return
         160             :
         161           0 :   end function sponge_damp_xm
         162             :
         163             :   !=============================================================================
         164           0 :   function sponge_damp_xp2( nz, dt, zm, xp2, x_tol_sqd, &
         165             :                             damping_profile ) &
         166           0 :   result( xp2_damped )
         167             :
         168             :     ! Description:
         169             :     ! Calculates the effects of "sponge"-layer damping on the variance of x,
         170             :     ! xp2.
         171             :     !
         172             :     ! Sponge damping on a local value of x is given by the equation:
         173             :     !
         174             :     ! x_d = x - ( delta_t / tau ) * ( x - <x> ),
         175             :     !
         176             :     ! where x is the local value prior to damping, x_d is the damped local value
         177             :     ! of x, <x> is the grid-level mean value of x, delta_t is the model time
         178             :     ! step duration, and tau is the damping time scale.  Since delta_t / tau has
         179             :     ! the same value everywhere at a grid level, the grid-level mean of x does
         180             :     ! not change as a result of damping.
         181             :     !
         182             :     ! Subtracting <x> from both sides:
         183             :     !
         184             :     ! x_d - <x> = ( x - <x> ) - ( delta_t / tau ) * ( x - <x> ),
         185             :     !
         186             :     ! which results in:
         187             :     !
         188             :     ! x_d - <x> = ( 1 - delta_t / tau ) * ( x - <x> ).
         189             :     !
         190             :     ! Squaring both sides:
         191             :     !
         192             :     ! ( x_d - <x> )^2 = ( 1 - delta_t / tau )^2 * ( x - <x> )^2.
         193             :     !
         194             :     ! After averaging both sides, the damped value of xp2 is:
         195             :     !
         196             :     ! < x_d'^2 > = ( 1 - delta_t / tau )^2 * < x'^2 >.
         197             :     !
         198             :     ! Any sponge damping is applied to (predictive) xp2 after the field has been
         199             :     ! advanced in time.  This allows sponge damping to be applied in an implicit
         200             :     ! manner.  The damped value of xp2 must also be limited at a minimum value
         201             :     ! of x_tol^2.
         202             :
         203             :     ! References:
         204             :     !-----------------------------------------------------------------------
         205             :
         206             :     use constants_clubb, only: &
         207             :         one    ! Constant(s)
         208             :
         209             :     use clubb_precision, only: &
         210             :         core_rknd    ! Variable(s)
         211             :
         212             :     implicit none
         213             :
         214             :     integer, intent(in) :: &
         215             :       nz
         216             :
         217             :     ! Input Variable(s)
         218             :     real( kind = core_rknd ), intent(in) :: &
         219             :       dt    ! Model Timestep  [s]
         220             :
         221             :     real( kind = core_rknd ), dimension(nz), intent(in) :: &
         222             :       zm,  & ! Height of model grid levels               [m]
         223             :       xp2    ! Variance of x, <x'^2>, prior to damping   [units vary]
         224             :
         225             :     real( kind = core_rknd ), intent(in) :: &
         226             :       x_tol_sqd    ! Square of the tolerance value of x    [units vary]
         227             :
         228             :     type(sponge_damp_profile), intent(in) :: &
         229             :       damping_profile
         230             :
         231             :     ! Output Variable
         232             :     real( kind = core_rknd ), dimension(nz) :: &
         233             :       xp2_damped    ! Variance of x, <x'^2>, after damping   [units vary]
         234             :
         235             :     ! Local Variable(s)
         236             :     real( kind = core_rknd ) :: &
         237             :       dt_on_tau    ! Ratio of model time step duration to damping timescale  [-]
         238             :
         239             :     integer :: &
         240             :       k    ! Loop index
         241             :
         242             :
         243           0 :     if ( allocated( damping_profile%tau_sponge_damp ) ) then
         244             :
         245             :        ! Set the entire profile of <x'^2> after damping to the profile of <x'^2>
         246             :        ! before damping.  The values of <x'^2> after damping will be overwritten
         247             :        ! at any levels where "sponge"-layer damping occurs.
         248           0 :        xp2_damped = xp2
         249             :
         250           0 :        do k = nz, 1, -1
         251             :
         252             :           ! The height of the model top is zm(nz).
         253           0 :           if ( zm(nz) - zm(k) < damping_profile%sponge_layer_depth ) then
         254             :
         255             :              ! Calculate the value of delta_t / tau at the grid level.
         256           0 :              dt_on_tau = dt / damping_profile%tau_sponge_damp(k)
         257             :
         258             :              ! Calculate the damped value of <x'^2>.
         259           0 :              xp2_damped(k) = ( one - dt_on_tau )**2 * xp2(k)
         260             :
         261             :              ! The damped value of <x'^2> needs to be greater than or equal to
         262             :              ! x_tol^2.
         263           0 :              xp2_damped(k) = max( xp2_damped(k), x_tol_sqd )
         264             :
         265             :           else ! zm(nz) - zm(k) >= damping_profile%sponge_layer_depth
         266             :
         267             :              ! Below sponge damping layer; exit loop.
         268             :              exit
         269             :
         270             :           endif ! zm(nz) - zm(k) < damping_profile%sponge_layer_depth
         271             :
         272             :
         273             :        enddo ! k = nz, 1, -1
         274             :
         275             :     else
         276             :
         277           0 :        error stop "tau_sponge_damp in sponge_damp_xp2 used before initialization"
         278             :
         279             :     endif
         280             :
         281             :
         282           0 :     return
         283             :
         284           0 :   end function sponge_damp_xp2
         285             :
         286             :   !=============================================================================
         287           0 :   function sponge_damp_xp3( nz, dt, z, zm, xp3, &
         288             :                             damping_profile ) &
         289           0 :   result( xp3_damped )
         290             :
         291             :     ! Description:
         292             :     ! Calculates the effects of "sponge"-layer damping on xp3.
         293             :     !
         294             :     ! Sponge damping on a local value of x is given by the equation:
         295             :     !
         296             :     ! x_d = x - ( delta_t / tau ) * ( x - <x> ),
         297             :     !
         298             :     ! where x is the local value prior to damping, x_d is the damped local value
         299             :     ! of x, <x> is the grid-level mean value of x, delta_t is the model time
         300             :     ! step duration, and tau is the damping time scale.  Since delta_t / tau has
         301             :     ! the same value everywhere at a grid level, the grid-level mean of x does
         302             :     ! not change as a result of damping.
         303             :     !
         304             :     ! Subtracting <x> from both sides:
         305             :     !
         306             :     ! x_d - <x> = ( x - <x> ) - ( delta_t / tau ) * ( x - <x> ),
         307             :     !
         308             :     ! which results in:
         309             :     !
         310             :     ! x_d - <x> = ( 1 - delta_t / tau ) * ( x - <x> ).
         311             :     !
         312             :     ! Taking both sides to the third power:
         313             :     !
         314             :     ! ( x_d - <x> )^3 = ( 1 - delta_t / tau )^3 * ( x - <x> )^3.
         315             :     !
         316             :     ! After averaging both sides, the damped value of xp3 is:
         317             :     !
         318             :     ! < x_d'^3 > = ( 1 - delta_t / tau )^3 * < x'^3 >.
         319             :     !
         320             :     ! Any sponge damping is applied to (predictive) xp3 after the field has been
         321             :     ! advanced in time.  This allows sponge damping to be applied in an implicit
         322             :     ! manner.
         323             :
         324             :     ! References:
         325             :     !-----------------------------------------------------------------------
         326             :
         327             :     use constants_clubb, only: &
         328             :         one    ! Constant(s)
         329             :
         330             :     use clubb_precision, only: &
         331             :         core_rknd    ! Variable(s)
         332             :
         333             :     implicit none
         334             :
         335             :     integer, intent(in) :: &
         336             :       nz
         337             :
         338             :     ! Input Variable(s)
         339             :     real( kind = core_rknd ), intent(in) :: &
         340             :       dt    ! Model Timestep  [s]
         341             :
         342             :     real( kind = core_rknd ), dimension(nz), intent(in) :: &
         343             :       z,   & ! Height of model grid levels     [m]
         344             :       xp3, & ! <x'^3> prior to damping         [units vary]
         345             :       zm     ! Momentum grid
         346             :
         347             :     type(sponge_damp_profile), intent(in) :: &
         348             :       damping_profile
         349             :
         350             :     ! Output Variable
         351             :     real( kind = core_rknd ), dimension(nz) :: &
         352             :       xp3_damped    ! <x'^3> after damping   [units vary]
         353             :
         354             :     ! Local Variable(s)
         355             :     real( kind = core_rknd ) :: &
         356             :       dt_on_tau    ! Ratio of model time step duration to damping timescale  [-]
         357             :
         358             :     integer :: &
         359             :       k    ! Loop index
         360             :
         361             :
         362           0 :     if ( allocated( damping_profile%tau_sponge_damp ) ) then
         363             :
         364             :        ! Set the entire profile of <x'^3> after damping to the profile of <x'^3>
         365             :        ! before damping.  The values of <x'^3> after damping will be overwritten
         366             :        ! at any levels where "sponge"-layer damping occurs.
         367           0 :        xp3_damped = xp3
         368             :
         369           0 :        do k = nz, 1, -1
         370             :
         371             :           ! The height of the model top is zm(nz).
         372           0 :           if ( zm(nz) - z(k) < damping_profile%sponge_layer_depth ) then
         373             :
         374             :              ! Calculate the value of delta_t / tau at the grid level.
         375           0 :              dt_on_tau = dt / damping_profile%tau_sponge_damp(k)
         376             :
         377             :              ! Calculate the damped value of <x'^3>.
         378           0 :              xp3_damped(k) = ( one - dt_on_tau )**3 * xp3(k)
         379             :
         380             :           else ! zm(nz) - z(k) >= damping_profile%sponge_layer_depth
         381             :
         382             :              ! Below sponge damping layer; exit loop.
         383             :              exit
         384             :
         385             :           endif ! zm(nz) - z(k) < damping_profile%sponge_layer_depth
         386             :
         387             :
         388             :        enddo ! k = nz, 1, -1
         389             :
         390             :     else
         391             :
         392           0 :        error stop "tau_sponge_damp in sponge_damp_xp3 used before initialization"
         393             :
         394             :     endif
         395             :
         396             :
         397           0 :     return
         398             :
         399           0 :   end function sponge_damp_xp3
         400             :
         401             :   !=============================================================================
         402           0 :   subroutine initialize_tau_sponge_damp( gr, dt, z, settings, &
         403             :                                          damping_profile )
         404             :
         405             :     ! Description:
         406             :     ! Initialize time scale, tau_sponge_damp, used for damping.  The time scale
         407             :     ! attains its maximum value, tau_sponge_damp_max, at the bottom of the
         408             :     ! "sponge" damping layer, which results in minimal damping.  Likewise, the
         409             :     ! time scale attains its minimum value, tau_sponge_damp_min, at the top of
         410             :     ! the model, which results in maximum damping.  At levels in-between the top
         411             :     ! of the model and the base of the sponge damping layer, the value of
         412             :     ! tau_sponge_damp is in-between tau_sponge_damp_min and tau_sponge_damp_max,
         413             :     ! as calculated by an interpolation formula.
         414             :
         415             :     ! References:
         416             :     ! None
         417             :     !-----------------------------------------------------------------------
         418             :
         419             :     use clubb_precision, only: &
         420             :         core_rknd    ! Variable(s)
         421             :
         422             :     use constants_clubb, only: &
         423             :         two,     & ! Constant(s)
         424             :         fstderr
         425             :
         426             :     use grid_class, only: &
         427             :         grid ! Type
         428             :
         429             : !    use interpolation, only: &
         430             : !        lin_interpolate_two_points    ! Procedure(s)
         431             :
         432             :     implicit none
         433             :
         434             :     type (grid), target, intent(in) :: gr
         435             :
         436             :     ! Input Variable(s)
         437             :     real( kind = core_rknd ), intent(in) :: &
         438             :       dt    ! Model Timestep    [s]
         439             :
         440             :     real( kind = core_rknd ), dimension(gr%nz), intent(in) :: &
         441             :       z    ! Height of model grid levels    [m]
         442             :
         443             :     type(sponge_damp_settings), intent(in) :: &
         444             :       settings
         445             :
         446             :     ! Output Variable(s)
         447             :     type(sponge_damp_profile), intent(out) :: &
         448             :       damping_profile
         449             :
         450             :     ! Local Variable(s)
         451             :     real( kind = core_rknd ) :: &
         452             :       tau_sponge_damp_exponent  ! Exponent in calculation of tau_sponge_damp [-]
         453             :
         454             :     integer :: &
         455             :       k    ! Loop index
         456             :
         457             :     ! ---- Begin Code ----
         458             :
         459             :     ! Allocate the damping time scale.
         460           0 :     allocate( damping_profile%tau_sponge_damp(1:gr%nz) )
         461             :
         462             :     ! Calculate the depth of the sponge layer.
         463             :     ! The height of the model top is gr%zm(1,gr%nz).
         464             :     damping_profile%sponge_layer_depth &
         465           0 :     = settings%sponge_damp_depth * gr%zm(1,gr%nz)
         466             :
         467             :     ! Check the value of tau_sponge_damp_min.
         468           0 :     if ( settings%tau_sponge_damp_min < two * dt ) then
         469           0 :        write(fstderr,*) "Error:  tau_sponge_damp_min is too small!"
         470           0 :        write(fstderr,*) "It must be at least 2.0 * dt"
         471           0 :        error stop
         472             :     endif
         473             :
         474             :     ! Calculate the value of the damping time scale, tau_sponge_damp, at levels
         475             :     ! that are within the sponge damping layer.
         476           0 :     do k = gr%nz, 1, -1
         477             :
         478             :        ! The height of the model top is gr%zm(1,gr%nz).
         479           0 :        if ( gr%zm(1,gr%nz) - z(k) < damping_profile%sponge_layer_depth ) then
         480             :
         481             :           ! Vince Larson added code to use standard linear interpolation.
         482             :           ! Brian Griffin reverted the linear interpolation in order to use code
         483             :           ! that is similar to what is found in SAM LES.
         484             :
         485             :           tau_sponge_damp_exponent &
         486           0 :           = ( gr%zm(1,gr%nz) - z(k) ) / damping_profile%sponge_layer_depth
         487             :
         488           0 :           damping_profile%tau_sponge_damp(k) &
         489             :           = settings%tau_sponge_damp_min &
         490             :             * ( settings%tau_sponge_damp_max &
         491           0 :                 / settings%tau_sponge_damp_min )**tau_sponge_damp_exponent
         492             :
         493             :           !damping_profile%tau_sponge_damp(k) &
         494             :           != lin_interpolate_two_points( z(k), gr%zm(1,gr%nz), &
         495             :           !                              gr%zm(1,gr%nz) &
         496             :           !                              - damping_profile%sponge_layer_depth, &
         497             :           !                              settings%tau_sponge_damp_min, &
         498             :           !                              settings%tau_sponge_damp_max )
         499             :
         500             :           ! End Vince Larson's change
         501             :           ! End Brian Griffin's rebellious reversion.
         502             :
         503             :        else ! gr%zm(1,gr%nz) - z(k) >= damping_profile%sponge_layer_depth
         504             :
         505             :           ! Below sponge damping layer; exit loop.
         506             :           exit
         507             :
         508             :        endif ! gr%zm(1,gr%nz) - z(k) < damping_profile%sponge_layer_depth
         509             :
         510             :     enddo ! k = gr%nz, 1, -1
         511             :
         512             :
         513           0 :     return
         514             :
         515             :   end subroutine initialize_tau_sponge_damp
         516             :
         517             :   !=============================================================================
         518           0 :   subroutine finalize_tau_sponge_damp( damping_profile )
         519             :
         520             :     ! Description:
         521             :     ! Frees memory allocated in initialize_tau_sponge_damp
         522             :     !
         523             :     ! References:
         524             :     ! None
         525             :     !-----------------------------------------------------------------------
         526             :
         527             :     implicit none
         528             :
         529             :     ! Input/Output Variable(s)
         530             :     type(sponge_damp_profile), intent(inout) :: &
         531             :       damping_profile ! Information for damping the profile
         532             :
         533             :     ! ---- Begin Code ----
         534             :
         535             :     ! Deallocate the damping time scale.
         536           0 :     deallocate( damping_profile%tau_sponge_damp )
         537             :
         538             :
         539           0 :     return
         540             :
         541             :   end subroutine finalize_tau_sponge_damp
         542             :
         543             : !===============================================================================
         544             :
         545           0 : end module sponge_layer_damping

Generated by: LCOV version 1.14