Skip to content

Commit

Permalink
MITgcm: Support changing model time step when non-integer divisor (#266)
Browse files Browse the repository at this point in the history
MITgcm: Added logic branch to support changing model time step
when new timestep is not a divisor of current runtime. Does so
by changing basetime.

Added test.
  • Loading branch information
aidanheerdegen committed May 18, 2020
1 parent 682d6ac commit 70a3ce9
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 8 deletions.
23 changes: 15 additions & 8 deletions payu/models/mitgcm.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ def setup(self):
except KeyError:
dt = float(data_nml['parm03']['deltatmom'])

# Basetime defaults to zero
basetime = 0.

# Runtime is set either by timesteps (ntimesteps) or physical
# time (startTime and endTime).
t_start = data_nml['parm03'].get('starttime', None)
Expand Down Expand Up @@ -130,7 +133,7 @@ def setup(self):
# Look for a restart file from a previous run
if os.path.exists(restart_calendar_path):
with open(restart_calendar_path, 'r') as restart_file:
restart_info = yaml.load(restart_file)
restart_info = yaml.safe_load(restart_file)
t_start = float(restart_info['endtime'])
else:
# Use same logic as MITgcm and assume
Expand All @@ -148,10 +151,11 @@ def setup(self):
n_iter0 = round(t_start / dt)

if n_iter0 * dt != t_start:
mesg = ('payu : error: Timestep changed to {dt}. New timestep '
'not integer multiple of start time: '
'{start}'.format(dt=dt, start=t_start))
sys.exit(mesg)
# Modify basetime.
# TODO: Change logic entirely to using
# this conceptually much simpler approach
basetime = t_start
n_iter0 = 0

if n_iter0 + n_timesteps == n_iter0_previous:
mesg = ('payu : error: Timestep changed to {dt}. '
Expand All @@ -163,21 +167,24 @@ def setup(self):
t_end = t_start + dt * n_timesteps
pchkpt_freq = t_end - t_start

print(' base time: {}'.format(basetime))
print(' start time: {}'.format(t_start))
print(' end time: {}'.format(t_end))
print(' niter0 : {}'.format(n_iter0))
print(' ntimesteps: {}'.format(n_timesteps))
print(' dt: {}'.format(dt))
print(' end - start: {}'.format(pchkpt_freq))
print(' dt * ntimeteps: {}'.format(dt * n_timesteps))
print(' end - start: {}'.format(pchkpt_freq))
print(' dt * ntimesteps: {}'.format(dt * n_timesteps))
if pchkpt_freq != dt * n_timesteps:
print('payu : error : time inconsistencies, '
'pchkptfreq != experiment length')
'pchkptfreq ({}) != experiment length ({})'
''.format(pchkpt_freq, dt * n_timesteps))
sys.exit(1)

data_nml['parm03']['startTime'] = t_start
data_nml['parm03']['niter0'] = n_iter0
data_nml['parm03']['endTime'] = t_end
data_nml['parm03']['baseTime'] = basetime

# NOTE: Consider permitting pchkpt_freq < dt * n_timesteps
if t_end % pchkpt_freq != 0:
Expand Down
35 changes: 35 additions & 0 deletions test/models/test_mitgcm.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,3 +333,38 @@ def test_setup_change_deltat():
with pytest.raises(SystemExit, match=matchstr) as setup_error:
payu_setup(lab_path=str(labdir))
assert setup_error.type == SystemExit

# deltaT which is not a divisor. Set ntimesteps instead of
# start and end times
data['parm03']['deltat'] = 999.
data['parm03']['ntimesteps'] = 5.
del data['parm03']['starttime']
del data['parm03']['endtime']

make_config_files()

payu_setup(lab_path=str(labdir))

data_local = f90nml.read(workdir/'data')

# Time step has halved, so nIter0 is doubled
assert data_local['parm03']['nIter0'] == 0
assert data_local['parm03']['deltaT'] == 999.
assert data_local['parm03']['basetime'] == 12000.
assert data_local['parm03']['starttime'] == 12000.
assert data_local['parm03']['endtime'] == 16995.
assert data_local['parm03']['pickupsuff'] == '0000000010'

# Make same number of timesteps as previous, which should throw
# an error
data['parm03']['ntimesteps'] = 10.

make_config_files()

# This should throw an error, as it would overwrite the existing
# pickup files in the work directory, as the nIter is the same
# matchstr = '.*not integer multiple.*'
matchstr = '.*Timestep at end identical to previous pickups.*'
with pytest.raises(SystemExit, match=matchstr) as setup_error:
payu_setup(lab_path=str(labdir))
assert setup_error.type == SystemExit

0 comments on commit 70a3ce9

Please sign in to comment.