Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[uwtools_integration] Integrate ics/lbcs #266

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
6bdab4c
initial chgres_cube config
WeirAE Aug 21, 2024
46a3227
update coldstart.yaml
WeirAE Aug 21, 2024
1af2517
second pass on passing files
WeirAE Aug 27, 2024
b7884cc
progress continues adding functionality
WeirAE Sep 4, 2024
b188301
update secondary YAML logic
WeirAE Sep 5, 2024
4753089
first version edits complete
WeirAE Sep 17, 2024
93ac362
config_defaults.yaml formatting fixes
WeirAE Sep 18, 2024
e437b3d
yaml fixes to complete build
WeirAE Sep 18, 2024
bee31be
try some changes in chgres_cube.py
WeirAE Sep 18, 2024
e661d1c
add changes from PR 264
WeirAE Sep 19, 2024
7360ec1
Merge branch 'uwtools_integration' into integrate_ics_lbcs
WeirAE Sep 19, 2024
ed58157
revert unintended changes
WeirAE Sep 19, 2024
8dde45f
also revert utils.py
WeirAE Sep 19, 2024
9f16342
Revert remaining formatting
WeirAE Sep 19, 2024
d6c3786
fix local issues
WeirAE Sep 19, 2024
4eff96a
fix YAML formatting
WeirAE Sep 19, 2024
3b65a6c
Fix remaining YAML syntax issues
WeirAE Sep 19, 2024
7116141
Undo prior incorrect sync and refix YAML
WeirAE Sep 19, 2024
c310cb8
local YAML and path fixes
WeirAE Sep 20, 2024
9a0ab65
progress resolving dereferencing
WeirAE Sep 20, 2024
226d335
fixes for loop logic
WeirAE Sep 25, 2024
8a3ed18
fixes for lbcs
WeirAE Oct 7, 2024
8b7dd87
fix external model yaml issues
WeirAE Oct 7, 2024
2f709e3
Merge remote-tracking branch 'refs/remotes/origin/integrate_ics_lbcs'…
WeirAE Oct 8, 2024
b83c5af
move tracers to external_model_defaults
WeirAE Oct 10, 2024
d9701bf
significant logic changes
WeirAE Oct 15, 2024
fc59204
Fix file copy logic
WeirAE Oct 16, 2024
12fb677
fix output directories
WeirAE Oct 18, 2024
f485be8
All fundamental tests pass
WeirAE Oct 24, 2024
fccb757
fix extra files 1
WeirAE Oct 24, 2024
7bc7732
First attempt to fix erroneous changes
WeirAE Oct 24, 2024
80bca46
remove spurious uwtools directory
WeirAE Oct 24, 2024
4300a3e
Fix missing newline
WeirAE Oct 24, 2024
91e15dd
update cleaner
WeirAE Oct 24, 2024
7d81efb
Merge remote-tracking branch 'refs/remotes/origin/integrate_ics_lbcs'…
WeirAE Oct 24, 2024
25fd2b4
Apply suggestions from code review
WeirAE Oct 25, 2024
1460cff
Merge remote-tracking branch 'gsl/uwtools_integration' into integrate…
WeirAE Oct 29, 2024
0e2f6e0
add back several changes lost in conflict resolutions
WeirAE Oct 29, 2024
093fbf0
additional residual formatting fixes
WeirAE Oct 30, 2024
affa5d4
fixes for running
WeirAE Oct 30, 2024
d74b410
Additional fixes
WeirAE Oct 30, 2024
86db971
move file handling to external_model_defaults.yaml
WeirAE Oct 30, 2024
d9488d9
clean dereferencing, fix file errors
WeirAE Oct 31, 2024
fb398c0
found missing file path
WeirAE Oct 31, 2024
bedeb67
Updates for make_ics/make_lbcs. Fundamental tests pass.
christinaholtNOAA Nov 1, 2024
396a321
Merge pull request #1 from christinaholtNOAA/chgres_cube_changes
WeirAE Nov 1, 2024
9da027b
Apply suggestions from code review
WeirAE Nov 1, 2024
43fedf3
Additional changes from comments
WeirAE Nov 1, 2024
4e55694
WIP.
christinaholtNOAA Nov 1, 2024
ef9f299
Run black.
christinaholtNOAA Nov 1, 2024
da4b988
Updates to scripts.
christinaholtNOAA Nov 4, 2024
e86eb94
Apply black.
christinaholtNOAA Nov 4, 2024
1d28136
Merge pull request #2 from christinaholtNOAA/update_chgres
WeirAE Nov 4, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions parm/wflow/coldstart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,16 @@ metatask_run_ensemble:
mem: '{% if global.DO_ENSEMBLE %}{%- for m in range(1, global.NUM_ENS_MEMBERS+1) -%}{{ "%03d "%m }}{%- endfor -%} {% else %}{{ "000"|string }}{% endif %}'
task_make_ics_mem#mem#:
<<: *default_task
command: '&LOAD_MODULES_RUN_TASK; "make_ics" "&JOBSdir;/JREGIONAL_MAKE_ICS"'
command:
cyclestr:
value: 'source &USHdir;/load_modules_wflow.sh {{ user.MACHINE }} ; &SCRIPTSdir;/chgres_cube.py
christinaholtNOAA marked this conversation as resolved.
Show resolved Hide resolved
-c &GLOBAL_VAR_DEFNS_FP;
--cycle @Y-@m-@dT@H:@M:@S
--key-path task_make_ics
--mem #mem#'
join:
cyclestr:
value: '&LOGDIR;/{{ jobname }}_@Y@m@d@H&LOGEXT;'
envars:
<<: *default_vars
SLASH_ENSMEM_SUBDIR: '&SLASH_ENSMEM_SUBDIR;'
Expand Down Expand Up @@ -144,7 +153,16 @@ metatask_run_ensemble:

