Skip to content

Commit 2e2434d

Browse files
committed
Merge 5 bit-for-bit pull requests:
* Add system and unit tests for making fsurdat with all crops everywhere (#2081) * Rework master_list* files etc. (#2087) * Fixes to methane Tech Note (#2091) * Add is_doy_in_interval() function (#2158) * Avoid using subprocess.run() in FSURDATMODIFYCTSM (#2125) Closes issues: * Add unit test for making fsurdat with all crops everywhere (#2079) * Rework master_list_(no)?fates.rst? (#2083) * conda run -n can fail if a conda environment is already active (#2109) * conda fails to load for SystemTests (#2111)
2 parents 350a436 + f3f76f4 commit 2e2434d

49 files changed

Lines changed: 3209 additions & 2627 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.git-blame-ignore-revs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# Ran python directory through black python formatter
2+
d229b5c6689efc4c2a6cef077515c4ccd5c18ff6
23
4cd83cb3ee6d85eb909403487abf5eeaf4d98911
34
0aa2957c1f8603c63fa30b11295c06cfddff44a5
45
2cdb380febb274478e84cd90945aee93f29fa2e6
@@ -10,6 +11,11 @@ b88e1cd1b28e3609684c79a2ec0e88f26cfc362b
1011
b771971e3299c4fa56534b93421f7a2b9c7282fd
1112
9de88bb57ea9855da408cbec1dc8acb9079eda47
1213
8bc4688e52ea23ef688e283698f70a44388373eb
14+
0a5a9e803b56ec1bbd6232eff1c99dbbeef25eb7
15+
810cb346f05ac1aabfff931ab1a2b7b584add241
16+
5933b0018f8e29413e30dda9b906370d147bad45
1317
# Ran SystemTests and python/ctsm through black python formatter
1418
5364ad66eaceb55dde2d3d598fe4ce37ac83a93c
1519
8056ae649c1b37f5e10aaaac79005d6e3a8b2380
20+
540b256d1f3382f4619d7b0877c32d54ce5c40b6
21+
8a168bb0895f4f2421608dd2589398e13a6663e6

bld/CLMBuildNamelist.pm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4413,7 +4413,7 @@ sub setup_logic_misc {
44134413
add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'for_testing_use_second_grain_pool');
44144414
add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'for_testing_use_repr_structure_pool');
44154415
add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'for_testing_no_crop_seed_replenishment');
4416-
add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'hist_master_list_file');
4416+
add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'hist_fields_list_file');
44174417
}
44184418

44194419
#-------------------------------------------------------------------------------

bld/namelist_files/namelist_defaults_ctsm.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ attributes from the config_cache.xml file (with keys converted to upper-case).
6767
<for_testing_use_repr_structure_pool>.false.</for_testing_use_repr_structure_pool>
6868
<for_testing_no_crop_seed_replenishment>.false.</for_testing_no_crop_seed_replenishment>
6969

70-
<!-- Set to .true. in namelist to write hist fields master list file -->
71-
<hist_master_list_file>.false.</hist_master_list_file>
70+
<!-- Set to .true. in namelist to write file with all history fields -->
71+
<hist_fields_list_file>.false.</hist_fields_list_file>
7272

7373
<!-- In accelerated spinup mode reduce the amount of history output -->
7474
<hist_empty_htapes clm_accelerated_spinup="on">.true.</hist_empty_htapes>

bld/namelist_files/namelist_definition_ctsm.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -764,9 +764,9 @@ SNICAR (SNow, ICe, and Aerosol Radiative model) optical data file name
764764
SNICAR (SNow, ICe, and Aerosol Radiative model) snow aging data file name
765765
</entry>
766766

767-
<entry id="hist_master_list_file" type="logical" category="history"
767+
<entry id="hist_fields_list_file" type="logical" category="history"
768768
group="clm_inparm" valid_values="" value=".false.">
769-
If TRUE, write master field list to separate file for documentation purposes
769+
If TRUE, write list of all output fields to separate file for documentation purposes
770770
</entry>
771771

772772
<entry id="hist_avgflag_pertape" type="char*10(10)" category="history"

