-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add workflow to run model with mean nudging tendency (#215)
* Add workflow runfile, configs, Makefile * Update runtime module * Fix fv3net runtime __init__ * Pin pandas in prognostic run to 1.0.1 * Update runfile and Makefile * Update experiment names in configs * Update Makefile * Remove workflow submit_job.py * Refactor nudge file handling to kube_jobs * Add tests for nudge file handling * Use common transfer_local_to_remote function * Add type hints to nudge_to_obs.py * Lint * Update configurations and Makefile to enable remote runs * Remove leftover debugging logging statement * Use common unique_tag() function * Change outdirs in Makefile * Update rule name in Makefile * Change run length to 91 days * Make layout 2,2 for nudge_mean_T * Make runfile work for multiple procs per tile * Add prepare_config.py script to simplify submission * Add get_fs and get_protocol to vcm.cloud.__init__.py * Fix Makefile * Make sure absolute paths are used for config_url * Update runfile for n_proc>6 * Set layout=2,2 in config * Rename dimensions as well * Load all timesteps of nudging data * Add submit_to_kubernetes script * Refactor runfile * Update scripts to allow local and remote runs * Make run length 91 days * Make flush_nc_files=True in namelist * Change nudging tendency year to model year instead of reverse * Update diagnostic to zarr pipeline * Add post-processing script * Lint * Add GFS analysis data to catalog.yml * Add back runtime get_runfile_config function * Add docstring * Add README.md * Add get_runfile_config back to runtime __init__ * Update postprocessing script * Address Jeremy PR comments * Rename nudging_tendency to mean_nudging_tendency * Update fv3config submdule to v0.3.1 * Use fv3config get_timestep and config_from_yaml * Address Noah PR comments * Update HISTORY.rst and workflow readme * Fix typo * Add quotes to filename_pattern in nudge config yamls * Update length of runs
- Loading branch information
Oliver Watt-Meyer
authored
Apr 9, 2020
1 parent
712603c
commit 541ae51
Showing
28 changed files
with
665 additions
and
95 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
FROM us.gcr.io/vcm-ml/fv3gfs-python:v0.4.0 | ||
|
||
|
||
COPY docker/learned_nudging_run/requirements.txt /tmp/requirements.txt | ||
RUN pip3 install -r /tmp/requirements.txt | ||
|
||
# cache external package installation | ||
COPY external/fv3config /fv3net/external/fv3config | ||
COPY external/vcm /fv3net/external/vcm | ||
RUN pip3 install -e /fv3net/external/vcm -e /fv3net/external/fv3config | ||
|
||
COPY . /fv3net | ||
RUN pip3 install --no-deps -e /fv3net |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
scikit-learn==0.22.1 | ||
dask | ||
zarr | ||
scikit-image | ||
google-cloud-logging | ||
pandas==1.0.1 |
Submodule fv3config
updated
from d41cf2 to f9087b
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
from .fsspec import get_fs | ||
from .fsspec import get_fs, get_protocol | ||
|
||
|
||
__all__ = [item for item in dir() if not item.startswith("_")] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,3 +5,4 @@ | |
update_nested_dict, | ||
get_base_fv3config, | ||
) | ||
from .nudge_to_obs import update_config_for_nudging |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
from datetime import datetime, timedelta | ||
import os | ||
import numpy as np | ||
from typing import List, Mapping | ||
|
||
import fsspec | ||
import fv3config | ||
|
||
|
||
# this module assumes that analysis files are at 00Z, 06Z, 12Z and 18Z | ||
SECONDS_IN_HOUR = 60 * 60 | ||
NUDGE_HOURS = np.array([0, 6, 12, 18]) # hours at which analysis data is available | ||
NUDGE_FILE_TARGET = "INPUT" # where to put analysis files in rundir | ||
|
||
|
||
def _most_recent_nudge_time(start_time: datetime) -> datetime: | ||
"""Return datetime object for the last nudging time preceding or concurrent | ||
with start_time""" | ||
first_nudge_hour = _most_recent_hour(start_time.hour) | ||
return datetime(start_time.year, start_time.month, start_time.day, first_nudge_hour) | ||
|
||
|
||
def _most_recent_hour(current_hour, hour_array=NUDGE_HOURS) -> int: | ||
"""Return latest hour in hour_array that precedes or is concurrent with | ||
current_hour""" | ||
first_nudge_hour = hour_array[np.argmax(hour_array > current_hour) - 1] | ||
return first_nudge_hour | ||
|
||
|
||
def _get_nudge_time_list(config: Mapping) -> List[datetime]: | ||
"""Return list of datetime objects corresponding to times at which analysis files | ||
are required for nudging for a given model run configuration""" | ||
current_date = config["namelist"]["coupler_nml"]["current_date"] | ||
start_time = datetime(*current_date) | ||
first_nudge_time = _most_recent_nudge_time(start_time) | ||
run_duration = fv3config.get_run_duration(config) | ||
nudge_duration = run_duration + (start_time - first_nudge_time) | ||
nudge_duration_hours = int( | ||
np.ceil(nudge_duration.total_seconds() / SECONDS_IN_HOUR) | ||
) | ||
nudge_interval = NUDGE_HOURS[1] - NUDGE_HOURS[0] | ||
nudging_hours = range(0, nudge_duration_hours + nudge_interval, nudge_interval) | ||
return [first_nudge_time + timedelta(hours=hour) for hour in nudging_hours] | ||
|
||
|
||
def _get_nudge_filename_list(config: Mapping) -> List[str]: | ||
"""Return list of filenames of all nudging files required""" | ||
nudge_filename_pattern = config["gfs_analysis_data"]["filename_pattern"] | ||
time_list = _get_nudge_time_list(config) | ||
return [time.strftime(nudge_filename_pattern) for time in time_list] | ||
|
||
|
||
def _get_nudge_files_asset_list(config: Mapping) -> List[Mapping]: | ||
"""Return list of fv3config assets for all nudging files required for a given | ||
model run configuration""" | ||
nudge_url = config["gfs_analysis_data"]["url"] | ||
return [ | ||
fv3config.get_asset_dict(nudge_url, file, target_location=NUDGE_FILE_TARGET) | ||
for file in _get_nudge_filename_list(config) | ||
] | ||
|
||
|
||
def _get_nudge_files_description_asset(config: Mapping, config_url: str) -> Mapping: | ||
"""Return an fv3config asset pointing to the text file that the | ||
model requires to describe the list of nudging files.""" | ||
fname_list_filename = config["namelist"]["fv_nwp_nudge_nml"]["input_fname_list"] | ||
return fv3config.get_asset_dict(config_url, fname_list_filename) | ||
|
||
|
||
def _write_nudge_files_description(config: Mapping, url: str): | ||
"""Write a text file with list of all nudging files (which the | ||
model requires to know what the nudging files are called).""" | ||
fname_list_contents = "\n".join(_get_nudge_filename_list(config)) | ||
with fsspec.open(url, "w") as f: | ||
f.write(fname_list_contents) | ||
|
||
|
||
def update_config_for_nudging(config: Mapping, config_url: str) -> Mapping: | ||
"""Add assets to config for all nudging files and for the text file listing | ||
nudging files. This text file will be written to config_url. | ||
Args: | ||
config: an fv3config configuration dictionary | ||
config_url: path where text file describing nudging files will be written. | ||
File will be written to {config_url}/{input_fname_list} where | ||
input_fname_list is a namelist parameter in the fv_nwp_nudge_nml namelist | ||
of config. | ||
Returns: | ||
config dict updated to include all required nudging files | ||
""" | ||
nudge_files_description = _get_nudge_files_description_asset(config, config_url) | ||
nudge_files_description_url = os.path.join( | ||
nudge_files_description["source_location"], | ||
nudge_files_description["source_name"], | ||
) | ||
_write_nudge_files_description(config, nudge_files_description_url) | ||
if "patch_files" not in config: | ||
config["patch_files"] = [] | ||
config["patch_files"].append(nudge_files_description) | ||
config["patch_files"].extend(_get_nudge_files_asset_list(config)) | ||
return config |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
from . import sklearn_interface as sklearn | ||
from .state_io import init_writers, append_to_writers, CF_TO_RESTART_MAP | ||
from .config import get_runfile_config, get_namelist | ||
from .config import get_runfile_config, get_config, get_namelist |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import pytest | ||
from datetime import datetime | ||
|
||
from fv3net.pipelines.kube_jobs import nudge_to_obs | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"start_time, expected", | ||
[ | ||
(datetime(2016, 1, 1), datetime(2016, 1, 1, 0)), | ||
(datetime(2016, 1, 1, 1), datetime(2016, 1, 1, 0)), | ||
(datetime(2016, 1, 1, 7), datetime(2016, 1, 1, 6)), | ||
(datetime(2016, 1, 1, 12), datetime(2016, 1, 1, 12)), | ||
(datetime(2016, 1, 2, 18, 1), datetime(2016, 1, 2, 18)), | ||
], | ||
) | ||
def test__get_first_nudge_file_time(start_time, expected): | ||
assert nudge_to_obs._most_recent_nudge_time(start_time) == expected | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"coupler_nml, expected_length, expected_first_datetime, expected_last_datetime", | ||
[ | ||
( | ||
{"current_date": [2016, 1, 1, 0, 0, 0], "days": 1}, | ||
4 + 1, | ||
datetime(2016, 1, 1), | ||
datetime(2016, 1, 2), | ||
), | ||
( | ||
{"current_date": [2016, 1, 1, 0, 0, 0], "days": 1, "hours": 5}, | ||
4 + 1 + 1, | ||
datetime(2016, 1, 1), | ||
datetime(2016, 1, 2, 6), | ||
), | ||
( | ||
{"current_date": [2016, 1, 1, 0, 0, 0], "days": 1, "hours": 7}, | ||
4 + 2 + 1, | ||
datetime(2016, 1, 1), | ||
datetime(2016, 1, 2, 12), | ||
), | ||
( | ||
{"current_date": [2016, 1, 2, 1, 0, 0], "days": 1}, | ||
4 + 2, | ||
datetime(2016, 1, 2), | ||
datetime(2016, 1, 3, 6), | ||
), | ||
], | ||
) | ||
def test__get_nudge_time_list( | ||
coupler_nml, expected_length, expected_first_datetime, expected_last_datetime | ||
): | ||
config = {"namelist": {"coupler_nml": coupler_nml}} | ||
nudge_file_list = nudge_to_obs._get_nudge_time_list(config) | ||
assert len(nudge_file_list) == expected_length | ||
assert nudge_file_list[0] == expected_first_datetime | ||
assert nudge_file_list[-1] == expected_last_datetime |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
IMAGE = us.gcr.io/vcm-ml/learned_nudging_run:v0.1.1 | ||
RUNFILE = mean_nudging_runfile.py | ||
TEMPLATE = fv3config_template.yml | ||
LOCAL_OUTDIR = rundir/nudge_mean_$* | ||
LOCAL_CONFIGDIR = $(LOCAL_OUTDIR)/config | ||
LOCAL_FV3CONFIG = $(LOCAL_CONFIGDIR)/fv3config.yml | ||
GCS_OUTDIR = gs://vcm-ml-data/2020-03-30-learned-nudging-FV3GFS-runs/nudge_mean_$* | ||
GCS_CONFIGDIR = $(GCS_OUTDIR)/config | ||
GCS_FV3CONFIG = $(GCS_CONFIGDIR)/fv3config.yml | ||
|
||
run_all_remote: run_remote_T run_remote_T_ps run_remote_T_ps_u_v | ||
|
||
run_remote_%: prepare_remote_% | ||
python submit_job.py --dockerimage $(IMAGE) --runfile $(RUNFILE) $(GCS_FV3CONFIG) $(GCS_OUTDIR) | ||
|
||
run_local_%: prepare_local_% | ||
fv3run --dockerimage $(IMAGE) --runfile $(RUNFILE) $(LOCAL_FV3CONFIG) $(LOCAL_OUTDIR) | ||
|
||
prepare_remote_%: | ||
python prepare_config.py $(TEMPLATE) $* $(GCS_CONFIGDIR) | ||
|
||
prepare_local_%: | ||
python prepare_config.py $(TEMPLATE) $* $(LOCAL_CONFIGDIR) | ||
|
||
clean: | ||
rm -rf rundir configdir | ||
|
||
.PHONY: run_all_remote |
Oops, something went wrong.