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

Fix date-based restart pruning breaking on empty restart dirs #376

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions payu/experiment.py
Original file line number Diff line number Diff line change
Expand Up @@ -1050,6 +1050,10 @@ def get_restarts_to_prune(self,
'model. To use integer based restart pruning, '
'set restart_freq to an integer value.')
raise
except FileNotFoundError as e:
print(f'payu: warning: Ignoring {restart} from date-based '
f'restart pruning. Error: {e}')
continue
except Exception:
aidanheerdegen marked this conversation as resolved.
Show resolved Hide resolved
print('payu: error: Error parsing restart directory ',
f'{restart} for a datetime to prune restarts.')
Expand Down
30 changes: 0 additions & 30 deletions payu/models/fms.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
from itertools import count
import fnmatch

import cftime

from payu.models.model import Model
from payu import envmod
from payu.fsops import required_libs
Expand Down Expand Up @@ -255,31 +253,3 @@ def archive(self, **kwargs):

def collate(self):
fms_collate(self)

def get_restart_datetime(self, restart_path):
"""Given a restart path, parse the restart files and
return a cftime datetime (for date-based restart pruning)"""
# Check for ocean_solo.res file
ocean_solo_path = os.path.join(restart_path, 'ocean_solo.res')
if not os.path.exists(ocean_solo_path):
raise NotImplementedError(
'Cannot find ocean_solo.res file, which is required for '
'date-based restart pruning')

with open(ocean_solo_path, 'r') as ocean_solo:
lines = ocean_solo.readlines()

calendar_int = int(lines[0].split()[0])
cftime_calendars = {
1: "360_day",
2: "julian",
3: "proleptic_gregorian",
4: "noleap"
}
calendar = cftime_calendars[calendar_int]

last_date_line = lines[-1].split()
date_values = [int(i) for i in last_date_line[:6]]
year, month, day, hour, minute, second = date_values
return cftime.datetime(year, month, day, hour, minute, second,
calendar=calendar)
3 changes: 2 additions & 1 deletion payu/models/mom.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@
import f90nml

from payu.models.fms import Fms
from payu.models.mom_mixin import MomMixin
from payu.fsops import mkdir_p, make_symlink


class Mom(Fms):
class Mom(MomMixin, Fms):

def __init__(self, expt, name, config):

Expand Down
3 changes: 2 additions & 1 deletion payu/models/mom6.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

# Local
from payu.models.fms import Fms
from payu.models.mom_mixin import MomMixin


def mom6_add_parameter_files(model):
Expand All @@ -42,7 +43,7 @@ def mom6_add_parameter_files(model):
model.config_files.extend(filenames)


class Mom6(Fms):
class Mom6(MomMixin, Fms):
"""Interface to GFDL's MOM6 ocean model."""

def __init__(self, expt, name, config):
Expand Down
40 changes: 40 additions & 0 deletions payu/models/mom_mixin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"""Mixin class for MOM and MOM6 drivers

:copyright: Copyright 2011 Marshall Ward, see AUTHORS for details
:license: Apache License, Version 2.0, see LICENSE for details
"""

import os

import cftime


class MomMixin:

def get_restart_datetime(self, restart_path):
"""Given a restart path, parse the restart files and
return a cftime datetime (for date-based restart pruning)"""
# Check for ocean_solo.res file
ocean_solo_path = os.path.join(restart_path, 'ocean_solo.res')
if not os.path.exists(ocean_solo_path):
raise FileNotFoundError(
'Cannot find ocean_solo.res file, which is required for '
'date-based restart pruning')

with open(ocean_solo_path, 'r') as ocean_solo:
lines = ocean_solo.readlines()

calendar_int = int(lines[0].split()[0])
cftime_calendars = {
1: "360_day",
2: "julian",
3: "proleptic_gregorian",
4: "noleap"
}
calendar = cftime_calendars[calendar_int]

last_date_line = lines[-1].split()
date_values = [int(i) for i in last_date_line[:6]]
year, month, day, hour, minute, second = date_values
return cftime.datetime(year, month, day, hour, minute, second,
calendar=calendar)
File renamed without changes.
39 changes: 37 additions & 2 deletions test/test_prune_restarts.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
from test.common import config as config_orig
from test.common import write_config
from test.common import make_all_files
from test.common import remove_expt_archive_dirs
from test.models.test_mom import make_ocean_restart_dir
from test.common import remove_expt_archive_dirs, make_expt_archive_dir
from test.models.test_mom_mixin import make_ocean_restart_dir

verbose = True

Expand Down Expand Up @@ -222,3 +222,38 @@ def test_prune_restarts(restarts,
]

assert restarts_to_prune_indices == expected_restart_indices


def test_prune_restarts_ignores_empty_restart_dirs():
# Test that in date-based restart pruning ignores any empty restart dirs

write_test_config(restart_freq='1YS')

# Create restart files
restart_datetimes = [(4, "1903-01-01 00:00:00"),
(5, "1903-06-01 00:00:00"),
(6, "1905-01-01 00:00:00")]
for index, datetime in restart_datetimes:
make_ocean_restart_dir(start_dt="1900-01-01 00:00:00",
run_dt=datetime,
calendar=4,
restart_index=index,
additional_path='ocean')

# Create empty restart dirs
make_expt_archive_dir(type='restart', index=0)
make_expt_archive_dir(type='restart', index=2)

with cd(ctrldir):
lab = payu.laboratory.Laboratory(lab_path=str(labdir))
expt = payu.experiment.Experiment(lab, reproduce=False)

# Function to test
restarts_to_prune = expt.get_restarts_to_prune()
jo-basevi marked this conversation as resolved.
Show resolved Hide resolved

# Extract out index
restarts_to_prune_indices = [
int(restart.lstrip('restart')) for restart in restarts_to_prune
]

assert restarts_to_prune_indices == [5]