task_make_lbcs_mem#mem#:
<<: *default_task
command: '&LOAD_MODULES_RUN_TASK; "make_lbcs" "&JOBSdir;/JREGIONAL_MAKE_LBCS"'
command:
cyclestr:
value: 'source &USHdir;/load_modules_wflow.sh {{ user.MACHINE }} ; &SCRIPTSdir;/chgres_cube.py
-c &GLOBAL_VAR_DEFNS_FP;
--cycle @Y-@m-@dT@H:@M:@S
--key-path task_make_lbcs
--mem #mem#'
join:
cyclestr:
value: '&LOGDIR;/{{ jobname }}_@Y@m@d@H&LOGEXT;'
envars:
<<: *default_vars
SLASH_ENSMEM_SUBDIR: '&SLASH_ENSMEM_SUBDIR;'
Expand Down
2 changes: 1 addition & 1 deletion parm/wflow/post.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ metatask_run_ens_post:
maxtries: '2'
command:
cyclestr:
value: 'source &USHdir;/load_modules_wflow.sh hera ; &SCRIPTSdir;/upp.py
value: 'source &USHdir;/load_modules_wflow.sh {{ user.MACHINE }} ; &SCRIPTSdir;/upp.py
-c &GLOBAL_VAR_DEFNS_FP;
--cycle @Y-@m-@dT@H:@M:@S
--leadtime #fhr#:00:00
Expand Down
237 changes: 237 additions & 0 deletions scripts/chgres_cube.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
#!/usr/bin/env python
WeirAE marked this conversation as resolved.
Show resolved Hide resolved
"""
The run script for chgres_cube for both initial and lateral boundary conditions.
"""

import datetime as dt
import logging
import os
import sys
from argparse import ArgumentParser
from copy import deepcopy
from pathlib import Path

from uwtools.api.chgres_cube import ChgresCube
from uwtools.api.config import get_yaml_config
from uwtools.api.fs import copy as uwcopy
from uwtools.api.logging import use_uwtools_logger


def _deliver_files(config, dst_dir, key_path, src_dir):
"""
Deliver files defined in the config "outuput_file_links" section.
"""
dst_dir.mkdir(exist_ok=True)
output_links = _walk_key_path(config, key_path + ["output_file_links"])
output_links = {k: str(src_dir / v) for k, v in output_links.items()}
if not uwcopy(target_dir=dst_dir, config=output_links):
logging.error("Files could not be copied to their final destination.")
sys.exit(1)


def _get_external_fns(config, cycle, key_path):
"""
Return external model file names and forecast hours for the given task in the experiment.

They come from the metadata file written by the prior data retrival task.
"""
config_cp = get_yaml_config(deepcopy(config.data))
config_cp.dereference(
context={
**config_cp,
**os.environ,
"cycle": cycle,
}
)
varsfilepath = _walk_key_path(config_cp, key_path)["input_files_metadata_path"]
external_config = get_yaml_config(varsfilepath)
external_config_fns = external_config["external_model_fns"]
external_config_fhrs = external_config["external_model_fhrs"]
return external_config_fhrs, external_config_fns


