control_mod.F90       coverage:  40.00 %func     15.76 %block


     1) #ifdef HAVE_CONFIG_H
     2) #include "config.h"
     3) #endif
     4) 
     5) ! This module contains constants and namelist variables used through out the model
     6) ! to avoid circular dependancies please do not 'use' any further modules here.
     7) !
     8) module control_mod
     9)   use kinds, only : real_kind
    10)   use physical_constants, only: dd_pi
    11) 
    12)   implicit none
    13) 
    14)   integer, public, parameter :: MAX_STRING_LEN=240
    15)   integer, public, parameter :: MAX_FILE_LEN=240
    16)   character(len=MAX_STRING_LEN)    , public :: integration    ! time integration (explicit, or full imp)
    17) 
    18)   ! Tracer transport algorithm type:
    19)   !     0  spectral-element Eulerian
    20)   !    12 interpolation semi-Lagrangian
    21)   integer, public  :: transport_alg = 0
    22)   ! Constrained density reconstructor for SL property preservation; not used if
    23)   ! transport_alg = 0:
    24)   !     0  none
    25)   !     2  QLT
    26)   !     3  CAAS
    27)   !    20  QLT  with superlevels
    28)   !    30  CAAS with superlevels
    29)   integer, public  :: semi_lagrange_cdr_alg = 3
    30)   ! If true, check mass conservation and shape preservation. The second
    31)   ! implicitly checks tracer consistency.
    32)   logical, public  :: semi_lagrange_cdr_check = .false.
    33)   ! If > 0 and nu_q > 0, apply hyperviscosity to tracers 1 through this value,
    34)   ! rather than just those that couple to the dynamics at the dynamical time
    35)   ! step. These latter are 'active' tracers, in contrast to 'passive' tracers
    36)   ! that directly couple only to the physics.
    37)   integer, public  :: semi_lagrange_hv_q = 1
    38)   ! If >= 1, then the SL algorithm may choose a nearby point inside the element
    39)   ! halo available to it if the actual point is outside the halo. This is done
    40)   ! in levels <= this parameter.
    41)   integer, public :: semi_lagrange_nearest_point_lev = 256
    42) 
    43) ! flag used by preqx, theta-l and theta-c models
    44) ! should be renamed to "hydrostatic_mode"
    45)   logical, public :: theta_hydrostatic_mode
    46) 
    47) 
    48)   integer, public  :: tstep_type= 5                           ! preqx timestepping options
    49)   integer, public  :: rk_stage_user  = 0                      ! number of RK stages (shallow water model) 
    50)   integer, public  :: ftype = 0                                ! Forcing Type
    51)                                                                ! ftype = 0  HOMME ApplyColumn() type forcing process split
    52)                                                                ! ftype = -1   ignore forcing  (used for testing energy balance)
    53)                                               
    54)   integer, public :: qsplit = 1           ! ratio of dynamics tsteps to tracer tsteps
    55)   integer, public :: rsplit = 0           ! for vertically lagrangian dynamics, apply remap
    56)                                           ! every rsplit tracer timesteps
    57) 
    58)   ! These factors replace rsplit and qsplit.
    59)   !   If dt_remap_factor = 0, use vertically Eulerian dynamics.
    60)   !   If dt_remap_factor > 0, the vertical remap time step is
    61)   ! dt_remap_factor*tstep.
    62)   !   The tracer transport time step is dt_tracer_factor*tstep.
    63)   !   The smaller of dt_remap_factor and dt_tracer_factor must divide
    64)   ! the larger.
    65)   !   If dt_remap_factor >= dt_tracer_factor, then
    66)   !     new dt_tracer_factor == old qsplit
    67)   !     new dt_remap_factor == old dt_tracer_factor/dt_remap_factor
    68)   ! Default values make qsplit and rsplit control the time steps.
    69)   integer, public :: dt_remap_factor = -1, dt_tracer_factor = -1
    70) 
    71)   integer, public :: prim_step_type = -1 ! 1 = old code for EUL, 2 = prim_run_flexible for SL
    72)                                           ! -1 means it wasn't set, error
    73) 
    74)   integer, public :: LFTfreq=0            ! leapfrog-trapazoidal frequency (shallow water only)
    75)                                           ! interspace a lf-trapazoidal step every LFTfreq leapfrogs    
    76)                                           ! 0 = disabled
    77) 
    78) ! vert_remap_q_alg:   -1  PPM remap without monotone filter, used for some test cases
    79) !                      0  Zerroukat monotonic splines
    80) !                      1  PPM vertical remap with constant extension at the boundaries
    81) !                     10  PPM with linear extrapolation at boundaries, with column limiter
    82) !                     11  PPM with unlimited linear extrapolation at boundaries
    83)  integer, public :: vert_remap_q_alg = 0    ! tracers
    84)  integer, public :: vert_remap_u_alg = -2   ! remap for dynamics. default -2 means inherit vert_remap_q_alg
    85) 
    86) ! advect theta 0: conservation form 
    87) !              1: expanded divergence form (less noisy, non-conservative)
    88)  integer, public :: theta_advect_form = 0
    89)  real (kind=real_kind), public :: vtheta_thresh = 100.d0  ! threshold for virtual potential temperature minimum limiter
    90)  real (kind=real_kind), public :: dp3d_thresh   = 0.125d0 ! threshold for dp3d minimum limiter
    91) 
    92)  integer, public :: pgrad_correction  = 0   ! 1=turn on theta model pressure gradient correction
    93)  integer, public :: hv_ref_profiles   = 0   ! 1=turn on theta model HV reference profiles
    94)  integer, public :: hv_theta_correction=0   ! 1=use HV on p-surface approximation for theta
    95)  real (kind=real_kind), public :: hv_theta_thresh=.025d0  ! d(theta)/dp max threshold for HV correction term
    96) 
    97)  integer, public :: cubed_sphere_map = -1  ! -1 = chosen at run time
    98)                                            !  0 = equi-angle Gnomonic (default)
    99)                                            !  1 = equi-spaced Gnomonic (not yet coded)
   100)                                            !  2 = element-local projection  (for var-res)
   101)                                            !  3 = parametric (not yet coded)
   102) 
   103) !tolerance to define smth small, was introduced for lim 8 in 2d and 3d
   104)   real (kind=real_kind), public, parameter :: tol_limiter=1e-13
   105) 
   106)   integer              , public :: limiter_option = 0
   107)   character(len=MAX_STRING_LEN)    , public :: precon_method  ! if semi_implicit, type of preconditioner:
   108)                                                   ! choices block_jacobi or identity
   109) 
   110)   integer              , public :: coord_transform_method   ! If zoltan2 is used, various ways of representing the coordinates methods
   111)                                                             ! Instead of using the sphere coordinates, it is better to use cube or projected 2D coordinates for quality.
   112)                                                             ! check params_mod for options.
   113) 
   114)   integer              , public :: z2_map_method            ! If zoltan2 is used,
   115)                                                             ! Task mapping method to be used by zoltan2.
   116)                                                             ! Z2_NO_TASK_MAPPING        (1) - is no task mapping
   117)                                                             ! Z2_TASK_MAPPING           (2) - performs default task mapping of zoltan2.
   118)                                                             ! Z2_OPTIMIZED_TASK_MAPPING (3) - includes network aware optimizations.
   119)                                                             ! Use (3) if zoltan2 is enabled.
   120) 
   121)   integer              , public :: partmethod     ! partition methods
   122)   character(len=MAX_STRING_LEN)    , public :: topology = "cube"       ! options: "cube", "plane"
   123)   character(len=MAX_STRING_LEN)    , public :: geometry = "sphere"      ! options: "sphere", "plane"
   124)   character(len=MAX_STRING_LEN)    , public :: test_case
   125)   !most tests don't have forcing
   126)   logical                          , public :: test_with_forcing = .false. 
   127)   integer              , public :: statefreq      ! output frequency of synopsis of system state (steps)
   128)   integer              , public :: restartfreq
   129)   integer              , public :: runtype 
   130)   integer              , public :: timerdetail 
   131)   integer              , public :: numnodes 
   132)   character(len=MAX_STRING_LEN)    , public :: restartfile 
   133)   character(len=MAX_STRING_LEN)    , public :: restartdir
   134) 
   135)   ! flag used for "slice" planar tests (no variation in y-dir)
   136)   logical, public :: planar_slice
   137)   
   138) ! namelist variable set to dry,notdry,moist
   139) ! internally the code should use logical "use_moisture"
   140)   character(len=MAX_STRING_LEN)    , public :: moisture  
   141) 
   142)   integer, public  :: use_cpstar=0          ! use cp or cp* in thermodynamics
   143)   logical, public  :: use_moisture=.false.  ! use Q(:,:,:,1) to compute T_v
   144) 
   145)   
   146)   integer              , public :: maxits         ! max iterations of solver
   147)   real (kind=real_kind), public :: tol            ! solver tolerance (convergence criteria)
   148)   integer              , public :: debug_level    ! debug level of CG solver
   149) 
   150) 
   151)   character(len=MAX_STRING_LEN)    ,public  :: vfile_int=""   ! vertical formulation (ecmwf,ccm1)
   152)   character(len=MAX_STRING_LEN)    ,public  :: vfile_mid=""   ! vertical grid spacing (equal,unequal)
   153)   integer,                          public  :: vanalytic = 0  ! if 1, test initializes vertical coords
   154)   real (kind=real_kind),            public  :: vtop = 0.1     ! top coordinate level for analytic vcoords
   155) 
   156)   real (kind=real_kind), public :: nu      = 7.0D5            ! viscosity (momentum equ)
   157)   real (kind=real_kind), public :: nu_div  = -1               ! viscsoity (momentum equ, div component)
   158)   real (kind=real_kind), public :: nu_s    = -1               ! default = nu   T equ. viscosity
   159)   real (kind=real_kind), public :: nu_q    = -1               ! default = nu   tracer viscosity
   160)   real (kind=real_kind), public :: nu_p    = -1               ! default = nu   ps equ. viscosity
   161)   real (kind=real_kind), public :: nu_top  = 0.0D5            ! top-of-the-model viscosity
   162)   real (kind=real_kind), public :: tom_sponge_start=0         ! start of sponge layer, in hPa
   163) 
   164)   integer, public :: hypervis_subcycle=1                      ! number of subcycles for hyper viscsosity timestep
   165)   integer, public :: hypervis_subcycle_tom=0                  ! number of subcycles for TOM diffusion
   166)                                                               !   0   apply together with hyperviscosity
   167)                                                               !   >1  apply timesplit from hyperviscosity
   168)   integer, public :: hypervis_subcycle_q=1                    ! number of subcycles for hyper viscsosity timestep on TRACERS
   169)   integer, public :: hypervis_order=0                         ! laplace**hypervis_order.  0=not used  1=regular viscosity, 2=grad**4
   170) 
   171)   real (kind=real_kind), public :: hypervis_scaling=0         ! use tensor hyperviscosity
   172) 
   173)   !three types of hyper viscosity are supported right now:
   174)   ! (1) const hv:    nu * del^2 del^2
   175)   ! (2) tensor hv,   nu * ( \div * tensor * \grad ) * del^2
   176)   !
   177)   ! (1) hypervis_scaling=0
   178)   ! (2) tensor HV var-res grids  
   179)   !            tensor within each element:
   180)   !            set hypervis_scaling > 0 (typical values would be 3.0)
   181)   !            (\div * tensor * \grad) operator uses cartesian laplace
   182)   !
   183) 
   184)   ! hyperviscosity parameters used for smoothing topography
   185)   integer, public :: smooth_phis_numcycle = -1   ! -1 = disable
   186)   integer, public :: smooth_phis_p2filt = -1     ! -1 = disable
   187)   real (kind=real_kind), public :: smooth_phis_nudt = 0
   188) 
   189)   integer, public :: prescribed_wind=0    ! fix the velocities?
   190) 
   191) 
   192)   integer, public, parameter :: west  = 1
   193)   integer, public, parameter :: east  = 2
   194)   integer, public, parameter :: south = 3
   195)   integer, public, parameter :: north = 4
   196)   integer, public, parameter :: swest = 5
   197)   integer, public, parameter :: seast = 6
   198)   integer, public, parameter :: nwest = 7
   199)   integer, public, parameter :: neast = 8
   200)   
   201)   logical, public :: disable_diagnostics  = .FALSE.
   202) 
   203)   ! Physgrid parameters
   204)   integer, public :: se_fv_phys_remap_alg = 1
   205) 
   206)   ! Hommexx-specific parameters
   207)   integer, public :: internal_diagnostics_level = 0
   208) 
   209) 
   210) !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
   211) !
   212) ! test case global parameters
   213) !
   214) !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
   215)   ! generic test case parameter - can be used by any test case to define options
   216)   integer, public :: sub_case = 1                  
   217) 
   218)   real (kind=real_kind), public :: initial_total_mass = 0    ! initial perturbation in JW test case
   219)   real (kind=real_kind), public :: u_perturb   = 0         ! initial perturbation in JW test case
   220) #ifndef CAM
   221)   real (kind=real_kind), public :: pertlim = 0          !pertibation to temperature [like CESM]
   222) #endif
   223) 
   224)   ! shallow water advection test paramters
   225)   ! kmass = level index with density.  other levels contain test tracers
   226)   integer, public  :: kmass  = -1
   227)   integer, public  :: toy_chemistry = 0            !  1 = toy chemestry is turned on in 2D advection code
   228)   real (kind=real_kind), public :: g_sw_output            	   = 9.80616D0          ! m s^-2
   229) 
   230)   ! parameters for dcmip12 test 2-0: steady state atmosphere with orography
   231)   real(real_kind), public :: dcmip2_0_h0      = 2000.d0        ! height of mountain range        (meters)
   232)   real(real_kind), public :: dcmip2_0_Rm      = 3.d0*dd_pi/4.d0   ! radius of mountain range        (radians)
   233)   real(real_kind), public :: dcmip2_0_zetam   = dd_pi/16.d0       ! mountain oscillation half-width (radians)
   234) 
   235)   ! parameters for dcmip12 test 2-x: mountain waves
   236)   real(real_kind), public :: dcmip2_x_ueq     = 20.d0          ! wind speed at equator (m/s)
   237)   real(real_kind), public :: dcmip2_x_h0      = 250.0d0        ! mountain height       (m)
   238)   real(real_kind), public :: dcmip2_x_d       = 5000.0d0       ! mountain half width   (m)
   239)   real(real_kind), public :: dcmip2_x_xi      = 4000.0d0       ! mountain wavelength   (m)
   240) 
   241)   ! for dcmip 2014 test 4:
   242)   integer,         public :: dcmip4_moist     = 1
   243)   real(real_kind), public :: dcmip4_X         = 1.0d0 
   244) 
   245)   ! for dcmip 2016 test 2
   246)   integer, public :: dcmip16_prec_type = 0;
   247)   integer, public :: dcmip16_pbl_type  = 0;
   248) 
   249)   ! for dcmip 2016 test 3
   250)   real (kind=real_kind), public :: dcmip16_mu      = 0        ! additional uniform viscosity (momentum)
   251)   real (kind=real_kind), public :: dcmip16_mu_s    = 0        ! additional uniform viscosity (scalar dynamical variables)
   252)   real (kind=real_kind), public :: dcmip16_mu_q    = -1       ! additional uniform viscosity (scalar tracers); -1 implies it defaults to dcmip16_mu_s value
   253)   real (kind=real_kind), public :: interp_lon0     = 0.0d0
   254) 
   255) !PLANAR
   256)   real (kind=real_kind), private, parameter :: tol_zero=1e-10 !tolerance to determine if lx,ly,sx,sy are set
   257) 
   258)   real (kind=real_kind), public :: bubble_T0 = 270.0       !bubble ref state
   259)   real (kind=real_kind), public :: bubble_dT = 0.5         !bubble dTheta
   260)   real (kind=real_kind), public :: bubble_xycenter = 0.0   !bubble xy position
   261)   real (kind=real_kind), public :: bubble_zcenter = 3000.0 !bubble z position
   262)   real (kind=real_kind), public :: bubble_ztop = 10000.0   !bubble z top
   263)   real (kind=real_kind), public :: bubble_xyradius = 2000.0!bubble radius along x or y axis
   264)   real (kind=real_kind), public :: bubble_zradius = 1500.0 !bubble radius along z axis
   265)   logical,               public :: bubble_cosine  = .TRUE. !bubble uniform or cosine
   266)   logical,               public :: bubble_moist  = .FALSE.    ! 
   267)   real (kind=real_kind), public :: bubble_moist_drh = 0.0     !bubble dRH parameter
   268)   real (kind=real_kind), public :: bubble_rh_background = 0.0 !bubble RH parameter
   269)   integer,               public :: bubble_prec_type = 0       !0 kessler, 1 rj
   270)   logical,               protected :: case_planar_bubble = .FALSE.
   271) 
   272)   public :: set_planar_defaults
   273) 
   274) contains
   275) 
   276)   function timestep_make_parameters_consistent(par, rsplit, qsplit, &
   277)        dt_remap_factor, dt_tracer_factor, tstep, dtime, nsplit, nstep_factor, &
   278)        abrtf, silent) result(status)
   279) 
   280)     ! Current and future development require a more flexibility in
   281)     ! specifying time steps. This routine analyzes the settings and
   282)     ! either sets unset ones consistently or provides an error message
   283)     ! and aborts.
   284)     !   A return value of 0 means success; <0 means there was an
   285)     ! error. In the case of error, a message is written to iulog.
   286)     !   If you want a value to be computed, set it to <0 on input.
   287) 
   288)     use parallel_mod, only: abortmp, parallel_t
   289)     use kinds, only: iulog
   290) 
   291)     type (parallel_t), intent(in) :: par
   292)     integer, intent(inout) :: &
   293)          ! Old method of specifying subcycles, in which the vertical
   294)          ! remap time step is restricted to be at least as large as
   295)          ! the tracer time step.
   296)          rsplit, qsplit, &
   297)          ! New method, which permits either time step to be the
   298)          ! larger, subject to that one must divide the other.
   299)          dt_remap_factor, dt_tracer_factor, &
   300)          nsplit
   301)     integer, intent(out) :: &
   302)          ! On output, dtime/tstep.
   303)          nstep_factor
   304)     real(kind=real_kind), intent(inout) :: &
   305)          ! Dynamics time step.
   306)          tstep
   307)     integer, intent(inout) :: &
   308)          ! Physics-dynamics coupling time step.
   309)          dtime
   310)     logical, intent(in), optional :: abrtf, silent
   311)     integer :: status
   312) 
   313)     real(kind=real_kind), parameter :: &
   314)          zero = 0.0_real_kind, &
   315)          eps = epsilon(1.0_real_kind), &
   316)          divisible_tol = 1e3_real_kind*eps
   317) 
   318)     logical :: abort_in, silent_in
   319) 
   320)     abort_in = .true.
   321)     if (present(abrtf)) abort_in = abrtf
   322)     silent_in = .false.
   323)     if (present(silent)) silent_in = silent
   324) 
   325)     status = timestep_make_subcycle_parameters_consistent( &
   326)          par, rsplit, qsplit, dt_remap_factor, dt_tracer_factor, &
   327)          abort_in, silent_in)
   328)     if (status /= 0) return
   329)     status = timestep_make_eam_parameters_consistent( &
   330)          par, dt_remap_factor, dt_tracer_factor, nsplit, nstep_factor, tstep, dtime, &
   331)          abort_in, silent_in)
   332)   end function timestep_make_parameters_consistent
   333) 
   334)   function timestep_make_subcycle_parameters_consistent(par, rsplit, qsplit, &
   335)        dt_remap_factor, dt_tracer_factor, abrtf, silent) result(status)
   336) 
   337)     use parallel_mod, only: abortmp, parallel_t
   338)     use kinds, only: iulog
   339) 
   340)     type (parallel_t), intent(in) :: par
   341)     integer, intent(inout) :: rsplit, qsplit, dt_remap_factor, dt_tracer_factor
   342)     logical, intent(in), optional :: abrtf, silent
   343)     integer :: status
   344) 
   345)     integer :: qsplit_prev, rsplit_prev
   346)     logical :: split_specified, factor_specified, split_is_master, abort_in, silent_in
   347) 
   348)     abort_in = .true.
   349)     if (present(abrtf)) abort_in = abrtf
   350)     silent_in = .false.
   351)     if (present(silent)) silent_in = silent
   352) 
   353)     status = -1 ! error value for early returns on error
   354) 
   355)     split_specified = rsplit >= 0 .and. qsplit >= 1
   356)     factor_specified = dt_remap_factor >= 0 .and. dt_tracer_factor >= 1
   357) 
   358)     if (.not. split_specified .and. .not. factor_specified) then
   359)        if (par%masterproc .and. .not. silent_in) then
   360)           write(iulog,*) 'Neither rsplit,qsplit nor dt_remap_factor,dt_tracer_factor &
   361)                &are specified; one set must be.'
   362)        end if
   363)        if (abort_in) call abortmp('timestep_make_parameters_consistent: input error')
   364)        return
   365)     end if
   366) 
   367)     !! Process rsplit, qsplit, dt_remap_factor, dt_tracer_factor.
   368) 
   369)     ! To support namelists with defaulted qsplit, rsplit values, we
   370)     ! permit (split_specified .and. factor_specified). In this case,
   371)     ! factor_specified means factor values are used.
   372) 
   373)     split_is_master = .not. factor_specified
   374) 
   375)     if (split_is_master) then
   376)        dt_remap_factor = rsplit*qsplit
   377)        dt_tracer_factor = qsplit
   378)     else
   379)        if (dt_remap_factor > 0) then
   380)           if (.not. (modulo(dt_remap_factor, dt_tracer_factor) == 0 .or. &
   381)                      modulo(dt_tracer_factor, dt_remap_factor) == 0)) then
   382)              if (par%masterproc .and. .not. silent_in) then
   383)                 write(iulog,*) 'dt_remap_factor and dt_tracer_factor were specified, &
   384)                      &but neither divides the other.'
   385)              end if
   386)              if (abort_in) call abortmp('timestep_make_parameters_consistent: divisibility error')
   387)              return
   388)           end if
   389)        end if
   390)        qsplit_prev = qsplit
   391)        rsplit_prev = rsplit
   392)        qsplit = dt_tracer_factor
   393)        ! This is the only inconsistent setting. But I want to keep
   394)        ! this here b/c almost all uses of rsplit is simply for whether
   395)        ! it's == 0, and I don't want to touch all those lines in this
   396)        ! PR.
   397)        if (dt_tracer_factor <= dt_remap_factor) then
   398)           rsplit = dt_remap_factor/dt_tracer_factor
   399)        else
   400)           ! If rsplit cannot be set consistently (because
   401)           ! dt_tracer_factor < dt_remap_factor), then just preserve
   402)           ! the sign to distinguish between vertically Eulerian and
   403)           ! Lagrangian methods.
   404)           if (dt_remap_factor > 0) then
   405)              rsplit = 1
   406)           else
   407)              rsplit = 0
   408)           end if
   409)        end if
   410)        if (split_specified .and. (qsplit /= qsplit_prev .or. rsplit /= rsplit_prev) .and. &
   411)             par%masterproc .and. .not. silent_in) then
   412)           write(iulog,'(a,i2,a,i2,a,i2,a,i2,a)') &
   413)                'dt_remap_factor and dt_tracer_factor were specified; changing qsplit from ', &
   414)                qsplit_prev, ' to ', qsplit, ' and rsplit from ', rsplit_prev, ' to ', rsplit, '.'
   415)        end if
   416)     end if
   417) 
   418)     status = 0 ! success value
   419)   end function timestep_make_subcycle_parameters_consistent
   420) 
   421)   function timestep_make_eam_parameters_consistent(par, dt_remap_factor, dt_tracer_factor, &
   422)        nsplit, nstep_factor, tstep, dtime, abrtf, silent) result(status)
   423) 
   424)     use parallel_mod, only: abortmp, parallel_t
   425)     use kinds, only: iulog
   426) 
   427)     type (parallel_t), intent(in) :: par
   428)     integer, intent(in) :: dt_remap_factor, dt_tracer_factor
   429)     integer, intent(inout) :: nsplit
   430)     integer, intent(out) :: nstep_factor
   431)     real(kind=real_kind), intent(inout) :: tstep
   432)     integer, intent(inout) :: dtime
   433)     logical, intent(in), optional :: abrtf, silent
   434)     integer :: status
   435) 
   436)     real(kind=real_kind), parameter :: &
   437)          zero = 0.0_real_kind, &
   438)          eps = epsilon(1.0_real_kind), &
   439)          divisible_tol = 1e3_real_kind*eps
   440) 
   441)     real(kind=real_kind) :: nsplit_real, tmp
   442)     integer :: dt_max_factor
   443)     logical :: abort_in, silent_in
   444) 
   445)     abort_in = .true.
   446)     if (present(abrtf)) abort_in = abrtf
   447)     silent_in = .false.
   448)     if (present(silent)) silent_in = silent
   449) 
   450)     status = -1 ! error value for early returns on error
   451) 
   452)     !! Process dtime, tstep, nsplit.
   453)     dt_max_factor = max(dt_remap_factor, dt_tracer_factor)
   454) 
   455)     ! Every 'if' has an 'else', so every case is covered.
   456)     if (nsplit > 0) nstep_factor = dt_max_factor*nsplit
   457)     if (dtime > 0) then
   458)        if (nsplit > zero) then
   459)           tmp = real(dtime, real_kind)/real(nstep_factor, real_kind)
   460)           if (tstep > zero) then
   461)              if (abs(tstep - tmp) > divisible_tol*tmp) then
   462)                 if (par%masterproc .and. .not. silent_in) then
   463)                    write(iulog,'(a,a,i6,a,i2,a,es11.4,a,i2)') &
   464)                         'dtime, nsplit, tstep were all >0 on input, but they disagree: ', &
   465)                         'dtime ', dtime, ' nsplit ', nsplit, ' tstep ', tstep, ' nstep_factor ', nstep_factor
   466)                 end if
   467)                 if (abort_in) call abortmp('timestep_make_parameters_consistent: divisibility error')
   468)                 return
   469)              end if
   470)           end if
   471)           tstep = tmp
   472)        elseif (tstep > zero) then
   473)           nsplit_real = real(dtime, real_kind)/(dt_max_factor*tstep)
   474)           nsplit = idnint(nsplit_real)
   475)           nstep_factor = dt_max_factor*nsplit
   476)           if (abs(nsplit_real - nsplit) > divisible_tol*nsplit_real) then
   477)              if (par%masterproc .and. .not. silent_in) then
   478)                 write(iulog,'(a,es11.4,a,i7,a,es11.4,a,i2,a,i2,a,i2,a)') &
   479)                      'nsplit was computed as ', nsplit_real, ' based on dtime ', dtime, &
   480)                      ', tstep ', tstep, &
   481)                      ', and dt_max_factor = max(dt_remap_factor, dt_tracer_factor) = max(', &
   482)                      dt_remap_factor, ',', dt_tracer_factor, ') =', dt_max_factor, &
   483)                      ', which is outside the divisibility tolerance. &
   484)                      &Set tstep, dt_remap_factor, and dt_tracer_factor so that &
   485)                      &tstep and dt_max_factor*tstep divide dtime.'
   486)              end if
   487)              if (abort_in) call abortmp('timestep_make_parameters_consistent: divisibility error')
   488)              return
   489)           end if
   490)        else
   491)           if (par%masterproc .and. .not. silent_in) then
   492)              write(iulog,*) 'If dtime is set to >0, then either nsplit or tstep must be >0.'
   493)           end if
   494)           if (abort_in) call abortmp('timestep_make_parameters_consistent: input error')
   495)           return
   496)        end if
   497)     else
   498)        if (tstep > zero) then
   499)           if (nsplit > 0) then
   500)              dtime = tstep*nstep_factor
   501)           else
   502) #ifdef CAM
   503)              if (par%masterproc .and. .not. silent_in) then
   504)                 write(iulog,*) 'If dtime is set to <=0 and tstep >0, then nsplit must be >0.'
   505)              end if
   506)              if (abort_in) call abortmp('timestep_make_parameters_consistent: input error')
   507)              return
   508) #endif
   509)           end if
   510)        else
   511)           if (par%masterproc .and. .not. silent_in) then
   512)              write(iulog,*) 'If dtime is set to <=0, then tstep must be >0.'
   513)           end if
   514)           if (abort_in) call abortmp('timestep_make_parameters_consistent: input error')
   515)           return          
   516)        end if
   517)     end if
   518) 
   519)     status = 0 ! success value
   520)   end function timestep_make_eam_parameters_consistent
   521) 
   522)   subroutine test_timestep_make_parameters_consistent(par, nerr)
   523)     ! Test timestep_make_parameters_consistent.
   524) 
   525)     use parallel_mod, only: parallel_t
   526)     use kinds, only: iulog
   527) 
   528)     type (parallel_t), intent(in) :: par
   529)     integer, intent(out) :: nerr
   530) 
   531)     real(real_kind), parameter :: eps = epsilon(1.0_real_kind), tol = 1e3_real_kind*eps
   532) 
   533)     real(real_kind) :: tstep
   534)     integer :: i, rs, qs, drf, dtf, ns, nstep_fac, dtime
   535)     logical :: a, s
   536) 
   537)     a = .false.
   538)     nerr = 0
   539) 
   540)     !! Test backwards compatibility.
   541)     dtime = 1800
   542) 
   543)     qs = 3; rs = 0; drf = -1; dtf = -1
   544)     tstep = -1; ns = 2
   545)     i = timestep_make_parameters_consistent(par,rs,qs,drf,dtf,tstep,dtime,ns,nstep_fac,a)
   546)     if (i /= 0 .or. drf /= 0 .or. dtf /= qs .or. nstep_fac /= qs*ns .or. &
   547)          abs(tstep - dtime/(ns*qs)) > tol) &
   548)          nerr = nerr + 1
   549) 
   550)     qs = 3; rs = 2; drf = -1; dtf = -1
   551)     tstep = -1; ns = 3
   552)     i = timestep_make_parameters_consistent(par,rs,qs,drf,dtf,tstep,dtime,ns,nstep_fac,a)
   553)     if (i /= 0 .or. drf /= qs*rs .or. dtf /= qs .or. nstep_fac /= qs*rs*ns .or. &
   554)          abs(tstep - dtime/(qs*rs*ns)) > tol) &
   555)          nerr = nerr + 1
   556) 
   557)     !! Test new interface.
   558)     tstep = 300_real_kind
   559) 
   560)     qs = -1; rs = -1; drf = 0; dtf = 6
   561)     dtime = -1; ns = 2
   562)     i = timestep_make_parameters_consistent(par,rs,qs,drf,dtf,tstep,dtime,ns,nstep_fac,a)
   563)     if (i /= 0 .or. rs /= drf .or. qs /= dtf .or. nstep_fac /= dtf*ns .or. &
   564)          abs(tstep - dtime/(ns*qs)) > tol) &
   565)          nerr = nerr + 1
   566) 
   567)     qs = -1; rs = -1; drf = 12; dtf = 6
   568)     dtime = -1; ns = 3
   569)     i = timestep_make_parameters_consistent(par,rs,qs,drf,dtf,tstep,dtime,ns,nstep_fac,a)
   570)     if (i /= 0 .or. rs /= 2 .or. qs /= 6 .or. nstep_fac /= qs*rs*ns .or. &
   571)          abs(tstep - dtime/(qs*rs*ns)) > tol) &
   572)          nerr = nerr + 1
   573) 
   574)     qs = -1; rs = -1; drf = 12; dtf = 6
   575)     tstep = 300_real_kind; dtime = 7200; ns = -1
   576)     i = timestep_make_parameters_consistent(par,rs,qs,drf,dtf,tstep,dtime,ns,nstep_fac,a)
   577)     if (i /= 0 .or. rs /= 2 .or. qs /= 6 .or. nstep_fac /= qs*rs*ns .or. ns /= 2 .or. &
   578)          abs(tstep - dtime/(qs*rs*ns)) > tol) &
   579)          nerr = nerr + 1
   580) 
   581)     !! Test new interface with new time step flexibility.
   582)     qs = -1; rs = -1; drf = 2; dtf = 6
   583)     dtime = -1; ns = 3
   584)     i = timestep_make_parameters_consistent(par,rs,qs,drf,dtf,tstep,dtime,ns,nstep_fac,a)
   585)     if (i /= 0 .or. rs == 0 .or. qs /= 6 .or. nstep_fac /= dtf*ns .or. &
   586)          abs(tstep - dtime/(dtf*ns)) > tol) &
   587)          nerr = nerr + 1
   588) 
   589)     !! Test error and warning conditions.
   590)     ! Silence messages in this unit test since we're forcing them.
   591)     s = .true.
   592) 
   593)     qs = -1; rs = 0; drf = -1; dtf = -1
   594)     tstep = -1; ns = 2
   595)     i = timestep_make_parameters_consistent(par,rs,qs,drf,dtf,tstep,dtime,ns,nstep_fac,a,s)
   596)     if (i == 0) nerr = nerr + 1
   597) 
   598)     qs = -1; rs = 0; drf = 3; dtf = 4
   599)     tstep = -1; ns = 2
   600)     i = timestep_make_parameters_consistent(par,rs,qs,drf,dtf,tstep,dtime,ns,nstep_fac,a,s)
   601)     if (i == 0) nerr = nerr + 1
   602) 
   603)     qs = -1; rs = 0; drf = 1; dtf = 4
   604)     tstep = 300; dtime = 700; ns = 1
   605)     i = timestep_make_parameters_consistent(par,rs,qs,drf,dtf,tstep,dtime,ns,nstep_fac,a,s)
   606)     if (i == 0) nerr = nerr + 1
   607) 
   608)     qs = -1; rs = 0; drf = 1; dtf = 4
   609)     tstep = 300; dtime = 700; ns = -1
   610)     i = timestep_make_parameters_consistent(par,rs,qs,drf,dtf,tstep,dtime,ns,nstep_fac,a,s)
   611)     if (i == 0) nerr = nerr + 1
   612) 
   613)     qs = -1; rs = 0; drf = 1; dtf = 4
   614)     tstep = -1; dtime = 700; ns = -1
   615)     i = timestep_make_parameters_consistent(par,rs,qs,drf,dtf,tstep,dtime,ns,nstep_fac,a,s)
   616)     if (i == 0) nerr = nerr + 1
   617) 
   618)     qs = -1; rs = 0; drf = 1; dtf = 4
   619)     tstep = -1; dtime = -1; ns = 2
   620)     i = timestep_make_parameters_consistent(par,rs,qs,drf,dtf,tstep,dtime,ns,nstep_fac,a,s)
   621)     if (i == 0) nerr = nerr + 1
   622) 
   623)     !! Test warning conditions.
   624)     qs = 4; rs = 0; drf = 3; dtf = 6
   625)     tstep = -1; dtime = 1800; ns = 2
   626)     i = timestep_make_parameters_consistent(par,rs,qs,drf,dtf,tstep,dtime,ns,nstep_fac,a,s)
   627)     if (i /= 0 .or. qs /= dtf .or. rs /= 1) nerr = nerr + 1
   628) 
   629)     qs = 4; rs = 0; drf = 12; dtf = 6
   630)     tstep = -1; dtime = 1800; ns = 2
   631)     i = timestep_make_parameters_consistent(par,rs,qs,drf,dtf,tstep,dtime,ns,nstep_fac,a,s)
   632)     if (i /= 0 .or. qs /= dtf .or. rs /= 2) nerr = nerr + 1
   633) 
   634)     if (par%masterproc .and. nerr > 0) &
   635)          write(iulog,'(a,i2)') 'test_timestep_make_parameters_consistent nerr', nerr
   636)   end subroutine test_timestep_make_parameters_consistent
   637) 
   638) 
   639) subroutine set_planar_defaults()
   640) 
   641) use physical_constants, only: Lx, Ly, Sx, Sy
   642)  
   643) !since defaults here depend on test, they cannot be set before ctl_nl is read, unlike some other parameters, bubble_*, etc.        
   644) !if true, most likely lx,ly,sx,sy weren't set in ctl_nl
   645)     if (      abs(lx).le.tol_zero .and. abs(ly).le.tol_zero &
   646)         .and. abs(sx).le.tol_zero .and. abs(sy).le.tol_zero )then
   647)     if (test_case == "planar_dbl_vrtx") then
   648)       Lx = 5000.0D0 * 1000.0D0
   649)       Ly = 5000.0D0 * 1000.0D0
   650)       Sx = 0.0D0
   651)       Sy = 0.0D0
   652)     else if (test_case == "planar_hydro_gravity_wave") then
   653)        Lx = 6000.0D0 * 1000.0D0
   654)        Ly = 6000.0D0 * 1000.0D0
   655)        Sx = -3000.0D0 * 1000.0D0
   656)        Sy = -3000.0D0 * 1000.0D0
   657)     else if (test_case == "planar_nonhydro_gravity_wave") then
   658)        Lx = 300.0D0 * 1000.0D0
   659)        Ly = 300.0D0 * 1000.0D0
   660)        Sx = -150.0D0 * 1000.0D0
   661)        Sy = -150.0D0 * 1000.0D0
   662)     else if (test_case == "planar_hydro_mtn_wave") then
   663)        Lx = 240.0D0 * 1000.0D0
   664)        Ly = 240.0D0 * 1000.0D0
   665)        Sx = 0.0D0 * 1000.0D0
   666)        Sy = 0.0D0 * 1000.0D0
   667)     else if (test_case == "planar_nonhydro_mtn_wave") then
   668)        Lx = 144.0D0 * 1000.0D0
   669)        Ly = 144.0D0 * 1000.0D0
   670)        Sx = 0.0D0 * 1000.0D0
   671)        Sy = 0.0D0 * 1000.0D0
   672)     else if (test_case == "planar_schar_mtn_wave") then
   673)        Lx = 100.0D0 * 1000.0D0
   674)        Ly = 100.0D0 * 1000.0D0
   675)        Sx = 0.0D0 * 1000.0D0
   676)        Sy = 0.0D0 * 1000.0D0
   677)     else if (test_case == "planar_density_current" .OR. test_case == "planar_moist_density_current") then
   678)        Lx = 51.2D0 * 1000.0D0
   679)        Ly = 51.2D0 * 1000.0D0
   680)        Sx = -25.6D0 * 1000.0D0
   681)        Sy = -25.6D0 * 1000.0D0
   682)     else if (test_case == "planar_rising_bubble" ) then
   683)        Lx = 2.0D0 * 10000.0D0
   684)        Ly = 2.0D0 * 10000.0D0
   685)        Sx = -10000.0D0
   686)        Sy = -10000.0D0
   687) ! THESE ARE WRONG AND NEED TO BE FIXED WHEN THESE CASES ARE ACTUALLY IMPLEMENTED....
   688) !else if (test_case == "planar_baroclinic_instab" .OR. test_case == "planar_moist_baroclinic_instab") then
   689) !       Lx = 5000.0D0 * 1000.0D0
   690) !       Ly = 5000.0D0 * 1000.0D0
   691) !       Sx = 0.0D0
   692) !       Sy = 0.0D0
   693) !    else if (test_case == "planar_tropical_cyclone") then
   694) !       Lx = 5000.0D0 * 1000.0D0
   695) !       Ly = 5000.0D0 * 1000.0D0
   696) !       Sx = 0.0D0
   697) !       Sy = 0.0D0
   698) !    else if (test_case == "planar_supercell") then
   699) !       Lx = 5000.0D0 * 1000.0D0
   700) !       Ly = 5000.0D0 * 1000.0D0
   701) !       Sx = 0.0D0
   702) !       Sy = 0.0D0
   703) 
   704)     endif
   705)     endif !if lx,ly,sx,sy are not set in nl
   706) 
   707)     if (test_case == "planar_rising_bubble" ) then
   708)        case_planar_bubble = .TRUE.
   709)     end if
   710) 
   711) end subroutine set_planar_defaults
   712) 
   713) end module control_mod

generated by
Intel(R) C++/Fortran Compiler code-coverage tool
Web-Page Owner: Nobody