diff --git a/.cicd/Jenkinsfile b/.cicd/Jenkinsfile index 0730e16acd..ce6963b7d8 100644 --- a/.cicd/Jenkinsfile +++ b/.cicd/Jenkinsfile @@ -10,11 +10,11 @@ pipeline { parameters { // Allow job runner to filter based on platform // Use the line below to enable all PW clusters - // choice(name: 'SRW_PLATFORM_FILTER', choices: ['all', 'cheyenne', 'gaea', 'hera', 'jet-epic', 'orion', 'pclusternoaav2use1', 'azclusternoaav2eus1', 'gclusternoaav2usc1'], description: 'Specify the platform(s) to use') + // choice(name: 'SRW_PLATFORM_FILTER', choices: ['all', 'cheyenne', 'gaea', 'hera', 'jet', 'orion', 'pclusternoaav2use1', 'azclusternoaav2eus1', 'gclusternoaav2usc1'], description: 'Specify the platform(s) to use') // Use the line below to enable the PW AWS cluster - // choice(name: 'SRW_PLATFORM_FILTER', choices: ['all', 'cheyenne', 'gaea', 'hera', 'jet-epic', 'orion', 'pclusternoaav2use1'], description: 'Specify the platform(s) to use') - // choice(name: 'SRW_PLATFORM_FILTER', choices: ['all', 'cheyenne', 'gaea', 'hera', 'jet-epic', 'orion'], description: 'Specify the platform(s) to use') - choice(name: 'SRW_PLATFORM_FILTER', choices: ['all', 'gaea', 'hera', 'jet-epic', 'orion'], description: 'Specify the platform(s) to use') + // choice(name: 'SRW_PLATFORM_FILTER', choices: ['all', 'cheyenne', 'gaea', 'hera', 'jet', 'orion', 'pclusternoaav2use1'], description: 'Specify the platform(s) to use') + // choice(name: 'SRW_PLATFORM_FILTER', choices: ['all', 'cheyenne', 'gaea', 'hera', 'jet', 'orion'], description: 'Specify the platform(s) to use') + choice(name: 'SRW_PLATFORM_FILTER', choices: ['all', 'gaea', 'hera', 'jet', 'orion'], description: 'Specify the platform(s) to use') // Allow job runner to filter based on compiler choice(name: 'SRW_COMPILER_FILTER', choices: ['all', 'gnu', 'intel'], description: 'Specify the compiler(s) to use to build') // Uncomment the following line to re-enable comprehensive tests @@ -77,8 +77,8 @@ pipeline { axes { axis { name 'SRW_PLATFORM' - // values 'cheyenne', 'gaea', 'hera', 'jet-epic', 'orion' //, 'pclusternoaav2use1', 'azclusternoaav2eus1', 'gclusternoaav2usc1' - values 'gaea', 'hera', 'jet-epic', 'orion' //, 'pclusternoaav2use1', 'azclusternoaav2eus1', 'gclusternoaav2usc1' + // values 'cheyenne', 'gaea', 'hera', 'jet', 'orion' //, 'pclusternoaav2use1', 'azclusternoaav2eus1', 'gclusternoaav2usc1' + values 'gaea', 'hera', 'jet', 'orion' //, 'pclusternoaav2use1', 'azclusternoaav2eus1', 'gclusternoaav2usc1' } axis { @@ -92,7 +92,7 @@ pipeline { exclude { axis { name 'SRW_PLATFORM' - values 'gaea', 'jet-epic', 'orion' //, 'pclusternoaav2use1' , 'azclusternoaav2eus1', 'gclusternoaav2usc1' + values 'gaea', 'jet', 'orion' //, 'pclusternoaav2use1' , 'azclusternoaav2eus1', 'gclusternoaav2usc1' } axis { diff --git a/tests/WE2E/machine_suites/comprehensive b/tests/WE2E/machine_suites/comprehensive index 3a4e986e4e..5de86df41d 100644 --- a/tests/WE2E/machine_suites/comprehensive +++ b/tests/WE2E/machine_suites/comprehensive @@ -1,7 +1,12 @@ 2020_CAD community custom_ESGgrid +custom_ESGgrid_Central_Asia_3km custom_ESGgrid_Great_Lakes_snow_8km +custom_ESGgrid_IndianOcean_6km +custom_ESGgrid_NewZealand_3km +custom_ESGgrid_Peru_12km +custom_ESGgrid_SF_1p1km custom_GFDLgrid__GFDLgrid_USE_NUM_CELLS_IN_FILENAMES_eq_FALSE custom_GFDLgrid deactivate_tasks @@ -54,6 +59,7 @@ grid_SUBCONUS_Ind_3km_ics_HRRR_lbcs_RAP_suite_WoFS_v0 grid_SUBCONUS_Ind_3km_ics_NAM_lbcs_NAM_suite_GFS_v16 grid_SUBCONUS_Ind_3km_ics_RAP_lbcs_RAP_suite_RRFS_v1beta_plot GST_release_public_v1 +long_fcst MET_ensemble_verification_only_vx MET_ensemble_verification_only_vx_time_lag MET_verification_only_vx @@ -64,6 +70,5 @@ nco_grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_timeoffset_suite_GFS_v16 nco_grid_RRFS_CONUS_3km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v15_thompson_mynn_lam3km nco_grid_RRFS_CONUScompact_25km_ics_HRRR_lbcs_RAP_suite_HRRR pregen_grid_orog_sfc_climo -quilting_false specify_EXTRN_MDL_SYSBASEDIR_ICS_LBCS specify_template_filenames diff --git a/tests/WE2E/machine_suites/comprehensive.cheyenne b/tests/WE2E/machine_suites/comprehensive.cheyenne index 239ad2a1f4..5d374b61b3 100644 --- a/tests/WE2E/machine_suites/comprehensive.cheyenne +++ b/tests/WE2E/machine_suites/comprehensive.cheyenne @@ -1,5 +1,10 @@ community custom_ESGgrid +custom_ESGgrid_Central_Asia_3km +custom_ESGgrid_IndianOcean_6km +custom_ESGgrid_NewZealand_3km +custom_ESGgrid_Peru_12km +custom_ESGgrid_SF_1p1km custom_GFDLgrid__GFDLgrid_USE_NUM_CELLS_IN_FILENAMES_eq_FALSE custom_GFDLgrid deactivate_tasks diff --git a/tests/WE2E/machine_suites/comprehensive.gaea b/tests/WE2E/machine_suites/comprehensive.gaea new file mode 120000 index 0000000000..18a56d9739 --- /dev/null +++ b/tests/WE2E/machine_suites/comprehensive.gaea @@ -0,0 +1 @@ +comprehensive.orion \ No newline at end of file diff --git a/tests/WE2E/machine_suites/comprehensive.orion b/tests/WE2E/machine_suites/comprehensive.orion index 952a7de642..7c7e42b30b 100644 --- a/tests/WE2E/machine_suites/comprehensive.orion +++ b/tests/WE2E/machine_suites/comprehensive.orion @@ -1,6 +1,11 @@ 2020_CAD community custom_ESGgrid +custom_ESGgrid_Central_Asia_3km +custom_ESGgrid_IndianOcean_6km +custom_ESGgrid_NewZealand_3km +custom_ESGgrid_Peru_12km +custom_ESGgrid_SF_1p1km custom_GFDLgrid__GFDLgrid_USE_NUM_CELLS_IN_FILENAMES_eq_FALSE custom_GFDLgrid deactivate_tasks diff --git a/tests/WE2E/machine_suites/coverage.cheyenne b/tests/WE2E/machine_suites/coverage.cheyenne index 9c47da1030..19bbc623c7 100644 --- a/tests/WE2E/machine_suites/coverage.cheyenne +++ b/tests/WE2E/machine_suites/coverage.cheyenne @@ -1,9 +1,9 @@ -custom_GFDLgrid__GFDLgrid_USE_NUM_CELLS_IN_FILENAMES_eq_FALSE +custom_ESGgrid_IndianOcean_6km grid_RRFS_CONUS_13km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16_plot grid_RRFS_CONUS_25km_ics_NAM_lbcs_NAM_suite_GFS_v16 grid_RRFS_CONUScompact_13km_ics_HRRR_lbcs_RAP_suite_HRRR grid_RRFS_CONUScompact_25km_ics_HRRR_lbcs_RAP_suite_RRFS_v1beta grid_SUBCONUS_Ind_3km_ics_HRRR_lbcs_HRRR_suite_HRRR -#nco_grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_timeoffset_suite_GFS_v16 +nco_grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_timeoffset_suite_GFS_v16 pregen_grid_orog_sfc_climo specify_template_filenames diff --git a/tests/WE2E/machine_suites/coverage.cheyenne.gnu b/tests/WE2E/machine_suites/coverage.cheyenne.gnu index 4ef642acb1..273de3108e 100644 --- a/tests/WE2E/machine_suites/coverage.cheyenne.gnu +++ b/tests/WE2E/machine_suites/coverage.cheyenne.gnu @@ -1,3 +1,4 @@ +custom_GFDLgrid__GFDLgrid_USE_NUM_CELLS_IN_FILENAMES_eq_FALSE grid_CONUS_25km_GFDLgrid_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16 grid_RRFS_CONUS_13km_ics_FV3GFS_lbcs_FV3GFS_suite_RRFS_v1beta grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v17_p8_plot diff --git a/tests/WE2E/machine_suites/coverage.gaea b/tests/WE2E/machine_suites/coverage.gaea index 25194b2c7d..4ff7f61f3c 100644 --- a/tests/WE2E/machine_suites/coverage.gaea +++ b/tests/WE2E/machine_suites/coverage.gaea @@ -1,4 +1,5 @@ community +custom_ESGgrid_NewZealand_3km grid_RRFS_CONUScompact_13km_ics_HRRR_lbcs_RAP_suite_RRFS_v1beta grid_RRFS_CONUS_13km_ics_FV3GFS_lbcs_FV3GFS_suite_RAP grid_RRFS_CONUS_13km_ics_FV3GFS_lbcs_FV3GFS_suite_HRRR diff --git a/tests/WE2E/machine_suites/coverage.hera.gnu.com b/tests/WE2E/machine_suites/coverage.hera.gnu.com index 02fc58db18..0c701f35bd 100644 --- a/tests/WE2E/machine_suites/coverage.hera.gnu.com +++ b/tests/WE2E/machine_suites/coverage.hera.gnu.com @@ -1,10 +1,11 @@ +custom_ESGgrid_Peru_12km get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio_2019061200 get_from_NOMADS_ics_FV3GFS_lbcs_FV3GFS grid_RRFS_CONUS_13km_ics_FV3GFS_lbcs_FV3GFS_suite_HRRR grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_RRFS_v1beta -quilting_false grid_SUBCONUS_Ind_3km_ics_HRRR_lbcs_RAP_suite_WoFS_v0 GST_release_public_v1 +long_fcst MET_verification_only_vx -#MET_ensemble_verification_only_vx_time_lag Removed temporarily due to HPSS permissions issue +MET_ensemble_verification_only_vx_time_lag nco_grid_RRFS_CONUS_13km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16 diff --git a/tests/WE2E/machine_suites/coverage.hera.intel.nco b/tests/WE2E/machine_suites/coverage.hera.intel.nco index f30f1a51b1..655bec70e3 100644 --- a/tests/WE2E/machine_suites/coverage.hera.intel.nco +++ b/tests/WE2E/machine_suites/coverage.hera.intel.nco @@ -1,3 +1,4 @@ +custom_ESGgrid_Central_Asia_3km get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_grib2_2019061200 get_from_HPSS_ics_GDAS_lbcs_GDAS_fmt_netcdf_2022040400_ensemble_2mems get_from_HPSS_ics_HRRR_lbcs_RAP diff --git a/tests/WE2E/machine_suites/coverage.jet b/tests/WE2E/machine_suites/coverage.jet index 05e7cf8452..aef32252f2 100644 --- a/tests/WE2E/machine_suites/coverage.jet +++ b/tests/WE2E/machine_suites/coverage.jet @@ -1,6 +1,6 @@ community custom_ESGgrid -#custom_ESGgrid_Great_Lakes_snow_8km Removed temporarily due to HPSS permissions issue +custom_ESGgrid_Great_Lakes_snow_8km custom_GFDLgrid get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio_2021032018 get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_netcdf_2022060112_48h diff --git a/tests/WE2E/machine_suites/coverage.orion b/tests/WE2E/machine_suites/coverage.orion index 89d47fbbea..dd13f27318 100644 --- a/tests/WE2E/machine_suites/coverage.orion +++ b/tests/WE2E/machine_suites/coverage.orion @@ -1,3 +1,4 @@ +custom_ESGgrid_SF_1p1km deactivate_tasks get_from_AWS_ics_GEFS_lbcs_GEFS_fmt_grib2_2022040400_ensemble_2mems grid_CONUS_3km_GFDLgrid_ics_FV3GFS_lbcs_FV3GFS_suite_RRFS_v1beta diff --git a/tests/WE2E/monitor_jobs.py b/tests/WE2E/monitor_jobs.py index 1a19951936..b870cd4654 100755 --- a/tests/WE2E/monitor_jobs.py +++ b/tests/WE2E/monitor_jobs.py @@ -16,20 +16,23 @@ from utils import calculate_core_hours, write_monitor_file, update_expt_status,\ update_expt_status_parallel, print_WE2E_summary -def monitor_jobs(expts_dict: dict, monitor_file: str = '', procs: int = 1, debug: bool = False) -> str: +def monitor_jobs(expts_dict: dict, monitor_file: str = '', procs: int = 1, + mode: str = 'continuous', debug: bool = False) -> str: """Function to monitor and run jobs for the specified experiment using Rocoto Args: expts_dict (dict): A dictionary containing the information needed to run one or more experiments. See example file monitor_jobs.yaml monitor_file (str): [optional] + mode (str): [optional] Mode of job monitoring + continuous (default): monitor jobs continuously until complete + advance: increment jobs once, then quit debug (bool): [optional] Enable extra output for debugging Returns: - str: The name of the file used for job monitoring (when script is finished, this + str: The name of the file used for job monitoring (when script is finished, this contains results/summary) """ - monitor_start = datetime.now() # Write monitor_file, which will contain information on each monitored experiment monitor_start_string = monitor_start.strftime("%Y%m%d%H%M%S") @@ -52,6 +55,12 @@ def monitor_jobs(expts_dict: dict, monitor_file: str = '', procs: int = 1, debug write_monitor_file(monitor_file,expts_dict) + if mode != 'continuous': + logging.debug("All experiments have been updated") + return monitor_file + else: + logging.debug("Continuous mode: will monitor jobs until all are complete") + logging.info(f'Setup complete; monitoring {len(expts_dict)} experiments') logging.info('Use ctrl-c to pause job submission/monitoring') @@ -102,7 +111,8 @@ def monitor_jobs(expts_dict: dict, monitor_file: str = '', procs: int = 1, debug endtime = datetime.now() total_walltime = endtime - monitor_start - logging.debug(f"Finished loop {i}\nWalltime so far is {str(total_walltime)}") + logging.debug(f"Finished loop {i}") + logging.debug(f"Walltime so far is {str(total_walltime)}") #Slow things down just a tad between loops so experiments behave better time.sleep(5) @@ -160,6 +170,11 @@ def setup_logging(logfile: str = "log.run_WE2E_tests", debug: bool = False) -> N parser.add_argument('-p', '--procs', type=int, help='Run resource-heavy tasks (such as calls to rocotorun) in parallel, '\ 'with provided number of parallel tasks', default=1) + parser.add_argument('-m', '--mode', type=str, default='continuous', + choices=['continuous','advance'], + help='continuous: script will run continuously until all experiments are'\ + 'finished.'\ + 'advance: will only advance each experiment one step') parser.add_argument('-d', '--debug', action='store_true', help='Script will be run in debug mode with more verbose output') @@ -175,7 +190,8 @@ def setup_logging(logfile: str = "log.run_WE2E_tests", debug: bool = False) -> N #Call main function try: - monitor_jobs(expts_dict,args.yaml_file,args.procs,args.debug) + monitor_jobs(expts_dict=expts_dict,monitor_file=args.yaml_file,procs=args.procs, + mode=args.mode,debug=args.debug) except KeyboardInterrupt: logging.info("\n\nUser interrupted monitor script; to resume monitoring jobs run:\n") logging.info(f"{__file__} -y={args.yaml_file} -p={args.procs}\n") diff --git a/tests/WE2E/run_WE2E_tests.py b/tests/WE2E/run_WE2E_tests.py index 8a4c913219..e0719a1325 100755 --- a/tests/WE2E/run_WE2E_tests.py +++ b/tests/WE2E/run_WE2E_tests.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 - +# pylint: disable=logging-fstring-interpolation import os import sys import glob @@ -47,6 +47,8 @@ def run_we2e_tests(homedir, args) -> None: if run_envir not in ['nco', 'community']: raise KeyError(f"Invalid 'run_envir' provided: {run_envir}") + alltests = glob.glob('test_configs/**/config*.yaml', recursive=True) + testdirs = next(os.walk('test_configs'))[1] # If args.tests is a list of length more than one, we assume it is a list of test names if len(args.tests) > 1: tests_to_check=args.tests @@ -62,13 +64,18 @@ def run_we2e_tests(homedir, args) -> None: # If not a valid test name, check if it is a test suite logging.debug(f'Checking if {user_spec_tests} is a valid test suite') if user_spec_tests[0] == 'all': - alltests = glob.glob('test_configs/**/config*.yaml', recursive=True) tests_to_check = [] for f in alltests: filename = os.path.basename(f) # We just want the test name in this list, so cut out the # "config." prefix and ".yaml" extension - tests_to_check.append(filename[7:-5]) + if len(filename) > 12: + if filename[:7] == "config." and filename[-5:] == ".yaml": + tests_to_check.append(filename[7:-5]) + else: + logging.debug(f"Skipping non-test file {filename}") + else: + logging.debug(f"Skipping non-test file {filename}") logging.debug(f"Will check all tests:\n{tests_to_check}") elif user_spec_tests[0] in ['fundamental', 'comprehensive', 'coverage']: # I am writing this section of code under protest; we should use args.run_envir to @@ -99,6 +106,23 @@ def run_we2e_tests(homedir, args) -> None: with open(testfilename, encoding="utf-8") as f: tests_to_check = [x.rstrip() for x in f] logging.debug(f"Will check {user_spec_tests[0]} tests:\n{tests_to_check}") + elif user_spec_tests[0] in testdirs: + # If a subdirectory under test_configs/ is specified, run all tests in that directory + logging.debug(f"{user_spec_tests[0]} is one of the testing directories:\n{testdirs}") + logging.debug(f"Will run all tests in test_configs/{user_spec_tests[0]}") + tests_in_dir = glob.glob(f'test_configs/{user_spec_tests[0]}/config*.yaml', recursive=True) + tests_to_check = [] + for f in tests_in_dir: + filename = os.path.basename(f) + # We just want the test name in this list, so cut out the + # "config." prefix and ".yaml" extension + if len(filename) > 12: + if filename[:7] == "config." and filename[-5:] == ".yaml": + tests_to_check.append(filename[7:-5]) + else: + logging.debug(f"Skipping non-test file {filename}") + else: + logging.debug(f"Skipping non-test file {filename}") else: # If we have gotten this far then the only option left for user_spec_tests is a # file containing test names @@ -109,8 +133,8 @@ def run_we2e_tests(homedir, args) -> None: else: raise FileNotFoundError(dedent(f""" The specified 'tests' argument '{user_spec_tests}' - does not appear to be a valid test name, a valid test suite, or a file - containing valid test names. + does not appear to be a valid test name, a valid test suite, a subdirectory + under test_configs/, or a file containing valid test names. Check your inputs and try again. """)) @@ -133,7 +157,7 @@ def run_we2e_tests(homedir, args) -> None: machine_defaults = load_config_file(machine_file) # Set up dictionary for job monitoring yaml - if not args.use_cron_to_relaunch: + if args.launch != "cron": monitor_yaml = dict() for test in tests_to_run: @@ -169,8 +193,8 @@ def run_we2e_tests(homedir, args) -> None: test_cfg['workflow'].update({"EXPT_SUBDIR": test_name}) if args.exec_subdir: test_cfg['workflow'].update({"EXEC_SUBDIR": args.exec_subdir}) - if args.use_cron_to_relaunch: - test_cfg['workflow'].update({"USE_CRON_TO_RELAUNCH": args.use_cron_to_relaunch}) + if args.launch == "cron": + test_cfg['workflow'].update({"USE_CRON_TO_RELAUNCH": True}) if args.cron_relaunch_intvl_mnts: test_cfg['workflow'].update({"CRON_RELAUNCH_INTVL_MNTS": args.cron_relaunch_intvl_mnts}) if args.debug_tests: @@ -232,25 +256,28 @@ def run_we2e_tests(homedir, args) -> None: monitor_yaml[test_name].update({"status": "CREATED"}) monitor_yaml[test_name].update({"start_time": starttime_string}) - if not args.use_cron_to_relaunch: - logging.info("calling function that monitors jobs, prints summary") + if args.launch != "cron": monitor_file = f'WE2E_tests_{starttime_string}.yaml' write_monitor_file(monitor_file,monitor_yaml) - try: - monitor_file = monitor_jobs(monitor_yaml, monitor_file=monitor_file, procs=args.procs, - debug=args.debug) - except KeyboardInterrupt: - logging.info("\n\nUser interrupted monitor script; to resume monitoring jobs run:\n") - logging.info(f"./monitor_jobs.py -y={monitor_file} -p={args.procs}\n") + logging.info("All experiments have been generated;") + logging.info(f"Experiment file {monitor_file} created") + if args.launch == "python": + write_monitor_file(monitor_file,monitor_yaml) + logging.debug("calling function that monitors jobs, prints summary") + try: + monitor_file = monitor_jobs(monitor_yaml, monitor_file=monitor_file, procs=args.procs, + debug=args.debug) + except KeyboardInterrupt: + logging.info("\n\nUser interrupted monitor script; to resume monitoring jobs run:\n") + logging.info(f"./monitor_jobs.py -y={monitor_file} -p={args.procs}\n") else: - logging.info("All experiments are complete") - logging.info(f"Summary of results available in {monitor_file}") + logging.info("To automatically run and monitor experiments, use:\n") + logging.info(f"./monitor_jobs.py -y={monitor_file}\n") else: logging.info("All experiments have been generated; using cron to submit workflows") logging.info("To view running experiments in cron try `crontab -l`") - def check_tests(tests: list) -> list: """ Function for checking that all tests in a provided list of tests are valid @@ -443,14 +470,14 @@ def setup_logging(logfile: str = "log.run_WE2E_tests", debug: bool = False) -> N #Get the "Home" directory, two levels above this one homedir=os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) - logfile='log.run_WE2E_tests' + LOGFILE='log.run_WE2E_tests' #Parse arguments - parser = argparse.ArgumentParser(epilog="For more information about config arguments (denoted "\ + ap = argparse.ArgumentParser(epilog="For more information about config arguments (denoted "\ "in CAPS), see ush/config_defaults.yaml\n") # Create a group for optional arguments so they can be listed after required args - optional = parser._action_groups.pop() - required = parser.add_argument_group('required arguments') + optional = ap._action_groups.pop() + required = ap.add_argument_group('required arguments') required.add_argument('-m', '--machine', type=str, help='Machine name; see ush/machine/ for valid values', required=True) @@ -463,44 +490,55 @@ def setup_logging(logfile: str = "log.run_WE2E_tests", debug: bool = False) -> N 3. The name of a file (full or relative path) containing a list of test names. """, required=True) - parser.add_argument('-c', '--compiler', type=str, - help='Compiler used for building the app', default='intel') - parser.add_argument('-d', '--debug', action='store_true', - help='Script will be run in debug mode with more verbose output') - parser.add_argument('-q', '--quiet', action='store_true', - help='Suppress console output from workflow generation; this will help '\ - 'keep the screen uncluttered') - parser.add_argument('-p', '--procs', type=int, - help='Run resource-heavy tasks (such as calls to rocotorun) in parallel, '\ - 'with provided number of parallel tasks', default=1) - - parser.add_argument('--modulefile', type=str, help='Modulefile used for building the app') - parser.add_argument('--run_envir', type=str, - help='Overrides RUN_ENVIR variable to a new value ("nco" or "community") '\ - 'for all experiments', default='') - parser.add_argument('--expt_basedir', type=str, - help='Explicitly set EXPT_BASEDIR for all experiments') - parser.add_argument('--exec_subdir', type=str, - help='Explicitly set EXEC_SUBDIR for all experiments') - parser.add_argument('--use_cron_to_relaunch', action='store_true', - help='Explicitly set USE_CRON_TO_RELAUNCH for all experiments; this '\ - 'option disables the "monitor" script functionality') - parser.add_argument('--cron_relaunch_intvl_mnts', type=int, - help='Overrides CRON_RELAUNCH_INTVL_MNTS for all experiments') - parser.add_argument('--opsroot', type=str, - help='If test is for NCO mode, sets OPSROOT (see config_defaults.yaml for '\ - 'more details on this variable)') - parser.add_argument('--print_test_info', action='store_true', - help='Create a "WE2E_test_info.txt" file summarizing each test prior to'\ - 'starting experiment') - parser.add_argument('--debug_tests', action='store_true', - help='Explicitly set DEBUG=TRUE for all experiments') - parser.add_argument('--verbose_tests', action='store_true', - help='Explicitly set VERBOSE=TRUE for all experiments') - - parser._action_groups.append(optional) - - args = parser.parse_args() + ap.add_argument('-c', '--compiler', type=str, + help='Compiler used for building the app', default='intel') + ap.add_argument('-d', '--debug', action='store_true', + help='Script will be run in debug mode with more verbose output') + ap.add_argument('-q', '--quiet', action='store_true', + help='Suppress console output from workflow generation; this will help '\ + 'keep the screen uncluttered') + ap.add_argument('-p', '--procs', type=int, + help='Run resource-heavy tasks (such as calls to rocotorun) in parallel, '\ + 'with provided number of parallel tasks', default=1) + ap.add_argument('-l', '--launch', type=str, choices=['python', 'cron', 'none'], + help='Method for launching jobs. Valid values are:\n'\ + ' python: [default] Monitor and launch experiments using monitor_jobs.py\n' + ' cron: Launch expts using ush/launch_FV3LAM_wflow.sh from crontab\n'\ + ' none: Do not launch experiments; only create experiment directories', + default="python") + + + ap.add_argument('--modulefile', type=str, help='Modulefile used for building the app') + ap.add_argument('--run_envir', type=str, + help='Overrides RUN_ENVIR variable to a new value ("nco" or "community") '\ + 'for all experiments', default='') + ap.add_argument('--expt_basedir', type=str, + help='Explicitly set EXPT_BASEDIR for all experiments') + ap.add_argument('--exec_subdir', type=str, + help='Explicitly set EXEC_SUBDIR for all experiments') + ap.add_argument('--use_cron_to_relaunch', action='store_true', + help='DEPRECATED; DO NOT USE. See "launch" option.') + ap.add_argument('--cron_relaunch_intvl_mnts', type=int, + help='Overrides CRON_RELAUNCH_INTVL_MNTS for all experiments') + ap.add_argument('--opsroot', type=str, + help='If test is for NCO mode, sets OPSROOT_default (see config_defaults.yaml'\ + 'for more details on this variable)') + ap.add_argument('--print_test_info', action='store_true', + help='Create a "WE2E_test_info.txt" file summarizing each test prior to'\ + 'starting experiment') + ap.add_argument('--debug_tests', action='store_true', + help='Explicitly set DEBUG=TRUE for all experiments') + ap.add_argument('--verbose_tests', action='store_true', + help='Explicitly set VERBOSE=TRUE for all experiments') + + ap._action_groups.append(optional) + + args = ap.parse_args() + + # Exit for deprecated options + if args.use_cron_to_relaunch: + raise ValueError("\nWARNING: The argument --use_cron_to_relaunch has been superseded by "\ + "--launch=cron\nPlease update your workflow accordingly") #Set defaults that need other argument values if args.modulefile is None: @@ -526,7 +564,7 @@ def setup_logging(logfile: str = "log.run_WE2E_tests", debug: bool = False) -> N FATAL ERROR: Experiment generation failed. See the error message(s) printed below. For more detailed information, check the log file from the workflow - generation script: {logfile} + generation script: {LOGFILE} *********************************************************************\n """ ) diff --git a/tests/WE2E/setup_WE2E_tests.sh b/tests/WE2E/setup_WE2E_tests.sh index 682334952e..9b9b9eea65 100755 --- a/tests/WE2E/setup_WE2E_tests.sh +++ b/tests/WE2E/setup_WE2E_tests.sh @@ -66,9 +66,6 @@ fi if [[ "$*" != *"verbose"* ]]; then opts="${opts} --verbose" fi -if [[ "$*" != *"cron_relaunch_intvl_mnts"* ]]; then - opts="${opts} --cron_relaunch_intvl_mnts=4" -fi if [[ "$*" != *"exec_subdir"* ]]; then opts="${opts} --exec_subdir=install_${compiler}/exec" fi diff --git a/tests/WE2E/test_configs/wflow_features/config.custom_ESGgrid.yaml b/tests/WE2E/test_configs/custom_grids/config.custom_ESGgrid.yaml similarity index 100% rename from tests/WE2E/test_configs/wflow_features/config.custom_ESGgrid.yaml rename to tests/WE2E/test_configs/custom_grids/config.custom_ESGgrid.yaml diff --git a/tests/WE2E/test_configs/custom_grids/config.custom_ESGgrid_Central_Asia_3km.yaml b/tests/WE2E/test_configs/custom_grids/config.custom_ESGgrid_Central_Asia_3km.yaml new file mode 100644 index 0000000000..c6b035ad54 --- /dev/null +++ b/tests/WE2E/test_configs/custom_grids/config.custom_ESGgrid_Central_Asia_3km.yaml @@ -0,0 +1,57 @@ +metadata: + description: |- + This test checks the capability of the workflow to have the user + specify a new grid (as opposed to one of the predefined ones in the + workflow) of ESGgrid type. +user: + RUN_ENVIR: community +workflow: + CCPP_PHYS_SUITE: FV3_GFS_v15_thompson_mynn_lam3km + GRID_GEN_METHOD: ESGgrid + DATE_FIRST_CYCL: '2019070100' + DATE_LAST_CYCL: '2019070100' + FCST_LEN_HRS: 6 + PREEXISTING_DIR_METHOD: rename +task_make_grid: + ESGgrid_LON_CTR: 76.0 + ESGgrid_LAT_CTR: 37.0 + ESGgrid_DELX: 3000.0 + ESGgrid_DELY: 3000.0 + ESGgrid_NX: 420 + ESGgrid_NY: 300 + ESGgrid_WIDE_HALO_WIDTH: 6 + ESGgrid_PAZI: 0.0 +task_get_extrn_ics: + EXTRN_MDL_NAME_ICS: FV3GFS + USE_USER_STAGED_EXTRN_FILES: true +task_get_extrn_lbcs: + EXTRN_MDL_NAME_LBCS: FV3GFS + LBC_SPEC_INTVL_HRS: 3 + USE_USER_STAGED_EXTRN_FILES: true +task_run_fcst: + DT_ATMOS: 45 + LAYOUT_X: 12 + LAYOUT_Y: 12 + BLOCKSIZE: 32 + QUILTING: true + WRTCMP_write_groups: 1 + WRTCMP_write_tasks_per_group: '{{ LAYOUT_Y }}' + WRTCMP_output_grid: lambert_conformal + WRTCMP_cen_lon: '{{ task_make_grid.ESGgrid_LON_CTR }}' + WRTCMP_cen_lat: '{{ task_make_grid.ESGgrid_LAT_CTR }}' + WRTCMP_lon_lwr_left: 69.6 + WRTCMP_lat_lwr_left: 33.0 + WRTCMP_stdlat1: '{{ task_make_grid.ESGgrid_LAT_CTR }}' + WRTCMP_stdlat2: '{{ task_make_grid.ESGgrid_LAT_CTR }}' + WRTCMP_nx: 399 + WRTCMP_ny: 285 + WRTCMP_dx: '{{ task_make_grid.ESGgrid_DELX }}' + WRTCMP_dy: '{{ task_make_grid.ESGgrid_DELY }}' +task_run_post: + POST_OUTPUT_DOMAIN_NAME: custom_ESGgrid_central_asia +rocoto: + tasks: + metatask_run_ensemble: + task_run_fcst_mem#mem#: + walltime: 01:00:00 + diff --git a/tests/WE2E/test_configs/verification/config.custom_ESGgrid_Great_Lakes_snow_8km.yaml b/tests/WE2E/test_configs/custom_grids/config.custom_ESGgrid_Great_Lakes_snow_8km.yaml similarity index 89% rename from tests/WE2E/test_configs/verification/config.custom_ESGgrid_Great_Lakes_snow_8km.yaml rename to tests/WE2E/test_configs/custom_grids/config.custom_ESGgrid_Great_Lakes_snow_8km.yaml index 64d9e02d9e..b604cbc06d 100644 --- a/tests/WE2E/test_configs/verification/config.custom_ESGgrid_Great_Lakes_snow_8km.yaml +++ b/tests/WE2E/test_configs/custom_grids/config.custom_ESGgrid_Great_Lakes_snow_8km.yaml @@ -29,18 +29,14 @@ task_make_grid: ESGgrid_WIDE_HALO_WIDTH: 6 ESGgrid_PAZI: 0.0 task_get_extrn_ics: - EXTRN_MDL_NAME_ICS: FV3GFS - FV3GFS_FILE_FMT_ICS: netcdf - USE_USER_STAGED_EXTRN_FILES: true + EXTRN_MDL_NAME_ICS: RAP task_get_extrn_lbcs: - EXTRN_MDL_NAME_LBCS: FV3GFS - FV3GFS_FILE_FMT_LBCS: netcdf - LBC_SPEC_INTVL_HRS: 6 - USE_USER_STAGED_EXTRN_FILES: true + EXTRN_MDL_NAME_LBCS: RAP + LBC_SPEC_INTVL_HRS: 3 task_run_fcst: DT_ATMOS: 90 - LAYOUT_X: 12 - LAYOUT_Y: 12 + LAYOUT_X: 8 + LAYOUT_Y: 10 BLOCKSIZE: 32 QUILTING: true WRTCMP_write_groups: 1 diff --git a/tests/WE2E/test_configs/custom_grids/config.custom_ESGgrid_IndianOcean_6km.yaml b/tests/WE2E/test_configs/custom_grids/config.custom_ESGgrid_IndianOcean_6km.yaml new file mode 100644 index 0000000000..6407a6f3ff --- /dev/null +++ b/tests/WE2E/test_configs/custom_grids/config.custom_ESGgrid_IndianOcean_6km.yaml @@ -0,0 +1,58 @@ +metadata: + description: |- + This test checks the capability of the workflow to have the user + specify a new grid (as opposed to one of the predefined ones in the + workflow) of ESGgrid type. +user: + RUN_ENVIR: community +workflow: + CCPP_PHYS_SUITE: FV3_RRFS_v1beta + GRID_GEN_METHOD: ESGgrid + DATE_FIRST_CYCL: '2019061518' + DATE_LAST_CYCL: '2019061518' + FCST_LEN_HRS: 12 + PREEXISTING_DIR_METHOD: rename +task_make_grid: + ESGgrid_LON_CTR: 76.0 + ESGgrid_LAT_CTR: -37.0 + ESGgrid_DELX: 6000.0 + ESGgrid_DELY: 6000.0 + ESGgrid_NX: 210 + ESGgrid_NY: 150 + ESGgrid_WIDE_HALO_WIDTH: 6 + ESGgrid_PAZI: 0.0 +task_get_extrn_ics: + EXTRN_MDL_NAME_ICS: FV3GFS + FV3GFS_FILE_FMT_ICS: grib2 + USE_USER_STAGED_EXTRN_FILES: true +task_get_extrn_lbcs: + EXTRN_MDL_NAME_LBCS: FV3GFS + FV3GFS_FILE_FMT_LBCS: grib2 + LBC_SPEC_INTVL_HRS: 6 + USE_USER_STAGED_EXTRN_FILES: true +task_run_fcst: + DT_ATMOS: 60 + LAYOUT_X: 6 + LAYOUT_Y: 6 + BLOCKSIZE: 32 + QUILTING: true + WRTCMP_write_groups: 1 + WRTCMP_write_tasks_per_group: '{{ LAYOUT_Y }}' + WRTCMP_output_grid: lambert_conformal + WRTCMP_cen_lon: '{{ task_make_grid.ESGgrid_LON_CTR }}' + WRTCMP_cen_lat: '{{ task_make_grid.ESGgrid_LAT_CTR }}' + WRTCMP_lon_lwr_left: 68.6 + WRTCMP_lat_lwr_left: -40.6 + WRTCMP_stdlat1: '{{ task_make_grid.ESGgrid_LAT_CTR }}' + WRTCMP_stdlat2: '{{ task_make_grid.ESGgrid_LAT_CTR }}' + WRTCMP_nx: 205 + WRTCMP_ny: 145 + WRTCMP_dx: '{{ task_make_grid.ESGgrid_DELX }}' + WRTCMP_dy: '{{ task_make_grid.ESGgrid_DELY }}' +task_run_post: + POST_OUTPUT_DOMAIN_NAME: custom_ESGgrid_Indian_Ocean +rocoto: + tasks: + metatask_run_ensemble: + task_run_fcst_mem#mem#: + walltime: 01:00:00 diff --git a/tests/WE2E/test_configs/custom_grids/config.custom_ESGgrid_NewZealand_3km.yaml b/tests/WE2E/test_configs/custom_grids/config.custom_ESGgrid_NewZealand_3km.yaml new file mode 100644 index 0000000000..1b61355bc6 --- /dev/null +++ b/tests/WE2E/test_configs/custom_grids/config.custom_ESGgrid_NewZealand_3km.yaml @@ -0,0 +1,58 @@ +metadata: + description: |- + This test checks the capability of the workflow to have the user + specify a new grid (as opposed to one of the predefined ones in the + workflow) of ESGgrid type. +user: + RUN_ENVIR: community +workflow: + CCPP_PHYS_SUITE: FV3_HRRR + GRID_GEN_METHOD: ESGgrid + DATE_FIRST_CYCL: '2019061518' + DATE_LAST_CYCL: '2019061518' + FCST_LEN_HRS: 6 + PREEXISTING_DIR_METHOD: rename +task_make_grid: + ESGgrid_LON_CTR: 175.0 + ESGgrid_LAT_CTR: -41.0 + ESGgrid_DELX: 3000.0 + ESGgrid_DELY: 3000.0 + ESGgrid_NX: 608 + ESGgrid_NY: 504 + ESGgrid_WIDE_HALO_WIDTH: 6 + ESGgrid_PAZI: 0.0 +task_get_extrn_ics: + EXTRN_MDL_NAME_ICS: FV3GFS + FV3GFS_FILE_FMT_ICS: grib2 + USE_USER_STAGED_EXTRN_FILES: true +task_get_extrn_lbcs: + EXTRN_MDL_NAME_LBCS: FV3GFS + FV3GFS_FILE_FMT_LBCS: grib2 + LBC_SPEC_INTVL_HRS: 6 + USE_USER_STAGED_EXTRN_FILES: true +task_run_fcst: + DT_ATMOS: 40 + LAYOUT_X: 16 + LAYOUT_Y: 14 + BLOCKSIZE: 32 + QUILTING: true + WRTCMP_write_groups: 1 + WRTCMP_write_tasks_per_group: '{{ LAYOUT_Y }}' + WRTCMP_output_grid: lambert_conformal + WRTCMP_cen_lon: '{{ task_make_grid.ESGgrid_LON_CTR }}' + WRTCMP_cen_lat: '{{ task_make_grid.ESGgrid_LAT_CTR }}' + WRTCMP_lon_lwr_left: 163.5 + WRTCMP_lat_lwr_left: -47.0 + WRTCMP_stdlat1: '{{ task_make_grid.ESGgrid_LAT_CTR }}' + WRTCMP_stdlat2: '{{ task_make_grid.ESGgrid_LAT_CTR }}' + WRTCMP_nx: 595 + WRTCMP_ny: 495 + WRTCMP_dx: '{{ task_make_grid.ESGgrid_DELX }}' + WRTCMP_dy: '{{ task_make_grid.ESGgrid_DELY }}' +task_run_post: + POST_OUTPUT_DOMAIN_NAME: custom_ESGgrid_New_Zealand +rocoto: + tasks: + metatask_run_ensemble: + task_run_fcst_mem#mem#: + walltime: 01:00:00 diff --git a/tests/WE2E/test_configs/custom_grids/config.custom_ESGgrid_Peru_12km.yaml b/tests/WE2E/test_configs/custom_grids/config.custom_ESGgrid_Peru_12km.yaml new file mode 100644 index 0000000000..0ea69d5d99 --- /dev/null +++ b/tests/WE2E/test_configs/custom_grids/config.custom_ESGgrid_Peru_12km.yaml @@ -0,0 +1,59 @@ +metadata: + description: |- + This test checks the capability of the workflow to have the user + specify a new grid (as opposed to one of the predefined ones in the + workflow) of ESGgrid type. +user: + RUN_ENVIR: community +workflow: + CCPP_PHYS_SUITE: FV3_RAP + GRID_GEN_METHOD: ESGgrid + DATE_FIRST_CYCL: '2019061500' + DATE_LAST_CYCL: '2019061500' + FCST_LEN_HRS: 12 + PREEXISTING_DIR_METHOD: rename +task_make_grid: + ESGgrid_LON_CTR: -75.0 + ESGgrid_LAT_CTR: -12.5 + ESGgrid_DELX: 12000.0 + ESGgrid_DELY: 12000.0 + ESGgrid_NX: 240 + ESGgrid_NY: 240 + ESGgrid_WIDE_HALO_WIDTH: 6 + ESGgrid_PAZI: 0.0 +task_get_extrn_ics: + EXTRN_MDL_NAME_ICS: FV3GFS + FV3GFS_FILE_FMT_ICS: grib2 + USE_USER_STAGED_EXTRN_FILES: true +task_get_extrn_lbcs: + EXTRN_MDL_NAME_LBCS: FV3GFS + FV3GFS_FILE_FMT_LBCS: grib2 + LBC_SPEC_INTVL_HRS: 3 + USE_USER_STAGED_EXTRN_FILES: true +task_run_fcst: + DT_ATMOS: 90 + LAYOUT_X: 8 + LAYOUT_Y: 8 + BLOCKSIZE: 32 + QUILTING: true + WRTCMP_write_groups: 1 + WRTCMP_write_tasks_per_group: '{{ LAYOUT_Y }}' + WRTCMP_output_grid: lambert_conformal + WRTCMP_cen_lon: '{{ task_make_grid.ESGgrid_LON_CTR }}' + WRTCMP_cen_lat: '{{ task_make_grid.ESGgrid_LAT_CTR }}' + WRTCMP_lon_lwr_left: -88.1 + WRTCMP_lat_lwr_left: -24.6 + WRTCMP_stdlat1: '{{ task_make_grid.ESGgrid_LAT_CTR }}' + WRTCMP_stdlat2: '{{ task_make_grid.ESGgrid_LAT_CTR }}' + WRTCMP_nx: 235 + WRTCMP_ny: 235 + WRTCMP_dx: '{{ task_make_grid.ESGgrid_DELX }}' + WRTCMP_dy: '{{ task_make_grid.ESGgrid_DELY }}' +task_run_post: + POST_OUTPUT_DOMAIN_NAME: custom_ESGgrid_Peru +rocoto: + tasks: + metatask_run_ensemble: + task_run_fcst_mem#mem#: + walltime: 01:00:00 + diff --git a/tests/WE2E/test_configs/custom_grids/config.custom_ESGgrid_SF_1p1km.yaml b/tests/WE2E/test_configs/custom_grids/config.custom_ESGgrid_SF_1p1km.yaml new file mode 100644 index 0000000000..fe58303a19 --- /dev/null +++ b/tests/WE2E/test_configs/custom_grids/config.custom_ESGgrid_SF_1p1km.yaml @@ -0,0 +1,61 @@ +metadata: + description: |- + This test checks the capability of the workflow to have the user + specify a new grid (as opposed to one of the predefined ones in the + workflow) of ESGgrid type. +user: + RUN_ENVIR: community +workflow: + CCPP_PHYS_SUITE: FV3_WoFS_v0 + GRID_GEN_METHOD: ESGgrid + DATE_FIRST_CYCL: '2019061500' + DATE_LAST_CYCL: '2019061500' + FCST_LEN_HRS: 6 + PREEXISTING_DIR_METHOD: rename +task_make_grid: + ESGgrid_LON_CTR: -122.2 + ESGgrid_LAT_CTR: 37.9 + ESGgrid_DELX: 1100.0 + ESGgrid_DELY: 1100.0 + ESGgrid_NX: 600 + ESGgrid_NY: 576 + ESGgrid_WIDE_HALO_WIDTH: 6 + ESGgrid_PAZI: 0.0 +task_get_extrn_ics: + EXTRN_MDL_NAME_ICS: FV3GFS + FV3GFS_FILE_FMT_ICS: grib2 + USE_USER_STAGED_EXTRN_FILES: true +task_get_extrn_lbcs: + EXTRN_MDL_NAME_LBCS: FV3GFS + FV3GFS_FILE_FMT_LBCS: grib2 + LBC_SPEC_INTVL_HRS: 3 + USE_USER_STAGED_EXTRN_FILES: true +task_run_fcst: + DT_ATMOS: 15 + LAYOUT_X: 24 + LAYOUT_Y: 24 + BLOCKSIZE: 35 + QUILTING: true + WRTCMP_write_groups: 1 + WRTCMP_write_tasks_per_group: '{{ LAYOUT_Y }}' + WRTCMP_output_grid: lambert_conformal + WRTCMP_cen_lon: '{{ task_make_grid.ESGgrid_LON_CTR }}' + WRTCMP_cen_lat: '{{ task_make_grid.ESGgrid_LAT_CTR }}' + WRTCMP_lon_lwr_left: -125.79 + WRTCMP_lat_lwr_left: 35.1 + WRTCMP_stdlat1: '{{ task_make_grid.ESGgrid_LAT_CTR }}' + WRTCMP_stdlat2: '{{ task_make_grid.ESGgrid_LAT_CTR }}' + WRTCMP_nx: 597 + WRTCMP_ny: 557 + WRTCMP_dx: '{{ task_make_grid.ESGgrid_DELX }}' + WRTCMP_dy: '{{ task_make_grid.ESGgrid_DELY }}' +task_run_post: + POST_OUTPUT_DOMAIN_NAME: custom_ESGgrid_SF_Bay_Area +rocoto: + tasks: + metatask_run_ensemble: + task_run_fcst_mem#mem#: + walltime: 01:00:00 + task_make_ics_mem#mem#: + nnodes: 16 + ppn: 12 diff --git a/tests/WE2E/test_configs/wflow_features/config.custom_GFDLgrid.yaml b/tests/WE2E/test_configs/custom_grids/config.custom_GFDLgrid.yaml similarity index 100% rename from tests/WE2E/test_configs/wflow_features/config.custom_GFDLgrid.yaml rename to tests/WE2E/test_configs/custom_grids/config.custom_GFDLgrid.yaml diff --git a/tests/WE2E/test_configs/wflow_features/config.custom_GFDLgrid__GFDLgrid_USE_NUM_CELLS_IN_FILENAMES_eq_FALSE.yaml b/tests/WE2E/test_configs/custom_grids/config.custom_GFDLgrid__GFDLgrid_USE_NUM_CELLS_IN_FILENAMES_eq_FALSE.yaml similarity index 100% rename from tests/WE2E/test_configs/wflow_features/config.custom_GFDLgrid__GFDLgrid_USE_NUM_CELLS_IN_FILENAMES_eq_FALSE.yaml rename to tests/WE2E/test_configs/custom_grids/config.custom_GFDLgrid__GFDLgrid_USE_NUM_CELLS_IN_FILENAMES_eq_FALSE.yaml diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_13km_ics_FV3GFS_lbcs_FV3GFS_suite_RAP.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_13km_ics_FV3GFS_lbcs_FV3GFS_suite_RAP.yaml index 5a01ff753a..748fa9546b 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_13km_ics_FV3GFS_lbcs_FV3GFS_suite_RAP.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_13km_ics_FV3GFS_lbcs_FV3GFS_suite_RAP.yaml @@ -3,6 +3,7 @@ metadata: This test is to ensure that the workflow running in community mode completes successfully on the RRFS_CONUS_13km grid using the GFS_v15p2 physics suite with ICs and LBCs derived from the FV3GFS. + In addition, this test activates the stochastic physics options. user: RUN_ENVIR: community workflow: diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_HRRR.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_HRRR.yaml index 30e65ed3d6..a64083516c 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_HRRR.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_HRRR.yaml @@ -3,6 +3,11 @@ metadata: This test is to ensure that the workflow running in community mode completes successfully on the RRFS_CONUS_25km grid using the HRRR physics suite with ICs and LBCs derived from the FV3GFS. + Additionally, this test deactivates the write component (QUILTING=False) + to test the workflow's support for this option. Note that run_post and + subsequent tasks are deactivated as well, since these do not work on the + native grid output at this time. + user: RUN_ENVIR: community workflow: @@ -12,6 +17,9 @@ workflow: DATE_LAST_CYCL: '2019070100' FCST_LEN_HRS: 6 PREEXISTING_DIR_METHOD: rename +rocoto: + tasks: + taskgroups: '{{ ["parm/wflow/prep.yaml", "parm/wflow/coldstart.yaml"]|include }}' task_get_extrn_ics: EXTRN_MDL_NAME_ICS: FV3GFS USE_USER_STAGED_EXTRN_FILES: true @@ -19,3 +27,5 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 USE_USER_STAGED_EXTRN_FILES: true +task_run_fcst: + QUILTING: false diff --git a/tests/WE2E/test_configs/verification/config.MET_verification_winter_wx.yaml b/tests/WE2E/test_configs/verification/config.MET_verification_winter_wx.yaml new file mode 120000 index 0000000000..be4c2e88af --- /dev/null +++ b/tests/WE2E/test_configs/verification/config.MET_verification_winter_wx.yaml @@ -0,0 +1 @@ +../custom_grids/config.custom_ESGgrid_Great_Lakes_snow_8km.yaml \ No newline at end of file diff --git a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_grib2_2019061200.yaml b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_grib2_2019061200.yaml index 2f1733dcdc..9dc677b9e6 100644 --- a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_grib2_2019061200.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_grib2_2019061200.yaml @@ -6,6 +6,8 @@ metadata: date (2019061200) on which the FV3GFS officially became operational. user: RUN_ENVIR: community +platform: + EXTRN_MDL_DATA_STORES: hpss workflow: CCPP_PHYS_SUITE: FV3_GFS_v15p2 PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio_2019061200.yaml b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio_2019061200.yaml index 294442641a..dc1dab0203 100644 --- a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio_2019061200.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio_2019061200.yaml @@ -6,6 +6,8 @@ metadata: date (2019061200) on which the FV3GFS officially became operational. user: RUN_ENVIR: community +platform: + EXTRN_MDL_DATA_STORES: hpss workflow: CCPP_PHYS_SUITE: FV3_GFS_v15p2 PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio_2021032018.yaml b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio_2021032018.yaml index 10ba42d937..2e89dd2597 100644 --- a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio_2021032018.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio_2021032018.yaml @@ -6,6 +6,8 @@ metadata: (2021032018) before nemsio was discontinued for netcdf files user: RUN_ENVIR: community +platform: + EXTRN_MDL_DATA_STORES: hpss workflow: CCPP_PHYS_SUITE: FV3_GFS_v15p2 PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_netcdf_2022060112_48h.yaml b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_netcdf_2022060112_48h.yaml index 435b4723a1..237cab83cc 100644 --- a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_netcdf_2022060112_48h.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_netcdf_2022060112_48h.yaml @@ -5,6 +5,8 @@ metadata: model (FCST_LEN_HRS>=40). user: RUN_ENVIR: community +platform: + EXTRN_MDL_DATA_STORES: hpss workflow: CCPP_PHYS_SUITE: FV3_GFS_v16 PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_GSMGFS_lbcs_GSMGFS.yaml b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_GSMGFS_lbcs_GSMGFS.yaml index 4fdbc93133..aed9d6246c 100644 --- a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_GSMGFS_lbcs_GSMGFS.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_GSMGFS_lbcs_GSMGFS.yaml @@ -5,6 +5,8 @@ metadata: LBCs will be derived. user: RUN_ENVIR: community +platform: + EXTRN_MDL_DATA_STORES: hpss workflow: CCPP_PHYS_SUITE: FV3_GFS_v15p2 PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_HRRR_lbcs_RAP.yaml b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_HRRR_lbcs_RAP.yaml index 9821a4b6ce..c25d37ebc4 100644 --- a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_HRRR_lbcs_RAP.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_HRRR_lbcs_RAP.yaml @@ -7,6 +7,8 @@ metadata: forecast hour) will be derived. user: RUN_ENVIR: community +platform: + EXTRN_MDL_DATA_STORES: hpss workflow: CCPP_PHYS_SUITE: FV3_HRRR PREDEF_GRID_NAME: RRFS_CONUScompact_25km diff --git a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_RAP_lbcs_RAP.yaml b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_RAP_lbcs_RAP.yaml index ef3386913b..df107c998c 100644 --- a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_RAP_lbcs_RAP.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_RAP_lbcs_RAP.yaml @@ -5,6 +5,8 @@ metadata: will be derived. user: RUN_ENVIR: community +platform: + EXTRN_MDL_DATA_STORES: hpss workflow: CCPP_PHYS_SUITE: FV3_HRRR PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/wflow_features/config.long_fcst.yaml b/tests/WE2E/test_configs/wflow_features/config.long_fcst.yaml new file mode 100644 index 0000000000..519cd9ccb7 --- /dev/null +++ b/tests/WE2E/test_configs/wflow_features/config.long_fcst.yaml @@ -0,0 +1,25 @@ +metadata: + description: |- + This test checks the capability of workflow components to function correctly + for long forecast times (FCST_LEN_HRS>=100). +user: + RUN_ENVIR: community +workflow: + CCPP_PHYS_SUITE: FV3_RAP + PREDEF_GRID_NAME: RRFS_CONUScompact_25km + DATE_FIRST_CYCL: '2023060112' + DATE_LAST_CYCL: '2023060112' + FCST_LEN_HRS: 108 + PREEXISTING_DIR_METHOD: rename +platform: + EXTRN_MDL_DATA_STORES: aws +task_get_extrn_ics: + EXTRN_MDL_NAME_ICS: FV3GFS + FV3GFS_FILE_FMT_ICS: grib2 +task_get_extrn_lbcs: + EXTRN_MDL_NAME_LBCS: FV3GFS + LBC_SPEC_INTVL_HRS: 12 + FV3GFS_FILE_FMT_LBCS: grib2 +task_run_fcst: + LAYOUT_X: 10 + LAYOUT_Y: 6 diff --git a/tests/WE2E/test_configs/wflow_features/config.quilting_false.yaml b/tests/WE2E/test_configs/wflow_features/config.quilting_false.yaml deleted file mode 100644 index 76d238846c..0000000000 --- a/tests/WE2E/test_configs/wflow_features/config.quilting_false.yaml +++ /dev/null @@ -1,35 +0,0 @@ -metadata: - description: |- - This test is to ensure that the workflow completes successfully with - QUILTING disabled. The forecast runs on the RRFS_CONUScompact_25km - grid using the RAP physics suite with ICs derived from the FV3GFS and - LBCs derived from the RAP. Note that with QUILTING disabled, the run_post - and subsequent tasks in the SRW App workflow cannot be run. This is - because QUILTING disabled, the output from the UFS Weather Model is on - the Weather Model's native grid, not the write-component grid, and UPP - does not (yet) have the capability to process output on the native grid. -user: - RUN_ENVIR: community -workflow: - CCPP_PHYS_SUITE: FV3_RAP - PREDEF_GRID_NAME: RRFS_CONUScompact_25km - DATE_FIRST_CYCL: '2019061518' - DATE_LAST_CYCL: '2019061518' - FCST_LEN_HRS: 6 - PREEXISTING_DIR_METHOD: rename -rocoto: - tasks: - taskgroups: '{{ ["parm/wflow/prep.yaml", "parm/wflow/coldstart.yaml"]|include }}' -task_get_extrn_ics: - EXTRN_MDL_NAME_ICS: FV3GFS - FV3GFS_FILE_FMT_ICS: grib2 - USE_USER_STAGED_EXTRN_FILES: true -task_get_extrn_lbcs: - EXTRN_MDL_NAME_LBCS: RAP - LBC_SPEC_INTVL_HRS: 1 - EXTRN_MDL_LBCS_OFFSET_HRS: 0 - USE_USER_STAGED_EXTRN_FILES: true -task_run_fcst: - QUILTING: false -verification: - VX_FCST_MODEL_NAME: FV3_GFS_v15p2_CONUS_25km diff --git a/tests/WE2E/test_configs/wflow_features/config.quilting_false.yaml b/tests/WE2E/test_configs/wflow_features/config.quilting_false.yaml new file mode 120000 index 0000000000..f95e874a71 --- /dev/null +++ b/tests/WE2E/test_configs/wflow_features/config.quilting_false.yaml @@ -0,0 +1 @@ +../grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_HRRR.yaml \ No newline at end of file diff --git a/tests/WE2E/utils.py b/tests/WE2E/utils.py index ba862bd855..fb96dab004 100755 --- a/tests/WE2E/utils.py +++ b/tests/WE2E/utils.py @@ -221,7 +221,7 @@ def update_expt_status(expt: dict, name: str, refresh: bool = False, debug: bool CREATED: The experiments have been created, but the monitor script has not yet processed them. This is immediately overwritten at the beginning of the "monitor_jobs" function, so we should never see this status in this function. Including just for completeness sake. - SUBMITTING: All jobs are in status SUBMITTING or SUCCEEDED. This is a normal state; we will + SUBMITTING: All jobs are in status SUBMITTING or SUCCEEDED. This is a normal state; we will continue to monitor this experiment. DYING: One or more tasks have died (status "DEAD"), so this experiment has had an error. We will continue to monitor this experiment until all tasks are either status DEAD or @@ -268,7 +268,7 @@ def update_expt_status(expt: dict, name: str, refresh: bool = False, debug: bool rocoto_xml = f"{expt['expt_dir']}/FV3LAM_wflow.xml" if submit: if refresh: - logging.info(f"Updating database for experiment {name}") + logging.debug(f"Updating database for experiment {name}") if debug: rocotorun_cmd = ["rocotorun", f"-w {rocoto_xml}", f"-d {rocoto_db}", "-v 10"] p = subprocess.run(rocotorun_cmd, stdout=subprocess.PIPE, @@ -557,7 +557,7 @@ def compare_rocotostat(expt_dict,name): for ut in untracked_tasks: msg += ut msg = msg + f"""WARNING: For experiment {name}, - there are some jobs that are not being submitted. + there are some jobs that are not being submitted. It could be that your jobs are being throttled at the system level, or some task dependencies have not been met. diff --git a/tests/test_python/test_get_crontab_contents.py b/tests/test_python/test_get_crontab_contents.py index 7998550f2f..5fb077cc1b 100644 --- a/tests/test_python/test_get_crontab_contents.py +++ b/tests/test_python/test_get_crontab_contents.py @@ -2,17 +2,15 @@ import unittest -from python_utils import define_macos_utilities, set_env_var +from python_utils import define_macos_utilities from get_crontab_contents import get_crontab_contents class Testing(unittest.TestCase): """ Define the tests""" def test_get_crontab_contents(self): """ Call the function and make sure it doesn't fail. """ - crontab_cmd, _ = get_crontab_contents(called_from_cron=True) + crontab_cmd, _ = get_crontab_contents(called_from_cron=True,machine="HERA",debug=True) self.assertEqual(crontab_cmd, "crontab") def setUp(self): define_macos_utilities() - set_env_var("DEBUG", False) - set_env_var("MACHINE", "HERA") diff --git a/ush/config_defaults.yaml b/ush/config_defaults.yaml index f80d4d7887..3a6a90929c 100644 --- a/ush/config_defaults.yaml +++ b/ush/config_defaults.yaml @@ -950,10 +950,10 @@ nco: # Name of model run (third level of com directory structure). # In general, same as ${NET_default}. # - # OPSROOT: + # OPSROOT_default: # The operations root directory in NCO mode. # - # LOGBASEDIR: + # LOGBASEDIR_default: # Directory in which the log files from the workflow tasks will be placed. # # NWGES: diff --git a/ush/generate_FV3LAM_wflow.py b/ush/generate_FV3LAM_wflow.py index f97f06dd6f..85408ef967 100755 --- a/ush/generate_FV3LAM_wflow.py +++ b/ush/generate_FV3LAM_wflow.py @@ -7,6 +7,7 @@ # pylint: disable=invalid-name +import argparse import os import logging from textwrap import dedent @@ -70,7 +71,6 @@ def generate_FV3LAM_wflow( # non-user-specified values from config_defaults.yaml expt_config = setup(ushdir,debug=debug) - verbose = expt_config["workflow"]["VERBOSE"] # # ----------------------------------------------------------------------- # @@ -117,6 +117,8 @@ def generate_FV3LAM_wflow( "-i", template_xml_fp, "-c", rocoto_yaml_fp, ] + if not debug: + args.append("-q") set_template(args) # # ----------------------------------------------------------------------- @@ -135,7 +137,7 @@ def generate_FV3LAM_wflow( workflow launch script (WFLOW_LAUNCH_SCRIPT_FP): EXPTDIR = '{exptdir}' WFLOW_LAUNCH_SCRIPT_FP = '{wflow_launch_script_fp}'""", - verbose=verbose, + verbose=debug, ) create_symlink_to_file( @@ -159,7 +161,9 @@ def generate_FV3LAM_wflow( # pylint: disable=undefined-variable if USE_CRON_TO_RELAUNCH: - add_crontab_line() + add_crontab_line(called_from_cron=False,machine=expt_config["user"]["MACHINE"], + crontab_line=expt_config["workflow"]["CRONTAB_LINE"], + exptdir=exptdir,debug=debug) # # Copy or symlink fix files @@ -170,7 +174,7 @@ def generate_FV3LAM_wflow( Symlinking fixed files from system directory (FIXgsm) to a subdirectory (FIXam): FIXgsm = '{FIXgsm}' FIXam = '{FIXam}'""", - verbose=verbose, + verbose=debug, ) ln_vrfy(f"""-fsn '{FIXgsm}' '{FIXam}'""") @@ -181,7 +185,7 @@ def generate_FV3LAM_wflow( Copying fixed files from system directory (FIXgsm) to a subdirectory (FIXam): FIXgsm = '{FIXgsm}' FIXam = '{FIXam}'""", - verbose=verbose, + verbose=debug, ) check_for_preexist_dir_file(FIXam, "delete") @@ -207,7 +211,7 @@ def generate_FV3LAM_wflow( FIXaer = '{FIXaer}' FIXlut = '{FIXlut}' FIXclim = '{FIXclim}'""", - verbose=verbose, + verbose=debug, ) check_for_preexist_dir_file(FIXclim, "delete") @@ -229,20 +233,20 @@ def generate_FV3LAM_wflow( log_info( """ Copying templates of various input files to the experiment directory...""", - verbose=verbose, + verbose=debug, ) log_info( """ Copying the template data table file to the experiment directory...""", - verbose=verbose, + verbose=debug, ) cp_vrfy(DATA_TABLE_TMPL_FP, DATA_TABLE_FP) log_info( """ Copying the template field table file to the experiment directory...""", - verbose=verbose, + verbose=debug, ) cp_vrfy(FIELD_TABLE_TMPL_FP, FIELD_TABLE_FP) @@ -255,7 +259,7 @@ def generate_FV3LAM_wflow( """ Copying the CCPP physics suite definition XML file from its location in the forecast model directory structure to the experiment directory...""", - verbose=verbose, + verbose=debug, ) cp_vrfy(CCPP_PHYS_SUITE_IN_CCPP_FP, CCPP_PHYS_SUITE_FP) # @@ -268,7 +272,7 @@ def generate_FV3LAM_wflow( Copying the field dictionary file from its location in the forecast model directory structure to the experiment directory...""", - verbose=verbose, + verbose=debug, ) cp_vrfy(FIELD_DICT_IN_UWM_FP, FIELD_DICT_FP) # @@ -281,7 +285,8 @@ def generate_FV3LAM_wflow( log_info( f""" Setting parameters in weather model's namelist file (FV3_NML_FP): - FV3_NML_FP = '{FV3_NML_FP}'""" + FV3_NML_FP = '{FV3_NML_FP}'""", + verbose=debug, ) # # Set npx and npy, which are just NX plus 1 and NY plus 1, respectively. @@ -486,9 +491,9 @@ def generate_FV3LAM_wflow( """ The variable 'settings' specifying values of the weather model's namelist variables has been set as follows:\n""", - verbose=verbose, + verbose=debug, ) - log_info("\nsettings =\n\n" + settings_str, verbose=verbose) + log_info("\nsettings =\n\n" + settings_str, verbose=debug) # # ----------------------------------------------------------------------- # @@ -502,19 +507,14 @@ def generate_FV3LAM_wflow( # # ----------------------------------------------------------------------- # - set_namelist( - [ - "-n", - FV3_NML_BASE_SUITE_FP, - "-c", - FV3_NML_YAML_CONFIG_FP, - CCPP_PHYS_SUITE, - "-u", - settings_str, - "-o", - FV3_NML_FP, - ] - ) + args=[ "-n", FV3_NML_BASE_SUITE_FP, + "-c", FV3_NML_YAML_CONFIG_FP, CCPP_PHYS_SUITE, + "-u", settings_str, + "-o", FV3_NML_FP, + ] + if not debug: + args.append("-q") + set_namelist(args) # # If not running the TN_MAKE_GRID task (which implies the workflow will # use pregenerated grid files), set the namelist variables specifying @@ -529,7 +529,7 @@ def generate_FV3LAM_wflow( # if not expt_config['rocoto']['tasks'].get('task_make_grid'): - set_FV3nml_sfc_climo_filenames() + set_FV3nml_sfc_climo_filenames(debug) # # ----------------------------------------------------------------------- @@ -551,16 +551,13 @@ def generate_FV3LAM_wflow( # # populate the namelist file # - set_namelist( - [ - "-n", - FV3_NML_FP, - "-u", - settings_str, - "-o", - FV3_NML_CYCSFC_FP, - ] - ) + args=[ "-n", FV3_NML_FP, + "-u", settings_str, + "-o", FV3_NML_CYCSFC_FP, + ] + if not debug: + args.append("-q") + set_namelist(args) # # ----------------------------------------------------------------------- # @@ -596,17 +593,13 @@ def generate_FV3LAM_wflow( # # populate the namelist file # - set_namelist( - [ - "-q", - "-n", - FV3_NML_FP, - "-u", - settings_str, - "-o", - FV3_NML_RESTART_FP, - ] - ) + args=[ "-n", FV3_NML_FP, + "-u", settings_str, + "-o", FV3_NML_RESTART_FP, + ] + if not debug: + args.append("-q") + set_namelist(args) # # ----------------------------------------------------------------------- # @@ -720,29 +713,22 @@ def generate_FV3LAM_wflow( # if any((DO_SPP, DO_SPPT, DO_SHUM, DO_SKEB, DO_LSM_SPP)): - set_namelist( - [ - "-n", - FV3_NML_FP, - "-u", - settings_str, - "-o", - FV3_NML_STOCH_FP, - ] - ) + args=[ "-n", FV3_NML_FP, + "-u", settings_str, + "-o", FV3_NML_STOCH_FP, + ] + if not debug: + args.append("-q") + set_namelist(args) if DO_DACYCLE or DO_ENKFUPDATE: - set_namelist( - [ - "-q", - "-n", - FV3_NML_RESTART_FP, - "-u", - settings_str, - "-o", - FV3_NML_RESTART_STOCH_FP, - ] - ) + args=[ "-n", FV3_NML_RESTART_FP, + "-u", settings_str, + "-o", FV3_NML_RESTART_STOCH_FP, + ] + if not debug: + args.append("-q") + set_namelist(args) # # ----------------------------------------------------------------------- # @@ -843,13 +829,22 @@ def setup_logging(logfile: str = "log.generate_FV3LAM_wflow", debug: bool = Fals if __name__ == "__main__": + #Parse arguments + parser = argparse.ArgumentParser( + description="Script for setting up a forecast and creating a workflow"\ + "according to the parameters specified in the config file\n") + + parser.add_argument('-d', '--debug', action='store_true', + help='Script will be run in debug mode with more verbose output') + pargs = parser.parse_args() + USHdir = os.path.dirname(os.path.abspath(__file__)) wflow_logfile = f"{USHdir}/log.generate_FV3LAM_wflow" # Call the generate_FV3LAM_wflow function defined above to generate the # experiment/workflow. try: - expt_dir = generate_FV3LAM_wflow(USHdir, wflow_logfile) + expt_dir = generate_FV3LAM_wflow(USHdir, wflow_logfile, pargs.debug) except: # pylint: disable=bare-except logging.exception( dedent( diff --git a/ush/get_crontab_contents.py b/ush/get_crontab_contents.py index acc222822a..3b4ed5b6a9 100644 --- a/ush/get_crontab_contents.py +++ b/ush/get_crontab_contents.py @@ -4,168 +4,146 @@ import sys import argparse from datetime import datetime -from textwrap import dedent - from python_utils import ( log_info, - import_vars, - set_env_var, - print_input_args, run_command, - define_macos_utilities, print_info_msg, ) -def get_crontab_contents(called_from_cron): +def get_crontab_contents(called_from_cron, machine, debug): """ - #----------------------------------------------------------------------- - # - # This function returns the contents of the user's - # cron table as well as the command to use to manipulate the cron table - # (i.e. the "crontab" command, but on some platforms the version or - # location of this may change depending on other circumstances, e.g. on - # Cheyenne, this depends on whether a script that wants to call "crontab" - # is itself being called from a cron job). Arguments are as follows: - # - # called_from_cron: - # Boolean flag that specifies whether this function (and the scripts or - # functions that are calling it) are called as part of a cron job. Must - # be set to "TRUE" or "FALSE". - # - # outvarname_crontab_cmd: - # Name of the output variable that will contain the command to issue for - # the system "crontab" command. - # - # outvarname_crontab_contents: - # Name of the output variable that will contain the contents of the - # user's cron table. - # - #----------------------------------------------------------------------- + This function returns the contents of the user's cron table, as well as the command used to + manipulate the cron table. Typically this latter value will be `crontab`, but on some + platforms the version or location of this may change depending on other circumstances, e.g. on + Cheyenne, this depends on whether a script that wants to call `crontab` is itself being called + from a cron job. + + Args: + called_from_cron (bool): Set this to True if script is called from within a crontab + machine (str) : The name of the current machine + debug (bool): True will give more verbose output + Returns: + crontab_cmd (str) : String containing the "crontab" command for this machine + crontab_contents (str) : String containing the contents of the user's cron table. """ - print_input_args(locals()) - - # import selected env vars - IMPORTS = ["MACHINE", "DEBUG"] - import_vars(env_vars=IMPORTS) - - __crontab_cmd__ = "crontab" # # On Cheyenne, simply typing "crontab" will launch the crontab command # at "/glade/u/apps/ch/opt/usr/bin/crontab". This is a containerized - # version of crontab that will work if called from scripts that are + # version of crontab that will not work if called from scripts that are # themselves being called as cron jobs. In that case, we must instead # call the system version of crontab at /usr/bin/crontab. # - if MACHINE == "CHEYENNE": + if machine == "CHEYENNE": if called_from_cron: - __crontab_cmd__ = "/usr/bin/crontab" + crontab_cmd = "/usr/bin/crontab" + else: + crontab_cmd = "crontab" print_info_msg( f""" Getting crontab content with command: ========================================================= - {__crontab_cmd__} -l + {crontab_cmd} -l =========================================================""", - verbose=DEBUG, + verbose=debug, ) - (_, __crontab_contents__, _) = run_command(f"""{__crontab_cmd__} -l""") + (_, crontab_contents, _) = run_command(f"{crontab_cmd} -l") + + if crontab_contents.startswith('no crontab for'): + crontab_contents='' print_info_msg( f""" Crontab contents: ========================================================= - {__crontab_contents__} + {crontab_contents} =========================================================""", - verbose=DEBUG, + verbose=debug, ) # replace single quotes (hopefully in comments) with double quotes - __crontab_contents__ = __crontab_contents__.replace("'", '"') + crontab_contents = crontab_contents.replace("'", '"') - return __crontab_cmd__, __crontab_contents__ + return crontab_cmd, crontab_contents -def add_crontab_line(): +def add_crontab_line(called_from_cron, machine, crontab_line, exptdir, debug): """Add crontab line to cron table""" - # import selected env vars - IMPORTS = ["MACHINE", "CRONTAB_LINE", "VERBOSE", "EXPTDIR"] - import_vars(env_vars=IMPORTS) - # # Make a backup copy of the user's crontab file and save it in a file. # time_stamp = datetime.now().strftime("%F_%T") - crontab_backup_fp = os.path.join(EXPTDIR, f"crontab.bak.{time_stamp}") + crontab_backup_fp = os.path.join(exptdir, f"crontab.bak.{time_stamp}") log_info( f""" Copying contents of user cron table to backup file: crontab_backup_fp = '{crontab_backup_fp}'""", - verbose=VERBOSE, + verbose=debug, ) - global called_from_cron - try: - called_from_cron - except: - called_from_cron = False - # Get crontab contents - crontab_cmd, crontab_contents = get_crontab_contents( - called_from_cron=called_from_cron - ) + crontab_cmd, crontab_contents = get_crontab_contents(called_from_cron, machine, debug) # Create backup run_command(f"""printf "%s" '{crontab_contents}' > '{crontab_backup_fp}'""") - # Add crontab line - if CRONTAB_LINE in crontab_contents: - + # Need to omit commented crontab entries for later logic + lines = crontab_contents.split('\n') + cronlines = [] + for line in lines: + comment = False + for char in line: + if char == "#": + comment = True + break + elif char.isspace(): + continue + else: + # If we find a character that isn't blank or comment, then this is a normal line + break + if not comment: + cronlines.append(line) + # Re-join all the separate lines into a multiline string again + crontab_no_comments = """{}""".format("\n".join(cronlines)) + if crontab_line in crontab_no_comments: log_info( f""" The following line already exists in the cron table and thus will not be added: - CRONTAB_LINE = '{CRONTAB_LINE}'""" + crontab_line = '{crontab_line}'""" ) - else: - log_info( f""" Adding the following line to the user's cron table in order to automatically resubmit SRW workflow: - CRONTAB_LINE = '{CRONTAB_LINE}'""", - verbose=VERBOSE, + crontab_line = '{crontab_line}'""", + verbose=debug, ) # add new line to crontab contents if it doesn't have one - NEWLINE_CHAR = "" + newline_char = "" if crontab_contents and crontab_contents[-1] != "\n": - NEWLINE_CHAR = "\n" + newline_char = "\n" # add the crontab line run_command( - f"""printf "%s%b%s\n" '{crontab_contents}' '{NEWLINE_CHAR}' '{CRONTAB_LINE}' | {crontab_cmd}""" + f"""printf "%s%b%s\n" '{crontab_contents}' '{newline_char}' '{crontab_line}' | {crontab_cmd}""" ) -def delete_crontab_line(called_from_cron): +def delete_crontab_line(called_from_cron, machine, crontab_line, debug): """Delete crontab line after job is complete i.e. either SUCCESS/FAILURE but not IN PROGRESS status""" - print_input_args(locals()) - - # import selected env vars - IMPORTS = ["MACHINE", "CRONTAB_LINE", "DEBUG"] - import_vars(env_vars=IMPORTS) - # # Get the full contents of the user's cron table. # - (crontab_cmd, crontab_contents) = get_crontab_contents(called_from_cron) + (crontab_cmd, crontab_contents) = get_crontab_contents(called_from_cron, machine, debug) # # Remove the line in the contents of the cron table corresponding to the # current forecast experiment (if that line is part of the contents). @@ -177,13 +155,15 @@ def delete_crontab_line(called_from_cron): ========================================================= {crontab_contents} =========================================================""", - verbose=True, + verbose=debug, ) - if (CRONTAB_LINE + "\n") in crontab_contents: - crontab_contents = crontab_contents.replace(CRONTAB_LINE + "\n", "") + if crontab_line in crontab_contents: + #Try removing with a newline first, then fall back to without newline + crontab_contents = crontab_contents.replace(crontab_line + "\n", "") + crontab_contents = crontab_contents.replace(crontab_line, "") else: - crontab_contents = crontab_contents.replace(CRONTAB_LINE, "") + print(f"\nWARNING: line not found in crontab, nothing to remove:\n {crontab_line}\n") run_command(f"""echo '{crontab_contents}' | {crontab_cmd}""") @@ -193,36 +173,65 @@ def delete_crontab_line(called_from_cron): ========================================================= {crontab_contents} =========================================================""", - verbose=True, + verbose=debug, ) def parse_args(argv): """Parse command line arguments for deleting crontab line. - This is needed because it is called from shell script + This is needed because it is called from shell script. + If 'delete' argument is not passed, print the crontab contents """ - parser = argparse.ArgumentParser(description="Crontab job manupilation program.") + parser = argparse.ArgumentParser(description="Crontab job manipulation program.") + + parser.add_argument( + "-c", + "--called_from_cron", + action="store_true", + help="Called from cron.", + ) parser.add_argument( "-d", - "--delete", - dest="delete", + "--debug", action="store_true", - help="Delete crontab line.", + help="Print debug output", ) parser.add_argument( - "-c", - "--called-from-cron", - dest="called_from_cron", + "-r", + "--remove", action="store_true", - help="Called from cron.", + help="Remove specified crontab line.", ) - return parser.parse_args(argv) + parser.add_argument( + "-l", + "--line", + help="Line to remove from crontab. If --remove not specified, has no effect", + ) + + parser.add_argument( + "-m", + "--machine", + help="Machine name", + required=True + ) + + # Check that inputs are correct and consistent + args = parser.parse_args(argv) + + if args.remove: + if args.line is None: + raise argparse.ArgumentTypeError("--line is a required argument if --remove is specified") + + return args if __name__ == "__main__": args = parse_args(sys.argv[1:]) - if args.delete: - delete_crontab_line(args.called_from_cron) + if args.remove: + delete_crontab_line(args.called_from_cron,args.machine,args.line,args.debug) + else: + _,out = get_crontab_contents(args.called_from_cron,args.machine,args.debug) + print_info_msg(out) diff --git a/ush/get_layout.sh b/ush/get_layout.sh index 878f1b30d9..620c0229e7 100755 --- a/ush/get_layout.sh +++ b/ush/get_layout.sh @@ -17,7 +17,7 @@ fi if [ "$#" -eq 3 ]; then nlayout=$3 - echo "ncups= $nlayout" + echo "ncpus= $nlayout" layout_x=$(echo "sqrt($nlayout*$nx/$ny)" |bc ) if [ $layout_x -gt $nx ]; then $layout_x=$nx diff --git a/ush/launch_FV3LAM_wflow.sh b/ush/launch_FV3LAM_wflow.sh index 43b1321c11..cfbedac9cf 100755 --- a/ush/launch_FV3LAM_wflow.sh +++ b/ush/launch_FV3LAM_wflow.sh @@ -381,11 +381,9 @@ script for this experiment: # Remove CRONTAB_LINE from cron table # if [ "${called_from_cron}" = "TRUE" ]; then - MACHINE=$MACHINE CRONTAB_LINE=$CRONTAB_LINE \ - python3 $USHdir/get_crontab_contents.py --delete --called-from-cron + python3 $USHdir/get_crontab_contents.py --remove -m=${machine} -l="${CRONTAB_LINE}" -c -d else - MACHINE=$MACHINE CRONTAB_LINE=$CRONTAB_LINE \ - python3 $USHdir/get_crontab_contents.py --delete + python3 $USHdir/get_crontab_contents.py --remove -m=${machine} -l="${CRONTAB_LINE}" -d fi fi # diff --git a/ush/predef_grid_params.yaml b/ush/predef_grid_params.yaml index 450e618c15..afcbdddf7c 100644 --- a/ush/predef_grid_params.yaml +++ b/ush/predef_grid_params.yaml @@ -499,280 +499,6 @@ # #----------------------------------------------------------------------- # -# EMC's Alaska grid. -# -#----------------------------------------------------------------------- -# -"EMC_AK": - GRID_GEN_METHOD: "ESGgrid" - ESGgrid_LON_CTR: -153.0 - ESGgrid_LAT_CTR: 61.0 - ESGgrid_DELX: 3000.0 - ESGgrid_DELY: 3000.0 - ESGgrid_NX: 1344 # Supergrid value 2704 - ESGgrid_NY: 1152 # Supergrid value 2320 - ESGgrid_PAZI: 0.0 - ESGgrid_WIDE_HALO_WIDTH: 6 - DT_ATMOS: 18 - LAYOUT_X: 28 - LAYOUT_Y: 16 - BLOCKSIZE: 24 - QUILTING: - WRTCMP_write_groups: 1 - WRTCMP_write_tasks_per_group: 24 - WRTCMP_output_grid: "lambert_conformal" - WRTCMP_cen_lon: -153.0 - WRTCMP_cen_lat: 61.0 - WRTCMP_stdlat1: 61.0 - WRTCMP_stdlat2: 61.0 - WRTCMP_nx: 1344 - WRTCMP_ny: 1152 - WRTCMP_lon_lwr_left: -177.0 - WRTCMP_lat_lwr_left: 42.5 - WRTCMP_dx: 3000.0 - WRTCMP_dy: 3000.0 -# -#----------------------------------------------------------------------- -# -# EMC's Hawaii grid. -# -#----------------------------------------------------------------------- -# -"EMC_HI": - GRID_GEN_METHOD: "ESGgrid" - ESGgrid_LON_CTR: -157.0 - ESGgrid_LAT_CTR: 20.0 - ESGgrid_DELX: 3000.0 - ESGgrid_DELY: 3000.0 - ESGgrid_NX: 432 # Supergrid value 880 - ESGgrid_NY: 360 # Supergrid value 736 - ESGgrid_PAZI: 0.0 - ESGgrid_WIDE_HALO_WIDTH: 6 - DT_ATMOS: 18 - LAYOUT_X: 8 - LAYOUT_Y: 8 - BLOCKSIZE: 27 - QUILTING: - WRTCMP_write_groups: 1 - WRTCMP_write_tasks_per_group: 8 - WRTCMP_output_grid: "lambert_conformal" - WRTCMP_cen_lon: -157.0 - WRTCMP_cen_lat: 20.0 - WRTCMP_stdlat1: 20.0 - WRTCMP_stdlat2: 20.0 - WRTCMP_nx: 420 - WRTCMP_ny: 348 - WRTCMP_lon_lwr_left: -162.8 - WRTCMP_lat_lwr_left: 15.2 - WRTCMP_dx: 3000.0 - WRTCMP_dy: 3000.0 -# -#----------------------------------------------------------------------- -# -# EMC's Puerto Rico grid. -# -#----------------------------------------------------------------------- -# -"EMC_PR": - GRID_GEN_METHOD: "ESGgrid" - ESGgrid_LON_CTR: -69.0 - ESGgrid_LAT_CTR: 18.0 - ESGgrid_DELX: 3000.0 - ESGgrid_DELY: 3000.0 - ESGgrid_NX: 576 # Supergrid value 1168 - ESGgrid_NY: 432 # Supergrid value 880 - ESGgrid_PAZI: 0.0 - ESGgrid_WIDE_HALO_WIDTH: 6 - DT_ATMOS: 18 - LAYOUT_X: 16 - LAYOUT_Y: 8 - BLOCKSIZE: 24 - QUILTING: - WRTCMP_write_groups: 1 - WRTCMP_write_tasks_per_group: 24 - WRTCMP_output_grid: "lambert_conformal" - WRTCMP_cen_lon: -69.0 - WRTCMP_cen_lat: 18.0 - WRTCMP_stdlat1: 18.0 - WRTCMP_stdlat2: 18.0 - WRTCMP_nx: 576 - WRTCMP_ny: 432 - WRTCMP_lon_lwr_left: -77 - WRTCMP_lat_lwr_left: 12 - WRTCMP_dx: 3000.0 - WRTCMP_dy: 3000.0 -# -#----------------------------------------------------------------------- -# -# EMC's Guam grid. -# -#----------------------------------------------------------------------- -# -"EMC_GU": - GRID_GEN_METHOD: "ESGgrid" - ESGgrid_LON_CTR: 146.0 - ESGgrid_LAT_CTR: 15.0 - ESGgrid_DELX: 3000.0 - ESGgrid_DELY: 3000.0 - ESGgrid_NX: 432 # Supergrid value 880 - ESGgrid_NY: 360 # Supergrid value 736 - ESGgrid_PAZI: 0.0 - ESGgrid_WIDE_HALO_WIDTH: 6 - DT_ATMOS: 18 - LAYOUT_X: 16 - LAYOUT_Y: 12 - BLOCKSIZE: 27 - QUILTING: - WRTCMP_write_groups: 1 - WRTCMP_write_tasks_per_group: 24 - WRTCMP_output_grid: "lambert_conformal" - WRTCMP_cen_lon: 146.0 - WRTCMP_cen_lat: 15.0 - WRTCMP_stdlat1: 15.0 - WRTCMP_stdlat2: 15.0 - WRTCMP_nx: 420 - WRTCMP_ny: 348 - WRTCMP_lon_lwr_left: 140 - WRTCMP_lat_lwr_left: 10 - WRTCMP_dx: 3000.0 - WRTCMP_dy: 3000.0 -# -#----------------------------------------------------------------------- -# -# Emulation of the HAFS v0.A grid at 25 km. -# -#----------------------------------------------------------------------- -# -"GSL_HAFSV0.A_25km": - GRID_GEN_METHOD: "ESGgrid" - ESGgrid_LON_CTR: -62.0 - ESGgrid_LAT_CTR: 22.0 - ESGgrid_DELX: 25000.0 - ESGgrid_DELY: 25000.0 - ESGgrid_NX: 345 - ESGgrid_NY: 230 - ESGgrid_PAZI: 0.0 - ESGgrid_WIDE_HALO_WIDTH: 6 - DT_ATMOS: 300 - LAYOUT_X: 5 - LAYOUT_Y: 5 - BLOCKSIZE: 6 - QUILTING: - WRTCMP_write_groups: 1 - WRTCMP_write_tasks_per_group: 32 - WRTCMP_output_grid: "regional_latlon" - WRTCMP_cen_lon: -62.0 - WRTCMP_cen_lat: 25.0 - WRTCMP_lon_lwr_left: -114.5 - WRTCMP_lat_lwr_left: -5.0 - WRTCMP_lon_upr_rght: -9.5 - WRTCMP_lat_upr_rght: 55.0 - WRTCMP_dlon: 0.25 - WRTCMP_dlat: 0.25 -# -#----------------------------------------------------------------------- -# -# Emulation of the HAFS v0.A grid at 13 km. -# -#----------------------------------------------------------------------- -# -"GSL_HAFSV0.A_13km": - GRID_GEN_METHOD: "ESGgrid" - ESGgrid_LON_CTR: -62.0 - ESGgrid_LAT_CTR: 22.0 - ESGgrid_DELX: 13000.0 - ESGgrid_DELY: 13000.0 - ESGgrid_NX: 665 - ESGgrid_NY: 444 - ESGgrid_PAZI: 0.0 - ESGgrid_WIDE_HALO_WIDTH: 6 - DT_ATMOS: 180 - LAYOUT_X: 19 - LAYOUT_Y: 12 - BLOCKSIZE: 35 - QUILTING: - WRTCMP_write_groups: 1 - WRTCMP_write_tasks_per_group: 32 - WRTCMP_output_grid: "regional_latlon" - WRTCMP_cen_lon: -62.0 - WRTCMP_cen_lat: 25.0 - WRTCMP_lon_lwr_left: -114.5 - WRTCMP_lat_lwr_left: -5.0 - WRTCMP_lon_upr_rght: -9.5 - WRTCMP_lat_upr_rght: 55.0 - WRTCMP_dlon: 0.13 - WRTCMP_dlat: 0.13 -# -#----------------------------------------------------------------------- -# -# Emulation of the HAFS v0.A grid at 3 km. -# -#----------------------------------------------------------------------- -# -"GSL_HAFSV0.A_3km": - GRID_GEN_METHOD: "ESGgrid" - ESGgrid_LON_CTR: -62.0 - ESGgrid_LAT_CTR: 22.0 - ESGgrid_DELX: 3000.0 - ESGgrid_DELY: 3000.0 - ESGgrid_NX: 2880 - ESGgrid_NY: 1920 - ESGgrid_PAZI: 0.0 - ESGgrid_WIDE_HALO_WIDTH: 6 - DT_ATMOS: 40 - LAYOUT_X: 32 - LAYOUT_Y: 24 - BLOCKSIZE: 32 - QUILTING: - WRTCMP_write_groups: 1 - WRTCMP_write_tasks_per_group: 32 - WRTCMP_output_grid: "regional_latlon" - WRTCMP_cen_lon: -62.0 - WRTCMP_cen_lat: 25.0 - WRTCMP_lon_lwr_left: -114.5 - WRTCMP_lat_lwr_left: -5.0 - WRTCMP_lon_upr_rght: -9.5 - WRTCMP_lat_upr_rght: 55.0 - WRTCMP_dlon: 0.03 - WRTCMP_dlat: 0.03 -# -#----------------------------------------------------------------------- -# -# 50-km HRRR Alaska grid. -# -#----------------------------------------------------------------------- -# -"GSD_HRRR_AK_50km": - GRID_GEN_METHOD: "ESGgrid" - ESGgrid_LON_CTR: -163.5 - ESGgrid_LAT_CTR: 62.8 - ESGgrid_DELX: 50000.0 - ESGgrid_DELY: 50000.0 - ESGgrid_NX: 74 - ESGgrid_NY: 51 - ESGgrid_PAZI: 0.0 - ESGgrid_WIDE_HALO_WIDTH: 6 - DT_ATMOS: 600 - LAYOUT_X: 2 - LAYOUT_Y: 3 - BLOCKSIZE: 37 - QUILTING: - WRTCMP_write_groups: 1 - WRTCMP_write_tasks_per_group: 1 - WRTCMP_output_grid: "lambert_conformal" - WRTCMP_cen_lon: -163.5 - WRTCMP_cen_lat: 62.8 - WRTCMP_stdlat1: 62.8 - WRTCMP_stdlat2: 62.8 - WRTCMP_nx: 70 - WRTCMP_ny: 45 - WRTCMP_lon_lwr_left: 172.0 - WRTCMP_lat_lwr_left: 49.0 - WRTCMP_dx: 50000.0 - WRTCMP_dy: 50000.0 -# -#----------------------------------------------------------------------- -# # 25-km HRRR grid for testing Online-CMAQ. # #----------------------------------------------------------------------- diff --git a/ush/set_FV3nml_sfc_climo_filenames.py b/ush/set_FV3nml_sfc_climo_filenames.py index bc579151c5..a1ffaa57ef 100644 --- a/ush/set_FV3nml_sfc_climo_filenames.py +++ b/ush/set_FV3nml_sfc_climo_filenames.py @@ -27,7 +27,7 @@ from set_namelist import set_namelist -def set_FV3nml_sfc_climo_filenames(): +def set_FV3nml_sfc_climo_filenames(debug=False): """ This function sets the values of the variables in the forecast model's namelist file that specify the paths to the surface @@ -38,7 +38,7 @@ def set_FV3nml_sfc_climo_filenames(): set by this function are relative or full paths to these links. Args: - None + debug (bool): Enable extra output for debugging Returns: None """ @@ -92,7 +92,7 @@ def set_FV3nml_sfc_climo_filenames(): settings =\n\n""" ) + settings_str, - verbose=VERBOSE, + verbose=debug, ) # Rename the FV3 namelist and call set_namelist @@ -134,6 +134,8 @@ def parse_args(argv): required=True, help="Path to var_defns file.", ) + parser.add_argument('-d', '--debug', action='store_true', + help='Script will be run in debug mode with more verbose output') return parser.parse_args(argv) @@ -143,4 +145,4 @@ def parse_args(argv): cfg = load_shell_config(args.path_to_defns) cfg = flatten_dict(cfg) import_vars(dictionary=cfg) - set_FV3nml_sfc_climo_filenames() + set_FV3nml_sfc_climo_filenames(args.debug) diff --git a/ush/setup.py b/ush/setup.py index 5c34d1d108..56121d16a5 100644 --- a/ush/setup.py +++ b/ush/setup.py @@ -1637,7 +1637,7 @@ def dict_find(user_dict, substring): return expt_config def clean_rocoto_dict(rocotodict): - """Removes any invalid entries from rocoto_dict. Examples of invalid entries are: + """Removes any invalid entries from rocotodict. Examples of invalid entries are: 1. A task dictionary containing no "command" key 2. A metatask dictionary containing no task dictionaries""" diff --git a/ush/valid_param_vals.yaml b/ush/valid_param_vals.yaml index 81eed41853..b838e5b95c 100644 --- a/ush/valid_param_vals.yaml +++ b/ush/valid_param_vals.yaml @@ -19,14 +19,6 @@ valid_vals_PREDEF_GRID_NAME: [ "RRFS_AK_3km", "CONUS_25km_GFDLgrid", "CONUS_3km_GFDLgrid", -"EMC_AK", -"EMC_HI", -"EMC_PR", -"EMC_GU", -"GSL_HAFSV0.A_25km", -"GSL_HAFSV0.A_13km", -"GSL_HAFSV0.A_3km", -"GSD_HRRR_AK_50km", "GSD_HRRR_25km", "AQM_NA_13km", "RRFS_NA_13km",