Skip to content

Commit fa786a7

Browse files
authored
Merge pull request #1471 from fvitt/tuvx_photo
cam6_4_160: TUV-x photolysis
2 parents 2d0761f + 98cd1e0 commit fa786a7

33 files changed

Lines changed: 15342 additions & 574 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
buildnmlc
33
buildcppc
44

5+
# Ignore ide configs
6+
.vscode
7+
58
# Ignore editor temporaries and backups
69
*~
710
.#*

.gitmodules

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,3 +205,10 @@ url = https://github.com/NCAR/CUPiD.git
205205
fxtag = v0.5.1
206206
fxrequired = ToplevelRequired
207207
fxDONOTUSEurl = https://github.com/NCAR/CUPiD.git
208+
209+
[submodule "tuv-x"]
210+
path = libraries/tuv-x
211+
url = https://github.com/NCAR/tuv-x.git
212+
fxtag = v0.14.3
213+
fxrequired = ToplevelRequired
214+
fxDONOTUSEurl = https://github.com/NCAR/tuv-x.git

bld/namelist_files/namelist_definition.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7750,6 +7750,17 @@ Maximum zenith angle (degrees) used for photolysis.
77507750
Default: set by build-namelist.
77517751
</entry>
77527752

7753+
<entry id="tuvx_config_path" type="char*256" input_pathname="abs" category="chemistry"
7754+
group="tuvx_opts" valid_values="" >
7755+
Filepath of TUV-X configuration specification.
7756+
Default: NONE
7757+
</entry>
7758+
7759+
<entry id="tuvx_active" type="logical" category="chemistry"
7760+
group="tuvx_opts" valid_values="" >
7761+
Switch to turn on TUV-X photolysis.
7762+
Default: FALSE
7763+
</entry>
77537764

77547765
<!-- Namelist read by seq_drydep_mod and shared by CAM and CLM -->
77557766

cime_config/buildlib

Lines changed: 148 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ create the cam library
77
# pylint: disable=unused-wildcard-import, bad-whitespace, too-many-locals
88
# pylint: disable=invalid-name
99
import sys, os, filecmp, shutil
10-
10+
from glob import glob
1111

1212
_CIMEROOT = os.environ.get("CIMEROOT")
1313
if _CIMEROOT is None:
@@ -27,7 +27,7 @@ logger = logging.getLogger(__name__)
2727

2828
###############################################################################
2929
def _build_fms(caseroot, libroot, bldroot):
30-
###############################################################################
30+
###############################################################################
3131

3232
with Case(caseroot) as case:
3333

@@ -71,7 +71,7 @@ def _build_fms(caseroot, libroot, bldroot):
7171

7272
###############################################################################
7373
def _build_cam(caseroot, libroot, bldroot):
74-
###############################################################################
74+
###############################################################################
7575

7676
with Case(caseroot, read_only=False) as case:
7777

@@ -157,12 +157,157 @@ def _build_cam(caseroot, libroot, bldroot):
157157
logger.info("%s: \n\n output:\n %s \n\n err:\n\n%s\n", cmd, out, err)
158158
expect(rc == 0, "Command %s failed with rc=%s" % (cmd, rc))
159159

