diff --git a/MOM6 b/MOM6 index c37361e..8e5ae29 160000 --- a/MOM6 +++ b/MOM6 @@ -1 +1 @@ -Subproject commit c37361ed68c2367c364db1e4d8238aca4e0c6349 +Subproject commit 8e5ae29312df6867b9f301887f55b628d498140e diff --git a/cime_config/testdefs/testlist_mom.xml b/cime_config/testdefs/testlist_mom.xml index 22a7f80..2d3b54e 100644 --- a/cime_config/testdefs/testlist_mom.xml +++ b/cime_config/testdefs/testlist_mom.xml @@ -298,4 +298,22 @@ + + + + + + + + + + + + + + + + + + diff --git a/param_templates/MOM_input.yaml b/param_templates/MOM_input.yaml index 04b15f8..c170715 100644 --- a/param_templates/MOM_input.yaml +++ b/param_templates/MOM_input.yaml @@ -3940,6 +3940,13 @@ Global: $OCN_GRID in ["tx2_3v2", "tx2_3v3"] and $TEST: = - ( - $NTASKS_OCN // 256) $OCN_GRID == "tx2_0v1" and $TEST: = - ( - $NTASKS_OCN // 256) $OCN_GRID == "tx0.25v1": = - ( - $NTASKS_OCN // 128) + MASKTABLE: + description: | + A text file to specify n_mask, layout and mask_list. + datatype: string + value: + $AUTO_MASKTABLE: = f'MOM_auto_mask_table{$INST_SUFFIX}' + else: MOM_mask_table GEOM_FILE: description: | default = ocean_geometry.nc diff --git a/param_templates/json/MOM_input.json b/param_templates/json/MOM_input.json index fb2e128..524631c 100644 --- a/param_templates/json/MOM_input.json +++ b/param_templates/json/MOM_input.json @@ -3255,6 +3255,14 @@ "$OCN_GRID == \"tx0.25v1\"": "= - ( - $NTASKS_OCN // 128)" } }, + "MASKTABLE": { + "description": "A text file to specify n_mask, layout and mask_list.\n", + "datatype": "string", + "value": { + "$AUTO_MASKTABLE": "= f'MOM_auto_mask_table{$INST_SUFFIX}'", + "else": "MOM_mask_table" + } + }, "GEOM_FILE": { "description": "default = ocean_geometry.nc\nThe file into which to write the ocean geometry.\n", "datatype": "string", diff --git a/tests/check_buildnml.py b/tests/check_buildnml.py new file mode 100644 index 0000000..ab8bd31 --- /dev/null +++ b/tests/check_buildnml.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python + +""" +Unit test for cime_config/buildnml and MOM parameter expansion. +Verifies MASKTABLE expansion under single-instance and multi-instance modes with AUTO_MASKTABLE True/False. +""" + +import os +import sys + +# Add cime_config/MOM_RPS to path +sys.path.append(os.path.join(os.path.dirname(__file__), "..", "cime_config", "MOM_RPS")) +from FType_MOM_params import FType_MOM_params + + +def get_param_val(mom_params, varname): + for module in mom_params._data: + if varname in mom_params._data[module]: + return mom_params._data[module][varname]["value"] + return None + + +def test_masktable_expansion(): + json_path = os.path.join( + os.path.dirname(__file__), "..", "param_templates", "json", "MOM_input.json" + ) + + # Provide default CIME environment mock values (booleans, floats, strings) to satisfy + # CIME.ParamGen formulas/guards across all MOM_input.json parameters and prevent + # Python eval() type errors (e.g., float / str or bool vs str comparisons). + default_env = { + "OCN_GRID": "tx2_3v2", + "TEST": False, + "NTASKS_OCN": 64, + "DIN_LOC_ROOT": "/tmp/inputdata", + "CASEROOT": "/tmp/caseroot", + "CASEBUILD": "/tmp/casebuild", + "CASE": "case", + "SRCROOT": "/tmp/srcroot", + "RUNDIR": "/tmp/rundir", + "COMP_ROOT_DIR_OCN": "/tmp/mom", + "RUN_TYPE": "startup", + "CONTINUE_RUN": False, + "GET_REFCASE": False, + "RUN_REFCASE": "refcase", + "RUN_REFDATE": "0001-01-01", + "RUN_REFTOD": "00000", + "CPL_I2O_PER_CAT": False, + "ICE_NCAT": 5, + "MARBL_DIAG_MODE": "none", + "MOM6_INFRA_API": "FMS2", + "MOM6_VERTICAL_GRID": "zstar_65L", + "COMP_ATM": "cam", + "COMP_ICE": "cice", + "COMP_WAVE": "ww3", + "RESTINT": 1.0, + "REST_OPTION": "nmonths", + "REST_N": 1, + "REST_FREQ": "monthly", + "STOP_OPTION": "nmonths", + "STOP_N": 1, + "STOP_FREQ": "monthly", + "ATM_CO2_OPT": "constant", + "ATM_ALT_CO2_OPT": "constant", + "ATM_CO2_CONST": 280.0, + "ATM_ALT_CO2_CONST": 280.0, + "USE_MARBL_TRACERS": False, + "NCPL_BASE_PERIOD": "day", + "OCN_NCPL": 24, + "DT": 3600.0, + } + + def run_reduction(auto_masktable, inst_suffix): + mom_params = FType_MOM_params.from_json(json_path) + dyn_env = { + "AUTO_MASKTABLE": auto_masktable, + "INST_SUFFIX": inst_suffix, + } + mom_params.reduce(lambda var: dyn_env.get(var, default_env.get(var, ""))) + return get_param_val(mom_params, "MASKTABLE") + + # 1. Test Single-Instance, AUTO_MASKTABLE=True + val1 = run_reduction(auto_masktable=True, inst_suffix="") + print(f"Single-instance AUTO_MASKTABLE=True MASKTABLE: {val1}") + assert ( + val1 == "MOM_auto_mask_table" + ), f"Expected 'MOM_auto_mask_table', got '{val1}'" + + # 2. Test Multi-Instance, AUTO_MASKTABLE=True (_0001) + val2 = run_reduction(auto_masktable=True, inst_suffix="_0001") + print(f"Multi-instance _0001 AUTO_MASKTABLE=True MASKTABLE: {val2}") + assert ( + val2 == "MOM_auto_mask_table_0001" + ), f"Expected 'MOM_auto_mask_table_0001', got '{val2}'" + + # 3. Test Single-Instance, AUTO_MASKTABLE=False + val3 = run_reduction(auto_masktable=False, inst_suffix="") + print(f"Single-instance AUTO_MASKTABLE=False MASKTABLE: {val3}") + assert val3 == "MOM_mask_table", f"Expected 'MOM_mask_table', got '{val3}'" + + # 4. Test Multi-Instance, AUTO_MASKTABLE=False (_0001) + val4 = run_reduction(auto_masktable=False, inst_suffix="_0001") + print(f"Multi-instance _0001 AUTO_MASKTABLE=False MASKTABLE: {val4}") + assert val4 == "MOM_mask_table", f"Expected 'MOM_mask_table', got '{val4}'" + + print("ALL MASKTABLE TESTS PASSED") + + +if __name__ == "__main__": + test_masktable_expansion()