diff --git a/.github/workflows/ci_build_scm_ubuntu_22.04_nvidia.yml b/.github/workflows/ci_build_scm_ubuntu_22.04_nvidia.yml index 6c1bb116e..602263f0b 100644 --- a/.github/workflows/ci_build_scm_ubuntu_22.04_nvidia.yml +++ b/.github/workflows/ci_build_scm_ubuntu_22.04_nvidia.yml @@ -291,10 +291,12 @@ jobs: make -j - name: Download data for SCM + if: contains(matrix.enable-gpu-acc, 'False') run: | cd ${SCM_ROOT} ./contrib/get_all_static_data.sh ./contrib/get_thompson_tables.sh + ./contrib/get_aerosol_climo.sh - name: Run SCM RTs (w/o GPU) if: contains(matrix.enable-gpu-acc, 'False') diff --git a/.github/workflows/ci_test_docker.yml b/.github/workflows/ci_test_docker.yml index b1dd5e747..55ab78b26 100644 --- a/.github/workflows/ci_test_docker.yml +++ b/.github/workflows/ci_test_docker.yml @@ -28,4 +28,4 @@ jobs: run: | mkdir $HOME/output chmod a+rw $HOME/output - docker run --rm -v $HOME/output:/home ${{ env.TEST_TAG }} ./run_scm.py -f ../../test/rt_test_cases.py --runtime_mult 0.1 -d + docker run --rm -v $HOME/output:/home ${{ env.TEST_TAG }} ./run_scm.py -f ../../test/rt_test_cases.py --runtime_mult 0.1 --mpi_command "mpirun -np 1 --allow-run-as-root" -d diff --git a/ccpp/physics b/ccpp/physics index 7506fd110..f0fbb34a3 160000 --- a/ccpp/physics +++ b/ccpp/physics @@ -1 +1 @@ -Subproject commit 7506fd110dbeefca83ecc6ecd7f50c0b4989694a +Subproject commit f0fbb34a350acac90e71de6e51351f78174eb8de diff --git a/ccpp/physics_namelists/input_GFS_v15p2_RRTMGP.nml b/ccpp/physics_namelists/input_GFS_v15p2_RRTMGP.nml index 08c6af0d0..011d3b5f8 100644 --- a/ccpp/physics_namelists/input_GFS_v15p2_RRTMGP.nml +++ b/ccpp/physics_namelists/input_GFS_v15p2_RRTMGP.nml @@ -49,11 +49,11 @@ do_RRTMGP = .true. active_gases = 'h2o_co2_o3_n2o_ch4_o2' ngases = 6 - rrtmgp_root = '../../ccpp/physics/physics/rte-rrtmgp/' + rrtmgp_root = '../../ccpp/physics/physics/Radiation/RRTMGP/rte-rrtmgp/' lw_file_gas = 'rrtmgp/data/rrtmgp-data-lw-g256-2018-12-04.nc' lw_file_clouds = 'extensions/cloud_optics/rrtmgp-cloud-optics-coeffs-lw.nc' sw_file_gas = 'rrtmgp/data/rrtmgp-data-sw-g224-2018-12-04.nc' - sw_file_clouds = 'extensions/cloud_optics/rrtmgp-cloud-optics-coeffs-sw.nc' + sw_file_clouds = 'extensions/cloud_optics/rrtmgp-cloud-optics-coeffs-reordered-sw.nc' doG_cldoptics = .true. rrtmgp_ngauss_ang = 3 rrtmgp_nrghice = 3 diff --git a/ccpp/physics_namelists/input_GFS_v16_RRTMGP.nml b/ccpp/physics_namelists/input_GFS_v16_RRTMGP.nml index e9ad918cd..238d8f362 100644 --- a/ccpp/physics_namelists/input_GFS_v16_RRTMGP.nml +++ b/ccpp/physics_namelists/input_GFS_v16_RRTMGP.nml @@ -81,11 +81,11 @@ doGP_lwscat = .true. active_gases = 'h2o_co2_o3_n2o_ch4_o2' ngases = 6 - rrtmgp_root = '../../ccpp/physics/physics/rte-rrtmgp/' + rrtmgp_root = '../../ccpp/physics/physics/Radiation/RRTMGP/rte-rrtmgp/' lw_file_gas = 'rrtmgp/data/rrtmgp-data-lw-g128-210809.nc' lw_file_clouds = 'extensions/cloud_optics/rrtmgp-cloud-optics-coeffs-lw.nc' sw_file_gas = 'rrtmgp/data/rrtmgp-data-sw-g112-210809.nc' - sw_file_clouds = 'extensions/cloud_optics/rrtmgp-cloud-optics-coeffs-sw.nc' + sw_file_clouds = 'extensions/cloud_optics/rrtmgp-cloud-optics-coeffs-reordered-sw.nc' rrtmgp_nGptsSW = 112 rrtmgp_nGptsLW = 128 rrtmgp_nBandsLW = 16 diff --git a/ccpp/physics_namelists/input_GFS_v16_RRTMGP_ps.nml b/ccpp/physics_namelists/input_GFS_v16_RRTMGP_ps.nml new file mode 100644 index 000000000..8b6da35a2 --- /dev/null +++ b/ccpp/physics_namelists/input_GFS_v16_RRTMGP_ps.nml @@ -0,0 +1,158 @@ + +&gfs_physics_nml + cal_pre = .false. + cdmbgwd = 4.0, 0.15, 1.0, 1.0 + cnvcld = .true. + cnvgwd = .true. + debug = .false. + do_shum = .false. + do_skeb = .false. + do_spp = .false. + do_sppt = .false. + do_tofd = .true. + do_ugwp = .false. + dspheat = .true. + effr_in = .true. + fhcyc = 0 + fhlwr = 1200.0 + fhswr = 1200.0 + fhzero = 1.0 + h2o_phys = .true. + hybedmf = .false. + iaer = 5111 + ialb = 1 + iau_inc_files = '' + icliq_sw = 2 + ico2 = 2 + iems = 1 + imfdeepcnv = 2 + imfshalcnv = 2 + imp_physics = 11 + iopt_alb = 2 + iopt_btr = 1 + iopt_crs = 1 + iopt_dveg = 1 + iopt_frz = 1 + iopt_inf = 1 + iopt_rad = 1 + iopt_run = 1 + iopt_sfc = 1 + iopt_snf = 4 + iopt_stc = 1 + iopt_tbot = 2 + iovr = 3 + isatmedmf = 1 + isol = 2 + isot = 1 + isubc_lw = 2 + isubc_sw = 2 + ivegsrc = 1 + ldiag3d = .true. + ldiag_ugwp = .false. + lgfdlmprad = .true. + lheatstrg = .false. + lndp_type = 0 + lsm = 1 + lsoil = 4 + lwhtr = .true. + n_var_lndp = 0 + n_var_spp = 0 + nsfullradar_diag = 3600 + nst_anl = .true. + nstf_name = 2, 1, 0, 0, 0 + oz_phys = .false. + oz_phys_2015 = .true. + pdfcld = .false. + prautco = 0.00015, 0.00015 + pre_rad = .false. + print_diff_pgr = .false. + prslrd0 = 0.0 + psautco = 0.0008, 0.0005 + qdiag3d = .true. + random_clds = .false. + redrag = .true. + satmedmf = .true. + shal_cnv = .true. + swhtr = .true. + trans_trac = .true. + use_ufo = .true. + do_RRTMGP = .true. + doGP_cldoptics_LUT = .true. + doGP_lwscat = .true. + active_gases = 'h2o_co2_o3_n2o_ch4_o2' + ngases = 6 + rrtmgp_root = '../../ccpp/physics/physics/Radiation/RRTMGP/rte-rrtmgp/' + lw_file_gas = 'rrtmgp/data/rrtmgp-data-lw-g128-210809.nc' + lw_file_clouds = 'extensions/cloud_optics/rrtmgp-cloud-optics-coeffs-lw.nc' + sw_file_gas = 'rrtmgp/data/rrtmgp-data-sw-g112-210809.nc' + sw_file_clouds = 'extensions/cloud_optics/rrtmgp-cloud-optics-coeffs-reordered-sw.nc' + rrtmgp_nGptsSW = 112 + rrtmgp_nGptsLW = 128 + rrtmgp_nBandsLW = 16 + rrtmgp_nBandsSW = 14 +/ + +&gfdl_cloud_microphysics_nml + c_cracw = 0.8 + c_paut = 0.5 + c_pgacs = 0.01 + c_psaci = 0.05 + ccn_l = 300.0 + ccn_o = 100.0 + const_vg = .false. + const_vi = .false. + const_vr = .false. + const_vs = .false. + de_ice = .false. + do_qa = .false. + do_sedi_heat = .false. + dw_land = 0.16 + dw_ocean = 0.1 + fast_sat_adj = .false. + fix_negative = .true. + icloud_f = 1 + mono_prof = .true. + mp_time = 150.0 + prog_ccn = .false. + qi0_crt = 8e-05 + qi_lim = 1.0 + ql_gen = 0.001 + ql_mlt = 0.001 + qs0_crt = 0.001 + rad_graupel = .true. + rad_rain = .true. + rad_snow = .true. + reiflag = 2 + rh_inc = 0.3 + rh_inr = 0.3 + rh_ins = 0.3 + rthresh = 1e-05 + sedi_transport = .true. + tau_g2v = 900.0 + tau_i2s = 1000.0 + tau_l2v = 225.0 + tau_v2l = 150.0 + use_ccn = .true. + use_ppm = .false. + vg_max = 12.0 + vi_max = 1.0 + vr_max = 12.0 + vs_max = 2.0 + z_slope_ice = .true. + z_slope_liq = .true. +/ + +&cires_ugwp_nml + knob_ugwp_azdir = 2, 4, 4, 4 + knob_ugwp_doaxyz = 1 + knob_ugwp_doheat = 1 + knob_ugwp_dokdis = 1 + knob_ugwp_effac = 1, 1, 1, 1 + knob_ugwp_ndx4lh = 1 + knob_ugwp_solver = 2 + knob_ugwp_source = 1, 1, 0, 0 + knob_ugwp_stoch = 0, 0, 0, 0 + knob_ugwp_version = 0 + knob_ugwp_wvspec = 1, 25, 25, 25 + launch_level = 27 +/ diff --git a/ccpp/physics_namelists/input_GFS_v17_p8_ugwpv1.nml b/ccpp/physics_namelists/input_GFS_v17_p8_ugwpv1.nml index 8d859e580..a2852c3a3 100644 --- a/ccpp/physics_namelists/input_GFS_v17_p8_ugwpv1.nml +++ b/ccpp/physics_namelists/input_GFS_v17_p8_ugwpv1.nml @@ -32,9 +32,11 @@ do_ugwp_v0_orog_only = .false. do_ugwp_v0_nst_only = .false. do_gsl_drag_ls_bl = .true. - do_gsl_drag_ss = .true. + do_gsl_drag_ss = .false. do_gsl_drag_tofd = .true. do_ugwp_v1_orog_only = .false. + do_gwd_opt_psl = .true. + psl_gwd_dx_factor = 6.0 min_lakeice = 0.15 min_seaice = 1.0e-6 use_cice_alb = .true. diff --git a/ccpp/physics_namelists/input_GFS_v17_p8_ugwpv1_ps.nml b/ccpp/physics_namelists/input_GFS_v17_p8_ugwpv1_ps.nml index b2f93c79c..dfbd4af10 100644 --- a/ccpp/physics_namelists/input_GFS_v17_p8_ugwpv1_ps.nml +++ b/ccpp/physics_namelists/input_GFS_v17_p8_ugwpv1_ps.nml @@ -9,7 +9,7 @@ pre_rad = .false. imp_physics = 8 iovr = 3 - ltaerosol = .False. + ltaerosol = .false. lradar = .true. ttendlim = -999 dt_inner = 150 @@ -32,9 +32,11 @@ do_ugwp_v0_orog_only = .false. do_ugwp_v0_nst_only = .false. do_gsl_drag_ls_bl = .true. - do_gsl_drag_ss = .true. + do_gsl_drag_ss = .false. do_gsl_drag_tofd = .true. do_ugwp_v1_orog_only = .false. + do_gwd_opt_psl = .true. + psl_gwd_dx_factor = 6.0 min_lakeice = 0.15 min_seaice = 1.0e-6 use_cice_alb = .true. diff --git a/ccpp/physics_namelists/input_HRRR_gf.nml b/ccpp/physics_namelists/input_HRRR_gf.nml index 60de83a4e..427c1c96c 100644 --- a/ccpp/physics_namelists/input_HRRR_gf.nml +++ b/ccpp/physics_namelists/input_HRRR_gf.nml @@ -91,15 +91,13 @@ lradar = .true. lrefres = .true. lsm = 3 - lsoil = 9 + lsoil = 4 lsoil_lsm = 9 ltaerosol = .true. lwhtr = .true. min_lakeice = 0.15 min_seaice = 0.15 mix_chem = .true. - mosaic_lu = 1 - mosaic_soil = 1 nsfullradar_diag = 3600 oz_phys = .false. oz_phys_2015 = .true. diff --git a/docker/Dockerfile b/docker/Dockerfile index f269fff5f..97ced6d17 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -102,9 +102,11 @@ RUN cd /comsoftware/ccpp-scm/ \ #USER comuser # Set working directory -WORKDIR /comsoftware/ccpp-scm/scm/bin +WORKDIR /comsoftware/ccpp-scm/ ENV SCM_WORK=/comsoftware ENV SCM_ROOT=/comsoftware/ccpp-scm/ # For interactive use, vim mouse settings are infuriating RUN echo "set mouse=" > ~/.vimrc + +ENTRYPOINT ["sh", "-c", "./contrib/get_aerosol_climo.sh && cd /comsoftware/ccpp-scm/scm/bin"] diff --git a/scm/etc/scripts/UFS_case_gen.py b/scm/etc/scripts/UFS_case_gen.py index 54802d3a7..c6f1dfab1 100755 --- a/scm/etc/scripts/UFS_case_gen.py +++ b/scm/etc/scripts/UFS_case_gen.py @@ -56,6 +56,8 @@ missing_variable_snow_layers = 3 missing_variable_soil_layers = 4 missing_variable_ice_layers = 2 +missing_variable_vegetation_categories = 20 +missing_variable_soil_categories = 16 # Path to the directory containing processed case input files PROCESSED_CASE_DIR = '../../data/processed_case_input' @@ -1686,7 +1688,7 @@ def get_UFS_surface_data(dir, tile, i, j, old_chgres, lam): ######################################################################################## # ######################################################################################## -def get_UFS_oro_data(dir, tile, i, j, lam): +def get_UFS_oro_data(dir, tile, i, j, lam, old_chgres): """Get the orographic data for the given tile and indices""" if lam: @@ -1721,6 +1723,9 @@ def get_UFS_oro_data(dir, tile, i, j, lam): #lake variables (optional) lake_frac_in = read_NetCDF_var(nc_file, "lake_frac", i, j) lake_depth_in = read_NetCDF_var(nc_file, "lake_depth", i, j) + + vegtype_frac_in = read_NetCDF_surface_var(nc_file, "vegetation_type_pct", i, j, old_chgres, missing_variable_vegetation_categories) + soiltype_frac_in = read_NetCDF_surface_var(nc_file, "soil_type_pct", i, j, old_chgres, missing_variable_soil_categories) # nc_file.close() @@ -1744,7 +1749,9 @@ def get_UFS_oro_data(dir, tile, i, j, lam): "oro_uf": orog_raw_in, "landfrac": land_frac_in, "lakefrac": lake_frac_in, - "lakedepth": lake_depth_in} + "lakedepth": lake_depth_in, + "vegtype_frac": vegtype_frac_in, + "soiltype_frac": soiltype_frac_in} return oro @@ -3208,6 +3215,8 @@ def write_SCM_case_file(state, surface, oro, forcing, init, case, date, forcing_ snow_dim = nc_file.createDimension('nsnow', len(surface["snicexy"])) nslsnw_dim = nc_file.createDimension('nsoil_plus_nsnow',len(surface["snicexy"]) + len(surface["stc"])) ice_dim = nc_file.createDimension('nice', len(surface["tiice"])) + vegcat_dim = nc_file.createDimension('nvegcat', len(oro["vegtype_frac"])) + soilcat_dim =nc_file.createDimension('nsoilcat', len(oro["soiltype_frac"])) # timei_var = nc_file.createVariable('t0', wp, ('t0')) @@ -3388,7 +3397,9 @@ def write_SCM_case_file(state, surface, oro, forcing, init, case, date, forcing_ {"name": "oro_uf", "type":wp, "dimd": ('t0'), "units": "m", "desc": "unfiltered orography"}, \ {"name": "landfrac", "type":wp, "dimd": ('t0'), "units": "none", "desc": "fraction of horizontal grid area occupied by land"}, \ {"name": "lakefrac", "type":wp, "dimd": ('t0'), "units": "none", "desc": "fraction of horizontal grid area occupied by lake", "default_value":0}, \ - {"name": "lakedepth", "type":wp, "dimd": ('t0'), "units": "none", "desc": "lake depth", "default_value":0}] + {"name": "lakedepth", "type":wp, "dimd": ('t0'), "units": "none", "desc": "lake depth", "default_value":0}, + {"name": "vegtype_frac", "type":wp, "dimd": ('t0', 'nvegcat'), "units": "none", "desc": "fraction of horizontal grid area occupied by given vegetation category"}, + {"name": "soiltype_frac","type":wp, "dimd": ('t0', 'nsoilcat'), "units": "none", "desc": "fraction of horizontal grid area occupied by given soil category"}] # var_nsst = [{"name": "tref", "type":wp, "dimd": ('t0'), "units": "K", "desc": "sea surface reference temperature for NSST"}, \ {"name": "z_c", "type":wp, "dimd": ('t0'), "units": "m", "desc": "sub-layer cooling thickness for NSST"}, \ @@ -3682,7 +3693,7 @@ def main(): check_IC_hist_surface_compatibility(forcing_dir, hist_i, hist_j, surface_data, lam, old_chgres, tile) #read in orographic data for the initial conditions at the IC point - oro_data = get_UFS_oro_data(in_dir, tile, IC_i, IC_j, lam) + oro_data = get_UFS_oro_data(in_dir, tile, IC_i, IC_j, lam, old_chgres) #read in the initial condition profiles diff --git a/scm/etc/tracer_config/tracers_GFS_v17_p8_ugwpv1.txt b/scm/etc/tracer_config/tracers_GFS_v17_p8_ugwpv1.txt new file mode 100644 index 000000000..eeba3d9e3 --- /dev/null +++ b/scm/etc/tracer_config/tracers_GFS_v17_p8_ugwpv1.txt @@ -0,0 +1,11 @@ +"sphum","water_vapor_specific_humidity","kg kg-1" +"liq_wat","cloud_condensed_water_mixing_ratio","kg kg-1" +"ice_wat","ice_water_mixing_ratio","kg kg-1" +"rainwat","rain_water_mixing_ratio","kg kg-1" +"snowwat","snow_water_mixing_ratio","kg kg-1" +"graupel","graupel_mixing_ratio","kg kg-1" +"ice_nc","ice_number_concentration","kg-1" +"rain_nc","rain_number_concentration","kg-1" +"o3mr","ozone_mixing_ratio","kg kg-1" +"sgs_tke","turbulent_kinetic_energy","m2 s-2" +"sigmab"," prognostic_updraft_area_fraction_in_convection","frac" diff --git a/scm/src/scm_input.F90 b/scm/src/scm_input.F90 index 59229cf68..8d3d2cda5 100644 --- a/scm/src/scm_input.F90 +++ b/scm/src/scm_input.F90 @@ -13,6 +13,8 @@ module scm_input integer :: missing_snow_layers = 3 integer :: missing_soil_layers = 4 integer :: missing_ice_layers = 2 +integer :: missing_nvegcat = 20 +integer :: missing_nsoilcat = 16 contains @@ -218,6 +220,7 @@ subroutine get_case_init(scm_state, scm_input) integer :: input_nice !< number of sea ice levels in the input file integer :: input_ntimes !< number of times represented in the input file integer :: input_nsoil_plus_nsnow !< number of combined snow and soil levels in the input file + integer :: input_nvegcat, input_nsoilcat real(kind=dp) :: input_lat !< column latitude (deg) real(kind=dp) :: input_lon !< column longitude (deg) real(kind=dp) :: input_area !< surface area [m^2] @@ -458,7 +461,19 @@ subroutine get_case_init(scm_state, scm_input) else call check(NF90_INQUIRE_DIMENSION(ncid, varID, tmpName, input_nice),"nf90_inq_dim(nice)") end if - + ierr = NF90_INQ_DIMID(ncid,"nvegcat",varID) + if(ierr /= NF90_NOERR) then + input_nvegcat = missing_nvegcat + else + call check(NF90_INQUIRE_DIMENSION(ncid, varID, tmpName, input_nvegcat),"nf90_inq_dim(nvegcat)") + end if + ierr = NF90_INQ_DIMID(ncid,"nsoilcat",varID) + if(ierr /= NF90_NOERR) then + input_nsoilcat = missing_nsoilcat + else + call check(NF90_INQUIRE_DIMENSION(ncid, varID, tmpName, input_nsoilcat),"nf90_inq_dim(nsoilcat)") + end if + !> - Allocate the dimension variables. allocate(input_pres(input_nlev),input_time(input_ntimes), stat=allocate_status) @@ -713,8 +728,8 @@ subroutine get_case_init(scm_state, scm_input) call check(NF90_CLOSE(NCID=ncid),"nf90_close()") - call scm_input%create(input_ntimes, input_nlev, input_nsoil, input_nsnow, input_nice) - + call scm_input%create(input_ntimes, input_nlev, input_nsoil, input_nsnow, input_nice, input_nvegcat, input_nsoilcat) + ! GJF already done in scm_input%create routine !scm_input%input_nlev = input_nlev !scm_input%input_ntimes = input_ntimes @@ -1049,7 +1064,9 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) real(kind=dp), allocatable :: input_landfrac(:) !< fraction of horizontal grid area occupied by land real(kind=dp), allocatable :: input_lakefrac(:) !< fraction of horizontal grid area occupied by lake real(kind=dp), allocatable :: input_lakedepth(:) !< lake depth (m) - + real(kind=dp), allocatable :: input_vegtype_frac(:,:) !< fraction of horizontal grid area occupied by given vegetation category + real(kind=dp), allocatable :: input_soiltype_frac(:,:) !< fraction of horizontal grid area occupied by given soil category + real(kind=dp), allocatable :: input_tvxy(:) !< vegetation temperature (K) real(kind=dp), allocatable :: input_tgxy(:) !< ground temperature for Noahmp (K) real(kind=dp), allocatable :: input_tahxy(:) !< canopy air temperature (K) @@ -1164,8 +1181,8 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) integer :: jdat(1:8), idat(1:8) !(yr, mon, day, t-zone, hr, min, sec, mil-sec) logical :: needed_for_lsm_ics, needed_for_model_ics, lev_in_altitude - integer :: input_n_init_times, input_n_forcing_times, input_n_lev, input_n_snow, input_n_ice, input_n_soil - + integer :: input_n_init_times, input_n_forcing_times, input_n_lev, input_n_snow, input_n_ice, input_n_soil, input_nvegcat, input_nsoilcat + missing_value_eps = missing_value + 0.01 !> - Open the case input file found in the processed_case_input dir corresponding to the experiment name. @@ -1213,7 +1230,19 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) else call check(NF90_INQUIRE_DIMENSION(ncid, varID, tmpName, input_n_ice),"nf90_inq_dim(nice)") end if - + ierr = NF90_INQ_DIMID(ncid,"nvegcat",varID) + if(ierr /= NF90_NOERR) then + input_nvegcat = missing_nvegcat + else + call check(NF90_INQUIRE_DIMENSION(ncid, varID, tmpName, input_nvegcat),"nf90_inq_dim(nvegcat)") + end if + ierr = NF90_INQ_DIMID(ncid,"nsoilcat",varID) + if(ierr /= NF90_NOERR) then + input_nsoilcat = missing_nsoilcat + else + call check(NF90_INQUIRE_DIMENSION(ncid, varID, tmpName, input_nsoilcat),"nf90_inq_dim(nsoilcat)") + end if + !> - Allocate the dimension variables. allocate(input_t0 (input_n_init_times), & input_time (input_n_forcing_times), & @@ -1398,6 +1427,8 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) input_landfrac ( input_n_init_times), & input_lakefrac ( input_n_init_times), & input_lakedepth ( input_n_init_times), & + input_vegtype_frac (input_nvegcat, input_n_init_times), & + input_soiltype_frac (input_nsoilcat, input_n_init_times),& stat=allocate_status) allocate(input_tvxy ( input_n_init_times), & input_tgxy ( input_n_init_times), & @@ -1539,6 +1570,8 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) call NetCDF_read_var(ncid, "landfrac", needed_for_model_ics, input_landfrac) call NetCDF_read_var(ncid, "lakefrac", needed_for_model_ics, input_lakefrac) call NetCDF_read_var(ncid, "lakedepth", needed_for_model_ics, input_lakedepth) + call NetCDF_read_var(ncid, "vegtype_frac", needed_for_model_ics, input_vegtype_frac) + call NetCDF_read_var(ncid, "soiltype_frac", needed_for_model_ics, input_soiltype_frac) !NSST variables call NetCDF_read_var(ncid, "tref", needed_for_model_ics, input_tref) @@ -1800,9 +1833,9 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) call check(NF90_CLOSE(NCID=ncid),"nf90_close()") - - call scm_input%create(input_n_forcing_times, input_n_lev, input_n_soil, input_n_snow, input_n_ice) - + + call scm_input%create(input_n_forcing_times, input_n_lev, input_n_soil, input_n_snow, input_n_ice, input_nvegcat, input_nsoilcat) + !fill the scm_input DDT !There may need to be logic to control which of the lon, lat, and init_times to use in the future, but for now, just take the first @@ -2042,7 +2075,9 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) scm_input%input_landfrac = input_landfrac(active_init_time) scm_input%input_lakefrac = input_lakefrac(active_init_time) scm_input%input_lakedepth= input_lakedepth(active_init_time) - + scm_input%input_vegtype_frac = input_vegtype_frac(:,active_init_time) + scm_input%input_soiltype_frac = input_soiltype_frac(:,active_init_time) + scm_input%input_tref = input_tref(active_init_time) scm_input%input_z_c = input_z_c(active_init_time) scm_input%input_c_0 = input_c_0(active_init_time) diff --git a/scm/src/scm_type_defs.F90 b/scm/src/scm_type_defs.F90 index 64c4289c0..664b91de6 100644 --- a/scm/src/scm_type_defs.F90 +++ b/scm/src/scm_type_defs.F90 @@ -180,6 +180,8 @@ module scm_type_defs integer :: input_nsoil !< number of soil levels in the input file integer :: input_nsnow !< number of snow layers in the input file integer :: input_nice !< number of sea ice layers in the input file + integer :: input_nvegcat !< number of vegetation type categories + integer :: input_nsoilcat !< number of soil type categories integer :: input_ntimes !< number of times in the input file where forcing is available real(kind=dp) :: input_lat !< latitude of column center real(kind=dp) :: input_lon !< longitude of column center @@ -262,6 +264,8 @@ module scm_type_defs real(kind=dp) :: input_landfrac !< fraction of horizontal grid area occupied by land real(kind=dp) :: input_lakefrac !< fraction of horizontal grid area occupied by lake real(kind=dp) :: input_lakedepth !< lake depth (m) + real(kind=dp), allocatable :: input_vegtype_frac(:) !< fraction of horizontal grid area occupied by given vegetation category + real(kind=dp), allocatable :: input_soiltype_frac(:) !< fraction of horizontal grid area occupied by given soil category real(kind=dp) :: input_tvxy !< vegetation temperature (K) real(kind=dp) :: input_tgxy !< ground temperature for Noahmp (K) @@ -668,14 +672,16 @@ subroutine scm_state_create(scm_state, n_columns, n_levels, n_soil, n_snow, n_ti end subroutine scm_state_create - subroutine scm_input_create(scm_input, ntimes, nlev, nsoil, nsnow, nice) + subroutine scm_input_create(scm_input, ntimes, nlev, nsoil, nsnow, nice, nvegcat, nsoilcat) class(scm_input_type) :: scm_input - integer, intent(in) :: ntimes, nlev, nsoil, nsnow, nice + integer, intent(in) :: ntimes, nlev, nsoil, nsnow, nice, nvegcat, nsoilcat scm_input%input_nlev = nlev scm_input%input_nsoil = nsoil scm_input%input_nsnow = nsnow scm_input%input_nice = nice + scm_input%input_nvegcat = nvegcat + scm_input%input_nsoilcat = nsoilcat scm_input%input_ntimes = ntimes scm_input%input_lat = real_zero @@ -762,6 +768,10 @@ subroutine scm_input_create(scm_input, ntimes, nlev, nsoil, nsnow, nice) scm_input%input_landfrac = real_zero scm_input%input_lakefrac = real_zero scm_input%input_lakedepth = real_zero + allocate(scm_input%input_vegtype_frac(nvegcat)) + scm_input%input_vegtype_frac = real_zero + allocate(scm_input%input_soiltype_frac(nsoilcat)) + scm_input%input_soiltype_frac = real_zero scm_input%input_tvxy = real_zero scm_input%input_tgxy = real_zero @@ -1082,8 +1092,13 @@ subroutine physics_set(physics, scm_input, scm_state) call conditionally_set_var(scm_input%input_elvmax, physics%Sfcprop%hprime(i,14), "elvmax", .true., missing_var(14)) call conditionally_set_var(scm_input%input_oro, physics%Sfcprop%oro(i), "oro", .true., missing_var(15)) call conditionally_set_var(scm_input%input_oro_uf, physics%Sfcprop%oro_uf(i), "oro_uf", (physics%Model%do_ugwp .and. physics%Model%nmtvr == 14), missing_var(16)) - - n = 19 + call conditionally_set_var(scm_input%input_landfrac, physics%Sfcprop%landfrac(i), "landfrac", physics%Model%frac_grid, missing_var(17)) + call conditionally_set_var(scm_input%input_lakefrac, physics%Sfcprop%lakefrac(i), "lakefrac", (physics%Model%lkm == 1), missing_var(18)) + call conditionally_set_var(scm_input%input_lakedepth, physics%Sfcprop%lakedepth(i), "lakedepth", (physics%Model%lkm == 1), missing_var(19)) + call conditionally_set_var(scm_input%input_vegtype_frac(:), physics%Sfcprop%vegtype_frac(i,:), "vegtype_frac", .true., missing_var(20)) + call conditionally_set_var(scm_input%input_soiltype_frac(:), physics%Sfcprop%soiltype_frac(i,:), "soiltype_frac", .true., missing_var(21)) + + n = 21 if ( i==1 .and. ANY( missing_var(1:n) ) ) then write(0,'(a)') "INPUT CHECK: Some missing input data was found related to (potentially non-required) orography and gravity wave drag parameters. This may lead to crashes or other strange behavior." write(0,'(a)') "Check scm_type_defs.F90/physics_set to see the names of variables that are missing, corresponding to the following indices:" @@ -1094,20 +1109,6 @@ subroutine physics_set(physics, scm_input, scm_state) missing_var = .false. end if - ! Variables found in orographic dataset but needed for non-orographic reasons (e.g. lake model, fractional grid) - call conditionally_set_var(scm_input%input_landfrac, physics%Sfcprop%landfrac(i), "landfrac", physics%Model%frac_grid, missing_var(1)) - call conditionally_set_var(scm_input%input_lakefrac, physics%Sfcprop%lakefrac(i), "lakefrac", (physics%Model%lkm == 1), missing_var(2)) - call conditionally_set_var(scm_input%input_lakedepth, physics%Sfcprop%lakedepth(i), "lakedepth", (physics%Model%lkm == 1), missing_var(3)) - n = 3 - if ( i==1 .and. ANY( missing_var(1:n) ) ) then - write(0,'(a)') "INPUT CHECK: Some missing input data was found related to (potentially non-required) lake-related or fractional grid-related variables. This may lead to crashes or other strange behavior." - write(0,'(a)') "Check scm_type_defs.F90/physics_set to see the names of variables that are missing, corresponding to the following indices:" - do j=1, n - if (missing_var(j)) write(0,'(a,i0)') "variable index ",j - end do - end if - missing_var = .false. - ! ! Surface data (2D) ! @@ -1214,7 +1215,7 @@ subroutine physics_set(physics, scm_input, scm_state) ! Derive physics quantities using surface model ICs. ! if(scm_state%model_ics .or. scm_state%lsm_ics) then - if (physics%Sfcprop%stype(i) == 14 .or. physics%Sfcprop%stype(i) <= 0) then + if (physics%Sfcprop%stype(i) == 14 .or. physics%Sfcprop%stype(i)+0.5 <= 0) then physics%Sfcprop%landfrac(i) = real_zero physics%Sfcprop%stype(i) = 0 if (physics%Sfcprop%lakefrac(i) > real_zero) then @@ -1316,7 +1317,7 @@ subroutine physics_set(physics, scm_input, scm_state) ! NSSTM variables ! if (physics%Model%nstf_name(1) > 0) then - if (physics%Model%nstf_name(2) == 1 .or. .not. (scm_state%model_ics .or. scm_state%lsm_ics)) then + if (physics%Model%nstf_name(2) == 1 .or. .not. (scm_state%model_ics)) then physics%Sfcprop%tref(i) = physics%Sfcprop%tsfco(i) physics%Sfcprop%z_c(i) = real_zero physics%Sfcprop%c_0(i) = real_zero diff --git a/scm/src/scm_vgrid.F90 b/scm/src/scm_vgrid.F90 index e492824fe..ca7a4ca69 100644 --- a/scm/src/scm_vgrid.F90 +++ b/scm/src/scm_vgrid.F90 @@ -553,7 +553,7 @@ subroutine get_FV3_vgrid(scm_input, scm_state) do k=1, km+1 pres_i(:,k) = scm_state%a_k(k) + scm_state%b_k(k)*p_ref scm_state%si(:,k) = scm_state%a_k(k)*pres_sfc_inv + scm_state%b_k(k) - scm_state%exner_i(:,k) = (scm_state%pres_i(:,k)/1.0E5)**con_rocp + scm_state%exner_i(:,k) = (pres_i(:,k)/1.0E5)**con_rocp end do scm_state%pres_i = pres_i diff --git a/scm/src/suite_info.py b/scm/src/suite_info.py index 97aebaf5f..299ca4d6e 100755 --- a/scm/src/suite_info.py +++ b/scm/src/suite_info.py @@ -43,7 +43,7 @@ def timestep(self, value): suite_list = [] suite_list.append(suite('SCM_GFS_v16', 'tracers_GFS_v16.txt', 'input_GFS_v16.nml', 600.0, 1800.0, True )) -suite_list.append(suite('SCM_GFS_v17_p8_ugwpv1', 'tracers_GFS_v17_p8.txt', 'input_GFS_v17_p8_ugwpv1.nml', 600.0, 600.0, True )) +suite_list.append(suite('SCM_GFS_v17_p8_ugwpv1', 'tracers_GFS_v17_p8_ugwpv1.txt', 'input_GFS_v17_p8_ugwpv1.nml', 600.0, 600.0, True )) suite_list.append(suite('SCM_RAP', 'tracers_RAP.txt', 'input_RAP.nml', 600.0, 600.0 , True )) suite_list.append(suite('SCM_HRRR_gf', 'tracers_HRRR_gf.txt', 'input_HRRR_gf.nml', 600.0, 600.0 , True )) suite_list.append(suite('SCM_WoFS_v0', 'tracers_WoFS_v0.txt', 'input_WoFS_v0.nml', 600.0, 600.0 , True ))