def _is_grib2(config, key_path):
"""
Is the input in grib2 format?
"""
return (
_walk_key_path(
config,
key_path + ["chgres_cube", "namelist", "update_values", "config"],
).get("input_type")
== "grib2"
)


def _walk_key_path(config, key_path):
"""
Navigate to the sub-config at the end of the path of given keys.
"""
keys = []
pathstr = "<unknown>"
for key in key_path:
keys.append(key)
pathstr = " -> ".join(keys)
try:
subconfig = config[key]
except KeyError:
logging.error(f"Bad config path: {pathstr}")
raise
if not isinstance(subconfig, dict):
logging.error(f"Value at {pathstr} must be a dictionary")
sys.exit(1)
config = subconfig
return config


def parse_args(argv):
"""
Parse arguments for the script.
"""
parser = ArgumentParser(
description="Script that runs chgres_cube via uwtools API for SRW",
)
parser.add_argument(
"-c",
"--config-file",
metavar="PATH",
required=True,
help="Path to experiment config file.",
type=Path,
)
parser.add_argument(
"--cycle",
help="The cycle in ISO8601 format (e.g. 2024-07-15T18).",
required=True,
type=dt.datetime.fromisoformat,
)
parser.add_argument(
"--key-path",
help="Dot-separated path of keys leading through the config to the driver's YAML block.",
metavar="KEY[.KEY...]",
required=True,
type=lambda s: s.split("."),
)
parser.add_argument(
"--member",
default="000",
help="The 3-digit ensemble member number.",
)
return parser.parse_args(argv)


def run_chgres_cube(config_file, cycle, key_path, member):
"""
Setup and run the chgres_cube UW Driver.
"""
expt_config = get_yaml_config(config_file)

# The experiment config will have {{ 'CRES' | env }} expressions in it that need to be
# dereferenced during driver initialization.
os.environ["CRES"] = expt_config["workflow"]["CRES"]
os.environ["MEMBER"] = member

ext_fhrs, ext_fns = _get_external_fns(expt_config, cycle, key_path)
grib2_input = _is_grib2(expt_config, key_path)
if "task_make_ics" in key_path:
if grib2_input:
os.environ["fn_grib2"] = ext_fns[0]
else:
os.environ["fn_atm"] = ext_fns[0]
os.environ["fn_sfc"] = ext_fns[1]

driver = run_driver(
ChgresCube, config_file, cycle, key_path, leadtime=dt.timedelta(hours=0)
)
rundir = Path(driver.config["rundir"])

# Deliver output data to the forecast's INPUT dir.
delivery_dir = rundir.parent / "INPUT"
expt_config_cp = get_yaml_config(deepcopy(expt_config.data))
expt_config_cp.dereference(
context={
**expt_config_cp,
**os.environ,
"cycle": cycle,
}
)
_deliver_files(
config=expt_config_cp,
dst_dir=delivery_dir,
key_path=key_path,
src_dir=rundir,
)

else: # Loop over make_lbcs tasks.
# This loop will need a version of the config that is not dereferenced.
expt_config = get_yaml_config(config_file)
for external_fhr, external_fn in list(zip(ext_fhrs, ext_fns)):
os.environ["fn_grib2" if grib2_input else "fn_atm"] = external_fn

# Determine lead time and run the driver
lbc_offset_fhrs = _walk_key_path(
expt_config, ["task_get_extrn_lbcs", "envvars"]
)["EXTRN_MDL_LBCS_OFFSET_HRS"]
leadtime = dt.timedelta(hours=int(external_fhr) - int(lbc_offset_fhrs))
driver = run_driver(
ChgresCube, config_file, cycle, key_path, leadtime=leadtime
)
rundir = Path(driver.config["rundir"])

# Use a copy of the original here to avoid opening the file every time.
expt_config_cp = get_yaml_config(deepcopy(expt_config.data))

