LCOV - code coverage report
Current view: top level - dynamics/se - dyn_comp.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 664 997 66.6 %
Date: 2025-03-13 18:42:46 Functions: 12 17 70.6 %

          Line data    Source code
       1             : module dyn_comp
       2             : 
       3             : ! CAM interfaces to the SE Dynamical Core
       4             : 
       5             : use shr_kind_mod,           only: r8=>shr_kind_r8, shr_kind_cl
       6             : use physconst,              only: pi
       7             : use spmd_utils,             only: iam, masterproc
       8             : use constituents,           only: pcnst, cnst_get_ind, cnst_name, cnst_longname, &
       9             :                                   cnst_read_iv, qmin, cnst_type, tottnam,        &
      10             :                                   cnst_is_a_water_species
      11             : use cam_control_mod,        only: initial_run
      12             : use cam_initfiles,          only: initial_file_get_id, topo_file_get_id, pertlim
      13             : use phys_control,           only: use_gw_front, use_gw_front_igw
      14             : use dyn_grid,               only: ini_grid_name, timelevel, hvcoord, edgebuf, &
      15             :                                   ini_grid_hdim_name
      16             : 
      17             : use cam_grid_support,       only: cam_grid_id, cam_grid_get_gcid, &
      18             :                                   cam_grid_dimensions, &
      19             :                                   cam_grid_get_latvals, cam_grid_get_lonvals,  &
      20             :                                   max_hcoordname_len
      21             : use cam_map_utils,          only: iMap
      22             : 
      23             : use inic_analytic,          only: analytic_ic_active, analytic_ic_set_ic
      24             : use dyn_tests_utils,        only: vcoord=>vc_dry_pressure
      25             : 
      26             : use cam_history,            only: outfld, hist_fld_active, fieldname_len
      27             : use cam_history_support,    only: max_fieldname_len
      28             : use time_manager,           only: get_step_size
      29             : 
      30             : use ncdio_atm,              only: infld
      31             : use pio,                    only: file_desc_t, pio_seterrorhandling, PIO_BCAST_ERROR, &
      32             :                                   pio_inq_dimid, pio_inq_dimlen, PIO_NOERR
      33             : 
      34             : use infnan,                 only: isnan
      35             : use cam_logfile,            only: iulog
      36             : use cam_abortutils,         only: endrun
      37             : use shr_sys_mod,            only: shr_sys_flush
      38             : 
      39             : use parallel_mod,           only: par
      40             : use hybrid_mod,             only: hybrid_t
      41             : use dimensions_mod,         only: nelemd, nlev, np, npsq, ntrac, nc, fv_nphys
      42             : use dimensions_mod,         only: qsize, use_cslam
      43             : use element_mod,            only: element_t, elem_state_t
      44             : use fvm_control_volume_mod, only: fvm_struct
      45             : use se_dyn_time_mod,        only: nsplit
      46             : use edge_mod,               only: initEdgeBuffer, edgeVpack, edgeVunpack, FreeEdgeBuffer
      47             : use edgetype_mod,           only: EdgeBuffer_t
      48             : use bndry_mod,              only: bndry_exchange
      49             : 
      50             : implicit none
      51             : private
      52             : save
      53             : 
      54             : public ::          &
      55             :      dyn_import_t, &
      56             :      dyn_export_t, &
      57             :      dyn_readnl,   &
      58             :      dyn_register, &
      59             :      dyn_init,     &
      60             :      dyn_run,      &
      61             :      dyn_final
      62             : 
      63             : type dyn_import_t
      64             :   type (element_t),  pointer :: elem(:) => null()
      65             :   type (fvm_struct), pointer :: fvm(:) => null()
      66             : end type dyn_import_t
      67             : 
      68             : type dyn_export_t
      69             :   type (element_t),  pointer :: elem(:) => null()
      70             :   type (fvm_struct), pointer :: fvm(:) => null()
      71             : end type dyn_export_t
      72             : 
      73             : ! Namelist
      74             : logical, public, protected :: write_restart_unstruct
      75             : 
      76             : ! Frontogenesis indices
      77             : integer, public    :: frontgf_idx      = -1
      78             : integer, public    :: frontga_idx      = -1
      79             : 
      80             : interface read_dyn_var
      81             :   module procedure read_dyn_field_2d
      82             :   module procedure read_dyn_field_3d
      83             : end interface read_dyn_var
      84             : 
      85             : real(r8), parameter :: rad2deg = 180.0_r8 / pi
      86             : real(r8), parameter :: deg2rad = pi / 180.0_r8
      87             : real(r8), parameter :: rarea_sphere = 1.0_r8 / (4.0_r8*PI)
      88             : 
      89             : !===============================================================================
      90             : contains
      91             : !===============================================================================
      92             : 
      93        1536 : subroutine dyn_readnl(NLFileName)
      94             :    use air_composition,only: thermodynamic_active_species_num
      95             :    use namelist_utils, only: find_group_name
      96             :    use namelist_mod,   only: homme_set_defaults, homme_postprocess_namelist
      97             :    use units,          only: getunit, freeunit
      98             :    use spmd_utils,     only: masterproc, masterprocid, mpicom, npes
      99             :    use spmd_utils,     only: mpi_real8, mpi_integer, mpi_character, mpi_logical
     100             :    use dyn_grid,       only: se_write_grid_file, se_grid_filename, se_write_gll_corners
     101             :    use dp_mapping,     only: nphys_pts
     102             :    use native_mapping, only: native_mapping_readnl
     103             : 
     104             :    use control_mod,    only: hypervis_subcycle, hypervis_subcycle_sponge
     105             :    use control_mod,    only: hypervis_subcycle_q, statefreq, runtype
     106             :    use control_mod,    only: nu, nu_div, nu_p, nu_q, nu_top, qsplit, rsplit
     107             :    use control_mod,    only: vert_remap_uvTq_alg, vert_remap_tracer_alg
     108             :    use control_mod,    only: tstep_type, rk_stage_user
     109             :    use control_mod,    only: ftype, limiter_option, partmethod
     110             :    use control_mod,    only: topology, variable_nsplit
     111             :    use control_mod,    only: fine_ne, hypervis_power, hypervis_scaling
     112             :    use control_mod,    only: max_hypervis_courant, statediag_numtrac,refined_mesh
     113             :    use control_mod,    only: molecular_diff, pgf_formulation, dribble_in_rsplit_loop
     114             :    use control_mod,    only: sponge_del4_nu_div_fac, sponge_del4_nu_fac, sponge_del4_lev
     115             :    use dimensions_mod, only: ne, npart
     116             :    use dimensions_mod, only: large_Courant_incr
     117             :    use dimensions_mod, only: fvm_supercycling, fvm_supercycling_jet
     118             :    use dimensions_mod, only: kmin_jet, kmax_jet
     119             :    use params_mod,     only: SFCURVE
     120             :    use parallel_mod,   only: initmpi
     121             :    use thread_mod,     only: initomp, max_num_threads
     122             :    use thread_mod,     only: horz_num_threads, vert_num_threads, tracer_num_threads
     123             :    ! Dummy argument
     124             :    character(len=*), intent(in) :: NLFileName
     125             : 
     126             :    ! Local variables
     127             :    integer                      :: unitn, ierr,k
     128             : 
     129             :    ! SE Namelist variables
     130             :    integer                      :: se_fine_ne
     131             :    integer                      :: se_ftype
     132             :    integer                      :: se_statediag_numtrac
     133             :    integer                      :: se_fv_nphys
     134             :    real(r8)                     :: se_hypervis_power
     135             :    real(r8)                     :: se_hypervis_scaling
     136             :    integer                      :: se_hypervis_subcycle
     137             :    integer                      :: se_hypervis_subcycle_sponge
     138             :    integer                      :: se_hypervis_subcycle_q
     139             :    integer                      :: se_limiter_option
     140             :    real(r8)                     :: se_max_hypervis_courant
     141             :    character(len=SHR_KIND_CL)   :: se_mesh_file
     142             :    integer                      :: se_ne
     143             :    integer                      :: se_npes
     144             :    integer                      :: se_nsplit
     145             :    real(r8)                     :: se_nu
     146             :    real(r8)                     :: se_nu_div
     147             :    real(r8)                     :: se_nu_p
     148             :    real(r8)                     :: se_nu_top
     149             :    real(r8)                     :: se_sponge_del4_nu_fac
     150             :    real(r8)                     :: se_sponge_del4_nu_div_fac
     151             :    integer                      :: se_sponge_del4_lev
     152             :    integer                      :: se_qsplit
     153             :    logical                      :: se_refined_mesh
     154             :    integer                      :: se_rsplit
     155             :    integer                      :: se_statefreq
     156             :    integer                      :: se_tstep_type
     157             :    character(len=32)            :: se_vert_remap_T
     158             :    character(len=32)            :: se_vert_remap_uvTq_alg
     159             :    character(len=32)            :: se_vert_remap_tracer_alg
     160             :    integer                      :: se_horz_num_threads
     161             :    integer                      :: se_vert_num_threads
     162             :    integer                      :: se_tracer_num_threads
     163             :    logical                      :: se_write_restart_unstruct
     164             :    logical                      :: se_large_Courant_incr
     165             :    integer                      :: se_fvm_supercycling
     166             :    integer                      :: se_fvm_supercycling_jet
     167             :    integer                      :: se_kmin_jet
     168             :    integer                      :: se_kmax_jet
     169             :    real(r8)                     :: se_molecular_diff
     170             :    integer                      :: se_pgf_formulation
     171             :    integer                      :: se_dribble_in_rsplit_loop
     172             :    namelist /dyn_se_inparm/        &
     173             :       se_fine_ne,                  & ! For refined meshes
     174             :       se_ftype,                    & ! forcing type
     175             :       se_statediag_numtrac,        &
     176             :       se_fv_nphys,                 &
     177             :       se_hypervis_power,           &
     178             :       se_hypervis_scaling,         &
     179             :       se_hypervis_subcycle,        &
     180             :       se_hypervis_subcycle_sponge, &
     181             :       se_hypervis_subcycle_q,      &
     182             :       se_limiter_option,           &
     183             :       se_max_hypervis_courant,     &
     184             :       se_mesh_file,                & ! Refined mesh definition file
     185             :       se_ne,                       &
     186             :       se_npes,                     &
     187             :       se_nsplit,                   & ! # of dyn steps per physics timestep
     188             :       se_nu,                       &
     189             :       se_nu_div,                   &
     190             :       se_nu_p,                     &
     191             :       se_nu_top,                   &
     192             :       se_sponge_del4_nu_fac,       &
     193             :       se_sponge_del4_nu_div_fac,   &
     194             :       se_sponge_del4_lev,          &
     195             :       se_qsplit,                   &
     196             :       se_refined_mesh,             &
     197             :       se_rsplit,                   &
     198             :       se_statefreq,                & ! number of steps per printstate call
     199             :       se_tstep_type,               &
     200             :       se_vert_remap_T,             &
     201             :       se_vert_remap_uvTq_alg,      &
     202             :       se_vert_remap_tracer_alg,    &
     203             :       se_write_grid_file,          &
     204             :       se_grid_filename,            &
     205             :       se_write_gll_corners,        &
     206             :       se_horz_num_threads,         &
     207             :       se_vert_num_threads,         &
     208             :       se_tracer_num_threads,       &
     209             :       se_write_restart_unstruct,   &
     210             :       se_large_Courant_incr,       &
     211             :       se_fvm_supercycling,         &
     212             :       se_fvm_supercycling_jet,     &
     213             :       se_kmin_jet,                 &
     214             :       se_kmax_jet,                 &
     215             :       se_molecular_diff,           &
     216             :       se_pgf_formulation,          &
     217             :       se_dribble_in_rsplit_loop
     218             :    !--------------------------------------------------------------------------
     219             : 
     220             :    ! defaults for variables not set by build-namelist
     221        1536 :    se_fine_ne                  = -1
     222        1536 :    se_hypervis_power           = 0
     223        1536 :    se_hypervis_scaling         = 0
     224        1536 :    se_max_hypervis_courant     = 1.0e99_r8
     225        1536 :    se_mesh_file                = ''
     226        1536 :    se_npes                     = npes
     227        1536 :    se_write_restart_unstruct   = .false.
     228             : 
     229             :    ! Read the namelist (dyn_se_inparm)
     230        1536 :    call MPI_barrier(mpicom, ierr)
     231        1536 :    if (masterproc) then
     232           2 :       write(iulog, *) "dyn_readnl: reading dyn_se_inparm namelist..."
     233           2 :       unitn = getunit()
     234           2 :       open( unitn, file=trim(NLFileName), status='old' )
     235           2 :       call find_group_name(unitn, 'dyn_se_inparm', status=ierr)
     236           2 :       if (ierr == 0) then
     237           2 :          read(unitn, dyn_se_inparm, iostat=ierr)
     238           2 :          if (ierr /= 0) then
     239           0 :             call endrun('dyn_readnl: ERROR reading dyn_se_inparm namelist')
     240             :          end if
     241             :       end if
     242           2 :       close(unitn)
     243           2 :       call freeunit(unitn)
     244             :    end if
     245             : 
     246             :    ! Broadcast namelist values to all PEs
     247        1536 :    call MPI_bcast(se_fine_ne, 1, mpi_integer, masterprocid, mpicom, ierr)
     248        1536 :    call MPI_bcast(se_ftype, 1, mpi_integer, masterprocid, mpicom, ierr)
     249        1536 :    call MPI_bcast(se_statediag_numtrac, 1, mpi_integer, masterprocid, mpicom, ierr)
     250        1536 :    call MPI_bcast(se_hypervis_power, 1, mpi_real8, masterprocid, mpicom, ierr)
     251        1536 :    call MPI_bcast(se_hypervis_scaling, 1, mpi_real8, masterprocid, mpicom, ierr)
     252        1536 :    call MPI_bcast(se_hypervis_subcycle, 1, mpi_integer, masterprocid, mpicom, ierr)
     253        1536 :    call MPI_bcast(se_hypervis_subcycle_sponge, 1, mpi_integer, masterprocid, mpicom, ierr)
     254        1536 :    call MPI_bcast(se_hypervis_subcycle_q, 1, mpi_integer, masterprocid, mpicom, ierr)
     255        1536 :    call MPI_bcast(se_limiter_option, 1, mpi_integer, masterprocid, mpicom, ierr)
     256        1536 :    call MPI_bcast(se_max_hypervis_courant, 1, mpi_real8, masterprocid, mpicom, ierr)
     257        1536 :    call MPI_bcast(se_mesh_file, SHR_KIND_CL,  mpi_character, masterprocid, mpicom, ierr)
     258        1536 :    call MPI_bcast(se_ne, 1, mpi_integer, masterprocid, mpicom, ierr)
     259        1536 :    call MPI_bcast(se_npes, 1, mpi_integer, masterprocid, mpicom, ierr)
     260        1536 :    call MPI_bcast(se_nsplit, 1, mpi_integer, masterprocid, mpicom, ierr)
     261        1536 :    call MPI_bcast(se_nu, 1, mpi_real8, masterprocid, mpicom, ierr)
     262        1536 :    call MPI_bcast(se_nu_div, 1, mpi_real8, masterprocid, mpicom, ierr)
     263        1536 :    call MPI_bcast(se_nu_p, 1, mpi_real8, masterprocid, mpicom, ierr)
     264        1536 :    call MPI_bcast(se_nu_top, 1, mpi_real8, masterprocid, mpicom, ierr)
     265        1536 :    call MPI_bcast(se_sponge_del4_nu_fac, 1, mpi_real8, masterprocid, mpicom, ierr)
     266        1536 :    call MPI_bcast(se_sponge_del4_nu_div_fac, 1, mpi_real8, masterprocid, mpicom, ierr)
     267        1536 :    call MPI_bcast(se_sponge_del4_lev, 1, mpi_integer, masterprocid, mpicom, ierr)
     268        1536 :    call MPI_bcast(se_qsplit, 1, mpi_integer, masterprocid, mpicom, ierr)
     269        1536 :    call MPI_bcast(se_refined_mesh, 1, mpi_logical, masterprocid, mpicom, ierr)
     270        1536 :    call MPI_bcast(se_rsplit, 1, mpi_integer, masterprocid, mpicom, ierr)
     271        1536 :    call MPI_bcast(se_statefreq, 1, mpi_integer, masterprocid, mpicom, ierr)
     272        1536 :    call MPI_bcast(se_tstep_type, 1, mpi_integer, masterprocid, mpicom, ierr)
     273        1536 :    call MPI_bcast(se_vert_remap_T, 32, mpi_character, masterprocid, mpicom, ierr)
     274        1536 :    call MPI_bcast(se_vert_remap_uvTq_alg, 32, mpi_character, masterprocid, mpicom, ierr)
     275        1536 :    call MPI_bcast(se_vert_remap_tracer_alg, 32, mpi_character, masterprocid, mpicom, ierr)
     276        1536 :    call MPI_bcast(se_fv_nphys, 1, mpi_integer, masterprocid, mpicom, ierr)
     277        1536 :    call MPI_bcast(se_write_grid_file, 16,  mpi_character, masterprocid, mpicom, ierr)
     278        1536 :    call MPI_bcast(se_grid_filename, shr_kind_cl, mpi_character, masterprocid, mpicom, ierr)
     279        1536 :    call MPI_bcast(se_write_gll_corners, 1,  mpi_logical, masterprocid, mpicom, ierr)
     280        1536 :    call MPI_bcast(se_horz_num_threads, 1, MPI_integer, masterprocid, mpicom,ierr)
     281        1536 :    call MPI_bcast(se_vert_num_threads, 1, MPI_integer, masterprocid, mpicom,ierr)
     282        1536 :    call MPI_bcast(se_tracer_num_threads, 1, MPI_integer, masterprocid, mpicom,ierr)
     283        1536 :    call MPI_bcast(se_write_restart_unstruct, 1, mpi_logical, masterprocid, mpicom, ierr)
     284        1536 :    call MPI_bcast(se_large_Courant_incr, 1, mpi_logical, masterprocid, mpicom, ierr)
     285        1536 :    call MPI_bcast(se_fvm_supercycling, 1, mpi_integer, masterprocid, mpicom, ierr)
     286        1536 :    call MPI_bcast(se_fvm_supercycling_jet, 1, mpi_integer, masterprocid, mpicom, ierr)
     287        1536 :    call MPI_bcast(se_kmin_jet, 1, mpi_integer, masterprocid, mpicom, ierr)
     288        1536 :    call MPI_bcast(se_kmax_jet, 1, mpi_integer, masterprocid, mpicom, ierr)
     289        1536 :    call MPI_bcast(se_molecular_diff, 1, mpi_real8, masterprocid, mpicom, ierr)
     290        1536 :    call MPI_bcast(se_pgf_formulation, 1, mpi_integer, masterprocid, mpicom, ierr)
     291        1536 :    call MPI_bcast(se_dribble_in_rsplit_loop, 1, mpi_integer, masterprocid, mpicom, ierr)
     292        1536 :    if (se_npes <= 0) then
     293           0 :       call endrun('dyn_readnl: ERROR: se_npes must be > 0')
     294             :    end if
     295             : 
     296             :    ! Initialize the SE structure that holds the MPI decomposition information
     297        1536 :    par = initmpi(se_npes)
     298        1536 :    call initomp()
     299             : 
     300             : 
     301        1536 :    if (se_fvm_supercycling < 0) se_fvm_supercycling = se_rsplit
     302        1536 :    if (se_fvm_supercycling_jet < 0) se_fvm_supercycling_jet = se_rsplit
     303             : 
     304             :    ! Go ahead and enforce ne = 0 for refined mesh runs
     305        1536 :    if (se_refined_mesh) then
     306           0 :       se_ne = 0
     307             :    end if
     308             : 
     309             :    ! Set HOMME defaults
     310        1536 :    call homme_set_defaults()
     311             :    ! Set HOMME variables not in CAM's namelist but with different CAM defaults
     312        1536 :    partmethod               = SFCURVE
     313        1536 :    npart                    = se_npes
     314             :    ! CAM requires forward-in-time, subcycled dynamics
     315             :    ! RK2 3 stage tracers, sign-preserving conservative
     316        1536 :    rk_stage_user            = 3
     317        1536 :    topology                 = "cube"
     318             :    ! Finally, set the HOMME variables which have different names
     319        1536 :    fine_ne                  = se_fine_ne
     320        1536 :    ftype                    = se_ftype
     321        1536 :    statediag_numtrac        = MIN(se_statediag_numtrac,pcnst)
     322        1536 :    hypervis_power           = se_hypervis_power
     323        1536 :    hypervis_scaling         = se_hypervis_scaling
     324        1536 :    hypervis_subcycle        = se_hypervis_subcycle
     325        1536 :    if (hypervis_subcycle_sponge<0) then
     326           0 :      hypervis_subcycle_sponge = hypervis_subcycle
     327             :    else
     328        1536 :      hypervis_subcycle_sponge = se_hypervis_subcycle_sponge
     329             :    end if
     330        1536 :    hypervis_subcycle_q      = se_hypervis_subcycle_q
     331        1536 :    limiter_option           = se_limiter_option
     332        1536 :    max_hypervis_courant     = se_max_hypervis_courant
     333        1536 :    refined_mesh             = se_refined_mesh
     334        1536 :    ne                       = se_ne
     335        1536 :    nsplit                   = se_nsplit
     336        1536 :    nu                       = se_nu
     337        1536 :    nu_div                   = se_nu_div
     338        1536 :    nu_p                     = se_nu_p
     339        1536 :    nu_q                     = se_nu_p !for tracer-wind consistency nu_q must me equal to nu_p
     340        1536 :    nu_top                   = se_nu_top
     341        1536 :    sponge_del4_nu_fac       = se_sponge_del4_nu_fac
     342        1536 :    sponge_del4_nu_div_fac   = se_sponge_del4_nu_div_fac
     343        1536 :    sponge_del4_lev          = se_sponge_del4_lev
     344        1536 :    qsplit                   = se_qsplit
     345        1536 :    rsplit                   = se_rsplit
     346        1536 :    statefreq                = se_statefreq
     347        1536 :    tstep_type               = se_tstep_type
     348        1536 :    vert_remap_uvTq_alg      = set_vert_remap(se_vert_remap_T, se_vert_remap_uvTq_alg)
     349        1536 :    vert_remap_tracer_alg    = set_vert_remap(se_vert_remap_T, se_vert_remap_tracer_alg)
     350        1536 :    fv_nphys                 = se_fv_nphys
     351        1536 :    large_Courant_incr       = se_large_Courant_incr
     352        1536 :    fvm_supercycling         = se_fvm_supercycling
     353        1536 :    fvm_supercycling_jet     = se_fvm_supercycling_jet
     354        1536 :    kmin_jet                 = se_kmin_jet
     355        1536 :    kmax_jet                 = se_kmax_jet
     356        1536 :    variable_nsplit          = .false.
     357        1536 :    molecular_diff           = se_molecular_diff
     358        1536 :    pgf_formulation          = se_pgf_formulation
     359        1536 :    dribble_in_rsplit_loop   = se_dribble_in_rsplit_loop
     360        1536 :    if (fv_nphys > 0) then
     361             :       ! Use finite volume physics grid and CSLAM for tracer advection
     362        1536 :       nphys_pts = fv_nphys*fv_nphys
     363        1536 :       qsize = thermodynamic_active_species_num ! number tracers advected by GLL
     364        1536 :       ntrac = pcnst                            ! number tracers advected by CSLAM
     365        1536 :       use_cslam = .true.
     366             :    else
     367             :       ! Use GLL grid for physics and tracer advection
     368           0 :       nphys_pts = npsq
     369           0 :       qsize = pcnst
     370           0 :       ntrac = 0
     371           0 :       use_cslam = .false.
     372             :    end if
     373             : 
     374        1536 :    if (rsplit < 1) then
     375           0 :       call endrun('dyn_readnl: rsplit must be > 0')
     376             :    end if
     377             : 
     378             :    ! if restart or branch run
     379        1536 :    if (.not. initial_run) then
     380         768 :       runtype = 1
     381             :    end if
     382             : 
     383             :    ! HOMME wants 'none' to indicate no mesh file
     384        1536 :    if (len_trim(se_mesh_file) == 0) then
     385        1536 :       se_mesh_file = 'none'
     386        1536 :       if (se_refined_mesh) then
     387           0 :          call endrun('dyn_readnl ERROR: se_refined_mesh=.true. but no se_mesh_file')
     388             :       end if
     389             :    end if
     390        1536 :    call homme_postprocess_namelist(se_mesh_file, par)
     391             : 
     392             :    ! Set threading numbers to reasonable values
     393        1536 :    if ((se_horz_num_threads == 0) .and. (se_vert_num_threads == 0) .and. (se_tracer_num_threads == 0)) then
     394             :       ! The user has not set any threading values, choose defaults
     395        1536 :       se_horz_num_threads = 1
     396        1536 :       se_vert_num_threads = max_num_threads
     397        1536 :       se_tracer_num_threads = se_vert_num_threads
     398             :    end if
     399        1536 :    if (se_horz_num_threads < 1) then
     400           0 :       se_horz_num_threads = 1
     401             :    end if
     402        1536 :    if (se_vert_num_threads < 1) then
     403           0 :       se_vert_num_threads = 1
     404             :    end if
     405        1536 :    if (se_tracer_num_threads < 1) then
     406           0 :       se_tracer_num_threads = 1
     407             :    end if
     408        1536 :    horz_num_threads = se_horz_num_threads
     409        1536 :    vert_num_threads = se_vert_num_threads
     410        1536 :    tracer_num_threads = se_tracer_num_threads
     411             : 
     412        1536 :    write_restart_unstruct = se_write_restart_unstruct
     413             : 
     414        1536 :    if (se_kmin_jet<0            ) kmin_jet             = 1
     415        1536 :    if (se_kmax_jet<0            ) kmax_jet             = nlev
     416             : 
     417        1536 :    if (masterproc) then
     418           2 :       write(iulog, '(a,i0)')   'dyn_readnl: se_ftype                    = ',ftype
     419           2 :       write(iulog, '(a,i0)')   'dyn_readnl: se_statediag_numtrac        = ',statediag_numtrac
     420           2 :       write(iulog, '(a,i0)')   'dyn_readnl: se_hypervis_subcycle        = ',se_hypervis_subcycle
     421           2 :       write(iulog, '(a,i0)')   'dyn_readnl: se_hypervis_subcycle_sponge = ',se_hypervis_subcycle_sponge
     422           2 :       write(iulog, '(a,i0)')   'dyn_readnl: se_hypervis_subcycle_q      = ',se_hypervis_subcycle_q
     423           2 :       write(iulog, '(a,l4)')   'dyn_readnl: se_large_Courant_incr       = ',se_large_Courant_incr
     424           2 :       write(iulog, '(a,i0)')   'dyn_readnl: se_limiter_option           = ',se_limiter_option
     425           2 :       if (.not. se_refined_mesh) then
     426           2 :          write(iulog, '(a,i0)')'dyn_readnl: se_ne                       = ',se_ne
     427             :       end if
     428           2 :       write(iulog, '(a,i0)')   'dyn_readnl: se_npes                     = ',se_npes
     429           2 :       write(iulog, '(a,i0)')   'dyn_readnl: se_nsplit                   = ',se_nsplit
     430             :       !
     431             :       ! se_nu<0 then coefficients are set automatically in module global_norms_mod
     432             :       !
     433           2 :       if (se_nu_div>0) &
     434           0 :            write(iulog, '(a,e9.2)') 'dyn_readnl: se_nu                       = ',se_nu
     435           2 :       if (se_nu_div>0) &
     436           0 :            write(iulog, '(a,e9.2)') 'dyn_readnl: se_nu_div                   = ',se_nu_div
     437           2 :       if (se_nu_p>0) then
     438           0 :         write(iulog, '(a,e9.2)') 'dyn_readnl: se_nu_p                     = ',se_nu_p
     439           0 :         write(iulog, '(a)') 'Note that nu_q must be the same as nu_p for  mass / tracer inconsistency'
     440             :       end if
     441           2 :       write(iulog, '(a,e9.2)') 'dyn_readnl: se_nu_top                     = ',se_nu_top
     442           2 :       write(iulog, '(a,i0)')   'dyn_readnl: se_qsplit                     = ',se_qsplit
     443           2 :       write(iulog, '(a,i0)')   'dyn_readnl: se_rsplit                     = ',se_rsplit
     444           2 :       write(iulog, '(a,i0)')   'dyn_readnl: se_statefreq                  = ',se_statefreq
     445           2 :       write(iulog, '(a,i0)')   'dyn_readnl: se_tstep_type                 = ',se_tstep_type
     446           2 :       write(iulog, '(a,a)')    'dyn_readnl: se_vert_remap_T               = ',trim(se_vert_remap_T)
     447           2 :       write(iulog, '(a,a)')    'dyn_readnl: se_vert_remap_uvTq_alg        = ',trim(se_vert_remap_uvTq_alg)
     448           2 :       write(iulog, '(a,a)')    'dyn_readnl: se_vert_remap_tracer_alg      = ',trim(se_vert_remap_tracer_alg)
     449           2 :       write(iulog, '(a,i0)')   'dyn_readnl: se_fvm_supercycling           = ',fvm_supercycling
     450           2 :       write(iulog, '(a,i0)')   'dyn_readnl: se_fvm_supercycling_jet       = ',fvm_supercycling_jet
     451           2 :       write(iulog, '(a,i0)')   'dyn_readnl: se_kmin_jet                   = ',kmin_jet
     452           2 :       write(iulog, '(a,i0)')   'dyn_readnl: se_kmax_jet                   = ',kmax_jet
     453             : 
     454           2 :       write(iulog, *)   'dyn_readnl: se_sponge_del4_nu_fac         = ',se_sponge_del4_nu_fac
     455           2 :       if (se_sponge_del4_nu_fac < 0) write(iulog, '(a)')   ' (automatically set based on model top location)'
     456           2 :       write(iulog, *)   'dyn_readnl: se_sponge_del4_nu_div_fac     = ',se_sponge_del4_nu_div_fac
     457           2 :       if (se_sponge_del4_nu_div_fac < 0)  write(iulog, '(a)')   ' (automatically set based on model top location)'
     458           2 :       write(iulog, *)   'dyn_readnl: se_sponge_del4_lev            = ',se_sponge_del4_lev
     459           2 :       if (se_sponge_del4_lev < 0)  write(iulog, '(a)')   ' (automatically set based on model top location)'
     460             : 
     461           2 :       if (se_refined_mesh) then
     462           0 :          write(iulog, '(a)') 'dyn_readnl: Refined mesh simulation'
     463           0 :          write(iulog, '(a)') 'dyn_readnl: se_mesh_file = ',trim(se_mesh_file)
     464           0 :          if (hypervis_power /= 0) then
     465           0 :            write(iulog, '(a)') 'Using scalar viscosity (Zarzycki et al 2014 JClim)'
     466           0 :            write(iulog, '(a,e11.4)') 'dyn_readnl: se_hypervis_power = ',se_hypervis_power, ', (tensor hyperviscosity)'
     467           0 :            write(iulog, '(a,e11.4)') 'dyn_readnl: se_max_hypervis_courant = ',se_max_hypervis_courant
     468             :          end if
     469           0 :          if (hypervis_scaling /= 0) then
     470           0 :            write(iulog, '(a)') 'Using tensor viscosity (Guba et al., 2014)'
     471           0 :            write(iulog, '(a,e11.4)') 'dyn_readnl: se_hypervis_scaling = ',se_hypervis_scaling
     472             :          end if
     473             :       end if
     474             : 
     475           2 :       if (use_cslam) then
     476           2 :          write(iulog, '(a)') 'dyn_readnl: physics will run on FVM points; advection by CSLAM'
     477           2 :          write(iulog,'(a,i0)') 'dyn_readnl: se_fv_nphys = ', fv_nphys
     478             :       else
     479           0 :          write(iulog, '(a)') 'dyn_readnl: physics will run on SE GLL points'
     480             :       end if
     481           2 :       write(iulog, '(a,i0)') 'dyn_readnl: se_horz_num_threads = ',horz_num_threads
     482           2 :       write(iulog, '(a,i0)') 'dyn_readnl: se_vert_num_threads = ',vert_num_threads
     483           2 :       write(iulog, '(a,i0)') 'dyn_readnl: se_tracer_num_threads = ',tracer_num_threads
     484           2 :       if (trim(se_write_grid_file) == 'SCRIP') then
     485           0 :          write(iulog,'(2a)') "dyn_readnl: write SCRIP grid file = ", trim(se_grid_filename)
     486             :       else
     487           2 :          write(iulog,'(a)') "dyn_readnl: do not write grid file"
     488             :       end if
     489           2 :       write(iulog,'(a,l1)') 'dyn_readnl: write gll corners to SEMapping.nc = ', &
     490           4 :                             se_write_gll_corners
     491           2 :       write(iulog,'(a,l1)') 'dyn_readnl: write restart data on unstructured grid = ', &
     492           4 :                             se_write_restart_unstruct
     493             : 
     494           2 :       write(iulog, '(a,e9.2)') 'dyn_readnl: se_molecular_diff  = ', molecular_diff
     495             :    end if
     496             : 
     497        1536 :    call native_mapping_readnl(NLFileName)
     498             : 
     499             :    !---------------------------------------------------------------------------
     500             :    contains
     501             :    !---------------------------------------------------------------------------
     502             : 
     503        3072 :       integer function set_vert_remap( remap_T, remap_alg )
     504             : 
     505             :          ! Convert namelist input strings to the internally used integers.
     506             : 
     507             :          character(len=*), intent(in) :: remap_T    ! scheme for remapping temperature
     508             :          character(len=*), intent(in) :: remap_alg  ! remapping algorithm
     509             : 
     510             :          ! check valid remap_T values:
     511        3072 :          if (remap_T /= 'thermal_energy_over_P' .and. remap_T /= 'Tv_over_logP') then
     512           0 :             write(iulog,*)'set_vert_remap: invalid remap_T= ',trim(remap_T)
     513           0 :             call endrun('set_vert_remap: invalid remap_T')
     514             :          end if
     515             : 
     516             :          select case (remap_alg)
     517             :          case ('PPM_bc_mirror')
     518           0 :             set_vert_remap = 1
     519             :          case ('PPM_bc_PCoM')
     520           0 :             set_vert_remap = 2
     521             :          case ('PPM_bc_linear_extrapolation')
     522        1536 :             set_vert_remap = 10
     523             :          case ('FV3_PPM')
     524           0 :             if (remap_T == 'thermal_energy_over_P') then
     525             :                set_vert_remap = -4
     526             :             else
     527           0 :                set_vert_remap = -40
     528             :             end if
     529             :          case ('FV3_CS')
     530        1536 :             if (remap_T == 'thermal_energy_over_P') then
     531             :                set_vert_remap = -9
     532             :             else
     533           0 :                set_vert_remap = -90
     534             :             end if
     535             :          case ('FV3_CS_2dz_filter')
     536           0 :             if (remap_T == 'thermal_energy_over_P') then
     537             :                set_vert_remap = -10
     538             :             else
     539           0 :                set_vert_remap = -100
     540             :             end if
     541             :          case ('FV3_non_monotone_CS_2dz_filter')
     542           0 :             if (remap_T == 'thermal_energy_over_P') then
     543             :                set_vert_remap = -11
     544             :             else
     545           0 :                set_vert_remap = -110
     546             :             end if
     547             :          case default
     548           0 :             write(iulog,*)'set_vert_remap: invalid remap_alg= ',trim(remap_alg)
     549        3072 :             call endrun('set_vert_remap: invalid remap_alg')
     550             :          end select
     551             : 
     552        1536 :       end function set_vert_remap
     553             : 
     554             : end subroutine dyn_readnl
     555             : 
     556             : !=========================================================================================
     557             : 
     558        1536 : subroutine dyn_register()
     559             : 
     560             :    use physics_buffer,  only: pbuf_add_field, dtype_r8
     561             :    use ppgrid,          only: pcols, pver
     562             : 
     563             :    ! These fields are computed by the dycore and passed to the physics via the
     564             :    ! physics buffer.
     565             : 
     566        1536 :    if (use_gw_front .or. use_gw_front_igw) then
     567             :       call pbuf_add_field("FRONTGF", "global", dtype_r8, (/pcols,pver/),       &
     568        1536 :          frontgf_idx)
     569             :       call pbuf_add_field("FRONTGA", "global", dtype_r8, (/pcols,pver/),       &
     570        1536 :          frontga_idx)
     571             :    end if
     572             : 
     573        1536 : end subroutine dyn_register
     574             : 
     575             : !=========================================================================================
     576             : 
     577        3072 : subroutine dyn_init(dyn_in, dyn_out)
     578        1536 :    use prim_advance_mod,   only: prim_advance_init
     579             :    use dyn_grid,           only: elem, fvm
     580             :    use cam_pio_utils,      only: clean_iodesc_list
     581             :    use physconst,          only: cpair, pstd
     582             :    use air_composition,    only: thermodynamic_active_species_num, thermodynamic_active_species_idx
     583             :    use air_composition,    only: thermodynamic_active_species_idx_dycore
     584             :    use air_composition,    only: thermodynamic_active_species_liq_idx,thermodynamic_active_species_ice_idx
     585             :    use air_composition,    only: thermodynamic_active_species_liq_idx_dycore,thermodynamic_active_species_ice_idx_dycore
     586             :    use air_composition,    only: thermodynamic_active_species_liq_num, thermodynamic_active_species_ice_num
     587             :    use cam_history,        only: addfld, add_default, horiz_only, register_vector_field
     588             :    use gravity_waves_sources, only: gws_init
     589             : 
     590             :    use thread_mod,         only: horz_num_threads
     591             :    use hybrid_mod,         only: get_loop_ranges, config_thread_region
     592             :    use dimensions_mod,     only: nu_scale_top
     593             :    use dimensions_mod,     only: ksponge_end, kmvis_ref, kmcnd_ref,rho_ref,km_sponge_factor
     594             :    use dimensions_mod,     only: cnst_name_gll, cnst_longname_gll
     595             :    use dimensions_mod,     only: irecons_tracer_lev, irecons_tracer, kord_tr, kord_tr_cslam
     596             :    use prim_driver_mod,    only: prim_init2
     597             :    use control_mod,        only: molecular_diff, nu_top
     598             :    use test_fvm_mapping,   only: test_mapping_addfld
     599             :    use phys_control,       only: phys_getopts
     600             :    use cam_thermo,         only: get_molecular_diff_coef_reference
     601             :    use control_mod,        only: vert_remap_uvTq_alg, vert_remap_tracer_alg
     602             :    use std_atm_profile,    only: std_atm_height
     603             :    use dyn_tests_utils,    only: vc_dycore, vc_dry_pressure, string_vc, vc_str_lgth
     604             :    use cam_budget,         only: cam_budget_em_snapshot, cam_budget_em_register, thermo_budget_history
     605             : 
     606             :    ! Dummy arguments:
     607             :    type(dyn_import_t), intent(out) :: dyn_in
     608             :    type(dyn_export_t), intent(out) :: dyn_out
     609             : 
     610             :    ! Local variables
     611             :    integer             :: nets, nete, ie, k, kmol_end, mfound
     612             :    real(r8), parameter :: Tinit = 300.0_r8
     613             :    real(r8)            :: press(1), ptop, tref,z(1)
     614             : 
     615             :    type(hybrid_t)      :: hybrid
     616             : 
     617             :    integer :: ixcldice, ixcldliq
     618             :    integer :: m_cnst, m
     619             : 
     620             :    ! variables for initializing energy and axial angular momentum diagnostics
     621             :    integer, parameter                         :: num_stages = 14
     622             :    character (len = 4), dimension(num_stages) :: stage         = (/"dED","dAF","dBD","dBL","dAL","dAD","dAR","dBF","dBH","dCH","dAH","dBS","dAS","p2d"/)
     623             :    character (len = 70),dimension(num_stages) :: stage_txt = (/&
     624             :       " end of previous dynamics                           ",& !dED
     625             :       " from previous remapping or state passed to dynamics",& !dAF - state in beginning of nsplit loop
     626             :       " state after applying CAM forcing                   ",& !dBD - state after applyCAMforcing
     627             :       " before floating dynamics                           ",& !dBL
     628             :       " after floating dynamics                            ",& !dAL
     629             :       " before vertical remapping                          ",& !dAD - state before vertical remapping
     630             :       " after vertical remapping                           ",& !dAR - state at end of nsplit loop
     631             :       " state passed to parameterizations                  ",& !dBF
     632             :       " state before hypervis                              ",& !dBH
     633             :       " state after hypervis but before adding heating term",& !dCH
     634             :       " state after hypervis                               ",& !dAH
     635             :       " state before sponge layer diffusion                ",& !dBS - state before sponge del2
     636             :       " state after sponge layer diffusion                 ",& !dAS - state after sponge del2
     637             :       " phys2dyn mapping errors (requires ftype-1)         " & !p2d - for assessing phys2dyn mapping errors
     638             :       /)
     639             : 
     640             :    integer :: istage
     641             :    character (len=vc_str_lgth) :: vc_str
     642             : 
     643             :    logical :: history_budget        ! output tendencies and state variables for budgets
     644             :    integer :: budget_hfile_num
     645             : 
     646             :    character(len=*), parameter :: sub = 'dyn_init'
     647             : 
     648             :    real(r8) :: km_sponge_factor_local(nlev+1)
     649             :    !----------------------------------------------------------------------------
     650        1536 :    vc_dycore = vc_dry_pressure
     651        1536 :    if (masterproc) then
     652           2 :      call string_vc(vc_dycore,vc_str)
     653           2 :      write(iulog,*) sub//': vertical coordinate dycore   : ',trim(vc_str)
     654             :    end if
     655             :    ! Now allocate and set condenstate vars
     656        4608 :    allocate(cnst_name_gll(qsize))     ! constituent names for gll tracers
     657        4608 :    allocate(cnst_longname_gll(qsize)) ! long name of constituents for gll tracers
     658             : 
     659        4608 :    allocate(kord_tr(qsize))
     660       10752 :    kord_tr(:) = vert_remap_tracer_alg
     661        1536 :    if (use_cslam) then
     662        4608 :      allocate(kord_tr_cslam(ntrac))
     663       64512 :      kord_tr_cslam(:) = vert_remap_tracer_alg
     664             :    end if
     665             : 
     666             : 
     667       10752 :    do m=1,qsize
     668             :      !
     669             :      ! The "_gll" index variables below are used to keep track of condensate-loading tracers
     670             :      ! since they are not necessarily indexed contiguously and not necessarily in the same
     671             :      ! order (physics is in charge of the order)
     672             :      !
     673             :      ! if running with CSLAM then the SE (gll) condensate-loading water tracers are always
     674             :      ! indexed contiguously (q,cldliq,cldice,rain,snow,graupel) - see above
     675             :      !
     676             :      ! CSLAM tracers are always indexed as in physics
     677             :      ! of no CSLAM then SE tracers are always indexed as in physics
     678             :      !
     679       10752 :      if (use_cslam) then
     680             :        !
     681             :        ! note that in this case qsize = thermodynamic_active_species_num
     682             :        !
     683        9216 :        thermodynamic_active_species_idx_dycore(m) = m
     684        9216 :        kord_tr_cslam(thermodynamic_active_species_idx(m)) = vert_remap_uvTq_alg
     685        9216 :        kord_tr(m)                                 = vert_remap_uvTq_alg
     686        9216 :        cnst_name_gll    (m)                       = cnst_name    (thermodynamic_active_species_idx(m))
     687        9216 :        cnst_longname_gll(m)                       = cnst_longname(thermodynamic_active_species_idx(m))
     688             :      else
     689             :        !
     690             :        ! if not running with CSLAM then the condensate-loading water tracers are not necessarily
     691             :        ! indexed contiguously (are indexed as in physics)
     692             :        !
     693           0 :        if (m.le.thermodynamic_active_species_num) then
     694           0 :          thermodynamic_active_species_idx_dycore(m) = thermodynamic_active_species_idx(m)
     695           0 :          kord_tr(thermodynamic_active_species_idx_dycore(m)) = vert_remap_uvTq_alg
     696             :        end if
     697           0 :        cnst_name_gll    (m)                = cnst_name    (m)
     698           0 :        cnst_longname_gll(m)                = cnst_longname(m)
     699             :      end if
     700             :    end do
     701             : 
     702        4608 :    do m=1,thermodynamic_active_species_liq_num
     703        3072 :      if (use_cslam) then
     704       21504 :        do mfound=1,qsize
     705       21504 :          if (TRIM(cnst_name(thermodynamic_active_species_liq_idx(m)))==TRIM(cnst_name_gll(mfound))) then
     706        3072 :            thermodynamic_active_species_liq_idx_dycore(m) = mfound
     707             :          end if
     708             :        end do
     709             :      else
     710           0 :        thermodynamic_active_species_liq_idx_dycore(m) = thermodynamic_active_species_liq_idx(m)
     711             :      end if
     712        4608 :      if (masterproc) then
     713           4 :        write(iulog,*) sub//": m,thermodynamic_active_species_idx_liq_dycore: ",m,thermodynamic_active_species_liq_idx_dycore(m)
     714             :      end if
     715             :    end do
     716        6144 :    do m=1,thermodynamic_active_species_ice_num
     717        4608 :      if (use_cslam) then
     718       32256 :        do mfound=1,qsize
     719       32256 :          if (TRIM(cnst_name(thermodynamic_active_species_ice_idx(m)))==TRIM(cnst_name_gll(mfound))) then
     720        4608 :            thermodynamic_active_species_ice_idx_dycore(m) = mfound
     721             :          end if
     722             :        end do
     723             :      else
     724           0 :        thermodynamic_active_species_ice_idx_dycore(m) = thermodynamic_active_species_ice_idx(m)
     725             :      end if
     726        6144 :      if (masterproc) then
     727           6 :        write(iulog,*) sub//": m,thermodynamic_active_species_idx_ice_dycore: ",m,thermodynamic_active_species_ice_idx_dycore(m)
     728             :      end if
     729             :    end do
     730             : 
     731             :    !
     732             :    ! Initialize the import/export objects
     733             :    !
     734        1536 :    if(iam < par%nprocs) then
     735        1536 :      dyn_in%elem  => elem
     736        1536 :      dyn_in%fvm   => fvm
     737             : 
     738        1536 :      dyn_out%elem => elem
     739        1536 :      dyn_out%fvm  => fvm
     740             :    else
     741           0 :      nullify(dyn_in%elem)
     742           0 :      nullify(dyn_in%fvm)
     743           0 :      nullify(dyn_out%elem)
     744           0 :      nullify(dyn_out%fvm)
     745             :    end if
     746             : 
     747        1536 :    call set_phis(dyn_in)
     748             : 
     749        1536 :    if (initial_run) then
     750         768 :      call read_inidat(dyn_in)
     751         768 :      call clean_iodesc_list()
     752             :    end if
     753             :    !
     754             :    ! initialize diffusion in dycore
     755             :    !
     756        1536 :    kmol_end = 0
     757        1536 :    if (molecular_diff>0) then
     758             :      !
     759             :      ! molecular diffusion and thermal conductivity reference values
     760             :      !
     761           0 :      if (masterproc) write(iulog,*) sub//": initialize molecular diffusion reference profiles"
     762           0 :      tref = 1000._r8     !mean value at model top for solar max
     763           0 :      km_sponge_factor = molecular_diff
     764           0 :      km_sponge_factor_local = molecular_diff
     765             :      !
     766             :      ! get rho, kmvis and kmcnd at mid-levels
     767             :      !
     768             :      call get_molecular_diff_coef_reference(tref,&
     769             :           (hvcoord%hyam(:)+hvcoord%hybm(:))*hvcoord%ps0,km_sponge_factor,&
     770           0 :           kmvis_ref,kmcnd_ref,rho_ref)
     771             : 
     772           0 :      if (masterproc) then
     773           0 :         write(iulog,*) "Molecular viscosity and thermal conductivity reference profile"
     774           0 :         write(iulog,*) "k, p, z, km_sponge_factor, kmvis_ref/rho_ref, kmcnd_ref/(cp*rho_ref):"
     775             :      end if
     776           0 :      do k=1,nlev
     777             :        ! only apply molecular viscosity where viscosity is > 1000 m/s^2
     778           0 :        if (MIN(kmvis_ref(k)/rho_ref(k),kmcnd_ref(k)/(cpair*rho_ref(k)))>1000.0_r8) then
     779           0 :          if (masterproc) then
     780           0 :            press = hvcoord%hyam(k)*hvcoord%ps0+hvcoord%hybm(k)*pstd
     781           0 :            call std_atm_height(press,z)
     782           0 :            write(iulog,'(i3,5e11.4)') k,press, z,km_sponge_factor(k),kmvis_ref(k)/rho_ref(k),kmcnd_ref(k)/(cpair*rho_ref(k))
     783             :          end if
     784           0 :          kmol_end = k
     785             :        else
     786           0 :          kmvis_ref(k) = 1.0_r8
     787           0 :          kmcnd_ref(k) = 1.0_r8
     788             :        end if
     789             :      end do
     790             :    else
     791             :      ! -1.0E6 is an arbitrary unrealistic value.  But it is used in the calculation
     792             :      ! of a diagnostic quantity in global_norms_mod so can't be set to huge or nan.
     793      144384 :      kmvis_ref(:) = -1.0E6_r8
     794      144384 :      kmcnd_ref(:) = -1.0E6_r8
     795      144384 :      rho_ref(:)   = -1.0E6_r8
     796             :    end if
     797             :    !
     798      144384 :    irecons_tracer_lev(:) = irecons_tracer !use high-order CSLAM in all layers
     799             :    !
     800             :    ! compute scaling of traditional sponge layer damping (following cd_core.F90 in CAM-FV)
     801             :    !
     802        1536 :    nu_scale_top(:) = 0.0_r8
     803        1536 :    if (nu_top>0) then
     804        1536 :       ptop  = hvcoord%hyai(1)*hvcoord%ps0
     805        1536 :       if (ptop>300.0_r8) then
     806             :          !
     807             :          ! for low tops the tanh formulae below makes the sponge excessively deep
     808             :          !
     809           0 :          nu_scale_top(1) = 4.0_r8
     810           0 :          nu_scale_top(2) = 2.0_r8
     811           0 :          nu_scale_top(3) = 1.0_r8
     812           0 :          ksponge_end = 3
     813        1536 :       else if (ptop>100.0_r8) then
     814             :          !
     815             :          ! CAM6 top (~225 Pa) or CAM7 low top
     816             :          !
     817             :          ! For backwards compatibility numbers below match tanh profile
     818             :          ! used in FV
     819             :          !
     820           0 :          nu_scale_top(1) = 4.4_r8
     821           0 :          nu_scale_top(2) = 1.3_r8
     822           0 :          nu_scale_top(3) = 3.9_r8
     823           0 :          ksponge_end = 3
     824        1536 :       else if (ptop>1e-1_r8) then
     825             :          !
     826             :          ! CAM7 FMT
     827             :          !
     828        1536 :          nu_scale_top(1) = 3.0_r8
     829        1536 :          nu_scale_top(2) = 1.0_r8
     830        1536 :          nu_scale_top(3) = 0.1_r8
     831        1536 :          nu_scale_top(4) = 0.05_r8
     832        1536 :          ksponge_end = 4
     833           0 :       else if (ptop>1e-4_r8) then
     834             :          !
     835             :          ! WACCM and WACCM-x
     836             :          !
     837           0 :          nu_scale_top(1) = 5.0_r8
     838           0 :          nu_scale_top(2) = 5.0_r8
     839           0 :          nu_scale_top(3) = 5.0_r8
     840           0 :          nu_scale_top(4) = 2.0_r8
     841           0 :          nu_scale_top(5) = 1.0_r8
     842           0 :          nu_scale_top(6) = 0.1_r8
     843           0 :          ksponge_end = 6
     844             :       end if
     845             :    else
     846           0 :       ksponge_end = 0
     847             :    end if
     848        1536 :    ksponge_end = MAX(MAX(ksponge_end,1),kmol_end)
     849        1536 :    if (masterproc) then
     850           2 :      write(iulog,*) sub//": ksponge_end = ",ksponge_end
     851           2 :      write(iulog,*) sub//": sponge layer Laplacian damping"
     852           2 :      write(iulog,*) "k, p, z, nu_scale_top, nu (actual Laplacian damping coefficient)"
     853           2 :      if (nu_top>0) then
     854          12 :        do k=1,ksponge_end+1
     855          20 :          press = (hvcoord%hyam(k)+hvcoord%hybm(k))*hvcoord%ps0
     856          10 :          call std_atm_height(press,z)
     857          20 :          write(iulog,'(i3,4e11.4)') k,press,z,&
     858          32 :               nu_scale_top(k),nu_scale_top(k)*nu_top
     859             :        end do
     860             :      end if
     861             :    end if
     862             : 
     863        1536 :    if (iam < par%nprocs) then
     864        1536 :       call prim_advance_init(par,elem)
     865             :       !$OMP PARALLEL NUM_THREADS(horz_num_threads), DEFAULT(SHARED), PRIVATE(hybrid,nets,nete)
     866        1536 :       hybrid = config_thread_region(par,'horizontal')
     867        1536 :       call get_loop_ranges(hybrid, ibeg=nets, iend=nete)
     868        1536 :       call prim_init2(elem, fvm, hybrid, nets, nete, TimeLevel, hvcoord)
     869             :       !$OMP END PARALLEL
     870             : 
     871        1536 :       if (use_gw_front .or. use_gw_front_igw) call gws_init(elem)
     872             :    end if  ! iam < par%nprocs
     873             : 
     874        3072 :    call addfld ('nu_kmvis',   (/ 'lev' /), 'A', '', 'Molecular viscosity Laplacian coefficient'            , gridname='GLL')
     875        3072 :    call addfld ('nu_kmcnd',   (/ 'lev' /), 'A', '', 'Thermal conductivity Laplacian coefficient'           , gridname='GLL')
     876        3072 :    call addfld ('nu_kmcnd_dp',(/ 'lev' /), 'A', '', 'Thermal conductivity like Laplacian coefficient on dp', gridname='GLL')
     877             : 
     878             : 
     879             :    ! Forcing from physics on the GLL grid
     880        3072 :    call addfld ('FU',  (/ 'lev' /), 'A', 'm/s2', 'Zonal wind forcing term on GLL grid',     gridname='GLL')
     881        3072 :    call addfld ('FV',  (/ 'lev' /), 'A', 'm/s2', 'Meridional wind forcing term on GLL grid',gridname='GLL')
     882        1536 :    call register_vector_field('FU', 'FV')
     883        3072 :    call addfld ('FT',  (/ 'lev' /), 'A', 'K/s', 'Temperature forcing term on GLL grid',gridname='GLL')
     884             : 
     885             :    ! Tracer forcing on fvm (CSLAM) grid and internal CSLAM pressure fields
     886        1536 :    if (use_cslam) then
     887       64512 :       do m = 1, ntrac
     888       62976 :          call addfld (trim(cnst_name(m))//'_fvm',  (/ 'lev' /), 'I', 'kg/kg',   &
     889      188928 :             trim(cnst_longname(m)), gridname='FVM')
     890             : 
     891       62976 :          call addfld ('F'//trim(cnst_name(m))//'_fvm',  (/ 'lev' /), 'I', 'kg/kg/s',   &
     892       62976 :             trim(cnst_longname(m))//' mixing ratio forcing term (q_new-q_old) on fvm grid', &
     893      253440 :             gridname='FVM')
     894             :       end do
     895             : 
     896        3072 :       call addfld ('dp_fvm' ,(/ 'lev' /), 'I', 'Pa','CSLAM Pressure level thickness', gridname='FVM')
     897        1536 :       call addfld ('PSDRY_fvm',horiz_only, 'I','Pa','CSLAM dry surface pressure'    , gridname='FVM')
     898             :    end if
     899             : 
     900       10752 :    do m_cnst = 1, qsize
     901           0 :      call addfld ('F'//trim(cnst_name_gll(m_cnst))//'_gll',  (/ 'lev' /), 'I', 'kg/kg/s',   &
     902       19968 :           trim(cnst_longname_gll(m_cnst))//' mixing ratio forcing term (q_new-q_old) on GLL grid', gridname='GLL')
     903             :    end do
     904             : 
     905             :    ! Energy diagnostics and axial angular momentum diagnostics
     906        1536 :    call addfld ('ABS_dPSdt',  horiz_only, 'A', 'Pa/s', 'Absolute surface pressure tendency',gridname='GLL')
     907             : 
     908        1536 :    if (use_cslam) then
     909             : #ifdef waccm_debug
     910             :      call addfld ('CSLAM_gamma',  (/ 'lev' /), 'A', '', 'Courant number from CSLAM',     gridname='FVM')
     911             : #endif
     912        1536 :      call addfld ('WV_PDC',   horiz_only, 'A', 'kg/m2','Total column water vapor lost in physics-dynamics coupling',gridname='FVM')
     913        1536 :      call addfld ('WL_PDC',   horiz_only, 'A', 'kg/m2','Total column cloud water lost in physics-dynamics coupling',gridname='FVM')
     914        1536 :      call addfld ('WI_PDC',   horiz_only, 'A', 'kg/m2','Total column cloud ice lost in physics-dynamics coupling'  ,gridname='FVM')
     915        1536 :      call addfld ('TT_PDC',   horiz_only, 'A', 'kg/m2','Total column test tracer lost in physics-dynamics coupling',gridname='FVM')
     916             :    else
     917           0 :      call addfld ('WV_PDC',   horiz_only, 'A', 'kg/m2','Total column water vapor lost in physics-dynamics coupling',gridname='GLL')
     918           0 :      call addfld ('WL_PDC',   horiz_only, 'A', 'kg/m2','Total column cloud water lost in physics-dynamics coupling',gridname='GLL')
     919           0 :      call addfld ('WI_PDC',   horiz_only, 'A', 'kg/m2','Total column cloud ice lost in physics-dynamics coupling'  ,gridname='GLL')
     920           0 :      call addfld ('TT_PDC',   horiz_only, 'A', 'kg/m2','Total column test tracer lost in physics-dynamics coupling',gridname='GLL')
     921             :    end if
     922             : 
     923        1536 :    if (thermo_budget_history) then
     924             :       ! Register stages for budgets
     925           0 :       do istage = 1, num_stages
     926           0 :          call cam_budget_em_snapshot(TRIM(ADJUSTL(stage(istage))), 'dyn', &
     927           0 :               longname=TRIM(ADJUSTL(stage_txt(istage))))
     928             :       end do
     929             :       !
     930             :       ! Register tendency (difference) budgets
     931             :       !
     932             :       call cam_budget_em_register('dEdt_floating_dyn'   ,'dAL','dBL','dyn','dif', &
     933           0 :                       longname="dE/dt floating dynamics (dAL-dBL)"               )
     934             :       call cam_budget_em_register('dEdt_vert_remap'     ,'dAR','dAD','dyn','dif', &
     935           0 :                       longname="dE/dt vertical remapping (dAR-dAD)"              )
     936             :       call cam_budget_em_register('dEdt_phys_tot_in_dyn','dBD','dAF','dyn','dif', &
     937           0 :                       longname="dE/dt physics tendency in dynamics (dBD-dAF)"    )
     938             :       call cam_budget_em_register('dEdt_del4'          ,'dCH','dBH','dyn','dif', &
     939           0 :                       longname="dE/dt del4 (dCH-dBH)"                            )
     940             :       call cam_budget_em_register('dEdt_del4_fric_heat','dAH','dCH','dyn','dif', &
     941           0 :                       longname="dE/dt del4 frictional heating (dAH-dCH)"         )
     942             :       call cam_budget_em_register('dEdt_del4_tot'      ,'dAH','dBH','dyn','dif', &
     943           0 :                       longname="dE/dt del4 + del4 frictional heating (dAH-dBH)"  )
     944             :       call cam_budget_em_register('dEdt_del2_sponge'   ,'dAS','dBS','dyn','dif', &
     945           0 :                       longname="dE/dt del2 sponge (dAS-dBS)"                     )
     946             :       !
     947             :       ! Register derived budgets
     948             :       !
     949             :       call cam_budget_em_register('dEdt_dycore'        ,'dEdt_floating_dyn','dEdt_vert_remap'   ,'dyn','sum', &
     950           0 :                       longname="dE/dt adiabatic dynamics"                              )
     951             :       call cam_budget_em_register('dEdt_del2_del4_tot' ,'dEdt_del4_tot'    ,'dEdt_del2_sponge'  ,'dyn','sum', &
     952           0 :                       longname="dE/dt explicit diffusion total"                        )
     953             :       call cam_budget_em_register('dEdt_residual'      ,'dEdt_floating_dyn','dEdt_del2_del4_tot','dyn','dif',&
     954           0 :                       longname="dE/dt residual (dEdt_floating_dyn-dEdt_del2_del4_tot)" )
     955             :    end if
     956             :    !
     957             :    ! add dynamical core tracer tendency output
     958             :    !
     959        1536 :    if (use_cslam) then
     960       64512 :      do m = 1, pcnst
     961      125952 :        call addfld(tottnam(m),(/ 'lev' /),'A','kg/kg/s',trim(cnst_name(m))//' horz + vert',  &
     962      253440 :             gridname='FVM')
     963             :      end do
     964             :    else
     965           0 :      do m = 1, pcnst
     966           0 :        call addfld(tottnam(m),(/ 'lev' /),'A','kg/kg/s',trim(cnst_name(m))//' horz + vert',  &
     967           0 :             gridname='GLL')
     968             :      end do
     969             :    end if
     970        1536 :    call phys_getopts(history_budget_out=history_budget, history_budget_histfile_num_out=budget_hfile_num)
     971        1536 :    if ( history_budget ) then
     972           0 :       call cnst_get_ind('CLDLIQ', ixcldliq)
     973           0 :       call cnst_get_ind('CLDICE', ixcldice)
     974           0 :       call add_default(tottnam(       1), budget_hfile_num, ' ')
     975           0 :       call add_default(tottnam(ixcldliq), budget_hfile_num, ' ')
     976           0 :       call add_default(tottnam(ixcldice), budget_hfile_num, ' ')
     977             :    end if
     978             : 
     979        1536 :    call test_mapping_addfld
     980        3072 : end subroutine dyn_init
     981             : 
     982             : !=========================================================================================
     983             : 
     984       14592 : subroutine dyn_run(dyn_state)
     985        1536 :    use air_composition,  only: thermodynamic_active_species_num, dry_air_species_num
     986             :    use air_composition,  only: thermodynamic_active_species_idx_dycore
     987             :    use prim_driver_mod,  only: prim_run_subcycle
     988             :    use dimensions_mod,   only: cnst_name_gll
     989             :    use se_dyn_time_mod,  only: tstep, nsplit, timelevel_qdp, tevolve
     990             :    use hybrid_mod,       only: config_thread_region, get_loop_ranges
     991             :    use control_mod,      only: qsplit, rsplit, ftype_conserve
     992             :    use thread_mod,       only: horz_num_threads
     993             : 
     994             :    type(dyn_export_t), intent(inout) :: dyn_state
     995             : 
     996             :    type(hybrid_t) :: hybrid
     997             :    integer        :: tl_f
     998             :    integer        :: n
     999             :    integer        :: nets, nete
    1000             :    integer        :: i, ie, j, k, m, nq, m_cnst
    1001             :    integer        :: n0_qdp, nsplit_local
    1002             :    logical        :: ldiag
    1003             : 
    1004             :    real(r8) :: ftmp(npsq,nlev,3)
    1005             :    real(r8) :: dtime
    1006             :    real(r8) :: rec2dt, pdel
    1007             : 
    1008       14592 :    real(r8), allocatable, dimension(:,:,:) :: ps_before
    1009       14592 :    real(r8), allocatable, dimension(:,:,:) :: abs_ps_tend
    1010       29184 :    real (kind=r8)                          :: omega_cn(2,nelemd) !min and max of vertical Courant number
    1011             :    !----------------------------------------------------------------------------
    1012             : 
    1013             : #ifdef debug_coupling
    1014             :    return
    1015             : #endif
    1016             : 
    1017       14592 :    nsplit_local = nsplit
    1018       14592 :    tevolve = 0._r8
    1019             : 
    1020       14592 :    if (iam >= par%nprocs) return
    1021             : 
    1022       14592 :    ldiag = hist_fld_active('ABS_dPSdt')
    1023       14592 :    if (ldiag) then
    1024           0 :       allocate(ps_before(np,np,nelemd))
    1025           0 :       allocate(abs_ps_tend(np,np,nelemd))
    1026             : 
    1027             :    end if
    1028             : 
    1029             :    !$OMP PARALLEL NUM_THREADS(horz_num_threads), DEFAULT(SHARED), PRIVATE(hybrid,nets,nete,n,ie,m,i,j,k,ftmp)
    1030       14592 :    hybrid = config_thread_region(par,'horizontal')
    1031       14592 :    call get_loop_ranges(hybrid, ibeg=nets, iend=nete)
    1032             : 
    1033       14592 :    dtime = get_step_size()
    1034       14592 :    rec2dt = 1._r8/dtime
    1035             : 
    1036       14592 :    tl_f = TimeLevel%n0   ! timelevel which was adjusted by physics
    1037       14592 :    call TimeLevel_Qdp(TimeLevel, qsplit, n0_qdp)!get n0_qdp for diagnostics call
    1038             : 
    1039             :    ! output physics forcing
    1040       14592 :    if (hist_fld_active('FU') .or. hist_fld_active('FV') .or.hist_fld_active('FT')) then
    1041           0 :       do ie = nets, nete
    1042           0 :          do k = 1, nlev
    1043           0 :             do j = 1, np
    1044           0 :                do i = 1, np
    1045           0 :                   ftmp(i+(j-1)*np,k,1) = dyn_state%elem(ie)%derived%FM(i,j,1,k)
    1046           0 :                   ftmp(i+(j-1)*np,k,2) = dyn_state%elem(ie)%derived%FM(i,j,2,k)
    1047           0 :                   ftmp(i+(j-1)*np,k,3) = dyn_state%elem(ie)%derived%FT(i,j,k)
    1048             :                end do
    1049             :             end do
    1050             :          end do
    1051             : 
    1052           0 :          call outfld('FU', ftmp(:,:,1), npsq, ie)
    1053           0 :          call outfld('FV', ftmp(:,:,2), npsq, ie)
    1054           0 :          call outfld('FT', ftmp(:,:,3), npsq, ie)
    1055             :       end do
    1056             :    end if
    1057             : 
    1058      102144 :    do m = 1, qsize
    1059      102144 :      if (hist_fld_active('F'//trim(cnst_name_gll(m))//'_gll')) then
    1060           0 :        do ie = nets, nete
    1061           0 :          call outfld('F'//trim(cnst_name_gll(m))//'_gll',&
    1062           0 :               RESHAPE(dyn_state%elem(ie)%derived%FQ(:,:,:,m), (/np*np,nlev/)), npsq, ie)
    1063             :        end do
    1064             :      end if
    1065             :    end do
    1066             : 
    1067             :    ! convert elem(ie)%derived%fq to mass tendency
    1068       14592 :    if (.not.use_cslam) then
    1069           0 :      do ie = nets, nete
    1070           0 :        do m = 1, qsize
    1071           0 :          do k = 1, nlev
    1072           0 :            do j = 1, np
    1073           0 :              do i = 1, np
    1074           0 :                dyn_state%elem(ie)%derived%FQ(i,j,k,m) = dyn_state%elem(ie)%derived%FQ(i,j,k,m)* &
    1075           0 :                     rec2dt*dyn_state%elem(ie)%state%dp3d(i,j,k,tl_f)
    1076             :              end do
    1077             :            end do
    1078             :          end do
    1079             :        end do
    1080             :      end do
    1081             :    end if
    1082             : 
    1083       14592 :    if (ftype_conserve>0.and..not.use_cslam) then
    1084           0 :      do ie = nets, nete
    1085           0 :        do k=1,nlev
    1086           0 :          do j=1,np
    1087           0 :            do i = 1, np
    1088           0 :              pdel     = dyn_state%elem(ie)%state%dp3d(i,j,k,tl_f)
    1089           0 :              do nq=dry_air_species_num+1,thermodynamic_active_species_num
    1090           0 :                m_cnst = thermodynamic_active_species_idx_dycore(nq)
    1091           0 :                pdel = pdel + (dyn_state%elem(ie)%state%qdp(i,j,k,m_cnst,n0_qdp)+dyn_state%elem(ie)%derived%FQ(i,j,k,m_cnst)*dtime)
    1092             :              end do
    1093           0 :              dyn_state%elem(ie)%derived%FDP(i,j,k) = pdel
    1094             :            end do
    1095             :          end do
    1096             :        end do
    1097             :      end do
    1098             :    end if
    1099             : 
    1100       14592 :    if (use_cslam) then
    1101      117192 :       do ie = nets, nete
    1102     4323792 :          do m = 1, ntrac
    1103   395523000 :             do k = 1, nlev
    1104  1569061800 :                do j = 1, nc
    1105  5085779400 :                   do i = 1, nc
    1106           0 :                      dyn_state%fvm(ie)%fc(i,j,k,m) = dyn_state%fvm(ie)%fc(i,j,k,m)* &
    1107  4694565600 :                         rec2dt!*dyn_state%fvm(ie)%dp_fvm(i,j,k)
    1108             :                   end do
    1109             :                end do
    1110             :             end do
    1111             :          end do
    1112             :       end do
    1113             :    end if
    1114             : 
    1115       14592 :    if (ldiag) then
    1116           0 :       abs_ps_tend(:,:,nets:nete) = 0.0_r8
    1117             :    endif
    1118             : 
    1119       43776 :    do n = 1, nsplit_local
    1120             : 
    1121       29184 :       if (ldiag) then
    1122           0 :          do ie = nets, nete
    1123           0 :             ps_before(:,:,ie) = dyn_state%elem(ie)%state%psdry(:,:)
    1124             :          end do
    1125             :       end if
    1126             : 
    1127             :       ! forward-in-time RK, with subcycling
    1128             :       call prim_run_subcycle(dyn_state%elem, dyn_state%fvm, hybrid, nets, nete, &
    1129       29184 :                              tstep, TimeLevel, hvcoord, n, omega_cn)
    1130             : 
    1131       43776 :       if (ldiag) then
    1132           0 :          do ie = nets, nete
    1133           0 :             abs_ps_tend(:,:,ie) = abs_ps_tend(:,:,ie) +                                &
    1134           0 :                ABS(ps_before(:,:,ie)-dyn_state%elem(ie)%state%psdry(:,:)) &
    1135           0 :                /(tstep*qsplit*rsplit)
    1136             :          end do
    1137             :       end if
    1138             : 
    1139             :    end do
    1140             : 
    1141       14592 :    if (ldiag) then
    1142           0 :       do ie=nets,nete
    1143           0 :          abs_ps_tend(:,:,ie)=abs_ps_tend(:,:,ie)/DBLE(nsplit)
    1144           0 :          call outfld('ABS_dPSdt',RESHAPE(abs_ps_tend(:,:,ie),(/npsq/)),npsq,ie)
    1145             :       end do
    1146             :    end if
    1147             : 
    1148             :    !$OMP END PARALLEL
    1149             : 
    1150             :    if (ldiag) then
    1151           0 :       deallocate(ps_before,abs_ps_tend)
    1152             :    endif
    1153             :    ! output vars on CSLAM fvm grid
    1154       14592 :    call write_dyn_vars(dyn_state)
    1155             : 
    1156       14592 : end subroutine dyn_run
    1157             : 
    1158             : !===============================================================================
    1159             : 
    1160           0 : subroutine dyn_final(DYN_STATE, RESTART_FILE)
    1161             : 
    1162             :    type (elem_state_t), target     :: DYN_STATE
    1163             :    character(LEN=*)   , intent(IN) :: RESTART_FILE
    1164             : 
    1165       14592 : end subroutine dyn_final
    1166             : 
    1167             : !===============================================================================
    1168             : 
    1169         768 : subroutine read_inidat(dyn_in)
    1170             :    use air_composition,     only: thermodynamic_active_species_num, dry_air_species_num
    1171             :    use shr_sys_mod,         only: shr_sys_flush
    1172             :    use hycoef,              only: hyai, hybi, ps0
    1173             :    use const_init,          only: cnst_init_default
    1174             : 
    1175             :    use element_mod,         only: timelevels
    1176             :    use fvm_mapping,         only: dyn2fvm_mass_vars
    1177             :    use control_mod,         only: runtype
    1178             :    use prim_driver_mod,     only: prim_set_dry_mass
    1179             :    use air_composition,     only: thermodynamic_active_species_idx
    1180             :    use cam_initfiles,       only: scale_dry_air_mass
    1181             :    ! Arguments
    1182             :    type (dyn_import_t), target, intent(inout) :: dyn_in   ! dynamics import
    1183             : 
    1184             :    ! Local variables
    1185             : 
    1186         768 :    integer(iMap), pointer           :: ldof(:) ! Basic (2D) grid dof
    1187             : 
    1188             :    type(file_desc_t), pointer       :: fh_ini, fh_topo
    1189             : 
    1190         768 :    type(element_t), pointer         :: elem(:)
    1191             : 
    1192         768 :    real(r8), allocatable            :: qtmp(:,:,:,:,:)    ! (np,np,nlev,nelemd,n)
    1193         768 :    real(r8), allocatable            :: dbuf2(:,:)         ! (npsq,nelemd)
    1194         768 :    real(r8), allocatable            :: dbuf3(:,:,:)       ! (npsq,nlev,nelemd)
    1195         768 :    real(r8), allocatable            :: phis_tmp(:,:)      ! (npsp,nelemd)
    1196         768 :    real(r8), allocatable            :: factor_array(:,:,:,:) ! (np,np,nlev,nelemd)
    1197         768 :    logical,  allocatable            :: pmask(:)           ! (npsq*nelemd) unique grid vals
    1198             : 
    1199             :    character(len=max_hcoordname_len):: grid_name
    1200         768 :    real(r8), allocatable            :: latvals(:)
    1201         768 :    real(r8), allocatable            :: lonvals(:)
    1202         768 :    real(r8), pointer                :: latvals_deg(:)
    1203         768 :    real(r8), pointer                :: lonvals_deg(:)
    1204             : 
    1205             :    integer                          :: ie, k, t
    1206             :    character(len=max_fieldname_len) :: fieldname, fieldname2
    1207             :    logical                          :: found
    1208             :    logical                          :: inic_wet           ! true if initial condition is based on
    1209             :                                                           ! wet pressure and water species
    1210             :    integer                          :: kptr, m_cnst
    1211         768 :    type(EdgeBuffer_t)               :: edge
    1212             : 
    1213             :    integer                          :: rndm_seed_sz
    1214         768 :    integer, allocatable             :: rndm_seed(:)
    1215             :    integer                          :: dims(2)
    1216             :    integer                          :: pio_errtype
    1217             :    real(r8)                         :: pertval
    1218             :    integer                          :: i, j, indx, nq
    1219             :    integer                          :: dyn_cols
    1220             :    character(len=128)               :: errmsg
    1221             :    character(len=*), parameter      :: sub='READ_INIDAT'
    1222             : 
    1223             :    real(r8)                         :: dp_tmp, pstmp(np,np)
    1224             : 
    1225             :    ! Variables for analytic initial conditions
    1226         768 :    integer,  allocatable            :: glob_ind(:)
    1227         768 :    integer,  allocatable            :: m_ind(:)
    1228         768 :    real(r8), allocatable            :: dbuf4(:,:,:,:)
    1229             :    !----------------------------------------------------------------------------
    1230             : 
    1231        1536 :    fh_ini  => initial_file_get_id()
    1232         768 :    fh_topo => topo_file_get_id()
    1233             : 
    1234         768 :    if (iam < par%nprocs) then
    1235         768 :       elem => dyn_in%elem
    1236             :    else
    1237           0 :       nullify(elem)
    1238             :    end if
    1239             : 
    1240        3072 :    allocate(qtmp(np,np,nlev,nelemd,pcnst))
    1241   432647856 :    qtmp = 0._r8
    1242             : 
    1243             :    ! Set mask to indicate which columns are active
    1244         768 :    nullify(ldof)
    1245         768 :    call cam_grid_get_gcid(cam_grid_id(ini_grid_name), ldof)
    1246        2304 :    allocate(pmask(npsq*nelemd))
    1247       87168 :    pmask(:) = (ldof /= 0)
    1248             : 
    1249             :    ! lat/lon needed in radians
    1250         768 :    latvals_deg => cam_grid_get_latvals(cam_grid_id(ini_grid_name))
    1251         768 :    lonvals_deg => cam_grid_get_lonvals(cam_grid_id(ini_grid_name))
    1252        2304 :    allocate(latvals(np*np*nelemd))
    1253        1536 :    allocate(lonvals(np*np*nelemd))
    1254       87168 :    latvals(:) = latvals_deg(:)*deg2rad
    1255       87168 :    lonvals(:) = lonvals_deg(:)*deg2rad
    1256             : 
    1257             :    ! Set PIO to return error codes when reading data from IC file.
    1258         768 :    call pio_seterrorhandling(fh_ini, PIO_BCAST_ERROR, pio_errtype)
    1259             : 
    1260             :    ! Get the number of columns in the global GLL grid.
    1261         768 :    call cam_grid_dimensions(ini_grid_name, dims)
    1262         768 :    dyn_cols = dims(1)
    1263             : 
    1264             :    ! Set ICs.  Either from analytic expressions or read from file.
    1265             : 
    1266         768 :    if (analytic_ic_active() .and. (iam < par%nprocs)) then
    1267             : 
    1268             :       ! PHIS has already been set by set_phis.  Get local copy for
    1269             :       ! possible use in setting T and PS in the analytic IC code.
    1270           0 :       allocate(phis_tmp(npsq,nelemd))
    1271           0 :       do ie = 1, nelemd
    1272             :          k = 1
    1273           0 :          do j = 1, np
    1274           0 :             do i = 1, np
    1275           0 :                phis_tmp(k,ie) = elem(ie)%state%phis(i,j)
    1276           0 :                k = k + 1
    1277             :             end do
    1278             :          end do
    1279             :       end do
    1280             : 
    1281           0 :       inic_wet = .false.
    1282           0 :       allocate(glob_ind(npsq * nelemd))
    1283           0 :       j = 1
    1284           0 :       do ie = 1, nelemd
    1285           0 :          do i = 1, npsq
    1286             :             ! Create a global(ish) column index
    1287           0 :             glob_ind(j) = elem(ie)%GlobalId
    1288           0 :             j = j + 1
    1289             :          end do
    1290             :       end do
    1291             : 
    1292             :       ! First, initialize all the variables, then assign
    1293           0 :       allocate(dbuf4(npsq, nlev, nelemd, (qsize + 4)))
    1294           0 :       dbuf4 = 0.0_r8
    1295           0 :       allocate(m_ind(qsize))
    1296           0 :       do m_cnst = 1, qsize
    1297           0 :          m_ind(m_cnst) = m_cnst
    1298             :       end do
    1299             : 
    1300             :       ! Init tracers on the GLL grid.  Note that analytic_ic_set_ic makes
    1301             :       ! use of cnst_init_default for the tracers except water vapor.
    1302             : 
    1303             :       call analytic_ic_set_ic(vcoord, latvals, lonvals, glob_ind,  &
    1304             :          PS=dbuf4(:,1,:,(qsize+1)), U=dbuf4(:,:,:,(qsize+2)),      &
    1305             :          V=dbuf4(:,:,:,(qsize+3)), T=dbuf4(:,:,:,(qsize+4)),       &
    1306           0 :          Q=dbuf4(:,:,:,1:qsize), m_cnst=m_ind, mask=pmask(:),      &
    1307           0 :          PHIS_IN=PHIS_tmp)
    1308           0 :       deallocate(m_ind)
    1309           0 :       deallocate(glob_ind)
    1310           0 :       deallocate(phis_tmp)
    1311           0 :       do ie = 1, nelemd
    1312             :          indx = 1
    1313           0 :          do j = 1, np
    1314           0 :             do i = 1, np
    1315             :                ! PS
    1316           0 :                elem(ie)%state%psdry(i,j) = dbuf4(indx, 1, ie, (qsize+1))
    1317             :                ! U
    1318           0 :                elem(ie)%state%v(i,j,1,:,1) = dbuf4(indx, :, ie, (qsize+2))
    1319             :                ! V
    1320           0 :                elem(ie)%state%v(i,j,2,:,1) = dbuf4(indx, :, ie, (qsize+3))
    1321             :                ! T
    1322           0 :                elem(ie)%state%T(i,j,:,1) = dbuf4(indx, :, ie, (qsize+4))
    1323           0 :                indx = indx + 1
    1324             :             end do
    1325             :          end do
    1326             :       end do
    1327             : 
    1328             :       ! Tracers to be advected on GLL grid.
    1329             :       ! Note that fvm tracers are initialized below.
    1330           0 :       do m_cnst = 1, qsize
    1331           0 :          do ie = 1, nelemd
    1332           0 :             qtmp(:,:,:,ie,m_cnst) = 0.0_r8
    1333             :             indx = 1
    1334           0 :             do j = 1, np
    1335           0 :                do i = 1, np
    1336             :                   ! Set qtmp at the unique columns only
    1337           0 :                   if (pmask(((ie - 1) * npsq) + indx)) then
    1338           0 :                      qtmp(i,j,:,ie,m_cnst) = dbuf4(indx, :, ie, m_cnst)
    1339             :                   end if
    1340           0 :                   indx = indx + 1
    1341             :                end do
    1342             :             end do
    1343             :          end do
    1344             :       end do
    1345           0 :       deallocate(dbuf4)
    1346             : 
    1347             : 
    1348             :    else
    1349             : 
    1350             :       ! Read ICs from file.  Assume all fields in the initial file are on the GLL grid.
    1351             : 
    1352        2304 :       allocate(dbuf2(npsq,nelemd))
    1353        2304 :       allocate(dbuf3(npsq,nlev,nelemd))
    1354             : 
    1355             :       ! Check that columns in IC file match grid definition.
    1356         768 :       call check_file_layout(fh_ini, elem, dyn_cols, 'ncdata', .true.)
    1357             : 
    1358             :       ! Read 2-D field
    1359             : 
    1360         768 :       fieldname  = 'PS'
    1361         768 :       fieldname2 = 'PSDRY'
    1362         768 :       if (dyn_field_exists(fh_ini, trim(fieldname), required=.false.)) then
    1363         768 :          inic_wet = .true.
    1364         768 :          call read_dyn_var(trim(fieldname), fh_ini, ini_grid_hdim_name, dbuf2)
    1365           0 :       elseif (dyn_field_exists(fh_ini, trim(fieldname2), required=.false.)) then
    1366           0 :          inic_wet = .false.
    1367           0 :          call read_dyn_var(trim(fieldname2), fh_ini, ini_grid_hdim_name, dbuf2)
    1368             :       else
    1369           0 :          call endrun(trim(sub)//': PS or PSDRY must be on GLL grid')
    1370             :       end if
    1371             : #ifndef planet_mars
    1372         768 :       if (iam < par%nprocs) then
    1373       94872 :          if (minval(dbuf2, mask=reshape(pmask, (/npsq,nelemd/))) < 10000._r8) then
    1374         768 :             call endrun(trim(sub)//': Problem reading ps or psdry field -- bad values')
    1375             :          end if
    1376             :       end if
    1377             : #endif
    1378        6168 :       do ie = 1, nelemd
    1379             :          indx = 1
    1380       27768 :          do j = 1, np
    1381      113400 :             do i = 1, np
    1382       86400 :                elem(ie)%state%psdry(i,j) = dbuf2(indx,ie) ! can be either wet or dry ps
    1383      108000 :                indx = indx + 1
    1384             :             end do
    1385             :          end do
    1386             :       end do
    1387             : 
    1388             :       ! Read in 3-D fields
    1389             : 
    1390         768 :       if (dyn_field_exists(fh_ini, 'U')) then
    1391         768 :          call read_dyn_var('U', fh_ini, ini_grid_hdim_name, dbuf3)
    1392             :       else
    1393           0 :          call endrun(trim(sub)//': U not found')
    1394             :       end if
    1395        6168 :       do ie = 1, nelemd
    1396    64805400 :          elem(ie)%state%v = 0.0_r8
    1397             :          indx = 1
    1398       27768 :          do j = 1, np
    1399      113400 :             do i = 1, np
    1400     8121600 :                elem(ie)%state%v(i,j,1,:,1) = dbuf3(indx,:,ie)
    1401      108000 :                indx = indx + 1
    1402             :             end do
    1403             :          end do
    1404             :       end do
    1405             : 
    1406         768 :       if (dyn_field_exists(fh_ini, 'V')) then
    1407         768 :          call read_dyn_var('V', fh_ini, ini_grid_hdim_name, dbuf3)
    1408             :       else
    1409           0 :          call endrun(trim(sub)//': V not found')
    1410             :       end if
    1411        6168 :       do ie = 1, nelemd
    1412             :          indx = 1
    1413       27768 :          do j = 1, np
    1414      113400 :             do i = 1, np
    1415     8121600 :                elem(ie)%state%v(i,j,2,:,1) = dbuf3(indx,:,ie)
    1416      108000 :                indx = indx + 1
    1417             :             end do
    1418             :          end do
    1419             :       end do
    1420             : 
    1421         768 :       if (dyn_field_exists(fh_ini, 'T')) then
    1422         768 :          call read_dyn_var('T', fh_ini, ini_grid_hdim_name, dbuf3)
    1423             :       else
    1424           0 :          call endrun(trim(sub)//': T not found')
    1425             :       end if
    1426        6168 :       do ie=1,nelemd
    1427    31660200 :          elem(ie)%state%T = 0.0_r8
    1428             :          indx = 1
    1429       27768 :          do j = 1, np
    1430      113400 :             do i = 1, np
    1431     8121600 :                elem(ie)%state%T(i,j,:,1) = dbuf3(indx,:,ie)
    1432      108000 :                indx = indx + 1
    1433             :             end do
    1434             :          end do
    1435             :       end do
    1436             : 
    1437         768 :       if (pertlim .ne. 0.0_r8) then
    1438           0 :          if (masterproc) then
    1439           0 :             write(iulog,*) trim(sub), ': Adding random perturbation bounded', &
    1440           0 :                'by +/- ', pertlim, ' to initial temperature field'
    1441             :          end if
    1442             : 
    1443           0 :          call random_seed(size=rndm_seed_sz)
    1444           0 :          allocate(rndm_seed(rndm_seed_sz))
    1445             : 
    1446           0 :          do ie = 1, nelemd
    1447             :             ! seed random number generator based on element ID
    1448             :             ! (possibly include a flag to allow clock-based random seeding)
    1449           0 :             rndm_seed = elem(ie)%GlobalId
    1450           0 :             call random_seed(put=rndm_seed)
    1451           0 :             do i = 1, np
    1452           0 :                do j = 1, np
    1453           0 :                   do k = 1, nlev
    1454           0 :                      call random_number(pertval)
    1455           0 :                      pertval = 2.0_r8*pertlim*(0.5_r8 - pertval)
    1456           0 :                      elem(ie)%state%T(i,j,k,1) = elem(ie)%state%T(i,j,k,1)*(1.0_r8 + pertval)
    1457             :                   end do
    1458             :                end do
    1459             :             end do
    1460             :          end do
    1461             : 
    1462           0 :          deallocate(rndm_seed)
    1463             :       end if
    1464             : 
    1465             :       ! Cleanup
    1466         768 :       deallocate(dbuf2)
    1467         768 :       deallocate(dbuf3)
    1468             : 
    1469             :    end if ! analytic_ic_active
    1470             : 
    1471             :    ! Read in or cold-initialize all the tracer fields.
    1472             :    ! Data is read in on the GLL grid.
    1473             :    ! Both GLL and FVM tracer fields are initialized based on the
    1474             :    ! dimension qsize or ntrac for GLL or FVM tracers respectively.
    1475             :    ! Data is only read in on GLL so if FVM tracers are active,
    1476             :    ! interpolation is performed.
    1477             :    !
    1478             :    ! If analytic ICs are being used, we allow constituents in an initial
    1479             :    ! file to overwrite mixing ratios set by the default constituent initialization
    1480             :    ! except for the water species.
    1481             : 
    1482         768 :    if (ntrac > qsize) then
    1483         768 :       if (ntrac < pcnst) then
    1484           0 :          write(errmsg, '(a,3(i0,a))') ': ntrac (',ntrac,') > qsize (',qsize, &
    1485           0 :             ') but < pcnst (',pcnst,')'
    1486           0 :          call endrun(trim(sub)//errmsg)
    1487             :       end if
    1488           0 :    else if (qsize < pcnst) then
    1489           0 :       write(errmsg, '(a,2(i0,a))') ': qsize (',qsize,') < pcnst (',pcnst,')'
    1490           0 :       call endrun(trim(sub)//errmsg)
    1491             :    end if
    1492             : 
    1493             :    ! If using analytic ICs the initial file only needs the horizonal grid
    1494             :    ! dimension checked in the case that the file contains constituent mixing
    1495             :    ! ratios.
    1496        3072 :    do m_cnst = 1, pcnst
    1497        3072 :       if (cnst_read_iv(m_cnst) .and. .not. cnst_is_a_water_species(cnst_name(m_cnst))) then
    1498         768 :          if (dyn_field_exists(fh_ini, trim(cnst_name(m_cnst)), required=.false.)) then
    1499         768 :             call check_file_layout(fh_ini, elem, dyn_cols, 'ncdata', .true.)
    1500         768 :             exit
    1501             :          end if
    1502             :       end if
    1503             :    end do
    1504             : 
    1505        2304 :    allocate(dbuf3(npsq,nlev,nelemd))
    1506             : 
    1507       32256 :    do m_cnst = 1, pcnst
    1508             : 
    1509       31488 :       if (analytic_ic_active() .and. cnst_is_a_water_species(cnst_name(m_cnst))) cycle
    1510             : 
    1511       31488 :       found = .false.
    1512       31488 :       if (cnst_read_iv(m_cnst)) then
    1513       31488 :          found = dyn_field_exists(fh_ini, trim(cnst_name(m_cnst)), required=.false.)
    1514             :       end if
    1515             : 
    1516       31488 :       if (found) then
    1517       31488 :          call read_dyn_var(trim(cnst_name(m_cnst)), fh_ini, ini_grid_hdim_name, dbuf3)
    1518             :       else
    1519           0 :          call cnst_init_default(m_cnst, latvals, lonvals, dbuf3, pmask)
    1520             :       end if
    1521             : 
    1522      253656 :       do ie = 1, nelemd
    1523             :          ! Copy tracers defined on GLL grid into Eulerian array
    1524             :          ! Make sure tracers have at least minimum value
    1525    20843088 :          do k=1, nlev
    1526             :             indx = 1
    1527   103172400 :             do j = 1, np
    1528   432394200 :                do i = 1, np
    1529             :                   ! Set qtmp at the unique columns only: zero non-unique columns
    1530   329443200 :                   if (pmask(((ie - 1) * npsq) + indx)) then
    1531   185319426 :                      qtmp(i,j, k, ie, m_cnst) = max(qmin(m_cnst),dbuf3(indx,k,ie))
    1532             :                   else
    1533   144123774 :                      qtmp(i,j, k, ie, m_cnst) = 0.0_r8
    1534             :                   end if
    1535   411804000 :                   indx = indx + 1
    1536             :                end do
    1537             :             end do
    1538             :          end do
    1539             :       end do
    1540             : 
    1541             :    end do ! pcnst
    1542             : 
    1543             :    ! Cleanup
    1544         768 :    deallocate(dbuf3)
    1545             : 
    1546             :    ! Put the error handling back the way it was
    1547         768 :    call pio_seterrorhandling(fh_ini, pio_errtype)
    1548             : 
    1549             :    ! Cleanup
    1550         768 :    deallocate(pmask)
    1551         768 :    deallocate(latvals)
    1552         768 :    deallocate(lonvals)
    1553             : 
    1554         768 :    if (associated(ldof)) then
    1555         768 :       deallocate(ldof)
    1556             :       nullify(ldof)
    1557             :    end if
    1558             : 
    1559             :    ! once we've read or initialized all the fields we do a boundary exchange to
    1560             :    ! update the redundent columns in the dynamics
    1561         768 :    if(iam < par%nprocs) then
    1562         768 :       call initEdgeBuffer(par, edge, elem, (3+pcnst)*nlev + 2 )
    1563             :    end if
    1564        6168 :    do ie = 1, nelemd
    1565        5400 :       kptr = 0
    1566        5400 :       call edgeVpack(edge, elem(ie)%state%psdry,1,kptr,ie)
    1567        5400 :       kptr = kptr + 1
    1568        5400 :       call edgeVpack(edge, elem(ie)%state%v(:,:,:,:,1),2*nlev,kptr,ie)
    1569        5400 :       kptr = kptr + (2 * nlev)
    1570        5400 :       call edgeVpack(edge, elem(ie)%state%T(:,:,:,1),nlev,kptr,ie)
    1571        5400 :       kptr = kptr + nlev
    1572   432621768 :       call edgeVpack(edge, qtmp(:,:,:,ie,:),nlev*pcnst,kptr,ie)
    1573             :    end do
    1574         768 :    if(iam < par%nprocs) then
    1575         768 :       call bndry_exchange(par,edge,location='read_inidat')
    1576             :    end if
    1577        6168 :    do ie = 1, nelemd
    1578        5400 :       kptr = 0
    1579        5400 :       call edgeVunpack(edge, elem(ie)%state%psdry,1,kptr,ie)
    1580        5400 :       kptr = kptr + 1
    1581        5400 :       call edgeVunpack(edge, elem(ie)%state%v(:,:,:,:,1),2*nlev,kptr,ie)
    1582        5400 :       kptr = kptr + (2 * nlev)
    1583        5400 :       call edgeVunpack(edge, elem(ie)%state%T(:,:,:,1),nlev,kptr,ie)
    1584        5400 :       kptr = kptr + nlev
    1585   865237368 :       call edgeVunpack(edge, qtmp(:,:,:,ie,:),nlev*pcnst,kptr,ie)
    1586             :    end do
    1587             : 
    1588         768 :    if (inic_wet) then
    1589             :       !
    1590             :       ! convert to dry
    1591             :       !
    1592             :       ! (this has to be done after edge-exchange since shared points between elements are only
    1593             :       !  initialized in one element and not the other!)
    1594             :       !
    1595         768 :       if (par%masterproc) then
    1596           1 :          write(iulog,*) 'Convert specific/wet mixing ratios to dry'
    1597             :       end if
    1598             : 
    1599        2304 :       allocate(factor_array(np,np,nlev,nelemd))
    1600             :       !
    1601             :       ! compute: factor_array = 1/(1-sum(q))
    1602             :       !
    1603    10552368 :       factor_array(:,:,:,:) = 1.0_r8
    1604        6168 :       do ie = 1, nelemd
    1605       38568 :          do k = dry_air_species_num+1, thermodynamic_active_species_num
    1606       32400 :             m_cnst = thermodynamic_active_species_idx(k)
    1607    63315000 :             factor_array(:,:,:,ie) = factor_array(:,:,:,ie) - qtmp(:,:,:,ie,m_cnst)
    1608             :          end do
    1609             :       end do
    1610    10552368 :       factor_array(:,:,:,:) = 1.0_r8/factor_array(:,:,:,:)
    1611             : 
    1612       32256 :       do m_cnst = 1, pcnst
    1613       32256 :          if (cnst_type(m_cnst) == 'wet') then
    1614       67848 :             do ie = 1, nelemd
    1615     5592048 :                do k = 1, nlev
    1616    27680400 :                   do j = 1, np
    1617   116008200 :                      do i = 1, np
    1618             : 
    1619             :                         ! convert wet mixing ratio to dry
    1620    88387200 :                         qtmp(i,j,k,ie,m_cnst) = qtmp(i,j,k,ie,m_cnst) * factor_array(i,j,k,ie)
    1621             : 
    1622             :                         ! truncate negative values if they were not analytically specified
    1623   110484000 :                         if (.not. analytic_ic_active()) then
    1624    88387200 :                            qtmp(i,j,k,ie,m_cnst) = max(qmin(m_cnst), qtmp(i,j,k,ie,m_cnst))
    1625             :                         end if
    1626             :                      end do
    1627             :                   end do
    1628             :                end do
    1629             :             end do
    1630             :          end if
    1631             :       end do
    1632             : 
    1633             :       ! initialize dp3d and qdp
    1634             :       !
    1635             :       ! compute: factor_array = 1/(1+sum(q))
    1636             : 
    1637    10552368 :       factor_array(:,:,:,:) = 1.0_r8
    1638        6168 :       do ie = 1, nelemd
    1639       38568 :          do k = dry_air_species_num+1, thermodynamic_active_species_num
    1640       32400 :             m_cnst = thermodynamic_active_species_idx(k)
    1641    63315000 :             factor_array(:,:,:,ie) = factor_array(:,:,:,ie) + qtmp(:,:,:,ie,m_cnst)
    1642             :          end do
    1643             :       end do
    1644    10552368 :       factor_array(:,:,:,:) = 1.0_r8/factor_array(:,:,:,:)
    1645        6168 :       do ie = 1, nelemd
    1646             :          ! pstmp is the wet ps
    1647      113400 :          pstmp = elem(ie)%state%psdry(:,:)
    1648             :          ! start accumulating the dry air pressure differences across each layer
    1649      113400 :          elem(ie)%state%psdry(:,:) = hyai(1)*ps0
    1650      508368 :          do k=1,nlev
    1651     2516400 :             do j = 1,np
    1652    10546200 :                do i = 1,np
    1653    16070400 :                   dp_tmp = ((hyai(k+1) - hyai(k))*ps0) + &
    1654    24105600 :                            ((hybi(k+1) - hybi(k))*pstmp(i,j))
    1655     8035200 :                   if (.not. analytic_ic_active()) then
    1656             : 
    1657             :                      ! if analytic_ic then the surface pressure is already dry
    1658             :                      ! (note that it is not correct to convert to moist pressure
    1659             :                      ! in analytic_ic and not have the #ifndef statement here
    1660             :                      ! since the dry levels are in a different location than
    1661             :                      ! what is obtained from algorithm below)
    1662             : 
    1663             :                      ! convert dp_tmp to dry
    1664     8035200 :                      dp_tmp = dp_tmp*factor_array(i,j,k,ie)
    1665             :                   end if
    1666             : 
    1667    32140800 :                   elem(ie)%state%dp3d(i,j,k,:) = dp_tmp
    1668             : 
    1669             :                   ! compute dry surface pressure; note that at this point
    1670             :                   !
    1671             :                   ! dp3d .NE. (hyai(k+1) - hyai(k))*ps0 + (hybi(k+1) - hybi(k))*ps(i,j)
    1672             : 
    1673    10044000 :                   elem(ie)%state%psdry(i,j) = elem(ie)%state%psdry(i,j)+elem(ie)%state%dp3d(i,j,k,1)
    1674             :                end do
    1675             :             end do
    1676             :          end do
    1677             :       end do
    1678             : 
    1679         768 :       deallocate(factor_array)
    1680             : 
    1681             :    else
    1682             : 
    1683             :       ! initial condition is based on dry surface pressure and constituents
    1684             :       !
    1685             :       ! we only need to initialize state%dp3d
    1686             : 
    1687           0 :       do ie = 1, nelemd
    1688           0 :          do k = 1, nlev
    1689           0 :             do j = 1, np
    1690           0 :                do i = 1, np
    1691           0 :                   elem(ie)%state%dp3d(i,j,k,:) = (hyai(k+1) - hyai(k))*ps0 + &
    1692           0 :                                                  (hybi(k+1) - hybi(k))*elem(ie)%state%psdry(i,j)
    1693             :                end do
    1694             :             end do
    1695             :          end do
    1696             :       end do
    1697             :    end if
    1698             : 
    1699             :    ! If scale_dry_air_mass > 0.0 then scale dry air mass to scale_dry_air_mass global average dry pressure
    1700         768 :    if (runtype == 0) then
    1701         768 :      if (scale_dry_air_mass > 0.0_r8) then
    1702         768 :        if (iam < par%nprocs) then
    1703         768 :          call prim_set_dry_mass(elem, hvcoord, scale_dry_air_mass, qtmp)
    1704             :        end if
    1705             :      end if
    1706             :    end if
    1707             : 
    1708             :    ! store Q values:
    1709             :    !
    1710             :    ! if CSLAM is NOT active then state%Qdp for all constituents
    1711             :    ! if CSLAM active then we only advect water vapor and condensate
    1712             :    ! loading tracers in state%qdp
    1713             : 
    1714         768 :    if (use_cslam) then
    1715        6168 :       do ie = 1, nelemd
    1716       38568 :          do nq = 1, thermodynamic_active_species_num
    1717       32400 :             m_cnst = thermodynamic_active_species_idx(nq)
    1718     3051000 :             do k = 1, nlev
    1719    15098400 :                do j = 1, np
    1720    63277200 :                   do i = 1, np
    1721           0 :                      elem(ie)%state%Qdp(i,j,k,nq,:) = &
    1722   108475200 :                                  elem(ie)%state%dp3d(i,j,k,1)*qtmp(i,j,k,ie,m_cnst)
    1723             :                   end do
    1724             :                end do
    1725             :             end do
    1726             :          end do
    1727             :       end do
    1728             :    else
    1729           0 :       do ie = 1, nelemd
    1730           0 :          do m_cnst = 1, qsize
    1731           0 :             do k = 1, nlev
    1732           0 :                do j = 1, np
    1733           0 :                   do i = 1, np
    1734           0 :                      elem(ie)%state%Qdp(i,j,k,m_cnst,:)=&
    1735           0 :                         elem(ie)%state%dp3d(i,j,k,1)*qtmp(i,j,k,ie,m_cnst)
    1736             :                   end do
    1737             :                end do
    1738             :             end do
    1739             :          end do
    1740             :       end do
    1741             :    end if
    1742             : 
    1743             :    ! interpolate fvm tracers and fvm pressure variables
    1744             : 
    1745         768 :    if (use_cslam) then
    1746         768 :       if (par%masterproc) then
    1747           1 :          write(iulog,*) 'Initializing dp_fvm from spectral element dp'
    1748             :       end if
    1749             : 
    1750        6168 :       do ie = 1, nelemd
    1751             : 
    1752             :          ! note that the area over fvm cells as computed from subcell_integration is up to 1.0E-6
    1753             :          ! different than the areas (exact) computed by CSLAM
    1754             :          !
    1755             :          ! Map the constituents which are also to be transported by dycore
    1756           0 :          call dyn2fvm_mass_vars(elem(ie)%state%dp3d(:,:,:,1),elem(ie)%state%psdry(:,:),&
    1757        5400 :             qtmp(:,:,:,ie,1:ntrac),&
    1758           0 :             dyn_in%fvm(ie)%dp_fvm(1:nc,1:nc,:),dyn_in%fvm(ie)%psC(1:nc,1:nc),&
    1759           0 :             dyn_in%fvm(ie)%c(1:nc,1:nc,:,1:ntrac),&
    1760   981472368 :             ntrac,elem(ie)%metdet,dyn_in%fvm(ie)%inv_se_area_sphere(1:nc,1:nc))
    1761             :       end do
    1762             : 
    1763         768 :       if(par%masterproc) then
    1764           1 :          write(iulog,*) 'FVM tracers, FVM pressure variables and se_area_sphere initialized.'
    1765             :       end if
    1766             : 
    1767             :    end if    ! (use_cslam)
    1768             : 
    1769             :    ! Cleanup
    1770         768 :    deallocate(qtmp)
    1771             : 
    1772        6168 :    do ie = 1, nelemd
    1773       16968 :       do t = 2, timelevels
    1774    43200000 :          elem(ie)%state%v(:,:,:,:,t) = elem(ie)%state%v(:,:,:,:,1)
    1775    21108600 :          elem(ie)%state%T(:,:,:,t)   = elem(ie)%state%T(:,:,:,1)
    1776             :       end do
    1777             :    end do
    1778             : 
    1779         768 :    if(iam < par%nprocs) then
    1780         768 :       call FreeEdgeBuffer(edge)
    1781             :    end if
    1782             : 
    1783        1536 : end subroutine read_inidat
    1784             : 
    1785             : 
    1786             : !========================================================================================
    1787             : 
    1788        1536 : subroutine set_phis(dyn_in)
    1789             : 
    1790             :    ! Set PHIS according to the following rules.
    1791             :    !
    1792             :    ! 1) If a topo file is specified use it.  This option has highest precedence.
    1793             :    ! 2) If not using topo file, but analytic_ic option is on, use analytic phis.
    1794             :    ! 3) Set phis = 0.0.
    1795             :    !
    1796             :    ! If using the physics grid then the topo file will be on that grid since its
    1797             :    ! contents are primarily for the physics parameterizations, and the values of
    1798             :    ! PHIS should be consistent with the values of sub-grid variability (e.g., SGH)
    1799             :    ! which are computed on the physics grid.  In this case phis on the physics grid
    1800             :    ! will be interpolated to the GLL grid.
    1801             : 
    1802             : 
    1803             :    ! Arguments
    1804             :    type (dyn_import_t), target, intent(inout) :: dyn_in   ! dynamics import
    1805             : 
    1806             :    ! local variables
    1807             :    type(file_desc_t), pointer       :: fh_topo
    1808             : 
    1809        1536 :    type(element_t), pointer         :: elem(:)
    1810             : 
    1811        1536 :    real(r8), allocatable            :: phis_tmp(:,:)      ! (npsp,nelemd)
    1812        1536 :    real(r8), allocatable            :: phis_phys_tmp(:,:) ! (fv_nphys**2,nelemd)
    1813             : 
    1814             :    integer                          :: i, ie, indx, j, kptr
    1815             :    integer                          :: ierr, pio_errtype
    1816             : 
    1817             :    character(len=max_fieldname_len) :: fieldname
    1818             :    character(len=max_fieldname_len) :: fieldname_gll
    1819             :    character(len=max_hcoordname_len):: grid_name
    1820             :    integer                          :: dims(2)
    1821             :    integer                          :: dyn_cols
    1822             :    integer                          :: ncol_did
    1823             :    integer                          :: ncol_size
    1824             : 
    1825        1536 :    integer(iMap), pointer           :: ldof(:)            ! Basic (2D) grid dof
    1826        1536 :    logical,  allocatable            :: pmask(:)           ! (npsq*nelemd) unique columns
    1827             : 
    1828             :    ! Variables for analytic initial conditions
    1829        1536 :    integer,  allocatable            :: glob_ind(:)
    1830             :    logical,  allocatable            :: pmask_phys(:)
    1831        1536 :    real(r8), pointer                :: latvals_deg(:)
    1832        1536 :    real(r8), pointer                :: lonvals_deg(:)
    1833        1536 :    real(r8), allocatable            :: latvals(:)
    1834        1536 :    real(r8), allocatable            :: lonvals(:)
    1835             :    real(r8), allocatable            :: latvals_phys(:)
    1836             :    real(r8), allocatable            :: lonvals_phys(:)
    1837             : 
    1838             :    character(len=*), parameter      :: sub='set_phis'
    1839             :    !----------------------------------------------------------------------------
    1840             : 
    1841        3072 :    fh_topo => topo_file_get_id()
    1842             : 
    1843        1536 :    if (iam < par%nprocs) then
    1844        1536 :       elem => dyn_in%elem
    1845             :    else
    1846           0 :       nullify(elem)
    1847             :    end if
    1848             : 
    1849        4608 :    allocate(phis_tmp(npsq,nelemd))
    1850      185136 :    phis_tmp = 0.0_r8
    1851             : 
    1852        1536 :    if (use_cslam) then
    1853        6144 :       allocate(phis_phys_tmp(fv_nphys**2,nelemd))
    1854      109536 :       phis_phys_tmp = 0.0_r8
    1855       12336 :       do ie=1,nelemd
    1856    53245536 :         elem(ie)%sub_elem_mass_flux=0.0_r8
    1857             : #ifdef waccm_debug
    1858             :         dyn_in%fvm(ie)%CSLAM_gamma = 0.0_r8
    1859             : #endif
    1860             :       end do
    1861             :    end if
    1862             : 
    1863             :    ! Set mask to indicate which columns are active in GLL grid.
    1864        1536 :    nullify(ldof)
    1865        1536 :    call cam_grid_get_gcid(cam_grid_id('GLL'), ldof)
    1866        4608 :    allocate(pmask(npsq*nelemd))
    1867      174336 :    pmask(:) = (ldof /= 0)
    1868        1536 :    deallocate(ldof)
    1869             : 
    1870        1536 :    if (associated(fh_topo)) then
    1871             : 
    1872             :       ! Set PIO to return error flags.
    1873        1536 :       call pio_seterrorhandling(fh_topo, PIO_BCAST_ERROR, pio_errtype)
    1874             : 
    1875             :       ! Set name of grid object which will be used to read data from file
    1876             :       ! into internal data structure via PIO.
    1877        1536 :       if (.not.use_cslam) then
    1878           0 :          grid_name = 'GLL'
    1879             :       else
    1880        1536 :          grid_name = 'physgrid_d'
    1881             :       end if
    1882             : 
    1883             :       ! Get number of global columns from the grid object and check that
    1884             :       ! it matches the file data.
    1885        1536 :       call cam_grid_dimensions(grid_name, dims)
    1886        1536 :       dyn_cols = dims(1)
    1887             : 
    1888             :       ! The dimension of the unstructured grid in the TOPO file is 'ncol'.
    1889        1536 :       ierr = pio_inq_dimid(fh_topo, 'ncol', ncol_did)
    1890        1536 :       if (ierr /= PIO_NOERR) then
    1891           0 :          call endrun(sub//': dimension ncol not found in bnd_topo file')
    1892             :       end if
    1893        1536 :       ierr = pio_inq_dimlen(fh_topo, ncol_did, ncol_size)
    1894        1536 :       if (ncol_size /= dyn_cols) then
    1895           0 :          if (masterproc) then
    1896           0 :             write(iulog,*) sub//': ncol_size=', ncol_size, ' : dyn_cols=', dyn_cols
    1897             :          end if
    1898           0 :          call endrun(sub//': ncol size in bnd_topo file does not match grid definition')
    1899             :       end if
    1900             : 
    1901        1536 :       fieldname = 'PHIS'
    1902        1536 :       fieldname_gll = 'PHIS_gll'
    1903        1536 :       if (use_cslam.and.dyn_field_exists(fh_topo, trim(fieldname_gll),required=.false.)) then
    1904             :          !
    1905             :          ! If physgrid it is recommended to read in PHIS on the GLL grid and then
    1906             :          ! map to the physgrid in d_p_coupling
    1907             :          !
    1908             :          ! This requires a topo file with PHIS_gll on it ...
    1909             :          !
    1910        1536 :          if (masterproc) then
    1911           2 :             write(iulog, *) "Reading in PHIS on GLL grid (mapped to physgrid in d_p_coupling)"
    1912             :          end if
    1913        1536 :          call read_dyn_var(fieldname_gll, fh_topo, 'ncol_gll', phis_tmp)
    1914           0 :       else if (dyn_field_exists(fh_topo, trim(fieldname))) then
    1915           0 :          if (.not.use_cslam) then
    1916           0 :             if (masterproc) then
    1917           0 :                write(iulog, *) "Reading in PHIS"
    1918             :             end if
    1919           0 :             call read_dyn_var(fieldname, fh_topo, 'ncol', phis_tmp)
    1920             :          else
    1921             :             !
    1922             :             ! For backwards compatibility we allow reading in PHIS on the physgrid
    1923             :             ! which is then mapped to the GLL grid and back to the physgrid in d_p_coupling
    1924             :             ! (the latter is to avoid noise in derived quantities such as PSL)
    1925             :             !
    1926           0 :             if (masterproc) then
    1927           0 :                write(iulog, *) "Reading in PHIS on physgrid"
    1928           0 :                write(iulog, *) "Recommended to read in PHIS on GLL grid"
    1929             :             end if
    1930           0 :             call read_phys_field_2d(fieldname, fh_topo, 'ncol', phis_phys_tmp)
    1931             :             call map_phis_from_physgrid_to_gll(dyn_in%fvm, elem, phis_phys_tmp, &
    1932           0 :                  phis_tmp, pmask)
    1933           0 :             deallocate(phis_phys_tmp)
    1934             :          end if
    1935             :       else
    1936           0 :          call endrun(sub//': Could not find PHIS field on input datafile')
    1937             :       end if
    1938             : 
    1939             :       ! Put the error handling back the way it was
    1940        1536 :       call pio_seterrorhandling(fh_topo, pio_errtype)
    1941             : 
    1942           0 :    else if (analytic_ic_active() .and. (iam < par%nprocs)) then
    1943             : 
    1944             :       ! lat/lon needed in radians
    1945           0 :       latvals_deg => cam_grid_get_latvals(cam_grid_id('GLL'))
    1946           0 :       lonvals_deg => cam_grid_get_lonvals(cam_grid_id('GLL'))
    1947           0 :       allocate(latvals(np*np*nelemd))
    1948           0 :       allocate(lonvals(np*np*nelemd))
    1949           0 :       latvals(:) = latvals_deg(:)*deg2rad
    1950           0 :       lonvals(:) = lonvals_deg(:)*deg2rad
    1951             : 
    1952           0 :       allocate(glob_ind(npsq*nelemd))
    1953           0 :       j = 1
    1954           0 :       do ie = 1, nelemd
    1955           0 :          do i = 1, npsq
    1956             :             ! Create a global(ish) column index
    1957           0 :             glob_ind(j) = elem(ie)%GlobalId
    1958           0 :             j = j + 1
    1959             :          end do
    1960             :       end do
    1961             :       call analytic_ic_set_ic(vcoord, latvals, lonvals, glob_ind, &
    1962           0 :                               PHIS_OUT=phis_tmp, mask=pmask(:))
    1963           0 :       deallocate(glob_ind)
    1964             : 
    1965             :    end if
    1966             : 
    1967        1536 :    deallocate(pmask)
    1968             : 
    1969             :    ! Set PHIS in element objects
    1970       12336 :    do ie = 1, nelemd
    1971      226800 :       elem(ie)%state%phis = 0.0_r8
    1972             :       indx = 1
    1973       55536 :       do j = 1, np
    1974      226800 :          do i = 1, np
    1975      172800 :             elem(ie)%state%phis(i,j) = phis_tmp(indx, ie)
    1976      216000 :             indx = indx + 1
    1977             :          end do
    1978             :       end do
    1979             :    end do
    1980        1536 :    deallocate(phis_tmp)
    1981             : 
    1982             :    ! boundary exchange to update the redundent columns in the element objects
    1983       12336 :    do ie = 1, nelemd
    1984       10800 :       kptr = 0
    1985       12336 :       call edgeVpack(edgebuf, elem(ie)%state%phis, 1, kptr, ie)
    1986             :    end do
    1987        1536 :    if(iam < par%nprocs) then
    1988        1536 :       call bndry_exchange(par, edgebuf, location=sub)
    1989             :    end if
    1990       12336 :    do ie = 1, nelemd
    1991       10800 :       kptr = 0
    1992       12336 :       call edgeVunpack(edgebuf, elem(ie)%state%phis,1,kptr,ie)
    1993             :    end do
    1994             : 
    1995        3840 : end subroutine set_phis
    1996             : 
    1997             : !========================================================================================
    1998             : 
    1999        1536 : subroutine check_file_layout(file, elem, dyn_cols, file_desc, dyn_ok)
    2000             : 
    2001             :    ! This routine is only called when data will be read from the initial file.  It is not
    2002             :    ! called when the initial file is only supplying vertical coordinate info.
    2003             : 
    2004             :    type(file_desc_t), pointer       :: file
    2005             :    type(element_t),   pointer       :: elem(:)
    2006             :    integer,           intent(in)    :: dyn_cols
    2007             :    character(len=*),  intent(in)    :: file_desc
    2008             :    logical,           intent(in)    :: dyn_ok ! .true. iff ncol_d is okay
    2009             : 
    2010             :    integer                          :: ncol_did, ncol_size
    2011             :    integer                          :: ierr
    2012             :    integer                          :: ie, i, j
    2013             :    integer                          :: indx
    2014        3072 :    real(r8)                         :: dbuf2(npsq, nelemd)
    2015             :    logical                          :: found
    2016             :    character(len=max_fieldname_len) :: coordname
    2017             : 
    2018             :    character(len=*), parameter      :: sub = 'check_file_layout'
    2019             :    !----------------------------------------------------------------------------
    2020             : 
    2021             :    ! Check that number of columns in IC file matches grid definition.
    2022        1536 :    if (trim(ini_grid_hdim_name) == 'none') then
    2023             :       call endrun(sub//': ERROR: no horizontal dimension in initial data file. &
    2024           0 :          &Cannot read data from file')
    2025             :    end if
    2026             : 
    2027        1536 :    ierr = pio_inq_dimid(file, trim(ini_grid_hdim_name), ncol_did)
    2028        1536 :    if (ierr /= PIO_NOERR) then
    2029             :       call endrun(sub//': ERROR: '//trim(ini_grid_hdim_name)//' dimension not found in ' &
    2030           0 :          //trim(file_desc)//' file')
    2031             :    end if
    2032             : 
    2033        1536 :    ierr = pio_inq_dimlen(file, ncol_did, ncol_size)
    2034        1536 :    if (ncol_size /= dyn_cols) then
    2035           0 :       if (masterproc) then
    2036           0 :          write(iulog, '(a,2(a,i0))') trim(sub), ': ncol_size=', ncol_size, &
    2037           0 :              ' : dyn_cols=', dyn_cols
    2038             :       end if
    2039           0 :       call endrun(sub//': ERROR: dimension '//trim(ini_grid_hdim_name)//' size not same as in ncdata file')
    2040             :    end if
    2041             : 
    2042             :    ! Set coordinate name associated with ini_grid_hdim_name.
    2043        1536 :    if (trim(ini_grid_hdim_name) == 'ncol') then
    2044           0 :       coordname = 'lat'
    2045             :    else
    2046        1536 :       coordname = 'lat_d'
    2047             :    end if
    2048             : 
    2049             :    !! Check to make sure file is in correct order
    2050        1536 :    call read_dyn_var(coordname, file, ini_grid_hdim_name, dbuf2)
    2051        1536 :    found = .true.
    2052       12336 :    do ie = 1, nelemd
    2053       10800 :       indx = 1
    2054       55536 :       do j = 1, np
    2055      226800 :          do i = 1, np
    2056      172800 :             if (abs(dbuf2(indx,ie)) > 1.e-12_r8) then
    2057       96484 :                if (abs((elem(ie)%spherep(i,j)%lat*rad2deg - dbuf2(indx,ie)) / &
    2058             :                     dbuf2(indx,ie)) > 1.0e-10_r8) then
    2059             :                   write(iulog, '(2a,4(i0,a),f11.5,a,f11.5)')                  &
    2060           0 :                        "ncdata file latitudes not in correct column order",   &
    2061           0 :                        ' on task ', iam, ': elem(', ie, ')%spherep(', i,      &
    2062           0 :                        ', ', j, ')%lat = ', elem(ie)%spherep(i,j)%lat,        &
    2063           0 :                        ' /= ', dbuf2(indx, ie)*deg2rad
    2064           0 :                   call shr_sys_flush(iulog)
    2065           0 :                   found = .false.
    2066             :                end if
    2067             :             end if
    2068      216000 :             indx = indx + 1
    2069             :          end do
    2070             :       end do
    2071             :    end do
    2072        1536 :    if (.not. found) then
    2073           0 :       call endrun("ncdata file latitudes not in correct column order")
    2074             :    end if
    2075             : 
    2076        1536 :    if (trim(ini_grid_hdim_name) == 'ncol') then
    2077           0 :       coordname = 'lon'
    2078             :    else
    2079        1536 :       coordname = 'lon_d'
    2080             :    end if
    2081             : 
    2082        1536 :    call read_dyn_var(coordname, file, ini_grid_hdim_name, dbuf2)
    2083       12336 :    do ie = 1, nelemd
    2084       10800 :       indx = 1
    2085       55536 :       do j = 1, np
    2086      226800 :          do i = 1, np
    2087      172800 :             if (abs(dbuf2(indx,ie)) > 1.e-12_r8) then
    2088       97200 :                if (abs((elem(ie)%spherep(i,j)%lon*rad2deg - dbuf2(indx,ie)) / &
    2089             :                     dbuf2(indx,ie)) > 1.0e-10_r8) then
    2090             :                   write(iulog, '(2a,4(i0,a),f11.5,a,f11.5)')                  &
    2091           0 :                        "ncdata file longitudes not in correct column order",  &
    2092           0 :                        ' on task ', iam, ': elem(', ie, ')%spherep(', i,      &
    2093           0 :                        ', ', j, ')%lon = ', elem(ie)%spherep(i,j)%lon,        &
    2094           0 :                        ' /= ', dbuf2(indx, ie)*deg2rad
    2095           0 :                   call shr_sys_flush(iulog)
    2096           0 :                   found = .false.
    2097             :                end if
    2098             :             end if
    2099      216000 :             indx = indx + 1
    2100             :          end do
    2101             :       end do
    2102             :    end do
    2103        1536 :    if (.not. found) then
    2104           0 :       call endrun("ncdata file longitudes not in correct column order")
    2105             :    end if
    2106        1536 : end subroutine check_file_layout
    2107             : 
    2108             : !========================================================================================
    2109             : 
    2110       36864 : logical function dyn_field_exists(fh, fieldname, required)
    2111             : 
    2112             :    use pio,            only: var_desc_t, PIO_inq_varid
    2113             :    use pio,            only: PIO_NOERR
    2114             : 
    2115             :    type(file_desc_t), intent(in) :: fh
    2116             :    character(len=*),  intent(in) :: fieldname
    2117             :    logical, optional, intent(in) :: required
    2118             : 
    2119             :    ! Local variables
    2120             :    logical                  :: found
    2121             :    logical                  :: field_required
    2122             :    integer                  :: ret
    2123             :    type(var_desc_t)         :: varid
    2124             :    character(len=128)       :: errormsg
    2125             :    !--------------------------------------------------------------------------
    2126             : 
    2127       36864 :    if (present(required)) then
    2128       34560 :       field_required = required
    2129             :    else
    2130             :       field_required = .true.
    2131             :    end if
    2132             : 
    2133       36864 :    ret = PIO_inq_varid(fh, trim(fieldname), varid)
    2134       36864 :    found = (ret == PIO_NOERR)
    2135       36864 :    if (.not. found) then
    2136           0 :       if (field_required) then
    2137           0 :          write(errormsg, *) trim(fieldname),' was not present in the input file.'
    2138           0 :          call endrun('DYN_FIELD_EXISTS: '//errormsg)
    2139             :       end if
    2140             :    end if
    2141             : 
    2142       36864 :    dyn_field_exists = found
    2143             : 
    2144       36864 : end function dyn_field_exists
    2145             : 
    2146             : !========================================================================================
    2147             : 
    2148        5376 : subroutine read_dyn_field_2d(fieldname, fh, dimname, buffer)
    2149             : 
    2150             :    ! Dummy arguments
    2151             :    character(len=*),  intent(in)    :: fieldname
    2152             :    type(file_desc_t), intent(inout) :: fh
    2153             :    character(len=*),  intent(in)    :: dimname
    2154             :    real(r8),          intent(inout) :: buffer(:, :)
    2155             : 
    2156             :    ! Local variables
    2157             :    logical                  :: found
    2158             :    real(r8)                 :: fillvalue
    2159             :    !----------------------------------------------------------------------------
    2160             : 
    2161      647976 :    buffer = 0.0_r8
    2162             :    call infld(trim(fieldname), fh, dimname, 1, npsq, 1, nelemd, buffer,    &
    2163        5376 :         found, gridname=ini_grid_name, fillvalue=fillvalue)
    2164        5376 :    if(.not. found) then
    2165           0 :       call endrun('READ_DYN_FIELD_2D: Could not find '//trim(fieldname)//' field on input datafile')
    2166             :    end if
    2167             : 
    2168             :    ! This code allows use of compiler option to set uninitialized values
    2169             :    ! to NaN.  In that case infld can return NaNs where the element GLL points
    2170             :    ! are not "unique columns"
    2171             :    ! Set NaNs or fillvalue points to zero
    2172      647976 :    where (isnan(buffer) .or. (buffer==fillvalue)) buffer = 0.0_r8
    2173             : 
    2174        5376 : end subroutine read_dyn_field_2d
    2175             : 
    2176             : !========================================================================================
    2177             : 
    2178       33792 : subroutine read_dyn_field_3d(fieldname, fh, dimname, buffer)
    2179             : 
    2180             :    ! Dummy arguments
    2181             :    character(len=*),  intent(in)    :: fieldname
    2182             :    type(file_desc_t), intent(inout) :: fh
    2183             :    character(len=*),  intent(in)    :: dimname
    2184             :    real(r8),          intent(inout) :: buffer(:,:,:)
    2185             : 
    2186             :    ! Local variables
    2187             :    logical                  :: found
    2188             :    real(r8)                 :: fillvalue
    2189             :    !----------------------------------------------------------------------------
    2190             : 
    2191   375916992 :    buffer = 0.0_r8
    2192             :    call infld(trim(fieldname), fh, dimname, 'lev',  1, npsq, 1, nlev,         &
    2193       33792 :         1, nelemd, buffer, found, gridname=ini_grid_name, fillvalue=fillvalue)
    2194       33792 :    if(.not. found) then
    2195           0 :       call endrun('READ_DYN_FIELD_3D: Could not find '//trim(fieldname)//' field on input datafile')
    2196             :    end if
    2197             : 
    2198             :    ! This code allows use of compiler option to set uninitialized values
    2199             :    ! to NaN.  In that case infld can return NaNs where the element GLL points
    2200             :    ! are not "unique columns"
    2201             :    ! Set NaNs or fillvalue points to zero
    2202   375916992 :    where (isnan(buffer) .or. (buffer == fillvalue)) buffer = 0.0_r8
    2203             : 
    2204       33792 : end subroutine read_dyn_field_3d
    2205             : 
    2206             : !========================================================================================
    2207             : 
    2208           0 : subroutine read_phys_field_2d(fieldname, fh, dimname, buffer)
    2209             : 
    2210             :    ! Dummy arguments
    2211             :    character(len=*),  intent(in)    :: fieldname
    2212             :    type(file_desc_t), intent(inout) :: fh
    2213             :    character(len=*),  intent(in)    :: dimname
    2214             :    real(r8),          intent(inout) :: buffer(:, :)
    2215             : 
    2216             :    ! Local variables
    2217             :    logical                  :: found
    2218             :    !----------------------------------------------------------------------------
    2219             : 
    2220             :    call infld(trim(fieldname), fh, dimname, 1, fv_nphys**2, 1, nelemd, buffer,    &
    2221           0 :       found, gridname='physgrid_d')
    2222           0 :    if(.not. found) then
    2223           0 :       call endrun('READ_PHYS_FIELD_2D: Could not find '//trim(fieldname)//' field on input datafile')
    2224             :    end if
    2225             : 
    2226           0 : end subroutine read_phys_field_2d
    2227             : 
    2228             : !========================================================================================
    2229             : 
    2230           0 : subroutine map_phis_from_physgrid_to_gll(fvm,elem,phis_phys_tmp,phis_tmp,pmask)
    2231             : 
    2232             :    use hybrid_mod,         only: get_loop_ranges, config_thread_region
    2233             :    use dimensions_mod,     only: nhc_phys
    2234             :    use fvm_mapping,        only: phys2dyn
    2235             :    use thread_mod,         only: horz_num_threads
    2236             : 
    2237             :    type(element_t),   intent(inout) :: elem(:)
    2238             :    type (fvm_struct), intent(in)    :: fvm(:)
    2239             :    real(r8)         , intent(in)    :: phis_phys_tmp(fv_nphys**2,nelemd) !physgrid phis
    2240             :    real(r8)         , intent(inout) :: phis_tmp(npsq,nelemd)             !gll phis
    2241             :    logical          , intent(in)    :: pmask(npsq*nelemd)
    2242             : 
    2243             :    type(hybrid_t)                   :: hybrid
    2244             :    integer                          :: nets, nete, ie,i,j,indx
    2245           0 :    real(r8),            allocatable :: fld_phys(:,:,:,:,:),fld_gll(:,:,:,:,:)
    2246             :    logical                          :: llimiter(1)
    2247             :    !----------------------------------------------------------------------------
    2248             : 
    2249             :    !!$OMP PARALLEL NUM_THREADS(horz_num_threads), DEFAULT(SHARED), PRIVATE(hybrid,nets,nete,ie)
    2250             :    !hybrid = config_thread_region(par,'horizontal')
    2251           0 :    hybrid = config_thread_region(par,'serial')
    2252             : 
    2253           0 :    call get_loop_ranges(hybrid, ibeg=nets, iend=nete)
    2254             : 
    2255           0 :    allocate(fld_phys(1-nhc_phys:fv_nphys+nhc_phys,1-nhc_phys:fv_nphys+nhc_phys,1,1,nets:nete))
    2256           0 :    allocate(fld_gll(np,np,1,1,nets:nete))
    2257           0 :    fld_phys = 0.0_r8
    2258           0 :    do ie = nets, nete
    2259           0 :       fld_phys(1:fv_nphys,1:fv_nphys,1,1,ie) = RESHAPE(phis_phys_tmp(:,ie),(/fv_nphys,fv_nphys/))
    2260             :    end do
    2261           0 :    llimiter = .true.
    2262           0 :    call phys2dyn(hybrid,elem,fld_phys,fld_gll,nets,nete,1,1,fvm,llimiter,halo_filled=.false.)
    2263           0 :    do ie = nets,nete
    2264             :       indx = 1
    2265           0 :       do j = 1, np
    2266           0 :          do i = 1, np
    2267           0 :             if (pmask(((ie - 1) * npsq) + indx)) then
    2268           0 :                phis_tmp(indx,ie) = fld_gll(i,j,1,1,ie)
    2269             :             else
    2270           0 :                phis_tmp(indx,ie) = 0.0_r8
    2271             :             end if
    2272           0 :             indx = indx + 1
    2273             :          end do
    2274             :       end do
    2275             :    end do
    2276           0 :    deallocate(fld_phys)
    2277           0 :    deallocate(fld_gll)
    2278             :    !!$OMP END PARALLEL
    2279           0 : end subroutine map_phis_from_physgrid_to_gll
    2280             : 
    2281             : !========================================================================================
    2282             : 
    2283       14592 : subroutine write_dyn_vars(dyn_out)
    2284             : 
    2285             :    type (dyn_export_t), intent(inout) :: dyn_out ! Dynamics export container
    2286             : 
    2287             :    character(len=fieldname_len) :: tfname
    2288             :    integer                      :: ie, m
    2289             :    !----------------------------------------------------------------------------
    2290             : 
    2291       14592 :    if (use_cslam) then
    2292      117192 :       do ie = 1, nelemd
    2293           0 :          call outfld('dp_fvm', RESHAPE(dyn_out%fvm(ie)%dp_fvm(1:nc,1:nc,:), &
    2294      102600 :                                        (/nc*nc,nlev/)), nc*nc, ie)
    2295           0 :          call outfld('PSDRY_fvm', RESHAPE(dyn_out%fvm(ie)%psc(1:nc,1:nc), &
    2296      102600 :                                           (/nc*nc/)), nc*nc, ie)
    2297     4323792 :          do m = 1, ntrac
    2298     4206600 :             tfname = trim(cnst_name(m))//'_fvm'
    2299           0 :             call outfld(tfname, RESHAPE(dyn_out%fvm(ie)%c(1:nc,1:nc,:,m), &
    2300     4206600 :                                         (/nc*nc,nlev/)), nc*nc, ie)
    2301             : 
    2302     4206600 :             tfname = 'F'//trim(cnst_name(m))//'_fvm'
    2303     8413200 :             call outfld(tfname, RESHAPE(dyn_out%fvm(ie)%fc(1:nc,1:nc,:,m),&
    2304    12722400 :                                         (/nc*nc,nlev/)), nc*nc, ie)
    2305             :          end do
    2306             :       end do
    2307             :    end if
    2308             : 
    2309           0 : end subroutine write_dyn_vars
    2310             : 
    2311             : !=========================================================================================
    2312           0 : end module dyn_comp

Generated by: LCOV version 1.14