160+
###############################################################################
161+
def _run_cmd(command, working_dir):
162+
###############################################################################
163+
164+
rc, out, err = run_cmd(command, from_dir=working_dir, verbose=True)
165+
expect(rc == 0, f"Command {command} failed with rc={rc} out={out} err={err}")
166+
167+
###############################################################################
168+
def _cmake_default_args(caseroot):
169+
###############################################################################
170+
# Returns a dictionary of CMake variables based on the Macros.cmake file for
171+
# the build.
172+
173+
with Case(caseroot) as case:
174+
macro_path = os.path.abspath(os.path.join(caseroot, "cmake_macros", ""))
175+
args = "-DCONVERT_TO_MAKE=ON "
176+
args += f"-DCASEROOT={caseroot} "
177+
args += f"-DCOMPILER={case.get_value('COMPILER')} "
178+
args += f"-DOS={case.get_value('OS')} "
179+
args += f"-DMACH={case.get_value('MACH')} "
180+
args += "-DCMAKE_C_COMPILER_WORKS=1 "
181+
args += "-DCMAKE_Fortran_COMPILER_WORKS=1 "
182+
args += "-DCMAKE_CXX_COMPILER_WORKS=1 "
183+
args += f"-DDEBUG={case.get_value('DEBUG')} "
184+
cmd = f"cmake {args} ."
185+
rc, out, err = run_cmd(cmd, combine_output=True, from_dir=macro_path)
186+
expect(rc == 0, f"Command {cmd} failed with rc={rc} out={out} err={err}")
187+
188+
arg_dict = {}
189+
for line in out.splitlines():
190+
if ":=" in line:
191+
key, val = line.split(":=")
192+
arg_dict[key.replace('CIME_SET_MAKEFILE_VAR','').strip()] = val.strip()
193+
194+
return arg_dict
195+
196+
###############################################################################
197+
def _build_tuvx(caseroot, libroot, bldroot):
198+
###############################################################################
199+
# Builds the TUV-x library and updates the case variables used to set the
200+
# include paths and linked libraries
201+
202+
with Case(caseroot) as case:
203+
bldpath = os.path.join(bldroot, "tuv-x")
204+
if not os.path.exists(bldpath):
205+
os.makedirs(bldpath)
206+
srcpath = os.path.abspath(os.path.join(case.get_value("COMP_ROOT_DIR_ATM"), \
207+
"libraries", "tuv-x", ""))
208+
logger.info("Building TUV-x in {} from source in {}\n".format(bldpath, srcpath))
209+
210+
arg_dict = _cmake_default_args(caseroot)
211+
cmake_args = "-DCMAKE_VERBOSE_MAKEFILE=ON "
212+
if case.get_value("MPILIB") != "mpi-serial":
213+
cmake_args += "-DTUVX_ENABLE_MPI:BOOL=TRUE "
214+
cmake_args += "-DCMAKE_BUILD_TYPE=Debug "
215+
cmake_args += "-DCMAKE_Fortran_COMPILER=mpif90 "
216+
cmake_args += "-DCMAKE_C_COMPILER=mpicc "
217+
cmake_args += "-DCMAKE_CXX_COMPILER=mpicxx "
218+
cmake_args += "-DCMAKE_Fortran_COMPILER_WORKS=1 "
219+
cmake_args += "-DCMAKE_C_COMPILER_WORKS=1 "
220+
cmake_args += "-DCMAKE_CXX_COMPILER_WORKS=1 "
221+
if (case.get_value("MACH") == "izumi") :
222+
cmake_args += f"-DCMAKE_PREFIX_PATH={arg_dict['NETCDF_PATH']} "
223+
cmake_args += f"-DCMAKE_IGNORE_PATH={os.environ.get('PYTHONHOME')} "
224+
if (case.get_value("MACH") == "izumi") and (case.get_value('COMPILER') == "nag") :
225+
cmake_args += "-DCMAKE_Fortran_FLAGS='-C=all -g ' "
226+
else :
227+
cmake_args += f"-DCMAKE_Fortran_FLAGS='{arg_dict['FFLAGS']}' "
228+
cmake_args += f"-DCMAKE_INSTALL_PREFIX='{libroot}' "
229+
cmake_args += "-DTUVX_ENABLE_TESTS=OFF "
230+
cmake_args += "-DTUVX_ENABLE_COVERAGE=OFF "
231+
cmake_args += "-DTUVX_BUILD_CLI=OFF "
232+
cmake_args += f"-DTUVX_INSTALL_INCLUDE_DIR='{_tuvx_include_dir(libroot)}' "
233+
cmake_args += f"-DTUVX_INSTALL_MOD_DIR='{_tuvx_include_dir(libroot)}' "
234+
cmake_args += srcpath
235+
236+
_run_cmd(f"cmake {cmake_args}", bldpath)
237+
_run_cmd(case.get_value('GMAKE'), bldpath)
238+
_run_cmd(f"{case.get_value('GMAKE')} install", bldpath)
239+
240+
# add TUV-x to include paths
241+
incldir = os.environ.get('USER_INCLDIR')
242+
if incldir is None:
243+
incldir = ''
244+
os.environ['USER_INCLDIR'] = incldir + \
245+
f" -I{_tuvx_include_dir(libroot)} "
246+
247+
# create symlink to library in folder CIME expects libraries to be in
248+
dst = os.path.join(libroot, "libtuvx.a")
249+
if os.path.isfile(dst):
250+
os.remove(dst)
251+
os.symlink(_tuvx_lib_path(libroot), dst)
252+
dst = os.path.join(libroot, "libyaml-cpp.a")
253+
if os.path.isfile(dst):
254+
os.remove(dst)
255+
os.symlink(_yaml_cpp_lib_path(libroot), dst)
256+
257+
###############################################################################
258+
def _tuvx_include_dir(libroot):
259+
###############################################################################
260+
# Returns the path to the TUV-x include directory
261+
262+
coreinc = os.path.join(libroot, "include")
263+
expect(os.path.exists(coreinc), f"TUV-x include directory not found at {coreinc}")
264+
265+
return coreinc
266+
267+
###############################################################################
268+
def _yaml_cpp_lib_path(libroot):
269+
###############################################################################
270+
# Returns the path to the yaml-cpp library
271+
272+
corelib = os.path.join(libroot, "lib64", "libyaml-cpp.a")
273+
if not os.path.exists(corelib):
274+
corelib = os.path.join(libroot, "lib64", "libyaml-cppd.a")
275+
if not os.path.exists(corelib):
276+
corelib = os.path.join(libroot, "lib", "libyaml-cpp.a")
277+
expect(os.path.exists(corelib), f"yaml-cpp library not found at {corelib}")
278+
279+
return corelib
280+
281+
###############################################################################
282+
def _tuvx_lib_path(libroot):
283+
###############################################################################
284+
# Returns the path to the TUV-x library
285+
286+
corelib = os.path.join(_tuvx_install_dir(libroot), "lib64", "libtuvx.a")
287+
if not os.path.exists(corelib):
288+
corelib = os.path.join(_tuvx_install_dir(libroot), "lib", "libtuvx.a")
289+
expect(os.path.exists(corelib), f"TUV-x library not found at {corelib}")
290+
291+
return corelib
292+
293+
###############################################################################
294+
def _tuvx_install_dir(libroot):
295+
###############################################################################
296+
# Returns the path to the TUV-x install directory
297+
298+
corepaths = glob(os.path.join(libroot, "tuvx*"))
299+
expect(len(corepaths)>0, f"TUV-x not found at {libroot}")
300+
expect(len(corepaths)<2, f"Multiple TUV-x versions found at {libroot}")
301+
expect(os.path.exists(corepaths[0]), f"TUV-x install directory not found at {corepaths[0]}")
302+
303+
return corepaths[0]
160304

