diff --git a/.gitmodules b/.gitmodules index dc508d842c..88d8acb0b3 100644 --- a/.gitmodules +++ b/.gitmodules @@ -52,7 +52,7 @@ fxDONOTUSEurl = https://github.com/ESCOMP/RTM [submodule "mosart"] path = components/mosart url = https://github.com/ESCOMP/MOSART -fxtag = mosart1.1.12 +fxtag = mosart1.1.13 fxrequired = ToplevelRequired # Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed fxDONOTUSEurl = https://github.com/ESCOMP/MOSART @@ -68,7 +68,7 @@ fxDONOTUSEurl = https://github.com/ESCOMP/mizuRoute [submodule "ccs_config"] path = ccs_config url = https://github.com/ESMCI/ccs_config_cesm.git -fxtag = ccs_config_cesm1.0.66 +fxtag = ccs_config_cesm1.0.75 fxrequired = ToplevelRequired # Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed fxDONOTUSEurl = https://github.com/ESMCI/ccs_config_cesm.git @@ -92,7 +92,7 @@ fxDONOTUSEurl = https://github.com/ESCOMP/CMEPS.git [submodule "cdeps"] path = components/cdeps url = https://github.com/ESCOMP/CDEPS.git -fxtag = cdeps1.0.92 +fxtag = cdeps1.0.93 fxrequired = ToplevelRequired # Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed fxDONOTUSEurl = https://github.com/ESCOMP/CDEPS.git diff --git a/bld/CLMBuildNamelist.pm b/bld/CLMBuildNamelist.pm index e2d7ee06bc..3d88d133a1 100755 --- a/bld/CLMBuildNamelist.pm +++ b/bld/CLMBuildNamelist.pm @@ -1834,6 +1834,11 @@ sub process_namelist_inline_logic { ################################## setup_logic_cropcal_streams($opts, $nl_flags, $definition, $defaults, $nl); + ################################## + # namelist group: distparams_streams # + ################################## + setup_logic_distparams_streams($opts, $nl_flags, $definition, $defaults, $nl); + ########################################## # namelist group: soil_moisture_streams # ########################################## @@ -1893,11 +1898,6 @@ sub process_namelist_inline_logic { ##################################### setup_logic_canopy($opts, $nl_flags, $definition, $defaults, $nl); - ######################################## - # namelist group: soilhydrology_inparm # - ######################################## - setup_logic_hydrology_params($opts, $nl_flags, $definition, $defaults, $nl); - ##################################### # namelist group: irrigation_inparm # ##################################### @@ -3354,28 +3354,6 @@ sub setup_logic_supplemental_nitrogen { #------------------------------------------------------------------------------- -sub setup_logic_hydrology_params { - # - # Logic for hydrology parameters - # - my ($opts, $nl_flags, $definition, $defaults, $nl) = @_; - - my $lower = $nl->get_value( 'lower_boundary_condition' ); - my $var = "baseflow_scalar"; - if ( $lower == 1 || $lower == 2 ) { - add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, - $var, 'lower_boundary_condition' => $lower ); - } - my $val = $nl->get_value( $var ); - if ( defined($val) ) { - if ( $lower != 1 && $lower != 2 ) { - $log->fatal_error("baseflow_scalar is only used for lower_boundary_condition of flux or zero-flux"); - } - } -} - -#------------------------------------------------------------------------------- - sub setup_logic_irrigation_parameters { my ($opts, $nl_flags, $definition, $defaults, $nl) = @_; @@ -4627,6 +4605,25 @@ sub setup_logic_cropcal_streams { #------------------------------------------------------------------------------- +sub setup_logic_distparams_streams { + my ($opts, $nl_flags, $definition, $defaults, $nl) = @_; + + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'use_distributed_parameters'); + + # Add defaults if using any crop calendar input files + my $distparams_file = $nl->get_value('stream_fldFileName_distparams') ; + my $mesh_file = $nl->get_value('stream_meshfile_distparams') ; + + # User provided an input file but set mesh file to empty + if ( !&string_is_undef_or_empty($distparams_file)) { + if ( &string_is_undef_or_empty($mesh_file) ) { + $log->fatal_error("If providing a spatially distributed parameter file, you must provide stream_meshfile_distparams" ); + } + } +} + +#------------------------------------------------------------------------------- + sub setup_logic_soilwater_movement { my ($opts, $nl_flags, $definition, $defaults, $nl) = @_; @@ -4865,19 +4862,6 @@ sub setup_logic_atm_forcing { } } } - - foreach $var ("precip_repartition_glc_all_snow_t", - "precip_repartition_glc_all_rain_t", - "precip_repartition_nonglc_all_snow_t", - "precip_repartition_nonglc_all_rain_t") { - if ( &value_is_true($nl->get_value("repartition_rain_snow")) ) { - add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var); - } else { - if (defined($nl->get_value($var))) { - $log->fatal_error("$var can only be set if repartition_rain_snow is true"); - } - } - } } #------------------------------------------------------------------------------- @@ -5427,11 +5411,11 @@ sub write_output_files { @groups = qw(clm_inparm ndepdyn_nml popd_streams urbantv_streams light_streams soil_moisture_streams lai_streams atm2lnd_inparm lnd2atm_inparm clm_canopyhydrology_inparm cnphenology - cropcal_streams megan_opts + cropcal_streams megan_opts distparams_streams clm_soilhydrology_inparm dynamic_subgrid cnvegcarbonstate finidat_consistency_checks dynpft_consistency_checks clm_initinterp_inparm century_soilbgcdecompcascade - soilhydrology_inparm luna friction_velocity mineral_nitrogen_dynamics + luna friction_velocity mineral_nitrogen_dynamics soilwater_movement_inparm rooting_profile_inparm soil_resis_inparm bgc_shared canopyfluxes_inparm aerosol clmu_inparm clm_soilstate_inparm clm_nitrogen clm_snowhydrology_inparm hillslope_hydrology_inparm hillslope_properties_inparm diff --git a/bld/namelist_files/namelist_defaults_ctsm.xml b/bld/namelist_files/namelist_defaults_ctsm.xml index 6819fad02c..933751f401 100644 --- a/bld/namelist_files/namelist_defaults_ctsm.xml +++ b/bld/namelist_files/namelist_defaults_ctsm.xml @@ -148,7 +148,7 @@ attributes from the config_cache.xml file (with keys converted to upper-case). lnd/clm2/isotopes/atm_delta_C14_CMIP6_SSP5B_3x1_global_1850-2100_yearly_c181209.nc -lnd/clm2/isotopes/ctsmforc.Graven.atm_delta_C14_CMIP7_360x720_1700-2023_yearly_v3.0_tweaked_latlons_c260108.nc +lnd/clm2/isotopes/ctsmforc.Graven.atm_delta_C14_CMIP7_360x720_1700-2023_yearly_v3.0_tweaked_latlons_c260108.no_nan_fill.nc share/meshes/360x720_120830_ESMFmesh_tweaked_latlons_c20260108.nc @@ -273,11 +273,6 @@ attributes from the config_cache.xml file (with keys converted to upper-case). 1 0 - -0.001d00 -1.d-2 -1.d-2 - 2.0d00 2.0d00 @@ -306,20 +301,6 @@ attributes from the config_cache.xml file (with keys converted to upper-case). 0.5 -0. -2. - --2. -0. - -0. -2. - .true. .false. @@ -623,10 +604,10 @@ attributes from the config_cache.xml file (with keys converted to upper-case). -lnd/clm2/paramdata/ctsm60_params.c260204.nc -ctsm60-cam70_params.c260204.nc -lnd/clm2/paramdata/clm50_params.c250311.nc -lnd/clm2/paramdata/clm45_params.c250311.nc +lnd/clm2/paramdata/ctsm60_params.c260303.nc +ctsm60-cam70_params.c260305.nc +lnd/clm2/paramdata/clm50_params.c260305.nc +lnd/clm2/paramdata/clm45_params.c260305.nc @@ -1828,7 +1809,7 @@ lnd/clm2/surfdata_esmf/ctsm5.4.0/surfdata_10x15_hist_2000_78pfts_c251022.nc -lnd/clm2/surfdata_esmf/ctsm5.4.0/surfdata_1x1_brazil_hist_2000_78pfts_c251023.nc +lnd/clm2/surfdata_esmf/ctsm5.4.0/surfdata_1x1_brazil_hist_2000_78pfts_c251023.no_nan_fill.nc lnd/clm2/surfdata_esmf/ctsm5.4.0/surfdata_5x5_amazon_hist_2000_78pfts_c251022.nc @@ -1851,7 +1832,7 @@ lnd/clm2/surfdata_esmf/ctsm5.4.0/surfdata_360x720cru_hist_2000_78pfts_c251022.nc lnd/clm2/surfdata_esmf/ctsm5.4.0/surfdata_C96_hist_2000_78pfts_c251022.nc -lnd/clm2/surfdata_esmf/ctsm5.4.0/surfdata_1x1_numaIA_hist_2000_78pfts_c251023.nc +lnd/clm2/surfdata_esmf/ctsm5.4.0/surfdata_1x1_numaIA_hist_2000_78pfts_c251023.no_nan_fill.nc @@ -1880,11 +1861,11 @@ lnd/clm2/surfdata_esmf/ctsm5.4.0/surfdata_ne0np4CONUS.ne30x8_hist_2000_78pfts_c2 -lnd/clm2/surfdata_esmf/ctsm5.4.0/surfdata_1x1_vancouverCAN_hist_2000_78pfts_c251023.nc +lnd/clm2/surfdata_esmf/ctsm5.4.0/surfdata_1x1_vancouverCAN_hist_2000_78pfts_c251023.no_nan_fill.nc -lnd/clm2/surfdata_esmf/ctsm5.4.0/surfdata_1x1_mexicocityMEX_hist_2000_78pfts_c251023.nc +lnd/clm2/surfdata_esmf/ctsm5.4.0/surfdata_1x1_mexicocityMEX_hist_2000_78pfts_c251023.no_nan_fill.nc -lnd/clm2/surfdata_esmf/ctsm5.4.0/synthetic/surfdata_1x1_urbanc_alpha_synth_hist_2000_78pfts_c251023.nc +lnd/clm2/surfdata_esmf/ctsm5.4.0/synthetic/surfdata_1x1_urbanc_alpha_synth_hist_2000_78pfts_c251023.no_nan_fill.nc @@ -1941,11 +1922,11 @@ lnd/clm2/surfdata_esmf/ctsm5.4.0/surfdata_ne3np4_hist_1850_78pfts_c251022.nc lnd/clm2/surfdata_esmf/ctsm5.4.0/surfdata_C96_hist_1850_78pfts_c251022.nc -lnd/clm2/surfdata_esmf/ctsm5.4.0/synthetic/surfdata_1x1_smallvilleIA_synth_hist_1850_78pfts_c251023.nc +lnd/clm2/surfdata_esmf/ctsm5.4.0/synthetic/surfdata_1x1_smallvilleIA_synth_hist_1850_78pfts_c251023.no_nan_fill.nc -lnd/clm2/surfdata_esmf/ctsm5.4.0/synthetic/surfdata_1x1_cidadinhoBR_synth_hist_2000_78pfts_c251023.nc +lnd/clm2/surfdata_esmf/ctsm5.4.0/synthetic/surfdata_1x1_cidadinhoBR_synth_hist_2000_78pfts_c251023.no_nan_fill.nc -lnd/clm2/surfdata_esmf/ctsm5.4.0/surfdata_1x1_brazil_hist_1850_78pfts_c251023.nc +lnd/clm2/surfdata_esmf/ctsm5.4.0/surfdata_1x1_brazil_hist_1850_78pfts_c251023.no_nan_fill.nc lnd/clm2/surfdata_esmf/ctsm5.4.0/surfdata_ne16np4.pg3_hist_1850_78pfts_c251022.nc @@ -2034,7 +2015,7 @@ lnd/clm2/surfdata_esmf/NEON/ctsm5.4.0/surfdata_1x1_NEON_TOOL_hist_2000_78pfts_c2 >lnd/clm2/surfdata_esmf/ctsm5.4.0/landuse.timeseries_360x720cru_hist_1850-2023_78pfts_c251022.nc lnd/clm2/surfdata_esmf/ctsm5.4.0/landuse.timeseries_1x1_brazil_hist_1850-2023_78pfts_c251023.nc +>lnd/clm2/surfdata_esmf/ctsm5.4.0/landuse.timeseries_1x1_brazil_hist_1850-2023_78pfts_c251023.no_nan_fill.nc lnd/clm2/surfdata_esmf/ctsm5.4.0/landuse.timeseries_mpasa120_hist_1850-2023_78pfts_c251022.nc @@ -2063,7 +2044,7 @@ lnd/clm2/surfdata_esmf/NEON/ctsm5.4.0/surfdata_1x1_NEON_TOOL_hist_2000_78pfts_c2 lnd/clm2/surfdata_esmf/ctsm5.4.0/synthetic/landuse.timeseries_1x1_smallvilleIA_synth_1850-1855_78pfts_c251023.nc +>lnd/clm2/surfdata_esmf/ctsm5.4.0/synthetic/landuse.timeseries_1x1_smallvilleIA_synth_1850-1855_78pfts_c251023.no_nan_fill.nc @@ -2090,7 +2071,7 @@ lnd/clm2/surfdata_esmf/NEON/ctsm5.4.0/surfdata_1x1_NEON_TOOL_hist_2000_78pfts_c2 >lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_360x720cru_SSP2-4.5_1850-2100_78pfts_c240908.nc lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_1x1_brazil_SSP2-4.5_1850-2100_78pfts_c240912.nc +>lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_1x1_brazil_SSP2-4.5_1850-2100_78pfts_c240912.no_nan_fill.nc lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_mpasa120_SSP2-4.5_1850-2100_78pfts_c240908.nc @@ -2131,14 +2112,14 @@ lnd/clm2/surfdata_esmf/NEON/ctsm5.4.0/surfdata_1x1_NEON_TOOL_hist_2000_78pfts_c2 lnd/clm2/surfdata_map/fates-sci.1.68.3_api.31.0.0_tools.1.0.1/LUH2_states_transitions_management.timeseries_4x5_hist_simyr1850-2015_c231101.nc + >lnd/clm2/surfdata_map/fates-sci.1.68.3_api.31.0.0_tools.1.0.1/LUH2_states_transitions_management.timeseries_4x5_hist_simyr1850-2015_c231101.no_nan_fill.nc -lnd/clm2/surfdata_map/fates-sci.1.77.0_api.36.0.0/fates_landuse_pft_map_4x5_240206.nc +lnd/clm2/surfdata_map/fates-sci.1.77.0_api.36.0.0/fates_landuse_pft_map_4x5_240206.no_nan_fill.nc lnd/clm2/surfdata_map/fates-sci.1.68.3_api.31.0.0_tools.1.0.1/LUH2_states_transitions_management.timeseries_4x5_hist_simyr0850-2015_c240216.nc + >lnd/clm2/surfdata_map/fates-sci.1.68.3_api.31.0.0_tools.1.0.1/LUH2_states_transitions_management.timeseries_4x5_hist_simyr0850-2015_c240216.no_nan_fill.nc .false. @@ -2298,30 +2279,36 @@ lnd/clm2/surfdata_esmf/NEON/ctsm5.4.0/surfdata_1x1_NEON_TOOL_hist_2000_78pfts_c2 2000 -lnd/clm2/cropdata/calendars/processed/cultivar_gdds.c251211.tweaked_latlons.nc -lnd/clm2/cropdata/calendars/processed/gdds_20230829_161011.tweaked_latlons.nc -lnd/clm2/cropdata/calendars/processed/gdds_20230829_161011.tweaked_latlons.nc -lnd/clm2/cropdata/calendars/processed/gdds_20230829_161011.tweaked_latlons.nc -lnd/clm2/cropdata/calendars/processed/cultivar_gdds.c251211.tweaked_latlons.nc -lnd/clm2/cropdata/calendars/processed/gdds_20230829_161011.tweaked_latlons.nc -lnd/clm2/cropdata/calendars/processed/gdds_20230829_161011.tweaked_latlons.nc -lnd/clm2/cropdata/calendars/processed/gdds_20230829_161011.tweaked_latlons.nc +lnd/clm2/cropdata/calendars/processed/cultivar_gdds.c251211.tweaked_latlons.no_nan_fill.nc +lnd/clm2/cropdata/calendars/processed/gdds_20230829_161011.tweaked_latlons.no_nan_fill.nc +lnd/clm2/cropdata/calendars/processed/gdds_20230829_161011.tweaked_latlons.no_nan_fill.nc +lnd/clm2/cropdata/calendars/processed/gdds_20230829_161011.tweaked_latlons.no_nan_fill.nc +lnd/clm2/cropdata/calendars/processed/cultivar_gdds.c251211.tweaked_latlons.no_nan_fill.nc +lnd/clm2/cropdata/calendars/processed/gdds_20230829_161011.tweaked_latlons.no_nan_fill.nc +lnd/clm2/cropdata/calendars/processed/gdds_20230829_161011.tweaked_latlons.no_nan_fill.nc +lnd/clm2/cropdata/calendars/processed/gdds_20230829_161011.tweaked_latlons.no_nan_fill.nc -lnd/clm2/cropdata/calendars/processed/swindow_starts_ggcmi_crop_calendar_phase3_v1.01.2000-2000.20231005_145103.tweaked_latlons.nc -lnd/clm2/cropdata/calendars/processed/swindow_ends_ggcmi_crop_calendar_phase3_v1.01.2000-2000.20231005_145103.tweaked_latlons.nc -lnd/clm2/cropdata/calendars/processed/360x720_120830_ESMFmesh_c20210507_cdf5.tweaked_latlons.nc -lnd/clm2/cropdata/calendars/processed/swindow_starts_ggcmi_crop_calendar_phase3_v1.01.2000-2000.20231005_145103.tweaked_latlons.nc -lnd/clm2/cropdata/calendars/processed/swindow_ends_ggcmi_crop_calendar_phase3_v1.01.2000-2000.20231005_145103.tweaked_latlons.nc -lnd/clm2/cropdata/calendars/processed/gdd20_baseline.c251120.tweaked_latlons.nc -lnd/clm2/cropdata/calendars/processed/20230714_cropcals_pr2_1deg.actually2deg.1980-2009.from_GDDB20.interpd_halfdeg.tweaked_latlons.nc -lnd/clm2/cropdata/calendars/processed/20230714_cropcals_pr2_1deg.actually2deg.1980-2009.from_GDDB20.interpd_halfdeg.tweaked_latlons.nc -lnd/clm2/cropdata/calendars/processed/20230714_cropcals_pr2_1deg.actually2deg.1980-2009.from_GDDB20.interpd_halfdeg.tweaked_latlons.nc -lnd/clm2/cropdata/calendars/processed/gdd20bl.copied_from.gdds_20230829_161011.v2.tweaked_latlons.nc -lnd/clm2/cropdata/calendars/processed/sdates_ggcmi_crop_calendar_phase3_v1.01_nninterp-hcru_hcru_mt13.2000-2000.20230728_165845.tweaked_latlons.nc -lnd/clm2/cropdata/calendars/processed/hdates_ggcmi_crop_calendar_phase3_v1.01_nninterp-hcru_hcru_mt13.2000-2000.20230728_165845.tweaked_latlons.nc -lnd/clm2/cropdata/calendars/processed/360x720_120830_ESMFmesh_c20210507_cdf5.tweaked_latlons.nc - +lnd/clm2/cropdata/calendars/processed/swindow_starts_ggcmi_crop_calendar_phase3_v1.01.2000-2000.20231005_145103.tweaked_latlons.no_nan_fill.nc +lnd/clm2/cropdata/calendars/processed/swindow_ends_ggcmi_crop_calendar_phase3_v1.01.2000-2000.20231005_145103.tweaked_latlons.no_nan_fill.nc +lnd/clm2/cropdata/calendars/processed/360x720_120830_ESMFmesh_c20210507_cdf5.tweaked_latlons.no_nan_fill.nc +lnd/clm2/cropdata/calendars/processed/swindow_starts_ggcmi_crop_calendar_phase3_v1.01.2000-2000.20231005_145103.tweaked_latlons.no_nan_fill.nc +lnd/clm2/cropdata/calendars/processed/swindow_ends_ggcmi_crop_calendar_phase3_v1.01.2000-2000.20231005_145103.tweaked_latlons.no_nan_fill.nc +lnd/clm2/cropdata/calendars/processed/gdd20_baseline.c251120.tweaked_latlons.no_nan_fill.nc +lnd/clm2/cropdata/calendars/processed/20230714_cropcals_pr2_1deg.actually2deg.1980-2009.from_GDDB20.interpd_halfdeg.tweaked_latlons.no_nan_fill.nc +lnd/clm2/cropdata/calendars/processed/20230714_cropcals_pr2_1deg.actually2deg.1980-2009.from_GDDB20.interpd_halfdeg.tweaked_latlons.no_nan_fill.nc +lnd/clm2/cropdata/calendars/processed/20230714_cropcals_pr2_1deg.actually2deg.1980-2009.from_GDDB20.interpd_halfdeg.tweaked_latlons.no_nan_fill.nc +lnd/clm2/cropdata/calendars/processed/gdd20bl.copied_from.gdds_20230829_161011.v2.tweaked_latlons.no_nan_fill.nc +lnd/clm2/cropdata/calendars/processed/sdates_ggcmi_crop_calendar_phase3_v1.01_nninterp-hcru_hcru_mt13.2000-2000.20230728_165845.tweaked_latlons.no_nan_fill.nc +lnd/clm2/cropdata/calendars/processed/hdates_ggcmi_crop_calendar_phase3_v1.01_nninterp-hcru_hcru_mt13.2000-2000.20230728_165845.tweaked_latlons.no_nan_fill.nc +lnd/clm2/cropdata/calendars/processed/360x720_120830_ESMFmesh_c20210507_cdf5.tweaked_latlons.no_nan_fill.nc + + +.false. + + +no_file_yet +no_file_yet diff --git a/bld/namelist_files/namelist_definition_ctsm.xml b/bld/namelist_files/namelist_definition_ctsm.xml index 1808f03215..1a3c31f082 100644 --- a/bld/namelist_files/namelist_definition_ctsm.xml +++ b/bld/namelist_files/namelist_definition_ctsm.xml @@ -415,12 +415,6 @@ Max number of iterations used in subr. CanopyFluxes. For many years, 40 was the If TRUE use clm5 equation for fraction of intercepted precipitation - -Scalar multiplier for base flow rate -(ONLY used if lower_boundary_condition is not aquifer or table) - - Index of solution method of Richards equation. @@ -1728,30 +1722,6 @@ This parameter must be in the range [0,1] Only relevant if glcmec_downscale_longwave is .true. - -Temperature below which all precipitation falls as snow, for glacier columns (deg C) -Only relevant if repartition_rain_snow is .true. - - - -Temperature above which all precipitation falls as rain, for glacier columns (deg C) -Only relevant if repartition_rain_snow is .true. - - - -Temperature below which all precipitation falls as snow, for non-glacier columns (deg C) -Only relevant if repartition_rain_snow is .true. - - - -Temperature above which all precipitation falls as rain, for non-glacier columns (deg C) -Only relevant if repartition_rain_snow is .true. - - @@ -2189,6 +2159,26 @@ Filename of input stream data for date (day of year) of end of gdd20 accumulatio Filename of input stream data for crop calendar inputs + + + + + + +Flag to enable spatially distributed parameters + + + +Filename of input stream data for spatially distributed parameters + + + +Filename of mesh data for spatially distributed parameters + + diff --git a/ccs_config b/ccs_config index 76370cc085..e5833b40b4 160000 --- a/ccs_config +++ b/ccs_config @@ -1 +1 @@ -Subproject commit 76370cc08587fd653458cdfb2e0b220b3168ded6 +Subproject commit e5833b40b47f54f9203474c6c3e01b656e92c25f diff --git a/cime_config/testdefs/ExpectedTestFails.xml b/cime_config/testdefs/ExpectedTestFails.xml index 1e82513737..6314965cd0 100644 --- a/cime_config/testdefs/ExpectedTestFails.xml +++ b/cime_config/testdefs/ExpectedTestFails.xml @@ -60,6 +60,72 @@ #2784 + + + FAIL + #3790 + + + + + FAIL + #3790 + + + + + FAIL + #3790 + + + + + FAIL + #3790 + + + + + FAIL + #3790 + + + + + FAIL + #3790 + + + + + FAIL + #3792 + + + + + FAIL + #3792 + + + + + FAIL + #3792 + + + + + FAIL + #3792 + + + + + FAIL + #3792 + + @@ -176,8 +242,23 @@ + + + FAIL + #3788 + + + + + + FAIL + #3660 + Restart issues with default "inactive" fields added to history by hist_all_fields. + + + diff --git a/cime_config/testdefs/testlist_clm.xml b/cime_config/testdefs/testlist_clm.xml index 27c52a3510..9afc04267d 100644 --- a/cime_config/testdefs/testlist_clm.xml +++ b/cime_config/testdefs/testlist_clm.xml @@ -109,6 +109,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/cime_config/testdefs/testmods_dirs/clm/GddGen/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/GddGen/user_nl_clm index 00e045888c..8d467950b3 100644 --- a/cime_config/testdefs/testmods_dirs/clm/GddGen/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/GddGen/user_nl_clm @@ -1,6 +1,6 @@ cropcals_rx = .true. -stream_fldFileName_swindow_start = '$DIN_LOC_ROOT/lnd/clm2/cropdata/calendars/processed/sdates_ggcmi_crop_calendar_phase3_v1.01_nninterp-hcru_hcru_mt13.2000-2000.20230728_165845.tweaked_latlons.nc' -stream_fldFileName_swindow_end = '$DIN_LOC_ROOT/lnd/clm2/cropdata/calendars/processed/sdates_ggcmi_crop_calendar_phase3_v1.01_nninterp-hcru_hcru_mt13.2000-2000.20230728_165845.tweaked_latlons.nc' +stream_fldFileName_swindow_start = '$DIN_LOC_ROOT/lnd/clm2/cropdata/calendars/processed/sdates_ggcmi_crop_calendar_phase3_v1.01_nninterp-hcru_hcru_mt13.2000-2000.20230728_165845.tweaked_latlons.no_nan_fill.nc' +stream_fldFileName_swindow_end = '$DIN_LOC_ROOT/lnd/clm2/cropdata/calendars/processed/sdates_ggcmi_crop_calendar_phase3_v1.01_nninterp-hcru_hcru_mt13.2000-2000.20230728_165845.tweaked_latlons.no_nan_fill.nc' stream_fldFileName_cultivar_gdds = '' generate_crop_gdds = .true. use_mxmat = .false. diff --git a/cime_config/testdefs/testmods_dirs/clm/Hillslope/shell_commands b/cime_config/testdefs/testmods_dirs/clm/Hillslope/shell_commands index 9cef7eb66f..45391a1554 100644 --- a/cime_config/testdefs/testmods_dirs/clm/Hillslope/shell_commands +++ b/cime_config/testdefs/testmods_dirs/clm/Hillslope/shell_commands @@ -5,10 +5,10 @@ DIN_LOC_ROOT=$(./xmlquery --value DIN_LOC_ROOT) lnd_grid=$(./xmlquery --value LND_GRID) if [[ ${lnd_grid} == "10x15" ]]; then # Synthetic data - hillslope_file='$DIN_LOC_ROOT/lnd/clm2/testdata/surfdata_10x15_hist_1850_78pfts_c240216.synth_hillslopes_241001.nc' + hillslope_file='$DIN_LOC_ROOT/lnd/clm2/testdata/surfdata_10x15_hist_1850_78pfts_c240216.synth_hillslopes_241001.no_nan_fill.nc' elif [[ ${lnd_grid} == "5x5_amazon" ]]; then # Real data - hillslope_file='/glade/derecho/scratch/samrabin/hillslopes_5x5_amazon/hand_analysis_global/combined/hilldata_5x5_amazon_hist_2000_78pfts_c240216.nc' + hillslope_file='$DIN_LOC_ROOT/lnd/clm2/testdata/hilldata_5x5_amazon_hist_2000_78pfts_c240216.nc' else echo "ERROR: Hillslope file not found for LND_GRID=${lnd_grid}" >&2 exit 1 diff --git a/cime_config/testdefs/testmods_dirs/clm/ciso_cwd_hr/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/ciso_cwd_hr/user_nl_clm index 6caaaa7018..3ba9e4bf8c 100644 --- a/cime_config/testdefs/testmods_dirs/clm/ciso_cwd_hr/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/ciso_cwd_hr/user_nl_clm @@ -1,2 +1,2 @@ -paramfile = '$DIN_LOC_ROOT/lnd/clm2/paramdata/ctsm60_ciso_cwd_hr_params.c250311.nc' +paramfile = '$DIN_LOC_ROOT/lnd/clm2/paramdata/ctsm60_ciso_cwd_hr_params.c250311.no_nan_fill.nc' hist_fincl1 = 'CWDC_HR','C13_CWDC_HR','C14_CWDC_HR','CWD_HR_L2','CWD_HR_L2_vr','CWD_HR_L3','CWD_HR_L3_vr' diff --git a/cime_config/testdefs/testmods_dirs/clm/clm60_monthly_matrixcn_soilCN30/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/clm60_monthly_matrixcn_soilCN30/user_nl_clm index 2a1a84fb8c..b008abff87 100644 --- a/cime_config/testdefs/testmods_dirs/clm/clm60_monthly_matrixcn_soilCN30/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/clm60_monthly_matrixcn_soilCN30/user_nl_clm @@ -1,2 +1,2 @@ use_soil_matrixcn = .true. -paramfile = '$DIN_LOC_ROOT/lnd/clm2/paramdata/ctsm60_params_cn30.c250311.nc' +paramfile = '$DIN_LOC_ROOT/lnd/clm2/paramdata/ctsm60_params_cn30.c250311.no_nan_fill.nc' diff --git a/cime_config/testdefs/testmods_dirs/clm/f09_constant2DDistParams/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/f09_constant2DDistParams/include_user_mods new file mode 100644 index 0000000000..fe0e18cf88 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/f09_constant2DDistParams/include_user_mods @@ -0,0 +1 @@ +../default diff --git a/cime_config/testdefs/testmods_dirs/clm/f09_constant2DDistParams/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/f09_constant2DDistParams/user_nl_clm new file mode 100644 index 0000000000..9937d487c9 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/f09_constant2DDistParams/user_nl_clm @@ -0,0 +1,6 @@ +! Turn on distributed parameters with values that are just copies of the 1D parameter file +! So tests with this and without distributed parameters should compare exactly +use_distributed_parameters = TRUE +! The distparam file MUST match the model resolution +stream_fldfilename_distparams = '$DIN_LOC_ROOT/lnd/clm2/paramdata/ctsm60_2Dparamdata_0.9x1.25_distparams_constant_ident2_ctsm60260303params_c260306.nc' +stream_meshfile_distparams = '$LND_DOMAIN_MESH' diff --git a/cime_config/testdefs/testmods_dirs/clm/leafcn_t_evolving/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/leafcn_t_evolving/user_nl_clm index 443e9ac1e5..2e7d4f6167 100644 --- a/cime_config/testdefs/testmods_dirs/clm/leafcn_t_evolving/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/leafcn_t_evolving/user_nl_clm @@ -1 +1 @@ -paramfile = '$DIN_LOC_ROOT/lnd/clm2/paramdata/ctsm60_ceta450_cn30_co2_slope30.c250326.nc' +paramfile = '$DIN_LOC_ROOT/lnd/clm2/paramdata/ctsm60_ceta450_cn30_co2_slope30.c250326.no_nan_fill.nc' diff --git a/cime_config/testdefs/testmods_dirs/clm/nnStreamMapAlgo/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/nnStreamMapAlgo/user_nl_clm index 316860ffa5..1328c99ca9 100644 --- a/cime_config/testdefs/testmods_dirs/clm/nnStreamMapAlgo/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/nnStreamMapAlgo/user_nl_clm @@ -17,8 +17,8 @@ use_c14_bombspike = .true. cropcals_rx = .true. cropcals_rx_adapt = .false. ! If cropcals_rx is on, rx_adapt must be off stream_gdd20_seasons = .true. -stream_fldFileName_swindow_start = '$DIN_LOC_ROOT/lnd/clm2/cropdata/calendars/processed/sdates_ggcmi_crop_calendar_phase3_v1.01_nninterp-hcru_hcru_mt13.2000-2000.20230728_165845.tweaked_latlons.nc' -stream_fldFileName_swindow_end = '$DIN_LOC_ROOT/lnd/clm2/cropdata/calendars/processed/sdates_ggcmi_crop_calendar_phase3_v1.01_nninterp-hcru_hcru_mt13.2000-2000.20230728_165845.tweaked_latlons.nc' +stream_fldFileName_swindow_start = '$DIN_LOC_ROOT/lnd/clm2/cropdata/calendars/processed/sdates_ggcmi_crop_calendar_phase3_v1.01_nninterp-hcru_hcru_mt13.2000-2000.20230728_165845.tweaked_latlons.no_nan_fill.nc' +stream_fldFileName_swindow_end = '$DIN_LOC_ROOT/lnd/clm2/cropdata/calendars/processed/sdates_ggcmi_crop_calendar_phase3_v1.01_nninterp-hcru_hcru_mt13.2000-2000.20230728_165845.tweaked_latlons.no_nan_fill.nc' stream_year_first_urbantv = 2106 ! Set urban time varying streams to a late year so that it has values diff --git a/cime_config/testdefs/testmods_dirs/clm/smallville_dynlakes_monthly/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/smallville_dynlakes_monthly/user_nl_clm index 46680fd36d..561273e5ab 100644 --- a/cime_config/testdefs/testmods_dirs/clm/smallville_dynlakes_monthly/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/smallville_dynlakes_monthly/user_nl_clm @@ -6,7 +6,7 @@ do_transient_lakes = .true. ! Key points are that lake area starts as 0, increases after the first year, then decreases after the second year. ! PCT_CROP is also changed so that PCT_LAKE + PCT_CROP <= 100. (Here, PCT_CROP increases and decreases at the same time as PCT_LAKE in order to exercise the simultaneous increase or decrease of two landunits, but that isn't a critical part of this test.) ! Note that the use of this file means that this testmod can only be used with the 1x1_smallvilleIA grid. -flanduse_timeseries = '$DIN_LOC_ROOT/lnd/clm2/surfdata_esmf/ctsm5.4.0/synthetic/landuse.timeseries_1x1_smallvilleIA_synth_1850-1855_78pfts_dynLakes_c251023.nc' +flanduse_timeseries = '$DIN_LOC_ROOT/lnd/clm2/surfdata_esmf/ctsm5.4.0/synthetic/landuse.timeseries_1x1_smallvilleIA_synth_1850-1855_78pfts_dynLakes_c251023.no_nan_fill.nc' ! NOTE slevis (2024/2/23) Adding option for tests to pass. In the long term ! ensure that subset_data generates fsurdat and landuse files consistent with diff --git a/cime_config/testdefs/testmods_dirs/clm/smallville_dynurban_monthly/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/smallville_dynurban_monthly/user_nl_clm index bb18638158..f978b18832 100644 --- a/cime_config/testdefs/testmods_dirs/clm/smallville_dynurban_monthly/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/smallville_dynurban_monthly/user_nl_clm @@ -7,7 +7,7 @@ do_transient_urban = .true. ! Medium density urban is set to zero to test the memory-saving behavior of PCT_URBAN_MAX. ! PCT_CROP is also changed so that PCT_URBAN + PCT_CROP <= 100. (Here, PCT_CROP increases and decreases at the same time as PCT_URBAN in order to exercise the simultaneous increase or decrease of two landunits, but that isn't a critical part of this test.) ! Note that the use of this file means that this testmod can only be used with the 1x1_smallvilleIA grid. -flanduse_timeseries = '$DIN_LOC_ROOT/lnd/clm2/surfdata_esmf/ctsm5.4.0/synthetic/landuse.timeseries_1x1_smallvilleIA_synth_1850-1855_78pfts_dynUrban_c251023.nc' +flanduse_timeseries = '$DIN_LOC_ROOT/lnd/clm2/surfdata_esmf/ctsm5.4.0/synthetic/landuse.timeseries_1x1_smallvilleIA_synth_1850-1855_78pfts_dynUrban_c251023.no_nan_fill.nc' ! NOTE slevis (2024/2/23) Adding option for tests to pass. In the long term ! ensure that subset_data generates fsurdat and landuse files consistent with diff --git a/components/cdeps b/components/cdeps index 099fdb8ca0..3f7f22d042 160000 --- a/components/cdeps +++ b/components/cdeps @@ -1 +1 @@ -Subproject commit 099fdb8ca006511c82783e52a19b28b63250ba6e +Subproject commit 3f7f22d0426ccc1428a1ebfd4357caf90009132a diff --git a/components/mosart b/components/mosart index 0faa624a59..a6f6e90606 160000 --- a/components/mosart +++ b/components/mosart @@ -1 +1 @@ -Subproject commit 0faa624a59b5ce677c40ed64f1ca65bb4997db8d +Subproject commit a6f6e90606e362aa6367f7003cb4c130c4664bc6 diff --git a/doc/ChangeLog b/doc/ChangeLog index c838859b0c..9e4e07a7bc 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,4 +1,126 @@ =============================================================== +Tag name: ctsm5.4.022 +Originator(s): erik (Erik Kluzek) +Date: Wed Mar 4 10:52:05 AM MST 2026 +One-line Summary: Change to using the ifx compiler and some more fixes related to it + +Purpose and description of changes +---------------------------------- + +Updates ccs_config to 1.0.75 which has the new ifx compiler in use for derecho_intel, as well as updating to using ESMF8.9.0. This exposed problems in the code on two fronts when running with DEBUG mode: + +Reliance on short-circuiting in if statements +Problems with NaN's, in datasets especially _FillValue +For the former, we changed code to break up if statements so this would work. And with the latter we point to new datasets with the NaN's handled. mosart and cdeps code also had short-circuiting problems. + +@samsrabin created a script to examine all of the files in namelist_defaults_ctsm.xml and in the testmod directories to check if there were problems with NaN's in _FillValues. The modified files here all were the result +of the first pass of that script. The new files all have a ".no_nan_fill.nc" ending on them. + +Includes updating submodules: ccs_config, cdeps, mosart + +Contributors: @samsrabin @billsacks +------------- + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[x] clm6_0 + +[x] clm5_0 + +[x] ctsm5_0-nwp + +[x] clm4_5 + + +Bugs fixed +---------- + +List of CTSM issues fixed (include CTSM Issue # and description) [one per line]: + Work on #3775 -- NaN's in _FillValue of some input datasets + Fixes #3794 -- Update to ccs_config1.0.75 + +Notes of particular relevance for users +--------------------------------------- + +Changes to the datasets (e.g., streams, surface or initial files): + Datasets with a ".no_nan_fill.nc" at the end were modified to remove NaN's in _FillValue + +Notes of particular relevance for developers: +--------------------------------------------- + +Caveats for developers (e.g., code that is duplicated that requires double maintenance): + This includes most of the files that have problems with NaN's + But, there are a few more that will be resolved after this tag. + aux_clm works fine with the exception of a hillslope test that now fails. + +Changes to tests or testing: + Added a bunch of tests to expected fails that will be resolved later + Update files in testmods that have issues + +Testing summary: regular, ctsm_sci, fates, crop_calendars +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + derecho -OK + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + derecho - PASS + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- OK + izumi ------- OK + + fates tests: (give name of baseline if different from CTSM tagname, normally fates baselines are fates--) + derecho ----- OK + izumi ------- OK + + any other testing (give details below): + + ctsm_sci + derecho ---- OK + crop_calendars + derecho ---- OK + +If the tag used for baseline comparisons was NOT the previous tag, note that here: + + +Answer changes +-------------- + +Changes answers relative to baseline: Yes for derecho_intel! + + Summarize any changes to answers, i.e., + - what code configurations: All + - what platforms/compilers: ONLY for Derecho with the intel compiler + (because of the updated ccs_config submodule) + - nature of change: We expect it to be roundoff, but haven't confirmed + +Other details +------------- + +List any git submodules updated (cime, rtm, mosart, cism, fates, etc.): + ccs_config to ccs_config_cesm1.0.75 + mosart to mosart1.1.13 + cdeps to cdeps1.0.93 + +Pull Requests that document the changes (include PR ids): +(https://github.com/ESCOMP/ctsm/pull) + #3787 -- Replace some netCDF inputs that have NaN fill values (@samsrabin) + #3769 -- Update to ifx compiler + +=============================================================== +=============================================================== Tag name: ctsm5.4.021 Originator(s): erik (Erik Kluzek,UCAR/TSS,303-497-1326) Date: Fri Feb 20 08:19:42 PM MST 2026 diff --git a/doc/ChangeSum b/doc/ChangeSum index 3c9781ad49..c935595869 100644 --- a/doc/ChangeSum +++ b/doc/ChangeSum @@ -1,5 +1,6 @@ Tag Who Date Summary ============================================================================================================================ + ctsm5.4.022 erik 03/04/2026 Change to using the ifx compiler and some more fixes related to it ctsm5.4.021 erik 02/20/2026 Bring b4b-dev to master ctsm5.4.020 slevis 02/19/2026 Address carbon cycle and fire biases in CESM3 development runs by updating namelist defaults ctsm5.4.019 samrabin 02/12/2026 Fix years used by generate_gdds diff --git a/src/biogeophys/CanopyHydrologyMod.F90 b/src/biogeophys/CanopyHydrologyMod.F90 index 166aa6d53d..a64c2e99fa 100644 --- a/src/biogeophys/CanopyHydrologyMod.F90 +++ b/src/biogeophys/CanopyHydrologyMod.F90 @@ -31,8 +31,9 @@ module CanopyHydrologyMod use WaterStateBulkType , only : waterstatebulk_type use WaterDiagnosticBulkType , only : waterdiagnosticbulk_type use WaterTracerUtils , only : CalcTracerFromBulk - use ColumnType , only : col, column_type - use PatchType , only : patch, patch_type + use ColumnType , only : col, column_type + use PatchType , only : patch, patch_type + ! ! !PUBLIC TYPES: implicit none diff --git a/src/biogeophys/InfiltrationExcessRunoffMod.F90 b/src/biogeophys/InfiltrationExcessRunoffMod.F90 index fff6a799ab..d5e4acc3b4 100644 --- a/src/biogeophys/InfiltrationExcessRunoffMod.F90 +++ b/src/biogeophys/InfiltrationExcessRunoffMod.F90 @@ -14,9 +14,10 @@ module InfiltrationExcessRunoffMod use clm_varcon , only : spval use SoilHydrologyType, only : soilhydrology_type use SoilStateType , only : soilstate_type + use DistParamType , only : distparams => distributed_parameters use SaturatedExcessRunoffMod, only : saturated_excess_runoff_type - use WaterFluxBulkType , only : waterfluxbulk_type - use WaterDiagnosticBulkType, only : waterdiagnosticbulk_type + use WaterFluxBulkType , only : waterfluxbulk_type + use WaterDiagnosticBulkType , only : waterdiagnosticbulk_type implicit none save @@ -267,6 +268,8 @@ subroutine ComputeQinmaxHksat(bounds, num_hydrologyc, filter_hydrologyc, & soilhydrology_inst, soilstate_inst, & qinmax_on_unsaturated_area) ! + ! USES + use ColumnType , only : col ! !DESCRIPTION: ! Compute qinmax using a parameterization based on hksat ! @@ -296,7 +299,7 @@ subroutine ComputeQinmaxHksat(bounds, num_hydrologyc, filter_hydrologyc, & do fc = 1, num_hydrologyc c = filter_hydrologyc(fc) - qinmax_on_unsaturated_area(c) = minval(10._r8**(-params_inst%e_ice*(icefrac(c,1:3)))*hksat(c,1:3)) + qinmax_on_unsaturated_area(c) = minval(10._r8**(-distparams%e_ice%param_val(col%gridcell(c))*(icefrac(c,1:3)))*hksat(c,1:3)) end do end associate diff --git a/src/biogeophys/SaturatedExcessRunoffMod.F90 b/src/biogeophys/SaturatedExcessRunoffMod.F90 index 9956a7dfb8..cdee4c7ec2 100644 --- a/src/biogeophys/SaturatedExcessRunoffMod.F90 +++ b/src/biogeophys/SaturatedExcessRunoffMod.F90 @@ -16,9 +16,10 @@ module SaturatedExcessRunoffMod use clm_varcon , only : spval,ispval use LandunitType , only : landunit_type use landunit_varcon , only : istcrop - use ColumnType , only : column_type + use ColumnType , only : column_type + use DistParamType , only : distparams => distributed_parameters use SoilHydrologyType, only : soilhydrology_type - use SoilStateType, only : soilstate_type + use SoilStateType , only : soilstate_type use WaterFluxBulkType, only : waterfluxbulk_type implicit none @@ -50,12 +51,6 @@ module SaturatedExcessRunoffMod procedure, private, nopass :: ComputeFsatTopmodel procedure, private, nopass :: ComputeFsatVic end type saturated_excess_runoff_type - public :: readParams - - type, private :: params_type - real(r8) :: fff ! Decay factor for fractional saturated area (1/m) - end type params_type - type(params_type), private :: params_inst ! !PRIVATE DATA MEMBERS: @@ -175,26 +170,6 @@ subroutine InitCold(this, bounds) end subroutine InitCold - !----------------------------------------------------------------------- - subroutine readParams( ncid ) - ! - ! !USES: - use ncdio_pio, only: file_desc_t - use paramUtilMod, only: readNcdioScalar - ! - ! !ARGUMENTS: - implicit none - type(file_desc_t),intent(inout) :: ncid ! pio netCDF file id - ! - ! !LOCAL VARIABLES: - character(len=*), parameter :: subname = 'readParams_SaturatedExcessRunoff' - !-------------------------------------------------------------------- - - ! Decay factor for fractional saturated area (1/m) - call readNcdioScalar(ncid, 'fff', subname, params_inst%fff) - - end subroutine readParams - ! ======================================================================== ! Science routines ! ======================================================================== @@ -315,6 +290,8 @@ end subroutine SaturatedExcessRunoff subroutine ComputeFsatTopmodel(bounds, num_hydrologyc, filter_hydrologyc, & soilhydrology_inst, soilstate_inst, fsat) ! + ! USES + use ColumnType , only : col ! !DESCRIPTION: ! Compute fsat using the TOPModel-based parameterization ! @@ -349,9 +326,9 @@ subroutine ComputeFsatTopmodel(bounds, num_hydrologyc, filter_hydrologyc, & c = filter_hydrologyc(fc) if (frost_table(c) > zwt_perched(c) .and. frost_table(c) <= zwt(c)) then ! use perched water table to determine fsat (if present) - fsat(c) = wtfact(c) * exp(-0.5_r8*params_inst%fff*zwt_perched(c)) + fsat(c) = wtfact(c) * exp(-0.5_r8*distparams%fff%param_val(col%gridcell(c))*zwt_perched(c)) else - fsat(c) = wtfact(c) * exp(-0.5_r8*params_inst%fff*zwt(c)) + fsat(c) = wtfact(c) * exp(-0.5_r8*distparams%fff%param_val(col%gridcell(c))*zwt(c)) end if end do diff --git a/src/biogeophys/SnowCoverFractionSwensonLawrence2012Mod.F90 b/src/biogeophys/SnowCoverFractionSwensonLawrence2012Mod.F90 index f6a5ff41ee..a791b7ffe1 100644 --- a/src/biogeophys/SnowCoverFractionSwensonLawrence2012Mod.F90 +++ b/src/biogeophys/SnowCoverFractionSwensonLawrence2012Mod.F90 @@ -20,6 +20,7 @@ module SnowCoverFractionSwensonLawrence2012Mod use fileutils , only : getavu, relavu, opnfil use clm_varcon , only : rpi use ColumnType , only : column_type + use DistParamType , only : distparams => distributed_parameters use glcBehaviorMod , only : glc_behavior_type use landunit_varcon, only : istice use paramUtilMod , only : readNcdioScalar @@ -44,7 +45,6 @@ module SnowCoverFractionSwensonLawrence2012Mod procedure, public :: Init procedure, private :: ReadNamelist - procedure, private :: ReadParams procedure, private :: CheckValidInputs procedure, private :: SetDerivedParameters end type snow_cover_fraction_swenson_lawrence_2012_type @@ -66,6 +66,8 @@ subroutine UpdateSnowDepthAndFrac(this, bounds, num_c, filter_c, & lun_itype_col, urbpoi, h2osno_total, snowmelt, int_snow, newsnow, bifall, & snow_depth, frac_sno, frac_sno_eff) ! + ! USES + use ColumnType , only : col ! !DESCRIPTION: ! Update snow depth and snow fraction using the SwensonLawrence2012 parameterization ! @@ -121,7 +123,7 @@ subroutine UpdateSnowDepthAndFrac(this, bounds, num_c, filter_c, & ! fsca parameterization based on *changes* in swe if (h2osno_total(c) == 0._r8) then if (newsnow(c) > 0._r8) then - frac_sno(c) = tanh(this%accum_factor * newsnow(c)) + frac_sno(c) = tanh(distparams%accum_factor%param_val(col%gridcell(c)) * newsnow(c)) else ! NOTE(wjs, 2019-08-07) This resetting of frac_sno to 0 when h2osno_total is 0 ! may already be done elsewhere; if it isn't, it possibly *should* be done @@ -146,7 +148,7 @@ subroutine UpdateSnowDepthAndFrac(this, bounds, num_c, filter_c, & ! ! This form is algebraically equivalent, but simpler and less prone to ! roundoff errors (see https://github.com/ESCOMP/ctsm/issues/784) - frac_sno(c) = frac_sno(c) + tanh(this%accum_factor * newsnow(c)) * (1._r8 - frac_sno(c)) + frac_sno(c) = frac_sno(c) + tanh(distparams%accum_factor%param_val(col%gridcell(c)) * newsnow(c)) * (1._r8 - frac_sno(c)) end if end if @@ -291,7 +293,6 @@ subroutine Init(this, bounds, col, glc_behavior, NLFilename, params_ncid) type(file_desc_t) , intent(inout) :: params_ncid ! pio netCDF file id for parameter file ! ! !LOCAL VARIABLES: - real(r8) :: n_melt_coef ! n_melt parameter (unitless) real(r8) :: n_melt_glcmec ! SCA shape parameter for glc_mec columns character(len=*), parameter :: subname = 'Init' @@ -301,10 +302,6 @@ subroutine Init(this, bounds, col, glc_behavior, NLFilename, params_ncid) NLFilename = NLFilename, & n_melt_glcmec = n_melt_glcmec) - call this%ReadParams( & - params_ncid = params_ncid, & - n_melt_coef = n_melt_coef) - if (masterproc) then call this%CheckValidInputs( & n_melt_glcmec = n_melt_glcmec) @@ -314,7 +311,6 @@ subroutine Init(this, bounds, col, glc_behavior, NLFilename, params_ncid) bounds = bounds, & col = col, & glc_behavior = glc_behavior, & - n_melt_coef = n_melt_coef, & n_melt_glcmec = n_melt_glcmec) end subroutine Init @@ -376,30 +372,6 @@ subroutine ReadNamelist(this, NLFilename, n_melt_glcmec) end subroutine ReadNamelist - !----------------------------------------------------------------------- - subroutine ReadParams(this, params_ncid, n_melt_coef) - ! - ! !DESCRIPTION: - ! Read netCDF parameters needed for the SwensonLawrence2012 method - ! - ! !ARGUMENTS: - class(snow_cover_fraction_swenson_lawrence_2012_type), intent(inout) :: this - type(file_desc_t) , intent(inout) :: params_ncid ! pio netCDF file id for parameter file - real(r8) , intent(out) :: n_melt_coef ! n_melt parameter (unitless) - ! - ! !LOCAL VARIABLES: - - character(len=*), parameter :: subname = 'ReadParams' - !----------------------------------------------------------------------- - - ! Accumulation constant for fractional snow covered area (unitless) - call readNcdioScalar(params_ncid, 'accum_factor', subname, this%accum_factor) - - ! n_melt parameter (unitless) - call readNcdioScalar(params_ncid, 'n_melt_coef', subname, n_melt_coef) - - end subroutine ReadParams - !----------------------------------------------------------------------- subroutine CheckValidInputs(this, n_melt_glcmec) ! @@ -430,7 +402,7 @@ subroutine CheckValidInputs(this, n_melt_glcmec) end subroutine CheckValidInputs !----------------------------------------------------------------------- - subroutine SetDerivedParameters(this, bounds, col, glc_behavior, n_melt_coef, n_melt_glcmec) + subroutine SetDerivedParameters(this, bounds, col, glc_behavior, n_melt_glcmec) ! ! !DESCRIPTION: ! Set parameters that are derived from other inputs @@ -440,7 +412,6 @@ subroutine SetDerivedParameters(this, bounds, col, glc_behavior, n_melt_coef, n_ type(bounds_type) , intent(in) :: bounds type(column_type) , intent(in) :: col type(glc_behavior_type) , intent(in) :: glc_behavior - real(r8) , intent(in) :: n_melt_coef real(r8) , intent(in) :: n_melt_glcmec ! SCA shape parameter for glc_mec columns ! ! !LOCAL VARIABLES: @@ -461,7 +432,7 @@ subroutine SetDerivedParameters(this, bounds, col, glc_behavior, n_melt_coef, n_ ! value of n_melt. this%n_melt(c) = n_melt_glcmec else - this%n_melt(c) = n_melt_coef / max(10._r8, col%topo_std(c)) + this%n_melt(c) = distparams%n_melt_coef%param_val(col%gridcell(c)) / max(10._r8, col%topo_std(c)) end if end do diff --git a/src/biogeophys/SnowHydrologyMod.F90 b/src/biogeophys/SnowHydrologyMod.F90 index 578769d9ea..8459740134 100644 --- a/src/biogeophys/SnowHydrologyMod.F90 +++ b/src/biogeophys/SnowHydrologyMod.F90 @@ -36,6 +36,7 @@ module SnowHydrologyMod use LandunitType , only : landunit_type, lun use TopoMod, only : topo_type use ColumnType , only : column_type, col + use DistParamType , only : distparams => distributed_parameters use landunit_varcon , only : istsoil, istdlak, istsoil, istwet, istice, istcrop use clm_time_manager, only : get_step_size_real, get_nstep use filterColMod , only : filter_col_type, col_filter_from_filter_and_logical_array @@ -70,7 +71,7 @@ module SnowHydrologyMod public :: SnowHydrologySetControlForTesting ! Set some of the control settings type, private :: params_type - real(r8) :: wimp ! Water impremeable if porosity less than wimp (unitless) + real(r8) :: wimp ! Water impermeable if porosity less than wimp (unitless) real(r8) :: ssi ! Irreducible water saturation of snow (unitless) real(r8) :: drift_gs ! Wind drift compaction / grain size (fixed value for now) (unitless) real(r8) :: eta0_anderson ! Viscosity coefficent from Anderson1976 (kg*s/m2) @@ -78,7 +79,6 @@ module SnowHydrologyMod real(r8) :: wind_snowcompact_fact ! Reference wind above which fresh snow density is (substantially) increased (m/s) real(r8) :: rho_max ! Wind drift compaction / maximum density (kg/m3) real(r8) :: tau_ref ! Wind drift compaction / reference time (48*3600) (s) - real(r8) :: scvng_fct_mlt_sf ! Scaling factor modifying scavenging factors for BC, OC, and dust species inclusion in meltwater (-) real(r8) :: scvng_fct_mlt_bcphi ! scavenging factor for hydrophillic BC inclusion in meltwater [frc] real(r8) :: scvng_fct_mlt_bcpho ! scavenging factor for hydrophobic BC inclusion in meltwater [frc] real(r8) :: scvng_fct_mlt_dst1 ! scavenging factor for dust species 1 inclusion in meltwater [frc] @@ -313,8 +313,6 @@ subroutine readParams( ncid ) call readNcdioScalar(ncid, 'rho_max', subname, params_inst%rho_max) ! Wind drift compaction / reference time (48*3600) (s) call readNcdioScalar(ncid, 'tau_ref', subname, params_inst%tau_ref) - ! Scaling factor modifying scavenging factors for BC, OC, and dust species inclusion in meltwater (-) - call readNcdioScalar(ncid, 'scvng_fct_mlt_sf', subname, params_inst%scvng_fct_mlt_sf) ! scavenging factor for hydrophillic BC inclusion in meltwater [frc] call readNcdioScalar(ncid, 'scvng_fct_mlt_bcphi', subname, params_inst%scvng_fct_mlt_bcphi) ! scavenging factor for hydrophobic BC inclusion in meltwater [frc] @@ -1600,7 +1598,7 @@ subroutine CalcAndApplyAerosolFluxes(bounds, num_snowc, filter_snowc, & ! BCPHI: ! 1. flux with meltwater: - qout_bc_phi(c) = qflx_snow_percolation(c,j)*params_inst%scvng_fct_mlt_sf* & + qout_bc_phi(c) = qflx_snow_percolation(c,j)*distparams%scvng_fct_mlt_sf%param_val(col%gridcell(c))* & params_inst%scvng_fct_mlt_bcphi*(mss_bcphi(c,j)/mss_liqice) if (qout_bc_phi(c)*dtime > mss_bcphi(c,j)) then qout_bc_phi(c) = mss_bcphi(c,j)/dtime @@ -1612,7 +1610,7 @@ subroutine CalcAndApplyAerosolFluxes(bounds, num_snowc, filter_snowc, & ! BCPHO: ! 1. flux with meltwater: - qout_bc_pho(c) = qflx_snow_percolation(c,j)*params_inst%scvng_fct_mlt_sf* & + qout_bc_pho(c) = qflx_snow_percolation(c,j)*distparams%scvng_fct_mlt_sf%param_val(col%gridcell(c))* & params_inst%scvng_fct_mlt_bcpho*(mss_bcpho(c,j)/mss_liqice) if (qout_bc_pho(c)*dtime > mss_bcpho(c,j)) then qout_bc_pho(c) = mss_bcpho(c,j)/dtime @@ -1624,7 +1622,7 @@ subroutine CalcAndApplyAerosolFluxes(bounds, num_snowc, filter_snowc, & ! OCPHI: ! 1. flux with meltwater: - qout_oc_phi(c) = qflx_snow_percolation(c,j)*params_inst%scvng_fct_mlt_sf* & + qout_oc_phi(c) = qflx_snow_percolation(c,j)*distparams%scvng_fct_mlt_sf%param_val(col%gridcell(c))* & scvng_fct_mlt_ocphi*(mss_ocphi(c,j)/mss_liqice) if (qout_oc_phi(c)*dtime > mss_ocphi(c,j)) then qout_oc_phi(c) = mss_ocphi(c,j)/dtime @@ -1636,7 +1634,7 @@ subroutine CalcAndApplyAerosolFluxes(bounds, num_snowc, filter_snowc, & ! OCPHO: ! 1. flux with meltwater: - qout_oc_pho(c) = qflx_snow_percolation(c,j)*params_inst%scvng_fct_mlt_sf* & + qout_oc_pho(c) = qflx_snow_percolation(c,j)*distparams%scvng_fct_mlt_sf%param_val(col%gridcell(c))* & scvng_fct_mlt_ocpho*(mss_ocpho(c,j)/mss_liqice) if (qout_oc_pho(c)*dtime > mss_ocpho(c,j)) then qout_oc_pho(c) = mss_ocpho(c,j)/dtime @@ -1648,7 +1646,7 @@ subroutine CalcAndApplyAerosolFluxes(bounds, num_snowc, filter_snowc, & ! DUST 1: ! 1. flux with meltwater: - qout_dst1(c) = qflx_snow_percolation(c,j)*params_inst%scvng_fct_mlt_sf* & + qout_dst1(c) = qflx_snow_percolation(c,j)*distparams%scvng_fct_mlt_sf%param_val(col%gridcell(c))* & params_inst%scvng_fct_mlt_dst1*(mss_dst1(c,j)/mss_liqice) if (qout_dst1(c)*dtime > mss_dst1(c,j)) then qout_dst1(c) = mss_dst1(c,j)/dtime @@ -1660,7 +1658,7 @@ subroutine CalcAndApplyAerosolFluxes(bounds, num_snowc, filter_snowc, & ! DUST 2: ! 1. flux with meltwater: - qout_dst2(c) = qflx_snow_percolation(c,j)*params_inst%scvng_fct_mlt_sf* & + qout_dst2(c) = qflx_snow_percolation(c,j)*distparams%scvng_fct_mlt_sf%param_val(col%gridcell(c))* & params_inst%scvng_fct_mlt_dst2*(mss_dst2(c,j)/mss_liqice) if (qout_dst2(c)*dtime > mss_dst2(c,j)) then qout_dst2(c) = mss_dst2(c,j)/dtime @@ -1672,7 +1670,7 @@ subroutine CalcAndApplyAerosolFluxes(bounds, num_snowc, filter_snowc, & ! DUST 3: ! 1. flux with meltwater: - qout_dst3(c) = qflx_snow_percolation(c,j)*params_inst%scvng_fct_mlt_sf* & + qout_dst3(c) = qflx_snow_percolation(c,j)*distparams%scvng_fct_mlt_sf%param_val(col%gridcell(c))* & params_inst%scvng_fct_mlt_dst3*(mss_dst3(c,j)/mss_liqice) if (qout_dst3(c)*dtime > mss_dst3(c,j)) then qout_dst3(c) = mss_dst3(c,j)/dtime @@ -1684,7 +1682,7 @@ subroutine CalcAndApplyAerosolFluxes(bounds, num_snowc, filter_snowc, & ! DUST 4: ! 1. flux with meltwater: - qout_dst4(c) = qflx_snow_percolation(c,j)*params_inst%scvng_fct_mlt_sf* & + qout_dst4(c) = qflx_snow_percolation(c,j)*distparams%scvng_fct_mlt_sf%param_val(col%gridcell(c))* & params_inst%scvng_fct_mlt_dst4*(mss_dst4(c,j)/mss_liqice) if (qout_dst4(c)*dtime > mss_dst4(c,j)) then qout_dst4(c) = mss_dst4(c,j)/dtime @@ -1972,8 +1970,8 @@ subroutine SnowCompaction(bounds, num_snowc, filter_snowc, & ! Settling as a result of destructive metamorphism ddz1 = -c3*dexpf - if (bi > params_inst%upplim_destruct_metamorph) ddz1 = & - ddz1*exp(-46.0e-3_r8*(bi-params_inst%upplim_destruct_metamorph)) + if (bi > distparams%upplim_destruct_metamorph%param_val(col%gridcell(c))) ddz1 = & + ddz1*exp(-46.0e-3_r8*(bi-distparams%upplim_destruct_metamorph%param_val(col%gridcell(c)))) ! Liquid water term diff --git a/src/biogeophys/SnowSnicarMod.F90 b/src/biogeophys/SnowSnicarMod.F90 index f6d41bd6a0..74455b7bca 100644 --- a/src/biogeophys/SnowSnicarMod.F90 +++ b/src/biogeophys/SnowSnicarMod.F90 @@ -16,6 +16,7 @@ module SnowSnicarMod snicar_snodst_intmix, do_sno_oc use clm_varcon , only : tfrz use shr_const_mod , only : SHR_CONST_RHOICE + use DistParamType , only : distparams => distributed_parameters use abortutils , only : endrun use decompMod , only : bounds_type, subgrid_level_column use atm2lndType , only : atm2lnd_type @@ -37,12 +38,10 @@ module SnowSnicarMod public :: SnowOptics_init ! Initial read in of snow-optics file type, private :: params_type - real(r8) :: xdrdt ! Arbitrary factor applied to snow aging rate (-) real(r8) :: snw_rds_refrz ! Effective radius of re-frozen snow (microns) real(r8) :: C2_liq_Brun89 ! Constant for liquid water grain growth [m3 s-1], ! from Brun89: corrected for LWC in units of percent real(r8) :: fresh_snw_rds_max ! maximum warm fresh snow effective radius [microns] - real(r8) :: snw_rds_min ! minimum allowed snow effective radius (also cold "fresh snow" value) [microns] end type params_type type(params_type), private :: params_inst ! @@ -173,16 +172,8 @@ subroutine readParams( ncid ) character(len=*), parameter :: subname = 'readParams_SnowSnicar' !-------------------------------------------------------------------- - ! Arbitrary factor applied to snow aging rate (-) - call readNcdioScalar(ncid, 'xdrdt', subname, params_inst%xdrdt) - ! Effective radius of re-frozen snow (microns) - call readNcdioScalar(ncid, 'snw_rds_refrz', subname, params_inst%snw_rds_refrz) ! constant for liquid water grain growth [m3 s-1], from Brun89: corrected for LWC in units of percent call readNcdioScalar(ncid, 'C2_liq_Brun89', subname, params_inst%C2_liq_Brun89) - ! maximum warm fresh snow effective radius [microns] - call readNcdioScalar(ncid, 'fresh_snw_rds_max', subname, params_inst%fresh_snw_rds_max) - ! minimum allowed snow effective radius (also cold "fresh snow" value) [microns] - call readNcdioScalar(ncid, 'snw_rds_min', subname, params_inst%snw_rds_min) end subroutine readParams @@ -678,7 +669,7 @@ subroutine SNICAR_RT (bounds, num_nourbanc, filter_nourbanc, & snl_lcl = -1 h2osno_ice_lcl(0) = h2osno_lcl h2osno_liq_lcl(0) = 0._r8 - snw_rds_lcl(0) = nint(params_inst%snw_rds_min) + snw_rds_lcl(0) = nint(distparams%snw_rds_min%param_val(col%gridcell(c_idx))) else flg_nosnl = 0 snl_lcl = snl(c_idx) @@ -1629,10 +1620,10 @@ subroutine SnowAge_grain(bounds, & !LvK extra boundary check, to prevent when using old restart file with lower snw_rds_min than current run - snw_rds(c_idx,i) = max(snw_rds(c_idx,i), params_inst%snw_rds_min) + snw_rds(c_idx,i) = max(snw_rds(c_idx,i), distparams%snw_rds_min%param_val(col%gridcell(c_idx))) ! change in snow effective radius, using best-fit parameters - dr_fresh = snw_rds(c_idx,i) - params_inst%snw_rds_min + dr_fresh = snw_rds(c_idx,i) - distparams%snw_rds_min%param_val(col%gridcell(c_idx)) dr = (bst_drdt0 * (bst_tau / (dr_fresh + bst_tau))**(1._r8 / bst_kappa)) * (dtime / secsphr) ! @@ -1656,7 +1647,7 @@ subroutine SnowAge_grain(bounds, & !********** 3. SNOWAGE SCALING ************* ! ! Multiply rate of change of effective radius by some constant, xdrdt - dr = dr*params_inst%xdrdt + dr = dr*distparams%xdrdt%param_val(col%gridcell(c_idx)) ! !********** 4. INCREMENT EFFECTIVE RADIUS, ACCOUNTING FOR: *********** @@ -1694,12 +1685,13 @@ subroutine SnowAge_grain(bounds, & ! mass-weighted mean of fresh snow, old snow, and re-frozen snow effective radius snw_rds(c_idx,i) = (snw_rds(c_idx,i)+dr)*frc_oldsnow + snw_rds_fresh*frc_newsnow + & - params_inst%snw_rds_refrz*frc_refrz + distparams%snw_rds_refrz%param_val(col%gridcell(c_idx))*frc_refrz ! + !********** 5. CHECK BOUNDARIES *********** ! ! boundary check - snw_rds(c_idx,i) = max(snw_rds(c_idx,i), params_inst%snw_rds_min) + snw_rds(c_idx,i) = max(snw_rds(c_idx,i), distparams%snw_rds_min%param_val(col%gridcell(c_idx))) snw_rds(c_idx,i) = min(snw_rds(c_idx,i), snw_rds_max) ! set top layer variables for history files @@ -1718,7 +1710,7 @@ subroutine SnowAge_grain(bounds, & do fc = 1, num_nosnowc c_idx = filter_nosnowc(fc) if (h2osno_no_layers(c_idx) > 0._r8) then - snw_rds(c_idx,0) = params_inst%snw_rds_min + snw_rds(c_idx,0) = distparams%snw_rds_min%param_val(col%gridcell(c_idx)) endif enddo @@ -1757,11 +1749,11 @@ real(r8) function FreshSnowRadius(c_idx, atm2lnd_inst) associate( & forc_t => atm2lnd_inst%forc_t_downscaled_col & ! Input: [real(r8) (:) ] atmospheric temperature (Kelvin) ) - if ( params_inst%fresh_snw_rds_max <= params_inst%snw_rds_min )then - FreshSnowRadius = params_inst%snw_rds_min + if ( distparams%fresh_snw_rds_max%param_val(col%gridcell(c_idx)) <= distparams%snw_rds_min%param_val(col%gridcell(c_idx)) )then + FreshSnowRadius = distparams%snw_rds_min%param_val(col%gridcell(c_idx)) else - gs_max = params_inst%fresh_snw_rds_max - gs_min = params_inst%snw_rds_min + gs_max = distparams%fresh_snw_rds_max%param_val(col%gridcell(c_idx)) + gs_min = distparams%snw_rds_min%param_val(col%gridcell(c_idx)) if (forc_t(c_idx) < tmin) then FreshSnowRadius = gs_min diff --git a/src/biogeophys/SoilHydrologyInitTimeConstMod.F90 b/src/biogeophys/SoilHydrologyInitTimeConstMod.F90 index 5f38830891..7289987fff 100644 --- a/src/biogeophys/SoilHydrologyInitTimeConstMod.F90 +++ b/src/biogeophys/SoilHydrologyInitTimeConstMod.F90 @@ -13,6 +13,7 @@ module SoilHydrologyInitTimeConstMod use WaterStateBulkType, only : waterstatebulk_type use LandunitType , only : lun use ColumnType , only : col + use DistParamType , only : distparams => distributed_parameters use SoilStateInitTimeConstMod, only: organic_max ! implicit none @@ -220,7 +221,7 @@ subroutine SoilHydrologyInitTimeConst(bounds, soilhydrology_inst, soilstate_inst if (micro_sigma(c) > 1.e-6_r8 .and. (soilhydrology_inst%h2osfcflag /= 0)) then d = 0.0_r8 do p = 1,4 - fd = 0.5_r8*(1.0_r8+shr_spfn_erf(d/(micro_sigma(c)*sqrt(2.0_r8)))) - params_inst%pc + fd = 0.5_r8*(1.0_r8+shr_spfn_erf(d/(micro_sigma(c)*sqrt(2.0_r8)))) - distparams%pc%param_val(col%gridcell(c)) dfdd = exp(-d**2/(2.0_r8*micro_sigma(c)**2))/(micro_sigma(c)*sqrt(2.0_r8*shr_const_pi)) d = d - fd/dfdd enddo diff --git a/src/biogeophys/SoilHydrologyMod.F90 b/src/biogeophys/SoilHydrologyMod.F90 index 5a4aa50f6e..a13d971977 100644 --- a/src/biogeophys/SoilHydrologyMod.F90 +++ b/src/biogeophys/SoilHydrologyMod.F90 @@ -10,7 +10,7 @@ module SoilHydrologyMod use abortutils , only : endrun use decompMod , only : bounds_type, subgrid_level_column use clm_varctl , only : iulog, use_vichydro - use clm_varcon , only : ispval + use clm_varcon , only : ispval, grlnd use clm_varcon , only : denh2o, denice, rpi use clm_varcon , only : pondmx_urban use clm_varpar , only : nlevsoi, nlevgrnd, nlayer, nlayert @@ -33,6 +33,7 @@ module SoilHydrologyMod use LandunitType , only : lun use ColumnType , only : column_type, col use PatchType , only : patch + use DistParamType , only : distparams => distributed_parameters ! ! !PUBLIC TYPES: @@ -40,7 +41,6 @@ module SoilHydrologyMod save ! ! !PUBLIC MEMBER FUNCTIONS: - public :: SoilHydReadNML ! Read in the Soil hydrology namelist public :: SetSoilWaterFractions ! Set diagnostic variables related to the fraction of water and ice in each layer public :: SetFloodc ! Apply gridcell flood water flux to non-lake columns public :: SetQflxInputs ! Set the flux of water into the soil from the top @@ -57,18 +57,8 @@ module SoilHydrologyMod public :: RenewCondensation ! Misc. corrections public :: CalcIrrigWithdrawals ! Calculate irrigation withdrawals from groundwater by layer public :: WithdrawGroundwaterIrrigation ! Remove groundwater irrigation from unconfined and confined aquifers - public :: readParams - - type, private :: params_type - real(r8) :: aq_sp_yield_min ! Minimum aquifer specific yield (unitless) - real(r8) :: n_baseflow ! Drainage power law exponent (unitless) - real(r8) :: perched_baseflow_scalar ! Scalar multiplier for perched base flow rate (kg/m2/s) - real(r8) :: e_ice ! Soil ice impedance factor (unitless) - end type params_type - type(params_type), public :: params_inst - + !----------------------------------------------------------------------- - real(r8), private :: baseflow_scalar = 1.e-2_r8 real(r8), parameter :: tolerance = 1.e-12_r8 ! tolerance for checking whether sublimation is greater than ice in top soil layer integer, private :: head_gradient_method ! Method for calculating hillslope saturated head gradient @@ -85,7 +75,7 @@ module SoilHydrologyMod __FILE__ contains - + !----------------------------------------------------------------------- subroutine hillslope_hydrology_ReadNML(NLFilename) ! @@ -171,91 +161,6 @@ subroutine hillslope_hydrology_ReadNML(NLFilename) end subroutine hillslope_hydrology_ReadNML - !----------------------------------------------------------------------- - subroutine readParams( ncid ) - ! - ! !USES: - use ncdio_pio, only: file_desc_t - use paramUtilMod, only: readNcdioScalar - ! - ! !ARGUMENTS: - implicit none - type(file_desc_t),intent(inout) :: ncid ! pio netCDF file id - ! - ! !LOCAL VARIABLES: - character(len=*), parameter :: subname = 'readParams_SoilHydrology' - !-------------------------------------------------------------------- - - ! Minimum aquifer specific yield (unitless) - call readNcdioScalar(ncid, 'aq_sp_yield_min', subname, params_inst%aq_sp_yield_min) - ! Drainage power law exponent (unitless) - call readNcdioScalar(ncid, 'n_baseflow', subname, params_inst%n_baseflow) - ! Scalar multiplier for perched base flow rate (kg/m2/s) - call readNcdioScalar(ncid, 'perched_baseflow_scalar', subname, params_inst%perched_baseflow_scalar) - ! Soil ice impedance factor (unitless) - call readNcdioScalar(ncid, 'e_ice', subname, params_inst%e_ice) - - end subroutine readParams - - !----------------------------------------------------------------------- - subroutine soilHydReadNML( NLFilename ) - ! - ! !DESCRIPTION: - ! Read the namelist for soil hydrology - ! - ! !USES: - use fileutils , only : getavu, relavu, opnfil - use shr_nl_mod , only : shr_nl_find_group_name - use spmdMod , only : masterproc, mpicom - use shr_mpi_mod , only : shr_mpi_bcast - use clm_varctl , only : iulog - use shr_log_mod , only : errMsg => shr_log_errMsg - ! - ! !ARGUMENTS: - character(len=*), intent(in) :: NLFilename ! Namelist filename - ! - ! !LOCAL VARIABLES: - integer :: ierr ! error code - integer :: unitn ! unit for namelist file - - character(len=*), parameter :: subname = 'soilHydReadNML' - character(len=*), parameter :: nmlname = 'soilhydrology_inparm' - !----------------------------------------------------------------------- - namelist /soilhydrology_inparm/ baseflow_scalar - - ! Initialize options to default values, in case they are not specified in - ! the namelist - - - if (masterproc) then - unitn = getavu() - write(iulog,*) 'Read in '//nmlname//' namelist' - call opnfil (NLFilename, unitn, 'F') - call shr_nl_find_group_name(unitn, nmlname, status=ierr) - if (ierr == 0) then - read(unitn, nml=soilhydrology_inparm, iostat=ierr) - if (ierr /= 0) then - call endrun(msg="ERROR reading "//nmlname//"namelist"//errmsg(sourcefile, __LINE__)) - end if - else - call endrun(msg="ERROR could NOT find "//nmlname//"namelist"//errmsg(sourcefile, __LINE__)) - end if - call relavu( unitn ) - end if - - call shr_mpi_bcast (baseflow_scalar, mpicom) - - if (masterproc) then - write(iulog,*) ' ' - write(iulog,*) nmlname//' settings:' - write(iulog,nml=soilhydrology_inparm) - write(iulog,*) ' ' - end if - - end subroutine soilhydReadNML - - - !----------------------------------------------------------------------- subroutine SetSoilWaterFractions(bounds, num_hydrologyc, filter_hydrologyc, & soilhydrology_inst, soilstate_inst, waterstatebulk_inst) @@ -791,7 +696,7 @@ subroutine WaterTable(bounds, num_hydrologyc, filter_hydrologyc, & ! use analytical expression for aquifer specific yield rous = watsat(c,nlevsoi) & * ( 1. - (1.+1.e3*zwt(c)/sucsat(c,nlevsoi))**(-1./bsw(c,nlevsoi))) - rous=max(rous, params_inst%aq_sp_yield_min) + rous=max(rous, distparams%aq_sp_yield_min%param_val(col%gridcell(c))) !-- water table is below the soil column -------------------------------------- if(jwt(c) == nlevsoi) then @@ -806,7 +711,7 @@ subroutine WaterTable(bounds, num_hydrologyc, filter_hydrologyc, & ! use analytical expression for specific yield s_y = watsat(c,j) & * ( 1. - (1.+1.e3*zwt(c)/sucsat(c,j))**(-1./bsw(c,j))) - s_y=max(s_y, params_inst%aq_sp_yield_min) + s_y=max(s_y, distparams%aq_sp_yield_min%param_val(col%gridcell(c))) qcharge_layer=min(qcharge_tot,(s_y*(zwt(c) - zi(c,j-1))*1.e3)) qcharge_layer=max(qcharge_layer,0._r8) @@ -821,7 +726,7 @@ subroutine WaterTable(bounds, num_hydrologyc, filter_hydrologyc, & ! use analytical expression for specific yield s_y = watsat(c,j) & * ( 1. - (1.+1.e3*zwt(c)/sucsat(c,j))**(-1./bsw(c,j))) - s_y=max(s_y, params_inst%aq_sp_yield_min) + s_y=max(s_y, distparams%aq_sp_yield_min%param_val(col%gridcell(c))) qcharge_layer=max(qcharge_tot,-(s_y*(zi(c,j) - zwt(c))*1.e3)) qcharge_layer=min(qcharge_layer,0._r8) @@ -1088,7 +993,7 @@ subroutine Drainage(bounds, num_hydrologyc, filter_hydrologyc, num_urbanc, filte c = filter_hydrologyc(fc) ! specify maximum drainage rate - q_perch_max = params_inst%perched_baseflow_scalar * sin(col%topo_slope(c) * (rpi/180._r8)) + q_perch_max = distparams%perched_baseflow_scalar%param_val(col%gridcell(c)) * sin(col%topo_slope(c) * (rpi/180._r8)) ! if layer containing water table is frozen, compute the following: ! frost table, perched water table, and drainage from perched saturated layer @@ -1121,7 +1026,7 @@ subroutine Drainage(bounds, num_hydrologyc, filter_hydrologyc, num_urbanc, filte wtsub = 0._r8 q_perch = 0._r8 do k = jwt(c)+1, k_frz - imped=10._r8**(-params_inst%e_ice*(0.5_r8*(icefrac(c,k)+icefrac(c,min(nlevsoi, k+1))))) + imped=10._r8**(-distparams%e_ice%param_val(col%gridcell(c))*(0.5_r8*(icefrac(c,k)+icefrac(c,min(nlevsoi, k+1))))) q_perch = q_perch + imped*hksat(c,k)*dzmm(c,k) wtsub = wtsub + dzmm(c,k) end do @@ -1197,7 +1102,7 @@ subroutine Drainage(bounds, num_hydrologyc, filter_hydrologyc, num_urbanc, filte wtsub = 0._r8 q_perch = 0._r8 do k = k_perch, k_frz - imped=10._r8**(-params_inst%e_ice*(0.5_r8*(icefrac(c,k)+icefrac(c,min(nlevsoi, k+1))))) + imped=10._r8**(-distparams%e_ice%param_val(col%gridcell(c))*(0.5_r8*(icefrac(c,k)+icefrac(c,min(nlevsoi, k+1))))) q_perch = q_perch + imped*hksat(c,k)*dzmm(c,k) wtsub = wtsub + dzmm(c,k) end do @@ -1242,11 +1147,11 @@ subroutine Drainage(bounds, num_hydrologyc, filter_hydrologyc, num_urbanc, filte end do ! add ice impedance factor to baseflow if (use_vichydro) then - imped=10._r8**(-params_inst%e_ice*min(1.0_r8,ice(c,nlayer)/max_moist(c,nlayer))) + imped=10._r8**(-distparams%e_ice%param_val(col%gridcell(c))*min(1.0_r8,ice(c,nlayer)/max_moist(c,nlayer))) dsmax_tmp(c) = Dsmax(c) * dtime/ secspday !mm/day->mm/dtime rsub_top_max = dsmax_tmp(c) else - imped=10._r8**(-params_inst%e_ice*(icefracsum/dzsum)) + imped=10._r8**(-distparams%e_ice%param_val(col%gridcell(c))*(icefracsum/dzsum)) rsub_top_max = 10._r8 * sin((rpi/180.) * col%topo_slope(c)) end if @@ -1271,7 +1176,7 @@ subroutine Drainage(bounds, num_hydrologyc, filter_hydrologyc, num_urbanc, filte ! use analytical expression for aquifer specific yield rous = watsat(c,nlevsoi) & * ( 1. - (1.+1.e3*zwt(c)/sucsat(c,nlevsoi))**(-1./bsw(c,nlevsoi))) - rous=max(rous, params_inst%aq_sp_yield_min) + rous=max(rous, distparams%aq_sp_yield_min%param_val(col%gridcell(c))) !-- water table is below the soil column -------------------------------------- if(jwt(c) == nlevsoi) then @@ -1308,7 +1213,7 @@ subroutine Drainage(bounds, num_hydrologyc, filter_hydrologyc, num_urbanc, filte ! use analytical expression for specific yield s_y = watsat(c,j) & * ( 1. - (1.+1.e3*zwt(c)/sucsat(c,j))**(-1./bsw(c,j))) - s_y=max(s_y, params_inst%aq_sp_yield_min) + s_y=max(s_y, distparams%aq_sp_yield_min%param_val(col%gridcell(c))) rsub_top_layer=max(rsub_top_tot,-(s_y*(zi(c,j) - zwt(c))*1.e3)) rsub_top_layer=min(rsub_top_layer,0._r8) @@ -1916,7 +1821,7 @@ subroutine PerchedLateralFlow(bounds, num_hydrologyc, & else ! Non-hillslope columns ! specify maximum drainage rate - q_perch_max = params_inst%perched_baseflow_scalar & + q_perch_max = distparams%perched_baseflow_scalar%param_val(col%gridcell(c)) & * sin(col%topo_slope(c) * (rpi/180._r8)) wtsub = 0._r8 @@ -1963,7 +1868,7 @@ subroutine PerchedLateralFlow(bounds, num_hydrologyc, & s_y = watsat(c,k) & * ( 1. - (1.+1.e3*zwt_perched(c)/sucsat(c,k))**(-1./bsw(c,k))) - s_y=max(s_y,params_inst%aq_sp_yield_min) + s_y=max(s_y,distparams%aq_sp_yield_min%param_val(col%gridcell(c))) if (k==k_perch(c)) then drainage_layer=min(drainage_tot,(s_y*(zi(c,k) - zwt_perched(c))*1.e3)) else @@ -2177,6 +2082,7 @@ subroutine SubsurfaceLateralFlow(bounds, & icefrac => soilhydrology_inst%icefrac_col , & ! Output: [real(r8) (:,:) ] fraction of ice in layer frost_table => soilhydrology_inst%frost_table_col , & ! Input: [real(r8) (:) ] frost table depth (m) zwt => soilhydrology_inst%zwt_col , & ! Input: [real(r8) (:) ] water table depth (m) + stream_water_volume => waterstatebulk_inst%stream_water_volume_lun, & ! Input: [real(r8) (:) ] stream water volume (m3) qflx_snwcp_liq => waterfluxbulk_inst%qflx_snwcp_liq_col , & ! Output: [real(r8) (:) ] excess rainfall due to snow capping (mm H2O /s) [+] @@ -2201,7 +2107,7 @@ subroutine SubsurfaceLateralFlow(bounds, & vol_ice = min(watsat(c,j), h2osoi_ice(c,j)/(dz(c,j)*denice)) icefrac(c,j) = min(1._r8,vol_ice/watsat(c,j)) - ice_imped(c,j)=10._r8**(-params_inst%e_ice*icefrac(c,j)) + ice_imped(c,j)=10._r8**(-distparams%e_ice%param_val(col%gridcell(c))*icefrac(c,j)) end do end do @@ -2243,7 +2149,7 @@ subroutine SubsurfaceLateralFlow(bounds, & dzsum = dzsum + dzmm(c,j) icefracsum = icefracsum + icefrac(c,j) * dzmm(c,j) end do - ice_imped_col(c)=10._r8**(-params_inst%e_ice*(icefracsum/dzsum)) + ice_imped_col(c)=10._r8**(-distparams%e_ice%param_val(col%gridcell(c))*(icefracsum/dzsum)) enddo do fc = 1, num_hydrologyc @@ -2391,9 +2297,9 @@ subroutine SubsurfaceLateralFlow(bounds, & ! Non-hillslope columns ! baseflow is power law expression relative to bedrock layer if(zwt(c) <= zi(c,nbedrock(c))) then - qflx_latflow_out(c) = ice_imped_col(c) * baseflow_scalar & + qflx_latflow_out(c) = ice_imped_col(c) * distparams%baseflow_scalar%param_val(col%gridcell(c)) & * tan(rpi/180._r8*col%topo_slope(c))* & - (zi(c,nbedrock(c)) - zwt(c))**(params_inst%n_baseflow) + (zi(c,nbedrock(c)) - zwt(c))**(distparams%n_baseflow%param_val(col%gridcell(c))) endif ! convert flux to volumetric flow qflx_latflow_out_vol(c) = 1.e-3_r8*qflx_latflow_out(c)*(grc%area(g)*1.e6_r8*col%wtgcell(c)) @@ -2456,7 +2362,7 @@ subroutine SubsurfaceLateralFlow(bounds, & ! analytical expression for specific yield s_y = watsat(c,j) & * ( 1. - (1.+1.e3*zwt(c)/sucsat(c,j))**(-1./bsw(c,j))) - s_y=max(s_y,params_inst%aq_sp_yield_min) + s_y=max(s_y,distparams%aq_sp_yield_min%param_val(col%gridcell(c))) drainage_layer=min(drainage_tot,(s_y*dz(c,j)*1.e3)) @@ -2483,7 +2389,7 @@ subroutine SubsurfaceLateralFlow(bounds, & ! analytical expression for specific yield s_y = watsat(c,j) & * ( 1. - (1.+1.e3*zwt(c)/sucsat(c,j))**(-1./bsw(c,j))) - s_y=max(s_y,params_inst%aq_sp_yield_min) + s_y=max(s_y,distparams%aq_sp_yield_min%param_val(col%gridcell(c))) drainage_layer=max(drainage_tot,-(s_y*(zi(c,j) - zwt(c))*1.e3)) drainage_layer=min(drainage_layer,0._r8) @@ -2822,7 +2728,7 @@ subroutine CalcIrrigWithdrawals(bounds, & ! use analytical expression for specific yield s_y = watsat(c,j) & * ( 1. - (1.+1.e3*zwt(c)/sucsat(c,j))**(-1./bsw(c,j))) - s_y=max(s_y, params_inst%aq_sp_yield_min) + s_y=max(s_y, distparams%aq_sp_yield_min%param_val(col%gridcell(c))) if (j==jwt(c)+1) then available_water_layer=max(0._r8,(s_y*(zi(c,j) - zwt(c))*1.e3)) diff --git a/src/biogeophys/SoilStateInitTimeConstMod.F90 b/src/biogeophys/SoilStateInitTimeConstMod.F90 index a730417315..3f5311f8ca 100644 --- a/src/biogeophys/SoilStateInitTimeConstMod.F90 +++ b/src/biogeophys/SoilStateInitTimeConstMod.F90 @@ -10,6 +10,7 @@ module SoilStateInitTimeConstMod use LandunitType , only : lun use ColumnType , only : col use PatchType , only : patch + use DistParamType , only : distparams => distributed_parameters use abortUtils , only : endrun use shr_infnan_mod, only : nan => shr_infnan_nan, assignment(=) ! @@ -547,13 +548,13 @@ subroutine SoilStateInitTimeConst(bounds, soilstate_inst, nlfilename) soilstate_inst%bd_col(c,lev) = (1._r8 - soilstate_inst%watsat_col(c,lev))*params_inst%pd ! do not allow watsat_sf to push watsat above 0.93 - soilstate_inst%watsat_col(c,lev) = min(params_inst%watsat_sf * ( (1._r8 - om_frac) * & + soilstate_inst%watsat_col(c,lev) = min(distparams%watsat_sf%param_val(col%gridcell(c)) * ( (1._r8 - om_frac) * & soilstate_inst%watsat_col(c,lev) + om_watsat*om_frac ), 0.93_r8) tkm = (1._r8-om_frac) * (params_inst%tkd_sand*sand+params_inst%tkd_clay*clay)/ & (sand+clay)+params_inst%tkm_om*om_frac ! W/(m K) - soilstate_inst%bsw_col(c,lev) = params_inst%bsw_sf * ( (1._r8-om_frac) * & + soilstate_inst%bsw_col(c,lev) = distparams%bsw_sf%param_val(col%gridcell(c)) * ( (1._r8-om_frac) * & (2.91_r8 + 0.159_r8*clay) + om_frac*om_b ) - soilstate_inst%sucsat_col(c,lev) = params_inst%sucsat_sf * ( (1._r8-om_frac) * & + soilstate_inst%sucsat_col(c,lev) = distparams%sucsat_sf%param_val(col%gridcell(c)) * ( (1._r8-om_frac) * & soilstate_inst%sucsat_col(c,lev) + om_sucsat*om_frac ) soilstate_inst%hksat_min_col(c,lev) = xksat @@ -575,7 +576,7 @@ subroutine SoilStateInitTimeConst(bounds, soilstate_inst, nlfilename) else uncon_hksat = 0._r8 end if - soilstate_inst%hksat_col(c,lev) = params_inst%hksat_sf * ( uncon_frac*uncon_hksat + & + soilstate_inst%hksat_col(c,lev) = distparams%hksat_sf%param_val(col%gridcell(c)) * ( uncon_frac*uncon_hksat + & (perc_frac*om_frac)*om_hksat ) soilstate_inst%tkmg_col(c,lev) = tkm ** (1._r8- soilstate_inst%watsat_col(c,lev)) @@ -649,16 +650,16 @@ subroutine SoilStateInitTimeConst(bounds, soilstate_inst, nlfilename) bd = (1._r8-soilstate_inst%watsat_col(c,lev))*params_inst%pd ! do not allow watsat_sf to push watsat above 0.93 - soilstate_inst%watsat_col(c,lev) = min(params_inst%watsat_sf * ( (1._r8 - om_frac) * & + soilstate_inst%watsat_col(c,lev) = min(distparams%watsat_sf%param_val(col%gridcell(c)) * ( (1._r8 - om_frac) * & soilstate_inst%watsat_col(c,lev) + om_watsat_lake * om_frac), 0.93_r8) tkm = (1._r8-om_frac)*(params_inst%tkd_sand*sand+params_inst%tkd_clay*clay)/(sand+clay) + & params_inst%tkm_om * om_frac ! W/(m K) - soilstate_inst%bsw_col(c,lev) = params_inst%bsw_sf * ( (1._r8-om_frac) * & + soilstate_inst%bsw_col(c,lev) = distparams%bsw_sf%param_val(col%gridcell(c)) * ( (1._r8-om_frac) * & (2.91_r8 + 0.159_r8*clay) + om_frac * om_b_lake ) - soilstate_inst%sucsat_col(c,lev) = params_inst%sucsat_sf * ( (1._r8-om_frac) * & + soilstate_inst%sucsat_col(c,lev) = distparams%sucsat_sf%param_val(col%gridcell(c)) * ( (1._r8-om_frac) * & soilstate_inst%sucsat_col(c,lev) + om_sucsat_lake * om_frac ) xksat = 0.0070556_r8 *( 10._r8**(-0.884_r8+0.0153_r8*sand) ) ! mm/s @@ -682,7 +683,7 @@ subroutine SoilStateInitTimeConst(bounds, soilstate_inst, nlfilename) uncon_hksat = 0._r8 end if - soilstate_inst%hksat_col(c,lev) = params_inst%hksat_sf * ( uncon_frac*uncon_hksat + & + soilstate_inst%hksat_col(c,lev) = distparams%hksat_sf%param_val(col%gridcell(c)) * ( uncon_frac*uncon_hksat + & (perc_frac*om_frac)*om_hksat_lake ) soilstate_inst%tkmg_col(c,lev) = tkm ** (1._r8- soilstate_inst%watsat_col(c,lev)) soilstate_inst%tksatu_col(c,lev) = soilstate_inst%tkmg_col(c,lev)*0.57_r8**soilstate_inst%watsat_col(c,lev) diff --git a/src/biogeophys/SoilWaterMovementMod.F90 b/src/biogeophys/SoilWaterMovementMod.F90 index c2909d0475..7358128840 100644 --- a/src/biogeophys/SoilWaterMovementMod.F90 +++ b/src/biogeophys/SoilWaterMovementMod.F90 @@ -9,6 +9,7 @@ module SoilWaterMovementMod ! created by Jinyun Tang, Mar 12, 2014 use shr_kind_mod , only : r8 => shr_kind_r8 use shr_sys_mod , only : shr_sys_flush + use DistParamType , only : distparams => distributed_parameters ! implicit none @@ -724,7 +725,7 @@ subroutine soilwater_zengdecker2009(bounds, num_hydrologyc, filter_hydrologyc, & s1 = min(1._r8, s1) s2 = hksat(c,j)*s1**(2._r8*bsw(c,j)+2._r8) - imped(c,j)=10._r8**(-params_inst%e_ice*(0.5_r8*(icefrac(c,j)+icefrac(c,min(nlevsoi, j+1))))) + imped(c,j)=10._r8**(-distparams%e_ice%param_val(col%gridcell(c))*(0.5_r8*(icefrac(c,j)+icefrac(c,min(nlevsoi, j+1))))) hk(c,j) = imped(c,j)*s1*s2 dhkdw(c,j) = imped(c,j)*(2._r8*bsw(c,j)+3._r8)*s2* & @@ -1518,10 +1519,10 @@ subroutine compute_hydraulic_properties(c, nlayers, & ! s1 is interface value, s2 is node value if(j==nlayers)then s1 = s2(j) - call IceImpedance(icefrac(c,j), imped(j) ) + call IceImpedance(c,icefrac(c,j), imped(j) ) else s1 = 0.5_r8 * (s2(j) + s2(j+1)) - call IceImpedance(0.5_r8*(icefrac(c,j) + icefrac(c,j+1)), imped(j) ) + call IceImpedance(c,0.5_r8*(icefrac(c,j) + icefrac(c,j+1)), imped(j) ) endif ! impose constraints on relative saturation at the layer interface @@ -2136,8 +2137,10 @@ end subroutine compute_qcharge !#13 !----------------------------------------------------------------------- - subroutine IceImpedance(icefrac, imped) + subroutine IceImpedance(c, icefrac, imped) ! + ! USES + use ColumnType , only : col !DESCRIPTION ! compute soil suction potential ! @@ -2147,15 +2150,16 @@ subroutine IceImpedance(icefrac, imped) ! ! !ARGUMENTS: implicit none - real(r8), intent(in) :: icefrac !fraction of pore space filled with ice + integer , intent(in) :: c ! column index + real(r8), intent(in) :: icefrac ! fraction of pore space filled with ice - real(r8), intent(out) :: imped !hydraulic conductivity reduction due to the presence of ice in pore space + real(r8), intent(out) :: imped ! hydraulic conductivity reduction due to the presence of ice in pore space ! ! !LOCAL VARIABLES: character(len=32) :: subname = 'IceImpedance' ! subroutine name !------------------------------------------------------------------------------ - imped = 10._r8**(-params_inst%e_ice*icefrac) + imped = 10._r8**(-distparams%e_ice%param_val(col%gridcell(c))*icefrac) end subroutine IceImpedance diff --git a/src/biogeophys/SurfaceResistanceMod.F90 b/src/biogeophys/SurfaceResistanceMod.F90 index 9b04327252..64d2bdba79 100644 --- a/src/biogeophys/SurfaceResistanceMod.F90 +++ b/src/biogeophys/SurfaceResistanceMod.F90 @@ -8,13 +8,14 @@ module SurfaceResistanceMod ! transported with BeTR. The surface here refers to water and soil, not including canopy ! ! !USES: - use shr_kind_mod , only: r8 => shr_kind_r8 - use shr_const_mod , only: SHR_CONST_TKFRZ - use clm_varctl , only: iulog - use SoilStateType , only: soilstate_type - use WaterStateBulkType, only: waterstatebulk_type - use WaterDiagnosticBulkType, only: waterdiagnosticbulk_type - use TemperatureType , only : temperature_type + use shr_kind_mod , only : r8 => shr_kind_r8 + use shr_const_mod , only : SHR_CONST_TKFRZ + use clm_varctl , only : iulog + use SoilStateType , only : soilstate_type + use DistParamType , only : distparams => distributed_parameters + use WaterStateBulkType, only : waterstatebulk_type + use WaterDiagnosticBulkType, only : waterdiagnosticbulk_type + use TemperatureType , only : temperature_type implicit none save private @@ -29,13 +30,6 @@ module SurfaceResistanceMod public :: do_soilevap_beta, do_soil_resistance_sl14 ! public :: init_soil_resistance public :: soil_resistance_readNL - public :: readParams - - type, private :: params_type - real(r8) :: d_max ! Dry surface layer parameter (mm) - real(r8) :: frac_sat_soil_dsl_init ! Fraction of saturated soil for moisture value at which DSL initiates (unitless) - end type params_type - type(params_type), private :: params_inst character(len=*), parameter, private :: sourcefile = & __FILE__ @@ -165,28 +159,6 @@ subroutine soil_resistance_readNL(NLFilename) endif end subroutine soil_resistance_readNL - - !------------------------------------------------------------------------------ - subroutine readParams( ncid ) - ! - ! !USES: - use ncdio_pio, only: file_desc_t - use paramUtilMod, only: readNcdioScalar - ! - ! !ARGUMENTS: - implicit none - type(file_desc_t),intent(inout) :: ncid ! pio netCDF file id - ! - ! !LOCAL VARIABLES: - character(len=*), parameter :: subname = 'readParams_SurfaceResistance' - !-------------------------------------------------------------------- - - ! Dry surface layer parameter (mm) - call readNcdioScalar(ncid, 'd_max', subname, params_inst%d_max) - ! Fraction of saturated soil for moisture value at which DSL initiates (unitless) - call readNcdioScalar(ncid, 'frac_sat_soil_dsl_init', subname, params_inst%frac_sat_soil_dsl_init) - - end subroutine readParams !------------------------------------------------------------------------------ subroutine calc_soilevap_resis(bounds, num_nolakec, filter_nolakec, & @@ -401,9 +373,9 @@ subroutine calc_soil_resistance_sl14(bounds, num_nolakec, filter_nolakec, & ! dsl(c) = dzmm(c,1)*max(0.001_r8,(0.8*eff_porosity(c,1) - vwc_liq)) & ! try arbitrary scaling (not top layer thickness) ! dsl(c) = 15._r8*max(0.001_r8,(0.8*eff_porosity(c,1) - vwc_liq)) & - dsl(c) = params_inst%d_max * max(0.001_r8, (params_inst%frac_sat_soil_dsl_init * eff_por_top - vwc_liq)) & + dsl(c) = distparams%d_max%param_val(col%gridcell(c)) * max(0.001_r8, (distparams%frac_sat_soil_dsl_init%param_val(col%gridcell(c)) * eff_por_top - vwc_liq)) & ! /max(0.001_r8,(watsat(c,1)- aird)) - / max(0.001_r8, (params_inst%frac_sat_soil_dsl_init * watsat(c,1) - aird)) + / max(0.001_r8, (distparams%frac_sat_soil_dsl_init%param_val(col%gridcell(c)) * watsat(c,1) - aird)) dsl(c)=max(dsl(c),0._r8) dsl(c)=min(dsl(c),200._r8) diff --git a/src/biogeophys/SurfaceWaterMod.F90 b/src/biogeophys/SurfaceWaterMod.F90 index 562c64cc18..e59471d514 100644 --- a/src/biogeophys/SurfaceWaterMod.F90 +++ b/src/biogeophys/SurfaceWaterMod.F90 @@ -15,6 +15,7 @@ module SurfaceWaterMod use column_varcon , only : icol_roof, icol_road_imperv, icol_sunwall, icol_shadewall, icol_road_perv use decompMod , only : bounds_type, subgrid_level_column use ColumnType , only : col + use DistParamType , only : distparams => distributed_parameters use NumericsMod , only : truncate_small_values use InfiltrationExcessRunoffMod , only : infiltration_excess_runoff_type use EnergyFluxType , only : energyflux_type @@ -32,45 +33,17 @@ module SurfaceWaterMod ! !PUBLIC MEMBER FUNCTIONS: public :: UpdateFracH2oSfc ! Determine fraction of land surfaces which are submerged public :: UpdateH2osfc ! Calculate fluxes out of h2osfc and update the h2osfc state - public :: readParams ! !PRIVATE MEMBER FUNCTIONS: private :: BulkDiag_FracH2oSfc ! Determine fraction of land surfaces which are submerged private :: QflxH2osfcSurf ! Compute qflx_h2osfc_surf private :: QflxH2osfcDrain ! Compute qflx_h2osfc_drain - type, private :: params_type - real(r8) :: pc ! Threshold probability for surface water (unitless) - real(r8) :: mu ! Connectivity exponent for surface water (unitless) - end type params_type - type(params_type), private :: params_inst character(len=*), parameter, private :: sourcefile = & __FILE__ contains - !----------------------------------------------------------------------- - subroutine readParams( ncid ) - ! - ! !USES: - use ncdio_pio, only: file_desc_t - use paramUtilMod, only: readNcdioScalar - ! - ! !ARGUMENTS: - implicit none - type(file_desc_t),intent(inout) :: ncid ! pio netCDF file id - ! - ! !LOCAL VARIABLES: - character(len=*), parameter :: subname = 'readParams_SurfaceWater' - !-------------------------------------------------------------------- - - ! Threshold probability for surface water (unitless) - call readNcdioScalar(ncid, 'pc', subname, params_inst%pc) - ! Connectivity exponent for surface water (unitless) - call readNcdioScalar(ncid, 'mu', subname, params_inst%mu) - - end subroutine readParams - !----------------------------------------------------------------------- subroutine UpdateFracH2oSfc(bounds, num_soilc, filter_soilc, & water_inst) @@ -473,10 +446,10 @@ subroutine QflxH2osfcSurf(bounds, num_hydrologyc, filter_hydrologyc, & c = filter_hydrologyc(fc) if (h2osfcflag==1) then - if (frac_h2osfc_nosnow(c) <= params_inst%pc) then + if (frac_h2osfc_nosnow(c) <= distparams%pc%param_val(col%gridcell(c))) then frac_infclust=0.0_r8 else - frac_infclust=(frac_h2osfc_nosnow(c)-params_inst%pc)**params_inst%mu + frac_infclust=(frac_h2osfc_nosnow(c)-distparams%pc%param_val(col%gridcell(c)))**distparams%mu%param_val(col%gridcell(c)) endif endif diff --git a/src/biogeophys/WaterDiagnosticBulkType.F90 b/src/biogeophys/WaterDiagnosticBulkType.F90 index 48aeef73aa..fa3ba08d47 100644 --- a/src/biogeophys/WaterDiagnosticBulkType.F90 +++ b/src/biogeophys/WaterDiagnosticBulkType.F90 @@ -21,6 +21,7 @@ module WaterDiagnosticBulkType use clm_varcon , only : spval use LandunitType , only : lun use ColumnType , only : col + use DistParamType , only : distparams => distributed_parameters use filterColMod , only : filter_col_type, col_filter_from_ltypes use WaterDiagnosticType, only : waterdiagnostic_type use WaterInfoBaseType, only : water_info_base_type @@ -106,42 +107,12 @@ module WaterDiagnosticBulkType end type waterdiagnosticbulk_type - ! PUBLIC MEMBER FUNCTIONS - public :: readParams - - type, private :: params_type - real(r8) :: zlnd ! Momentum roughness length for soil, glacier, wetland (m) - real(r8) :: snw_rds_min ! minimum allowed snow effective radius (also cold "fresh snow" value) [microns] - end type params_type - type(params_type), private :: params_inst - character(len=*), parameter, private :: sourcefile = & __FILE__ !------------------------------------------------------------------------ contains - subroutine readParams( ncid ) - ! - ! !USES: - use ncdio_pio, only: file_desc_t - use paramUtilMod, only: readNcdioScalar - ! - ! !ARGUMENTS: - implicit none - type(file_desc_t),intent(inout) :: ncid ! pio netCDF file id - ! - ! !LOCAL VARIABLES: - character(len=*), parameter :: subname = 'readParams_WaterDiagnosticBulk' - !-------------------------------------------------------------------- - - ! Momentum roughness length for soil, glacier, wetland (m) - call readNcdioScalar(ncid, 'zlnd', subname, params_inst%zlnd) - ! minimum allowed snow effective radius (also cold "fresh snow" value) [microns] - call readNcdioScalar(ncid, 'snw_rds_min', subname, params_inst%snw_rds_min) - - end subroutine readParams - !------------------------------------------------------------------------ subroutine InitBulk(this, bounds, info, vars, & snow_depth_input_col, h2osno_input_col) @@ -757,18 +728,18 @@ subroutine InitBulkCold(this, bounds, & fmelt = (snowbd/100.)**1. ! 100 is the assumed fresh snow density; 1 is a melting factor that could be ! reconsidered, optimal value of 1.5 in Niu et al., 2007 - this%frac_sno_col(c) = tanh( this%snow_depth_col(c) / (2.5 * params_inst%zlnd * fmelt) ) + this%frac_sno_col(c) = tanh( this%snow_depth_col(c) / (2.5 * distparams%zlnd%param_val(col%gridcell(c)) * fmelt) ) endif end if end do do c = bounds%begc,bounds%endc if (snl(c) < 0) then - this%snw_rds_col(c,snl(c)+1:0) = params_inst%snw_rds_min + this%snw_rds_col(c,snl(c)+1:0) = distparams%snw_rds_min%param_val(col%gridcell(c)) this%snw_rds_col(c,-nlevsno+1:snl(c)) = 0._r8 - this%snw_rds_top_col(c) = params_inst%snw_rds_min + this%snw_rds_top_col(c) = distparams%snw_rds_min%param_val(col%gridcell(c)) elseif (h2osno_input_col(c) > 0._r8) then - this%snw_rds_col(c,0) = params_inst%snw_rds_min + this%snw_rds_col(c,0) = distparams%snw_rds_min%param_val(col%gridcell(c)) this%snw_rds_col(c,-nlevsno+1:-1) = 0._r8 this%snw_rds_top_col(c) = spval this%sno_liq_top_col(c) = spval @@ -1250,7 +1221,7 @@ subroutine ResetBulk(this, column) integer , intent(in) :: column ! column index !----------------------------------------------------------------------- - this%snw_rds_col(column,0) = params_inst%snw_rds_min + this%snw_rds_col(column,0) = distparams%snw_rds_min%param_val(col%gridcell(column)) end subroutine ResetBulk diff --git a/src/cpl/share_esmf/DistParamStreamMod.F90 b/src/cpl/share_esmf/DistParamStreamMod.F90 new file mode 100644 index 0000000000..42f1acb1ec --- /dev/null +++ b/src/cpl/share_esmf/DistParamStreamMod.F90 @@ -0,0 +1,368 @@ +module DistParamsStreamMod + + + !----------------------------------------------------------------------- + ! !DESCRIPTION: + ! Contains methods for reading from a spatially distributed parameter file + + ! !USES + use ESMF + use dshr_strdata_mod , only : shr_strdata_type + use shr_kind_mod , only : r8 => shr_kind_r8, CL => shr_kind_cl + use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) + use shr_log_mod , only : errMsg => shr_log_errMsg + use spmdMod , only : mpicom, masterproc + use clm_varctl , only : iulog, FL => fname_len + use clm_varctl , only : use_distributed_parameters + use abortutils , only : endrun + use decompMod , only : bounds_type + use DistParamType , only : distributed_parameter_type, distparam_class + + ! !PUBLIC TYPES: + implicit none + private + + ! + type, public :: distributed_parameter_stream_type + ! + contains + + ! !PUBLIC MEMBER FUNCTIONS: + procedure, public :: Init ! Initialize and read data in + procedure, public :: Clean ! Clean and deallocate the object + + end type distributed_parameter_stream_type + + type(distributed_parameter_stream_type), public, target :: distributed_parameter_stream + + ! ! PRIVATE DATA: + type, private :: streamcontrol_type + character(len=FL) :: stream_fldFileName_distparams ! data Filename + character(len=FL) :: stream_meshfile_distparams ! mesh Filename + character(len=CL) :: mapalgo_distparams ! map algo + contains + procedure, private :: ReadNML ! Read in control namelist + end type streamcontrol_type + + type(streamcontrol_type), private :: control ! Stream control data + logical , private :: NMLRead = .false. ! If namelist has been read + logical , private :: InitDone = .false. ! If initialization of streams has been done + + character(len=*), parameter, private :: sourcefile = & + __FILE__ + +!============================================================================== +contains +!============================================================================== + + !------------------------------------------------------------------------ + subroutine AssignDistributedParameter(this,bounds,dataptr1d,stream_varname) + ! + ! !USES: + ! + ! !ARGUMENTS: + implicit none + class(distparam_class), intent(inout) :: this ! distributed parameter + type(bounds_type) , intent(in) :: bounds + real(r8) , pointer, intent(in) :: dataptr1d(:) ! stream data + character(len=*) , intent(in) :: stream_varname ! name of parameter on stream file + ! + ! local variables + integer :: g, ig + character(len=*), parameter :: subname = 'AssignDistributedParameter' + !-------------------------------------------------------------------- + + if (trim(stream_varname) == trim(this%name)) then + allocate(this%val(bounds%begg:bounds%endg)) + this%val(:) = nan + ig = 0 + do g = bounds%begg,bounds%endg + ig = ig+1 + this%val(g) = dataptr1d(ig) + end do + this%is_distributed = .true. + end if + + end subroutine AssignDistributedParameter + + !------------------------------------------------------------------------ + subroutine Init(this, bounds, NLFilename, distparams) + ! + ! Initialize the distributed parameters stream object + ! + ! Uses: + use spmdMod , only : iam + use lnd_comp_shr , only : mesh, model_clock + use dshr_strdata_mod , only : shr_strdata_init_from_inline, shr_strdata_print + use dshr_strdata_mod , only : shr_strdata_advance + use dshr_methods_mod , only : dshr_fldbun_getfldptr + use fileutils , only : getfil + use ncdio_pio , only : ncd_pio_closefile, ncd_pio_openfile + use ncdio_pio , only : file_desc_t, var_desc_t + use ncdio_pio , only : ncd_inqvname, ncd_inqnvars + ! + ! arguments + implicit none + class(distributed_parameter_stream_type) :: this + type(bounds_type), intent(in) :: bounds + character(len=*), intent(in) :: NLFilename ! Namelist filename + type(distributed_parameter_type), intent(inout) :: distparams + ! + ! local variables + integer :: ig, g, n ! Indices + integer :: begg, endg + integer :: year ! year (0, ...) for nstep+1 + integer :: mon ! month (1, ..., 12) for nstep+1 + integer :: day ! day of month (1, ..., 31) for nstep+1 + integer :: sec ! seconds into current date for nstep+1 + integer :: mcdate ! Current model date (yyyymmdd) + integer :: nparams ! number of parameters on file + integer :: nvariables ! number of variables on file + integer :: dimid ! netCDF dimension id + type(file_desc_t) :: ncid ! pio netCDF file id + character(len=256) :: locfn ! local filename + type(shr_strdata_type) :: sdat_distparams ! input data stream + character(len=256) :: varname ! variable name + type(var_desc_t) :: var_desc ! variable descriptor + character(len=CL), allocatable :: stream_varnames_in(:) ! array of stream field names + character(len=CL), allocatable :: stream_varnames(:) ! array of stream field names + integer :: rc ! error code + real(r8), pointer :: dataptr1d(:) ! temporary pointer + character(len=*), parameter :: stream_name = 'Distributed parameters' + character(len=*), parameter :: subname = 'DistParamsStream::Init' + !----------------------------------------------------------------------- + + call control%ReadNML( bounds, NLFileName ) + + if ( use_distributed_parameters )then + + ! query parameter file + call getfil (control%stream_fldFileName_distparams, locfn, 0) + call ncd_pio_openfile (ncid, trim(locfn), 0) + + call ncd_inqnvars(ncid,nvariables=nvariables) + + allocate(stream_varnames_in(nvariables)) + nparams = 0 + do n=1,nvariables + call ncd_inqvname(ncid,n,varname,var_desc) + if ( .not. any((/trim(varname) == 'time',trim(varname) == 'lat',trim(varname) == 'lon'/)) ) then + nparams = nparams + 1 + write(stream_varnames_in(nparams),'(a)') trim(varname) + endif + enddo + + ! close parameter file + call ncd_pio_closefile(ncid) + + ! keep valid variable names (not entirely satisfying, but avoids having to explicitly index array later + allocate(stream_varnames(nparams)) + stream_varnames = stream_varnames_in(1:nparams) + deallocate(stream_varnames_in) + + if (masterproc) then + write(iulog,*) ' stream_varnames = ',stream_varnames + end if + + ! Initialize the cdeps data type sdat_distparams + call shr_strdata_init_from_inline(sdat_distparams, & + my_task = iam, & + logunit = iulog, & + compname = 'LND', & + model_clock = model_clock, & + model_mesh = mesh, & + stream_meshfile = control%stream_meshfile_distparams, & + stream_lev_dimname = 'null', & + stream_mapalgo = control%mapalgo_distparams, & + stream_filenames = (/trim(control%stream_fldFileName_distparams)/), & +! stream_fldlistFile = stream_varnames(:nparams), & +! stream_fldListModel = stream_varnames(:nparams), & + stream_fldlistFile = stream_varnames, & + stream_fldListModel = stream_varnames, & + stream_yearFirst = 2000, & + stream_yearLast = 2000, & + stream_yearAlign = 1, & + stream_offset = 0, & + stream_taxmode = 'extend', & + stream_dtlimit = 1.0e30_r8, & + stream_tintalgo = 'linear', & + stream_name = 'Distributed parameters', & + rc = rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + + ! Explicitly set current date to a hardcoded constant value. Otherwise + ! using the real date can cause roundoff differences that are + ! detrected as issues with exact restart. EBK M05/20/2017 + ! call get_curr_date(year, mon, day, sec) + year = 2000 + mon = 12 + day = 31 + sec = 0 + mcdate = year*10000 + mon*100 + day + + call shr_strdata_advance(sdat_distparams, ymd=mcdate, tod=sec, logunit=iulog, istr='distparams', rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + + ! Get pointer for stream data that is time and spatially interpolate to model time and grid + begg = bounds%begg; endg = bounds%endg + + do n = 1,size(stream_varnames) + call dshr_fldbun_getFldPtr(sdat_distparams%pstrm(1)%fldbun_model, stream_varnames(n), fldptr1=dataptr1d, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + + ! Assign values to distributed parameter arrays if stream data exist + call AssignDistributedParameter(distparams%aq_sp_yield_min,bounds,dataptr1d,stream_varnames(n)) + call AssignDistributedParameter(distparams%n_baseflow,bounds,dataptr1d,stream_varnames(n)) + call AssignDistributedParameter(distparams%perched_baseflow_scalar,bounds,dataptr1d,stream_varnames(n)) + call AssignDistributedParameter(distparams%e_ice,bounds,dataptr1d,stream_varnames(n)) + call AssignDistributedParameter(distparams%baseflow_scalar,bounds,dataptr1d,stream_varnames(n)) + call AssignDistributedParameter(distparams%fff,bounds,dataptr1d,stream_varnames(n)) + call AssignDistributedParameter(distparams%slopebeta,bounds,dataptr1d,stream_varnames(n)) + call AssignDistributedParameter(distparams%slopemax,bounds,dataptr1d,stream_varnames(n)) + call AssignDistributedParameter(distparams%n_melt_coef,bounds,dataptr1d,stream_varnames(n)) + call AssignDistributedParameter(distparams%accum_factor,bounds,dataptr1d,stream_varnames(n)) + call AssignDistributedParameter(distparams%upplim_destruct_metamorph,bounds,dataptr1d,stream_varnames(n)) + call AssignDistributedParameter(distparams%pc,bounds,dataptr1d,stream_varnames(n)) + call AssignDistributedParameter(distparams%mu,bounds,dataptr1d,stream_varnames(n)) + call AssignDistributedParameter(distparams%bsw_sf,bounds,dataptr1d,stream_varnames(n)) + call AssignDistributedParameter(distparams%hksat_sf,bounds,dataptr1d,stream_varnames(n)) + call AssignDistributedParameter(distparams%sucsat_sf,bounds,dataptr1d,stream_varnames(n)) + call AssignDistributedParameter(distparams%watsat_sf,bounds,dataptr1d,stream_varnames(n)) + call AssignDistributedParameter(distparams%d_max,bounds,dataptr1d,stream_varnames(n)) + call AssignDistributedParameter(distparams%frac_sat_soil_dsl_init,bounds,dataptr1d,stream_varnames(n)) + call AssignDistributedParameter(distparams%zlnd,bounds,dataptr1d,stream_varnames(n)) + call AssignDistributedParameter(distparams%snw_rds_min,bounds,dataptr1d,stream_varnames(n)) + call AssignDistributedParameter(distparams%xdrdt,bounds,dataptr1d,stream_varnames(n)) + call AssignDistributedParameter(distparams%snw_rds_refrz,bounds,dataptr1d,stream_varnames(n)) + call AssignDistributedParameter(distparams%fresh_snw_rds_max,bounds,dataptr1d,stream_varnames(n)) + call AssignDistributedParameter(distparams%scvng_fct_mlt_sf,bounds,dataptr1d,stream_varnames(n)) + call AssignDistributedParameter(distparams%precip_repartition_nonglc_all_rain_t_celsius,bounds,dataptr1d,stream_varnames(n)) + call AssignDistributedParameter(distparams%precip_repartition_nonglc_all_snow_t_celsius,bounds,dataptr1d,stream_varnames(n)) + call AssignDistributedParameter(distparams%precip_repartition_glc_all_rain_t_celsius,bounds,dataptr1d,stream_varnames(n)) + call AssignDistributedParameter(distparams%precip_repartition_glc_all_snow_t_celsius,bounds,dataptr1d,stream_varnames(n)) + + end do + deallocate(stream_varnames) + InitDone = .true. + end if + + end subroutine Init + + !============================================================================== + subroutine Clean(this) + ! + ! Deallocate and clean the object + ! + ! Uses: + ! + ! arguments + implicit none + class(distributed_parameter_stream_type) :: this + ! + ! local variables + !----------------------------------------------------------------------- + !deallocate(this%distparams) + !this%distparams => NULL() + InitDone = .false. + + end subroutine Clean + + !============================================================================== + subroutine ReadNML(this, bounds, NLFilename) + ! + ! Read the namelist data stream information. + ! + ! Uses: + use shr_nl_mod , only : shr_nl_find_group_name + use shr_log_mod , only : errMsg => shr_log_errMsg + use shr_mpi_mod , only : shr_mpi_bcast + ! + ! arguments + implicit none + class(streamcontrol_type) :: this + type(bounds_type), intent(in) :: bounds + character(len=*), intent(in) :: NLFilename ! Namelist filename + ! + ! local variables + integer :: nu_nml ! unit for namelist file + integer :: nml_error ! namelist i/o error flag + character(len=FL) :: stream_fldFileName_distparams = ' ' + character(len=FL) :: stream_meshfile_distparams = ' ' + character(len=CL) :: mapalgo_distparams = 'bilinear' + character(len=*), parameter :: namelist_name = 'distparams_streams' ! MUST agree with group name in namelist definition to read. + character(len=*), parameter :: subName = "('distparams_streams::ReadNML')" + !----------------------------------------------------------------------- + + namelist /distparams_streams/ & ! MUST agree with namelist_name above + use_distributed_parameters, stream_fldFileName_distparams, & + stream_meshfile_distparams + + ! Default values for namelist + + ! Read distparams_streams namelist + if (masterproc) then + open( newunit=nu_nml, file=trim(NLFilename), status='old', iostat=nml_error ) + call shr_nl_find_group_name(nu_nml, namelist_name, status=nml_error) + if (nml_error == 0) then + read(nu_nml, nml=distparams_streams,iostat=nml_error) ! MUST agree with namelist_name above + if (nml_error /= 0) then + call endrun(msg=' ERROR reading '//namelist_name//' namelist'//errMsg(sourcefile, __LINE__)) + end if + else + call endrun(msg=' ERROR finding '//namelist_name//' namelist'//errMsg(sourcefile, __LINE__)) + end if + close(nu_nml) + endif + + call shr_mpi_bcast(use_distributed_parameters , mpicom) + call shr_mpi_bcast(mapalgo_distparams , mpicom) + call shr_mpi_bcast(stream_fldFileName_distparams , mpicom) + call shr_mpi_bcast(stream_meshfile_distparams , mpicom) + + ! Error checking + if ( .not. use_distributed_parameters )then + if ( len_trim(stream_fldFileName_distparams) /= 0 )then + call endrun(msg=' ERROR stream_fldFileName_distparams is set, but use_distributed_parameters is FALSE' & + //errMsg(sourcefile, __LINE__)) + end if + if ( len_trim(stream_meshfile_distparams) /= 0 )then + call endrun(msg=' ERROR stream_meshfile_distparams is set, but use_distributed_parameters is FALSE' & + //errMsg(sourcefile, __LINE__)) + end if + else + if ( len_trim(stream_fldFileName_distparams) == 0 )then + call endrun(msg=' ERROR stream_fldFileName_distparams is NOT set, but use_distributed_parameters is TRUE' & + //errMsg(sourcefile, __LINE__)) + end if + if ( len_trim(stream_meshfile_distparams) == 0 )then + call endrun(msg=' ERROR stream_meshfile_distparams is NOT set, but use_distributed_parameters is TRUE' & + //errMsg(sourcefile, __LINE__)) + end if + end if + + if (masterproc) then + write(iulog,*) ' ' + write(iulog,*) namelist_name, ' stream settings:' + write(iulog,*) ' use_distributed_parameters = ',use_distributed_parameters + if ( use_distributed_parameters )then + write(iulog,*) ' stream_fldFileName_distparams = ',trim(stream_fldFileName_distparams) + write(iulog,*) ' stream_meshfile_distparams = ',trim(stream_meshfile_distparams) + write(iulog,*) ' mapalgo_distparams = ',trim(mapalgo_distparams) + end if + endif + this%stream_fldFileName_distparams = stream_fldFileName_distparams + this%stream_meshfile_distparams = stream_meshfile_distparams + this%mapalgo_distparams = mapalgo_distparams + + ! Mark namelist read as having been done + NMLRead = .true. + + end subroutine ReadNML + +end module DistParamsStreamMod diff --git a/src/main/DistParamMod.F90 b/src/main/DistParamMod.F90 new file mode 100644 index 0000000000..f3ac886475 --- /dev/null +++ b/src/main/DistParamMod.F90 @@ -0,0 +1,66 @@ +module DistParamMod + + !----------------------------------------------------------------------- + ! !DESCRIPTION: + ! Spatially distributed parameter data type allocation and initialization + ! -------------------------------------------------------- + ! + use shr_kind_mod , only : r8 => shr_kind_r8 + use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) + use shr_sys_mod , only : shr_sys_abort + use clm_varcon , only : spval, ispval, grlnd + use clm_varctl , only : iulog + use clm_varctl , only : use_distributed_parameters + use spmdMod , only : masterproc, mpicom + use shr_mpi_mod , only : shr_mpi_bcast + use decompMod , only : bounds_type + + ! + ! !PUBLIC TYPES: + implicit none + save + private + character(len=*), parameter, private :: sourcefile = __FILE__ + ! + + public :: InitDistributedParameters + + !------------------------------------------------------------------------ + +contains + + !------------------------------------------------------------------------ + subroutine InitDistributedParameters(bounds) + ! + ! !USES: + use DistParamType , only : distributed_parameters, InitGlobalParameters + use DistParamsStreamMod, only : distributed_parameter_stream + use clm_varctl , only : NLFilename => NLFilename_in + use abortutils , only : endrun + + ! + ! !ARGUMENTS: + implicit none + type(bounds_type), intent(in) :: bounds + ! + ! !LOCAL VARIABLES: + logical :: readvar ! whether the variable was found + character(len=*), parameter :: subname = 'InitDistributedParameters' + !-------------------------------------------------------------------- + + if (masterproc) then + write(iulog,*) trim(subname)//' :: reading CLM parameters' + end if + + ! Initialize distributed_parameters object + call distributed_parameters%Init() + + ! Initialize distributed parameters based on stream data + call distributed_parameter_stream%Init(bounds, NLFilename, distributed_parameters) + + ! Initialize global parameters + call InitGlobalParameters(bounds) + + end subroutine InitDistributedParameters + +end module DistParamMod diff --git a/src/main/DistParamType.F90 b/src/main/DistParamType.F90 new file mode 100644 index 0000000000..0aa1a63896 --- /dev/null +++ b/src/main/DistParamType.F90 @@ -0,0 +1,478 @@ +module DistParamType + + !----------------------------------------------------------------------- + ! !DESCRIPTION: + ! Spatially distributed parameter data type allocation and initialization + ! -------------------------------------------------------- + ! + use shr_kind_mod , only : r8 => shr_kind_r8 + use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) + use shr_sys_mod , only : shr_sys_abort + use clm_varcon , only : spval, ispval, grlnd + use clm_varctl , only : iulog + use clm_varctl , only : paramfile + use ColumnType , only : col + use spmdMod , only : masterproc, mpicom + use fileutils , only : getfil, opnfil, getavu, relavu + use shr_nl_mod , only : shr_nl_find_group_name + use shr_mpi_mod , only : shr_mpi_bcast + use decompMod , only : bounds_type + use ncdio_pio , only : ncd_pio_closefile, ncd_pio_openfile + use ncdio_pio , only : file_desc_t, ncd_inqdid, ncd_inqdlen + + ! + ! !PUBLIC TYPES: + implicit none + save + private + character(len=*), parameter, private :: sourcefile = __FILE__ + ! + + type, public :: distparam_class + logical :: is_distributed = .false. ! is parameter spatially distributed? + character(len=256) :: name ! name on parameter files + real(r8), allocatable :: val(:) ! parameter value array (either distributed or length 1) + contains + procedure, public :: param_val ! return parameter value + end type distparam_class + + type, public :: distributed_parameter_type + ! all parameters that could *potentially* be spatially distributed + + ! SoilHydrologyMod + class(distparam_class), pointer :: aq_sp_yield_min => NULL() ! Minimum aquifer specific yield (unitless) + class(distparam_class), pointer :: n_baseflow => NULL() ! Drainage power law exponent (unitless) + class(distparam_class), pointer :: perched_baseflow_scalar => NULL() ! Scalar multiplier for perched base flow rate (kg/m2/s) + class(distparam_class), pointer :: e_ice => NULL() ! Soil ice impedance factor (unitless) + class(distparam_class), pointer :: baseflow_scalar => NULL() ! Scalar multiplier for base flow rate () + + ! SaturatedExcessRunoff + class(distparam_class), pointer :: fff => NULL() ! Decay factor for fractional saturated area (1/m) + + ! initVerticalMod + class(distparam_class), pointer :: slopebeta => NULL() ! exponent for microtopography pdf sigma (unitless) + class(distparam_class), pointer :: slopemax => NULL() ! max topographic slope for microtopography pdf sigma (unitless) + + ! SnowCoverFractionSwensonLawrence2012Mod + class(distparam_class), pointer :: n_melt_coef => NULL() ! SCA shape parameter + class(distparam_class), pointer :: accum_factor => NULL() ! Accumulation constant for fractional snow covered area (unitless) + + ! SnowHydrologyMod + class(distparam_class), pointer :: upplim_destruct_metamorph => NULL() ! Upper limit on destructive metamorphism compaction (kg/m3) + class(distparam_class), pointer :: scvng_fct_mlt_sf => NULL() ! Scaling factor modifying scavenging factors for BC, OC, and dust species inclusion in meltwater (-) + + ! SnowSnicarMod + class(distparam_class), pointer :: xdrdt => NULL() ! Arbitrary factor applied to snow aging rate (-) + class(distparam_class), pointer :: snw_rds_refrz => NULL() ! Effective radius of re-frozen snow (microns) + class(distparam_class), pointer :: fresh_snw_rds_max => NULL() ! maximum warm fresh snow effective radius [microns] + + ! SoilStateInitTimeConstMod + class(distparam_class), pointer :: bsw_sf => NULL() ! Scale factor for bsw (unitless) + class(distparam_class), pointer :: hksat_sf => NULL() ! Scale factor for hksat (unitless) + class(distparam_class), pointer :: sucsat_sf => NULL() ! Scale factor for sucsat (unitless) + class(distparam_class), pointer :: watsat_sf => NULL() ! Scale factor for watsat (unitless) + + ! SurfaceResistanceMod + class(distparam_class), pointer :: d_max => NULL() ! Dry surface layer parameter (mm) + class(distparam_class), pointer :: frac_sat_soil_dsl_init => NULL() ! Fraction of saturated soil for moisture value at which DSL initiates (unitless) + + ! SurfaceWaterMod + class(distparam_class), pointer :: pc => NULL() ! Threshold probability for surface water (unitless) + class(distparam_class), pointer :: mu => NULL() ! Connectivity exponent for surface water (unitless) + + ! WaterDiagnosticBulkType + class(distparam_class), pointer :: zlnd => NULL() ! Momentum roughness length for soil, glacier, wetland (m) + class(distparam_class), pointer :: snw_rds_min => NULL() ! minimum allowed snow effective radius (also cold "fresh snow" value) [microns] + + ! atm2lndType + class(distparam_class), pointer :: precip_repartition_nonglc_all_rain_t_celsius => NULL() ! Rain temperature threshold for non-glacier landunits (C) + class(distparam_class), pointer :: precip_repartition_nonglc_all_snow_t_celsius => NULL() ! Snow temperature threshold for non-glacier landunits (C) + class(distparam_class), pointer :: precip_repartition_glc_all_rain_t_celsius => NULL() ! Rain temperature threshold for glacier landunits (C) + class(distparam_class), pointer :: precip_repartition_glc_all_snow_t_celsius => NULL() ! Snow temperature threshold for glacier landunits (C) + + contains + + procedure, public :: Init + procedure, public :: Clean + + end type distributed_parameter_type + + type(distributed_parameter_type), public, target :: distributed_parameters + + public :: InitGlobalParameters + + !------------------------------------------------------------------------ + +contains + + !------------------------------------------------------------------------ + function param_val(this,g) + ! + ! !DESCRIPTION: + ! Return distributed parameter value if allocated, otherwise return scalar value + ! + ! !ARGUMENTS: + implicit none + class(distparam_class) :: this + real(r8) :: param_val + integer :: g + ! + if ( this%is_distributed )then + param_val = this%val(g) + else + param_val = this%val(1) + end if + end function param_val + + !------------------------------------------------------------------------ + subroutine ReadScalarParameter(this,ncid) + ! + ! !USES: + use paramUtilMod , only : readNcdioScalar + ! !ARGUMENTS: + implicit none + class(distparam_class), intent(inout) :: this + type(file_desc_t) , intent(inout) :: ncid ! pio netCDF file id + ! + ! !LOCAL VARIABLES: + real(r8) :: fscalar_in ! read in - scalar - float + character(len=*), parameter :: subname = 'ReadScalarParameter' + !-------------------------------------------------------------------- + + if ( .not. this%is_distributed ) then + allocate(this%val(1)) + call readNcdioScalar(ncid, this%name, subname, fscalar_in) + this%val(1) = fscalar_in + endif + + end subroutine ReadScalarParameter + + !------------------------------------------------------------------------ + subroutine InitGlobalParameters(bounds) + ! + ! !USES: + use ncdio_pio , only : check_var, ncd_io + use paramUtilMod , only : readNcdioScalar + use abortutils , only : endrun + use shr_log_mod , only : errMsg => shr_log_errMsg + use domainMod , only : ldomain + use clm_varctl , only : NLFilename => NLFilename_in + + ! + ! !ARGUMENTS: + implicit none + type(bounds_type), intent(in) :: bounds + ! + ! !LOCAL VARIABLES: + logical :: readvar ! whether the variable was found + integer :: c, g + real(r8) :: fscalar_in ! read in - scalar - float + real(r8), pointer :: fparam_in(:) ! read in - 1D - float + type(file_desc_t) :: ncid ! pio netCDF file id + character(len=256) :: locfn ! local filename + character(len=*), parameter :: subname = 'InitGlobalParameters' + !-------------------------------------------------------------------- + + if (masterproc) then + write(iulog,*) trim(subname)//' :: reading CLM parameters' + end if + + !distributed_parameter_stream%Init must be called before this routine is called. + + ! global (scalar) parameters + call getfil (paramfile, locfn, 0) + call ncd_pio_openfile (ncid, trim(locfn), 0) + + ! Any parameters not read from stream will be read here from parameter file or namelist + !----------------------------------------------------------- + ! SoilHydrology ! + !----------------------------------------------------------- + + ! Minimum aquifer specific yield (unitless) + call ReadScalarParameter(distributed_parameters%aq_sp_yield_min,ncid) + + ! Drainage power law exponent (unitless) + call ReadScalarParameter(distributed_parameters%n_baseflow,ncid) + + ! Scalar multiplier for perched base flow rate () + call ReadScalarParameter(distributed_parameters%baseflow_scalar,ncid) + + ! Scalar multiplier for perched base flow rate (kg/m2/s) + call ReadScalarParameter(distributed_parameters%perched_baseflow_scalar,ncid) + + ! Soil ice impedance factor (unitless) + call ReadScalarParameter(distributed_parameters%e_ice,ncid) + + !----------------------------------------------------------- + ! SaturatedExcessRunoff ! + !----------------------------------------------------------- + + ! Decay factor for fractional saturated area (1/m) + call ReadScalarParameter(distributed_parameters%fff,ncid) + + !----------------------------------------------------------- + ! initVertical ! + !----------------------------------------------------------- + + ! exponent for microtopography pdf sigma (unitless) + call ReadScalarParameter(distributed_parameters%slopebeta,ncid) + + ! max topographic slope for microtopography pdf sigma (unitless) + call ReadScalarParameter(distributed_parameters%slopemax,ncid) + + !----------------------------------------------------------- + ! SnowCoverFractionSwensonLawrence2012 ! + !----------------------------------------------------------- + + ! SCA shape parameter + call ReadScalarParameter(distributed_parameters%n_melt_coef,ncid) + + ! Accumulation constant for fractional snow covered area (unitless) + call ReadScalarParameter(distributed_parameters%accum_factor,ncid) + + !----------------------------------------------------------- + ! SnowHydrologyMod ! + !----------------------------------------------------------- + + ! Upper limit on destructive metamorphism compaction (kg/m3) + call ReadScalarParameter(distributed_parameters%upplim_destruct_metamorph,ncid) + ! Scaling factor modifying scavenging factors for BC, OC, and dust species inclusion in meltwater (-) + call ReadScalarParameter(distributed_parameters%scvng_fct_mlt_sf,ncid) + !----------------------------------------------------------- + ! SnowSnicarMod ! + !----------------------------------------------------------- + + ! Arbitrary factor applied to snow aging rate (-) + call ReadScalarParameter(distributed_parameters%xdrdt,ncid) + ! Effective radius of re-frozen snow (microns) + call ReadScalarParameter(distributed_parameters%snw_rds_refrz,ncid) + ! maximum warm fresh snow effective radius [microns] + call ReadScalarParameter(distributed_parameters%fresh_snw_rds_max,ncid) + + !----------------------------------------------------------- + ! SoilStateInitTimeConstMod ! + !----------------------------------------------------------- + + call ReadScalarParameter(distributed_parameters%bsw_sf,ncid) + + call ReadScalarParameter(distributed_parameters%hksat_sf,ncid) + + call ReadScalarParameter(distributed_parameters%sucsat_sf,ncid) + + call ReadScalarParameter(distributed_parameters%watsat_sf,ncid) + + !----------------------------------------------------------- + ! SurfaceResistanceMod ! + !----------------------------------------------------------- + + ! Dry surface layer parameter (mm) + call ReadScalarParameter(distributed_parameters%d_max,ncid) + + ! Fraction of saturated soil for moisture value at which DSL initiates (unitless) + call ReadScalarParameter(distributed_parameters%frac_sat_soil_dsl_init,ncid) + + !----------------------------------------------------------- + ! SurfaceWaterMod ! + !----------------------------------------------------------- + + ! Threshold probability for surface water (unitless) + call ReadScalarParameter(distributed_parameters%pc,ncid) + + ! Connectivity exponent for surface water (unitless) + call ReadScalarParameter(distributed_parameters%mu,ncid) + + !----------------------------------------------------------- + ! WaterDiagnosticBulkType ! + !----------------------------------------------------------- + + ! Momentum roughness length for soil, glacier, wetland (m) + call ReadScalarParameter(distributed_parameters%zlnd,ncid) + + ! Minimum allowed snow effective radius (also cold "fresh snow" value) [microns] + call ReadScalarParameter(distributed_parameters%snw_rds_min,ncid) + + !----------------------------------------------------------- + ! atm2lndType ! + !----------------------------------------------------------- + + ! non-glacier all rain temperature (degrees C) + call ReadScalarParameter(distributed_parameters%precip_repartition_nonglc_all_rain_t_celsius,ncid) + ! non-glacier all snow temperature (degrees C) + call ReadScalarParameter(distributed_parameters%precip_repartition_nonglc_all_snow_t_celsius,ncid) + ! glacier all rain temperature (degrees C) + call ReadScalarParameter(distributed_parameters%precip_repartition_glc_all_rain_t_celsius,ncid) + ! glacier all snow temperature (degrees C) + call ReadScalarParameter(distributed_parameters%precip_repartition_glc_all_snow_t_celsius,ncid) + + ! close parameter file + call ncd_pio_closefile(ncid) + + end subroutine InitGlobalParameters + + !------------------------------------------------------------------------ + subroutine Init(this) + ! + ! !ARGUMENTS: + class(distributed_parameter_type) :: this + !------------------------------------------------------------------------ + + allocate(this%aq_sp_yield_min) + allocate(this%n_baseflow) + allocate(this%perched_baseflow_scalar) + allocate(this%e_ice) + allocate(this%baseflow_scalar) + allocate(this%fff) + allocate(this%slopebeta) + allocate(this%slopemax) + allocate(this%n_melt_coef) + allocate(this%accum_factor) + allocate(this%upplim_destruct_metamorph) + allocate(this%pc) + allocate(this%mu) + allocate(this%bsw_sf) + allocate(this%hksat_sf) + allocate(this%sucsat_sf) + allocate(this%watsat_sf) + allocate(this%d_max) + allocate(this%frac_sat_soil_dsl_init) + allocate(this%zlnd) + allocate(this%snw_rds_min) + allocate(this%xdrdt) + allocate(this%snw_rds_refrz) + allocate(this%fresh_snw_rds_max) + allocate(this%scvng_fct_mlt_sf) + allocate(this%precip_repartition_nonglc_all_rain_t_celsius) + allocate(this%precip_repartition_nonglc_all_snow_t_celsius) + allocate(this%precip_repartition_glc_all_rain_t_celsius) + allocate(this%precip_repartition_glc_all_snow_t_celsius) + + this%aq_sp_yield_min%name = 'aq_sp_yield_min' + this%aq_sp_yield_min%is_distributed = .false. + + this%n_baseflow%name = 'n_baseflow' + this%n_baseflow%is_distributed = .false. + + this%perched_baseflow_scalar%name = 'perched_baseflow_scalar' + this%perched_baseflow_scalar%is_distributed = .false. + + this%e_ice%name = 'e_ice' + this%e_ice%is_distributed = .false. + + this%baseflow_scalar%name = 'baseflow_scalar' + this%baseflow_scalar%is_distributed = .false. + + this%fff%name = 'fff' + this%fff%is_distributed = .false. + + this%slopebeta%name = 'slopebeta' + this%slopebeta%is_distributed = .false. + + this%slopemax%name = 'slopemax' + this%slopemax%is_distributed = .false. + + this%n_melt_coef%name = 'n_melt_coef' + this%n_melt_coef%is_distributed = .false. + + this%accum_factor%name = 'accum_factor' + this%accum_factor%is_distributed = .false. + + this%upplim_destruct_metamorph%name = 'upplim_destruct_metamorph' + this%upplim_destruct_metamorph%is_distributed = .false. + + this%pc%name = 'pc' + this%pc%is_distributed = .false. + + this%mu%name = 'mu' + this%mu%is_distributed = .false. + + this%bsw_sf%name = 'bsw_sf' + this%bsw_sf%is_distributed = .false. + + this%hksat_sf%name = 'hksat_sf' + this%hksat_sf%is_distributed = .false. + + this%sucsat_sf%name = 'sucsat_sf' + this%sucsat_sf%is_distributed = .false. + + this%watsat_sf%name = 'watsat_sf' + this%watsat_sf%is_distributed = .false. + + this%d_max%name = 'd_max' + this%d_max%is_distributed = .false. + + this%frac_sat_soil_dsl_init%name = 'frac_sat_soil_dsl_init' + this%frac_sat_soil_dsl_init%is_distributed = .false. + + this%zlnd%name = 'zlnd' + this%zlnd%is_distributed = .false. + + this%snw_rds_min%name = 'snw_rds_min' + this%snw_rds_min%is_distributed = .false. + + this%xdrdt%name = 'xdrdt' + this%xdrdt%is_distributed = .false. + this%snw_rds_refrz%name = 'snw_rds_refrz' + this%snw_rds_refrz%is_distributed = .false. + this%fresh_snw_rds_max%name = 'fresh_snw_rds_max' + this%fresh_snw_rds_max%is_distributed = .false. + this%scvng_fct_mlt_sf%name = 'scvng_fct_mlt_sf' + this%scvng_fct_mlt_sf%is_distributed = .false. + + this%precip_repartition_nonglc_all_rain_t_celsius%name = & + 'precip_repartition_nonglc_all_rain_t' + this%precip_repartition_nonglc_all_rain_t_celsius%is_distributed = .false. + + this%precip_repartition_nonglc_all_snow_t_celsius%name = & + 'precip_repartition_nonglc_all_snow_t' + this%precip_repartition_nonglc_all_snow_t_celsius%is_distributed = .false. + + this%precip_repartition_glc_all_rain_t_celsius%name = & + 'precip_repartition_glc_all_rain_t' + this%precip_repartition_glc_all_rain_t_celsius%is_distributed = .false. + + this%precip_repartition_glc_all_snow_t_celsius%name = & + 'precip_repartition_glc_all_snow_t' + this%precip_repartition_glc_all_snow_t_celsius%is_distributed = .false. + + end subroutine Init + + !------------------------------------------------------------------------ + subroutine Clean(this) + ! + ! !ARGUMENTS: + class(distributed_parameter_type) :: this + !------------------------------------------------------------------------ + + deallocate(this%aq_sp_yield_min%val) + deallocate(this%n_baseflow%val) + deallocate(this%perched_baseflow_scalar%val) + deallocate(this%e_ice%val) + deallocate(this%baseflow_scalar%val) + deallocate(this%fff%val) + deallocate(this%slopebeta%val) + deallocate(this%slopemax%val) + deallocate(this%n_melt_coef%val) + deallocate(this%accum_factor%val) + deallocate(this%upplim_destruct_metamorph%val) + deallocate(this%pc%val) + deallocate(this%mu%val) + deallocate(this%bsw_sf%val) + deallocate(this%hksat_sf%val) + deallocate(this%sucsat_sf%val) + deallocate(this%watsat_sf%val) + deallocate(this%d_max%val) + deallocate(this%frac_sat_soil_dsl_init%val) + deallocate(this%zlnd%val) + deallocate(this%snw_rds_min%val) + deallocate(this%xdrdt%val) + deallocate(this%snw_rds_refrz%val) + deallocate(this%fresh_snw_rds_max%val) + deallocate(this%scvng_fct_mlt_sf%val) + deallocate(this%precip_repartition_nonglc_all_rain_t_celsius%val) + deallocate(this%precip_repartition_nonglc_all_snow_t_celsius%val) + deallocate(this%precip_repartition_glc_all_rain_t_celsius%val) + deallocate(this%precip_repartition_glc_all_snow_t_celsius%val) + + end subroutine Clean + +end module Distparamtype diff --git a/src/main/atm2lndMod.F90 b/src/main/atm2lndMod.F90 index 5da4ff6333..cfd80264f4 100644 --- a/src/main/atm2lndMod.F90 +++ b/src/main/atm2lndMod.F90 @@ -25,7 +25,6 @@ module atm2lndMod use landunit_varcon, only : istice use WaterType , only : water_type use Wateratm2lndBulkType, only : wateratm2lndbulk_type - ! ! !PUBLIC TYPES: implicit none @@ -266,7 +265,7 @@ subroutine downscale_forcings(bounds, & end do - ! adjust hillslope precpitation before repartitioning rain/snow + ! adjust hillslope precipitation before repartitioning rain/snow if (use_hillslope .and. downscale_hillslope_meteorology) then call downscale_hillslope_solar(bounds, atm2lnd_inst, surfalb_inst) call downscale_hillslope_precipitation(bounds, topo_inst, atm2lnd_inst, wateratm2lndbulk_inst) @@ -359,15 +358,16 @@ subroutine partition_precip(bounds, atm2lnd_inst, wateratm2lndbulk_inst, eflx_sh if (atm2lnd_inst%params%repartition_rain_snow) then do c = bounds%begc, bounds%endc if (col%active(c)) then + g = col%gridcell(c) l = col%landunit(c) rain_orig = forc_rain_c(c) snow_orig = forc_snow_c(c) if (lun%itype(l) == istice) then - all_snow_t = atm2lnd_inst%params%precip_repartition_glc_all_snow_t - frac_rain_slope = atm2lnd_inst%params%precip_repartition_glc_frac_rain_slope + all_snow_t = atm2lnd_inst%params%precip_repartition_glc_all_snow_t%param_val(g) + frac_rain_slope = atm2lnd_inst%params%precip_repartition_glc_frac_rain_slope%param_val(g) else - all_snow_t = atm2lnd_inst%params%precip_repartition_nonglc_all_snow_t - frac_rain_slope = atm2lnd_inst%params%precip_repartition_nonglc_frac_rain_slope + all_snow_t = atm2lnd_inst%params%precip_repartition_nonglc_all_snow_t%param_val(g) + frac_rain_slope = atm2lnd_inst%params%precip_repartition_nonglc_frac_rain_slope%param_val(g) end if call repartition_rain_snow_one_col(& temperature = forc_t_c(c), & @@ -387,6 +387,7 @@ subroutine partition_precip(bounds, atm2lnd_inst, wateratm2lndbulk_inst, eflx_sh sens_heat_flux = eflx_sh_precip_conversion(c)) end if end do + end if end associate diff --git a/src/main/atm2lndType.F90 b/src/main/atm2lndType.F90 index 298ca4a41d..b864828948 100644 --- a/src/main/atm2lndType.F90 +++ b/src/main/atm2lndType.F90 @@ -14,6 +14,10 @@ module atm2lndType use decompMod , only : bounds_type use abortutils , only : endrun use PatchType , only : patch + use DistParamType , only : distparam_class, distparams => distributed_parameters + + + use GridcellType , only : grc ! debug ! ! !PUBLIC TYPES: implicit none @@ -43,14 +47,19 @@ module atm2lndType ! Rain-snow ramp for glacier landunits ! frac_rain = (temp - all_snow_t) * frac_rain_slope ! (all_snow_t is in K) - real(r8) :: precip_repartition_glc_all_snow_t - real(r8) :: precip_repartition_glc_frac_rain_slope + class(distparam_class), pointer :: precip_repartition_glc_all_snow_t => NULL() + class(distparam_class), pointer :: precip_repartition_glc_frac_rain_slope => NULL() +! real(r8) :: precip_repartition_glc_all_snow_t +! real(r8) :: precip_repartition_glc_frac_rain_slope ! Rain-snow ramp for non-glacier landunits ! frac_rain = (temp - all_snow_t) * frac_rain_slope ! (all_snow_t is in K) - real(r8) :: precip_repartition_nonglc_all_snow_t - real(r8) :: precip_repartition_nonglc_frac_rain_slope + class(distparam_class), pointer :: precip_repartition_nonglc_all_snow_t => NULL() + class(distparam_class), pointer :: precip_repartition_nonglc_frac_rain_slope => NULL() + +! real(r8) :: precip_repartition_nonglc_all_snow_t +! real(r8) :: precip_repartition_nonglc_frac_rain_slope end type atm2lnd_params_type !---------------------------------------------------- @@ -143,9 +152,7 @@ module atm2lndType !----------------------------------------------------------------------- function atm2lnd_params_constructor(repartition_rain_snow, glcmec_downscale_longwave, & - lapse_rate, lapse_rate_longwave, longwave_downscaling_limit, & - precip_repartition_glc_all_snow_t, precip_repartition_glc_all_rain_t, & - precip_repartition_nonglc_all_snow_t, precip_repartition_nonglc_all_rain_t) & + lapse_rate, lapse_rate_longwave, longwave_downscaling_limit) & result(params) ! ! !DESCRIPTION: @@ -169,17 +176,9 @@ function atm2lnd_params_constructor(repartition_rain_snow, glcmec_downscale_long ! Must be present if glcmec_downscale_longwave is true; ignored otherwise real(r8), intent(in), optional :: longwave_downscaling_limit - ! End-points of the rain-snow ramp for glacier landunits (degrees C) - ! Must be present if repartition_rain_snow is true; ignored otherwise - real(r8), intent(in), optional :: precip_repartition_glc_all_snow_t - real(r8), intent(in), optional :: precip_repartition_glc_all_rain_t - - ! End-points of the rain-snow ramp for non-glacier landunits (degrees C) - ! Must be present if repartition_rain_snow is true; ignored otherwise - real(r8), intent(in), optional :: precip_repartition_nonglc_all_snow_t - real(r8), intent(in), optional :: precip_repartition_nonglc_all_rain_t ! ! !LOCAL VARIABLES: + integer :: beg_index, end_index character(len=*), parameter :: subname = 'atm2lnd_params_constructor' !----------------------------------------------------------------------- @@ -212,75 +211,107 @@ function atm2lnd_params_constructor(repartition_rain_snow, glcmec_downscale_long params%longwave_downscaling_limit = nan end if - if (repartition_rain_snow) then - ! Make sure all of the repartitioning-related parameters are present + ! allocate derived type variables + allocate(params%precip_repartition_glc_all_snow_t) + allocate(params%precip_repartition_glc_frac_rain_slope) + allocate(params%precip_repartition_nonglc_all_snow_t) + allocate(params%precip_repartition_nonglc_frac_rain_slope) + + ! allocate derived type arrays based on distributed parameter arrays + if (.not. allocated(distparams%precip_repartition_glc_all_rain_t_celsius%val)) then + call endrun(subname //' ERROR: Must initialize precip_repartition_glc_all_rain_t_celsius') + endif + if (.not. allocated(distparams%precip_repartition_glc_all_snow_t_celsius%val)) then + call endrun(subname //' ERROR: Must initialize precip_repartition_glc_all_snow_t_celsius') + endif + if (.not. allocated(distparams%precip_repartition_nonglc_all_rain_t_celsius%val)) then + call endrun(subname //' ERROR: Must initialize precip_repartition_nonglc_all_rain_t_celsius') + endif + if (.not. allocated(distparams%precip_repartition_nonglc_all_snow_t_celsius%val)) then + call endrun(subname //' ERROR: Must initialize precip_repartition_nonglc_all_snow_t_celsius') + endif - if (.not. present(precip_repartition_glc_all_snow_t)) then - call endrun(subname // & - ' ERROR: For repartition_rain_snow true, precip_repartition_glc_all_snow_t must be provided') - end if - if (.not. present(precip_repartition_glc_all_rain_t)) then - call endrun(subname // & - ' ERROR: For repartition_rain_snow true, precip_repartition_glc_all_rain_t must be provided') - end if - if (.not. present(precip_repartition_nonglc_all_snow_t)) then - call endrun(subname // & - ' ERROR: For repartition_rain_snow true, precip_repartition_nonglc_all_snow_t must be provided') - end if - if (.not. present(precip_repartition_nonglc_all_rain_t)) then - call endrun(subname // & - ' ERROR: For repartition_rain_snow true, precip_repartition_nonglc_all_rain_t must be provided') - end if + ! set %is_distributed based on distparams values + params%precip_repartition_glc_all_snow_t%is_distributed = & + distparams%precip_repartition_glc_all_rain_t_celsius%is_distributed + params%precip_repartition_glc_frac_rain_slope%is_distributed = & + distparams%precip_repartition_glc_all_rain_t_celsius%is_distributed + params%precip_repartition_nonglc_all_snow_t%is_distributed = & + distparams%precip_repartition_nonglc_all_rain_t_celsius%is_distributed + params%precip_repartition_nonglc_frac_rain_slope%is_distributed = & + distparams%precip_repartition_nonglc_all_rain_t_celsius%is_distributed + + ! allocate glacier parameter arrays + beg_index = lbound(distparams%precip_repartition_glc_all_rain_t_celsius%val,1) + end_index = ubound(distparams%precip_repartition_glc_all_rain_t_celsius%val,1) + allocate(params%precip_repartition_glc_all_snow_t%val(beg_index:end_index)) + allocate(params%precip_repartition_glc_frac_rain_slope%val(beg_index:end_index)) + params%precip_repartition_glc_all_snow_t%val(:) = nan + params%precip_repartition_glc_frac_rain_slope%val(:) = nan + + ! allocate non-glacier parameter arrays + beg_index = lbound(distparams%precip_repartition_nonglc_all_rain_t_celsius%val,1) + end_index = ubound(distparams%precip_repartition_nonglc_all_rain_t_celsius%val,1) + allocate(params%precip_repartition_nonglc_all_snow_t%val(beg_index:end_index)) + allocate(params%precip_repartition_nonglc_frac_rain_slope%val(beg_index:end_index)) + params%precip_repartition_nonglc_all_snow_t%val(:) = nan + params%precip_repartition_nonglc_frac_rain_slope%val(:) = nan + + if (repartition_rain_snow) then ! Do some other error checking - if (precip_repartition_glc_all_rain_t <= precip_repartition_glc_all_snow_t) then - call endrun(subname // & - ' ERROR: Must have precip_repartition_glc_all_snow_t < precip_repartition_glc_all_rain_t') - end if + ! NOTE: EBK 3/5/2026 -- this was commented out in PR #305 with this note below. It would need to be redone over gridcells... + !todo: should this be done on a gridcell basis, or just removed? - if (precip_repartition_nonglc_all_rain_t <= precip_repartition_nonglc_all_snow_t) then - call endrun(subname // & - ' ERROR: Must have precip_repartition_nonglc_all_snow_t < precip_repartition_nonglc_all_rain_t') - end if +!!$ if (precip_repartition_glc_all_rain_t_celsius <= precip_repartition_glc_all_snow_t_celsius) then +!!$ call endrun(subname // & +!!$ ' ERROR: Must have precip_repartition_glc_all_snow_t < precip_repartition_glc_all_rain_t') +!!$ end if +!!$ +!!$ if (precip_repartition_nonglc_all_rain_t_celsius <= precip_repartition_nonglc_all_snow_t_celsius) then +!!$ call endrun(subname // & +!!$ ' ERROR: Must have precip_repartition_nonglc_all_snow_t < precip_repartition_nonglc_all_rain_t') +!!$ end ifb ! Convert to the form of the parameters we want for the main code call compute_ramp_params( & - all_snow_t_c = precip_repartition_glc_all_snow_t, & - all_rain_t_c = precip_repartition_glc_all_rain_t, & - all_snow_t_k = params%precip_repartition_glc_all_snow_t, & - frac_rain_slope = params%precip_repartition_glc_frac_rain_slope) + all_snow_t_c = distparams%precip_repartition_glc_all_snow_t_celsius%val, & + all_rain_t_c = distparams%precip_repartition_glc_all_rain_t_celsius%val, & + all_snow_t_k = params%precip_repartition_glc_all_snow_t%val, & + frac_rain_slope = params%precip_repartition_glc_frac_rain_slope%val) call compute_ramp_params( & - all_snow_t_c = precip_repartition_nonglc_all_snow_t, & - all_rain_t_c = precip_repartition_nonglc_all_rain_t, & - all_snow_t_k = params%precip_repartition_nonglc_all_snow_t, & - frac_rain_slope = params%precip_repartition_nonglc_frac_rain_slope) - - else ! .not. repartition_rain_snow - params%precip_repartition_glc_all_snow_t = nan - params%precip_repartition_glc_frac_rain_slope = nan - params%precip_repartition_nonglc_all_snow_t = nan - params%precip_repartition_nonglc_frac_rain_slope = nan + all_snow_t_c = distparams%precip_repartition_nonglc_all_snow_t_celsius%val, & + all_rain_t_c = distparams%precip_repartition_nonglc_all_rain_t_celsius%val, & + all_snow_t_k = params%precip_repartition_nonglc_all_snow_t%val, & + frac_rain_slope = params%precip_repartition_nonglc_frac_rain_slope%val) + end if contains subroutine compute_ramp_params(all_snow_t_c, all_rain_t_c, & all_snow_t_k, frac_rain_slope) - real(r8), intent(in) :: all_snow_t_c ! Temperature at which precip falls entirely as rain (deg C) - real(r8), intent(in) :: all_rain_t_c ! Temperature at which precip falls entirely as snow (deg C) - real(r8), intent(out) :: all_snow_t_k ! Temperature at which precip falls entirely as snow (K) - real(r8), intent(out) :: frac_rain_slope ! Slope of the frac_rain vs. T relationship - - frac_rain_slope = 1._r8 / (all_rain_t_c - all_snow_t_c) - all_snow_t_k = all_snow_t_c + tfrz + real(r8), intent(in) :: all_snow_t_c(:) ! Temperature at which precip falls entirely as rain (deg C) + real(r8), intent(in) :: all_rain_t_c(:) ! Temperature at which precip falls entirely as snow (deg C) + real(r8), intent(out) :: all_snow_t_k(:) ! Temperature at which precip falls entirely as snow (K) + real(r8), intent(out) :: frac_rain_slope(:) ! Slope of the frac_rain vs. T relationship + integer :: g + integer :: beg_index, end_index + + beg_index = lbound(all_rain_t_c,1) + end_index = ubound(all_rain_t_c,1) + + do g = beg_index,end_index + frac_rain_slope(g) = 1._r8 / (all_rain_t_c(g) - all_snow_t_c(g)) + all_snow_t_k(g) = all_snow_t_c(g) + tfrz + enddo end subroutine compute_ramp_params end function atm2lnd_params_constructor - !------------------------------------------------------------------------ subroutine Init(this, bounds, NLFilename) @@ -356,10 +387,6 @@ subroutine ReadNamelist(this, NLFilename) real(r8) :: lapse_rate real(r8) :: lapse_rate_longwave real(r8) :: longwave_downscaling_limit - real(r8) :: precip_repartition_glc_all_snow_t - real(r8) :: precip_repartition_glc_all_rain_t - real(r8) :: precip_repartition_nonglc_all_snow_t - real(r8) :: precip_repartition_nonglc_all_rain_t integer :: ierr ! error code integer :: unitn ! unit for namelist file @@ -369,9 +396,7 @@ subroutine ReadNamelist(this, NLFilename) !----------------------------------------------------------------------- namelist /atm2lnd_inparm/ repartition_rain_snow, glcmec_downscale_longwave, & - lapse_rate, lapse_rate_longwave, longwave_downscaling_limit, & - precip_repartition_glc_all_snow_t, precip_repartition_glc_all_rain_t, & - precip_repartition_nonglc_all_snow_t, precip_repartition_nonglc_all_rain_t + lapse_rate, lapse_rate_longwave, longwave_downscaling_limit ! Initialize namelist variables to defaults repartition_rain_snow = .false. @@ -379,10 +404,6 @@ subroutine ReadNamelist(this, NLFilename) lapse_rate = nan lapse_rate_longwave = nan longwave_downscaling_limit = nan - precip_repartition_glc_all_snow_t = nan - precip_repartition_glc_all_rain_t = nan - precip_repartition_nonglc_all_snow_t = nan - precip_repartition_nonglc_all_rain_t = nan if (masterproc) then unitn = getavu() @@ -404,10 +425,6 @@ subroutine ReadNamelist(this, NLFilename) call shr_mpi_bcast(lapse_rate, mpicom) call shr_mpi_bcast(lapse_rate_longwave, mpicom) call shr_mpi_bcast(longwave_downscaling_limit, mpicom) - call shr_mpi_bcast(precip_repartition_glc_all_snow_t, mpicom) - call shr_mpi_bcast(precip_repartition_glc_all_rain_t, mpicom) - call shr_mpi_bcast(precip_repartition_nonglc_all_snow_t, mpicom) - call shr_mpi_bcast(precip_repartition_nonglc_all_rain_t, mpicom) if (masterproc) then write(iulog,*) ' ' @@ -421,12 +438,6 @@ subroutine ReadNamelist(this, NLFilename) write(iulog,*) 'lapse_rate_longwave = ', lapse_rate_longwave write(iulog,*) 'longwave_downscaling_limit = ', longwave_downscaling_limit end if - if (repartition_rain_snow) then - write(iulog,*) 'precip_repartition_glc_all_snow_t = ', precip_repartition_glc_all_snow_t - write(iulog,*) 'precip_repartition_glc_all_rain_t = ', precip_repartition_glc_all_rain_t - write(iulog,*) 'precip_repartition_nonglc_all_snow_t = ', precip_repartition_nonglc_all_snow_t - write(iulog,*) 'precip_repartition_nonglc_all_rain_t = ', precip_repartition_nonglc_all_rain_t - end if write(iulog,*) ' ' end if @@ -435,15 +446,10 @@ subroutine ReadNamelist(this, NLFilename) glcmec_downscale_longwave = glcmec_downscale_longwave, & lapse_rate = lapse_rate, & lapse_rate_longwave = lapse_rate_longwave, & - longwave_downscaling_limit = longwave_downscaling_limit, & - precip_repartition_glc_all_snow_t = precip_repartition_glc_all_snow_t, & - precip_repartition_glc_all_rain_t = precip_repartition_glc_all_rain_t, & - precip_repartition_nonglc_all_snow_t = precip_repartition_nonglc_all_snow_t, & - precip_repartition_nonglc_all_rain_t = precip_repartition_nonglc_all_rain_t) + longwave_downscaling_limit = longwave_downscaling_limit) end subroutine ReadNamelist - !------------------------------------------------------------------------ subroutine InitAllocate(this, bounds) ! diff --git a/src/main/clm_initializeMod.F90 b/src/main/clm_initializeMod.F90 index 4530fda860..7f0a9f2ebd 100644 --- a/src/main/clm_initializeMod.F90 +++ b/src/main/clm_initializeMod.F90 @@ -25,6 +25,8 @@ module clm_initializeMod use LandunitType , only : lun ! instance use ColumnType , only : col ! instance use PatchType , only : patch ! instance +! use DistParamType , only : distparams, distparamsstreams + use DistParamMod , only : InitDistributedParameters use reweightMod , only : reweight_wrapup use filterMod , only : allocFilters, filter, filter_inactive_and_active use CLMFatesInterfaceMod , only : CLMFatesGlobals1,CLMFatesGlobals2 @@ -345,12 +347,16 @@ subroutine initialize2(ni,nj, currtime) call get_proc_bounds(bounds_proc) nclumps = get_proc_clumps() - ! Read in parameters files + ! Read in parameters call clm_instReadNML( NLFilename ) allocate(nutrient_competition_method, & source=create_nutrient_competition_method(bounds_proc)) call readParameters(photosyns_inst) + ! Read in spatially distributed parameters +! call distparams%Init(bounds_proc) +!scs call distparams%readDistributedParams(bounds_proc) + call InitDistributedParameters(bounds_proc) ! Initialize time manager if (nsrest == nsrStartup) then diff --git a/src/main/clm_varctl.F90 b/src/main/clm_varctl.F90 index 83133acf2b..12425aee4c 100644 --- a/src/main/clm_varctl.F90 +++ b/src/main/clm_varctl.F90 @@ -111,6 +111,7 @@ module clm_varctl character(len=fname_len), public :: fsurdat = ' ' ! surface data file name character(len=fname_len), public :: hillslope_file = ' ' ! hillslope data file name character(len=fname_len), public :: paramfile = ' ' ! ASCII data file with PFT physiological constants + character(len=fname_len), public :: distributed_paramfile = ' ' ! spatially distributed parameter file name character(len=fname_len), public :: nrevsn = ' ' ! restart data file name for branch run character(len=fname_len), public :: fsnowoptics = ' ' ! snow optical properties file name character(len=fname_len), public :: fsnowaging = ' ' ! snow aging parameters file name @@ -398,6 +399,12 @@ module clm_varctl integer, public :: CN_evergreen_phenology_opt = 0 integer, public :: carbon_resp_opt = 0 + !---------------------------------------------------------- + ! spatially distributed parameters switch + !---------------------------------------------------------- + + logical, public :: use_distributed_parameters = .false. ! true => use spatially distributed parameter stream data + !---------------------------------------------------------- ! prescribed soil moisture streams switch !---------------------------------------------------------- diff --git a/src/main/controlMod.F90 b/src/main/controlMod.F90 index 936e87a337..bc137dfc5e 100644 --- a/src/main/controlMod.F90 +++ b/src/main/controlMod.F90 @@ -46,7 +46,7 @@ module controlMod use SoilBiogeochemLittVertTranspMod , only: som_adv_flux, max_depth_cryoturb use SoilBiogeochemVerticalProfileMod , only: surfprof_exp use SoilBiogeochemNitrifDenitrifMod , only: no_frozen_nitrif_denitrif - use SoilHydrologyMod , only: soilHydReadNML, hillslope_hydrology_ReadNML + use SoilHydrologyMod , only: hillslope_hydrology_ReadNML use CNFireFactoryMod , only: CNFireReadNML use CanopyFluxesMod , only: CanopyFluxesReadNML use shr_drydep_mod , only: n_drydep @@ -149,7 +149,7 @@ subroutine control_init(dtime) namelist /clm_inparm/ & fsurdat, hillslope_file, & - paramfile, fsnowoptics, fsnowaging + paramfile, distributed_paramfile, fsnowoptics, fsnowaging ! History, restart options @@ -618,7 +618,6 @@ subroutine control_init(dtime) call CNFUNReadNML( NLFilename ) end if - call soilHydReadNML( NLFilename ) if ( use_hillslope ) then call hillslope_hydrology_ReadNML( NLFilename ) endif @@ -758,6 +757,7 @@ subroutine control_spmd() call mpi_bcast (hillslope_file, len(hillslope_file), MPI_CHARACTER, 0, mpicom, ier) call mpi_bcast (fatmlndfrc,len(fatmlndfrc),MPI_CHARACTER, 0, mpicom, ier) call mpi_bcast (paramfile, len(paramfile) , MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (distributed_paramfile, len(distributed_paramfile) , MPI_CHARACTER, 0, mpicom, ier) call mpi_bcast (fsnowoptics, len(fsnowoptics), MPI_CHARACTER, 0, mpicom, ier) call mpi_bcast (fsnowaging, len(fsnowaging), MPI_CHARACTER, 0, mpicom, ier) @@ -1051,6 +1051,7 @@ subroutine control_print () write(iulog,*) ' use_SSRE = ', use_SSRE write(iulog,*) 'input data files:' write(iulog,*) ' PFT physiology and parameters file = ',trim(paramfile) + write(iulog,*) ' distributed parameter file = ',trim(distributed_paramfile) if (fsurdat == ' ') then write(iulog,*) ' fsurdat, surface dataset not set' else diff --git a/src/main/initVerticalMod.F90 b/src/main/initVerticalMod.F90 index 64383e7a7c..87a540e668 100644 --- a/src/main/initVerticalMod.F90 +++ b/src/main/initVerticalMod.F90 @@ -27,6 +27,7 @@ module initVerticalMod use LandunitType , only : lun use GridcellType , only : grc use ColumnType , only : col + use DistParamType , only : distparams => distributed_parameters use glcBehaviorMod , only : glc_behavior_type use abortUtils , only : endrun use ncdio_pio @@ -45,8 +46,6 @@ module initVerticalMod ! !PRIVATE MEMBER FUNCTIONS: private :: hasBedrock ! true if the given column type includes bedrock layers type, private :: params_type - real(r8) :: slopebeta ! exponent for microtopography pdf sigma (unitless) - real(r8) :: slopemax ! max topographic slope for microtopography pdf sigma (unitless) real(r8) :: zbedrock ! parameter to substitute for zbedrock (m) real(r8) :: zbedrock_sf ! parameter to scale zbedrock (m) end type params_type @@ -76,11 +75,6 @@ subroutine readParams( ncid ) character(len=*), parameter :: subname = 'readParams_initVertical' !-------------------------------------------------------------------- - ! Exponent for microtopography pdf sigma (unitless) - call readNcdioScalar(ncid, 'slopebeta', subname, params_inst%slopebeta) - ! Max topographic slope for microtopography pdf sigma (unitless) - call readNcdioScalar(ncid, 'slopemax', subname, params_inst%slopemax) - call readNcdioScalar(ncid, 'zbedrock', subname, params_inst%zbedrock) call readNcdioScalar(ncid, 'zbedrock_sf', subname, params_inst%zbedrock_sf) @@ -657,12 +651,12 @@ subroutine initVertical(bounds, glc_behavior, thick_wall, thick_roof) do c = begc,endc ! microtopographic parameter, units are meters (try smooth function of slope) - slope0 = params_inst%slopemax**(1._r8/params_inst%slopebeta) + slope0 = distparams%slopemax%param_val(col%gridcell(c))**(1._r8/distparams%slopebeta%param_val(col%gridcell(c))) if (col%is_hillslope_column(c)) then - col%micro_sigma(c) = (atan(col%hill_slope(c)) + slope0)**(params_inst%slopebeta) + col%micro_sigma(c) = (atan(col%hill_slope(c)) + slope0)**(distparams%slopebeta%param_val(col%gridcell(c))) else - col%micro_sigma(c) = (col%topo_slope(c) + slope0)**(params_inst%slopebeta) + col%micro_sigma(c) = (col%topo_slope(c) + slope0)**(distparams%slopebeta%param_val(col%gridcell(c))) endif end do diff --git a/src/main/ncdio_pio.F90.in b/src/main/ncdio_pio.F90.in index 991823fb67..7f0a5931af 100644 --- a/src/main/ncdio_pio.F90.in +++ b/src/main/ncdio_pio.F90.in @@ -62,6 +62,7 @@ module ncdio_pio public :: ncd_inqdname ! inquire dimension name public :: ncd_inqdlen ! inquire dimension length public :: ncd_inqfdims ! inquire file dimnesions + public :: ncd_inqnvars ! inquire number of variables on file public :: ncd_defvar ! define variables public :: ncd_inqvid ! inquire variable id public :: ncd_inqvname ! inquire variable name @@ -678,7 +679,7 @@ contains !----------------------------------------------------------------------- vname = '' - status = PIO_inq_varname(ncid,vardesc,vname) + status = PIO_inq_varname(ncid,varid,vname) end subroutine ncd_inqvname @@ -897,6 +898,26 @@ contains end subroutine ncd_inqnatts + !----------------------------------------------------------------------- + subroutine ncd_inqnvars(ncid, nvariables) + ! + ! !DESCRIPTION: + ! Inquire number of variables + ! + ! !ARGUMENTS: + class(file_desc_t), intent(inout) :: ncid ! netcdf file id + integer , intent(out) :: nvariables ! number of variables + ! + ! !LOCAL VARIABLES: + integer :: status + + character(len=*), parameter :: subname = 'ncd_inqnvars' + !----------------------------------------------------------------------- + + status = PIO_inquire(ncid, nvariables=nvariables) + + end subroutine ncd_inqnvars + !----------------------------------------------------------------------- subroutine ncd_inqattname(ncid, varid, attnum, attname) ! diff --git a/src/main/readParamsMod.F90 b/src/main/readParamsMod.F90 index c11a741198..5a9a7b9185 100644 --- a/src/main/readParamsMod.F90 +++ b/src/main/readParamsMod.F90 @@ -8,14 +8,17 @@ module readParamsMod ! ! ! USES: use clm_varctl , only : paramfile, iulog, use_fates, use_cn + use clm_varctl , only : distributed_paramfile use SoilBiogeochemDecompCascadeConType, only : mimics_decomp, century_decomp, decomp_method use spmdMod , only : masterproc use fileutils , only : getfil use ncdio_pio , only : ncd_pio_closefile, ncd_pio_openfile use ncdio_pio , only : file_desc_t , ncd_inqdid, ncd_inqdlen + use decompMod , only : bounds_type implicit none private + character(len=*), parameter, private :: sourcefile = __FILE__ ! public :: readParameters @@ -49,20 +52,16 @@ subroutine readParameters (photosyns_inst) use CanopyFluxesMod , only : readParams_CanopyFluxes => readParams use UrbanFluxesMod , only : readParams_UrbanFluxes => readParams use CanopyHydrologyMod , only : readParams_CanopyHydrology => readParams - use SoilHydrologyMod , only : readParams_SoilHydrology => readParams use SoilStateInitTimeConstMod , only : readParams_SoilStateInitTimeConst => readParams use SoilWaterMovementMod , only : readParams_SoilWaterMovement => readParams - use SaturatedExcessRunoffMod , only : readParams_SaturatedExcessRunoff => readParams use InfiltrationExcessRunoffMod , only : readParams_InfiltrationExcessRunoff => readParams - use SurfaceResistanceMod , only : readParams_SurfaceResistance => readParams - use WaterDiagnosticBulkType , only : readParams_WaterDiagnosticBulk => readParams use SnowHydrologyMod , only : readParams_SnowHydrology => readParams use SnowSnicarMod , only : readParams_SnowSnicar => readParams use initVerticalMod , only : readParams_initVertical => readParams - use SurfaceWaterMod , only : readParams_SurfaceWater => readParams use SoilHydrologyInitTimeConstMod , only : readParams_SoilHydrologyInitTimeConst => readParams use clm_varctl, only : NLFilename_in use PhotosynthesisMod , only : photosyns_type + ! ! !ARGUMENTS: type(photosyns_type) , intent(in) :: photosyns_inst @@ -126,17 +125,12 @@ subroutine readParameters (photosyns_inst) call readParams_CanopyFluxes ( ncid ) call readParams_UrbanFluxes ( ncid ) call readParams_CanopyHydrology ( ncid ) - call readParams_SoilHydrology ( ncid ) call readParams_SoilStateInitTimeConst ( ncid ) - call readParams_SaturatedExcessRunoff ( ncid ) call readParams_SoilWaterMovement ( ncid ) call readParams_InfiltrationExcessRunoff ( ncid ) - call readParams_SurfaceResistance ( ncid ) - call readParams_WaterDiagnosticBulk ( ncid ) call readParams_SnowHydrology ( ncid ) call readParams_SnowSnicar ( ncid ) call readParams_initVertical ( ncid ) - call readParams_SurfaceWater ( ncid ) call readParams_SoilHydrologyInitTimeConst ( ncid ) ! call ncd_pio_closefile(ncid) diff --git a/tools/contrib/README b/tools/contrib/README index d56b185b73..812a937c7d 100644 --- a/tools/contrib/README +++ b/tools/contrib/README @@ -14,6 +14,8 @@ conda activate ctsm_pylib Brief description of scripts: +create_2d_distparam_file.py + Create a 2D distributed parameter file to use with the use_distributed_parameters option in CTSM create_scrip_file.ncl Create a SCRIP grid file needed for running with WRF run_clm_historical.v11.csh diff --git a/tools/contrib/create_2d_distparam_file.py b/tools/contrib/create_2d_distparam_file.py new file mode 100755 index 0000000000..961440d2ec --- /dev/null +++ b/tools/contrib/create_2d_distparam_file.py @@ -0,0 +1,163 @@ +#! /usr/bin/env python3 +""" +---------------------------------------------------------------- +Instructions for running using conda python environments: +../../py_env_create +conda activate ctsm_pylib +""" +import subprocess +import numpy as np +import netCDF4 as netcdf4 +import os +import sys + +# -- add python/ctsm to path +_CTSM_PYTHON = os.path.join( + os.path.dirname(os.path.realpath(__file__)), os.pardir, os.pardir, "python" +) +sys.path.insert(1, _CTSM_PYTHON) + +from ctsm.utils import add_tag_to_filename + +# Location for CESM inputdata directory +# TODO: Have this as an input argument and set defaults for: Derecho, Casper and Izumi +din_loc_root = '/glade/campaign/cesm/cesmdata/inputdata' +# creates surface dataset with distributed parameters +dir_surfdata = os.path.join( din_loc_root, 'lnd', 'clm2', 'surfdata_esmf', 'ctsm5.4.0' ) +dir_output='./' + +# template file at model resolution for coordinates, land mask, etc. +# NOTE: the particular simulation year (here 2000) and PFT number doesn't matter for these purposes +fsurf = os.path.join( dir_surfdata, 'surfdata_0.9x1.25_hist_2000_78pfts_c251022.nc' ) + +tag = "distparams" +# use add_tag_to_filename to update the ending creating date to current time +outfile = add_tag_to_filename( os.path.join( dir_output, 'ctsm60_2Dparamdata_0.9x1.25.c260306.nc'), tag ) +paramfile = os.path.join( din_loc_root, 'lnd/clm2/paramdata/ctsm60_params.c260303.nc' ) + +# calibrated parameters from Tang2025 +param_list = ['e_ice','n_baseflow','baseflow_scalar','fff','d_max','FMAX','om_frac_sf','interception_fraction','watsat_sf','sucsat_sf','bsw_sf','zbedrock_sf','hksat_sf','slopebeta','liq_canopy_storage_scalar','maximum_leaf_wetted_fraction','n_melt_coef','accum_factor','upplim_destruct_metamorph','zsno','precip_repartition_nonglc_all_rain_t','medlynslope','jmaxb0','kmax','cv','leafcn'] + +# snow parameters +param_list += ['xdrdt','scvng_fct_mlt_sf','snw_rds_refrz','fresh_snw_rds_max'] + +# remove non-standard parameters and those already on surface data file +exclude_list = ['FMAX','zbedrock_sf','om_frac_sf'] +for e in exclude_list: + param_list.remove(e) + +# namelist parameters (add all_snow_t) +pnamelist = ['baseflow_scalar','precip_repartition_nonglc_all_rain_t','precip_repartition_nonglc_all_snow_t'] +param_list += ['precip_repartition_nonglc_all_snow_t'] +# assign values from namelist_defaults_ctsm.xml +pnamelist_values = [1e-3,2,0] +pnamelist_attributes = [{'long_name':'baseflow scaling coefficient','units':'unitless'},{'long_name':'all rain temperature','units':'degrees C'},{'long_name':'all snow temperature','units':'degrees C'}] + +nparams = len(param_list) + +#-- Check whether file exists --------------------------------- +command=['ls',outfile] +file_exists=subprocess.call(command,stderr=subprocess.PIPE) +if file_exists > 0: + print('creating new file: ', outfile) +else: + print('overwriting file: ', outfile) + +#-- Open surface data file +f = netcdf4.Dataset(fsurf, 'r') +global_attributes = f.ncattrs() +variables = f.variables +dimensions = f.dimensions +jm, im = len(dimensions['lsmlat']),len(dimensions['lsmlon']) +lon = np.asarray(f.variables['LONGXY'][0,]) +lat = np.asarray(f.variables['LATIXY'][:,0]) + +if 'PFTDATA_MASK' in f.variables.keys(): + landmask = np.asarray(f.variables['PFTDATA_MASK'][:,]) +if 'LANDFRAC_PFT' in f.variables.keys(): # ctsm >= 5.3.0 + landmask = np.where(f.variables['LANDFRAC_PFT'][:,]>0,1,0) + +#-- Open parameter file +p1 = netcdf4.Dataset(paramfile, 'r') + +#-- Open output file +w = netcdf4.Dataset(outfile, 'w', format='NETCDF3_64BIT') +w.title = 'CTSM parameters' +w.createDimension('lat',int(jm)) +w.createDimension('lon',int(im)) +w.createDimension('time',None) +w.createVariable('lon',float,('lon',)) +w.variables['lon'].units = 'degrees east' +w.variables['lon'].long_name = 'longitude of grid cell center' +w.variables['lon'][:,] = lon +w.createVariable('lat',float,('lat',)) +w.variables['lat'].units = 'degrees north' +w.variables['lat'].long_name = 'latitude of grid cell center' +w.variables['lat'][:,] = lat +w.createVariable('time',float,('time',)) +w.variables['time'].units = 'days since 2000-01-01 00:00' +w.variables['time'].long_name = 'time' +w.variables['time'].calendar = 'noleap' +w.variables['time'][0,] = 0.5 +for pname in param_list: + print(pname) + # set namelist variable values using specified values + if pname in pnamelist: + ip = pnamelist.index(pname) + pvar = pnamelist_values[ip] + #-- Create variable and populate array + w.createVariable(pname,float,('time','lat','lon')) + wvar = w.variables[pname][:,] + #wvar[landmask>0,] = pvar # seems that valid data needed everywhere + wvar[0,] = pvar + + # create spatial variation + if 1==2 and pname == 'baseflow_scalar': + wvar[0,:,lon < 60] = 1e-1 + wvar[0,:,lon > 250] = 1e-4 + if 1==2 and pname == 'precip_repartition_nonglc_all_rain_t': + wvar[0,:,lon < 90] = 1 + wvar[0,:,lon > 250] = 3 + if 1==2 and pname == 'precip_repartition_nonglc_all_snow_t': + wvar[0,:,lon < 90] = -3 + wvar[0,:,lon > 250] = -4 + + + w.variables[pname][0,] = wvar + #-- Set attribute values + for att in pnamelist_attributes[ip].keys(): + #print(pname,att,pnamelist_attributes[ip][att]) + w.variables[pname].setncattr(att,pnamelist_attributes[ip][att]) + else: # use parameter values from parameter file + pvar = p1.variables[pname][:,] + # only create 2d fields from scalars for now + if len(pvar.shape) == 0: + #-- Create variable and populate array + + #(shr_strdata_readstrm) ERROR: only double, real and short types are supported for stream read + print('dtype ',pvar.dtype) + if pvar.dtype in ['int','int32','int64']: + #pvar = pvar.astype('short') + pvar = pvar.astype(float) + w.createVariable(pname,pvar.dtype,('time','lat','lon')) + #w.variables[pname][landmask>0,] = pvar + wvar = w.variables[pname][:,] + #wvar[landmask>0,] = pvar # seems that valid data needed everywhere + wvar[0,] = pvar + + if 1==2 and pname == 'd_max': + wvar[0,:,lon < 60] = 5 + wvar[0,:,lon > 250] = 30 + if 1==2 and pname == 'xdrdt': + wvar[0,lat < -60] = 1 + + w.variables[pname][0,] = wvar + #-- Set attribute values + att = p1.variables[pname].ncattrs() + for attname in att: + w.variables[pname].setncattr(attname,p1.variables[pname].getncattr(attname)) + +w.close() +p1.close() +f.close() +print('created ',outfile)