diff --git a/payu/models/cice.py b/payu/models/cice.py index 0ba13822..8f058117 100644 --- a/payu/models/cice.py +++ b/payu/models/cice.py @@ -45,6 +45,8 @@ def __init__(self, expt, name, config): self.ice_nml_fname = 'cice_in.nml' + self.history_nml_fname = 'ice_history.nml' # only used by payu + self.set_timestep = self.set_local_timestep self.copy_inputs = False @@ -156,6 +158,14 @@ def get_access_ptr_restart_dir(self): def setup(self): super(Cice, self).setup() + # If there is a seperate ice_history.nml, + # update the cice namelist with its contents + history_nml_fpath = os.path.join(self.control_path, + self.history_nml_fname) + if os.path.isfile(history_nml_fpath): + history_nml = f90nml.read(history_nml_fpath) + self.ice_in.patch(history_nml) + setup_nml = self.ice_in['setup_nml'] init_date = datetime.date(year=setup_nml['year_init'], month=1, day=1) @@ -244,9 +254,6 @@ def setup(self): assert(total_runtime % setup_nml['dt'] == 0) setup_nml['istep0'] = int(total_runtime / setup_nml['dt']) - # Force creation of a dump (restart) file at end of run - setup_nml['dump_last'] = True - nml_path = os.path.join(self.work_path, self.ice_nml_fname) self.ice_in.write(nml_path, force=True) diff --git a/payu/models/cice5.py b/payu/models/cice5.py index 0a498b6d..08bac794 100644 --- a/payu/models/cice5.py +++ b/payu/models/cice5.py @@ -53,6 +53,9 @@ def set_local_timestep(self, t_step): self.ice_in.write(ice_in_path, force=True) def setup(self): + # Force creation of a dump (restart) file at end of run + self.ice_in['setup_nml']['dump_last'] = True + super(Cice5, self).setup() # Make log dir diff --git a/test/models/test_cice.py b/test/models/test_cice.py new file mode 100644 index 00000000..13b91a10 --- /dev/null +++ b/test/models/test_cice.py @@ -0,0 +1,144 @@ +import os +import shutil + +import pytest +import f90nml + +import payu + +from test.common import cd +from test.common import tmpdir, ctrldir, labdir, expt_workdir, ctrldir_basename +from test.common import write_config, write_metadata +from test.common import make_inputs, make_exe + +verbose = True + +DEFAULT_CICE_NML = { + "setup_nml": { + "history_dir": "./HISTORY/", + "restart_dir": "./RESTART/", + "year_init": 9999, + "days_per_year": 360, + "ice_ic": "default", + "restart": ".false.", + "pointer_file": "./RESTART/ice.restart_file", + "runtype": "initial", + "npt": 99999, + "dt": 1, + }, + "grid_nml": {"grid_file": "./INPUT/grid.nc", "kmt_file": "./INPUT/kmt.nc"}, + "icefields_nml": {"f_icy": "x"}, +} +CICE_NML_NAME = "cice_in.nml" +HIST_NML_NAME = "ice_history.nml" + + +def setup_module(module): + """ + Put any test-wide setup code in here, e.g. creating test files + """ + if verbose: + print("setup_module module:%s" % module.__name__) + + # Should be taken care of by teardown, in case remnants lying around + try: + shutil.rmtree(tmpdir) + except FileNotFoundError: + pass + + try: + tmpdir.mkdir() + labdir.mkdir() + ctrldir.mkdir() + expt_workdir.mkdir(parents=True) + make_inputs() + make_exe() + write_metadata() + except Exception as e: + print(e) + + config = { + "laboratory": "lab", + "jobname": "testrun", + "model": "cice", + "exe": "test.exe", + "experiment": ctrldir_basename, + "metadata": {"enable": False}, + } + write_config(config) + + +def teardown_module(module): + """ + Put any test-wide teardown code in here, e.g. removing test outputs + """ + if verbose: + print("teardown_module module:%s" % module.__name__) + + try: + shutil.rmtree(tmpdir) + print("removing tmp") + except Exception as e: + print(e) + + +# Confirm that 1: payu overwrites cice_in with ice_history +# 2: payu works without ice_history.nml +# 3: payu overwrites cice_in and allows additional fields +# In all cases confirm dump_last is not added to model_type='cice' +@pytest.mark.parametrize( + "ice_history", + [ + {"icefields_nml": { "f_icy": "m" }}, + False, + {"icefields_nml": {"f_icy": "m", "f_new": "y"}}, + ], +) +def test_setup(ice_history): + cice_nml = DEFAULT_CICE_NML + + # create the files parsed by setup: + # 1. a restart pointer file + with cd(expt_workdir): + os.mkdir(cice_nml["setup_nml"]["restart_dir"]) + with open(cice_nml["setup_nml"]["pointer_file"], "w") as f: + f.write("./RESTART/ice.r") + f.close() + + with cd(ctrldir): + # 2. Create config.nml + f90nml.write(cice_nml, CICE_NML_NAME) + if ice_history: + f90nml.write(ice_history, HIST_NML_NAME) + + lab = payu.laboratory.Laboratory(lab_path=str(labdir)) + expt = payu.experiment.Experiment(lab, reproduce=False) + model = expt.models[0] + + # Function to test + model.setup() + + # Check config files are moved to model's work path + work_path_files = os.listdir(model.work_path) + assert CICE_NML_NAME in work_path_files + + # Check cice_in was patched with ice_history + work_input_fpath = os.path.join(model.work_path, CICE_NML_NAME) + input_nml = f90nml.read(work_input_fpath) + if ice_history: + assert input_nml["icefields_nml"] == ice_history["icefields_nml"] + else: + assert input_nml["icefields_nml"] == DEFAULT_CICE_NML["icefields_nml"] + + # Check dump_last doesn't exist + with pytest.raises(KeyError, match="dump_last"): + input_nml["setup_nml"]["dump_last"] + + # cleanup + with cd(expt_workdir): + os.remove(cice_nml["setup_nml"]["pointer_file"]) + os.rmdir(cice_nml["setup_nml"]["restart_dir"]) + with cd(ctrldir): + os.remove(CICE_NML_NAME) + if ice_history: + os.remove(HIST_NML_NAME)