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

Clean up "make all" for 5.2 branch #2424

Merged
merged 15 commits into from
Mar 15, 2024
Merged
Show file tree
Hide file tree
Changes from 13 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
1 change: 1 addition & 0 deletions .git-blame-ignore-revs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ e4d38681df23ccca0ae29581a45f8362574e0630
a9d96219902cf609636886c7073a84407f450d9a
d866510188d26d51bcd6d37239283db690af7e82
0dcd0a3c1abcaffe5529f8d79a6bc34734b195c7
e096358c832ab292ddfd22dd5878826c7c788968
# Ran SystemTests and python/ctsm through black python formatter
5364ad66eaceb55dde2d3d598fe4ce37ac83a93c
8056ae649c1b37f5e10aaaac79005d6e3a8b2380
Expand Down
4 changes: 3 additions & 1 deletion python/ctsm/test/test_sys_gen_mksurfdata_jobscript_multi.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,12 @@ def tearDown(self):
os.chdir(self._original_wd)
shutil.rmtree(self._tempdir, ignore_errors=True)

def createJS(self, nodes, tasks_per_node, scenario, option_list=[]):
def createJS(self, nodes, tasks_per_node, scenario, option_list=None):
"""
Create a JobScript by sending a list of options in
"""
if option_list is None:
option_list = []
if len(option_list) > 1:
sys.argv.extend(option_list)
sys.argv.extend(
Expand Down
4 changes: 3 additions & 1 deletion python/ctsm/test/test_sys_gen_mksurfdata_jobscript_single.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,12 @@ def tearDown(self):
os.chdir(self._original_wd)
shutil.rmtree(self._tempdir, ignore_errors=True)

def createJS(self, nodes, tasks_per_node, option_list=[]):
def createJS(self, nodes, tasks_per_node, option_list=None):
"""
Create a JobScript by sending a list of options in
"""
if option_list is None:
option_list = []
if len(option_list) > 1:
sys.argv.extend(option_list)
sys.argv.extend(
Expand Down
32 changes: 13 additions & 19 deletions python/ctsm/test/test_sys_mesh_modifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,6 @@ def setUp(self):
path_to_ctsm_root(), "tools/modify_input_files/modify_mesh_template.cfg"
)
self.testinputs_path = os.path.join(path_to_ctsm_root(), "python/ctsm/test/testinputs")
fsurdat_in = os.path.join(
self.testinputs_path,
"surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031.nc",
)
self._tempdir = tempfile.mkdtemp()
self._cfg_file_path = os.path.join(self._tempdir, "modify_mesh_mask.cfg")
self._mesh_mask_in = os.path.join(self._tempdir, "mesh_mask_in.nc")
Expand All @@ -72,7 +68,7 @@ def setUp(self):
except subprocess.CalledProcessError as e:
sys.exit(f"{e} ERROR using {configure_cmd}")

def createScripGridAndMask(self):
def createScripGridAndMask(self, fsurdat_in):
ekluzek marked this conversation as resolved.
Show resolved Hide resolved
"""Create the SCRIP gird and mask file"""
samsrabin marked this conversation as resolved.
Show resolved Hide resolved
# Generate scrip file from fsurdat_in using nco
# In the ctsm_py environment this requires running 'module load nco'
Expand All @@ -86,14 +82,14 @@ def createScripGridAndMask(self):

# This could also alturnatively be done, by using the stored SCRIP grid file for the resolution under CESM inputdata
ncks_cmd = (
f"ncks --rgr infer --rgr scrip={self.scrip_file} {self.fsurdat_in} {self.metadata_file}"
f"ncks --rgr infer --rgr scrip={self.scrip_file} {fsurdat_in} {self.metadata_file}"
)
try:
subprocess.check_call(ncks_cmd, shell=True)
except subprocess.CalledProcessError as e:
err_msg = (
f"{e} ERROR using ncks to generate {self.scrip_file} from "
+ f"{self.fsurdat_in}; MOST LIKELY SHOULD INVOKE module load nco"
+ f"{fsurdat_in}; MOST LIKELY SHOULD INVOKE module load nco"
)
sys.exit(err_msg)
# Run .env_mach_specific.sh to load esmf and generate mesh_mask_in
Expand All @@ -109,13 +105,13 @@ def createScripGridAndMask(self):
# Generate landmask_file from fsurdat_in
self._lat_varname = "LATIXY" # same as in fsurdat_in
self._lon_varname = "LONGXY" # same as in fsurdat_in
fsurdat_in_data = xr.open_dataset(self.fsurdat_in)
fsurdat_in_data = xr.open_dataset(fsurdat_in)
assert self._lat_varname in fsurdat_in_data.variables
assert self._lon_varname in fsurdat_in_data.variables
self._lat_dimname = fsurdat_in_data[self._lat_varname].dims[0]
self._lon_dimname = fsurdat_in_data[self._lat_varname].dims[1]

def createLandMaskFile(self):
def createLandMaskFile(self, fsurdat_in):
"""Create the LandMask file from the input fsurdat_in file"""
if os.path.exists(self._landmask_file):
os.remove(self._landmask_file)
Expand All @@ -124,14 +120,12 @@ def createLandMaskFile(self):
+ "-A -v -s 'landmask=LANDFRAC_MKSURFDATA.convert(NC_INT)' "
+ f"-A -v -s {self._lat_varname}={self._lat_varname} "
+ f"-A -v -s {self._lon_varname}={self._lon_varname} "
+ f"{self.fsurdat_in} {self._landmask_file}"
+ f"{fsurdat_in} {self._landmask_file}"
)
try:
subprocess.check_call(ncap2_cmd, shell=True)
except subprocess.CalledProcessError as e:
sys.exit(
f"{e} ERROR using ncap2 to generate {self._landmask_file} from {self.fsurdat_in}"
)
sys.exit(f"{e} ERROR using ncap2 to generate {self._landmask_file} from {fsurdat_in}")

