forked from ESCOMP/CAM
-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathbuildnml
More file actions
executable file
·255 lines (208 loc) · 10.8 KB
/
Copy pathbuildnml
File metadata and controls
executable file
·255 lines (208 loc) · 10.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
#!/usr/bin/env python3
"""
CAM namelist creator
"""
# pylint: disable=multiple-imports
import sys, os, shutil, filecmp
_CIMEROOT = os.environ.get("CIMEROOT")
if _CIMEROOT is None:
raise SystemExit("ERROR: must set CIMEROOT environment variable")
_LIBDIR = os.path.join(_CIMEROOT, "scripts", "Tools")
sys.path.append(_LIBDIR)
# pylint: disable=wildcard-import, wrong-import-position, invalid-name
# pylint: disable=bad-whitespace, unused-wildcard-import, too-many-locals
# pylint: disable=too-many-branches, too-many-statements
from standard_script_setup import *
from CIME.XML.standard_module_setup import *
from CIME.buildnml import create_namelist_infile, parse_input
from CIME.case import Case
from CIME.utils import expect, run_cmd, import_from_file
logger = logging.getLogger(__name__)
###############################################################################
def buildnml(case, caseroot, compname):
###############################################################################
"""Build the cam namelist """
# Build the component namelist
if compname != "cam":
raise AttributeError
srcroot = case.get_value("SRCROOT")
rundir = case.get_value("RUNDIR")
din_loc_root = case.get_value("DIN_LOC_ROOT")
atm_ncpl = case.get_value("ATM_NCPL")
CAM_NAMELIST_OPTS = case.get_value("CAM_NAMELIST_OPTS")
CAM_CONFIG_OPTS = case.get_value("CAM_CONFIG_OPTS")
CAM_NML_USE_CASE = case.get_value("CAM_NML_USE_CASE")
DEBUG = case.get_value("DEBUG")
NINST_ATM = case.get_value("NINST_ATM")
NTASKS = case.get_value("NTASKS_PER_INST_ATM")
RUN_TYPE = case.get_value("RUN_TYPE")
RUN_STARTDATE = case.get_value("RUN_STARTDATE")
RUN_REFCASE = case.get_value("RUN_REFCASE")
RUN_REFDATE = case.get_value("RUN_REFDATE")
RUN_REFTOD = case.get_value("RUN_REFTOD")
COMP_INTERFACE = case.get_value("COMP_INTERFACE")
CALENDAR = case.get_value("CALENDAR")
COMPSET = case.get_value("COMPSET")
mesh_file = case.get_value("ATM_DOMAIN_MESH")
# The Gregorian calendar currently can't be used with spinup compsets
# because CAM's stream-handling code can't handle a request for data
# for Feb 29 (possibly specified in a leapday testmod) from a non-leap-year
# in the stream(s) data (specified in a use_case, e.g. 1850_cam_lt.xml).
# This limitation can be removed when CAM's stream-handling is switched to
# using CDEPS, which appears to handle this situation. (See discussion in
# https://github.com/ESCOMP/CAM/issues/1447 for details.)
if CALENDAR.startswith("GREGORIAN"):
spinup_po = re.compile('\d{4}')
spinup = spinup_po.match(COMPSET)
expect(spinup == None,
"Gregorian calendar (modifier _cG) cannot be used with spinup compset \n {}".format(COMPSET)
)
if '-tuvx' in CAM_CONFIG_OPTS:
tuvx_data_src = os.path.join(srcroot, "libraries", "tuv-x", "data")
testsrc = os.path.join(srcroot, "components", "cam")
if os.path.exists(testsrc):
srcroot = testsrc
#--------------------------------------------------------------------
# call buildcpp to set both cppdefs and config_cache.xml file for generating namelist
#--------------------------------------------------------------------
call_buildcpp = False
camconf = os.path.join(caseroot, "Buildconf", "camconf")
filename = os.path.join(camconf, "config_cache.xml")
if not os.path.isfile(filename):
call_buildcpp = True
else:
file1 = os.path.join(caseroot,"env_build.xml")
file2 = os.path.join(caseroot,"LockedFiles","env_build.xml")
if os.path.isfile(file2) and not filecmp.cmp(file1, file2):
call_buildcpp = True
if call_buildcpp:
cmd = os.path.join(os.path.join(srcroot,"cime_config","buildcpp"))
logger.info(" ...calling cam buildcpp to set build time options")
try:
buildcpp = import_from_file("buildcpp", cmd)
_ = buildcpp.buildcpp(case)
except:
logger.warning(" ...cam buildcpp exited with error")
# Verify that we have a config_cache file (generated by the call to buildcpp)
expect(os.path.isfile(filename),
" Missing CAM's config_cache.xml - cannot run build-namelist")
#--------------------------------------------------------------------
# Invoke cam build-namelist - output will go in $CASEROOT/Buildconf/camconf
#--------------------------------------------------------------------
input_data_list = os.path.join(caseroot, "Buildconf", "cam.input_data_list")
if os.path.isfile(input_data_list):
os.remove(input_data_list)
ninst = int(NINST_ATM)
for inst_counter in range(1, ninst+1):
# -----------------------------------------------------
# determine instance string
# -----------------------------------------------------
inst_string = ""
if ninst > 1:
single_case_rpointer = os.path.join(rundir, "rpointer.atm")
inst_string = '_%04d' % inst_counter
instance_rpointer = os.path.join(rundir,"rpointer.atm"+inst_string)
# If multi-instance case does not have restart file, use
# single-case restart for each instance
if os.path.isfile(single_case_rpointer) and \
not os.path.isfile(instance_rpointer):
shutil.copy(single_case_rpointer, instance_rpointer)
# -----------------------------------------------------
# create camconf/namelist
# -----------------------------------------------------
infile_lines = []
# This simplifies the filename mangling for different cases.
def _create_ic_filename(inst_string, i_or_r):
return "{}.cam{}.{}.{}-{}.nc".format( \
RUN_REFCASE, inst_string, i_or_r, RUN_REFDATE, RUN_REFTOD)
if RUN_TYPE == 'hybrid':
ncdata = _create_ic_filename(inst_string, 'i')
# Fallback if no instance-specific file is found.
if not os.path.isfile(os.path.join(rundir, ncdata)):
ncdata = _create_ic_filename('', 'i')
infile_lines.append(" ncdata = '" + ncdata + "'")
if ninst > 1:
logger.info("%s is being used for ncdata", ncdata)
if RUN_TYPE == 'branch':
cam_branch_file = _create_ic_filename(inst_string, 'r')
# Fallback if no instance-specific file is found.
if not os.path.isfile(os.path.join(rundir, cam_branch_file)):
cam_branch_file = _create_ic_filename('', 'r')
infile_lines.append(" cam_branch_file = '" + cam_branch_file + "'")
if ninst > 1:
logger.info("%s is being used for cam_branch_file", cam_branch_file)
# ESMF mesh file
infile_lines.append(" cam_physics_mesh = '" + mesh_file + "'")
# In python3 integer division returns a float value.
# Adjust argument of int() to get nearest integer.
dtime = int( (3600*24)/int(atm_ncpl) + .5)
infile_lines.append(" dtime = " + str(dtime))
start_ymd = RUN_STARTDATE.replace('-','')
if DEBUG:
infile_lines.append(" state_debug_checks = .true.")
user_nl_file = os.path.join(caseroot, "user_nl_cam" + inst_string)
namelist_infile = os.path.join(camconf, "namelist")
create_namelist_infile(case, user_nl_file, namelist_infile, "\n".join(infile_lines))
# -----------------------------------------------------
# call build-namelist
# -----------------------------------------------------
buildnl_opts = ["-ntasks", str(NTASKS), "-csmdata", din_loc_root,
"-infile", os.path.join(camconf, "namelist"),
"-start_ymd", start_ymd]
if ('-01-01' in RUN_STARTDATE) or ('-09-01' in RUN_STARTDATE):
buildnl_opts.append("-ignore_ic_year")
else:
buildnl_opts.append("-ignore_ic_date")
if CAM_NML_USE_CASE != 'UNSET':
buildnl_opts += ["-use_case", CAM_NML_USE_CASE]
buildnl_opts += ["-inputdata", input_data_list]
buildnl_opts += ["-namelist",
'" &atmexp ' + CAM_NAMELIST_OPTS + '/" ']
if COMP_INTERFACE == 'nuopc':
buildnl_opts.append("-cmeps")
cmd = os.path.join(srcroot, "bld", "build-namelist")
cmd += " " + " ".join(buildnl_opts)
rc, out, err = run_cmd(cmd, from_dir=camconf)
expect(rc==0,"Command %s failed rc=%d\nout=%s\nerr=%s"%(cmd,rc,out,err))
# -----------------------------------------------------
# copy resolved namelist, atm_in, to rundir
# -----------------------------------------------------
if os.path.isdir(rundir):
file1 = os.path.join(camconf, "atm_in")
file2 = os.path.join(rundir, "atm_in")
if ninst > 1:
file2 += inst_string
logger.info("CAM namelist copy: file1 %s file2 %s ", file1, file2)
shutil.copy(file1,file2)
# -----------------------------------------------------
# copy drv_flds_in to rundir if it does not exist
# -----------------------------------------------------
file1 = os.path.join(camconf, "drv_flds_in")
file2 = os.path.join(rundir, "drv_flds_in")
if (os.path.isfile(file1)) and (not os.path.isfile(file2)):
shutil.copy(file1,file2)
# -----------------------------------------------------
# copy geos-chem config files to rundir if using geos-chem chemistry
# -----------------------------------------------------
if os.path.isdir(rundir) \
and os.path.exists(os.path.join(caseroot, "species_database.yml"))\
and '-chem geoschem' in CAM_CONFIG_OPTS:
for fname in ['species_database.yml', 'geoschem_config.yml',
'HISTORY.rc', 'HEMCO_Config.rc', 'HEMCO_Diagn.rc']:
file1 = os.path.join(caseroot, fname)
file2 = os.path.join(rundir, fname)
logger.info("GEOS-Chem config file copy: file1 %s file2 %s ", file1, file2)
shutil.copy(file1,file2)
# Copy TUV-x data to rundir
if '-tuvx' in CAM_CONFIG_OPTS:
dest_data = os.path.join(rundir, "data")
if os.path.exists(dest_data):
shutil.rmtree(dest_data)
shutil.copytree(tuvx_data_src, dest_data)
###############################################################################
def _main_func():
caseroot = parse_input(sys.argv)
with Case(caseroot) as case:
buildnml(case, caseroot, "cam")
if __name__ == "__main__":
_main_func()