157 lines
6.8 KiB
Python
157 lines
6.8 KiB
Python
"""
|
|
This test passes if mksurfdata_esmf generates an fsurdat (surface dataset)
|
|
and the CTSM completes a simulation with this fsurdat file.
|
|
|
|
We test res = '10x15' because it uses a lower-res topography file instead of
|
|
the 1-km topography raw dataset. The 1-km file causes the test to run out of
|
|
memory on cheyenne.
|
|
|
|
Currently casper complains that `git -C` is not a valid option.
|
|
I added -C to the `git describe` in gen_mksurfdata_namelist for this
|
|
system test to work.
|
|
"""
|
|
import os
|
|
import sys
|
|
import subprocess
|
|
from datetime import datetime
|
|
from CIME.SystemTests.system_tests_common import SystemTestsCommon
|
|
from CIME.XML.standard_module_setup import *
|
|
from CIME.SystemTests.test_utils.user_nl_utils import append_to_user_nl_files
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class MKSURFDATAESMF(SystemTestsCommon):
|
|
def __init__(self, case):
|
|
"""
|
|
initialize an object interface to the SMS system test
|
|
"""
|
|
SystemTestsCommon.__init__(self, case)
|
|
|
|
# Paths and strings needed throughout
|
|
ctsm_root = self._case.get_value("COMP_ROOT_DIR_LND")
|
|
self._tool_path = os.path.join(ctsm_root, "tools/mksurfdata_esmf")
|
|
self._tool_bld = os.path.join(self._get_caseroot(), "tool_bld")
|
|
time_stamp = datetime.today().strftime("%y%m%d")
|
|
self._res = "10x15" # see important comment in script's docstring
|
|
self._model_yr = "1850"
|
|
self._jobscript = os.path.join(
|
|
self._get_caseroot(), "mksurfdataesmf_test_jobscript_single.sh"
|
|
)
|
|
self._fsurdat_namelist = os.path.join(
|
|
self._get_caseroot(),
|
|
f"surfdata_{self._res}_hist_{self._model_yr}_78pfts_c{time_stamp}.namelist",
|
|
)
|
|
self._fsurdat_nc = os.path.join(
|
|
self._get_caseroot(),
|
|
f"surfdata_{self._res}_hist_{self._model_yr}_78pfts_c{time_stamp}.nc",
|
|
)
|
|
self._TestStatus_log_path = os.path.join(self._get_caseroot(), "TestStatus.log")
|
|
|
|
def build_phase(self, sharedlib_only=False, model_only=False):
|
|
"""
|
|
Build executable that will generate fsurdat
|
|
Generate namelist for generating fsurdat
|
|
Generate jobscript that runs executable
|
|
Modify user_nl_clm to point to the generated fsurdat
|
|
"""
|
|
# build_phase gets called twice:
|
|
# - once with sharedlib_only = True and
|
|
# - once with model_only = True
|
|
# Call the following steps only once during the test but do not skip
|
|
# if the test stops and gets restarted.
|
|
if sharedlib_only:
|
|
# Paths and strings
|
|
build_script_path = os.path.join(self._tool_path, "gen_mksurfdata_build")
|
|
nml_script_path = os.path.join(self._tool_path, "gen_mksurfdata_namelist")
|
|
gen_jobscript_path = os.path.join(self._tool_path, "gen_mksurfdata_jobscript_single")
|
|
gen_mksurfdata_namelist = f"{nml_script_path} --res {self._res} --start-year {self._model_yr} --end-year {self._model_yr}"
|
|
|
|
if not os.path.exists(nml_script_path):
|
|
sys.exit(f"ERROR The build naemlist script {nml_script_path} does NOT exist")
|
|
|
|
if not os.path.exists(gen_jobscript_path):
|
|
sys.exit(f"ERROR The jobscript script {gen_jobscript_path} does NOT exist")
|
|
|
|
gen_mksurfdata_jobscript = (
|
|
f"{gen_jobscript_path} --number-of-nodes 1 --tasks-per-node 64 --namelist-file "
|
|
+ f"{self._fsurdat_namelist} --bld-path {self._tool_bld} --jobscript-file {self._jobscript}"
|
|
)
|
|
if not os.path.exists(build_script_path):
|
|
sys.exit(f"ERROR The build script {build_script_path} does NOT exist")
|
|
|
|
# Rm tool_bld and build executable that will generate fsurdat
|
|
try:
|
|
subprocess.check_call(f"rm -rf {self._tool_bld}", shell=True)
|
|
except subprocess.CalledProcessError as e:
|
|
sys.exit(
|
|
f"{e} ERROR REMOVING {self._tool_bld}. DETAILS IN {self._TestStatus_log_path}"
|
|
)
|
|
try:
|
|
subprocess.check_call(f"{build_script_path} --blddir {self._tool_bld}", shell=True)
|
|
except subprocess.CalledProcessError as e:
|
|
print(f"build directory = {self._tool_bld}\n")
|
|
sys.exit(
|
|
f"{e} ERROR RUNNING {build_script_path} DETAILS IN {self._TestStatus_log_path}"
|
|
)
|
|
|
|
# Generate namelist for generating fsurdat (rm namelist if exists)
|
|
if os.path.exists(self._fsurdat_namelist):
|
|
os.remove(self._fsurdat_namelist)
|
|
try:
|
|
subprocess.check_call(gen_mksurfdata_namelist, shell=True)
|
|
except subprocess.CalledProcessError as e:
|
|
sys.exit(
|
|
f"{e} ERROR RUNNING {gen_mksurfdata_namelist}. DETAILS IN {self._TestStatus_log_path}"
|
|
)
|
|
|
|
# Generate jobscript that will run the executable
|
|
if os.path.exists(self._jobscript):
|
|
os.remove(self._jobscript)
|
|
try:
|
|
subprocess.check_call(gen_mksurfdata_jobscript, shell=True)
|
|
except subprocess.CalledProcessError as e:
|
|
sys.exit(
|
|
f"{e} ERROR RUNNING {gen_mksurfdata_jobscript}. DETAILS IN {self._TestStatus_log_path}"
|
|
)
|
|
# Change self._jobscript to an executable file
|
|
subprocess.check_call(f"chmod a+x {self._jobscript}", shell=True)
|
|
|
|
# Call this step only once even if the test stops and gets restarted.
|
|
if not os.path.exists(os.path.join(self._get_caseroot(), "done_MKSURFDATAESMF_setup.txt")):
|
|
# Modify user_nl_clm to point to the generated fsurdat
|
|
self._modify_user_nl()
|
|
with open("done_MKSURFDATAESMF_setup.txt", "w") as fp:
|
|
pass
|
|
|
|
self.build_indv(sharedlib_only=sharedlib_only, model_only=model_only)
|
|
|
|
def run_phase(self):
|
|
"""
|
|
Run executable to generate fsurdat
|
|
Submit CTSM run that uses fsurdat just generated
|
|
"""
|
|
|
|
# Run executable to generate fsurdat (rm fsurdat if exists)
|
|
if os.path.exists(self._fsurdat_nc):
|
|
os.remove(self._fsurdat_nc)
|
|
try:
|
|
subprocess.check_call(self._jobscript, shell=True)
|
|
except subprocess.CalledProcessError as e:
|
|
sys.exit(f"{e} ERROR RUNNING {self._jobscript}; details in {self._TestStatus_log_path}")
|
|
|
|
# Submit CTSM run that uses fsurdat just generated
|
|
self.run_indv()
|
|
|
|
def _modify_user_nl(self):
|
|
"""
|
|
Modify user_nl_clm to point to the generated fsurdat
|
|
"""
|
|
append_to_user_nl_files(
|
|
caseroot=self._get_caseroot(),
|
|
component="clm",
|
|
contents="fsurdat = '{}'".format(self._fsurdat_nc)
|
|
+ "\n"
|
|
+ "convert_ocean_to_land = .true.",
|
|
)
|