def tearDown(self):
"""
Expand All @@ -147,13 +141,13 @@ def test_allInfo(self):
For a case where the mesh remains unchanged, it's just output as
ocean so the mesh is output as all zero's rather than the all 1's that came in.
"""
self.fsurdat_in = os.path.join(
fsurdat_in = os.path.join(
self.testinputs_path,
"surfdata_5x5_amazon_hist_78pfts_CMIP6_2000_c230517.nc",
)

self.createScripGridAndMask()
self.createLandMaskFile()
self.createScripGridAndMask(fsurdat_in)
self.createLandMaskFile(fsurdat_in)
self._create_config_file()

# run the mesh_mask_modifier tool
Expand Down Expand Up @@ -185,12 +179,12 @@ def test_modifyMesh(self):
For a case where the mesh is changed.
"""

self.fsurdat_in = os.path.join(
fsurdat_in = os.path.join(
self.testinputs_path,
"surfdata_5x5_amazon_hist_78pfts_CMIP6_2000_c230517_modify_mask.nc",
)
self.createScripGridAndMask()
self.createLandMaskFile()
self.createScripGridAndMask(fsurdat_in)
self.createLandMaskFile(fsurdat_in)
self._create_config_file()

if os.path.exists(self._mesh_mask_out):
Expand Down
3 changes: 2 additions & 1 deletion python/ctsm/test/test_unit_modify_fsurdat.py
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,8 @@ def test_check_varlist_lists_wrongsizes(self):
settings = {"var_lev1": lev1list}
with self.assertRaisesRegex(
SystemExit,
" Variable var_lev1 is 8 is of the wrong size. It should be = 9 in input settings dictionary",
" Variable var_lev1 is 8 is of the wrong size."
+ " It should be = 9 in input settings dictionary",
):
self.modify_fsurdat.check_varlist(settings)

Expand Down
143 changes: 93 additions & 50 deletions python/ctsm/toolchain/gen_mksurfdata_jobscript_multi.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,74 @@ def get_parser():
return parser


def write_runscript(
samsrabin marked this conversation as resolved.
Show resolved Hide resolved
scenario,
jobscript_file,
number_of_nodes,
tasks_per_node,
account,
walltime,
queue,
target_list,
resolution_dict,
dataset_dict,
env_specific_script,
mksurfdata,
runfile,
):
"""
Write run script
"""
runfile.write("#!/bin/bash \n")
runfile.write(f"#PBS -A {account} \n")
runfile.write(f"#PBS -N mksrf_{scenario} \n")
runfile.write("#PBS -j oe \n")
runfile.write("#PBS -k eod \n")
runfile.write("#PBS -S /bin/bash \n")
runfile.write(f"#PBS -q {queue} \n")
runfile.write(f"#PBS -l walltime={walltime} \n")
runfile.write(
"#PBS -l select="
+ f"{number_of_nodes}:ncpus={tasks_per_node}:mpiprocs={tasks_per_node}:mem=218GB \n"
)
runfile.write(
f"# This is a batch script to run a set of resolutions for mksurfdata_esmf {scenario}\n"
)
runfile.write(
"# NOTE: THIS SCRIPT IS AUTOMATICALLY GENERATED "
+ "SO IN GENERAL YOU SHOULD NOT EDIT it!!\n\n"
)
runfile.write("\n")

# Run env_mach_specific.sh to control the machine dependent
# environment including the paths to compilers and libraries
# external to cime such as netcdf
runfile.write(". " + env_specific_script + "\n")
check = "if [ $? != 0 ]; then echo 'Error running env_specific_script'; exit -4; fi"
runfile.write(f"{check} \n")
for target in target_list:
res_set = dataset_dict[target][1]
if res_set not in resolution_dict:
abort(f"Resolution is not in the resolution_dict: {res_set}")
for res in resolution_dict[res_set]:
namelist = f"{scenario}_{res}.namelist"
command = os.path.join(os.getcwd(), "gen_mksurfdata_namelist")
command = command + " " + dataset_dict[target][0] + " " + res
command = command + " --silent"
command = command + f" --namelist {namelist}"
print(f"command is {command}")
sys.argv = [x for x in command.split(" ") if x]
main_nml()
print(f"generated namelist {namelist}")
output = f"time mpiexec {mksurfdata} < {namelist}"
runfile.write(f"{output} \n")
check = f"if [ $? != 0 ]; then echo 'Error running resolution {res}'; exit -4; fi"
runfile.write(f"{check} \n")
runfile.write(f"echo Successfully ran resolution {res}\n")

runfile.write(f"echo Successfully ran {jobscript_file}\n")


def main():
"""
See docstring at the top.
Expand Down Expand Up @@ -168,7 +236,13 @@ def main():
# Determine resolution sets that are referenced in commands
# TODO slevis: When new resolutions become supported in ccs_config, the
# first entry will change to
# "standard_res_no_crop": ["0.9x1.25", "1.9x2.5", "mpasa60", "mpasa60-3conus", "mpasa60-3centralUS"],
# "standard_res_no_crop": [
# "0.9x1.25",
# "1.9x2.5",
# "mpasa60",
# "mpasa60-3conus",
# "mpasa60-3centralUS",
# ],
# --------------------------
resolution_dict = {
"standard_res_no_crop": ["0.9x1.25", "1.9x2.5", "mpasa60"],
Expand Down Expand Up @@ -246,7 +320,8 @@ def main():
"mpasa480",
),
"crop-global-present-nldas": (
"--start-year 2000 --end-year 2000 --res", # TODO slevis: --hirespft uses old data for now, so keep out
# TODO slevis: --hirespft uses old data for now, so keep out
"--start-year 2000 --end-year 2000 --res",
"nldas_res",
),
"crop-global-1850": (
Expand Down Expand Up @@ -370,7 +445,8 @@ def main():
if not os.path.exists(args.bld_path):
print(
args.bld_path
+ " directory does NOT exist -- build mksurdata_esmf before running this script -- using ./gen_mksurfdata_build.sh"
+ " directory does NOT exist -- build mksurdata_esmf before running this script --"
+ " using ./gen_mksurfdata_build.sh"
)
sys.exit(1)

Expand All @@ -387,53 +463,20 @@ def main():
# --------------------------
with open(jobscript_file, "w", encoding="utf-8") as runfile:

runfile.write("#!/bin/bash \n")
runfile.write(f"#PBS -A {account} \n")
runfile.write(f"#PBS -N mksrf_{scenario} \n")
runfile.write("#PBS -j oe \n")
runfile.write("#PBS -k eod \n")
runfile.write("#PBS -S /bin/bash \n")
runfile.write(f"#PBS -q {queue} \n")
runfile.write(f"#PBS -l walltime={walltime} \n")
runfile.write(
f"#PBS -l select={number_of_nodes}:ncpus={tasks_per_node}:mpiprocs={tasks_per_node}:mem=218GB \n"
)
runfile.write(
f"# This is a batch script to run a set of resolutions for mksurfdata_esmf {scenario} \n"
)
runfile.write(
"# NOTE: THIS SCRIPT IS AUTOMATICALLY GENERATED SO IN GENERAL YOU SHOULD NOT EDIT it!!\n\n"
write_runscript(
scenario,
jobscript_file,
number_of_nodes,
tasks_per_node,
account,
walltime,
queue,
target_list,
resolution_dict,
dataset_dict,
env_specific_script,
mksurfdata,
runfile,
)
runfile.write("\n")

n_p = int(tasks_per_node) * int(number_of_nodes)

# Run env_mach_specific.sh to control the machine dependent
# environment including the paths to compilers and libraries
# external to cime such as netcdf
runfile.write(". " + env_specific_script + "\n")
check = "if [ $? != 0 ]; then echo 'Error running env_specific_script'; exit -4; fi"
runfile.write(f"{check} \n")
for target in target_list:
res_set = dataset_dict[target][1]
if res_set not in resolution_dict:
abort(f"Resolution is not in the resolution_dict: {res_set}")
for res in resolution_dict[res_set]:
namelist = f"{scenario}_{res}.namelist"
command = os.path.join(os.getcwd(), "gen_mksurfdata_namelist")
command = command + " " + dataset_dict[target][0] + " " + res
command = command + " --silent"
command = command + f" --namelist {namelist}"
print(f"command is {command}")
sys.argv = [x for x in command.split(" ") if x]
main_nml()
print(f"generated namelist {namelist}")
output = f"time mpiexec {mksurfdata} < {namelist}"
runfile.write(f"{output} \n")
check = f"if [ $? != 0 ]; then echo 'Error running resolution {res}'; exit -4; fi"
runfile.write(f"{check} \n")
runfile.write(f"echo Successfully ran resolution {res}\n")

runfile.write(f"echo Successfully ran {jobscript_file}\n")

print(f"echo Successfully created jobscript {jobscript_file}\n")
Loading
Loading