161305
###############################################################################
162306

163307

164308
def _main_func():
165309
caseroot, libroot, bldroot = parse_input(sys.argv)
310+
_build_tuvx(caseroot, libroot, bldroot)
166311
_build_fms(caseroot, libroot, bldroot)
167312
_build_cam(caseroot, libroot, bldroot)
168313

cime_config/buildnml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,13 @@ def buildnml(case, caseroot, compname):
231231
logger.info("GEOS-Chem config file copy: file1 %s file2 %s ", file1, file2)
232232
shutil.copy(file1,file2)
233233

234+
# Copy TUV-x data to rundir
235+
dest_data = os.path.join(rundir, "data")
236+
if os.path.exists(dest_data):
237+
shutil.rmtree(dest_data)
238+
shutil.copytree(os.path.join(srcroot, "libraries", "tuv-x", "data"), \
239+
dest_data)
240+
234241
###############################################################################
235242
def _main_func():
236243

cime_config/config_component.xml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,18 @@
227227
</desc>
228228
</entry>
229229

230+
<entry id="CAM_LINKED_LIBS">
231+
<type>char</type>
232+
<valid_values></valid_values>
233+
<default_value>-ltuvx -lyaml-cpp -lstdc++</default_value>
234+
<group>build_component_cam</group>
235+
<file>env_build.xml</file>
236+
<desc>
237+
CAM linked libraries. The libraries are built by CAM's buildlib script and should be included
238+
during linking of the model executable.
239+
</desc>
240+
</entry>
241+
230242
<entry id="CAM_NML_USE_CASE">
231243
<type>char</type>
232244
<valid_values></valid_values>
Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
mfilt=1,1,1,1,1,1
2-
ndens=1,1,1,1,1,1
3-
nhtfrq=3,3,3,3,3,3
1+
mfilt=1,1,1,1,1,1,1,1,1,1
2+
ndens=1,1,1,1,1,1,1,1,1,1
3+
nhtfrq=3,3,3,3,3,3,3,3,3,3
44
inithist='ENDOFRUN'
55
pbuf_global_allocate=.false.
66
history_carma=.true.
@@ -11,3 +11,5 @@ solar_data_type='FIXED'
1111
solar_data_ymd=20000101
1212
carma_maxretries = 40
1313
ubc_specifier = 'T->MSIS', 'Q->2.d-8vmr', 'CH4->2.d-10vmr', 'H->MSIS', 'N->MSIS', 'O->MSIS', 'O2->MSIS', 'H2->TGCM', 'NO->SNOE'
14+
tuvx_active = .true.
15+
tuvx_config_path = '$COMP_ROOT_DIR_ATM/src/chemistry/pp_waccm_ma_sulfur/tuvx_config.json'
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
./xmlchange ROF_NCPL=\$ATM_NCPL
2+
./xmlchange GLC_NCPL=\$ATM_NCPL
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
mfilt=1,1,1,1,1,1,1,1,1
2+
ndens=1,1,1,1,1,1,1,1,1
3+
nhtfrq=9,9,9,9,9,9,9,9,9
4+
write_nstep0=.true.
5+
inithist='ENDOFRUN'
6+
7+
tuvx_active = .true.
8+
tuvx_config_path = '$COMP_ROOT_DIR_ATM/src/chemistry/pp_waccm_ma_mam5/tuvx_config.json'
9+
10+
fincl2 = 'TUVX_DOSE_RATE_01','TUVX_DOSE_RATE_02','TUVX_DOSE_RATE_03','TUVX_DOSE_RATE_04','TUVX_DOSE_RATE_05',
11+
'TUVX_DOSE_RATE_06','TUVX_DOSE_RATE_07','TUVX_DOSE_RATE_08','TUVX_DOSE_RATE_09','TUVX_DOSE_RATE_10',
12+
'TUVX_DOSE_RATE_11','TUVX_DOSE_RATE_12','TUVX_DOSE_RATE_13','TUVX_DOSE_RATE_14','TUVX_DOSE_RATE_15',
13+
'TUVX_DOSE_RATE_16','TUVX_DOSE_RATE_17','TUVX_DOSE_RATE_18','TUVX_DOSE_RATE_19','TUVX_DOSE_RATE_20',
14+
'TUVX_DOSE_RATE_21','TUVX_DOSE_RATE_22','TUVX_DOSE_RATE_23','TUVX_DOSE_RATE_24',
15+
'TUVX_DOSE_RATE_25','TUVX_DOSE_RATE_26','TUVX_DOSE_RATE_27','TUVX_DOSE_RATE_28'
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
!----------------------------------------------------------------------------------
2+
! Users should add all user specific namelist changes below in the form of
3+
! namelist_var = new_namelist_value
4+
!
5+
! Include namelist variables for drv_flds_in ONLY if -megan and/or -drydep options
6+
! are set in the CLM_NAMELIST_OPTS env variable.
7+
!
8+
! EXCEPTIONS:
9+
! Set use_cndv by the compset you use and the CLM_BLDNML_OPTS -dynamic_vegetation setting
10+
! Set use_vichydro by the compset you use and the CLM_BLDNML_OPTS -vichydro setting
11+
! Set use_cn by the compset you use and CLM_BLDNML_OPTS -bgc setting
12+
! Set use_crop by the compset you use and CLM_BLDNML_OPTS -crop setting
13+
! Set spinup_state by the CLM_BLDNML_OPTS -bgc_spinup setting
14+
! Set irrigate by the CLM_BLDNML_OPTS -irrig setting
15+
! Set dtime with L_NCPL option
16+
! Set fatmlndfrc with LND_DOMAIN_PATH/LND_DOMAIN_FILE options
17+
! Set finidat with RUN_REFCASE/RUN_REFDATE/RUN_REFTOD options for hybrid or branch cases
18+
! (includes $inst_string for multi-ensemble cases)
19+
! Set glc_grid with CISM_GRID option
20+
! Set glc_smb with GLC_SMB option
21+
! Set maxpatch_glcmec with GLC_NEC option
22+
! Set glc_do_dynglacier with GLC_TWO_WAY_COUPLING env variable
23+
!----------------------------------------------------------------------------------
24+
hist_nhtfrq = 9
25+
hist_mfilt = 1
26+
hist_ndens = 1
27+

0 commit comments

Comments
 (0)