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 17:57:11 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