# This dereferencing must be inside loop bc the fcst hour is set differently each time.
expt_config_cp.dereference(
context={
**expt_config_cp,
**os.environ,
"cycle": cycle,
"leadtime": leadtime,
}
)
# Deliver output data to the forecast's INPUT dir.
delivery_dir = rundir.parent / "INPUT"
_deliver_files(
config=expt_config_cp,
dst_dir=delivery_dir,
key_path=key_path,
src_dir=rundir,
)


def run_driver(driver_obj, config_file, cycle, key_path, leadtime):
"""
Initialize and run the provided UW driver.

Return the configured object.
"""
driver = driver_obj(
config=config_file,
cycle=cycle,
key_path=key_path,
leadtime=leadtime,
)
rundir = Path(driver.config["rundir"])
logging.info(f"Will run {driver.driver_name()} in {rundir}")
driver.run()

if not (rundir / f"runscript.{driver.driver_name()}.done").is_file():
logging.error(
f"Error occurred running {driver.driver_name()}. Please see component error logs."
)
sys.exit(1)
return driver


if __name__ == "__main__":

use_uwtools_logger()

args = parse_args(sys.argv[1:])
run_chgres_cube(
config_file=args.config_file,
cycle=args.cycle,
key_path=args.key_path,
member=args.member,
)
4 changes: 2 additions & 2 deletions scripts/exregional_get_extrn_mdl_files.sh
Original file line number Diff line number Diff line change
Expand Up @@ -240,9 +240,9 @@ fi
mkdir -p ${EXTRN_MDL_STAGING_DIR}

if [ $RUN_ENVIR = "nco" ]; then
EXTRN_DEFNS="${NET}.${cycle}.${EXTRN_MDL_NAME}.${ICS_OR_LBCS}.${EXTRN_MDL_VAR_DEFNS_FN}.sh"
EXTRN_DEFNS="${NET}.${cycle}.${EXTRN_MDL_NAME}.${ICS_OR_LBCS}.${EXTRN_MDL_VAR_DEFNS_FN}.yaml"
else
EXTRN_DEFNS="${EXTRN_MDL_VAR_DEFNS_FN}.sh"
EXTRN_DEFNS="${EXTRN_MDL_VAR_DEFNS_FN}.yaml"
fi
cmd="
python3 -u ${USHdir}/retrieve_data.py \
Expand Down
43 changes: 43 additions & 0 deletions ush/ccpp_suites_defaults.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
chgres_cube_gsd_defaults: &chgres_cube_gsd_defaults
namelist:
update_values:
config:
varmap_file: "{{ user.PARMdir }}/ufs_utils/varmap_tables/GSDphys_var_map.txt"

orog_gsl_defaults: &orog_gsl_defaults
config:
Expand All @@ -19,18 +24,56 @@ orog_gsl_defaults: &orog_gsl_defaults
rundir: "{{ task_make_orog.rundir }}/orog_gsl"

FV3_RAP:
task_make_ics:
chgres_cube:
<<: *chgres_cube_gsd_defaults
task_make_lbcs:
chgres_cube:
<<: *chgres_cube_gsd_defaults
task_make_orog:
orog_gsl:
<<: *orog_gsl_defaults
FV3_HRRR:
task_make_ics:
chgres_cube:
<<: *chgres_cube_gsd_defaults
task_make_lbcs:
chgres_cube:
<<: *chgres_cube_gsd_defaults
task_make_orog:
orog_gsl:
<<: *orog_gsl_defaults
FV3_WoFS_v0:
task_make_ics:
chgres_cube:
<<: *chgres_cube_gsd_defaults
task_make_lbcs:
chgres_cube:
<<: *chgres_cube_gsd_defaults
FV3_RRFS_v1beta:
task_make_ics:
chgres_cube:
<<: *chgres_cube_gsd_defaults
task_make_lbcs:
chgres_cube:
<<: *chgres_cube_gsd_defaults
FV3_GFS_v15_thompson_mynn_lam3km:
task_make_ics:
chgres_cube:
<<: *chgres_cube_gsd_defaults
task_make_lbcs:
chgres_cube:
<<: *chgres_cube_gsd_defaults
task_make_orog:
orog_gsl:
<<: *orog_gsl_defaults
FV3_GFS_v17_p8:
task_make_ics:
chgres_cube:
<<: *chgres_cube_gsd_defaults
task_make_lbcs:
chgres_cube:
<<: *chgres_cube_gsd_defaults
task_make_orog:
orog_gsl:
<<: *orog_gsl_defaults
Loading