cime_config/SystemTests/fsurdatmodifyctsm.py

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,18 @@
55

66
import os
77
import re
8-
import systemtest_utils as stu
98
from CIME.SystemTests.system_tests_common import SystemTestsCommon
109
from CIME.XML.standard_module_setup import *
1110
from CIME.SystemTests.test_utils.user_nl_utils import append_to_user_nl_files
1211

12+
# For calling fsurdat_modifier
13+
from argparse import Namespace
14+
15+
_CTSM_PYTHON = os.path.join(
16+
os.path.dirname(os.path.realpath(__file__)), os.pardir, os.pardir, "python"
17+
)
18+
sys.path.insert(1, _CTSM_PYTHON)
19+
1320
logger = logging.getLogger(__name__)
1421

1522

@@ -66,16 +73,18 @@ def _create_config_file(self):
6673
cfg_out.write(line)
6774

6875
def _run_modify_fsurdat(self):
69-
tool_path = os.path.join(self._ctsm_root, "tools/modify_input_files/fsurdat_modifier")
70-
71-
self._case.load_env(reset=True)
72-
command = f"python3 {tool_path} {self._cfg_file_path}"
73-
stu.run_python_script(
74-
self._get_caseroot(),
75-
"ctsm_pylib",
76-
command,
77-
tool_path,
76+
fsurdat_modifier_args = Namespace(
77+
cfg_path=self._cfg_file_path,
78+
debug=False,
79+
fsurdat_in="UNSET",
80+
fsurdat_out="UNSET",
81+
overwrite=False,
82+
silent=False,
83+
verbose=False,
7884
)
85+
from ctsm.modify_input_files.fsurdat_modifier import fsurdat_modifier
86+
87+
fsurdat_modifier(fsurdat_modifier_args)
7988

8089
def _modify_user_nl(self):
8190
append_to_user_nl_files(

cime_config/SystemTests/rxcropmaturity.py

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,8 @@ def run_phase(self):
134134
case_gddgen.check_all_input_data()
135135

136136
# Make custom version of surface file
137-
logger.info("RXCROPMATURITY log: run make_fsurdat_all_crops_everywhere")
138-
self._run_make_fsurdat_all_crops_everywhere()
137+
logger.info("RXCROPMATURITY log: run fsurdat_modifier")
138+
self._run_fsurdat_modifier()
139139

140140
# -------------------------------------------------------------------
141141
# (2) Perform GDD-generating run and generate prescribed GDDs file
@@ -239,7 +239,7 @@ def _setup_all(self):
239239
logger.info("RXCROPMATURITY log: _setup_all done")
240240

241241
# Make a surface dataset that has every crop in every gridcell
242-
def _run_make_fsurdat_all_crops_everywhere(self):
242+
def _run_fsurdat_modifier(self):
243243

244244
# fsurdat should be defined. Where is it?
245245
self._fsurdat_in = None
@@ -255,20 +255,29 @@ def _run_make_fsurdat_all_crops_everywhere(self):
255255
raise RuntimeError(error_message)
256256

257257
# Where we will save the fsurdat version for this test
258-
self._fsurdat_out = os.path.join(self._path_gddgen, "fsurdat.nc")
258+
path, ext = os.path.splitext(self._fsurdat_in)
259+
dir_in, filename_in_noext = os.path.split(path)
260+
self._fsurdat_out = os.path.join(
261+
self._path_gddgen, f"{filename_in_noext}.all_crops_everywhere{ext}"
262+
)
259263

260264
# Make fsurdat for this test, if not already done
261265
if not os.path.exists(self._fsurdat_out):
262266
tool_path = os.path.join(
263267
self._ctsm_root,
264-
"python",
265-
"ctsm",
266-
"crop_calendars",
267-
"make_fsurdat_all_crops_everywhere.py",
268+
"tools",
269+
"modify_input_files",
270+
"fsurdat_modifier",
268271
)
269-
command = (
270-
f"python3 {tool_path} " + f"-i {self._fsurdat_in} " + f"-o {self._fsurdat_out}"
272+
273+
# Create configuration file for fsurdat_modifier
274+
self._cfg_path = os.path.join(
275+
self._path_gddgen,
276+
"modify_fsurdat_allcropseverywhere.cfg",
271277
)
278+
self._create_config_file_evenlysplitcrop()
279+
280+
command = f"python3 {tool_path} {self._cfg_path} "
272281
stu.run_python_script(
273282
self._get_caseroot(),
274283
self._this_conda_env,
@@ -287,6 +296,40 @@ def _run_make_fsurdat_all_crops_everywhere(self):
287296
]
288297
)
289298

299+
def _create_config_file_evenlysplitcrop(self):
300+
"""
301+
Open the new and the template .cfg files
302+
Loop line by line through the template .cfg file
303+
When string matches, replace that line's content
304+
"""
305+
cfg_template_path = os.path.join(
306+
self._ctsm_root, "tools/modify_input_files/modify_fsurdat_template.cfg"
307+
)
308+
309+
with open(self._cfg_path, "w", encoding="utf-8") as cfg_out:
310+
# Copy template, replacing some lines
311+
with open(cfg_template_path, "r", encoding="utf-8") as cfg_in:
312+
for line in cfg_in:
313+
if re.match(r" *evenly_split_cropland *=", line):
314+
line = f"evenly_split_cropland = True"
315+
elif re.match(r" *fsurdat_in *=", line):
316+
line = f"fsurdat_in = {self._fsurdat_in}"
317+
elif re.match(r" *fsurdat_out *=", line):
318+
line = f"fsurdat_out = {self._fsurdat_out}"
319+
elif re.match(r" *process_subgrid_section *=", line):
320+
line = f"process_subgrid_section = True"
321+
cfg_out.write(line)
322+
323+
# Add new lines
324+
cfg_out.write("\n")
325+
cfg_out.write("[modify_fsurdat_subgrid_fractions]\n")
326+
cfg_out.write("PCT_CROP = 100.0\n")
327+
cfg_out.write("PCT_NATVEG = 0.0\n")
328+
cfg_out.write("PCT_GLACIER = 0.0\n")
329+
cfg_out.write("PCT_WETLAND = 0.0\n")
330+
cfg_out.write("PCT_LAKE = 0.0\n")
331+
cfg_out.write("PCT_URBAN = 0.0 0.0 0.0\n")
332+
290333
def _run_check_rxboth_run(self):
291334

292335
output_dir = os.path.join(self._get_caseroot(), "run")

cime_config/SystemTests/systemtest_utils.py

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,27 +10,41 @@ def cmds_to_setup_conda(caseroot):
1010
# Use semicolon here since it's OK to fail
1111
#
1212
conda_setup_commands = ". " + caseroot + "/.env_mach_specific.sh; "
13+
# Setting CONDA_PREFIX to empty ensures that this works even if called from
14+
# a shell with a conda environment activated
15+
conda_setup_commands += "CONDA_PREFIX=; "
1316
# Execute the module unload/load when "which conda" fails
1417
# eg on cheyenne
1518
try:
1619
subprocess.run("which conda", shell=True, check=True)
1720
except subprocess.CalledProcessError:
1821
# Remove python and add conda to environment for cheyennne
19-
conda_setup_commands += " module unload python; module load conda;"
22+
unload_python_load_conda = "module unload python; module load conda;"
23+
# Make sure that adding this actually loads conda
24+
subprocess.run(unload_python_load_conda + "which conda", shell=True, check=True)
25+
# Save
26+
conda_setup_commands += " " + unload_python_load_conda
2027

2128
return conda_setup_commands
2229

2330

24-
def run_python_script(caseroot, this_conda_env, command, tool_path):
25-
31+
def cmds_to_run_via_conda(caseroot, conda_run_call, command):
2632
# Run in the specified conda environment
2733
conda_setup_commands = cmds_to_setup_conda(caseroot)
28-
conda_setup_commands += f" conda run -n {this_conda_env}"
34+
conda_setup_commands += " " + conda_run_call
2935

3036
# Finish with Python script call
3137
command = conda_setup_commands + " " + command
3238
print(f"command: {command}")
3339

40+
return command
41+
42+
43+
def run_python_script(caseroot, this_conda_env, command_in, tool_path):
44+
45+
# First, try with "conda run -n"
46+
command = cmds_to_run_via_conda(caseroot, f"conda run -n {this_conda_env}", command_in)
47+
3448
# Run with logfile
3549
tool_name = os.path.split(tool_path)[-1]
3650
try:
@@ -39,19 +53,34 @@ def run_python_script(caseroot, this_conda_env, command, tool_path):
3953
command, shell=True, check=True, text=True, stdout=f, stderr=subprocess.STDOUT
4054
)
4155
except subprocess.CalledProcessError as error:
42-
print("ERROR while getting the conda environment and/or ")
43-
print(f"running the {tool_name} tool: ")
44-
print(f"(1) If your {this_conda_env} environment is out of date or you ")
45-
print(f"have not created the {this_conda_env} environment, yet, you may ")
46-
print("get past this error by running ./py_env_create ")
47-
print("in your ctsm directory and trying this test again. ")
48-
print("(2) If conda is not available, install and load conda, ")
49-
print("run ./py_env_create, and then try this test again. ")
50-
print("(3) If (1) and (2) are not the issue, then you may be ")
51-
print(f"getting an error within {tool_name} itself. ")
52-
print("Default error message: ")
53-
print(error.output)
54-
raise
56+
# Retry with the original "conda activate" method
57+
command = cmds_to_run_via_conda(
58+
caseroot,
59+
f"conda activate {this_conda_env} && ",
60+
command_in,
61+
)
62+
try:
63+
with open(tool_name + ".log2", "w") as f:
64+
subprocess.run(
65+
command, shell=True, check=True, text=True, stdout=f, stderr=subprocess.STDOUT
66+
)
67+
except subprocess.CalledProcessError as error:
68+
print("ERROR while getting the conda environment and/or ")
69+
print(f"running the {tool_name} tool: ")
70+
print(f"(1) If your {this_conda_env} environment is out of date or you ")
71+
print(f"have not created the {this_conda_env} environment, yet, you may ")
72+
print("get past this error by running ./py_env_create ")
73+
print("in your ctsm directory and trying this test again. ")
74+
print("(2) If conda is not available, install and load conda, ")
75+
print("run ./py_env_create, and then try this test again. ")
76+
print("(3) If (1) and (2) are not the issue, then you may be ")
77+
print(f"getting an error within {tool_name} itself. ")
78+
print("Default error message: ")
79+
print(error.output)
80+
raise
81+
except:
82+
print(f"ERROR trying to run {tool_name}.")
83+
raise
5584
except:
5685
print(f"ERROR trying to run {tool_name}.")
5786
raise

cime_config/testdefs/testlist_clm.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,7 +1007,7 @@
10071007
</machines>
10081008
<options>
10091009
<option name="wallclock">00:20:00</option>
1010-
<option name="comment" >Among other extra outputs, ensure that writing the history field master list to a separate file does not cause failure"</option>
1010+
<option name="comment" >Among other extra outputs, ensure that writing the list of all history fields to a separate file does not cause failure"</option>
10111011
</options>
10121012
</test>
10131013
<test name="ERS_D_Ld3" grid="f10_f10_mg37" compset="I1850Clm50BgcCrop" testmods="clm/default">
@@ -2590,7 +2590,7 @@
25902590
</machines>
25912591
</test>
25922592

2593-
<test name="RXCROPMATURITY_Lm61" grid="f09_g17" compset="IHistClm50BgcCrop">
2593+
<test name="RXCROPMATURITY_Lm61" grid="f09_g17" compset="IHistClm50BgcCrop" testmods="clm/cropMonthOutput">
25942594
<machines>
25952595
<machine name="cheyenne" compiler="intel" category="ctsm_sci">
25962596
<options>
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
use_lch4 = .false.
2-
hist_master_list_file = .true.
2+
hist_fields_list_file = .true.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
hist_fields_list_file = .true.

0 commit comments

Comments
 (0)