diff --git a/bld/CLMBuildNamelist.pm b/bld/CLMBuildNamelist.pm
index 54752b6dbc..bbe83a3dc5 100755
--- a/bld/CLMBuildNamelist.pm
+++ b/bld/CLMBuildNamelist.pm
@@ -4172,60 +4172,115 @@ sub setup_logic_lai_streams {
sub setup_logic_cropcal_streams {
my ($opts, $nl_flags, $definition, $defaults, $nl) = @_;
- # Set first and last stream years
- add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'stream_year_first_cropcal',
- 'sim_year'=>$nl_flags->{'sim_year'},
- 'sim_year_range'=>$nl_flags->{'sim_year_range'});
- add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'stream_year_last_cropcal',
- 'sim_year'=>$nl_flags->{'sim_year'},
- 'sim_year_range'=>$nl_flags->{'sim_year_range'});
-
- # Set align year, if first and last years are different
- if ( $nl->get_value('stream_year_first_cropcal') !=
- $nl->get_value('stream_year_last_cropcal') ) {
- add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl,
- 'model_year_align_cropcal', 'sim_year'=>$nl_flags->{'sim_year'},
- 'sim_year_range'=>$nl_flags->{'sim_year_range'});
- }
-
# Set up other crop calendar parameters
+ add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'cropcals_rx');
+ add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'cropcals_rx_adapt');
add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'generate_crop_gdds');
add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'use_mxmat');
- # Option checks
- my $generate_crop_gdds = $nl->get_value('generate_crop_gdds') ;
- my $use_mxmat = $nl->get_value('use_mxmat') ;
+ # These can't both be true
+ my $cropcals_rx = $nl->get_value('cropcals_rx') ;
+ my $cropcals_rx_adapt = $nl->get_value('cropcals_rx_adapt') ;
+ if (&value_is_true($cropcals_rx) and &value_is_true($cropcals_rx_adapt)) {
+ $log->fatal_error("cropcals_rx and cropcals_rx_adapt may not both be true" );
+ }
+
+ # Add defaults if using prescribed crop calendars
+ if ( &value_is_true($cropcals_rx) or &value_is_true($cropcals_rx_adapt) ) {
+ add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'stream_fldFileName_swindow_start');
+ add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'stream_fldFileName_swindow_end');
+ add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'stream_fldfilename_cultivar_gdds');
+ add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'stream_meshfile_cropcal');
+ if ( &value_is_true($cropcals_rx_adapt) ) {
+ add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'stream_fldFileName_gdd20_baseline');
+ }
+ }
+
+ # Add defaults if using any crop calendar input files
my $swindow_start_file = $nl->get_value('stream_fldFileName_swindow_start') ;
my $swindow_end_file = $nl->get_value('stream_fldFileName_swindow_end') ;
my $gdd_file = $nl->get_value('stream_fldFileName_cultivar_gdds') ;
my $gdd20_baseline_file = $nl->get_value('stream_fldFileName_gdd20_baseline') ;
my $mesh_file = $nl->get_value('stream_meshfile_cropcal') ;
- if ( ($swindow_start_file eq '' and $swindow_start_file ne '') or ($swindow_start_file ne '' and $swindow_start_file eq '') ) {
- $log->fatal_error("When specifying sowing window dates, you must provide both swindow_start_file and swindow_end_file. To specify exact sowing dates, use the same file." );
+ if ( !&string_is_undef_or_empty($swindow_start_file) or !&string_is_undef_or_empty($swindow_end_file) or !&string_is_undef_or_empty($gdd_file) or !&string_is_undef_or_empty($gdd20_baseline_file) or !&string_is_undef_or_empty($mesh_file)) {
+
+ # User gave an input file without specifying cropcals_rx or cropcals_rx_adapt = .true.
+ # Requiring this means nothing to the code, but helps namelist make more sense
+ if ( !&value_is_true($cropcals_rx) and !&value_is_true($cropcals_rx_adapt) ){
+ $log->fatal_error("If providing any crop calendar input file(s), cropcals_rx or cropcals_rx_adapt must be true" );
+ }
+
+ # User set cropcals_rx_adapt to true but set stream_fldFileName_gdd20_baseline to empty
+ if ( &value_is_true($cropcals_rx_adapt) and &string_is_undef_or_empty($gdd20_baseline_file) ) {
+ $log->fatal_error("If cropcals_rx_adapt is true, stream_fldFileName_gdd20_baseline must be provided" );
+ }
+
+ # cropcals_rx_adapt is false but user provided stream_fldFileName_gdd20_baseline
+ if ( !&value_is_true($cropcals_rx_adapt) and !&string_is_undef_or_empty($gdd20_baseline_file) ) {
+ $log->fatal_error("If stream_fldFileName_gdd20_baseline provided, cropcals_rx_adapt must be true" );
+ }
+
+ # User provided an input file but set mesh file to empty
+ if ( &string_is_undef_or_empty($mesh_file) ) {
+ $log->fatal_error("If providing any crop calendar input file(s), you must provide stream_meshfile_cropcal" );
+ }
+
+ # Set stream years
+ add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'stream_year_first_cropcal',
+ 'sim_year'=>$nl_flags->{'sim_year'},
+ 'sim_year_range'=>$nl_flags->{'sim_year_range'});
+ add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'stream_year_last_cropcal',
+ 'sim_year'=>$nl_flags->{'sim_year'},
+ 'sim_year_range'=>$nl_flags->{'sim_year_range'});
+ add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'model_year_align_cropcal',
+ 'sim_year'=>$nl_flags->{'sim_year'},
+ 'sim_year_range'=>$nl_flags->{'sim_year_range'});
+
+ # Check/set things if first and last years are different
+ if ( $nl->get_value('stream_year_first_cropcal') !=
+ $nl->get_value('stream_year_last_cropcal') ) {
+
+ # Do not allow maturity requirements to change over time if stream_fldFileName_gdd20_baseline is provided. That would be nonsensical.
+ # Note that this restricts sowing windows from changing over time as well, because there are not separate stream_year settings for that.
+ if ( !&string_is_undef_or_empty($gdd20_baseline_file) ) {
+ $log->fatal_error("If cropcals_rx_adapt is true (i.e., stream_fldFileName_gdd20_baseline is provided), no crop calendar input is allowed to vary over time (i.e., stream_year_first_cropcal and stream_year_last_cropcal must be the same)." );
+ }
+ }
}
- if ( $gdd_file eq '' and $gdd20_baseline_file ne '' ) {
+
+ # If running with prescribed crop calendars, certain files must be provided
+ my $generate_crop_gdds = $nl->get_value('generate_crop_gdds') ;
+ if ( &value_is_true($cropcals_rx) or &value_is_true($cropcals_rx_adapt) ) {
+ if ( &string_is_undef_or_empty($swindow_start_file) or &string_is_undef_or_empty($swindow_end_file) ) {
+ $log->fatal_error("If cropcals_rx or cropcals_rx_adapt is true, sowing window start and end files must be provided. To specify exact sowing dates, use the same file." );
+ }
+ if ( &string_is_undef_or_empty($gdd_file) and (! &value_is_true($generate_crop_gdds)) ){
+ $log->fatal_error("If cropcals_rx or cropcals_rx_adapt is true and generate_crop_gdds is false, maturity requirement file stream_fldFileName_cultivar_gdds must be provided" );
+ }
+ }
+
+ # Option checks
+ if ( &string_is_undef_or_empty($gdd_file) and ! &string_is_undef_or_empty($gdd20_baseline_file) ) {
$log->fatal_error("If not providing stream_fldFileName_cultivar_gdds, don't provide stream_fldFileName_gdd20_baseline");
}
- if ( $generate_crop_gdds eq '.true.' ) {
- if ( $use_mxmat eq '.true.' ) {
+ if ( &value_is_true($generate_crop_gdds) ) {
+ my $use_mxmat = $nl->get_value('use_mxmat') ;
+ if ( &value_is_true($use_mxmat) ) {
$log->fatal_error("If generate_crop_gdds is true, you must also set use_mxmat to false" );
}
- if ( $swindow_start_file eq '' or $swindow_end_file eq '' ) {
+ if ( &string_is_undef_or_empty($swindow_start_file) or &string_is_undef_or_empty($swindow_end_file) ) {
$log->fatal_error("If generate_crop_gdds is true, you must specify stream_fldFileName_swindow_start and stream_fldFileName_swindow_end")
}
if ( $swindow_start_file ne $swindow_end_file ) {
$log->fatal_error("If generate_crop_gdds is true, you must specify exact sowing dates by setting stream_fldFileName_swindow_start and stream_fldFileName_swindow_end to the same file")
}
- if ( $gdd_file ne '' ) {
+ if ( ! &string_is_undef_or_empty($gdd_file) ) {
$log->fatal_error("If generate_crop_gdds is true, do not specify stream_fldFileName_cultivar_gdds")
}
- if ( $gdd20_baseline_file ne '' ) {
+ if ( ! &string_is_undef_or_empty($gdd20_baseline_file) ) {
$log->fatal_error("If generate_crop_gdds is true, do not specify stream_fldFileName_gdd20_baseline")
}
}
- if ( $mesh_file eq '' and ( $swindow_start_file ne '' or $gdd_file ne '' ) ) {
- $log->fatal_error("If prescribing crop sowing dates and/or maturity requirements, you must specify stream_meshfile_cropcal")
- }
}
#-------------------------------------------------------------------------------
diff --git a/bld/namelist_files/namelist_defaults_ctsm.xml b/bld/namelist_files/namelist_defaults_ctsm.xml
index 655e97c47c..85f37a22fd 100644
--- a/bld/namelist_files/namelist_defaults_ctsm.xml
+++ b/bld/namelist_files/namelist_defaults_ctsm.xml
@@ -1686,10 +1686,23 @@ lnd/clm2/surfdata_esmf/NEON/surfdata_1x1_NEON_TOOL_hist_78pfts_CMIP6_simyr2000_c
nnnn
-
-1850
-2100
-1850
+
+.false.
+.false.
+2000
+2000
+2000
+
+
+lnd/clm2/cropdata/calendars/processed/swindow_starts_ggcmi_crop_calendar_phase3_v1.01.2000-2000.20231005_145103.nc
+lnd/clm2/cropdata/calendars/processed/swindow_ends_ggcmi_crop_calendar_phase3_v1.01.2000-2000.20231005_145103.nc
+lnd/clm2/cropdata/calendars/processed/gdds_20230829_161011.nc
+share/meshes/360x720_120830_ESMFmesh_c20210507_cdf5.nc
+lnd/clm2/cropdata/calendars/processed/swindow_starts_ggcmi_crop_calendar_phase3_v1.01.2000-2000.20231005_145103.nc
+lnd/clm2/cropdata/calendars/processed/swindow_ends_ggcmi_crop_calendar_phase3_v1.01.2000-2000.20231005_145103.nc
+lnd/clm2/cropdata/calendars/processed/gdds_20230829_161011.nc
+lnd/clm2/testdata/gdd20baseline.tmp_dontupload.nc
+share/meshes/360x720_120830_ESMFmesh_c20210507_cdf5.nc
diff --git a/bld/namelist_files/namelist_definition_ctsm.xml b/bld/namelist_files/namelist_definition_ctsm.xml
index c88e987756..f37ada6847 100644
--- a/bld/namelist_files/namelist_definition_ctsm.xml
+++ b/bld/namelist_files/namelist_definition_ctsm.xml
@@ -1773,14 +1773,24 @@ Mapping method from LAI input file to the model resolution
+
+Flag to enable prescribed crop calendars (sowing window dates and maturity requirement)
+
+
+
+Flag to enable prescribed crop calendars (sowing window dates and maturity requirement), with maturity requirement adaptive based on recent climate
+
+
-First year to loop over for crop calendar data
+First year to loop over for crop calendar data (not including gdd20_baseline file)
-Last year to loop over for crop calendar data
+Last year to loop over for crop calendar data (not including gdd20_baseline file)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cime_config/testdefs/testmods_dirs/clm/RxCropCals/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/RxCropCals/user_nl_clm
index 9cbfea97f0..8a0b4a91be 100644
--- a/cime_config/testdefs/testmods_dirs/clm/RxCropCals/user_nl_clm
+++ b/cime_config/testdefs/testmods_dirs/clm/RxCropCals/user_nl_clm
@@ -1,8 +1,2 @@
-! Sowing windows
-stream_fldFileName_swindow_start = '$DIN_LOC_ROOT/lnd/clm2/cropdata/calendars/processed/swindow_starts_ggcmi_crop_calendar_phase3_v1.01.2000-2000.20231005_145103.nc'
-stream_fldFileName_swindow_end = '$DIN_LOC_ROOT/lnd/clm2/cropdata/calendars/processed/swindow_ends_ggcmi_crop_calendar_phase3_v1.01.2000-2000.20231005_145103.nc'
-stream_fldFileName_cultivar_gdds = '$DIN_LOC_ROOT/lnd/clm2/cropdata/calendars/processed/gdds_20230829_161011.nc'
-stream_year_first_cropcal = 2000
-stream_year_last_cropcal = 2000
-stream_meshfile_cropcal = '$DIN_LOC_ROOT/share/meshes/360x720_120830_ESMFmesh_c20210507_cdf5.nc'
+cropcals_rx = .true.
diff --git a/cime_config/testdefs/testmods_dirs/clm/RxCropCalsAdapt/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/RxCropCalsAdapt/user_nl_clm
index 1bba9d2a89..709c7221e0 100644
--- a/cime_config/testdefs/testmods_dirs/clm/RxCropCalsAdapt/user_nl_clm
+++ b/cime_config/testdefs/testmods_dirs/clm/RxCropCalsAdapt/user_nl_clm
@@ -1,3 +1,3 @@
-! Eventually replace this with half-degree version in the proper place
-stream_fldFileName_gdd20_baseline = '/glade/u/home/samrabin/ctsm_scale-mat-reqs/tools/crop_calendars/test.nc'
+cropcals_rx = .false.
+cropcals_rx_adapt = .true.
diff --git a/src/cpl/share_esmf/cropcalStreamMod.F90 b/src/cpl/share_esmf/cropcalStreamMod.F90
index f60ab51000..3333b6cfdc 100644
--- a/src/cpl/share_esmf/cropcalStreamMod.F90
+++ b/src/cpl/share_esmf/cropcalStreamMod.F90
@@ -47,6 +47,8 @@ module cropcalStreamMod
character(len=CL) :: stream_fldFileName_swindow_end ! sowing window end stream filename to read
character(len=CL) :: stream_fldFileName_cultivar_gdds ! cultivar growing degree-days stream filename to read
character(len=CL) :: stream_fldFileName_gdd20_baseline ! GDD20 baseline stream filename to read
+ logical :: cropcals_rx ! Used only for setting input files in namelist; does nothing in code, but needs to be here so namelist read doesn't crash
+ logical :: cropcals_rx_adapt ! Used only for setting input files in namelist; does nothing in code, but needs to be here so namelist read doesn't crash
character(len=*), parameter :: sourcefile = &
__FILE__
@@ -95,7 +97,9 @@ subroutine cropcal_init(bounds)
stream_fldFileName_swindow_end, &
stream_fldFileName_cultivar_gdds, &
stream_fldFileName_gdd20_baseline, &
- stream_meshfile_cropcal
+ stream_meshfile_cropcal, &
+ cropcals_rx, &
+ cropcals_rx_adapt
! Default values for namelist
stream_year_first_cropcal = 1 ! first year in stream to use